starcluster.tests.test_config

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
     18 -    def test_valid_config_template(self):
     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
    266 -    def test_multiple_instance_types(self):
    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