1
2 import os
3 import copy
4 import tempfile
5
6 import logging
7 logging.disable(logging.WARN)
8
9 from starcluster import exception
10 from starcluster import tests
11 from starcluster import static
12 from starcluster import config
13 from starcluster import utils
14
15
17
20
22 tmp_file = tempfile.NamedTemporaryFile()
23 non_existent_file = tmp_file.name
24 tmp_file.close()
25 assert not os.path.exists(non_existent_file)
26 try:
27 config.StarClusterConfig(non_existent_file, cache=True).load()
28 except exception.ConfigNotFound:
29 pass
30 else:
31 raise Exception('config loaded non-existent config file %s' % \
32 non_existent_file)
33
41
43 cases = [{'c1_size':'-s'}, {'c1_size': 2.5}, {'v1_partition': 'asdf'},
44 {'v1_partition': 0.33}]
45 for case in cases:
46 try:
47 self.get_custom_config(**case)
48 except exception.ConfigError:
49 pass
50 else:
51 raise Exception('config is not enforcing ints correctly')
52
54 cases = [{'enable_experimental': 2}]
55 for case in cases:
56 try:
57 self.get_custom_config(**case)
58 except exception.ConfigError:
59 pass
60 else:
61 raise Exception("config is not enforcing strs correctly")
62
78
80 c1 = self.config.get_cluster_template('c1')
81 vols = c1.volumes
82 assert len(vols) == 3
83 assert 'v1' in vols
84 v1 = vols['v1']
85 assert 'volume_id' in v1 and v1['volume_id'] == 'vol-c999999'
86 assert 'device' in v1 and v1['device'] == '/dev/sdj'
87 assert 'partition' in v1 and v1['partition'] == '/dev/sdj1'
88 assert 'mount_path' in v1 and v1['mount_path'] == '/volume1'
89 assert 'v2' in vols
90 v2 = vols['v2']
91 assert 'volume_id' in v2 and v2['volume_id'] == 'vol-c888888'
92 assert 'device' in v2 and v2['device'] == '/dev/sdk'
93 assert 'partition' in v2 and v2['partition'] == '/dev/sdk1'
94 assert 'mount_path' in v2 and v2['mount_path'] == '/volume2'
95 assert 'v3' in vols
96 v3 = vols['v3']
97 assert 'volume_id' in v3 and v3['volume_id'] == 'vol-c777777'
98 assert 'device' in v3 and v3['device'] == '/dev/sdl'
99 assert 'partition' in v3 and v3['partition'] == '/dev/sdl1'
100 assert 'mount_path' in v3 and v3['mount_path'] == '/volume3'
101
103 try:
104 self.get_custom_config(**{'c1_vols': 'v1,v2,v2323'})
105 except exception.ConfigError:
106 pass
107 else:
108 raise Exception(
109 'config allows non-existent volumes to be specified')
110
112 assert 'c1' in self.config.clusters
113 assert 'c2' in self.config.clusters
114 assert 'c3' in self.config.clusters
115
117 c1 = self.config.clusters.get('c1')
118 c2 = self.config.clusters.get('c2')
119 c3 = self.config.clusters.get('c3')
120 c2_settings = ['__name__', 'extends', 'keyname', 'key_location',
121 'cluster_size', 'node_instance_type',
122 'master_instance_type', 'volumes']
123 c3_settings = ['__name__', 'extends', 'keyname', 'key_location',
124 'cluster_size', 'volumes']
125 for key in c1:
126 if key in c2 and not key in c2_settings:
127 assert c2[key] == c1[key]
128 else:
129
130
131 assert c2[key] != c1[key]
132 for key in c2:
133 if key in c3 and not key in c3_settings:
134 assert c3[key] == c2[key]
135 else:
136
137
138 assert c3[key] != c2[key]
139
141 """
142 Loads all cluster sections in the test config in all possible orders
143 (ie c1,c2,c3, c3,c1,c2, etc) and test that the results are the same
144 """
145 cfg = self.config
146 orig = cfg.clusters
147 cfg.clusters = None
148 sections = cfg._get_sections('cluster')
149 for perm in utils.permute(sections):
150 new = cfg._load_cluster_sections(perm)
151 assert new == orig
152
154 c1 = self.config.get_cluster_template('c1')
155 plugs = c1.plugins
156 assert len(plugs) == 3
157 plugs = self.config.clusters.c1.plugins
158
159 p1 = plugs[0]
160 p2 = plugs[1]
161 p3 = plugs[2]
162 assert p1['__name__'] == 'p1'
163 assert p1['setup_class'] == 'starcluster.tests.mytestplugin.SetupClass'
164 assert p1['my_arg'] == '23'
165 assert p1['my_other_arg'] == 'skidoo'
166 assert p2['__name__'] == 'p2'
167 setup_class2 = 'starcluster.tests.mytestplugin.SetupClass2'
168 assert p2['setup_class'] == setup_class2
169 assert p2['my_arg'] == 'hello'
170 assert p2['my_other_arg'] == 'world'
171 assert p3['__name__'] == 'p3'
172 setup_class3 = 'starcluster.tests.mytestplugin.SetupClass3'
173 assert p3['setup_class'] == setup_class3
174 assert p3['my_arg'] == 'bon'
175 assert p3['my_other_arg'] == 'jour'
176 assert p3['my_other_other_arg'] == 'monsignour'
177
179 try:
180 self.get_custom_config(**{'c1_plugs': 'p1,p2,p233'})
181 except exception.ConfigError:
182 pass
183 else:
184 raise Exception(
185 'config allows non-existent plugins to be specified')
186
188 kpairs = self.config.keys
189 assert len(kpairs) == 3
190 k1 = kpairs.get('k1')
191 k2 = kpairs.get('k2')
192 k3 = kpairs.get('k3')
193 dcfg = tests.templates.config.default_config
194 k1_location = os.path.expanduser(dcfg['k1_location'])
195 k2_location = dcfg['k2_location']
196 k3_location = dcfg['k3_location']
197 assert k1 and k1['key_location'] == k1_location
198 assert k2 and k2['key_location'] == k2_location
199 assert k3 and k3['key_location'] == k3_location
200
202 try:
203 self.get_custom_config(**{'c1_keyname': 'k2323'})
204 except exception.ConfigError:
205 pass
206 else:
207 raise Exception(
208 'config allows non-existent keypairs to be specified')
209
211 """
212 Test that reading a non-INI formatted file raises an exception
213 """
214 tmp_file = tempfile.NamedTemporaryFile()
215 tmp_file.write(
216 "<html>random garbage file with no section headings</html>")
217 tmp_file.flush()
218 try:
219 config.StarClusterConfig(tmp_file.name, cache=True).load()
220 except exception.ConfigHasNoSections:
221 pass
222 else:
223 raise Exception("config allows non-INI formatted files")
224
226 """
227 Test that reading an empty config generates no errors and that aws
228 credentials can be read from the environment.
229 """
230 aws_key = 'testkey'
231 aws_secret_key = 'testsecret'
232 os.environ['AWS_ACCESS_KEY_ID'] = aws_key
233 os.environ['AWS_SECRET_ACCESS_KEY'] = aws_secret_key
234 tmp_file = tempfile.NamedTemporaryFile()
235 cfg = config.StarClusterConfig(tmp_file.name, cache=True).load()
236 assert cfg.aws['aws_access_key_id'] == aws_key
237 assert cfg.aws['aws_secret_access_key'] == aws_secret_key
238
240 """
241 Test that cyclical extends in the config raises an exception
242 """
243 try:
244 self.get_custom_config(**{'c2_extends': 'c3',
245 'c3_extends': 'c2'})
246 self.get_custom_config(**{'c2_extends': 'c3',
247 'c3_extends': 'c4',
248 'c4_extends': 'c2'})
249 except exception.ConfigError:
250 pass
251 else:
252 raise Exception('config allows cyclical extends graph')
253
255 """
256 Test that config enforces a value to be one of a list of choices if
257 specified
258 """
259 try:
260 self.get_custom_config(**{'c1_shell': 'blahblah'})
261 except exception.ConfigError:
262 pass
263 else:
264 raise Exception('config not enforcing choices for setting')
265
267 """
268 Test that config properly handles multiple instance types syntax
269 (within node_instance_type setting)
270 """
271 invalid_cases = [{'c1_node_type': 'c1.xlarge:ami-asdffdas'},
272 {'c1_node_type': 'c1.xlarge:3'},
273 {'c1_node_type': 'c1.xlarge:ami-asdffdas:3'},
274 {'c1_node_type': 'c1.xlarge:asdf:asdf:asdf,m1.small'},
275 {'c1_node_type': 'c1.asdf:4, m1.small'},
276 {'c1_node_type': 'c1.xlarge: 0, m1.small'},
277 {'c1_node_type': 'c1.xlarge:-1, m1.small'}]
278 for case in invalid_cases:
279 try:
280 self.get_custom_config(**case)
281 except exception.ConfigError:
282 pass
283 else:
284 raise Exception(('config allows invalid multiple instance ' +
285 'type syntax: %s') % case)
286 valid_cases = [
287 {'c1_node_type': 'c1.xlarge:3, m1.small'},
288 {'c1_node_type': 'c1.xlarge:ami-asdfasdf:3, m1.small'},
289 {'c1_node_type': 'c1.xlarge:ami-asdfasdf:3, m1.large, m1.small'},
290 {'c1_node_type': 'm1.large, c1.xlarge:ami-asdfasdf:3, m1.large, ' +
291 'm1.small'},
292 {'c1_node_type': 'c1.xlarge:ami-asdfasdf:2, m1.large:2, m1.small'},
293 ]
294 for case in valid_cases:
295 try:
296 self.get_custom_config(**case)
297 except exception.ConfigError:
298 raise Exception(('config rejects valid multiple instance ' +
299 'type syntax: %s') % case)
300