diff --git a/heat/engine/resources/openstack/neutron/router.py b/heat/engine/resources/openstack/neutron/router.py index a05eafcd86..9f8bb158b8 100644 --- a/heat/engine/resources/openstack/neutron/router.py +++ b/heat/engine/resources/openstack/neutron/router.py @@ -37,10 +37,10 @@ class Router(neutron.NeutronResource): PROPERTIES = ( NAME, EXTERNAL_GATEWAY, VALUE_SPECS, ADMIN_STATE_UP, - L3_AGENT_ID, L3_AGENT_IDS, DISTRIBUTED, HA, + L3_AGENT_ID, L3_AGENT_IDS, DISTRIBUTED, HA, TAGS, ) = ( 'name', 'external_gateway_info', 'value_specs', 'admin_state_up', - 'l3_agent_id', 'l3_agent_ids', 'distributed', 'ha' + 'l3_agent_id', 'l3_agent_ids', 'distributed', 'ha', 'tags', ) _EXTERNAL_GATEWAY_KEYS = ( @@ -173,6 +173,13 @@ class Router(neutron.NeutronResource): 'do not support distributed and ha at the same time.'), support_status=support.SupportStatus(version='2015.1') ), + TAGS: properties.Schema( + properties.Schema.LIST, + _('The tags to be added to the router.'), + schema=properties.Schema(properties.Schema.STRING), + update_allowed=True, + support_status=support.SupportStatus(version='9.0.0') + ), } attributes_schema = { @@ -297,12 +304,15 @@ class Router(neutron.NeutronResource): self.physical_resource_name()) self._resolve_gateway(props) l3_agent_ids = self._get_l3_agent_list(props) + tags = props.pop(self.TAGS, []) router = self.client().create_router({'router': props})['router'] self.resource_id_set(router['id']) if l3_agent_ids: self._replace_agent(l3_agent_ids) + if tags: + self.set_tags(tags) def check_create_complete(self, *args): attributes = self._show_resource() @@ -324,6 +334,10 @@ class Router(neutron.NeutronResource): l3_agent_ids = self._get_l3_agent_list(prop_diff) self._replace_agent(l3_agent_ids) + 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_router( diff --git a/heat/tests/openstack/neutron/test_neutron_router.py b/heat/tests/openstack/neutron/test_neutron_router.py index aa3d3d652c..f603a7a9c3 100644 --- a/heat/tests/openstack/neutron/test_neutron_router.py +++ b/heat/tests/openstack/neutron/test_neutron_router.py @@ -257,6 +257,8 @@ class NeutronRouterTest(common.HeatTestCase): def test_router(self): t = template_format.parse(neutron_template) + tags = ['for_test'] + t['resources']['router']['properties']['tags'] = tags stack = utils.parse_stack(t) create_body = { 'router': { @@ -321,8 +323,14 @@ class NeutronRouterTest(common.HeatTestCase): self.delete_mock.side_effect = [ None, qe.NeutronClientException(status_code=404)] + set_tag_mock = self.patchobject(neutronclient.Client, 'replace_tag') rsrc = self.create_router(t, stack, 'router') self.create_mock.assert_called_with(create_body) + set_tag_mock.assert_called_with( + 'routers', + rsrc.resource_id, + {'tags': tags} + ) rsrc.validate() ref_id = rsrc.FnGetRefId() @@ -334,14 +342,19 @@ class NeutronRouterTest(common.HeatTestCase): prop_diff = { "admin_state_up": False, "name": "myrouter", - "l3_agent_ids": ["63b3fd83-2c5f-4dad-b3ae-e0f83a40f216"] + "l3_agent_ids": ["63b3fd83-2c5f-4dad-b3ae-e0f83a40f216"], + 'tags': ['new_tag'] } props = copy.copy(rsrc.properties.data) props.update(prop_diff) update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(), props) rsrc.handle_update(update_snippet, {}, prop_diff) - + set_tag_mock.assert_called_with( + 'routers', + rsrc.resource_id, + {'tags': ['new_tag']} + ) self.update_mock.assert_called_with( '3e46229d-8fce-4733-819a-b5fe630550f8', {'router': { diff --git a/releasenotes/notes/add-tags-for-neutron-router-43d72e78aa89fd07.yaml b/releasenotes/notes/add-tags-for-neutron-router-43d72e78aa89fd07.yaml new file mode 100644 index 0000000000..7fce68c653 --- /dev/null +++ b/releasenotes/notes/add-tags-for-neutron-router-43d72e78aa89fd07.yaml @@ -0,0 +1,3 @@ +--- +features: + - Allow to set or update the tags for OS::Neutron::Router resource.