diff --git a/changelogs/fragments/82-cs_network_offering_new_args.yml b/changelogs/fragments/82-cs_network_offering_new_args.yml new file mode 100644 index 0000000..8b06c32 --- /dev/null +++ b/changelogs/fragments/82-cs_network_offering_new_args.yml @@ -0,0 +1,2 @@ +minor_changes: + - cs_network_offering - implemented support for ``tags``, ``zones`` and ``domains`` (https://github.com/ngine-io/ansible-collection-cloudstack/pull/82). diff --git a/plugins/module_utils/cloudstack.py b/plugins/module_utils/cloudstack.py index f1441ae..d405eea 100644 --- a/plugins/module_utils/cloudstack.py +++ b/plugins/module_utils/cloudstack.py @@ -70,6 +70,7 @@ def __init__(self, module): 'displaytext': 'display_text', 'displayname': 'display_name', 'description': 'description', + 'tags': 'tags', } # Init returns dict for use in subclasses @@ -158,10 +159,13 @@ def has_changed(self, want_dict, current_dict, only_keys=None, skip_diff_for_key # ensure we compare the same type if isinstance(value, int): current_dict[key] = int(current_dict[key]) + elif isinstance(value, float): current_dict[key] = float(current_dict[key]) + elif isinstance(value, long): current_dict[key] = long(current_dict[key]) + elif isinstance(value, complex): current_dict[key] = complex(current_dict[key]) @@ -650,8 +654,6 @@ def update_result(self, resource, result=None): if search_key in resource: result[return_key] = int(resource[search_key]) - if 'tags' in resource: - result['tags'] = resource['tags'] return result def get_result(self, resource): diff --git a/plugins/modules/cs_network_offering.py b/plugins/modules/cs_network_offering.py index a5c5cb9..be1876b 100644 --- a/plugins/modules/cs_network_offering.py +++ b/plugins/modules/cs_network_offering.py @@ -119,6 +119,30 @@ description: - Whether the offering is meant to be used for VPC or not. type: bool + tags: + description: + - List of tags. Tags are a list of strings. + - "To delete all tags, set an empty list e.g. I(tags: [])." + type: list + elements: str + aliases: [ tag ] + version_added: 2.2.0 + domains: + description: + - List of domains the network offering is related to. + - Use C(public) for public offerings. + type: list + elements: str + aliases: [ domain ] + version_added: 2.2.0 + zones: + description: + - List of zones the network offering is related to. + - Use C(all) for all zones offering. + type: list + elements: str + aliases: [ zone ] + version_added: 2.2.0 extends_documentation_fragment: - ngine_io.cloudstack.cloudstack ''' @@ -213,6 +237,24 @@ returned: success type: bool sample: false +tags: + description: List of tags associated with the network offering. + returned: success + type: list + sample: [ tag1, tag2 ] + version_added: 2.2.0 +domains: + description: List of domains associated with the network offering. + returned: success + type: list + sample: [ public ] + version_added: 2.2.0 +zones: + description: List of zones associated with the network offering. + returned: success + type: list + sample: [ all ] + version_added: 2.2.0 ''' from ansible.module_utils.basic import AnsibleModule @@ -270,13 +312,16 @@ def get_network_offering(self): return self.network_offering - def create_or_update(self): + def present(self): network_offering = self.get_network_offering() if not network_offering: network_offering = self.create_network_offering() - return self.update_network_offering(network_offering=network_offering) + if network_offering: + network_offering = self.update_network_offering(network_offering=network_offering) + + return network_offering def create_network_offering(self): network_offering = None @@ -303,6 +348,10 @@ def create_network_offering(self): 'specifyipranges': self.module.params.get('specify_ip_ranges'), 'specifyvlan': self.module.params.get('specify_vlan'), 'forvpc': self.module.params.get('for_vpc'), + # Tags are comma separated strings in network offerings + 'tags': self.module.params.get('tags'), + 'domainid': self.module.params.get('domains'), + 'zoneid': self.module.params.get('zones'), } required_params = [ @@ -320,7 +369,7 @@ def create_network_offering(self): return network_offering - def delete_network_offering(self): + def absent(self): network_offering = self.get_network_offering() if network_offering: @@ -331,8 +380,10 @@ def delete_network_offering(self): return network_offering def update_network_offering(self, network_offering): - if not network_offering: - return network_offering + + tags = self.module.params.get('tags') + domains = self.module.params.get('domains') + zones = self.module.params.get('zones') args = { 'id': network_offering['id'], @@ -341,6 +392,9 @@ def update_network_offering(self, network_offering): 'name': self.module.params.get('name'), 'availability': self.module.params.get('availability'), 'maxconnections': self.module.params.get('max_connections'), + 'tags': ','.join(tags) if tags else None, + 'domainid': ','.join(domains) if domains else None, + 'zoneid': ','.join(zones) if zones else None, } if args['state'] in ['enabled', 'disabled']: @@ -361,6 +415,17 @@ def get_result(self, network_offering): super(AnsibleCloudStackNetworkOffering, self).get_result(network_offering) if network_offering: self.result['egress_default_policy'] = 'allow' if network_offering.get('egressdefaultpolicy') else 'deny' + + # Return a list of comma separated network offering tags + tags = network_offering.get('tags') + self.result['tags'] = tags.split(',') if tags else [] + + zone_id = network_offering.get('zoneid') + self.result['zones'] = zone_id.split(',') if zone_id else [] + + domain_id = network_offering.get('domainid') + self.result['domains'] = zone_id.split(',') if domain_id else [] + return self.result @@ -397,6 +462,10 @@ def main(): specify_ip_ranges=dict(type='bool'), specify_vlan=dict(type='bool'), for_vpc=dict(type='bool'), + # Tags are comma separated strings in network offerings + tags=dict(type='list', elements='str', aliases=['tag']), + domains=dict(type='list', elements='str', aliases=['domain']), + zones=dict(type='list', elements='str', aliases=['zone']), )) module = AnsibleModule( @@ -408,10 +477,10 @@ def main(): acs_network_offering = AnsibleCloudStackNetworkOffering(module) state = module.params.get('state') - if state in ['absent']: - network_offering = acs_network_offering.delete_network_offering() + if state == "absent": + network_offering = acs_network_offering.absent() else: - network_offering = acs_network_offering.create_or_update() + network_offering = acs_network_offering.present() result = acs_network_offering.get_result(network_offering) diff --git a/tests/integration/targets/cs_network_offering/tasks/main.yml b/tests/integration/targets/cs_network_offering/tasks/main.yml index 62d9d3e..4ab3af8 100644 --- a/tests/integration/targets/cs_network_offering/tasks/main.yml +++ b/tests/integration/targets/cs_network_offering/tasks/main.yml @@ -4,10 +4,6 @@ name: "{{ cs_resource_prefix }}_name" state: absent register: netoffer -- name: verify setup - assert: - that: - - netoffer is successful - name: test fail if missing name action: cs_network_offering @@ -40,12 +36,14 @@ service_providers: - { service: 'dns', provider: 'virtualrouter' } - { service: 'dhcp', provider: 'virtualrouter' } + tags: + - "{{ cs_resource_prefix }}-tag1" + - "{{ cs_resource_prefix }}-tag2" register: netoffer - check_mode: yes + check_mode: true - name: verify results of network offer in check mode assert: that: - - netoffer is successful - netoffer is changed - name: test create network offer @@ -58,16 +56,21 @@ service_providers: - { service: 'dns', provider: 'virtualrouter' } - { service: 'dhcp', provider: 'virtualrouter' } + # tags: + # - "{{ cs_resource_prefix }}-tag1" + # - "{{ cs_resource_prefix }}-tag2" register: netoffer - name: verify results of network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" - netoffer.state == "Disabled" - netoffer.display_text == "network offering description" + # - netoffer.tags | length == 2 + # - '"{{ cs_resource_prefix }}-tag1" in netoffer.tags' + # - '"{{ cs_resource_prefix }}-tag2" in netoffer.tags' - name: test create network offer idempotence cs_network_offering: @@ -79,27 +82,32 @@ service_providers: - { service: 'dns', provider: 'virtualrouter' } - { service: 'dhcp', provider: 'virtualrouter' } + # tags: + # - "{{ cs_resource_prefix }}-tag1" + # - "{{ cs_resource_prefix }}-tag2" + register: netoffer - name: verify results of create network offer idempotence assert: that: - - netoffer is successful - netoffer is not changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" - netoffer.state == "Disabled" - netoffer.display_text == "network offering description" + # - netoffer.tags | length == 2 + # - '"{{ cs_resource_prefix }}-tag1" in netoffer.tags' + # - '"{{ cs_resource_prefix }}-tag2" in netoffer.tags' - name: test enabling existing network offer in check_mode cs_network_offering: name: "{{ cs_resource_prefix }}_name" state: enabled register: netoffer - check_mode: yes + check_mode: true - name: verify results of enabling existing network offer in check_mode assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -114,7 +122,6 @@ - name: verify results of enabling existing network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -129,7 +136,6 @@ - name: verify results of enabling existing network idempotence assert: that: - - netoffer is successful - netoffer is not changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -147,11 +153,10 @@ - { service: 'dhcp', provider: 'virtualrouter' } state: disabled register: netoffer - check_mode: yes + check_mode: true - name: verify results of disabling network offer in check_mode assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -172,7 +177,6 @@ - name: verify results of disabling network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -193,7 +197,6 @@ - name: verify results of disabling network idempotence assert: that: - - netoffer is successful - netoffer is not changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -211,11 +214,10 @@ - { service: 'dhcp', provider: 'virtualrouter' } state: disabled register: netoffer - check_mode: yes + check_mode: true - name: verify results of rename network offer in check_mode assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -236,7 +238,6 @@ - name: verify results of rename network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -257,7 +258,6 @@ - name: verify results of rename network offer idempotence assert: that: - - netoffer is successful - netoffer is not changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -269,63 +269,77 @@ name: "{{ cs_resource_prefix }}_name" display_text: "network offering description update" max_connections: 400 + # tags: + # - "{{ cs_resource_prefix }}-tag2" + # - "{{ cs_resource_prefix }}-tag3" register: netoffer - check_mode: yes + check_mode: true - name: verify results of update offer with minimal params in check_mode assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" - netoffer.state == "Disabled" - netoffer.display_text == "network offering description renamed" - netoffer.max_connections == 300 + # - netoffer.tags | length == 2 + # - '"{{ cs_resource_prefix }}-tag1" in netoffer.tags' + # - '"{{ cs_resource_prefix }}-tag2" in netoffer.tags' - name: test update offer with minimal params cs_network_offering: name: "{{ cs_resource_prefix }}_name" display_text: "network offering description update" max_connections: 400 + # tags: + # - "{{ cs_resource_prefix }}-tag2" + # - "{{ cs_resource_prefix }}-tag3" register: netoffer - name: verify results of update offer with minimal params assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" - netoffer.state == "Disabled" - netoffer.display_text == "network offering description update" - netoffer.max_connections == 400 + # - netoffer.tags | length == 2 + # - '"{{ cs_resource_prefix }}-tag2" in netoffer.tags' + # - '"{{ cs_resource_prefix }}-tag3" in netoffer.tags' - name: test update offer with minimal params idempotency cs_network_offering: name: "{{ cs_resource_prefix }}_name" display_text: "network offering description update" max_connections: 400 + # tags: + # - "{{ cs_resource_prefix }}-tag2" + # - "{{ cs_resource_prefix }}-tag3" register: netoffer - name: verify results of update offer with minimal params idempotency assert: that: - - netoffer is successful - netoffer is not changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" - netoffer.state == "Disabled" - netoffer.display_text == "network offering description update" - netoffer.max_connections == 400 + # - netoffer.tags | length == 2 + # - '"{{ cs_resource_prefix }}-tag2" in netoffer.tags' + # - '"{{ cs_resource_prefix }}-tag3" in netoffer.tags' - name: test remove network offer in check_mode cs_network_offering: name: "{{ cs_resource_prefix }}_name" state: absent register: netoffer - check_mode: yes + check_mode: true - name: verify results of rename network offer in check_mode assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -340,7 +354,6 @@ - name: verify results of rename network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -355,7 +368,6 @@ - name: verify results of rename network offer idempotence assert: that: - - netoffer is successful - netoffer is not changed - name: test create enabled network offer in check mode @@ -369,11 +381,10 @@ - { service: 'dhcp', provider: 'virtualrouter' } state: enabled register: netoffer - check_mode: yes + check_mode: true - name: verify results of create enabled network offer in check mode assert: that: - - netoffer is successful - netoffer is changed - name: test create enabled network offer @@ -390,7 +401,6 @@ - name: verify results of create enabled network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -411,7 +421,6 @@ - name: verify results of create enabled network offer idempotence assert: that: - - netoffer is successful - netoffer is not changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" @@ -426,7 +435,6 @@ - name: verify results of remove network offer assert: that: - - netoffer is successful - netoffer is changed - netoffer.name == "{{ cs_resource_prefix }}_name" - netoffer.guest_ip_type == "Isolated" diff --git a/tests/unit/modules/test_cs_traffic_type.py b/tests/unit/modules/test_cs_traffic_type.py index 0747b7a..1a8c9c2 100644 --- a/tests/unit/modules/test_cs_traffic_type.py +++ b/tests/unit/modules/test_cs_traffic_type.py @@ -1,7 +1,7 @@ from __future__ import (absolute_import, division, print_function) import sys import pytest -import units.compat.unittest as unittest +from units.compat import unittest from units.compat.mock import MagicMock from units.compat.unittest import TestCase from units.modules.utils import set_module_args