Package starcluster :: Package tests :: Module test_config
[hide private]
[frames] | no frames]

Source Code for Module starcluster.tests.test_config

  1  #!/usr/bin/env python 
  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   
16 -class TestStarClusterConfig(tests.StarClusterTest):
17
19 self.config
20
21 - def test_config_dne(self):
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
34 - def test_get_cluster(self):
35 try: 36 self.config.get_cluster_template('no_such_cluster') 37 except exception.ClusterTemplateDoesNotExist: 38 pass 39 else: 40 raise Exception('config returned non-existent cluster')
41
42 - def test_int_required(self):
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
53 - def test_bool_required(self):
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
63 - def test_missing_required(self):
64 cfg = self.config._config 65 section_copy = copy.deepcopy(cfg._sections) 66 for setting in static.CLUSTER_SETTINGS: 67 if not static.CLUSTER_SETTINGS[setting][1]: 68 continue 69 del cfg._sections['cluster c1'][setting] 70 try: 71 self.config.load() 72 except exception.ConfigError: 73 pass 74 else: 75 raise Exception( 76 "config is not enforcing required setting '%s'" % setting) 77 cfg._sections = copy.deepcopy(section_copy)
78
79 - def test_volumes(self):
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
102 - def test_volume_not_defined(self):
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
111 - def test_clusters(self):
112 assert 'c1' in self.config.clusters 113 assert 'c2' in self.config.clusters 114 assert 'c3' in self.config.clusters
115
116 - def test_extends(self):
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 # below only true for default test config 130 # not required in general 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 # below only true for default test config 137 # not required in general 138 assert c3[key] != c2[key]
139
140 - def test_order_invariance(self):
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
153 - def test_plugins(self):
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 # test that order is preserved 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
178 - def test_plugin_not_defined(self):
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
187 - def test_keypairs(self):
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
201 - def test_keypair_not_defined(self):
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
210 - def test_invalid_config(self):
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
225 - def test_empty_config(self):
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
239 - def test_cyclical_extends(self):
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
254 - def test_choices(self):
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