From dbc6f7d44aa1c200fa9188ada338d1858735efdc Mon Sep 17 00:00:00 2001 From: Austin Jamias Date: Fri, 7 Nov 2025 19:06:37 -0500 Subject: [PATCH] Add ability to set tags in network modules This adds the `tags` parameter to the network, subnet, and router modules. Change-Id: I704b40c44c733a3d4ec93a95d8efcb7ecf6e2a32 Signed-off-by: Austin Jamias --- ci/roles/network/tasks/main.yml | 36 ++++++++++++++++++++++++++++++++ ci/roles/router/tasks/main.yml | 37 +++++++++++++++++++++++++++++++++ ci/roles/subnet/tasks/main.yml | 12 +++++++++++ plugins/modules/network.py | 15 ++++++++++++- plugins/modules/router.py | 13 ++++++++++++ plugins/modules/subnet.py | 13 ++++++++++++ 6 files changed, 125 insertions(+), 1 deletion(-) diff --git a/ci/roles/network/tasks/main.yml b/ci/roles/network/tasks/main.yml index bbd59dc7..ba55a0ba 100644 --- a/ci/roles/network/tasks/main.yml +++ b/ci/roles/network/tasks/main.yml @@ -69,6 +69,9 @@ external: false mtu: "{{ mtu }}" port_security_enabled: "{{ port_security_enabled }}" + tags: + - foo + - bar register: result_create_nw_with_new_params ignore_errors: true @@ -85,6 +88,8 @@ - result_newparams.networks.0.mtu == mtu - "'is_port_security_enabled' in result_newparams.networks.0" - result_newparams.networks.0['is_port_security_enabled'] == port_security_enabled + - "'foo' in result_newparams.networks.0.tags" + - "'bar' in result_newparams.networks.0.tags" - name: Delete network - generic and with new SDK params openstack.cloud.network: @@ -115,6 +120,9 @@ external: false mtu: "{{ mtu }}" port_security_enabled: "{{ port_security_enabled }}" + tags: + - foo + - bar register: result_create_nw_for_updates - name: Update network - update failure @@ -147,6 +155,11 @@ mtu: "{{ mtu - 50 }}" # NOTE: This property should be updated port_security_enabled: "{{ not port_security_enabled }}" + # NOTE: This property should be updated + tags: + - foo + - bar + - baz register: result_nw_update_success - name: Gather networks info - updates @@ -162,6 +175,29 @@ - result_network_updates_info.networks.0.name == network_name_updates - result_network_updates_info.networks.0.mtu == mtu - 50 - result_network_updates_info.networks.0['is_port_security_enabled'] == (not port_security_enabled) + - "'foo' in result_network_updates_info.networks.0.tags" + - "'bar' in result_network_updates_info.networks.0.tags" + - "'baz' in result_network_updates_info.networks.0.tags" + +- name: Update network - no change + openstack.cloud.network: + cloud: "{{ cloud }}" + name: "{{ network_name_updates }}" + state: present + shared: "{{ network_shared }}" + external: false + mtu: "{{ mtu - 50 }}" + port_security_enabled: "{{ not port_security_enabled }}" + tags: + - foo + - bar + - baz + register: result_nw_update_no_change + +- name: Verify networks info - no change + assert: + that: + - result_nw_update_no_change is not changed - name: Delete network - updates openstack.cloud.network: diff --git a/ci/roles/router/tasks/main.yml b/ci/roles/router/tasks/main.yml index 53694852..abcda9d7 100644 --- a/ci/roles/router/tasks/main.yml +++ b/ci/roles/router/tasks/main.yml @@ -325,6 +325,43 @@ - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list == ['10.7.7.1'] +- name: Update router (add tags) + openstack.cloud.router: + cloud: "{{ cloud }}" + state: present + name: "{{ router_name }}" + tags: + - foo + - bar + +- name: Gather routers info + openstack.cloud.routers_info: + cloud: "{{ cloud }}" + name: "{{ router_name }}" + register: info + +- name: Verify tags + assert: + that: + - info.routers.0.name == router_name + - info.routers.0.id == router.router.id + - "'foo' in info.routers.0.tags" + - "'bar' in info.routers.0.tags" + +- name: Update router (add tags) again + openstack.cloud.router: + cloud: "{{ cloud }}" + state: present + name: "{{ router_name }}" + tags: + - foo + - bar + register: router + +- name: Assert idempotent module + assert: + that: router is not changed + # Admin operation - name: Create external network openstack.cloud.network: diff --git a/ci/roles/subnet/tasks/main.yml b/ci/roles/subnet/tasks/main.yml index 5c48f32b..875acab1 100644 --- a/ci/roles/subnet/tasks/main.yml +++ b/ci/roles/subnet/tasks/main.yml @@ -31,6 +31,9 @@ gateway_ip: 192.168.0.1 allocation_pool_start: 192.168.0.2 allocation_pool_end: 192.168.0.254 + tags: + - foo + - bar register: subnet - name: Assert changed @@ -56,6 +59,9 @@ gateway_ip: 192.168.0.1 allocation_pool_start: 192.168.0.2 allocation_pool_end: 192.168.0.254 + tags: + - foo + - bar register: subnet - name: Assert not changed @@ -80,6 +86,8 @@ enable_dhcp: "{{ enable_subnet_dhcp }}" gateway_ip: 192.168.0.1 cidr: 192.168.0.0/24 + tags: + - bar register: subnet - name: Verify Subnet info result @@ -114,6 +122,10 @@ dns_nameservers: - 8.8.8.7 cidr: 192.168.0.0/24 + tags: + - foo + - bar + - baz register: subnet - name: Assert changed diff --git a/plugins/modules/network.py b/plugins/modules/network.py index 8e1a3387..ed6fb641 100644 --- a/plugins/modules/network.py +++ b/plugins/modules/network.py @@ -83,6 +83,11 @@ options: Network will use Openstack defaults if this option is not provided. type: str + tags: + description: + - A list of tags to set on the network + type: list + elements: str extends_documentation_fragment: - openstack.cloud.openstack ''' @@ -208,7 +213,8 @@ class NetworkModule(OpenStackModule): project=dict(), port_security_enabled=dict(type='bool'), mtu=dict(type='int', aliases=['mtu_size']), - dns_domain=dict() + dns_domain=dict(), + tags=dict(type='list', elements='str'), ) def run(self): @@ -224,6 +230,7 @@ class NetworkModule(OpenStackModule): provider_network_type = self.params['provider_network_type'] provider_segmentation_id = self.params['provider_segmentation_id'] project = self.params['project'] + tags = self.params['tags'] kwargs = {} for arg in ('port_security_enabled', 'mtu', 'dns_domain'): @@ -304,6 +311,12 @@ class NetworkModule(OpenStackModule): ) changed = True + if tags is not None: + old_tags = self.conn.network.get_tags(net) + if set(old_tags) != set(tags): + self.conn.network.set_tags(net, tags) + changed = True + net = net.to_dict(computed=False) self.exit(changed=changed, network=net, id=net['id']) elif state == 'absent': diff --git a/plugins/modules/router.py b/plugins/modules/router.py index 47df8c97..a928a0f7 100644 --- a/plugins/modules/router.py +++ b/plugins/modules/router.py @@ -112,6 +112,11 @@ options: choices: ['present', 'absent'] default: present type: str + tags: + description: + - A list of tags to set on the network + type: list + elements: str extends_documentation_fragment: - openstack.cloud.openstack ''' @@ -326,6 +331,7 @@ class RouterModule(OpenStackModule): network=dict(), project=dict(), state=dict(default='present', choices=['absent', 'present']), + tags=dict(type='list', elements='str'), ) module_kwargs = dict( @@ -603,6 +609,7 @@ class RouterModule(OpenStackModule): name = self.params['name'] network_name_or_id = self._get_external_gateway_network_name() project_name_or_id = self.params['project'] + tags = self.params['tags'] if self.params['external_fixed_ips'] and not network_name_or_id: self.fail( @@ -686,6 +693,12 @@ class RouterModule(OpenStackModule): self._update_ifaces(router, to_add, to_remove, missing_internal_ports) + if tags is not None: + old_tags = self.conn.network.get_tags(router) + if set(old_tags) != set(tags): + self.conn.network.set_tags(router, tags) + changed = True + self.exit_json(changed=changed, router=router.to_dict(computed=False)) diff --git a/plugins/modules/subnet.py b/plugins/modules/subnet.py index 7c50aee3..9e371192 100644 --- a/plugins/modules/subnet.py +++ b/plugins/modules/subnet.py @@ -133,6 +133,11 @@ options: - The subnet pool name or ID from which to obtain a CIDR type: str required: false + tags: + description: + - A list of tags to set on the network + type: list + elements: str extends_documentation_fragment: - openstack.cloud.openstack ''' @@ -317,6 +322,7 @@ class SubnetModule(OpenStackModule): state=dict(default='present', choices=['absent', 'present']), project=dict(), + tags=dict(type='list', elements='str'), ) module_kwargs = dict( @@ -421,6 +427,7 @@ class SubnetModule(OpenStackModule): subnet_name = self.params['name'] gateway_ip = self.params['gateway_ip'] disable_gateway_ip = self.params['disable_gateway_ip'] + tags = self.params['tags'] # fail early if incompatible options have been specified if disable_gateway_ip and gateway_ip: @@ -470,6 +477,12 @@ class SubnetModule(OpenStackModule): self._validate_update(subnet, updates) subnet = self.conn.network.update_subnet(subnet, **updates) changed = True + if tags is not None: + old_tags = self.conn.network.get_tags(subnet) + if set(old_tags) != set(tags): + self.conn.network.set_tags(subnet, tags) + changed = True + self.exit_json(changed=changed, subnet=subnet, id=subnet.id) elif state == 'absent' and subnet is not None: self.conn.network.delete_subnet(subnet)