diff --git a/heat/engine/resources/openstack/neutron/subnet.py b/heat/engine/resources/openstack/neutron/subnet.py index bee9a6f889..316428823e 100644 --- a/heat/engine/resources/openstack/neutron/subnet.py +++ b/heat/engine/resources/openstack/neutron/subnet.py @@ -38,12 +38,12 @@ class Subnet(neutron.NeutronResource): NETWORK_ID, NETWORK, SUBNETPOOL, PREFIXLEN, CIDR, VALUE_SPECS, NAME, IP_VERSION, DNS_NAMESERVERS, GATEWAY_IP, ENABLE_DHCP, ALLOCATION_POOLS, TENANT_ID, HOST_ROUTES, - IPV6_RA_MODE, IPV6_ADDRESS_MODE, SEGMENT + IPV6_RA_MODE, IPV6_ADDRESS_MODE, SEGMENT, TAGS, ) = ( 'network_id', 'network', 'subnetpool', 'prefixlen', 'cidr', 'value_specs', 'name', 'ip_version', 'dns_nameservers', 'gateway_ip', 'enable_dhcp', 'allocation_pools', 'tenant_id', 'host_routes', - 'ipv6_ra_mode', 'ipv6_address_mode', 'segment' + 'ipv6_ra_mode', 'ipv6_address_mode', 'segment', 'tags', ) _ALLOCATION_POOL_KEYS = ( @@ -244,6 +244,13 @@ class Subnet(neutron.NeutronResource): ], support_status=support.SupportStatus(version='9.0.0') ), + TAGS: properties.Schema( + properties.Schema.LIST, + _('The tags to be added to the subnet.'), + schema=properties.Schema(properties.Schema.STRING), + update_allowed=True, + support_status=support.SupportStatus(version='9.0.0') + ), } attributes_schema = { @@ -374,12 +381,19 @@ class Subnet(neutron.NeutronResource): props['network_id'] = props.pop(self.NETWORK) if self.SEGMENT in props and props[self.SEGMENT]: props['segment_id'] = props.pop(self.SEGMENT) + + tags = props.pop(self.TAGS, []) + if self.SUBNETPOOL in props and props[self.SUBNETPOOL]: props['subnetpool_id'] = props.pop('subnetpool') self._null_gateway_ip(props) + subnet = self.client().create_subnet({'subnet': props})['subnet'] self.resource_id_set(subnet['id']) + if tags: + self.set_tags(tags) + def handle_delete(self): try: self.client().delete_subnet(self.resource_id) @@ -397,7 +411,9 @@ class Subnet(neutron.NeutronResource): # If the new value is '', set to None self._null_gateway_ip(prop_diff) - + if self.TAGS in prop_diff: + tags = prop_diff.pop(self.TAGS) + self.set_tags(tags) self.client().update_subnet( self.resource_id, {'subnet': prop_diff}) diff --git a/heat/tests/openstack/neutron/test_neutron_subnet.py b/heat/tests/openstack/neutron/test_neutron_subnet.py index 624de21e36..ff3679b395 100644 --- a/heat/tests/openstack/neutron/test_neutron_subnet.py +++ b/heat/tests/openstack/neutron/test_neutron_subnet.py @@ -124,11 +124,14 @@ class NeutronSubnetTest(common.HeatTestCase): stack) return rsrc - def _setup_mock(self, stack_name=None, use_deprecated_templ=False): + def _setup_mock(self, stack_name=None, use_deprecated_templ=False, + tags=None): if use_deprecated_templ: t = template_format.parse(neutron_template_deprecated) else: t = template_format.parse(neutron_template) + if tags: + t['resources']['sub_net']['properties']['tags'] = tags stack = utils.parse_stack(t, stack_name=stack_name) sn = { "subnet": { @@ -170,11 +173,12 @@ class NeutronSubnetTest(common.HeatTestCase): 'host_routes': [{'destination': '192.168.1.0/24', 'nexthop': '194.168.1.2'}], 'gateway_ip': '10.0.3.105', + 'tags': ['tag2', 'tag3'], 'allocation_pools': [ {'start': '10.0.3.20', 'end': '10.0.3.100'}, {'start': '10.0.3.110', 'end': '10.0.3.200'}]}} - t, stack = self._setup_mock() + t, stack = self._setup_mock(tags=['tag1', 'tag2']) create_props = {'subnet': { 'name': utils.PhysName(stack.name, 'test_subnet'), 'network_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', @@ -190,10 +194,16 @@ class NeutronSubnetTest(common.HeatTestCase): self.patchobject(stack['net'], 'FnGetRefId', return_value='fc68ea2c-b60b-4b4f-bd82-94ec81110766') + set_tag_mock = self.patchobject(neutronclient.Client, 'replace_tag') rsrc = self.create_subnet(t, stack, 'sub_net') scheduler.TaskRunner(rsrc.create)() self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.create_mock.assert_called_once_with(create_props) + set_tag_mock.assert_called_once_with( + 'subnets', + rsrc.resource_id, + {'tags': ['tag1', 'tag2']} + ) rsrc.validate() ref_id = rsrc.FnGetRefId() self.assertEqual('91e47a57-7508-46fe-afc9-fc454e8580e1', ref_id) @@ -213,6 +223,11 @@ class NeutronSubnetTest(common.HeatTestCase): self.update_mock.assert_called_once_with( '91e47a57-7508-46fe-afc9-fc454e8580e1', update_props) + set_tag_mock.assert_called_with( + 'subnets', + rsrc.resource_id, + {'tags': ['tag2', 'tag3']} + ) # with name None del update_props['subnet']['name'] rsrc.handle_update(update_snippet, {}, update_props['subnet']) diff --git a/releasenotes/notes/set-tags-for-subnet-17a97b88dd11de63.yaml b/releasenotes/notes/set-tags-for-subnet-17a97b88dd11de63.yaml new file mode 100644 index 0000000000..93c8de6957 --- /dev/null +++ b/releasenotes/notes/set-tags-for-subnet-17a97b88dd11de63.yaml @@ -0,0 +1,3 @@ +--- +features: + - Allow to set or update the tags for OS::Neutron::Subnet resource.