Example #1
0
class UpgradeTests(unittest.TestCase):

    def setUp(self, *args, **kwargs):
        super(UpgradeTests, self).setUp(*args, **kwargs)
        self.do = DeploymentUpgrader('somehost', 10000)

    def test_lookup_ordered_data_from_hash(self):
        self.assertEquals(self.do.lookup_ordered_data_from_hash('config_version/enable_puppet', ['host1'], {'config_version/enable_puppet/host/host1': True}), {'host1': True})

    def test_upgrade(self):
        instructions = {'rollin_rules': ''}
        self.assertRaises(ValueError, self.do.upgrade, '123', instructions)

    def test_upgrade_list(self):
        # when there is no data, return no data
        status = {
            'upgraded': {},
            'upgrading': {},
            'pending': {}
        }
        instructions = {}
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'roles': [],
            'hosts': [],
            'delete_hosts': []
        })
        # when there are no instructions, upgrade everyone
        status = {
            'upgraded': {'h': ['h1', 'h2']},
            'upgrading': {'h': ['h3'], 'i': ['i1']},
            'pending': {'i': ['i2'], 'j': ['j1']}
        }
        instructions = {}
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'hosts': [],
            'roles': ['i', 'j'],
            'delete_hosts': ['i1', 'i2', 'j1']
        })
        # if the total number to be upgraded is higher than the upgrading and pending, upgrade all
        status = {
            'upgraded': {'h': ['h1', 'h2']},
            'upgrading': {'h': ['h3']},
            'pending': {'h': ['h4', 'h5']}
        }
        instructions = {'rolling_rules': {'global': 5}}
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'hosts': [],
            'roles': ['h'],
            'delete_hosts': ['h3', 'h1', 'h2', 'h4', 'h5']
        })
        # when upgading is greater of equal to number, do nothing
        status = {
            'upgraded': {'h': ['h1', 'h2']},
            'upgrading': {'h': ['h1', 'h2', 'h3']},
            'pending': {'h': ['h4', 'h5']}
        }
        instructions = {'rolling_rules': {'global': 3}}
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'hosts': [],
            'roles': [],
            'delete_hosts': []
        })
        # if upgrading and upgrading + pending are less then num, upgrade some hosts
        status = {
            'upgraded': {'h': ['h1', 'h2']},
            'upgrading': {'h': ['h1', 'h2', 'h3']},
            'pending': {'h': ['h4', 'h5', 'h6', 'h7']}
        }
        instructions = {'rolling_rules': {'global': 5}}
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'hosts': ['h4', 'h5'],
            'roles': [],
            'delete_hosts': []
        })
        # with global and host specific overrides
        status = {
            'upgraded': {'h': ['h1', 'h2']},
            'upgrading': {'h': ['h1'], 'i': ['i1']},
            'pending': {'h': ['h2', 'h3', 'h4'], 'i': ['i2', 'i3']}
        }
        instructions = {'rolling_rules': {'global': 3, 'roles': {'i': 2}}, }
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'hosts': ['i2', 'h2', 'h3'],
            'roles': [],
            'delete_hosts': []
        })
        # with one host in pending state
        status = {
            'upgraded': {},
            'upgrading': {},
            'pending': {'h': ['h2']}
        }
        instructions = {'rolling_rules': {'global': 1}}
        self.assertEquals(self.do.upgrade_list(instructions, status), {
            'hosts': [],
            'roles': ['h'],
            'delete_hosts': ['h2']
        })
        # when a group is marked as a dep, any role in that group should prevent us
        # from running
        self.verify_upgrade_list(
            {}, {'bar': ['bar1']}, {'baz': ['baz1']},
            {'global': 1}, {'foo': ['bar']}, {'baz': 'foo'}
        )
        # when a role in a dep group is pending, do not run a role
        self.verify_upgrade_list(
            {}, {}, {'bar': ['bar1'], 'baz': ['baz1']},
            {'global': 1}, {'foo': ['bar']}, {'baz': 'foo'},
            {'roles': ['bar'], 'hosts': [], 'delete_hosts': ['bar1']}
        )
        # when multiple roles from our group are pending, only one will upgrade
        self.verify_upgrade_list(
            {}, {}, {'bar': ['bar1'], 'baz': ['baz1']},
            {'global': 1}, {'baz': ['bar']}, {},
            # these results are actually a bug. when we finish up a subrole,
            # we should delete that subroles hosts and add it's role
            {'roles': [], 'hosts': ['bar1'], 'delete_hosts': []}
        )
        # when a role from our group is upgrading, we will wait
        self.verify_upgrade_list(
            {}, {'bar': ['bar1']}, {'baz': ['baz1']},
            {'global': 1}, {'baz': ['bar']}, {}
        )

    def verify_upgrade_list(
      self,
      upgraded,
      upgrading,
      pending,
      rolling_rules = {},
      group_mappings = {},
      role_order = {},
      result     = {
          'hosts': [],
          'roles': [],
          'delete_hosts': []
      }
    ):
        status = {
            'upgraded': upgraded,
            'upgrading': upgrading,
            'pending': pending
        }
        instructions = {
            'rolling_rules': rolling_rules,
            'group_mappings': group_mappings,
            'role_dependencies': role_order
        }
        self.assertEquals(self.do.upgrade_list(instructions, status), result)

    def test_upgrade_from_data(self):
        def consul_set_side_effect(*args, **kwargs):
            return None

        def consul_delete_side_effect(*args, **kwargs):
            return None

        with mock.patch('jiocloud.orchestrate.DeploymentOrchestrator.consul', new_callable=mock.PropertyMock) as consul:
            data = {'hosts': [], 'roles': [], 'delete_hosts': []}
            consul.return_value.kv.set.side_effect = consul_set_side_effect()
            consul.return_value.kv.__delitem__.side_effect = consul_delete_side_effect()
            self.assertEquals(
                self.do.upgrade_from_data(data),
                {'set': [], 'delete': []}
            )
            data = {
                'hosts': ['h1'],
                'roles': ['h'],
                'delete_hosts': ['h2']
            }
            self.assertEquals(
                self.do.upgrade_from_data(data),
                {
                    'delete': ['/config_state/enable_puppet/host/h2'],
                    'set': ['/config_state/enable_puppet/host/h1', '/config_state/enable_puppet/role/h']
                }
            )

    def test_upgrade_status(self):
        with nested(
                mock.patch.object(self.do, 'current_version'),
                mock.patch.object(self.do, 'hosts_at_versions'),
                mock.patch.object(self.do, '_consul')
                ) as (current_version, hosts_at_versions, consul):
            current_version.return_value = '1'
            # when there are no hosts
            hosts_at_versions.return_value = {}
            consul.kv.find.return_value = {}
            self.assertEquals(self.do.upgrade_status(), {'pending': [], 'upgraded': [], 'upgrading': []})
            # when there are hosts but no config rules
            hosts_at_versions.return_value = {'1': ['h1'], '2': ['h2']}
            consul.kv.find.return_value = {}
            self.assertEquals(
                self.do.upgrade_status(),
                {'pending': [], 'upgraded': ['h1'], 'upgrading': ['h2']}
            )
            # when nothing is in the pending state
            hosts_at_versions.return_value = {'1': ['h1'], '2': ['h2', 'i3'], '3': ['i4']}
            config_state = {
                'config_state/enable_puppet/global': False,
                'config_state/enable_puppet/role/h': True,
                'config_state/enable_puppet/host/i4': 'True',
            }
            consul.kv.find.return_value = config_state
            self.assertEquals(self.do.upgrade_status(), {
                              'upgraded': ['h1'],
                              'upgrading': ['h2', 'i4'],
                              'pending': ['i3']
                              })

    def test_key_status_off_role(self):
        self.assertEquals(self.do.key_status_off_role({}), {})
        self.assertEquals(self.do.key_status_off_role(
            {'a': []}),
            {'a': {}}
        )
        self.assertEquals(self.do.key_status_off_role(
            {'a': ['h1', 'h2', 'i1']}),
            {'a': {'h': ['h1', 'h2'], 'i': ['i1']}}
        )

    def test_subrole_mappings(self):
        # with no instructions
        self.assertEquals(self.do.subrole_mappings(
            {'foo': ['foo1', 'foo2']}, {}),
            {'foo': {'foo': ['foo1', 'foo2']}}
        )
        # with a match
        self.assertEquals(self.do.subrole_mappings(
            {'foo': ['foo1', 'foo2']},
            {'bar': ['blah', 'fo.*?']}),
            {'bar': {'foo': ['foo1', 'foo2']}}
        )
        self.assertEquals(self.do.subrole_mappings(
            {'foo': ['foo1', 'foo2'], 'bar': ['bar1']},
            {'bar': ['blah', 'fo.*?']}),
            {'bar': {'bar': ['bar1'], 'foo': ['foo1', 'foo2']}}
        )

    def test_group_from_role(self):
        self.assertEquals(self.do.group_from_role(None, None), None)
        self.assertEquals(self.do.group_from_role('role', {'other_role': ['foo?']}), 'role')
        self.assertEquals(self.do.group_from_role('role', {'other_role': ['ro?']}), 'other_role')

    def test_roles_not_allowed(self):
        # non-matching roles return themselved
        self.assertEquals(
            self.do.roles_not_allowed({'a', 'b'}, {'b', 'c'}, {}),
            set()
        )
        role_order = {
            'c': 'a'
        }
        self.assertEquals(
            self.do.roles_not_allowed({'a', 'b'}, {'b', 'c'}, role_order),
            set('c')
        )
Example #2
0
 def setUp(self, *args, **kwargs):
     super(UpgradeTests, self).setUp(*args, **kwargs)
     self.do = DeploymentUpgrader('somehost', 10000)