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

Source Code for Module starcluster.tests.test_config

  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   
15 -class TestStarClusterConfig(tests.StarClusterTest):
16
18 self.config
19
20 - def test_config_dne(self):
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
33 - def test_get_cluster(self):
34 try: 35 self.config.get_cluster_template('no_such_cluster') 36 except exception.ClusterTemplateDoesNotExist: 37 pass 38 else: 39 raise Exception('config returned non-existent cluster')
40
41 - def test_int_required(self):
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
52 - def test_bool_required(self):
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
62 - def test_missing_required(self):
63 cfg = self.config._config 64 section_copy = copy.deepcopy(cfg._sections) 65 for setting in static.CLUSTER_SETTINGS: 66 if not static.CLUSTER_SETTINGS[setting][1]: 67 continue 68 del cfg._sections['cluster c1'][setting] 69 try: 70 self.config.load() 71 except exception.ConfigError: 72 pass 73 else: 74 raise Exception( 75 "config is not enforcing required setting '%s'" % setting) 76 cfg._sections = copy.deepcopy(section_copy)
77
78 - def test_volumes(self):
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
101 - def test_volume_not_defined(self):
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
110 - def test_clusters(self):
111 assert 'c1' in self.config.clusters 112 assert 'c2' in self.config.clusters 113 assert 'c3' in self.config.clusters
114
115 - def test_extends(self):
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 # below only true for default test config 129 # not required in general 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 # below only true for default test config 136 # not required in general 137 assert c3[key] != c2[key]
138
139 - def test_order_invariance(self):
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
152 - def test_plugins(self):
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 # test that order is preserved 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
177 - def test_plugin_not_defined(self):
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
186 - def test_keypairs(self):
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
200 - def test_keypair_not_defined(self):
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
209 - def test_invalid_config(self):
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
224 - def test_empty_config(self):
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
238 - def test_cyclical_extends(self):
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
253 - def test_choices(self):
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