From 7005482787c3478589889d4e1457f569ac398ae3 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Sat, 19 Oct 2024 14:43:47 +0000 Subject: [PATCH] Add method to create network resource tags Depends-On: https://review.opendev.org/c/openstack/neutron/+/924724 Related-Bug: #2073836 Change-Id: I920595d36352f778b6488dfa3fe5d6278c0e7ec6 --- openstack/network/v2/_base.py | 20 +++++++++++++++++++ openstack/network/v2/_proxy.py | 13 ++++++++++++ openstack/network/v2/floating_ip.py | 6 +++--- openstack/network/v2/network.py | 6 +++--- openstack/network/v2/port.py | 5 ++--- openstack/network/v2/router.py | 6 +++--- openstack/network/v2/security_group.py | 6 +++--- openstack/network/v2/security_group_rule.py | 6 +++--- openstack/network/v2/subnet.py | 6 +++--- openstack/network/v2/subnet_pool.py | 7 ++++--- .../tests/functional/network/v2/common.py | 18 +++++++++++++++++ ...k-create-tags-method-ccb37b01ed52a58c.yaml | 5 +++++ 12 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 releasenotes/notes/network-create-tags-method-ccb37b01ed52a58c.yaml diff --git a/openstack/network/v2/_base.py b/openstack/network/v2/_base.py index e55b900ec..8282cd694 100644 --- a/openstack/network/v2/_base.py +++ b/openstack/network/v2/_base.py @@ -9,7 +9,11 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. + +from openstack.common import tag +from openstack import exceptions from openstack import resource +from openstack import utils class NetworkResource(resource.Resource): @@ -39,3 +43,19 @@ class NetworkResource(resource.Resource): if if_revision is not None: req.headers['If-Match'] = "revision_number=%d" % if_revision return req + + +class TagMixinNetwork(tag.TagMixin): + def add_tags(self, session, tags): + """Create the tags on the resource + + :param session: The session to use for making this request. + :param tags: List with tags to be set on the resource + """ + tags = tags or [] + url = utils.urljoin(self.base_path, self.id, 'tags') + session = self._get_session(session) + response = session.post(url, json={'tags': tags}) + exceptions.raise_from_response(response) + self._body.attributes.update({'tags': tags}) + return self diff --git a/openstack/network/v2/_proxy.py b/openstack/network/v2/_proxy.py index 1ea397046..bf3150c2c 100644 --- a/openstack/network/v2/_proxy.py +++ b/openstack/network/v2/_proxy.py @@ -5433,6 +5433,19 @@ class Proxy(proxy.Proxy): self._check_tag_support(resource) return resource.set_tags(self, tags) + def add_tags(self, resource, tags): + """Add tags to a specified resource + + :param resource: :class:`~openstack.resource.Resource` instance. + :param tags: New tags to be set. + :type tags: "list" + + :returns: The updated resource + :rtype: :class:`~openstack.resource.Resource` + """ + self._check_tag_support(resource) + return resource.add_tags(self, tags) + def add_tag(self, resource, tag): """Add one single tag to a specified resource diff --git a/openstack/network/v2/floating_ip.py b/openstack/network/v2/floating_ip.py index cb75e7a47..562ce763e 100644 --- a/openstack/network/v2/floating_ip.py +++ b/openstack/network/v2/floating_ip.py @@ -9,12 +9,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + from openstack.network.v2 import _base from openstack import resource -class FloatingIP(_base.NetworkResource, tag.TagMixin): +class FloatingIP(_base.NetworkResource, _base.TagMixinNetwork): name_attribute = "floating_ip_address" resource_name = "floating ip" resource_key = 'floatingip' @@ -43,7 +43,7 @@ class FloatingIP(_base.NetworkResource, tag.TagMixin): 'sort_key', 'sort_dir', tenant_id='project_id', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/network.py b/openstack/network/v2/network.py index a894668b0..12e0e4b21 100644 --- a/openstack/network/v2/network.py +++ b/openstack/network/v2/network.py @@ -9,12 +9,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + from openstack.network.v2 import _base from openstack import resource -class Network(_base.NetworkResource, tag.TagMixin): +class Network(_base.NetworkResource, _base.TagMixinNetwork): resource_key = 'network' resources_key = 'networks' base_path = '/networks' @@ -43,7 +43,7 @@ class Network(_base.NetworkResource, tag.TagMixin): provider_network_type='provider:network_type', provider_physical_network='provider:physical_network', provider_segmentation_id='provider:segmentation_id', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/port.py b/openstack/network/v2/port.py index ffecae3b2..a49fa4088 100644 --- a/openstack/network/v2/port.py +++ b/openstack/network/v2/port.py @@ -10,12 +10,11 @@ # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag from openstack.network.v2 import _base from openstack import resource -class Port(_base.NetworkResource, tag.TagMixin): +class Port(_base.NetworkResource, _base.TagMixinNetwork): resource_key = 'port' resources_key = 'ports' base_path = '/ports' @@ -53,7 +52,7 @@ class Port(_base.NetworkResource, tag.TagMixin): is_admin_state_up='admin_state_up', is_port_security_enabled='port_security_enabled', security_group_ids='security_groups', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/router.py b/openstack/network/v2/router.py index 41aba3018..42a84bbfa 100644 --- a/openstack/network/v2/router.py +++ b/openstack/network/v2/router.py @@ -9,14 +9,14 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + from openstack import exceptions from openstack.network.v2 import _base from openstack import resource from openstack import utils -class Router(_base.NetworkResource, tag.TagMixin): +class Router(_base.NetworkResource, _base.TagMixinNetwork): resource_key = 'router' resources_key = 'routers' base_path = '/routers' @@ -40,7 +40,7 @@ class Router(_base.NetworkResource, tag.TagMixin): is_admin_state_up='admin_state_up', is_distributed='distributed', is_ha='ha', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/security_group.py b/openstack/network/v2/security_group.py index 9e1797104..425878793 100644 --- a/openstack/network/v2/security_group.py +++ b/openstack/network/v2/security_group.py @@ -9,12 +9,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + from openstack.network.v2 import _base from openstack import resource -class SecurityGroup(_base.NetworkResource, tag.TagMixin): +class SecurityGroup(_base.NetworkResource, _base.TagMixinNetwork): resource_key = 'security_group' resources_key = 'security_groups' base_path = '/security-groups' @@ -37,7 +37,7 @@ class SecurityGroup(_base.NetworkResource, tag.TagMixin): 'revision_number', 'sort_dir', 'sort_key', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/security_group_rule.py b/openstack/network/v2/security_group_rule.py index ef9504d14..ba65c737c 100644 --- a/openstack/network/v2/security_group_rule.py +++ b/openstack/network/v2/security_group_rule.py @@ -9,12 +9,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + from openstack.network.v2 import _base from openstack import resource -class SecurityGroupRule(_base.NetworkResource, tag.TagMixin): +class SecurityGroupRule(_base.NetworkResource, _base.TagMixinNetwork): resource_key = 'security_group_rule' resources_key = 'security_group_rules' base_path = '/security-group-rules' @@ -43,7 +43,7 @@ class SecurityGroupRule(_base.NetworkResource, tag.TagMixin): 'sort_dir', 'sort_key', ether_type='ethertype', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/subnet.py b/openstack/network/v2/subnet.py index 5acc22744..959e29592 100644 --- a/openstack/network/v2/subnet.py +++ b/openstack/network/v2/subnet.py @@ -9,12 +9,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + from openstack.network.v2 import _base from openstack import resource -class Subnet(_base.NetworkResource, tag.TagMixin): +class Subnet(_base.NetworkResource, _base.TagMixinNetwork): resource_key = 'subnet' resources_key = 'subnets' base_path = '/subnets' @@ -44,7 +44,7 @@ class Subnet(_base.NetworkResource, tag.TagMixin): is_dhcp_enabled='enable_dhcp', subnet_pool_id='subnetpool_id', use_default_subnet_pool='use_default_subnetpool', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/network/v2/subnet_pool.py b/openstack/network/v2/subnet_pool.py index 5da9a4c94..f87248046 100644 --- a/openstack/network/v2/subnet_pool.py +++ b/openstack/network/v2/subnet_pool.py @@ -9,11 +9,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from openstack.common import tag + +from openstack.network.v2 import _base from openstack import resource -class SubnetPool(resource.Resource, tag.TagMixin): +class SubnetPool(resource.Resource, _base.TagMixinNetwork): resource_key = 'subnetpool' resources_key = 'subnetpools' base_path = '/subnetpools' @@ -37,7 +38,7 @@ class SubnetPool(resource.Resource, tag.TagMixin): 'sort_key', 'sort_dir', is_shared='shared', - **tag.TagMixin._tag_query_parameters, + **_base.TagMixinNetwork._tag_query_parameters, ) # Properties diff --git a/openstack/tests/functional/network/v2/common.py b/openstack/tests/functional/network/v2/common.py index e958c3f9b..8908d524e 100644 --- a/openstack/tests/functional/network/v2/common.py +++ b/openstack/tests/functional/network/v2/common.py @@ -88,3 +88,21 @@ class TestTagNeutron(base.BaseFunctionalTest): self.user_cloud.network.remove_all_tags(sot) sot = self.get_command(self.ID) self.assertEqual([], sot.tags) + + def test_add_tags(self): + sot = self.get_command(self.ID) + self.assertEqual([], sot.tags) + + self.user_cloud.network.add_tags(sot, ["red", "green"]) + self.user_cloud.network.add_tags(sot, ["blue", "yellow"]) + sot = self.get_command(self.ID) + self.assertEqual(["blue", "green", "red", "yellow"], sot.tags) + + # The operation is idempotent. + self.user_cloud.network.add_tags(sot, ["blue", "yellow"]) + sot = self.get_command(self.ID) + self.assertEqual(["blue", "green", "red", "yellow"], sot.tags) + + self.user_cloud.network.add_tags(sot, []) + sot = self.get_command(self.ID) + self.assertEqual(["blue", "green", "red", "yellow"], sot.tags) diff --git a/releasenotes/notes/network-create-tags-method-ccb37b01ed52a58c.yaml b/releasenotes/notes/network-create-tags-method-ccb37b01ed52a58c.yaml new file mode 100644 index 000000000..ff48f14ed --- /dev/null +++ b/releasenotes/notes/network-create-tags-method-ccb37b01ed52a58c.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Added a method to create (POST) tags in the network resources. This method + is idempotent.