diff --git a/heat/engine/resources/openstack/neutron/subnetpool.py b/heat/engine/resources/openstack/neutron/subnetpool.py index e6afe6c871..1a67519ae4 100644 --- a/heat/engine/resources/openstack/neutron/subnetpool.py +++ b/heat/engine/resources/openstack/neutron/subnetpool.py @@ -36,11 +36,11 @@ class SubnetPool(neutron.NeutronResource): PROPERTIES = ( NAME, PREFIXES, ADDRESS_SCOPE, DEFAULT_QUOTA, DEFAULT_PREFIXLEN, MIN_PREFIXLEN, MAX_PREFIXLEN, - IS_DEFAULT, TENANT_ID, SHARED, + IS_DEFAULT, TENANT_ID, SHARED, TAGS, ) = ( 'name', 'prefixes', 'address_scope', 'default_quota', 'default_prefixlen', 'min_prefixlen', 'max_prefixlen', - 'is_default', 'tenant_id', 'shared', + 'is_default', 'tenant_id', 'shared', 'tags', ) properties_schema = { @@ -121,6 +121,13 @@ class SubnetPool(neutron.NeutronResource): 'attribute to administrative users only.'), default=False, ), + TAGS: properties.Schema( + properties.Schema.LIST, + _('The tags to be added to the subnetpool.'), + schema=properties.Schema(properties.Schema.STRING), + update_allowed=True, + support_status=support.SupportStatus(version='9.0.0') + ), } def validate(self): @@ -177,10 +184,14 @@ class SubnetPool(neutron.NeutronResource): props['address_scope_id'] = self.client_plugin( ).find_resourceid_by_name_or_id( 'address_scope', props.pop(self.ADDRESS_SCOPE)) + tags = props.pop(self.TAGS, []) subnetpool = self.client().create_subnetpool( {'subnetpool': props})['subnetpool'] self.resource_id_set(subnetpool['id']) + if tags: + self.set_tags(tags) + def handle_delete(self): if self.resource_id is not None: with self.client_plugin().ignore_not_found: @@ -200,6 +211,9 @@ class SubnetPool(neutron.NeutronResource): else: prop_diff[ 'address_scope_id'] = prop_diff.pop(self.ADDRESS_SCOPE) + if self.TAGS in prop_diff: + tags = prop_diff.pop(self.TAGS) + self.set_tags(tags) if prop_diff: self.prepare_update_properties(prop_diff) self.client().update_subnetpool( diff --git a/heat/tests/openstack/neutron/test_neutron_subnetpool.py b/heat/tests/openstack/neutron/test_neutron_subnetpool.py index 1398c9096a..0cf5c5becc 100644 --- a/heat/tests/openstack/neutron/test_neutron_subnetpool.py +++ b/heat/tests/openstack/neutron/test_neutron_subnetpool.py @@ -37,8 +37,10 @@ class NeutronSubnetPoolTest(common.HeatTestCase): 'find_resourceid_by_name_or_id', return_value='new_test') - def create_subnetpool(self, status='COMPLETE'): + def create_subnetpool(self, status='COMPLETE', tags=None): self.t = template_format.parse(inline_templates.SPOOL_TEMPLATE) + if tags: + self.t['resources']['sub_pool']['properties']['tags'] = tags self.stack = utils.parse_stack(self.t) resource_defns = self.stack.t.resource_definitions(self.stack) rsrc = subnetpool.SubnetPool('sub_pool', resource_defns['sub_pool'], @@ -61,6 +63,10 @@ class NeutronSubnetPoolTest(common.HeatTestCase): scheduler.TaskRunner(rsrc.create)() self.assertEqual((rsrc.CREATE, status), rsrc.state) + if tags: + self.set_tag_mock.assert_called_once_with('subnetpools', + rsrc.resource_id, + {'tags': tags}) return rsrc def test_validate_prefixlen_min_gt_max(self): @@ -113,6 +119,14 @@ class NeutronSubnetPoolTest(common.HeatTestCase): ref_id = rsrc.FnGetRefId() self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', ref_id) + def test_create_subnetpool_with_tags(self): + tags = ['for_test'] + self.set_tag_mock = self.patchobject(neutronclient.Client, + 'replace_tag') + rsrc = self.create_subnetpool(tags=tags) + ref_id = rsrc.FnGetRefId() + self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', ref_id) + def test_create_subnetpool_failed(self): self.create_subnetpool('FAILED') @@ -144,11 +158,15 @@ class NeutronSubnetPoolTest(common.HeatTestCase): def test_update_subnetpool(self): update_subnetpool = self.patchobject(neutronclient.Client, 'update_subnetpool') - rsrc = self.create_subnetpool() + self.set_tag_mock = self.patchobject(neutronclient.Client, + 'replace_tag') + old_tags = ['old_tag'] + rsrc = self.create_subnetpool(tags=old_tags) self.patchobject(rsrc, 'physical_resource_name', return_value='the_new_sp') ref_id = rsrc.FnGetRefId() self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', ref_id) + new_tags = ['new_tag'] props = { 'name': 'the_new_sp', 'prefixes': [ @@ -160,6 +178,7 @@ class NeutronSubnetPoolTest(common.HeatTestCase): 'min_prefixlen': '24', 'max_prefixlen': '28', 'is_default': False, + 'tags': new_tags } update_dict = props.copy() update_dict['name'] = 'the_new_sp' @@ -168,12 +187,16 @@ class NeutronSubnetPoolTest(common.HeatTestCase): props) # with name self.assertIsNone(rsrc.handle_update(update_snippet, {}, props)) + self.set_tag_mock.assert_called_with('subnetpools', + rsrc.resource_id, + {'tags': new_tags}) # without name props['name'] = None self.assertIsNone(rsrc.handle_update(update_snippet, {}, props)) self.assertEqual(2, update_subnetpool.call_count) + update_dict.pop('tags') update_subnetpool.assert_called_with( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', {'subnetpool': update_dict}) diff --git a/releasenotes/notes/set-tags-for-subnetpool-d86ca0d7e35a05f1.yaml b/releasenotes/notes/set-tags-for-subnetpool-d86ca0d7e35a05f1.yaml new file mode 100644 index 0000000000..7c8ecfe00c --- /dev/null +++ b/releasenotes/notes/set-tags-for-subnetpool-d86ca0d7e35a05f1.yaml @@ -0,0 +1,3 @@ +--- +features: + - Allow to set or update the tags for OS::Neutron::SubnetPool resource.