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