From c79cc8c7f28d189c61a5889c8e0ce9cc4ca69c8f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Aug 2019 07:24:35 +0200 Subject: [PATCH 01/17] Rename cloudstack _facts -> _info --- .../rst/porting_guides/porting_guide_2.9.rst | 6 ++ .../cloud/cloudstack/_cs_instance_facts.py | 1 + .../cloud/cloudstack/_cs_zone_facts.py | 1 + ..._instance_facts.py => cs_instance_info.py} | 63 ++++++++++---- .../{cs_zone_facts.py => cs_zone_info.py} | 52 +++++++---- .../targets/cs_instance/tasks/host.yml | 5 +- .../targets/cs_instance/tasks/present.yml | 2 +- .../targets/cs_instance_facts/tasks/main.yml | 86 ------------------- .../aliases | 0 .../defaults/main.yml | 0 .../meta/main.yml | 0 .../targets/cs_instance_info/tasks/main.yml | 74 ++++++++++++++++ .../cs_volume/tasks/extract_upload.yml | 6 +- .../{cs_zone_facts => cs_zone_info}/aliases | 0 .../meta/main.yml | 0 .../tasks/main.yml | 34 ++------ test/sanity/ignore.txt | 6 +- 17 files changed, 179 insertions(+), 157 deletions(-) create mode 120000 lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py create mode 120000 lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py rename lib/ansible/modules/cloud/cloudstack/{cs_instance_facts.py => cs_instance_info.py} (83%) rename lib/ansible/modules/cloud/cloudstack/{cs_zone_facts.py => cs_zone_info.py} (72%) delete mode 100644 test/integration/targets/cs_instance_facts/tasks/main.yml rename test/integration/targets/{cs_instance_facts => cs_instance_info}/aliases (100%) rename test/integration/targets/{cs_instance_facts => cs_instance_info}/defaults/main.yml (100%) rename test/integration/targets/{cs_instance_facts => cs_instance_info}/meta/main.yml (100%) create mode 100644 test/integration/targets/cs_instance_info/tasks/main.yml rename test/integration/targets/{cs_zone_facts => cs_zone_info}/aliases (100%) rename test/integration/targets/{cs_zone_facts => cs_zone_info}/meta/main.yml (100%) rename test/integration/targets/{cs_zone_facts => cs_zone_info}/tasks/main.yml (51%) diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst index 81bab7420e2b42..2824a6d30def2d 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst @@ -353,6 +353,12 @@ be removed in Ansible 2.13. Please update update your playbooks accordingly. When called with the new name, the module no longer returns ``ansible_facts``. To access return values, :ref:`register a variable `. * The ``cloudwatchlogs_log_group_facts`` module was renamed to :ref:`cloudwatchlogs_log_group_info `. +* The ``cs_instance_facts`` module was renamed to :ref:`cs_instance_info `. + When called with the new name, the module no longer returns ``ansible_facts``. + To access return values, :ref:`register a variable `. +* The ``cs_zone_facts`` module was renamed to :ref:`cs_zone_info `. + When called with the new name, the module no longer returns ``ansible_facts``. + To access return values, :ref:`register a variable `. * The ``digital_ocean_account_facts`` module was renamed to :ref:`digital_ocean_account_info `. * The ``digital_ocean_certificate_facts`` module was renamed to :ref:`digital_ocean_certificate_info `. * The ``digital_ocean_domain_facts`` module was renamed to :ref:`digital_ocean_domain_info `. diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py new file mode 120000 index 00000000000000..b47ddbd4619b2c --- /dev/null +++ b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py @@ -0,0 +1 @@ +cs_instance_info.py \ No newline at end of file diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py new file mode 120000 index 00000000000000..d041284b8be755 --- /dev/null +++ b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py @@ -0,0 +1 @@ +cs_zone_info.py \ No newline at end of file diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_facts.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py similarity index 83% rename from lib/ansible/modules/cloud/cloudstack/cs_instance_facts.py rename to lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index 78e4f304b0fa05..6959a4b0d7c7fd 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_facts.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -15,10 +15,13 @@ DOCUMENTATION = ''' --- -module: cs_instance_facts -short_description: Gathering facts from the API of instances from Apache CloudStack based clouds. +module: cs_instance_info +short_description: Gathering information from the API of instances from Apache CloudStack based clouds. description: - - Gathering facts from the API of an instance. + - Gathering information from the API of an instance. + - This module was called C(cs_instance_facts) before Ansible 2.9, returning C(ansible_facts) with key C(cloudstack_instance). + Since Ansible 2.6, the module also returned registerable results. + Note that the M(cs_instance_info) module no longer returns C(ansible_facts)! version_added: '2.1' author: René Moser (@resmo) options: @@ -43,17 +46,28 @@ ''' EXAMPLES = ''' -- name: gather instance facts - cs_instance_facts: +- name: gather instance info + cs_instance_info: name: web-vm-1 delegate_to: localhost register: vm -- debug: - var: cloudstack_instance - -- debug: +- name: Show the returned results of the registered variable + debug: var: vm + +# When the module is called as cs_instance_info, return values are also +# published in ansible_facts['cloudstack_instance'] and can be used as +# follows. Note that this is deprecated and will stop working in +# Ansible 2.13. +- name: gather instance info + cs_instance_facts: + name: web-vm-1 + delegate_to: localhost + +- name: Show the facts by the ansible_facts key cloudstack_instance + debug: + var: cloudstack_instance ''' RETURN = ''' @@ -256,10 +270,10 @@ from ansible.module_utils.cloudstack import AnsibleCloudStack, cs_argument_spec -class AnsibleCloudStackInstanceFacts(AnsibleCloudStack): +class AnsibleCloudStackInstanceInfo(AnsibleCloudStack): def __init__(self, module): - super(AnsibleCloudStackInstanceFacts, self).__init__(module) + super(AnsibleCloudStackInstanceInfo, self).__init__(module) self.instance = None self.returns = { 'group': 'group', @@ -274,7 +288,7 @@ def __init__(self, module): 'keypair': 'ssh_key', 'hostname': 'host', } - self.facts = { + self.info = { 'cloudstack_instance': None, } @@ -322,7 +336,7 @@ def run(self): return instance def get_result(self, instance): - super(AnsibleCloudStackInstanceFacts, self).get_result(instance) + super(AnsibleCloudStackInstanceInfo, self).get_result(instance) if instance: if 'securitygroup' in instance: security_groups = [] @@ -358,12 +372,23 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, ) - acs_instance_facts = AnsibleCloudStackInstanceFacts(module=module) - cs_instance_facts = acs_instance_facts.get_result_and_facts( - facts_name='cloudstack_instance', - resource=acs_instance_facts.run() - ) - module.exit_json(**cs_instance_facts) + is_old_facts = module._name == 'cs_instance_facts' + if is_old_facts: + module.deprecate("The 'cs_instance_facts' module has been renamed to 'cs_instance_info', " + "and the renamed one no longer returns ansible_facts", version='2.13') + + acs_instance_info = AnsibleCloudStackInstanceInfo(module=module) + if is_old_facts: + cs_instance_info = acs_instance_info.get_result_and_facts( + facts_name='cloudstack_instance', + resource=acs_instance_info.run() + ) + module.exit_json(**cs_instance_info) + else: + cs_instance_info = acs_instance_info.get_result( + resource=acs_instance_info.run() + ) + module.exit_json(**cs_instance_info) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_facts.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py similarity index 72% rename from lib/ansible/modules/cloud/cloudstack/cs_zone_facts.py rename to lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 92c815e95756f4..5e98e84a0f1b1b 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_facts.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -11,11 +11,14 @@ DOCUMENTATION = ''' --- -module: cs_zone_facts -short_description: Gathering facts of zones from Apache CloudStack based clouds. +module: cs_zone_info +short_description: Gathering information about zones from Apache CloudStack based clouds. description: - - Gathering facts from the API of a zone. + - Gathering information from the API of a zone. - Sets Ansible facts accessable by the key C(cloudstack_zone) and since version 2.6 also returns results. + - This module was called C(cs_zone_facts) before Ansible 2.9, returning C(ansible_facts) with key C(cloudstack_zone). + Since Ansible 2.6, the module also returned registerable results. + Note that the M(cs_zone_info) module no longer returns C(ansible_facts)! version_added: '2.1' author: René Moser (@resmo) options: @@ -29,8 +32,8 @@ ''' EXAMPLES = ''' -- name: Gather facts from a zone - cs_zone_facts: +- name: Gather info from a zone + cs_zone_info: name: ch-gva-1 register: zone delegate_to: localhost @@ -39,6 +42,15 @@ debug: var: zone +# When the module is called as cs_zone_info, return values are also +# published in ansible_facts['cloudstack_zone'] and can be used as +# follows. Note that this is deprecated and will stop working in +# Ansible 2.13. +- name: Gather info from a zone + cs_zone_facts: + name: ch-gva-1 + delegate_to: localhost + - name: Show the facts by the ansible_facts key cloudstack_zone debug: var: cloudstack_zone @@ -145,10 +157,10 @@ ) -class AnsibleCloudStackZoneFacts(AnsibleCloudStack): +class AnsibleCloudStackZoneInfo(AnsibleCloudStack): def __init__(self, module): - super(AnsibleCloudStackZoneFacts, self).__init__(module) + super(AnsibleCloudStackZoneInfo, self).__init__(module) self.returns = { 'dns1': 'dns1', 'dns2': 'dns2', @@ -167,7 +179,7 @@ def __init__(self, module): } def get_zone(self): - return super(AnsibleCloudStackZoneFacts, self).get_zone() + return super(AnsibleCloudStackZoneInfo, self).get_zone() def main(): @@ -180,13 +192,23 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, ) - - acs_zone_facts = AnsibleCloudStackZoneFacts(module=module) - result = acs_zone_facts.get_result_and_facts( - facts_name='cloudstack_zone', - resource=acs_zone_facts.get_zone() - ) - module.exit_json(**result) + is_old_facts = module._name == 'cs_zone_facts' + if is_old_facts: + module.deprecate("The 'cs_zone_facts' module has been renamed to 'cs_zone_info', " + "and the renamed one no longer returns ansible_facts", version='2.13') + + acs_zone_info = AnsibleCloudStackZoneInfo(module=module) + if is_old_facts: + result = acs_zone_info.get_result_and_facts( + facts_name='cloudstack_zone', + resource=acs_zone_info.get_zone() + ) + module.exit_json(**result) + else: + result = acs_zone_info.get_result( + resource=acs_zone_info.get_zone() + ) + module.exit_json(**result) if __name__ == '__main__': diff --git a/test/integration/targets/cs_instance/tasks/host.yml b/test/integration/targets/cs_instance/tasks/host.yml index c0614a1624cd40..9bc61401d5ae54 100644 --- a/test/integration/targets/cs_instance/tasks/host.yml +++ b/test/integration/targets/cs_instance/tasks/host.yml @@ -13,11 +13,12 @@ state: stopped - name: setup zone facts - cs_zone_facts: + cs_zone_info: name: "{{ cs_common_zone_basic }}" + register: zone_info - name: setup find the host name - shell: cs listHosts type=routing zoneid="{{ cloudstack_zone.id }}" + shell: cs listHosts type=routing zoneid="{{ zone_info.id }}" args: chdir: "{{ playbook_dir }}" register: host diff --git a/test/integration/targets/cs_instance/tasks/present.yml b/test/integration/targets/cs_instance/tasks/present.yml index 7edf54bed3ca6c..28d3eb2fecf230 100644 --- a/test/integration/targets/cs_instance/tasks/present.yml +++ b/test/integration/targets/cs_instance/tasks/present.yml @@ -86,7 +86,7 @@ - not instance.tags - name: gather host facts of running instance - cs_instance_facts: + cs_instance_info: name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" - name: test running instance not updated in check mode diff --git a/test/integration/targets/cs_instance_facts/tasks/main.yml b/test/integration/targets/cs_instance_facts/tasks/main.yml deleted file mode 100644 index b7824f1b6a75ec..00000000000000 --- a/test/integration/targets/cs_instance_facts/tasks/main.yml +++ /dev/null @@ -1,86 +0,0 @@ ---- -- name: setup ssh key - cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey - register: sshkey -- name: verify setup ssh key - assert: - that: - - sshkey is successful - -- name: setup affinity group - cs_affinitygroup: name={{ cs_resource_prefix }}-ag - register: ag -- name: verify setup affinity group - assert: - that: - - ag is successful - -- name: setup security group - cs_securitygroup: name={{ cs_resource_prefix }}-sg - register: sg -- name: verify setup security group - assert: - that: - - sg is successful - -- name: setup instance - cs_instance: - name: "{{ cs_resource_prefix }}-vm" - template: "{{ test_cs_instance_template }}" - service_offering: "{{ test_cs_instance_offering_1 }}" - affinity_group: "{{ cs_resource_prefix }}-ag" - security_group: "{{ cs_resource_prefix }}-sg" - ssh_key: "{{ cs_resource_prefix }}-sshkey" - tags: [] - register: instance -- name: verify create instance - assert: - that: - - instance is successful - -- name: test instance facts in check mode - cs_instance_facts: - name: "{{ cs_resource_prefix }}-vm" - register: instance_facts - check_mode: true -- name: verify test instance facts in check mode - assert: - that: - - instance_facts is successful - - instance_facts is not changed - - instance_facts.id == instance.id - - instance_facts.domain == instance.domain - - instance_facts.account == instance.account - - instance_facts.zone == instance.zone - - instance_facts.name == instance.name - - instance_facts.service_offering == instance.service_offering - - instance_facts.host != "" - - cloudstack_instance.id == instance.id - - cloudstack_instance.domain == instance.domain - - cloudstack_instance.account == instance.account - - cloudstack_instance.zone == instance.zone - - cloudstack_instance.name == instance.name - - cloudstack_instance.service_offering == instance.service_offering - -- name: test instance facts - cs_instance_facts: - name: "{{ cs_resource_prefix }}-vm" - register: instance_facts -- name: verify test instance facts - assert: - that: - - instance_facts is successful - - instance_facts is not changed - - instance_facts.id == instance.id - - instance_facts.domain == instance.domain - - instance_facts.account == instance.account - - instance_facts.zone == instance.zone - - instance_facts.name == instance.name - - instance_facts.service_offering == instance.service_offering - - instance_facts.host != "" - - cloudstack_instance.id == instance.id - - cloudstack_instance.domain == instance.domain - - cloudstack_instance.account == instance.account - - cloudstack_instance.zone == instance.zone - - cloudstack_instance.name == instance.name - - cloudstack_instance.service_offering == instance.service_offering diff --git a/test/integration/targets/cs_instance_facts/aliases b/test/integration/targets/cs_instance_info/aliases similarity index 100% rename from test/integration/targets/cs_instance_facts/aliases rename to test/integration/targets/cs_instance_info/aliases diff --git a/test/integration/targets/cs_instance_facts/defaults/main.yml b/test/integration/targets/cs_instance_info/defaults/main.yml similarity index 100% rename from test/integration/targets/cs_instance_facts/defaults/main.yml rename to test/integration/targets/cs_instance_info/defaults/main.yml diff --git a/test/integration/targets/cs_instance_facts/meta/main.yml b/test/integration/targets/cs_instance_info/meta/main.yml similarity index 100% rename from test/integration/targets/cs_instance_facts/meta/main.yml rename to test/integration/targets/cs_instance_info/meta/main.yml diff --git a/test/integration/targets/cs_instance_info/tasks/main.yml b/test/integration/targets/cs_instance_info/tasks/main.yml new file mode 100644 index 00000000000000..38e1a20ecdef3f --- /dev/null +++ b/test/integration/targets/cs_instance_info/tasks/main.yml @@ -0,0 +1,74 @@ +--- +- name: setup ssh key + cs_sshkeypair: name={{ cs_resource_prefix }}-sshkey + register: sshkey +- name: verify setup ssh key + assert: + that: + - sshkey is successful + +- name: setup affinity group + cs_affinitygroup: name={{ cs_resource_prefix }}-ag + register: ag +- name: verify setup affinity group + assert: + that: + - ag is successful + +- name: setup security group + cs_securitygroup: name={{ cs_resource_prefix }}-sg + register: sg +- name: verify setup security group + assert: + that: + - sg is successful + +- name: setup instance + cs_instance: + name: "{{ cs_resource_prefix }}-vm" + template: "{{ test_cs_instance_template }}" + service_offering: "{{ test_cs_instance_offering_1 }}" + affinity_group: "{{ cs_resource_prefix }}-ag" + security_group: "{{ cs_resource_prefix }}-sg" + ssh_key: "{{ cs_resource_prefix }}-sshkey" + tags: [] + register: instance +- name: verify create instance + assert: + that: + - instance is successful + +- name: test instance info in check mode + cs_instance_info: + name: "{{ cs_resource_prefix }}-vm" + register: instance_info + check_mode: true +- name: verify test instance info in check mode + assert: + that: + - instance_info is successful + - instance_info is not changed + - instance_info.id == instance.id + - instance_info.domain == instance.domain + - instance_info.account == instance.account + - instance_info.zone == instance.zone + - instance_info.name == instance.name + - instance_info.service_offering == instance.service_offering + - instance_info.host != "" + +- name: test instance info + cs_instance_info: + name: "{{ cs_resource_prefix }}-vm" + register: instance_info +- name: verify test instance info + assert: + that: + - instance_info is successful + - instance_info is not changed + - instance_info.id == instance.id + - instance_info.domain == instance.domain + - instance_info.account == instance.account + - instance_info.zone == instance.zone + - instance_info.name == instance.name + - instance_info.service_offering == instance.service_offering + - instance_info.host != "" diff --git a/test/integration/targets/cs_volume/tasks/extract_upload.yml b/test/integration/targets/cs_volume/tasks/extract_upload.yml index d80bb0257477d1..e4d22e4b113f68 100644 --- a/test/integration/targets/cs_volume/tasks/extract_upload.yml +++ b/test/integration/targets/cs_volume/tasks/extract_upload.yml @@ -52,11 +52,11 @@ - instance is successful - instance.state == 'Stopped' -- name: setup get instance facts - cs_instance_facts: +- name: setup get instance info + cs_instance_info: name: "{{ test_cs_instance_3 }}" register: instance -- name: verify setup get instance facts +- name: verify setup get instance info assert: that: - instance is successful diff --git a/test/integration/targets/cs_zone_facts/aliases b/test/integration/targets/cs_zone_info/aliases similarity index 100% rename from test/integration/targets/cs_zone_facts/aliases rename to test/integration/targets/cs_zone_info/aliases diff --git a/test/integration/targets/cs_zone_facts/meta/main.yml b/test/integration/targets/cs_zone_info/meta/main.yml similarity index 100% rename from test/integration/targets/cs_zone_facts/meta/main.yml rename to test/integration/targets/cs_zone_info/meta/main.yml diff --git a/test/integration/targets/cs_zone_facts/tasks/main.yml b/test/integration/targets/cs_zone_info/tasks/main.yml similarity index 51% rename from test/integration/targets/cs_zone_facts/tasks/main.yml rename to test/integration/targets/cs_zone_info/tasks/main.yml index d275101724df5a..ac387b2a19438a 100644 --- a/test/integration/targets/cs_zone_facts/tasks/main.yml +++ b/test/integration/targets/cs_zone_info/tasks/main.yml @@ -11,12 +11,12 @@ that: - zone is successful -- name: get facts from zone in check mode - cs_zone_facts: +- name: get info from zone in check mode + cs_zone_info: name: "{{ cs_resource_prefix }}-zone" register: zone check_mode: yes -- name: verify get facts from zone in check mode +- name: verify get info from zone in check mode assert: that: - zone is successful @@ -31,23 +31,12 @@ - zone.securitygroups_enabled == true - zone.dhcp_provider == "VirtualRouter" - zone.local_storage_enabled == false - # Ansible Facts - - cloudstack_zone.dns1 == "8.8.8.8" - - cloudstack_zone.dns2 == "8.8.4.4" - - cloudstack_zone.internal_dns1 == "8.8.8.8" - - cloudstack_zone.internal_dns2 == "8.8.4.4" - - cloudstack_zone.local_storage_enabled == false - - cloudstack_zone.network_type == "Basic" - - cloudstack_zone.zone_token != "" - - cloudstack_zone.securitygroups_enabled == true - - cloudstack_zone.dhcp_provider == "VirtualRouter" - - cloudstack_zone.local_storage_enabled == false -- name: get facts from zone - cs_zone_facts: +- name: get info from zone + cs_zone_info: name: "{{ cs_resource_prefix }}-zone" register: zone -- name: verify get facts from zone +- name: verify get info from zone assert: that: - zone is successful @@ -62,14 +51,3 @@ - zone.securitygroups_enabled == true - zone.dhcp_provider == "VirtualRouter" - zone.local_storage_enabled == false - # Ansible Facts - - cloudstack_zone.dns1 == "8.8.8.8" - - cloudstack_zone.dns2 == "8.8.4.4" - - cloudstack_zone.internal_dns1 == "8.8.8.8" - - cloudstack_zone.internal_dns2 == "8.8.4.4" - - cloudstack_zone.local_storage_enabled == false - - cloudstack_zone.network_type == "Basic" - - cloudstack_zone.zone_token != "" - - cloudstack_zone.securitygroups_enabled == true - - cloudstack_zone.dhcp_provider == "VirtualRouter" - - cloudstack_zone.local_storage_enabled == false diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index 2137d989aea4ba..c1c2fadcc88f94 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -1366,9 +1366,9 @@ lib/ansible/modules/cloud/cloudstack/cs_vpn_gateway.py future-import-boilerplate lib/ansible/modules/cloud/cloudstack/cs_vpn_gateway.py metaclass-boilerplate lib/ansible/modules/cloud/cloudstack/cs_zone.py future-import-boilerplate lib/ansible/modules/cloud/cloudstack/cs_zone.py metaclass-boilerplate -lib/ansible/modules/cloud/cloudstack/cs_zone_facts.py future-import-boilerplate -lib/ansible/modules/cloud/cloudstack/cs_zone_facts.py metaclass-boilerplate -lib/ansible/modules/cloud/cloudstack/cs_zone_facts.py validate-modules:doc-missing-type +lib/ansible/modules/cloud/cloudstack/cs_zone_info.py future-import-boilerplate +lib/ansible/modules/cloud/cloudstack/cs_zone_info.py metaclass-boilerplate +lib/ansible/modules/cloud/cloudstack/cs_zone_info.py validate-modules:doc-missing-type lib/ansible/modules/cloud/digital_ocean/_digital_ocean.py validate-modules:undocumented-parameter lib/ansible/modules/cloud/digital_ocean/_digital_ocean.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/digital_ocean/_digital_ocean.py validate-modules:doc-missing-type From 5d53fbb833efeff0c13d2758befbd4944b9e570c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Aug 2019 07:26:43 +0200 Subject: [PATCH 02/17] Add changelog. --- changelogs/fragments/61090-cloudstack-facts-info.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/fragments/61090-cloudstack-facts-info.yaml diff --git a/changelogs/fragments/61090-cloudstack-facts-info.yaml b/changelogs/fragments/61090-cloudstack-facts-info.yaml new file mode 100644 index 00000000000000..d5eea3723fc802 --- /dev/null +++ b/changelogs/fragments/61090-cloudstack-facts-info.yaml @@ -0,0 +1,5 @@ +minor_changes: +- The ``cs_instance_facts`` module has been renamed to ``cs_instance_info``. + When called with the new name, the module no longer returns ``ansible_facts``. +- The ``cs_zone_facts`` module has been renamed to ``cs_zone_info``. + When called with the new name, the module no longer returns ``ansible_facts``. From c4c0af9d20d68587c1e3a86b1046876412075fef Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Aug 2019 07:52:53 +0200 Subject: [PATCH 03/17] Fix errors due to overloaded get_result having different parameter names. --- lib/ansible/modules/cloud/cloudstack/cs_instance_info.py | 4 +--- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index 6959a4b0d7c7fd..e45bf0df6ff23f 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -385,9 +385,7 @@ def main(): ) module.exit_json(**cs_instance_info) else: - cs_instance_info = acs_instance_info.get_result( - resource=acs_instance_info.run() - ) + cs_instance_info = acs_instance_info.get_result(acs_instance_info.run()) module.exit_json(**cs_instance_info) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 5e98e84a0f1b1b..165d676747136a 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -205,9 +205,7 @@ def main(): ) module.exit_json(**result) else: - result = acs_zone_info.get_result( - resource=acs_zone_info.get_zone() - ) + result = acs_zone_info.get_result(acs_zone_info.get_zone()) module.exit_json(**result) From f2b57ea170ab9f40699ca4c39cbf57cb4c1f4f70 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Aug 2019 22:04:30 +0200 Subject: [PATCH 04/17] Fix examples. --- lib/ansible/modules/cloud/cloudstack/cs_instance_info.py | 6 +++--- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index e45bf0df6ff23f..3ef524eae68509 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -46,7 +46,7 @@ ''' EXAMPLES = ''' -- name: gather instance info +- name: gather instance information cs_instance_info: name: web-vm-1 delegate_to: localhost @@ -56,11 +56,11 @@ debug: var: vm -# When the module is called as cs_instance_info, return values are also +# When the module is called as cs_instance_facts, return values are also # published in ansible_facts['cloudstack_instance'] and can be used as # follows. Note that this is deprecated and will stop working in # Ansible 2.13. -- name: gather instance info +- name: gather instance information cs_instance_facts: name: web-vm-1 delegate_to: localhost diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 165d676747136a..d497731172da6a 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -32,7 +32,7 @@ ''' EXAMPLES = ''' -- name: Gather info from a zone +- name: Gather information from a zone cs_zone_info: name: ch-gva-1 register: zone @@ -42,11 +42,11 @@ debug: var: zone -# When the module is called as cs_zone_info, return values are also +# When the module is called as cs_zone_facts, return values are also # published in ansible_facts['cloudstack_zone'] and can be used as # follows. Note that this is deprecated and will stop working in # Ansible 2.13. -- name: Gather info from a zone +- name: Gather information from a zone cs_zone_facts: name: ch-gva-1 delegate_to: localhost From 5107cc625bfb30c4a5e0752a9148b991bbd6ad38 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 28 Aug 2019 20:49:23 +0200 Subject: [PATCH 05/17] Change debug tasks. --- lib/ansible/modules/cloud/cloudstack/cs_instance_info.py | 4 ++-- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index 3ef524eae68509..5a9df172cc1fb3 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -54,7 +54,7 @@ - name: Show the returned results of the registered variable debug: - var: vm + msg: "{{ vm }}" # When the module is called as cs_instance_facts, return values are also # published in ansible_facts['cloudstack_instance'] and can be used as @@ -67,7 +67,7 @@ - name: Show the facts by the ansible_facts key cloudstack_instance debug: - var: cloudstack_instance + msg: "{{ cloudstack_instance }}" ''' RETURN = ''' diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index d497731172da6a..4e90804f98301b 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -40,7 +40,7 @@ - name: Show the returned results of the registered variable debug: - var: zone + msg: "{{ zone }}" # When the module is called as cs_zone_facts, return values are also # published in ansible_facts['cloudstack_zone'] and can be used as @@ -53,7 +53,7 @@ - name: Show the facts by the ansible_facts key cloudstack_zone debug: - var: cloudstack_zone + msg: "{{ cloudstack_zone }}" ''' RETURN = ''' From a3d0f97fc63e9cdd03b6583bd4ab5869d2d86b26 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 28 Aug 2019 20:50:51 +0200 Subject: [PATCH 06/17] Remove unneeded code. --- lib/ansible/modules/cloud/cloudstack/cs_instance_info.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index 5a9df172cc1fb3..1b039b624eafac 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -288,9 +288,6 @@ def __init__(self, module): 'keypair': 'ssh_key', 'hostname': 'host', } - self.info = { - 'cloudstack_instance': None, - } def get_instance(self): instance = self.instance From 395a1a3e14cec8f401286181b2fc30364c5f350d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 12:31:42 +0200 Subject: [PATCH 07/17] Change from rename -> deprecate+new module. --- .../61090-cloudstack-facts-info.yaml | 6 +- .../rst/porting_guides/porting_guide_2.9.rst | 10 +- .../cloud/cloudstack/_cs_instance_facts.py | 375 +++++++++++++++++- .../cloud/cloudstack/_cs_zone_facts.py | 198 ++++++++- .../cloud/cloudstack/cs_instance_info.py | 33 +- .../modules/cloud/cloudstack/cs_zone_info.py | 34 +- 6 files changed, 583 insertions(+), 73 deletions(-) mode change 120000 => 100644 lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py mode change 120000 => 100644 lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py diff --git a/changelogs/fragments/61090-cloudstack-facts-info.yaml b/changelogs/fragments/61090-cloudstack-facts-info.yaml index d5eea3723fc802..2c5f3acae3cdb4 100644 --- a/changelogs/fragments/61090-cloudstack-facts-info.yaml +++ b/changelogs/fragments/61090-cloudstack-facts-info.yaml @@ -1,5 +1,3 @@ minor_changes: -- The ``cs_instance_facts`` module has been renamed to ``cs_instance_info``. - When called with the new name, the module no longer returns ``ansible_facts``. -- The ``cs_zone_facts`` module has been renamed to ``cs_zone_info``. - When called with the new name, the module no longer returns ``ansible_facts``. +- The ``cs_instance_facts`` module has been deprecated. Use ``cs_instance_info`` instead. +- The ``cs_zone_facts`` module has been deprecated. Use ``cs_zone_info`` instead. diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst index 2824a6d30def2d..da602ec92a3755 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.9.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.9.rst @@ -117,6 +117,10 @@ Deprecation notices The following modules will be removed in Ansible 2.13. Please update update your playbooks accordingly. +* cs_instance_facts use :ref:`cs_instance_info ` instead. + +* cs_zone_facts use :ref:`cs_zone_info ` instead. + * digital_ocean_sshkey_facts use :ref:`digital_ocean_sshkey_info ` instead. * junos_interface use :ref:`junos_interfaces ` instead. @@ -353,12 +357,6 @@ be removed in Ansible 2.13. Please update update your playbooks accordingly. When called with the new name, the module no longer returns ``ansible_facts``. To access return values, :ref:`register a variable `. * The ``cloudwatchlogs_log_group_facts`` module was renamed to :ref:`cloudwatchlogs_log_group_info `. -* The ``cs_instance_facts`` module was renamed to :ref:`cs_instance_info `. - When called with the new name, the module no longer returns ``ansible_facts``. - To access return values, :ref:`register a variable `. -* The ``cs_zone_facts`` module was renamed to :ref:`cs_zone_info `. - When called with the new name, the module no longer returns ``ansible_facts``. - To access return values, :ref:`register a variable `. * The ``digital_ocean_account_facts`` module was renamed to :ref:`digital_ocean_account_info `. * The ``digital_ocean_certificate_facts`` module was renamed to :ref:`digital_ocean_certificate_info `. * The ``digital_ocean_domain_facts`` module was renamed to :ref:`digital_ocean_domain_info `. diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py deleted file mode 120000 index b47ddbd4619b2c..00000000000000 --- a/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py +++ /dev/null @@ -1 +0,0 @@ -cs_instance_info.py \ No newline at end of file diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py new file mode 100644 index 00000000000000..9e02aeb1d538aa --- /dev/null +++ b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py @@ -0,0 +1,374 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# (c) 2016, René Moser +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['deprecated'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: cs_instance_facts +short_description: Gathering facts from the API of instances from Apache CloudStack based clouds. +description: + - Gathering facts from the API of an instance. +deprecated: + removed_in: "2.12" + why: Transformed into an info module. + alternative: Use M(cs_instance_info) instead. +version_added: '2.1' +author: René Moser (@resmo) +options: + name: + description: + - Name or display name of the instance. + type: str + required: true + domain: + description: + - Domain the instance is related to. + type: str + account: + description: + - Account the instance is related to. + type: str + project: + description: + - Project the instance is related to. + type: str +extends_documentation_fragment: cloudstack +''' + +EXAMPLES = ''' +- name: gather instance facts + cs_instance_facts: + name: web-vm-1 + delegate_to: localhost + register: vm + +- debug: + var: cloudstack_instance + +- debug: + var: vm +''' + +RETURN = ''' +--- +id: + description: UUID of the instance. + returned: success + type: str + sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 +name: + description: Name of the instance. + returned: success + type: str + sample: web-01 +display_name: + description: Display name of the instance. + returned: success + type: str + sample: web-01 +group: + description: Group name of the instance is related. + returned: success + type: str + sample: web +created: + description: Date of the instance was created. + returned: success + type: str + sample: 2014-12-01T14:57:57+0100 +password_enabled: + description: True if password setting is enabled. + returned: success + type: bool + sample: true +password: + description: The password of the instance if exists. + returned: success + type: str + sample: Ge2oe7Do +ssh_key: + description: Name of SSH key deployed to instance. + returned: success + type: str + sample: key@work +domain: + description: Domain the instance is related to. + returned: success + type: str + sample: example domain +account: + description: Account the instance is related to. + returned: success + type: str + sample: example account +project: + description: Name of project the instance is related to. + returned: success + type: str + sample: Production +default_ip: + description: Default IP address of the instance. + returned: success + type: str + sample: 10.23.37.42 +public_ip: + description: Public IP address with instance via static NAT rule. + returned: success + type: str + sample: 1.2.3.4 +iso: + description: Name of ISO the instance was deployed with. + returned: success + type: str + sample: Debian-8-64bit +template: + description: Name of template the instance was deployed with. + returned: success + type: str + sample: Debian-8-64bit +service_offering: + description: Name of the service offering the instance has. + returned: success + type: str + sample: 2cpu_2gb +zone: + description: Name of zone the instance is in. + returned: success + type: str + sample: ch-gva-2 +state: + description: State of the instance. + returned: success + type: str + sample: Running +security_groups: + description: Security groups the instance is in. + returned: success + type: list + sample: '[ "default" ]' +affinity_groups: + description: Affinity groups the instance is in. + returned: success + type: list + sample: '[ "webservers" ]' +tags: + description: List of resource tags associated with the instance. + returned: success + type: list + sample: '[ { "key": "foo", "value": "bar" } ]' +hypervisor: + description: Hypervisor related to this instance. + returned: success + type: str + sample: KVM +host: + description: Host the instance is running on. + returned: success and instance is running + type: str + sample: host01.example.com + version_added: '2.6' +instance_name: + description: Internal name of the instance (ROOT admin only). + returned: success + type: str + sample: i-44-3992-VM +volumes: + description: List of dictionaries of the volumes attached to the instance. + returned: success + type: list + sample: '[ { name: "ROOT-1369", type: "ROOT", size: 10737418240 }, { name: "data01, type: "DATADISK", size: 10737418240 } ]' +nic: + description: List of dictionaries of the instance nics. + returned: success + type: complex + version_added: '2.8' + contains: + broadcasturi: + description: The broadcast uri of the nic. + returned: success + type: str + sample: vlan://2250 + gateway: + description: The gateway of the nic. + returned: success + type: str + sample: 10.1.2.1 + id: + description: The ID of the nic. + returned: success + type: str + sample: 5dc74fa3-2ec3-48a0-9e0d-6f43365336a9 + ipaddress: + description: The ip address of the nic. + returned: success + type: str + sample: 10.1.2.3 + isdefault: + description: True if nic is default, false otherwise. + returned: success + type: bool + sample: true + isolationuri: + description: The isolation uri of the nic. + returned: success + type: str + sample: vlan://2250 + macaddress: + description: The mac address of the nic. + returned: success + type: str + sample: 06:a2:03:00:08:12 + netmask: + description: The netmask of the nic. + returned: success + type: str + sample: 255.255.255.0 + networkid: + description: The ID of the corresponding network. + returned: success + type: str + sample: 432ce27b-c2bb-4e12-a88c-a919cd3a3017 + networkname: + description: The name of the corresponding network. + returned: success + type: str + sample: network1 + traffictype: + description: The traffic type of the nic. + returned: success + type: str + sample: Guest + type: + description: The type of the network. + returned: success + type: str + sample: Shared +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.cloudstack import AnsibleCloudStack, cs_argument_spec + + +class AnsibleCloudStackInstanceFacts(AnsibleCloudStack): + + def __init__(self, module): + super(AnsibleCloudStackInstanceFacts, self).__init__(module) + self.instance = None + self.returns = { + 'group': 'group', + 'hypervisor': 'hypervisor', + 'instancename': 'instance_name', + 'publicip': 'public_ip', + 'passwordenabled': 'password_enabled', + 'password': 'password', + 'serviceofferingname': 'service_offering', + 'isoname': 'iso', + 'templatename': 'template', + 'keypair': 'ssh_key', + 'hostname': 'host', + } + self.facts = { + 'cloudstack_instance': None, + } + + def get_instance(self): + instance = self.instance + if not instance: + instance_name = self.module.params.get('name') + + args = { + 'account': self.get_account(key='name'), + 'domainid': self.get_domain(key='id'), + 'projectid': self.get_project(key='id'), + 'fetch_list': True, + } + # Do not pass zoneid, as the instance name must be unique across zones. + instances = self.query_api('listVirtualMachines', **args) + if instances: + for v in instances: + if instance_name.lower() in [v['name'].lower(), v['displayname'].lower(), v['id']]: + self.instance = v + break + return self.instance + + def get_volumes(self, instance): + volume_details = [] + if instance: + args = { + 'account': self.get_account(key='name'), + 'domainid': self.get_domain(key='id'), + 'projectid': self.get_project(key='id'), + 'virtualmachineid': instance['id'], + 'fetch_list': True, + } + + volumes = self.query_api('listVolumes', **args) + if volumes: + for vol in volumes: + volume_details.append({'size': vol['size'], 'type': vol['type'], 'name': vol['name']}) + return volume_details + + def run(self): + instance = self.get_instance() + if not instance: + self.module.fail_json(msg="Instance not found: %s" % self.module.params.get('name')) + return instance + + def get_result(self, instance): + super(AnsibleCloudStackInstanceFacts, self).get_result(instance) + if instance: + if 'securitygroup' in instance: + security_groups = [] + for securitygroup in instance['securitygroup']: + security_groups.append(securitygroup['name']) + self.result['security_groups'] = security_groups + if 'affinitygroup' in instance: + affinity_groups = [] + for affinitygroup in instance['affinitygroup']: + affinity_groups.append(affinitygroup['name']) + self.result['affinity_groups'] = affinity_groups + if 'nic' in instance: + for nic in instance['nic']: + if nic['isdefault'] and 'ipaddress' in nic: + self.result['default_ip'] = nic['ipaddress'] + self.result['nic'] = instance['nic'] + volumes = self.get_volumes(instance) + if volumes: + self.result['volumes'] = volumes + return self.result + + +def main(): + argument_spec = cs_argument_spec() + argument_spec.update(dict( + name=dict(required=True), + domain=dict(), + account=dict(), + project=dict(), + )) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + acs_instance_facts = AnsibleCloudStackInstanceFacts(module=module) + cs_instance_facts = acs_instance_facts.get_result_and_facts( + facts_name='cloudstack_instance', + resource=acs_instance_facts.run() + ) + module.exit_json(**cs_instance_facts) + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py deleted file mode 120000 index d041284b8be755..00000000000000 --- a/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py +++ /dev/null @@ -1 +0,0 @@ -cs_zone_info.py \ No newline at end of file diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py new file mode 100644 index 00000000000000..393d0432b5d8e0 --- /dev/null +++ b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py @@ -0,0 +1,197 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016, René Moser +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['deprecated'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: cs_zone_facts +short_description: Gathering facts of zones from Apache CloudStack based clouds. +description: + - Gathering facts from the API of a zone. + - Sets Ansible facts accessable by the key C(cloudstack_zone) and since version 2.6 also returns results. +deprecated: + removed_in: "2.12" + why: Transformed into an info module. + alternative: Use M(cs_zone_info) instead. +version_added: '2.1' +author: René Moser (@resmo) +options: + name: + description: + - Name of the zone. + type: str + required: true + aliases: [ zone ] +extends_documentation_fragment: cloudstack +''' + +EXAMPLES = ''' +- name: Gather facts from a zone + cs_zone_facts: + name: ch-gva-1 + register: zone + delegate_to: localhost + +- name: Show the returned results of the registered variable + debug: + var: zone + +- name: Show the facts by the ansible_facts key cloudstack_zone + debug: + var: cloudstack_zone +''' + +RETURN = ''' +--- +id: + description: UUID of the zone. + returned: success + type: str + sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 +name: + description: Name of the zone. + returned: success + type: str + sample: zone01 +dns1: + description: First DNS for the zone. + returned: success + type: str + sample: 8.8.8.8 +dns2: + description: Second DNS for the zone. + returned: success + type: str + sample: 8.8.4.4 +internal_dns1: + description: First internal DNS for the zone. + returned: success + type: str + sample: 8.8.8.8 +internal_dns2: + description: Second internal DNS for the zone. + returned: success + type: str + sample: 8.8.4.4 +dns1_ipv6: + description: First IPv6 DNS for the zone. + returned: success + type: str + sample: "2001:4860:4860::8888" +dns2_ipv6: + description: Second IPv6 DNS for the zone. + returned: success + type: str + sample: "2001:4860:4860::8844" +allocation_state: + description: State of the zone. + returned: success + type: str + sample: Enabled +domain: + description: Domain the zone is related to. + returned: success + type: str + sample: ROOT +network_domain: + description: Network domain for the zone. + returned: success + type: str + sample: example.com +network_type: + description: Network type for the zone. + returned: success + type: str + sample: basic +local_storage_enabled: + description: Local storage offering enabled. + returned: success + type: bool + sample: false +securitygroups_enabled: + description: Security groups support is enabled. + returned: success + type: bool + sample: false +guest_cidr_address: + description: Guest CIDR address for the zone + returned: success + type: str + sample: 10.1.1.0/24 +dhcp_provider: + description: DHCP provider for the zone + returned: success + type: str + sample: VirtualRouter +zone_token: + description: Zone token + returned: success + type: str + sample: ccb0a60c-79c8-3230-ab8b-8bdbe8c45bb7 +tags: + description: List of resource tags associated with the zone. + returned: success + type: dict + sample: [ { "key": "foo", "value": "bar" } ] +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.cloudstack import ( + AnsibleCloudStack, + cs_argument_spec, +) + + +class AnsibleCloudStackZoneFacts(AnsibleCloudStack): + + def __init__(self, module): + super(AnsibleCloudStackZoneFacts, self).__init__(module) + self.returns = { + 'dns1': 'dns1', + 'dns2': 'dns2', + 'internaldns1': 'internal_dns1', + 'internaldns2': 'internal_dns2', + 'ipv6dns1': 'dns1_ipv6', + 'ipv6dns2': 'dns2_ipv6', + 'domain': 'network_domain', + 'networktype': 'network_type', + 'securitygroupsenabled': 'securitygroups_enabled', + 'localstorageenabled': 'local_storage_enabled', + 'guestcidraddress': 'guest_cidr_address', + 'dhcpprovider': 'dhcp_provider', + 'allocationstate': 'allocation_state', + 'zonetoken': 'zone_token', + } + + def get_zone(self): + return super(AnsibleCloudStackZoneFacts, self).get_zone() + + +def main(): + argument_spec = cs_argument_spec() + argument_spec.update(dict( + zone=dict(required=True, aliases=['name']), + )) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + acs_zone_facts = AnsibleCloudStackZoneFacts(module=module) + result = acs_zone_facts.get_result_and_facts( + facts_name='cloudstack_zone', + resource=acs_zone_facts.get_zone() + ) + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index 1b039b624eafac..cdf768de0c9c8e 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -19,10 +19,7 @@ short_description: Gathering information from the API of instances from Apache CloudStack based clouds. description: - Gathering information from the API of an instance. - - This module was called C(cs_instance_facts) before Ansible 2.9, returning C(ansible_facts) with key C(cloudstack_instance). - Since Ansible 2.6, the module also returned registerable results. - Note that the M(cs_instance_info) module no longer returns C(ansible_facts)! -version_added: '2.1' +version_added: '2.9' author: René Moser (@resmo) options: name: @@ -55,19 +52,6 @@ - name: Show the returned results of the registered variable debug: msg: "{{ vm }}" - -# When the module is called as cs_instance_facts, return values are also -# published in ansible_facts['cloudstack_instance'] and can be used as -# follows. Note that this is deprecated and will stop working in -# Ansible 2.13. -- name: gather instance information - cs_instance_facts: - name: web-vm-1 - delegate_to: localhost - -- name: Show the facts by the ansible_facts key cloudstack_instance - debug: - msg: "{{ cloudstack_instance }}" ''' RETURN = ''' @@ -369,21 +353,10 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, ) - is_old_facts = module._name == 'cs_instance_facts' - if is_old_facts: - module.deprecate("The 'cs_instance_facts' module has been renamed to 'cs_instance_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') acs_instance_info = AnsibleCloudStackInstanceInfo(module=module) - if is_old_facts: - cs_instance_info = acs_instance_info.get_result_and_facts( - facts_name='cloudstack_instance', - resource=acs_instance_info.run() - ) - module.exit_json(**cs_instance_info) - else: - cs_instance_info = acs_instance_info.get_result(acs_instance_info.run()) - module.exit_json(**cs_instance_info) + cs_instance_info = acs_instance_info.get_result(acs_instance_info.run()) + module.exit_json(**cs_instance_info) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 4e90804f98301b..6dfb5f0a1df588 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -15,11 +15,7 @@ short_description: Gathering information about zones from Apache CloudStack based clouds. description: - Gathering information from the API of a zone. - - Sets Ansible facts accessable by the key C(cloudstack_zone) and since version 2.6 also returns results. - - This module was called C(cs_zone_facts) before Ansible 2.9, returning C(ansible_facts) with key C(cloudstack_zone). - Since Ansible 2.6, the module also returned registerable results. - Note that the M(cs_zone_info) module no longer returns C(ansible_facts)! -version_added: '2.1' +version_added: '2.9' author: René Moser (@resmo) options: name: @@ -41,19 +37,6 @@ - name: Show the returned results of the registered variable debug: msg: "{{ zone }}" - -# When the module is called as cs_zone_facts, return values are also -# published in ansible_facts['cloudstack_zone'] and can be used as -# follows. Note that this is deprecated and will stop working in -# Ansible 2.13. -- name: Gather information from a zone - cs_zone_facts: - name: ch-gva-1 - delegate_to: localhost - -- name: Show the facts by the ansible_facts key cloudstack_zone - debug: - msg: "{{ cloudstack_zone }}" ''' RETURN = ''' @@ -192,21 +175,10 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, ) - is_old_facts = module._name == 'cs_zone_facts' - if is_old_facts: - module.deprecate("The 'cs_zone_facts' module has been renamed to 'cs_zone_info', " - "and the renamed one no longer returns ansible_facts", version='2.13') acs_zone_info = AnsibleCloudStackZoneInfo(module=module) - if is_old_facts: - result = acs_zone_info.get_result_and_facts( - facts_name='cloudstack_zone', - resource=acs_zone_info.get_zone() - ) - module.exit_json(**result) - else: - result = acs_zone_info.get_result(acs_zone_info.get_zone()) - module.exit_json(**result) + result = acs_zone_info.get_result(acs_zone_info.get_zone()) + module.exit_json(**result) if __name__ == '__main__': From 544ca0522cf3adc7ec58462e989ad94ce6b1293f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 12:50:31 +0200 Subject: [PATCH 08/17] Make cs_zone_info return a list. --- lib/ansible/module_utils/cloudstack.py | 15 +- .../modules/cloud/cloudstack/cs_zone_info.py | 199 +++++++++--------- .../targets/cs_instance/tasks/host.yml | 2 +- .../targets/cs_zone_info/tasks/main.yml | 50 +++-- 4 files changed, 146 insertions(+), 120 deletions(-) diff --git a/lib/ansible/module_utils/cloudstack.py b/lib/ansible/module_utils/cloudstack.py index 61c148938e47b7..85a53b6b6e7594 100644 --- a/lib/ansible/module_utils/cloudstack.py +++ b/lib/ansible/module_utils/cloudstack.py @@ -628,22 +628,27 @@ def poll_job(self, job=None, key=None): time.sleep(2) return job - def get_result(self, resource): + def update_result(self, resource, result=None): + if result is None: + result = dict() if resource: returns = self.common_returns.copy() returns.update(self.returns) for search_key, return_key in returns.items(): if search_key in resource: - self.result[return_key] = resource[search_key] + result[return_key] = resource[search_key] # Bad bad API does not always return int when it should. for search_key, return_key in self.returns_to_int.items(): if search_key in resource: - self.result[return_key] = int(resource[search_key]) + result[return_key] = int(resource[search_key]) if 'tags' in resource: - self.result['tags'] = resource['tags'] - return self.result + result['tags'] = resource['tags'] + return result + + def get_result(self, resource): + return self.update_result(resource, self.result) def get_result_and_facts(self, facts_name, resource): result = self.get_result(resource) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 6dfb5f0a1df588..0c4f9d950077cd 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -21,8 +21,9 @@ name: description: - Name of the zone. + - If not specified, all zones are returned type: str - required: true + required: false aliases: [ zone ] extends_documentation_fragment: cloudstack ''' @@ -41,96 +42,100 @@ RETURN = ''' --- -id: - description: UUID of the zone. - returned: success - type: str - sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 -name: - description: Name of the zone. - returned: success - type: str - sample: zone01 -dns1: - description: First DNS for the zone. - returned: success - type: str - sample: 8.8.8.8 -dns2: - description: Second DNS for the zone. - returned: success - type: str - sample: 8.8.4.4 -internal_dns1: - description: First internal DNS for the zone. - returned: success - type: str - sample: 8.8.8.8 -internal_dns2: - description: Second internal DNS for the zone. - returned: success - type: str - sample: 8.8.4.4 -dns1_ipv6: - description: First IPv6 DNS for the zone. - returned: success - type: str - sample: "2001:4860:4860::8888" -dns2_ipv6: - description: Second IPv6 DNS for the zone. - returned: success - type: str - sample: "2001:4860:4860::8844" -allocation_state: - description: State of the zone. - returned: success - type: str - sample: Enabled -domain: - description: Domain the zone is related to. - returned: success - type: str - sample: ROOT -network_domain: - description: Network domain for the zone. - returned: success - type: str - sample: example.com -network_type: - description: Network type for the zone. - returned: success - type: str - sample: basic -local_storage_enabled: - description: Local storage offering enabled. - returned: success - type: bool - sample: false -securitygroups_enabled: - description: Security groups support is enabled. - returned: success - type: bool - sample: false -guest_cidr_address: - description: Guest CIDR address for the zone - returned: success - type: str - sample: 10.1.1.0/24 -dhcp_provider: - description: DHCP provider for the zone - returned: success - type: str - sample: VirtualRouter -zone_token: - description: Zone token - returned: success - type: str - sample: ccb0a60c-79c8-3230-ab8b-8bdbe8c45bb7 -tags: - description: List of resource tags associated with the zone. - returned: success - type: dict - sample: [ { "key": "foo", "value": "bar" } ] +zones: + description: A list of matching zones. + type: list + suboptions: + id: + description: UUID of the zone. + returned: success + type: str + sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 + name: + description: Name of the zone. + returned: success + type: str + sample: zone01 + dns1: + description: First DNS for the zone. + returned: success + type: str + sample: 8.8.8.8 + dns2: + description: Second DNS for the zone. + returned: success + type: str + sample: 8.8.4.4 + internal_dns1: + description: First internal DNS for the zone. + returned: success + type: str + sample: 8.8.8.8 + internal_dns2: + description: Second internal DNS for the zone. + returned: success + type: str + sample: 8.8.4.4 + dns1_ipv6: + description: First IPv6 DNS for the zone. + returned: success + type: str + sample: "2001:4860:4860::8888" + dns2_ipv6: + description: Second IPv6 DNS for the zone. + returned: success + type: str + sample: "2001:4860:4860::8844" + allocation_state: + description: State of the zone. + returned: success + type: str + sample: Enabled + domain: + description: Domain the zone is related to. + returned: success + type: str + sample: ROOT + network_domain: + description: Network domain for the zone. + returned: success + type: str + sample: example.com + network_type: + description: Network type for the zone. + returned: success + type: str + sample: basic + local_storage_enabled: + description: Local storage offering enabled. + returned: success + type: bool + sample: false + securitygroups_enabled: + description: Security groups support is enabled. + returned: success + type: bool + sample: false + guest_cidr_address: + description: Guest CIDR address for the zone + returned: success + type: str + sample: 10.1.1.0/24 + dhcp_provider: + description: DHCP provider for the zone + returned: success + type: str + sample: VirtualRouter + zone_token: + description: Zone token + returned: success + type: str + sample: ccb0a60c-79c8-3230-ab8b-8bdbe8c45bb7 + tags: + description: List of resource tags associated with the zone. + returned: success + type: dict + sample: [ { "key": "foo", "value": "bar" } ] ''' from ansible.module_utils.basic import AnsibleModule @@ -162,13 +167,19 @@ def __init__(self, module): } def get_zone(self): - return super(AnsibleCloudStackZoneInfo, self).get_zone() + if self.module.params['zone']: + zones = [super(AnsibleCloudStackZoneInfo, self).get_zone()] + else: + zones = self.query_api('listZones') + return { + 'zones': [self.update_result(resource) for resource in zones] + } def main(): argument_spec = cs_argument_spec() argument_spec.update(dict( - zone=dict(required=True, aliases=['name']), + zone=dict(required=False, aliases=['name']), )) module = AnsibleModule( @@ -177,7 +188,7 @@ def main(): ) acs_zone_info = AnsibleCloudStackZoneInfo(module=module) - result = acs_zone_info.get_result(acs_zone_info.get_zone()) + result = acs_zone_info.get_zone() module.exit_json(**result) diff --git a/test/integration/targets/cs_instance/tasks/host.yml b/test/integration/targets/cs_instance/tasks/host.yml index 9bc61401d5ae54..051448f264a802 100644 --- a/test/integration/targets/cs_instance/tasks/host.yml +++ b/test/integration/targets/cs_instance/tasks/host.yml @@ -18,7 +18,7 @@ register: zone_info - name: setup find the host name - shell: cs listHosts type=routing zoneid="{{ zone_info.id }}" + shell: cs listHosts type=routing zoneid="{{ zone_info.zones[0].id }}" args: chdir: "{{ playbook_dir }}" register: host diff --git a/test/integration/targets/cs_zone_info/tasks/main.yml b/test/integration/targets/cs_zone_info/tasks/main.yml index ac387b2a19438a..538d2528b767d9 100644 --- a/test/integration/targets/cs_zone_info/tasks/main.yml +++ b/test/integration/targets/cs_zone_info/tasks/main.yml @@ -21,16 +21,16 @@ that: - zone is successful - zone is not changed - - zone.dns1 == "8.8.8.8" - - zone.dns2 == "8.8.4.4" - - zone.internal_dns1 == "8.8.8.8" - - zone.internal_dns2 == "8.8.4.4" - - zone.local_storage_enabled == false - - zone.network_type == "Basic" - - zone.zone_token != "" - - zone.securitygroups_enabled == true - - zone.dhcp_provider == "VirtualRouter" - - zone.local_storage_enabled == false + - zone.zones[0].dns1 == "8.8.8.8" + - zone.zones[0].dns2 == "8.8.4.4" + - zone.zones[0].internal_dns1 == "8.8.8.8" + - zone.zones[0].internal_dns2 == "8.8.4.4" + - zone.zones[0].local_storage_enabled == false + - zone.zones[0].network_type == "Basic" + - zone.zones[0].zone_token != "" + - zone.zones[0].securitygroups_enabled == true + - zone.zones[0].dhcp_provider == "VirtualRouter" + - zone.zones[0].local_storage_enabled == false - name: get info from zone cs_zone_info: @@ -41,13 +41,23 @@ that: - zone is successful - zone is not changed - - zone.dns1 == "8.8.8.8" - - zone.dns2 == "8.8.4.4" - - zone.internal_dns1 == "8.8.8.8" - - zone.internal_dns2 == "8.8.4.4" - - zone.local_storage_enabled == false - - zone.network_type == "Basic" - - zone.zone_token != "" - - zone.securitygroups_enabled == true - - zone.dhcp_provider == "VirtualRouter" - - zone.local_storage_enabled == false + - zone.zones[0].dns1 == "8.8.8.8" + - zone.zones[0].dns2 == "8.8.4.4" + - zone.zones[0].internal_dns1 == "8.8.8.8" + - zone.zones[0].internal_dns2 == "8.8.4.4" + - zone.zones[0].local_storage_enabled == false + - zone.zones[0].network_type == "Basic" + - zone.zones[0].zone_token != "" + - zone.zones[0].securitygroups_enabled == true + - zone.zones[0].dhcp_provider == "VirtualRouter" + - zone.zones[0].local_storage_enabled == false + +- name: get info from all zones + cs_zone_info: + register: zones +- name: verify get info from all zones + assert: + that: + - zones is successful + - zones is not changed + - zones.zones | length > 0 From 7bfd006739f9ee814e732a4c06096a78c01a2949 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 12:56:50 +0200 Subject: [PATCH 09/17] Make cs_instance_info return a list. --- .../cloud/cloudstack/cs_instance_info.py | 403 +++++++++--------- .../targets/cs_instance/tasks/present.yml | 2 +- .../targets/cs_instance_info/tasks/main.yml | 38 +- .../cs_volume/tasks/extract_upload.yml | 8 +- 4 files changed, 233 insertions(+), 218 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index cdf768de0c9c8e..8fd49be10c710f 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -25,8 +25,9 @@ name: description: - Name or display name of the instance. + - If not specified, all instances are returned type: str - required: true + required: false domain: description: - Domain the instance is related to. @@ -56,198 +57,202 @@ RETURN = ''' --- -id: - description: UUID of the instance. - returned: success - type: str - sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 -name: - description: Name of the instance. - returned: success - type: str - sample: web-01 -display_name: - description: Display name of the instance. - returned: success - type: str - sample: web-01 -group: - description: Group name of the instance is related. - returned: success - type: str - sample: web -created: - description: Date of the instance was created. - returned: success - type: str - sample: 2014-12-01T14:57:57+0100 -password_enabled: - description: True if password setting is enabled. - returned: success - type: bool - sample: true -password: - description: The password of the instance if exists. - returned: success - type: str - sample: Ge2oe7Do -ssh_key: - description: Name of SSH key deployed to instance. - returned: success - type: str - sample: key@work -domain: - description: Domain the instance is related to. - returned: success - type: str - sample: example domain -account: - description: Account the instance is related to. - returned: success - type: str - sample: example account -project: - description: Name of project the instance is related to. - returned: success - type: str - sample: Production -default_ip: - description: Default IP address of the instance. - returned: success - type: str - sample: 10.23.37.42 -public_ip: - description: Public IP address with instance via static NAT rule. - returned: success - type: str - sample: 1.2.3.4 -iso: - description: Name of ISO the instance was deployed with. - returned: success - type: str - sample: Debian-8-64bit -template: - description: Name of template the instance was deployed with. - returned: success - type: str - sample: Debian-8-64bit -service_offering: - description: Name of the service offering the instance has. - returned: success - type: str - sample: 2cpu_2gb -zone: - description: Name of zone the instance is in. - returned: success - type: str - sample: ch-gva-2 -state: - description: State of the instance. - returned: success - type: str - sample: Running -security_groups: - description: Security groups the instance is in. - returned: success +instances: + description: A list of matching instances. type: list - sample: '[ "default" ]' -affinity_groups: - description: Affinity groups the instance is in. - returned: success - type: list - sample: '[ "webservers" ]' -tags: - description: List of resource tags associated with the instance. - returned: success - type: list - sample: '[ { "key": "foo", "value": "bar" } ]' -hypervisor: - description: Hypervisor related to this instance. - returned: success - type: str - sample: KVM -host: - description: Host the instance is running on. - returned: success and instance is running - type: str - sample: host01.example.com - version_added: '2.6' -instance_name: - description: Internal name of the instance (ROOT admin only). - returned: success - type: str - sample: i-44-3992-VM -volumes: - description: List of dictionaries of the volumes attached to the instance. - returned: success - type: list - sample: '[ { name: "ROOT-1369", type: "ROOT", size: 10737418240 }, { name: "data01, type: "DATADISK", size: 10737418240 } ]' -nic: - description: List of dictionaries of the instance nics. - returned: success - type: complex - version_added: '2.8' - contains: - broadcasturi: - description: The broadcast uri of the nic. + suboptions: + id: + description: UUID of the instance. returned: success type: str - sample: vlan://2250 - gateway: - description: The gateway of the nic. + sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 + name: + description: Name of the instance. returned: success type: str - sample: 10.1.2.1 - id: - description: The ID of the nic. + sample: web-01 + display_name: + description: Display name of the instance. returned: success type: str - sample: 5dc74fa3-2ec3-48a0-9e0d-6f43365336a9 - ipaddress: - description: The ip address of the nic. + sample: web-01 + group: + description: Group name of the instance is related. returned: success type: str - sample: 10.1.2.3 - isdefault: - description: True if nic is default, false otherwise. + sample: web + created: + description: Date of the instance was created. + returned: success + type: str + sample: 2014-12-01T14:57:57+0100 + password_enabled: + description: True if password setting is enabled. returned: success type: bool sample: true - isolationuri: - description: The isolation uri of the nic. + password: + description: The password of the instance if exists. + returned: success + type: str + sample: Ge2oe7Do + ssh_key: + description: Name of SSH key deployed to instance. returned: success type: str - sample: vlan://2250 - macaddress: - description: The mac address of the nic. + sample: key@work + domain: + description: Domain the instance is related to. returned: success type: str - sample: 06:a2:03:00:08:12 - netmask: - description: The netmask of the nic. + sample: example domain + account: + description: Account the instance is related to. returned: success type: str - sample: 255.255.255.0 - networkid: - description: The ID of the corresponding network. + sample: example account + project: + description: Name of project the instance is related to. returned: success type: str - sample: 432ce27b-c2bb-4e12-a88c-a919cd3a3017 - networkname: - description: The name of the corresponding network. + sample: Production + default_ip: + description: Default IP address of the instance. returned: success type: str - sample: network1 - traffictype: - description: The traffic type of the nic. + sample: 10.23.37.42 + public_ip: + description: Public IP address with instance via static NAT rule. returned: success type: str - sample: Guest - type: - description: The type of the network. + sample: 1.2.3.4 + iso: + description: Name of ISO the instance was deployed with. returned: success type: str - sample: Shared + sample: Debian-8-64bit + template: + description: Name of template the instance was deployed with. + returned: success + type: str + sample: Debian-8-64bit + service_offering: + description: Name of the service offering the instance has. + returned: success + type: str + sample: 2cpu_2gb + zone: + description: Name of zone the instance is in. + returned: success + type: str + sample: ch-gva-2 + state: + description: State of the instance. + returned: success + type: str + sample: Running + security_groups: + description: Security groups the instance is in. + returned: success + type: list + sample: '[ "default" ]' + affinity_groups: + description: Affinity groups the instance is in. + returned: success + type: list + sample: '[ "webservers" ]' + tags: + description: List of resource tags associated with the instance. + returned: success + type: list + sample: '[ { "key": "foo", "value": "bar" } ]' + hypervisor: + description: Hypervisor related to this instance. + returned: success + type: str + sample: KVM + host: + description: Host the instance is running on. + returned: success and instance is running + type: str + sample: host01.example.com + version_added: '2.6' + instance_name: + description: Internal name of the instance (ROOT admin only). + returned: success + type: str + sample: i-44-3992-VM + volumes: + description: List of dictionaries of the volumes attached to the instance. + returned: success + type: list + sample: '[ { name: "ROOT-1369", type: "ROOT", size: 10737418240 }, { name: "data01, type: "DATADISK", size: 10737418240 } ]' + nic: + description: List of dictionaries of the instance nics. + returned: success + type: complex + version_added: '2.8' + contains: + broadcasturi: + description: The broadcast uri of the nic. + returned: success + type: str + sample: vlan://2250 + gateway: + description: The gateway of the nic. + returned: success + type: str + sample: 10.1.2.1 + id: + description: The ID of the nic. + returned: success + type: str + sample: 5dc74fa3-2ec3-48a0-9e0d-6f43365336a9 + ipaddress: + description: The ip address of the nic. + returned: success + type: str + sample: 10.1.2.3 + isdefault: + description: True if nic is default, false otherwise. + returned: success + type: bool + sample: true + isolationuri: + description: The isolation uri of the nic. + returned: success + type: str + sample: vlan://2250 + macaddress: + description: The mac address of the nic. + returned: success + type: str + sample: 06:a2:03:00:08:12 + netmask: + description: The netmask of the nic. + returned: success + type: str + sample: 255.255.255.0 + networkid: + description: The ID of the corresponding network. + returned: success + type: str + sample: 432ce27b-c2bb-4e12-a88c-a919cd3a3017 + networkname: + description: The name of the corresponding network. + returned: success + type: str + sample: network1 + traffictype: + description: The traffic type of the nic. + returned: success + type: str + sample: Guest + type: + description: The type of the network. + returned: success + type: str + sample: Shared ''' from ansible.module_utils.basic import AnsibleModule @@ -258,7 +263,6 @@ class AnsibleCloudStackInstanceInfo(AnsibleCloudStack): def __init__(self, module): super(AnsibleCloudStackInstanceInfo, self).__init__(module) - self.instance = None self.returns = { 'group': 'group', 'hypervisor': 'hypervisor', @@ -273,25 +277,24 @@ def __init__(self, module): 'hostname': 'host', } - def get_instance(self): - instance = self.instance - if not instance: - instance_name = self.module.params.get('name') + def get_instances(self): + instance_name = self.module.params.get('name') - args = { - 'account': self.get_account(key='name'), - 'domainid': self.get_domain(key='id'), - 'projectid': self.get_project(key='id'), - 'fetch_list': True, - } - # Do not pass zoneid, as the instance name must be unique across zones. - instances = self.query_api('listVirtualMachines', **args) - if instances: - for v in instances: - if instance_name.lower() in [v['name'].lower(), v['displayname'].lower(), v['id']]: - self.instance = v - break - return self.instance + args = { + 'account': self.get_account(key='name'), + 'domainid': self.get_domain(key='id'), + 'projectid': self.get_project(key='id'), + 'fetch_list': True, + } + # Do not pass zoneid, as the instance name must be unique across zones. + instances = self.query_api('listVirtualMachines', **args) + if not instance_name: + return instances or [] + if instances: + for v in instances: + if instance_name.lower() in [v['name'].lower(), v['displayname'].lower(), v['id']]: + return [v] + return [] def get_volumes(self, instance): volume_details = [] @@ -311,39 +314,41 @@ def get_volumes(self, instance): return volume_details def run(self): - instance = self.get_instance() - if not instance: + instances = self.get_instance() + if self.module.params.get('name') and not instances: self.module.fail_json(msg="Instance not found: %s" % self.module.params.get('name')) - return instance + return { + 'instances': [self.update_result(resource) for resource in instances] + } - def get_result(self, instance): - super(AnsibleCloudStackInstanceInfo, self).get_result(instance) + def update_result(self, instance, result=None): + result = super(AnsibleCloudStackInstanceInfo, self).update_result(instance, result) if instance: if 'securitygroup' in instance: security_groups = [] for securitygroup in instance['securitygroup']: security_groups.append(securitygroup['name']) - self.result['security_groups'] = security_groups + result['security_groups'] = security_groups if 'affinitygroup' in instance: affinity_groups = [] for affinitygroup in instance['affinitygroup']: affinity_groups.append(affinitygroup['name']) - self.result['affinity_groups'] = affinity_groups + result['affinity_groups'] = affinity_groups if 'nic' in instance: for nic in instance['nic']: if nic['isdefault'] and 'ipaddress' in nic: - self.result['default_ip'] = nic['ipaddress'] - self.result['nic'] = instance['nic'] + result['default_ip'] = nic['ipaddress'] + result['nic'] = instance['nic'] volumes = self.get_volumes(instance) if volumes: - self.result['volumes'] = volumes - return self.result + result['volumes'] = volumes + return result def main(): argument_spec = cs_argument_spec() argument_spec.update(dict( - name=dict(required=True), + name=dict(), domain=dict(), account=dict(), project=dict(), @@ -355,7 +360,7 @@ def main(): ) acs_instance_info = AnsibleCloudStackInstanceInfo(module=module) - cs_instance_info = acs_instance_info.get_result(acs_instance_info.run()) + cs_instance_info = acs_instance_info.run() module.exit_json(**cs_instance_info) diff --git a/test/integration/targets/cs_instance/tasks/present.yml b/test/integration/targets/cs_instance/tasks/present.yml index 28d3eb2fecf230..81b770331de7f8 100644 --- a/test/integration/targets/cs_instance/tasks/present.yml +++ b/test/integration/targets/cs_instance/tasks/present.yml @@ -85,7 +85,7 @@ - instance.ssh_key == "{{ cs_resource_prefix }}-sshkey" - not instance.tags -- name: gather host facts of running instance +- name: gather host infos of running instance cs_instance_info: name: "{{ cs_resource_prefix }}-vm-{{ instance_number }}" diff --git a/test/integration/targets/cs_instance_info/tasks/main.yml b/test/integration/targets/cs_instance_info/tasks/main.yml index 38e1a20ecdef3f..286f077d799bb6 100644 --- a/test/integration/targets/cs_instance_info/tasks/main.yml +++ b/test/integration/targets/cs_instance_info/tasks/main.yml @@ -48,13 +48,13 @@ that: - instance_info is successful - instance_info is not changed - - instance_info.id == instance.id - - instance_info.domain == instance.domain - - instance_info.account == instance.account - - instance_info.zone == instance.zone - - instance_info.name == instance.name - - instance_info.service_offering == instance.service_offering - - instance_info.host != "" + - instance_info.instances[0].id == instance.id + - instance_info.instances[0].domain == instance.domain + - instance_info.instances[0].account == instance.account + - instance_info.instances[0].zone == instance.zone + - instance_info.instances[0].name == instance.name + - instance_info.instances[0].service_offering == instance.service_offering + - instance_info.instances[0].host != "" - name: test instance info cs_instance_info: @@ -65,10 +65,20 @@ that: - instance_info is successful - instance_info is not changed - - instance_info.id == instance.id - - instance_info.domain == instance.domain - - instance_info.account == instance.account - - instance_info.zone == instance.zone - - instance_info.name == instance.name - - instance_info.service_offering == instance.service_offering - - instance_info.host != "" + - instance_info.instances[0].id == instance.id + - instance_info.instances[0].domain == instance.domain + - instance_info.instances[0].account == instance.account + - instance_info.instances[0].zone == instance.zone + - instance_info.instances[0].name == instance.name + - instance_info.instances[0].service_offering == instance.service_offering + - instance_info.instances[0].host != "" + +- name: test instance info for all instances + cs_instance_info: + register: instance_info +- name: verify test instance info + assert: + that: + - instance_info is successful + - instance_info is not changed + - instance_info.instances | length > 0 diff --git a/test/integration/targets/cs_volume/tasks/extract_upload.yml b/test/integration/targets/cs_volume/tasks/extract_upload.yml index e4d22e4b113f68..5dc701873b5474 100644 --- a/test/integration/targets/cs_volume/tasks/extract_upload.yml +++ b/test/integration/targets/cs_volume/tasks/extract_upload.yml @@ -65,7 +65,7 @@ cs_volume: zone: "{{ cs_common_zone_adv }}" state: extracted - name: "{{ instance.volumes[0].name }}" + name: "{{ instance.instances[0].volumes[0].name }}" check_mode: yes register: extracted_vol - name: verify test extract volume in check mode @@ -74,14 +74,14 @@ - extracted_vol is successful - extracted_vol is changed - extracted_vol.state == "Ready" - - extracted_vol.name == "{{ instance.volumes[0].name }}" + - extracted_vol.name == "{{ instance.instances[0].volumes[0].name }}" - extracted_vol.url is not defined - name: test extract volume cs_volume: zone: "{{ cs_common_zone_adv }}" state: extracted - name: "{{ instance.volumes[0].name }}" + name: "{{ instance.instances[0].volumes[0].name }}" register: extracted_vol - name: verify test extract volume assert: @@ -89,7 +89,7 @@ - extracted_vol is successful - extracted_vol is changed - extracted_vol.state == "DOWNLOAD_URL_CREATED" - - extracted_vol.name == "{{ instance.volumes[0].name }}" + - extracted_vol.name == "{{ instance.instances[0].volumes[0].name }}" - extracted_vol.url is defined - name: test upload volume with missing param From 8a9dc9e686c40d292243128a4bbe0598c950d3db Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 13:07:48 +0200 Subject: [PATCH 10/17] Fix return value docs. --- lib/ansible/modules/cloud/cloudstack/cs_instance_info.py | 3 ++- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index 8fd49be10c710f..dd6ade72376d8a 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -60,7 +60,8 @@ instances: description: A list of matching instances. type: list - suboptions: + returned: success + contains: id: description: UUID of the instance. returned: success diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 0c4f9d950077cd..7bdd468827ab80 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -45,7 +45,8 @@ zones: description: A list of matching zones. type: list - suboptions: + returned: success + contains: id: description: UUID of the zone. returned: success From a7f83c60715cbe503959b2a1e9a555102a27f13f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 13:10:55 +0200 Subject: [PATCH 11/17] Fix typo. --- lib/ansible/modules/cloud/cloudstack/cs_instance_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index dd6ade72376d8a..b0baf00d588327 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -315,7 +315,7 @@ def get_volumes(self, instance): return volume_details def run(self): - instances = self.get_instance() + instances = self.get_instances() if self.module.params.get('name') and not instances: self.module.fail_json(msg="Instance not found: %s" % self.module.params.get('name')) return { From 77558bb4a0863faeab8b8f8d4cfefb1ea2fb84a6 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 13:51:19 +0200 Subject: [PATCH 12/17] Improve tests. --- .../targets/cs_instance_info/tasks/main.yml | 7 +++++++ test/integration/targets/cs_zone_info/tasks/main.yml | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/test/integration/targets/cs_instance_info/tasks/main.yml b/test/integration/targets/cs_instance_info/tasks/main.yml index 286f077d799bb6..d041ffe0d7a284 100644 --- a/test/integration/targets/cs_instance_info/tasks/main.yml +++ b/test/integration/targets/cs_instance_info/tasks/main.yml @@ -82,3 +82,10 @@ - instance_info is successful - instance_info is not changed - instance_info.instances | length > 0 + - '"id" in instance_info.instances[0]' + - '"domain" in instance_info.instances[0]' + - '"account" in instance_info.instances[0]' + - '"zone" in instance_info.instances[0]' + - '"name" in instance_info.instances[0]' + - '"service_offering" in instance_info.instances[0]' + - '"host" in instance_info.instances[0]' diff --git a/test/integration/targets/cs_zone_info/tasks/main.yml b/test/integration/targets/cs_zone_info/tasks/main.yml index 538d2528b767d9..74dccf80622465 100644 --- a/test/integration/targets/cs_zone_info/tasks/main.yml +++ b/test/integration/targets/cs_zone_info/tasks/main.yml @@ -61,3 +61,13 @@ - zones is successful - zones is not changed - zones.zones | length > 0 + - '"dns1" in zone.zones[0]' + - '"dns2" in zone.zones[0]' + - '"internal_dns1" in zone.zones[0]' + - '"internal_dns2" in zone.zones[0]' + - '"local_storage_enabled" in zone.zones[0]' + - '"network_type" in zone.zones[0]' + - '"zone_token" in zone.zones[0]' + - '"securitygroups_enabled" in zone.zones[0]' + - '"dhcp_provider" in zone.zones[0]' + - '"local_storage_enabled" in zone.zones[0]' From ef558a1e7bb2b325000b0edf8f1a1f41045e34d1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 13:54:28 +0200 Subject: [PATCH 13/17] Fix cs_zone_info. --- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 7bdd468827ab80..715f5d45abf710 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -172,6 +172,10 @@ def get_zone(self): zones = [super(AnsibleCloudStackZoneInfo, self).get_zone()] else: zones = self.query_api('listZones') + if zones: + zones = zones['zone'] + else: + zones = [] return { 'zones': [self.update_result(resource) for resource in zones] } From b64f7af69851f64804c39403f8600cdfa131d1d7 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 14:15:09 +0200 Subject: [PATCH 14/17] Linting. --- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 6 ++++-- test/sanity/ignore.txt | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 715f5d45abf710..17926e66db5446 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -4,6 +4,9 @@ # Copyright (c) 2016, René Moser # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function +__metaclass__ = type + ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['stableinterface'], 'supported_by': 'community'} @@ -23,7 +26,6 @@ - Name of the zone. - If not specified, all zones are returned type: str - required: false aliases: [ zone ] extends_documentation_fragment: cloudstack ''' @@ -184,7 +186,7 @@ def get_zone(self): def main(): argument_spec = cs_argument_spec() argument_spec.update(dict( - zone=dict(required=False, aliases=['name']), + zone=dict(type='str', aliases=['name']), )) module = AnsibleModule( diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index c1c2fadcc88f94..f3f5e03fc6437c 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -1366,9 +1366,9 @@ lib/ansible/modules/cloud/cloudstack/cs_vpn_gateway.py future-import-boilerplate lib/ansible/modules/cloud/cloudstack/cs_vpn_gateway.py metaclass-boilerplate lib/ansible/modules/cloud/cloudstack/cs_zone.py future-import-boilerplate lib/ansible/modules/cloud/cloudstack/cs_zone.py metaclass-boilerplate -lib/ansible/modules/cloud/cloudstack/cs_zone_info.py future-import-boilerplate -lib/ansible/modules/cloud/cloudstack/cs_zone_info.py metaclass-boilerplate -lib/ansible/modules/cloud/cloudstack/cs_zone_info.py validate-modules:doc-missing-type +lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py future-import-boilerplate +lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py metaclass-boilerplate +lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py validate-modules:doc-missing-type lib/ansible/modules/cloud/digital_ocean/_digital_ocean.py validate-modules:undocumented-parameter lib/ansible/modules/cloud/digital_ocean/_digital_ocean.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/digital_ocean/_digital_ocean.py validate-modules:doc-missing-type From 955d0e624815ca733e765d4562032b36a6946b9a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 14:21:53 +0200 Subject: [PATCH 15/17] Fix alias/option switch. --- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index 17926e66db5446..cb394380ba1845 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -21,19 +21,19 @@ version_added: '2.9' author: René Moser (@resmo) options: - name: + zone: description: - Name of the zone. - If not specified, all zones are returned type: str - aliases: [ zone ] + aliases: [ name ] extends_documentation_fragment: cloudstack ''' EXAMPLES = ''' - name: Gather information from a zone cs_zone_info: - name: ch-gva-1 + zone: ch-gva-1 register: zone delegate_to: localhost From 0f601b807989bffe23849ccece1919af63cab033 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 15:04:41 +0200 Subject: [PATCH 16/17] Fix version numbers. --- lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py | 2 +- lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py index 9e02aeb1d538aa..6f9567448ac4ef 100644 --- a/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py +++ b/lib/ansible/modules/cloud/cloudstack/_cs_instance_facts.py @@ -20,7 +20,7 @@ description: - Gathering facts from the API of an instance. deprecated: - removed_in: "2.12" + removed_in: "2.13" why: Transformed into an info module. alternative: Use M(cs_instance_info) instead. version_added: '2.1' diff --git a/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py index 393d0432b5d8e0..d0663b586ab6d5 100644 --- a/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py +++ b/lib/ansible/modules/cloud/cloudstack/_cs_zone_facts.py @@ -17,7 +17,7 @@ - Gathering facts from the API of a zone. - Sets Ansible facts accessable by the key C(cloudstack_zone) and since version 2.6 also returns results. deprecated: - removed_in: "2.12" + removed_in: "2.13" why: Transformed into an info module. alternative: Use M(cs_zone_info) instead. version_added: '2.1' From d824c8922caa3c589f58926b51aeaf6ace911dbf Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Aug 2019 15:17:59 +0200 Subject: [PATCH 17/17] Extend docs. --- .../modules/cloud/cloudstack/cs_instance_info.py | 11 ++++++++++- lib/ansible/modules/cloud/cloudstack/cs_zone_info.py | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py index b0baf00d588327..ea5435c6b3c66c 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_instance_info.py @@ -44,7 +44,7 @@ ''' EXAMPLES = ''' -- name: gather instance information +- name: Gather instance information cs_instance_info: name: web-vm-1 delegate_to: localhost @@ -53,6 +53,15 @@ - name: Show the returned results of the registered variable debug: msg: "{{ vm }}" + +- name: Gather information from all instances + cs_instance_info: + delegate_to: localhost + register: vms + +- name: Show information on all instances + debug: + msg: "{{ vms }}" ''' RETURN = ''' diff --git a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py index cb394380ba1845..cf8a0eddd2899d 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_zone_info.py @@ -40,6 +40,15 @@ - name: Show the returned results of the registered variable debug: msg: "{{ zone }}" + +- name: Gather information from all zones + cs_zone_info: + register: zones + delegate_to: localhost + +- name: Show information on all zones + debug: + msg: "{{ zones }}" ''' RETURN = '''