diff --git a/changelogs/fragments/89-consolidate-arg-specs-and-docs.yml b/changelogs/fragments/89-consolidate-arg-specs-and-docs.yml new file mode 100644 index 00000000..8635302e --- /dev/null +++ b/changelogs/fragments/89-consolidate-arg-specs-and-docs.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - doc fragments - Remove redundant fragments. Update pyvmomi modules to use new consolidated docs + - argument specs - Remove redundant argument specs. Update pyvmomi modules to use new consolidated spec diff --git a/plugins/doc_fragments/additional_rest_options.py b/plugins/doc_fragments/additional_rest_options.py new file mode 100644 index 00000000..eb7a857e --- /dev/null +++ b/plugins/doc_fragments/additional_rest_options.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2016, Charles Paul +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2019, Abhijeet Kasurde +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +class ModuleDocFragment(object): + # This document fragment serves as a compliment to the vmware.vmware.base documentation fragment for modules + # that use the REST API SDK. You must include the base fragment in addition to this + # + # This vmware.vmware.additional_rest_options fragment will cover any options returned by rest_compatible_argument_spec() + # that are not included in vmware.vmware.base + DOCUMENTATION = r''' +options: + proxy_protocol: + description: + - The proxy connection protocol to use. + - This is option is used if the correct proxy protocol cannot be automatically determined. + type: str + choices: [ http, https ] + default: https + aliases: [protocol] +''' diff --git a/plugins/doc_fragments/base_options.py b/plugins/doc_fragments/base_options.py new file mode 100644 index 00000000..ef5d34a2 --- /dev/null +++ b/plugins/doc_fragments/base_options.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2016, Charles Paul +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2019, Abhijeet Kasurde +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +class ModuleDocFragment(object): + # This document fragment serves as a base for all vmware modules. If you are using the REST API SDK in your module, + # you should also include the vmware.vmware.additional_rest_options fragment. + # + # This vmware.vmware.base_options fragment covers the arg spec provided by the base_argument_spec() function + DOCUMENTATION = r''' +notes: + - All modules require API write access and hence is not supported on a free ESXi license. + - All variables and VMware object names are case sensitive. + - >- + Modules may rely on the 'requests' python library, which does not use the system certificate store by default. You can + specify the certificate store by setting the REQUESTS_CA_BUNDLE environment variable. + Example: 'export REQUESTS_CA_BUNDLE=/path/to/your/ca_bundle.pem' +options: + hostname: + description: + - The hostname or IP address of the vSphere vCenter server. + - If the value is not specified in the task, the value of environment variable E(VMWARE_HOST) will be used instead. + type: str + username: + description: + - The username of the vSphere vCenter server. + - If the value is not specified in the task, the value of environment variable E(VMWARE_USER) will be used instead. + type: str + aliases: [ admin, user ] + password: + description: + - The password of the vSphere vCenter server. + - If the value is not specified in the task, the value of environment variable E(VMWARE_PASSWORD) will be used instead. + type: str + aliases: [ pass, pwd ] + validate_certs: + description: + - Allows connection when SSL certificates are not valid. Set to V(false) when certificates are not trusted. + - If the value is not specified in the task, the value of environment variable E(VMWARE_VALIDATE_CERTS) will be used instead. + type: bool + default: true + port: + description: + - The port number of the vSphere vCenter server. + - If the value is not specified in the task, the value of environment variable E(VMWARE_PORT) will be used instead. + type: int + default: 443 + proxy_host: + description: + - Address of a proxy that will receive all HTTPS requests and relay them. + - The format is a hostname or a IP. + - If the value is not specified in the task, the value of environment variable E(VMWARE_PROXY_HOST) will be used instead. + type: str + required: false + proxy_port: + description: + - Port of the HTTP proxy that will receive all HTTPS requests and relay them. + - If the value is not specified in the task, the value of environment variable E(VMWARE_PROXY_PORT) will be used instead. + type: int + required: false +''' diff --git a/plugins/doc_fragments/vmware.py b/plugins/doc_fragments/vmware.py deleted file mode 100644 index ed4e14c0..00000000 --- a/plugins/doc_fragments/vmware.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, Charles Paul -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2019, Abhijeet Kasurde -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class ModuleDocFragment(object): - # Parameters for VMware modules - DOCUMENTATION = r''' -notes: - - All modules require API write access and hence is not supported on a free ESXi license. - - All variables and VMware object names are case sensitive. -options: - hostname: - description: - - The hostname or IP address of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_HOST) will be used instead. - type: str - username: - description: - - The username of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_USER) will be used instead. - type: str - aliases: [ admin, user ] - password: - description: - - The password of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PASSWORD) will be used instead. - type: str - aliases: [ pass, pwd ] - validate_certs: - description: - - Allows connection when SSL certificates are not valid. Set to V(false) when certificates are not trusted. - - If the value is not specified in the task, the value of environment variable E(VMWARE_VALIDATE_CERTS) will be used instead. - type: bool - default: true - port: - description: - - The port number of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PORT) will be used instead. - type: int - default: 443 - datacenter: - description: - - The datacenter to use when connecting to a vCenter. - type: str - aliases: [ datacenter_name ] - cluster: - description: - - The cluster to use when connecting to a vCenter. - type: str - aliases: [ cluster_name ] - proxy_host: - description: - - Address of a proxy that will receive all HTTPS requests and relay them. - - The format is a hostname or a IP. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PROXY_HOST) will be used instead. - type: str - required: false - proxy_port: - description: - - Port of the HTTP proxy that will receive all HTTPS requests and relay them. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PROXY_PORT) will be used instead. - type: int - required: false -''' - - # This doc fragment is specific to vcenter modules like vcenter_license - VCENTER_DOCUMENTATION = r''' -notes: - - All modules require API write access and hence is not supported on a free ESXi license. -options: - hostname: - description: - - The hostname or IP address of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_HOST) will be used instead. - type: str - username: - description: - - The username of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_USER) will be used instead. - type: str - aliases: [ admin, user ] - password: - description: - - The password of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PASSWORD) will be used instead. - type: str - aliases: [ pass, pwd ] - validate_certs: - description: - - Allows connection when SSL certificates are not valid. Set to V(false) when certificates are not trusted. - - If the value is not specified in the task, the value of environment variable E(VMWARE_VALIDATE_CERTS) will be used instead. - type: bool - default: true - port: - description: - - The port number of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PORT) will be used instead. - type: int - default: 443 - datacenter: - description: - - The datacenter to use when connecting to a vCenter. - type: str - aliases: [ datacenter_name ] - cluster: - description: - - The cluster to use when connecting to a vCenter. - type: str - aliases: [ cluster_name ] - proxy_host: - description: - - Address of a proxy that will receive all HTTPS requests and relay them. - - The format is a hostname or a IP. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PROXY_HOST) will be used instead. - type: str - required: false - proxy_port: - description: - - Port of the HTTP proxy that will receive all HTTPS requests and relay them. - - If the value is not specified in the task, the value of environment variable E(VMWARE_PROXY_PORT) will be used instead. - type: int - required: false - ''' diff --git a/plugins/module_utils/_vmware.py b/plugins/module_utils/_vmware.py index 69f57189..652b14fe 100644 --- a/plugins/module_utils/_vmware.py +++ b/plugins/module_utils/_vmware.py @@ -32,7 +32,7 @@ PYVMOMI_IMP_ERR = traceback.format_exc() HAS_PYVMOMI = False -from ansible.module_utils.basic import env_fallback, missing_required_lib +from ansible.module_utils.basic import missing_required_lib class ApiAccessError(Exception): @@ -40,46 +40,6 @@ def __init__(self, *args, **kwargs): super(ApiAccessError, self).__init__(*args, **kwargs) -def vmware_argument_spec(): - return dict( - hostname=dict(type='str', - required=False, - fallback=(env_fallback, ['VMWARE_HOST']), - ), - username=dict(type='str', - aliases=['user', 'admin'], - required=False, - fallback=(env_fallback, ['VMWARE_USER'])), - password=dict(type='str', - aliases=['pass', 'pwd'], - required=False, - no_log=True, - fallback=(env_fallback, ['VMWARE_PASSWORD'])), - cluster=dict(type='str', - aliases=['cluster_name'], - required=False), - datacenter=dict(type='str', - aliases=['datacenter_name'], - required=False), - port=dict(type='int', - default=443, - fallback=(env_fallback, ['VMWARE_PORT'])), - validate_certs=dict(type='bool', - required=False, - default=True, - fallback=(env_fallback, ['VMWARE_VALIDATE_CERTS']) - ), - proxy_host=dict(type='str', - required=False, - default=None, - fallback=(env_fallback, ['VMWARE_PROXY_HOST'])), - proxy_port=dict(type='int', - required=False, - default=None, - fallback=(env_fallback, ['VMWARE_PROXY_PORT'])), - ) - - def connect_to_api(module, disconnect_atexit=True, return_si=False, hostname=None, username=None, password=None, port=None, validate_certs=None, httpProxyHost=None, httpProxyPort=None): diff --git a/plugins/module_utils/_vmware_argument_spec.py b/plugins/module_utils/_vmware_argument_spec.py new file mode 100644 index 00000000..46b7f935 --- /dev/null +++ b/plugins/module_utils/_vmware_argument_spec.py @@ -0,0 +1,72 @@ +from ansible.module_utils.basic import env_fallback + + +def rest_compatible_argument_spec(): + """ + This returns a dictionary that can be used as the baseline for all REST module specs. + If your module uses the REST API, you should use this instead of the base_argument_spec. + If your module uses both this and the pyvmomi SDK, you should still use this spec. + """ + return { + **base_argument_spec(), + **dict( + proxy_protocol=dict( + type='str', + default='https', + choices=['https', 'http'], + aliases=['protocol'] + ), + ) + } + + +def base_argument_spec(): + """ + This returns a dictionary that can be used as the baseline for all vmware module specs. Any arguments + common to both the REST API SDK and pyvmomi SDK should be placed here. + If your module uses the REST API, you should use the rest_compatible_argument_spec since that + includes additional arguments specific to that SDK. + """ + return dict( + hostname=dict( + type='str', + required=False, + fallback=(env_fallback, ['VMWARE_HOST']), + ), + username=dict( + type='str', + aliases=['user', 'admin'], + required=False, + fallback=(env_fallback, ['VMWARE_USER']) + ), + password=dict( + type='str', + aliases=['pass', 'pwd'], + required=False, + no_log=True, + fallback=(env_fallback, ['VMWARE_PASSWORD']) + ), + port=dict( + type='int', + default=443, + fallback=(env_fallback, ['VMWARE_PORT']) + ), + validate_certs=dict( + type='bool', + required=False, + default=True, + fallback=(env_fallback, ['VMWARE_VALIDATE_CERTS']) + ), + proxy_host=dict( + type='str', + required=False, + default=None, + fallback=(env_fallback, ['VMWARE_PROXY_HOST']) + ), + proxy_port=dict( + type='int', + required=False, + default=None, + fallback=(env_fallback, ['VMWARE_PROXY_PORT']) + ), + ) diff --git a/plugins/modules/cluster.py b/plugins/modules/cluster.py index df75a599..dd99f849 100644 --- a/plugins/modules/cluster.py +++ b/plugins/modules/cluster.py @@ -45,8 +45,9 @@ - module: vmware.vmware.cluster_drs - module: community.vmware.vmware_cluster_ha - module: community.vmware.vmware_cluster_vsan + extends_documentation_fragment: - - vmware.vmware.vmware.documentation + - vmware.vmware.base_options ''' EXAMPLES = r''' @@ -92,8 +93,10 @@ from ansible.module_utils._text import to_native from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( - PyVmomi, - vmware_argument_spec + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec ) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_tasks import ( TaskError, @@ -182,7 +185,7 @@ def get_cluster_outputs(self): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **base_argument_spec(), **dict( cluster=dict(type='str', required=True, aliases=['cluster_name', 'name']), datacenter=dict(type='str', required=True, aliases=['datacenter_name']), state=dict(type='str', default='present', choices=['absent', 'present']), diff --git a/plugins/modules/cluster_dpm.py b/plugins/modules/cluster_dpm.py index 36437401..dbf1cd6a 100644 --- a/plugins/modules/cluster_dpm.py +++ b/plugins/modules/cluster_dpm.py @@ -58,7 +58,7 @@ choices: [ 1, 2, 3, 4, 5 ] extends_documentation_fragment: - - vmware.vmware.vmware.documentation + - vmware.vmware.base_options ''' EXAMPLES = r''' @@ -110,8 +110,10 @@ from ansible.module_utils.basic import AnsibleModule from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( - PyVmomi, - vmware_argument_spec + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec ) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_tasks import ( TaskError, @@ -208,7 +210,7 @@ def apply_dpm_configuration(self): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **base_argument_spec(), **dict( cluster=dict(type='str', required=True, aliases=['cluster_name']), datacenter=dict(type='str', required=True, aliases=['datacenter_name']), enable=dict(type='bool', default=True), diff --git a/plugins/modules/cluster_drs.py b/plugins/modules/cluster_drs.py index b2b093d8..8765b1e7 100644 --- a/plugins/modules/cluster_drs.py +++ b/plugins/modules/cluster_drs.py @@ -73,7 +73,7 @@ default: false extends_documentation_fragment: - - vmware.vmware.vmware.documentation + - vmware.vmware.base_options ''' EXAMPLES = r''' @@ -136,8 +136,10 @@ from ansible.module_utils.basic import AnsibleModule from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( - PyVmomi, - vmware_argument_spec + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec ) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_tasks import ( TaskError, @@ -246,7 +248,7 @@ def apply_drs_configuration(self): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **base_argument_spec(), **dict( cluster=dict(type='str', required=True, aliases=['cluster_name']), datacenter=dict(type='str', required=True, aliases=['datacenter_name']), enable=dict(type='bool', default=True), diff --git a/plugins/modules/cluster_drs_recommendations.py b/plugins/modules/cluster_drs_recommendations.py index c2c01ed5..ab9480a4 100644 --- a/plugins/modules/cluster_drs_recommendations.py +++ b/plugins/modules/cluster_drs_recommendations.py @@ -42,7 +42,7 @@ aliases: [ datacenter_name ] extends_documentation_fragment: - - vmware.vmware.vmware.documentation + - vmware.vmware.base_options ''' EXAMPLES = r''' @@ -96,8 +96,10 @@ from itertools import zip_longest from ansible.module_utils.basic import AnsibleModule from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( - PyVmomi, - vmware_argument_spec + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec ) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_tasks import ( TaskError, @@ -177,7 +179,7 @@ def __wait_for_recommendation_task_results(self, recommendation_tasks): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **base_argument_spec(), **dict( cluster=dict(type='str', required=True, aliases=['cluster_name']), datacenter=dict(type='str', required=True, aliases=['datacenter_name']), ) diff --git a/plugins/modules/cluster_info.py b/plugins/modules/cluster_info.py index 51e2ffbd..6de3d4cb 100644 --- a/plugins/modules/cluster_info.py +++ b/plugins/modules/cluster_info.py @@ -57,7 +57,8 @@ elements: str extends_documentation_fragment: - - vmware.vmware.vmware.vcenter_documentation + - vmware.vmware.base_options + - vmware.vmware.additional_rest_options ''' EXAMPLES = r''' @@ -155,7 +156,12 @@ except ImportError: pass from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vmware.vmware.plugins.module_utils._vmware import PyVmomi, vmware_argument_spec +from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + rest_compatible_argument_spec +) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_rest_client import VmwareRestClient from ansible_collections.vmware.vmware.plugins.module_utils._vmware_facts import ( ClusterFacts, @@ -230,7 +236,7 @@ def _get_tags(self, cluster): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **rest_compatible_argument_spec(), **dict( cluster=dict(type='str', aliases=['cluster_name', 'name']), datacenter=dict(type='str', aliases=['datacenter_name']), gather_tags=dict(type='bool', default=False), diff --git a/plugins/modules/cluster_vcls.py b/plugins/modules/cluster_vcls.py index 1f0c45ec..2f3f7699 100644 --- a/plugins/modules/cluster_vcls.py +++ b/plugins/modules/cluster_vcls.py @@ -63,7 +63,7 @@ extends_documentation_fragment: - - vmware.vmware.vmware.documentation + - vmware.vmware.base_options ''' EXAMPLES = r''' @@ -137,8 +137,10 @@ from ansible.module_utils._text import to_native from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( - PyVmomi, - vmware_argument_spec + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec ) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_tasks import ( TaskError, @@ -246,7 +248,7 @@ def configure_vcls(self, datastores_to_add, datastores_to_remove): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **base_argument_spec(), **dict( cluster=dict(type='str', required=True, aliases=['cluster_name']), datacenter=dict(type='str', required=False, aliases=['datacenter_name']), allowed_datastores=dict(type='list', elements='str'), diff --git a/plugins/modules/folder_template_from_vm.py b/plugins/modules/folder_template_from_vm.py index ec4b6686..eac322e2 100644 --- a/plugins/modules/folder_template_from_vm.py +++ b/plugins/modules/folder_template_from_vm.py @@ -99,7 +99,7 @@ description: The check_mode support. support: full extends_documentation_fragment: - - vmware.vmware.vmware.vcenter_documentation + - vmware.vmware.base_options ''' @@ -143,7 +143,12 @@ import traceback from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vmware.vmware.plugins.module_utils._vmware import PyVmomi, vmware_argument_spec +from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec +) from ansible_collections.vmware.vmware.plugins.module_utils._vmware_folder_paths import format_folder_path_as_vm_fq_path from ansible_collections.vmware.vmware.plugins.module_utils._vmware_tasks import RunningTaskMonitor, TaskError @@ -262,7 +267,7 @@ def custom_validation(module): def main(): module = AnsibleModule( argument_spec={ - **vmware_argument_spec(), **dict( + **base_argument_spec(), **dict( vm_name=dict(type='str', required=False, default=None), vm_name_match=dict(type='str', required=False, choices=['first', 'last']), vm_uuid=dict(type='str', required=False, default=None), diff --git a/plugins/modules/license_info.py b/plugins/modules/license_info.py index 3aedeb0a..d28c02ff 100644 --- a/plugins/modules/license_info.py +++ b/plugins/modules/license_info.py @@ -22,7 +22,7 @@ description: The check_mode support. support: full extends_documentation_fragment: -- vmware.vmware.vmware.vcenter_documentation +- vmware.vmware.base_options ''' EXAMPLES = r''' @@ -44,7 +44,12 @@ ''' from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vmware.vmware.plugins.module_utils._vmware import PyVmomi, vmware_argument_spec +from ansible_collections.vmware.vmware.plugins.module_utils._vmware import ( + PyVmomi +) +from ansible_collections.vmware.vmware.plugins.module_utils._vmware_argument_spec import ( + base_argument_spec +) class VcenterLicenseMgr(PyVmomi): @@ -62,7 +67,7 @@ def list_keys(self, licenses): def main(): module = AnsibleModule( - argument_spec=vmware_argument_spec(), + argument_spec=base_argument_spec(), supports_check_mode=True, )