Add functional test for ResourceGroup rolling_update
Change-Id: I77456afde1a425aacce5d9778825861179ac89aa
diff --git a/functional/test_resource_group.py b/functional/test_resource_group.py
index 4fd70af..e40376c 100644
--- a/functional/test_resource_group.py
+++ b/functional/test_resource_group.py
@@ -45,19 +45,6 @@
def setUp(self):
super(ResourceGroupTest, self).setUp()
- def _group_nested_identifier(self, stack_identifier,
- group_name='random_group'):
- # Get the nested stack identifier from the group
- rsrc = self.client.resources.get(stack_identifier, group_name)
- physical_resource_id = rsrc.physical_resource_id
-
- nested_stack = self.client.stacks.get(physical_resource_id)
- nested_identifier = '%s/%s' % (nested_stack.stack_name,
- nested_stack.id)
- parent_id = stack_identifier.split("/")[-1]
- self.assertEqual(parent_id, nested_stack.parent)
- return nested_identifier
-
def test_resource_group_zero_novalidate(self):
# Nested resources should be validated only when size > 0
# This allows features to be disabled via size=0 without
@@ -92,7 +79,8 @@
self.list_resources(stack_identifier))
# Check we created an empty nested stack
- nested_identifier = self._group_nested_identifier(stack_identifier)
+ nested_identifier = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual({}, self.list_resources(nested_identifier))
# Prove validation works for non-zero create/update
@@ -108,12 +96,9 @@
environment=env, files=files)
self.assertIn(expected_err, six.text_type(ex))
- def _list_group_resources(self, stack_identifier):
- nested_identifier = self._group_nested_identifier(stack_identifier)
- return self.list_resources(nested_identifier)
-
def _validate_resources(self, stack_identifier, expected_count):
- resources = self._list_group_resources(stack_identifier)
+ resources = self.list_group_resources(stack_identifier,
+ 'random_group')
self.assertEqual(expected_count, len(resources))
expected_resources = dict(
(str(idx), 'My::RandomString')
@@ -187,7 +172,8 @@
stack_identifier = self.stack_create(template=rp_template)
self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
self.list_resources(stack_identifier))
- group_resources = self._list_group_resources(stack_identifier)
+ group_resources = self.list_group_resources(stack_identifier,
+ 'random_group')
expected_resources = {u'0': u'OS::Heat::RandomString',
u'1': u'OS::Heat::RandomString',
u'2': u'OS::Heat::RandomString',
@@ -200,7 +186,8 @@
'removal_policies: []',
'removal_policies: [{resource_list: [\'1\', \'2\', \'3\']}]')
self.update_stack(stack_identifier, update_template)
- group_resources = self._list_group_resources(stack_identifier)
+ group_resources = self.list_group_resources(stack_identifier,
+ 'random_group')
expected_resources = {u'0': u'OS::Heat::RandomString',
u'4': u'OS::Heat::RandomString',
u'5': u'OS::Heat::RandomString',
@@ -219,7 +206,8 @@
self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
self.list_resources(stack_identifier))
- initial_nested_ident = self._group_nested_identifier(stack_identifier)
+ initial_nested_ident = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual({'0': 'My::RandomString'},
self.list_resources(initial_nested_ident))
# get the resource id
@@ -230,7 +218,8 @@
# not the nested stack or resource group.
template_salt = template_one.replace("salt: initial", "salt: more")
self.update_stack(stack_identifier, template_salt, environment=env)
- updated_nested_ident = self._group_nested_identifier(stack_identifier)
+ updated_nested_ident = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual(initial_nested_ident, updated_nested_ident)
# compare the resource id, we expect a change.
@@ -249,7 +238,8 @@
self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
self.list_resources(stack_identifier))
- initial_nested_ident = self._group_nested_identifier(stack_identifier)
+ initial_nested_ident = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual({'0': 'My::RandomString', '1': 'My::RandomString'},
self.list_resources(initial_nested_ident))
# get the output
@@ -258,7 +248,8 @@
template_copy = copy.deepcopy(template_one)
self.update_stack(stack_identifier, template_copy, environment=env)
- updated_nested_ident = self._group_nested_identifier(stack_identifier)
+ updated_nested_ident = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual(initial_nested_ident, updated_nested_ident)
# compare the random number, we expect no change.
@@ -309,7 +300,8 @@
self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
self.list_resources(stack_identifier))
- initial_nested_ident = self._group_nested_identifier(stack_identifier)
+ initial_nested_ident = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual({'0': 'My::RandomString', '1': 'My::RandomString'},
self.list_resources(initial_nested_ident))
# get the output
@@ -320,7 +312,8 @@
# note "files2".
self.update_stack(stack_identifier, template_one,
environment=env, files=files2)
- updated_nested_ident = self._group_nested_identifier(stack_identifier)
+ updated_nested_ident = self.group_nested_identifier(stack_identifier,
+ 'random_group')
self.assertEqual(initial_nested_ident, updated_nested_ident)
# compare the output, we expect a change.
@@ -510,3 +503,201 @@
self._wait_for_stack_status(
stack_identifier, 'DELETE_COMPLETE',
success_on_not_found=True)
+
+
+class ResourceGroupUpdatePolicyTest(functional_base.FunctionalTestsBase):
+
+ template = '''
+heat_template_version: '2015-04-30'
+resources:
+ random_group:
+ type: OS::Heat::ResourceGroup
+ update_policy:
+ rolling_update:
+ min_in_service: 1
+ max_batch_size: 2
+ pause_time: 1
+ properties:
+ count: 10
+ resource_def:
+ type: OS::Heat::TestResource
+ properties:
+ value: initial
+ update_replace: False
+'''
+
+ def update_resource_group(self, update_template,
+ updated, created, deleted):
+ stack_identifier = self.stack_create(template=self.template)
+ group_resources = self.list_group_resources(stack_identifier,
+ 'random_group',
+ minimal=False)
+
+ init_names = [res.physical_resource_id for res in group_resources]
+
+ self.update_stack(stack_identifier, update_template)
+ group_resources = self.list_group_resources(stack_identifier,
+ 'random_group',
+ minimal=False)
+
+ updt_names = [res.physical_resource_id for res in group_resources]
+
+ matched_names = set(updt_names) & set(init_names)
+
+ self.assertEqual(updated, len(matched_names))
+
+ self.assertEqual(created, len(set(updt_names) - set(init_names)))
+
+ self.assertEqual(deleted, len(set(init_names) - set(updt_names)))
+
+ def test_resource_group_update(self):
+ """Test rolling update with no conflict.
+
+ Simple rolling update with no conflict in batch size
+ and minimum instances in service.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '1'
+ policy['max_batch_size'] = '3'
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+
+ self.update_resource_group(updt_template,
+ updated=10,
+ created=0,
+ deleted=0)
+
+ def test_resource_group_update_replace(self):
+ """Test rolling update(replace)with no conflict.
+
+ Simple rolling update replace with no conflict in batch size
+ and minimum instances in service.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '1'
+ policy['max_batch_size'] = '3'
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+ res_def['properties']['update_replace'] = True
+
+ self.update_resource_group(updt_template,
+ updated=0,
+ created=10,
+ deleted=10)
+
+ def test_resource_group_update_scaledown(self):
+ """Test rolling update with scaledown.
+
+ Simple rolling update with reduced size.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '1'
+ policy['max_batch_size'] = '3'
+ grp['properties']['count'] = 6
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+
+ self.update_resource_group(updt_template,
+ updated=6,
+ created=0,
+ deleted=4)
+
+ def test_resource_group_update_scaleup(self):
+ """Test rolling update with scaleup.
+
+ Simple rolling update with increased size.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '1'
+ policy['max_batch_size'] = '3'
+ grp['properties']['count'] = 12
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+
+ self.update_resource_group(updt_template,
+ updated=10,
+ created=2,
+ deleted=0)
+
+ def test_resource_group_update_adjusted(self):
+ """Test rolling update with enough available resources
+
+ Update with capacity adjustment with enough resources.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '8'
+ policy['max_batch_size'] = '4'
+ grp['properties']['count'] = 6
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+
+ self.update_resource_group(updt_template,
+ updated=6,
+ created=0,
+ deleted=4)
+
+ def test_resource_group_update_with_adjusted_capacity(self):
+ """Test rolling update with capacity adjustment.
+
+ Rolling update with capacity adjustment due to conflict in
+ batch size and minimum instances in service.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '8'
+ policy['max_batch_size'] = '4'
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+
+ self.update_resource_group(updt_template,
+ updated=10,
+ created=0,
+ deleted=0)
+
+ def test_resource_group_update_huge_batch_size(self):
+ """Test rolling update with huge batch size.
+
+ Rolling Update with a huge batch size(more than
+ current size).
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '0'
+ policy['max_batch_size'] = '20'
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+ self.update_resource_group(updt_template,
+ updated=10,
+ created=0,
+ deleted=0)
+
+ def test_resource_group_update_huge_min_in_service(self):
+ """Test rolling update with huge minimum capacity.
+
+ Rolling Update with a huge number of minimum instances
+ in service.
+ """
+ updt_template = yaml.load(copy.deepcopy(self.template))
+ grp = updt_template['resources']['random_group']
+ policy = grp['update_policy']['rolling_update']
+ policy['min_in_service'] = '20'
+ policy['max_batch_size'] = '1'
+ res_def = grp['properties']['resource_def']
+ res_def['properties']['value'] = 'updated'
+
+ self.update_resource_group(updt_template,
+ updated=10,
+ created=0,
+ deleted=0)