diff --git a/docs/docsite/rst/scenario_guides/guide_aci.rst b/docs/docsite/rst/scenario_guides/guide_aci.rst index 1568194ff22..00748ac197f 100644 --- a/docs/docsite/rst/scenario_guides/guide_aci.rst +++ b/docs/docsite/rst/scenario_guides/guide_aci.rst @@ -61,39 +61,90 @@ For instance ensuring that a specific tenant exists, is done using the following A complete list of existing ACI modules is available for `the latest stable release `_ as well as `the current development version `_. -Standard module parameters -.......................... +Common parameters +................. Every Ansible ACI module accepts the following parameters that influence the module's communication with the APIC REST API: -- ``host`` -- Hostname or IP address of the APIC -- ``port`` -- Port to use for communication (defaults to ``443`` for HTTPS, and ``80`` for HTTP) -- ``username`` -- User name used to log on to the APIC (defaults to ``admin``) -- ``password`` -- Password for ``username`` to log on to the APIC (using password-based authentication) -- ``private_key`` -- Private key for ``username`` to log on to APIC (using signature-based authentication) -- ``certificate_name`` -- Name of the certificate in the ACI Web GUI (defaults to ``private_key`` file base name) -- ``timeout`` -- Timeout value for socket-level communication -- ``use_proxy`` -- Use system proxy settings (defaults to ``yes``) -- ``use_ssl`` -- Use HTTPS or HTTP for APIC REST communication (defaults to ``yes``) -- ``validate_certs`` -- Validate certificate when using HTTPS communication (defaults to ``yes``) -- ``output_level`` -- Influence the level of detail ACI modules return to the user (one of ``normal``, ``info`` or ``debug``) + host + Hostname or IP address of the APIC. + + port + Port to use for communication. (Defaults to ``443`` for HTTPS, and ``80`` for HTTP) + + username + User name used to log on to the APIC. (Defaults to ``admin``) + + password + Password for ``username`` to log on to the APIC, using password-based authentication. + + private_key + Private key for ``username`` to log on to APIC, using signature-based authentication. *New in version 2.5* + + certificate_name + Name of the certificate in the ACI Web GUI. (Defaults to ``private_key`` file base name) *New in version 2.5* + + timeout + Timeout value for socket-level communication. + + use_proxy + Use system proxy settings. (Defaults to ``yes``) + + use_ssl + Use HTTPS or HTTP for APIC REST communication. (Defaults to ``yes``) + + validate_certs + Validate certificate when using HTTPS communication. (Defaults to ``yes``) + + output_level + Influence the level of detail ACI modules return to the user. (One of ``normal``, ``info`` or ``debug``) *New in version 2.5* Proxy support ............. -By default, if an environment variable ``_proxy`` is set on the target host, requests will be sent through that proxy. This behaviour can be overridden by setting a variable for this task (see setting the environment), or by using the ``use_proxy`` module parameter. +By default, if an environment variable ``_proxy`` is set on the target host, requests will be sent through that proxy. This behaviour can be overridden by setting a variable for this task (see :ref:`setting the environment `), or by using the ``use_proxy`` module parameter. HTTP redirects can redirect from HTTP to HTTPS so you should be sure that your proxy environment for both protocols is correct. If you don't need proxy support, but the system may have it configured nevertheless, you can add this parameter setting: ``use_proxy: no`` to avoid accidental proxy usage. -.. note:: Selective proxy support using the ``no_proxy`` environment variable is also supported. +.. hint:: Selective proxy support using the ``no_proxy`` environment variable is also supported. + +Return values +............. + +.. versionadded:: 2.5 + +The following values are always returned: + + current + The resulting state of the managed object. + +The following values are returned when ``output_level: info``: + + previous + The original state of the managed object (before any change was made). + + proposed + The proposed config payload, based on user-supplied values. -Module return values -.................... -By default the ACI modules (excluding :ref:`the aci_rest module `) return the resulting state of the managed object in a key ``current``. + sent + The sent config payload, based on user-supplied values and the existing configuration. -By increasing the ``output_level`` to ``info``, the modules give access to the ``previous`` state of the object, but also the ``proposed`` and ``sent`` configuration payload. +The following values are returned when ``output_level: debug`` or ``ANSIBLE_DEBUG=1``: -For troubleshooting purposes setting ``output_level: debug`` or defining environment variable ``ANSIBLE_DEBUG=1`` enables more detailed information on the actual APIC REST communication, incl. ``filter_string``, ``method``, ``response``, ``status`` and ``url``. + filter_string + The filter used for specific APIC queries. + + method + The HTTP method used for the sent payload. (Either ``GET`` for queries, ``DELETE`` or ``POST`` for changes) + + response + The HTTP response from the APIC. + + status + The HTTP status code for the request. + + url + The url used for the request. .. note:: The module return values are documented in detail as part of each module's documentation. @@ -128,9 +179,11 @@ Password-based authentication is very simple to work with, but it is not the mos The "Vault" feature of Ansible allows you to keep sensitive data such as passwords or keys in encrypted files, rather than as plain text in your playbooks or roles. These vault files can then be distributed or placed in source control. See :doc:`playbooks_vault` for more information. - Signature-based authentication using certificates ................................................. + +.. versionadded:: 2.5 + Using signature-based authentication is more efficient and more reliable than password-based authentication. Generate certificate and private key @@ -183,7 +236,7 @@ You need the following parameters with your ACI module(s) for it to work: private_key: pki/admin.key certificate_name: admin # This could be left out ! -.. note:: If you use a certificate name in ACI that matches the private key's basename, you can leave out the ``certificate_name`` parameter like the example above. +.. hint:: If you use a certificate name in ACI that matches the private key's basename, you can leave out the ``certificate_name`` parameter like the example above. More information ,,,,,,,,,,,,,,,, @@ -271,8 +324,9 @@ More information ................ Plenty of resources exist to learn about ACI's APIC REST interface, we recommend the links below: -- :ref:`The apic_rest Ansible module ` -- `APIC REST API Configuration Guide `_ +- :ref:`The apic_rest Ansible module documentation ` +- `APIC REST API Configuration Guide `_-- Detailed guide on how the APIC REST API is designed and used, incl. many examples +- `APIC Management Information Model reference `_-- Complete reference of the APIC object model - `Cisco DevNet Learning Labs about ACI and REST `_ @@ -334,22 +388,18 @@ APIC error messages ------------------- The following error messages may occur and this section can help you understand what exactly is going on. -- **APIC Error 122: unknown managed object class 'polUni'** - - In case you receive this error while you are certain your :ref:`aci_rest ` payload and object classes are seemingly correct, the issue might be that your payload is not in fact correct JSON (e.g. the sent payload is using single quotes, rather than double quotes), and as a result the APIC is not correctly parsing your object classes from the payload. One way to avoid this is by using a YAML or an XML formatted payload. - + APIC Error 122: unknown managed object class 'polUni' + In case you receive this error while you are certain your :ref:`aci_rest ` payload and object classes are seemingly correct, the issue might be that your payload is not in fact correct JSON (e.g. the sent payload is using single quotes, rather than double quotes), and as a result the APIC is not correctly parsing your object classes from the payload. One way to avoid this is by using a YAML or an XML formatted payload. -- **APIC Error 400: invalid data at line '1'. Attributes are missing, tag 'attributes' must be specified first, before any other tag** - Although the JSON specification allows unordered elements, the APIC REST API requires that the JSON ``attributes`` element precede the ``children`` array or other elements. So you need to ensure that your payload conforms to this requirement. Sorting your dictionary keys will do the trick just fine. If you don't have any attributes, it may be necessary to add: ``attributes: {}`` as the APIC does expect the entry to proceed any ``children``. + APIC Error 400: invalid data at line '1'. Attributes are missing, tag 'attributes' must be specified first, before any other tag + Although the JSON specification allows unordered elements, the APIC REST API requires that the JSON ``attributes`` element precede the ``children`` array or other elements. So you need to ensure that your payload conforms to this requirement. Sorting your dictionary keys will do the trick just fine. If you don't have any attributes, it may be necessary to add: ``attributes: {}`` as the APIC does expect the entry to proceed any ``children``. + APIC Error 801: property descr of uni/tn-TENANT/ap-AP failed validation for value 'A "legacy" network' + Some values in the APIC have strict format-rules to comply to, and the internal APIC validation check for the provided value failed. In the above case, the ``description`` parameter (internally known as ``descr``) only accepts values conforming to `Regex: [a-zA-Z0-9\\!#$%()*,-./:;@ _{|}~?&+]+ `_, in general it must not include quotes or square brackets. -- **APIC Error 801: property descr of uni/tn-TENANT/ap-AP failed validation for value 'A "legacy" network'** - Some values in the APIC have strict format-rules to comply to, and the internal APIC validation check for the provided value failed. In the above case, the ``description`` parameter (internally known as ``descr``) only accepts values conforming to `Regex: [a-zA-Z0-9\\!#$%()*,-./:;@ _{|}~?&+]+ `_, in general it must not include quotes or square brackets. - - -.. _aci_guide_issues: +.. _aci_guide_known_issues: Known issues ------------ @@ -357,38 +407,28 @@ Known issues All below issues either have been reported to the vendor, or can simply be avoided. -- **Too many consecutive API calls may result in connection throttling** - - Starting with ACI v3.1 the APIC will actively throttle password-based authenticated connection rates over a specific treshold. This is as part of an anti-DDOS measure but can act up when using Ansible with ACI using password-based authentication. Currently, one solution is to increase this treshold within the nginx configuration, but using signature-based authentication is recommended. - - **NOTE:** It is advisable to use signature-based authentication with ACI as it not only prevents connection-throttling, but also improves general performance when using the ACI modules. - - -- **Specific requests may not reflect changes correctly** - - There is a known issue where specific requests to the APIC do not properly reflect changed in the resulting output, even when we request those changes explicitly from the APIC. In one instance using the path ``api/node/mo/uni/infra.xml`` fails, where ``api/node/mo/uni/infra/.xml`` does work correctly. - - More information from: `#35401 aci_rest: change not detected `_ - - **NOTE:** A workaround is to register the task return values (e.g. ``register: this``) and influence when the task should report a change by adding: ``changed_when: this.imdata != []``. + Too many consecutive API calls may result in connection throttling + Starting with ACI v3.1 the APIC will actively throttle password-based authenticated connection rates over a specific treshold. This is as part of an anti-DDOS measure but can act up when using Ansible with ACI using password-based authentication. Currently, one solution is to increase this treshold within the nginx configuration, but using signature-based authentication is recommended. + **NOTE:** It is advisable to use signature-based authentication with ACI as it not only prevents connection-throttling, but also improves general performance when using the ACI modules. -- **Specific requests are known to not be idempotent** - The behaviour of the APIC is inconsistent to the use of ``status="created"`` and ``status="deleted"``. The result is that when you use ``status="created"`` in your payload the resulting tasks are not idempotent and creation will fail when the object was already created. However this is not the case with ``status="deleted"`` where such call to an non-existing object does not cause any failure whatsoever. + Specific requests may not reflect changes correctly (`#35401 `_) + There is a known issue where specific requests to the APIC do not properly reflect changed in the resulting output, even when we request those changes explicitly from the APIC. In one instance using the path ``api/node/mo/uni/infra.xml`` fails, where ``api/node/mo/uni/infra/.xml`` does work correctly. - More information from: `#35050 aci_rest: Using status="created" behaves differently than status="deleted" `_ + **NOTE:** A workaround is to register the task return values (e.g. ``register: this``) and influence when the task should report a change by adding: ``changed_when: this.imdata != []``. - **NOTE:** A workaround is to avoid using ``status="created"`` and instead use ``status="modified"`` when idempotency is essential to your workflow.. + Specific requests are known to not be idempotent (`#35050 `_) + The behaviour of the APIC is inconsistent to the use of ``status="created"`` and ``status="deleted"``. The result is that when you use ``status="created"`` in your payload the resulting tasks are not idempotent and creation will fail when the object was already created. However this is not the case with ``status="deleted"`` where such call to an non-existing object does not cause any failure whatsoever. -- **Setting user password is not idempotent** + **NOTE:** A workaround is to avoid using ``status="created"`` and instead use ``status="modified"`` when idempotency is essential to your workflow.. - Due to an inconsistency in the APIC REST API, a task that sets the password of a locally-authenticated user is not idempotent. The APIC will complain with message ``Password history check: user dag should not use previous 5 passwords``. - More information from: `#35544 aci_aaa_user: Setting user password is not idempotent `_ + Setting user password is not idempotent (`#35544 `_) + Due to an inconsistency in the APIC REST API, a task that sets the password of a locally-authenticated user is not idempotent. The APIC will complain with message ``Password history check: user dag should not use previous 5 passwords``. - **NOTE:** There is no workaround for this issue. + **NOTE:** There is no workaround for this issue. .. _aci_guide_community: diff --git a/lib/ansible/modules/network/aci/aci_aaa_user.py b/lib/ansible/modules/network/aci/aci_aaa_user.py index 3061cbefa16..adde79c6911 100644 --- a/lib/ansible/modules/network/aci/aci_aaa_user.py +++ b/lib/ansible/modules/network/aci/aci_aaa_user.py @@ -17,15 +17,16 @@ module: aci_aaa_user short_description: Manage AAA users (aaa:User) description: - Manage AAA users. -- More information from the internal APIC class I(aaa:User) at - U(https://developer.cisco.com/docs/apic-mim-ref/). -author: -- Dag Wieers (@dagwieers) notes: - This module is not idempotent when C(aaa_password) is being used (even if that password was already set identically). This appears to be an inconsistency wrt. the idempotent nature - of the APIC REST API. + of the APIC REST API. The vendor has been informed. + More information in :ref:`the ACI documentation `. +- More information from the internal APIC class I(aaa:User) at + U(https://developer.cisco.com/docs/apic-mim-ref/). +author: +- Dag Wieers (@dagwieers) requirements: - python-dateutil version_added: '2.5' @@ -246,7 +247,7 @@ def main(): aaa_password=dict(type='str', no_log=True), aaa_password_lifetime=dict(type='int'), aaa_password_update_required=dict(type='bool'), - aaa_user=dict(type='str', required=True, aliases=['name']), + aaa_user=dict(type='str', required=True, aliases=['name']), # Not required for querying all objects clear_password_history=dict(type='bool'), description=dict(type='str', aliases=['descr']), email=dict(type='str'), @@ -306,7 +307,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='aaaUser', class_config=dict( @@ -325,10 +325,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='aaaUser') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_aaa_user_certificate.py b/lib/ansible/modules/network/aci/aci_aaa_user_certificate.py index bc0f822ca21..f82fcf2a4a1 100644 --- a/lib/ansible/modules/network/aci/aci_aaa_user_certificate.py +++ b/lib/ansible/modules/network/aci/aci_aaa_user_certificate.py @@ -16,15 +16,15 @@ DOCUMENTATION = r''' module: aci_aaa_user_certificate short_description: Manage AAA user certificates (aaa:UserCert) description: -- Manage AAA user and appuser certificates. +- Manage AAA user certificates. +notes: +- The C(aaa_user) must exist before using this module in your playbook. + The M(aci_aaa_user) module can be used for this. - More information from the internal APIC class I(aaa:UserCert) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.5' -notes: -- The C(aaa_user) must exist before using this module in your playbook. - The M(aci_aaa_user) module can be used for this. options: aaa_user: description: @@ -212,10 +212,10 @@ ACI_MAPPING = dict( def main(): argument_spec = aci_argument_spec() argument_spec.update( - aaa_user=dict(type='str', required=True), + aaa_user=dict(type='str', required=True), # Not required for querying all objects aaa_user_type=dict(type='str', default='user', choices=['appuser', 'user']), - certificate=dict(type='str', aliases=['cert_data', 'certificate_data']), - certificate_name=dict(type='str', aliases=['cert_name']), + certificate=dict(type='str', aliases=['cert_data', 'certificate_data']), # Not required for querying all objects + certificate_name=dict(type='str', aliases=['cert_name']), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -252,7 +252,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='aaaUserCert', class_config=dict( @@ -261,10 +260,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='aaaUserCert') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_access_port_to_interface_policy_leaf_profile.py b/lib/ansible/modules/network/aci/aci_access_port_to_interface_policy_leaf_profile.py index df5dc461dd2..834b576a09d 100644 --- a/lib/ansible/modules/network/aci/aci_access_port_to_interface_policy_leaf_profile.py +++ b/lib/ansible/modules/network/aci/aci_access_port_to_interface_policy_leaf_profile.py @@ -17,6 +17,7 @@ module: aci_access_port_to_interface_policy_leaf_profile short_description: Manage Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics (infra:HPortS, infra:RsAccBaseGrp, infra:PortBlk) description: - Manage Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(infra:HPortS, infra:RsAccBaseGrp, infra:PortBlk) at U(https://developer.cisco.com/media/mim-ref). author: @@ -36,7 +37,6 @@ options: description: description: - The description to assign to the C(access_port_selector) - required: no leaf_port_blk: description: - The name of the Fabric access policy leaf interface profile access port block. @@ -59,7 +59,6 @@ options: policy_group: description: - The name of the fabric access policy group to be associated with the leaf interface profile interface selector. - required: no aliases: [ policy_group_name ] state: description: @@ -227,8 +226,8 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update({ - 'leaf_interface_profile': dict(type='str', aliases=['leaf_interface_profile_name']), - 'access_port_selector': dict(type='str', aliases=['name', 'access_port_selector_name']), + 'leaf_interface_profile': dict(type='str', aliases=['leaf_interface_profile_name']), # Not required for querying all objects + 'access_port_selector': dict(type='str', aliases=['name', 'access_port_selector_name']), # Not required for querying all objects 'description': dict(typ='str'), 'leaf_port_blk': dict(type='str', aliases=['leaf_port_blk_name']), 'leaf_port_blk_description': dict(type='str'), @@ -277,7 +276,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='infraHPortS', class_config=dict( @@ -292,23 +290,21 @@ def main(): name=leaf_port_blk, fromPort=from_, toPort=to_, - ) - ) + ), + ), ), dict( infraRsAccBaseGrp=dict( attributes=dict( tDn='uni/infra/funcprof/accportgrp-{0}'.format(policy_group), - ) - ) + ), + ), ), ], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraHPortS') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_aep.py b/lib/ansible/modules/network/aci/aci_aep.py index 5a68d08f86b..399886fe9d6 100644 --- a/lib/ansible/modules/network/aci/aci_aep.py +++ b/lib/ansible/modules/network/aci/aci_aep.py @@ -17,13 +17,12 @@ short_description: Manage attachable Access Entity Profile (AEP) on Cisco ACI fa description: - Connect to external virtual and physical domains by using attachable Access Entity Profiles (AEP) on Cisco ACI fabrics. +notes: - More information from the internal APIC classes I(infra:AttEntityP) and I(infra:ProvAcc) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Swetha Chunduri (@schunduri) version_added: '2.4' -requirements: -- ACI Fabric 1.0(3f)+ options: aep: description: @@ -198,7 +197,7 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - aep=dict(type='str', aliases=['name', 'aep_name']), # not required for querying all AEPs + aep=dict(type='str', aliases=['name', 'aep_name']), # Not required for querying all objects description=dict(type='str', aliases=['descr']), infra_vlan=dict(type='bool', aliases=['infrastructure_vlan']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), @@ -237,7 +236,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='infraAttEntityP', class_config=dict( @@ -247,10 +245,8 @@ def main(): child_configs=child_configs, ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraAttEntityP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_aep_to_domain.py b/lib/ansible/modules/network/aci/aci_aep_to_domain.py index 0112a496948..c4785a31ce8 100755 --- a/lib/ansible/modules/network/aci/aci_aep_to_domain.py +++ b/lib/ansible/modules/network/aci/aci_aep_to_domain.py @@ -17,14 +17,14 @@ module: aci_aep_to_domain short_description: Bind AEPs to Physical or Virtual Domains on Cisco ACI fabrics (infra:RsDomP) description: - Bind AEPs to Physical or Virtual Domains on Cisco ACI fabrics. +notes: +- The C(aep) and C(domain) parameters should exist before using this module. + The M(aci_aep) and M(aci_domain) can be used for these. - More information from the internal APIC class I(infra:RsDomP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.5' -notes: -- The C(aep) and C(domain) parameters should exist before using this module. - The M(aci_aep) and M(aci_domain) can be used for these. options: aep: description: @@ -215,9 +215,9 @@ VM_PROVIDER_MAPPING = dict( def main(): argument_spec = aci_argument_spec() argument_spec.update( - aep=dict(type='str', aliases=['aep_name']), - domain=dict(type='str', aliases=['domain_name', 'domain_profile']), - domain_type=dict(type='str', choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm'], aliases=['type']), + aep=dict(type='str', aliases=['aep_name']), # Not required for querying all objects + domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects + domain_type=dict(type='str', choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm'], aliases=['type']), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']), ) @@ -278,16 +278,13 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='infraRsDomP', class_config=dict(tDn=domain_mo), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraRsDomP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_ap.py b/lib/ansible/modules/network/aci/aci_ap.py index 1b5488bb715..e2a4b2c6547 100644 --- a/lib/ansible/modules/network/aci/aci_ap.py +++ b/lib/ansible/modules/network/aci/aci_ap.py @@ -16,15 +16,15 @@ module: aci_ap short_description: Manage top level Application Profile (AP) objects on Cisco ACI fabrics (fv:Ap) description: - Manage top level Application Profile (AP) objects on Cisco ACI fabrics +notes: +- This module does not manage EPGs, see M(aci_epg) to do this. +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(fv:Ap) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Swetha Chunduri (@schunduri) version_added: '2.4' -notes: -- This module does not manage EPGs, see M(aci_epg) to do this. -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: tenant: description: @@ -198,8 +198,8 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - tenant=dict(type='str', aliases=['tenant_name']), # tenant not required for querying all APs - ap=dict(type='str', aliases=['app_profile', 'app_profile_name', 'name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects + ap=dict(type='str', aliases=['app_profile', 'app_profile_name', 'name']), # Not required for querying all objects description=dict(type='str', aliases=['descr'], required=False), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 @@ -215,7 +215,6 @@ def main(): ], ) - # tenant = module.params['tenant'] ap = module.params['ap'] description = module.params['description'] state = module.params['state'] @@ -240,7 +239,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvAp', class_config=dict( @@ -249,10 +247,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvAp') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_bd.py b/lib/ansible/modules/network/aci/aci_bd.py index 36c6d76d5b7..46d44735157 100644 --- a/lib/ansible/modules/network/aci/aci_bd.py +++ b/lib/ansible/modules/network/aci/aci_bd.py @@ -16,14 +16,14 @@ module: aci_bd short_description: Manage Bridge Domains (BD) on Cisco ACI Fabrics (fv:BD) description: - Manages Bridge Domains (BD) on Cisco ACI Fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(fv:BD) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: arp_flooding: description: @@ -319,7 +319,7 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update( arp_flooding=dict(type='bool'), - bd=dict(type='str', aliases=['bd_name', 'name']), + bd=dict(type='str', aliases=['bd_name', 'name']), # Not required for querying all objects bd_type=dict(type='str', choices=['ethernet', 'fc']), description=dict(type='str'), enable_multicast=dict(type='bool'), @@ -337,7 +337,7 @@ def main(): mac_address=dict(type='str', aliases=['mac']), multi_dest=dict(choices=['bd-flood', 'drop', 'encap-flood']), state=dict(choices=['absent', 'present', 'query'], type='str', default='present'), - tenant=dict(type='str', aliases=['tenant_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects vrf=dict(type='str', aliases=['vrf_name']), gateway_ip=dict(type='str', removed_in_version='2.4'), # Deprecated starting from v2.4 scope=dict(type='str', removed_in_version='2.4'), # Deprecated starting from v2.4 @@ -409,7 +409,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='fvBD', class_config=dict( @@ -436,10 +435,8 @@ def main(): ], ) - # generate config diff which will be used as POST request body aci.get_diff(aci_class='fvBD') - # submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_bd_subnet.py b/lib/ansible/modules/network/aci/aci_bd_subnet.py index 29f6d17c2db..1675040810a 100644 --- a/lib/ansible/modules/network/aci/aci_bd_subnet.py +++ b/lib/ansible/modules/network/aci/aci_bd_subnet.py @@ -16,16 +16,16 @@ module: aci_bd_subnet short_description: Manage Subnets on Cisco ACI fabrics (fv:Subnet) description: - Manage Subnets on Cisco ACI fabrics. -- More information from the internal APIC class I(fv:Subnet) at - U(https://developer.cisco.com/docs/apic-mim-ref/). -author: -- Jacob McGill (@jmcgill298) -version_added: '2.4' notes: - The C(gateway) parameter is the root key used to access the Subnet (not name), so the C(gateway) is required when the state is C(absent) or C(present). - The C(tenant) and C(bd) used must exist before using this module in your playbook. The M(aci_tenant) module and M(aci_bd) can be used for these. +- More information from the internal APIC class I(fv:Subnet) at + U(https://developer.cisco.com/docs/apic-mim-ref/). +author: +- Jacob McGill (@jmcgill298) +version_added: '2.4' options: bd: description: @@ -316,11 +316,11 @@ from ansible.module_utils.basic import AnsibleModule, SEQUENCETYPE def main(): argument_spec = aci_argument_spec() argument_spec.update( - bd=dict(type='str', aliases=['bd_name']), + bd=dict(type='str', aliases=['bd_name']), # Not required for querying all objects description=dict(type='str', aliases=['descr']), enable_vip=dict(type='bool'), - gateway=dict(type='str', aliases=['gateway_ip']), - mask=dict(type='int', aliases=['subnet_mask']), + gateway=dict(type='str', aliases=['gateway_ip']), # Not required for querying all objects + mask=dict(type='int', aliases=['subnet_mask']), # Not required for querying all objects subnet_name=dict(type='str', aliases=['name']), nd_prefix_policy=dict(type='str'), preferred=dict(type='bool'), @@ -329,7 +329,7 @@ def main(): scope=dict(type='list', choices=['private', 'public', 'shared']), subnet_control=dict(type='str', choices=['nd_ra', 'no_gw', 'querier_ip', 'unspecified']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), - tenant=dict(type='str', aliases=['tenant_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 protocol=dict(type='str', removed_in_version='2.6'), # Deprecated in v2.6 ) @@ -398,7 +398,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='fvSubnet', class_config=dict( @@ -416,10 +415,8 @@ def main(): ], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvSubnet') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_bd_to_l3out.py b/lib/ansible/modules/network/aci/aci_bd_to_l3out.py index 6f20227d2ce..0de89fe16dd 100644 --- a/lib/ansible/modules/network/aci/aci_bd_to_l3out.py +++ b/lib/ansible/modules/network/aci/aci_bd_to_l3out.py @@ -16,14 +16,14 @@ module: aci_bd_to_l3out short_description: Bind Bridge Domain to L3 Out on Cisco ACI fabrics (fv:RsBDToOut) description: - Bind Bridge Domain to L3 Out on Cisco ACI fabrics. +notes: +- The C(bd) and C(l3out) parameters should exist before using this module. + The M(aci_bd) and M(aci_l3out) can be used for these. - More information from the internal APIC class I(fv:RsBDToOut) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(bd) and C(l3out) parameters should exist before using this module. - The M(aci_bd) and M(aci_l3out) can be used for these. options: bd: description: @@ -162,10 +162,10 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - bd=dict(type='str', aliases=['bd_name', 'bridge_domain']), - l3out=dict(type='str'), + bd=dict(type='str', aliases=['bd_name', 'bridge_domain']), # Not required for querying all objects + l3out=dict(type='str'), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), - tenant=dict(type='str', aliases=['tenant_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 protocol=dict(type='str', removed_in_version='2.6'), # Deprecated in v2.6 ) @@ -210,16 +210,13 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='fvRsBDToOut', class_config=dict(tnL3extOutName=l3out), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvRsBDToOut') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_config_rollback.py b/lib/ansible/modules/network/aci/aci_config_rollback.py index f3464f4d1b8..2774e698a22 100644 --- a/lib/ansible/modules/network/aci/aci_config_rollback.py +++ b/lib/ansible/modules/network/aci/aci_config_rollback.py @@ -17,6 +17,7 @@ short_description: Provides rollback and rollback preview functionality for Cisc description: - Provides rollback and rollback preview functionality for Cisco ACI fabric. - Config Rollbacks are done using snapshots C(aci_snapshot) with the configImportP class. +notes: - More information from the internal APIC class I(config:ImportP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -241,7 +242,6 @@ def main(): aci.get_existing() - # Filter out module parameters with null values aci.payload( aci_class='configImportP', class_config=dict( @@ -256,10 +256,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='configImportP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'preview': diff --git a/lib/ansible/modules/network/aci/aci_config_snapshot.py b/lib/ansible/modules/network/aci/aci_config_snapshot.py index 676989d2624..81b8950829c 100644 --- a/lib/ansible/modules/network/aci/aci_config_snapshot.py +++ b/lib/ansible/modules/network/aci/aci_config_snapshot.py @@ -18,15 +18,15 @@ description: - Manage Config Snapshots on Cisco ACI fabrics. - Creating new Snapshots is done using the configExportP class. - Removing Snapshots is done using the configSnapshot class. +notes: +- The APIC does not provide a mechanism for naming the snapshots. +- 'Snapshot files use the following naming structure: ce_---
T::.+:.' +- 'Snapshot objects use the following naming structure: run---
T--.' - More information from the internal APIC classes I(config:Snapshot) and I(config:ExportP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The APIC does not provide a mechanism for naming the snapshots. -- 'Snapshot files use the following naming structure: ce_---
T::.+:.' -- 'Snapshot objects use the following naming structure: run---
T--.' options: description: description: @@ -215,7 +215,7 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update( description=dict(type='str', aliases=['descr']), - export_policy=dict(type='str', aliases=['name']), + export_policy=dict(type='str', aliases=['name']), # Not required for querying all objects format=dict(type='str', choices=['json', 'xml']), include_secure=dict(type='bool'), max_count=dict(type='int'), @@ -261,7 +261,6 @@ def main(): aci.get_existing() - # Filter out module params with null values aci.payload( aci_class='configExportP', class_config=dict( diff --git a/lib/ansible/modules/network/aci/aci_contract.py b/lib/ansible/modules/network/aci/aci_contract.py index b445e2ba374..373a0faa29e 100644 --- a/lib/ansible/modules/network/aci/aci_contract.py +++ b/lib/ansible/modules/network/aci/aci_contract.py @@ -16,16 +16,16 @@ module: aci_contract short_description: Manage contract resources on Cisco ACI fabrics (vz:BrCP) description: - Manage Contract resources on Cisco ACI fabrics. -- More information from the internal APIC class I(vz:BrCP) at - U(https://developer.cisco.com/docs/apic-mim-ref/). -author: -- Dag Wieers (@dagwieers) -version_added: '2.4' notes: - This module does not manage Contract Subjects, see M(aci_contract_subject) to do this. Contract Subjects can still be removed using this module. - The C(tenant) used must exist before using this module in your playbook. The M(aci_tenant) module can be used for this. +- More information from the internal APIC class I(vz:BrCP) at + U(https://developer.cisco.com/docs/apic-mim-ref/). +author: +- Dag Wieers (@dagwieers) +version_added: '2.4' options: contract: description: @@ -234,8 +234,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ['state', 'absent', ['tenant', 'contract']], - ['state', 'present', ['tenant', 'contract']], + ['state', 'absent', ['contract', 'tenant']], + ['state', 'present', ['contract', 'tenant']], ], ) @@ -266,7 +266,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='vzBrCP', class_config=dict( @@ -278,10 +277,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='vzBrCP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_contract_subject.py b/lib/ansible/modules/network/aci/aci_contract_subject.py index a731a4e3a90..49362b3ef51 100755 --- a/lib/ansible/modules/network/aci/aci_contract_subject.py +++ b/lib/ansible/modules/network/aci/aci_contract_subject.py @@ -16,14 +16,14 @@ module: aci_contract_subject short_description: Manage initial Contract Subjects on Cisco ACI fabrics (vz:Subj) description: - Manage initial Contract Subjects on Cisco ACI fabrics. +notes: +- The C(tenant) and C(contract) used must exist before using this module in your playbook. +- The M(aci_tenant) and M(aci_contract) modules can be used for this. - More information from the internal APIC class I(vz:Subj) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Swetha Chunduri (@schunduri) version_added: '2.4' -notes: -- The C(tenant) and C(contract) used must exist before using this module in your playbook. -- The M(aci_tenant) and M(aci_contract) modules can be used for this. options: tenant: description: @@ -240,9 +240,9 @@ MATCH_MAPPING = dict(all='All', at_least_one='AtleastOne', at_most_one='AtmostOn def main(): argument_spec = aci_argument_spec() argument_spec.update( - contract=dict(type='str', aliases=['contract_name']), - subject=dict(type='str', aliases=['contract_subject', 'name', 'subject_name']), - tenant=dict(type='str', aliases=['tenant_name']), + contract=dict(type='str', aliases=['contract_name']), # Not required for querying all objects + subject=dict(type='str', aliases=['contract_subject', 'name', 'subject_name']), # Not required for querying all objects + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects priority=dict(type='str', choices=['unspecified', 'level1', 'level2', 'level3']), reverse_filter=dict(type='bool'), dscp=dict(type='str', aliases=['target']), @@ -311,7 +311,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='vzSubj', class_config=dict( @@ -325,10 +324,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='vzSubj') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_contract_subject_to_filter.py b/lib/ansible/modules/network/aci/aci_contract_subject_to_filter.py index eb1cf7964c7..b6c98b97f9c 100644 --- a/lib/ansible/modules/network/aci/aci_contract_subject_to_filter.py +++ b/lib/ansible/modules/network/aci/aci_contract_subject_to_filter.py @@ -16,16 +16,14 @@ module: aci_contract_subject_to_filter short_description: Bind Contract Subjects to Filters on Cisco ACI fabrics (vz:RsSubjFiltAtt) description: - Bind Contract Subjects to Filters on Cisco ACI fabrics. +notes: +- The C(tenant), C(contract), C(subject), and C(filter_name) must exist before using this module in your playbook. +- The M(aci_tenant), M(aci_contract), M(aci_contract_subject), and M(aci_filter) modules can be used for these. - More information from the internal APIC class I(vz:RsSubjFiltAtt) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -requirements: -- ACI Fabric 1.0(3f)+ -notes: -- The C(tenant), C(contract), C(subject), and C(filter_name) must exist before using this module in your playbook. -- The M(aci_tenant), M(aci_contract), M(aci_contract_subject), and M(aci_filter) modules can be used for these. options: contract: description: @@ -60,7 +58,6 @@ options: extends_documentation_fragment: aci ''' -# FIXME: Add more, better examples EXAMPLES = r''' - name: Add a new contract subject to filer binding aci_subject_filter_binding: @@ -220,11 +217,11 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - contract=dict(type='str', aliases=['contract_name']), - filter=dict(type='str', aliases=['filter_name']), + contract=dict(type='str', aliases=['contract_name']), # Not required for querying all objects + filter=dict(type='str', aliases=['filter_name']), # Not required for querying all objects log=dict(tyep='str', choices=['log', 'none'], aliases=['directive']), - subject=dict(type='str', aliases=['contract_subject', 'subject_name']), - tenant=dict(type='str', aliases=['tenant_name']), + subject=dict(type='str', aliases=['contract_subject', 'subject_name']), # Not required for querying all objects + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 protocol=dict(type='str', removed_in_version='2.6'), # Deprecated in v2.6 @@ -284,7 +281,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='vzRsSubjFiltAtt', class_config=dict( @@ -293,10 +289,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='vzRsSubjFiltAtt') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_domain.py b/lib/ansible/modules/network/aci/aci_domain.py index 7631ab887e9..3c597d96060 100644 --- a/lib/ansible/modules/network/aci/aci_domain.py +++ b/lib/ansible/modules/network/aci/aci_domain.py @@ -16,6 +16,7 @@ module: aci_domain short_description: Manage physical, virtual, bridged, routed or FC domain profiles (*:DomP) description: - Manage physical, virtual, bridged, routed or FC domain profiles. +notes: - More information from the internal APIC classes I(phys:DomP), I(vmm:DomP), I(l2ext:DomP), I(l3ext:DomP), I(fc:DomP) at U(https://developer.cisco.com/docs/apic-mim-ref/). @@ -259,8 +260,8 @@ def main(): choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42', 'AF43', 'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified'], aliases=['target']), - domain=dict(type='str', aliases=['domain_name', 'domain_profile', 'name']), - domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm'], aliases=['type']), + domain=dict(type='str', aliases=['domain_name', 'domain_profile', 'name']), # Not required for querying all objects + domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm'], aliases=['type']), # Not required for querying all objects encap_mode=dict(type='str', choices=['unknown', 'vlan', 'vxlan']), multicast_address=dict(type='str'), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), @@ -341,7 +342,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class=domain_class, class_config=dict( @@ -353,10 +353,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class=domain_class) - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_domain_to_encap_pool.py b/lib/ansible/modules/network/aci/aci_domain_to_encap_pool.py index fab88aaadc5..9b00cb257a6 100644 --- a/lib/ansible/modules/network/aci/aci_domain_to_encap_pool.py +++ b/lib/ansible/modules/network/aci/aci_domain_to_encap_pool.py @@ -17,14 +17,14 @@ module: aci_domain_to_encap_pool short_description: Bind Domain to Encap Pools on Cisco ACI fabrics (infra:RsVlanNs) description: - Bind Domain to Encap Pools on Cisco ACI fabrics. +notes: +- The C(domain) and C(encap_pool) parameters should exist before using this module. + The M(aci_domain) and M(aci_encap_pool) can be used for these. - More information from the internal APIC class I(infra:RsVlanNs) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.5' -notes: -- The C(domain) and C(encap_pool) parameters should exist before using this module. - The M(aci_domain) and M(aci_encap_pool) can be used for these. options: domain: description: diff --git a/lib/ansible/modules/network/aci/aci_domain_to_vlan_pool.py b/lib/ansible/modules/network/aci/aci_domain_to_vlan_pool.py index 5f30cbccfba..5a81623108a 100755 --- a/lib/ansible/modules/network/aci/aci_domain_to_vlan_pool.py +++ b/lib/ansible/modules/network/aci/aci_domain_to_vlan_pool.py @@ -17,14 +17,14 @@ module: aci_domain_to_vlan_pool short_description: Bind Domain to VLAN Pools on Cisco ACI fabrics (infra:RsVlanNs) description: - Bind Domain to VLAN Pools on Cisco ACI fabrics. +notes: +- The C(domain) and C(vlan_pool) parameters should exist before using this module. + The M(aci_domain) and M(aci_vlan_pool) can be used for these. - More information from the internal APIC class I(infra:RsVlanNs) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.5' -notes: -- The C(domain) and C(vlan_pool) parameters should exist before using this module. - The M(aci_domain) and M(aci_vlan_pool) can be used for these. options: domain: description: @@ -248,9 +248,9 @@ VM_PROVIDER_MAPPING = dict( def main(): argument_spec = aci_argument_spec() argument_spec.update( - domain=dict(type='str', aliases=['domain_name', 'domain_profile']), - domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm']), - pool=dict(type='str', aliases=['pool_name', 'vlan_pool']), + domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects + domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm']), # Not required for querying all objects + pool=dict(type='str', aliases=['pool_name', 'vlan_pool']), # Not required for querying all objects pool_allocation_mode=dict(type='str', required=True, aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']), @@ -324,7 +324,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class=domain_class, class_config=dict(name=domain), @@ -333,10 +332,8 @@ def main(): ] ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class=domain_class) - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_encap_pool.py b/lib/ansible/modules/network/aci/aci_encap_pool.py index f80f6aca44f..d5767291430 100644 --- a/lib/ansible/modules/network/aci/aci_encap_pool.py +++ b/lib/ansible/modules/network/aci/aci_encap_pool.py @@ -16,6 +16,7 @@ module: aci_encap_pool short_description: Manage encap pools on Cisco ACI fabrics (fvns:VlanInstP, fvns:VxlanInstP, fvns:VsanInstP) description: - Manage vlan, vxlan, and vsan pools on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(fvns:VlanInstP), I(fvns:VxlanInstP), and I(fvns:VsanInstP) at U(https://developer.cisco.com/docs/apic-mim-ref/). @@ -218,7 +219,7 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update( description=dict(type='str', aliases=['descr']), - pool=dict(type='str', aliases=['name', 'pool_name']), + pool=dict(type='str', aliases=['name', 'pool_name']), # Not required for querying all objects pool_allocation_mode=dict(type='str', aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']), pool_type=dict(type='str', aliases=['type'], choices=['vlan', 'vxlan', 'vsan'], required=True), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), diff --git a/lib/ansible/modules/network/aci/aci_encap_pool_range.py b/lib/ansible/modules/network/aci/aci_encap_pool_range.py index b6749d8dd68..be22da83655 100644 --- a/lib/ansible/modules/network/aci/aci_encap_pool_range.py +++ b/lib/ansible/modules/network/aci/aci_encap_pool_range.py @@ -16,13 +16,13 @@ module: aci_encap_pool_range short_description: Manage encap ranges assigned to pools on Cisco ACI fabrics (fvns:EncapBlk, fvns:VsanEncapBlk) description: - Manage vlan, vxlan, and vsan ranges that are assigned to pools on Cisco ACI fabrics. +notes: +- The C(pool) must exist in order to add or delete a range. - More information from the internal APIC class I(fvns:EncapBlk) and I(fvns:VsanEncapBlk) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.5' -requirements: -- The C(pool) must exist in order to add or delete a range. options: allocation_mode: description: @@ -252,12 +252,12 @@ def main(): argument_spec.update( allocation_mode=dict(type='str', aliases=['mode'], choices=['dynamic', 'inherit', 'static']), description=dict(type='str', aliases=['descr']), - pool=dict(type='str', aliases=['pool_name']), + pool=dict(type='str', aliases=['pool_name']), # Not required for querying all objects pool_allocation_mode=dict(type='str', aliases=['pool_mode'], choices=['dynamic', 'static']), pool_type=dict(type='str', aliases=['type'], choices=['vlan', 'vxlan', 'vsan'], required=True), - range_end=dict(type='int', aliases=['end']), - range_name=dict(type='str', aliases=["name", "range"]), - range_start=dict(type='int', aliases=["start"]), + range_end=dict(type='int', aliases=['end']), # Not required for querying all objects + range_name=dict(type='str', aliases=["name", "range"]), # Not required for querying all objects + range_start=dict(type='int', aliases=["start"]), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -383,7 +383,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class=aci_range_class, class_config={ @@ -392,13 +391,11 @@ def main(): "from": encap_start, "name": range_name, "to": encap_end, - } + }, ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class=aci_range_class) - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_epg.py b/lib/ansible/modules/network/aci/aci_epg.py index 6017010a1b1..57e5037eaae 100644 --- a/lib/ansible/modules/network/aci/aci_epg.py +++ b/lib/ansible/modules/network/aci/aci_epg.py @@ -16,14 +16,14 @@ module: aci_epg short_description: Manage End Point Groups (EPG) on Cisco ACI fabrics (fv:AEPg) description: - Manage End Point Groups (EPG) on Cisco ACI fabrics. +notes: +- The C(tenant) and C(app_profile) used must exist before using this module in your playbook. + The M(aci_tenant) and M(aci_ap) modules can be used for this. - More information from the internal APIC class I(fv:AEPg) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Swetha Chunduri (@schunduri) version_added: '2.4' -notes: -- The C(tenant) and C(app_profile) used must exist before using this module in your playbook. - The M(aci_tenant) and M(aci_ap) modules can be used for this. options: tenant: description: @@ -270,10 +270,10 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - epg=dict(type='str', aliases=['name', 'epg_name']), + epg=dict(type='str', aliases=['name', 'epg_name']), # Not required for querying all objects bd=dict(type='str', aliases=['bd_name', 'bridge_domain']), - ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), - tenant=dict(type='str', aliases=['tenant_name']), + ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects description=dict(type='str', aliases=['descr']), priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']), intra_epg_isolation=dict(choices=['enforced', 'unenforced']), @@ -331,7 +331,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvAEPg', class_config=dict( @@ -347,10 +346,8 @@ def main(): ], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvAEPg') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_epg_monitoring_policy.py b/lib/ansible/modules/network/aci/aci_epg_monitoring_policy.py index 722bb4906d3..6ad0edbc00b 100644 --- a/lib/ansible/modules/network/aci/aci_epg_monitoring_policy.py +++ b/lib/ansible/modules/network/aci/aci_epg_monitoring_policy.py @@ -16,16 +16,14 @@ module: aci_epg_monitoring_policy short_description: Manage monitoring policies on Cisco ACI fabrics (mon:EPGPol) description: - Manage monitoring policies on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(mon:EPGPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' -requirements: -- ACI Fabric 1.0(3f)+ -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: monitoring_policy: description: @@ -214,7 +212,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='monEPGPol', class_config=dict( @@ -223,10 +220,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='monEPGPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_epg_to_contract.py b/lib/ansible/modules/network/aci/aci_epg_to_contract.py index 01af80528c2..b2e3428c3f2 100644 --- a/lib/ansible/modules/network/aci/aci_epg_to_contract.py +++ b/lib/ansible/modules/network/aci/aci_epg_to_contract.py @@ -16,14 +16,14 @@ module: aci_epg_to_contract short_description: Bind EPGs to Contracts on Cisco ACI fabrics (fv:RsCons and fv:RsProv) description: - Bind EPGs to Contracts on Cisco ACI fabrics. +notes: +- The C(tenant), C(app_profile), C(EPG), and C(Contract) used must exist before using this module in your playbook. + The M(aci_tenant), M(aci_ap), M(aci_epg), and M(aci_contract) modules can be used for this. - More information from the internal APIC classes I(fv:RsCons) and I(fv:RsProv) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(tenant), C(app_profile), C(EPG), and C(Contract) used must exist before using this module in your playbook. - The M(aci_tenant), M(aci_ap), M(aci_epg), and M(aci_contract) modules can be used for this. options: ap: description: @@ -228,14 +228,14 @@ PROVIDER_MATCH_MAPPING = {"all": "All", "at_least_one": "AtleastOne", "at_most_o def main(): argument_spec = aci_argument_spec() argument_spec.update( - ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), - epg=dict(type='str', aliases=['epg_name']), - contract=dict(type='str', aliases=['contract_name']), + ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects + epg=dict(type='str', aliases=['epg_name']), # Not required for querying all objects + contract=dict(type='str', aliases=['contract_name']), # Not required for querying all objects contract_type=dict(type='str', required=True, choices=['consumer', 'provider']), priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']), provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), - tenant=dict(type='str', aliases=['tenant_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 protocol=dict(type='str', removed_in_version='2.6'), # Deprecated in v2.6 ) @@ -297,7 +297,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class=aci_class, class_config=dict( @@ -307,10 +306,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class=aci_class) - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_epg_to_domain.py b/lib/ansible/modules/network/aci/aci_epg_to_domain.py index d801f5306f6..095aa3c99a9 100644 --- a/lib/ansible/modules/network/aci/aci_epg_to_domain.py +++ b/lib/ansible/modules/network/aci/aci_epg_to_domain.py @@ -16,17 +16,17 @@ module: aci_epg_to_domain short_description: Bind EPGs to Domains on Cisco ACI fabrics (fv:RsDomAtt) description: - Bind EPGs to Physical and Virtual Domains on Cisco ACI fabrics. -- More information from the internal APIC class I(fv:RsDomAtt) at - U(https://developer.cisco.com/docs/apic-mim-ref/). -author: -- Jacob McGill (@jmcgill298) -version_added: '2.4' notes: - The C(tenant), C(ap), C(epg), and C(domain) used must exist before using this module in your playbook. The M(aci_tenant) M(aci_ap), M(aci_epg) M(aci_domain) modules can be used for this. - OpenStack VMM domains must not be created using this module. The OpenStack VMM domain is created directly by the Cisco APIC Neutron plugin as part of the installation and configuration. This module can be used to query status of an OpenStack VMM domain. +- More information from the internal APIC class I(fv:RsDomAtt) at + U(https://developer.cisco.com/docs/apic-mim-ref/). +author: +- Jacob McGill (@jmcgill298) +version_added: '2.4' options: allow_useg: description: @@ -271,18 +271,18 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update( allow_useg=dict(type='str', choices=['encap', 'useg']), - ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), + ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects deploy_immediacy=dict(type='str', choices=['immediate', 'on-demand']), - domain=dict(type='str', aliases=['domain_name', 'domain_profile']), - domain_type=dict(type='str', choices=['phys', 'vmm'], aliases=['type']), + domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects + domain_type=dict(type='str', choices=['phys', 'vmm'], aliases=['type']), # Not required for querying all objects encap=dict(type='int'), encap_mode=dict(type='str', choices=['auto', 'vlan', 'vxlan']), - epg=dict(type='str', aliases=['name', 'epg_name']), + epg=dict(type='str', aliases=['name', 'epg_name']), # Not required for querying all objects netflow=dict(type='raw'), # Turn into a boolean in v2.9 primary_encap=dict(type='int'), resolution_immediacy=dict(type='str', choices=['immediate', 'lazy', 'pre-provision']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), - tenant=dict(type='str', aliases=['tenant_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']), method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 protocol=dict(type='str', removed_in_version='2.6'), # Deprecated in v2.6 @@ -366,7 +366,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvRsDomAtt', class_config=dict( @@ -380,10 +379,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvRsDomAtt') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_fabric_node.py b/lib/ansible/modules/network/aci/aci_fabric_node.py index a462c2ce789..bdaa0561485 100644 --- a/lib/ansible/modules/network/aci/aci_fabric_node.py +++ b/lib/ansible/modules/network/aci/aci_fabric_node.py @@ -17,6 +17,7 @@ module: aci_fabric_node short_description: Add a new Fabric Node Member on Cisco ACI fabrics (fabric:NodeIdentP) description: - Add a new Fabric Node Member on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(fabric:NodeIdentP) at U(https://developer.cisco.com/site/aci/docs/apis/apic-mim-ref/). author: @@ -36,7 +37,7 @@ options: switch: description: - Switch Name for the new Fabric Node Member. - aliases: [ switch_name ] + aliases: [ name, switch_name ] description: description: - Description for the new Fabric Node Member. @@ -71,7 +72,108 @@ EXAMPLES = r''' ''' RETURN = r''' -# +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: string + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: string + sample: '?rsp-prop-include=config-only' +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: string + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: string + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: string + sample: https://10.11.12.13/api/mo/uni/tn-production.json ''' from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec @@ -84,12 +186,12 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - pod_id=dict(type='int'), - serial=dict(type='str', aliases=['serial_number']), - node_id=dict(type='int'), - switch=dict(type='str', aliases=['switch_name']), description=dict(type='str', aliases=['descr']), + node_id=dict(type='int'), # Not required for querying all objects + pod_id=dict(type='int'), role=dict(type='str', choices=['leaf', 'spine', 'unspecified'], aliases=['role_name']), + serial=dict(type='str', aliases=['serial_number']), # Not required for querying all objects + switch=dict(type='str', aliases=['name', 'switch_name']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -97,8 +199,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ['state', 'absent', ['serial', 'node_id']], - ['state', 'present', ['serial', 'node_id']], + ['state', 'absent', ['node_id', 'serial']], + ['state', 'present', ['node_id', 'serial']], ], ) @@ -123,31 +225,27 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fabricNodeIdentP', class_config=dict( - dn='uni/controller/nodeidentpol/nodep-{0}'.format(serial), - podId=pod_id, - serial=serial, - nodeId=node_id, + descr=description, name=switch, - role=role, + nodeId=node_id, + podId=pod_id, rn='nodep-{0}'.format(serial), - descr=description, + role=role, + serial=serial, ) ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fabricNodeIdentP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': aci.delete_config() - module.exit_json(**aci.result) + aci.exit_json(**aci.result) if __name__ == "__main__": diff --git a/lib/ansible/modules/network/aci/aci_filter.py b/lib/ansible/modules/network/aci/aci_filter.py index 2949e47b930..8d868c15eba 100644 --- a/lib/ansible/modules/network/aci/aci_filter.py +++ b/lib/ansible/modules/network/aci/aci_filter.py @@ -16,15 +16,15 @@ module: aci_filter short_description: Manages top level filter objects on Cisco ACI fabrics (vz:Filter) description: - Manages top level filter objects on Cisco ACI fabrics. +- This modules does not manage filter entries, see M(aci_filter_entry) for this functionality. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(vz:Filter) at U(https://developer.cisco.com/docs/apic-mim-ref/). -- This modules does not manage filter entries, see M(aci_filter_entry) for this functionality. author: - Dag Wieers (@dagwieers) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: filter: description: @@ -240,7 +240,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='vzFilter', class_config=dict( @@ -249,10 +248,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='vzFilter') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_filter_entry.py b/lib/ansible/modules/network/aci/aci_filter_entry.py index e81f25448bc..1d106ec7402 100644 --- a/lib/ansible/modules/network/aci/aci_filter_entry.py +++ b/lib/ansible/modules/network/aci/aci_filter_entry.py @@ -16,14 +16,14 @@ module: aci_filter_entry short_description: Manage filter entries on Cisco ACI fabrics (vz:Entry) description: - Manage filter entries for a filter on Cisco ACI fabrics. +notes: +- The C(tenant) and C(filter) used must exist before using this module in your playbook. + The M(aci_tenant) and M(aci_filter) modules can be used for this. - More information from the internal APIC class I(vz:Entry) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(tenant) and C(filter) used must exist before using this module in your playbook. - The M(aci_tenant) and M(aci_filter) modules can be used for this. options: arp_flag: description: @@ -247,15 +247,15 @@ def main(): dst_port=dict(type='str'), dst_port_end=dict(type='str'), dst_port_start=dict(type='str'), - entry=dict(type='str', aliases=['entry_name', 'filter_entry', 'name']), + entry=dict(type='str', aliases=['entry_name', 'filter_entry', 'name']), # Not required for querying all objects ether_type=dict(choices=VALID_ETHER_TYPES, type='str'), - filter=dict(type='str', aliases=['filter_name']), + filter=dict(type='str', aliases=['filter_name']), # Not required for querying all objects icmp_msg_type=dict(type='str', choices=VALID_ICMP_TYPES), icmp6_msg_type=dict(type='str', choices=VALID_ICMP6_TYPES), ip_protocol=dict(choices=VALID_IP_PROTOCOLS, type='str'), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), stateful=dict(type='bool'), - tenant=dict(type="str", aliases=['tenant_name']), + tenant=dict(type="str", aliases=['tenant_name']), # Not required for querying all objects ) module = AnsibleModule( @@ -327,7 +327,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='vzEntry', class_config=dict( @@ -344,10 +343,8 @@ def main(): ), ) - # generate config diff which will be used as POST request body aci.get_diff(aci_class='vzEntry') - # submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_firmware_source.py b/lib/ansible/modules/network/aci/aci_firmware_source.py index 52972671b0c..56ff67c464b 100644 --- a/lib/ansible/modules/network/aci/aci_firmware_source.py +++ b/lib/ansible/modules/network/aci/aci_firmware_source.py @@ -17,11 +17,12 @@ module: aci_firmware_source short_description: Manage firmware image sources on Cisco ACI fabrics (firmware:OSource) description: - Manage firmware image sources on Cisco ACI fabrics. -- More information from the internal APIC class I(firmware:OSource) at - U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.5' +notes: +- More information from the internal APIC class I(firmware:OSource) at + U(https://developer.cisco.com/docs/apic-mim-ref/). options: source: description: @@ -241,7 +242,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='firmwareOSource', class_config=dict( @@ -254,10 +254,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='firmwareOSource') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_fc.py b/lib/ansible/modules/network/aci/aci_interface_policy_fc.py index 7b963a81a3e..46ff1b0c945 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_fc.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_fc.py @@ -16,11 +16,12 @@ module: aci_interface_policy_fc short_description: Manage Fibre Channel interface policies on Cisco ACI fabrics (fc:IfPol) description: - Manage ACI Fiber Channel interface policies on Cisco ACI fabrics. -- More information from the internal APIC class I(fc:IfPol) at - U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' +notes: +- More information from the internal APIC class I(fc:IfPol) at + U(https://developer.cisco.com/docs/apic-mim-ref/). options: fc_policy: description: @@ -203,7 +204,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fcIfPol', class_config=dict( @@ -213,10 +213,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fcIfPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_l2.py b/lib/ansible/modules/network/aci/aci_interface_policy_l2.py index 5649ce385ed..c264d9b58c2 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_l2.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_l2.py @@ -16,11 +16,12 @@ module: aci_interface_policy_l2 short_description: Manage Layer 2 interface policies on Cisco ACI fabrics (l2:IfPol) description: - Manage Layer 2 interface policies on Cisco ACI fabrics. -- More information from the internal APIC class I(l2:IfPol) at - U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' +notes: +- More information from the internal APIC class I(l2:IfPol) at + U(https://developer.cisco.com/docs/apic-mim-ref/). options: l2_policy: description: @@ -222,7 +223,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='l2IfPol', class_config=dict( @@ -233,10 +233,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='l2IfPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_leaf_policy_group.py b/lib/ansible/modules/network/aci/aci_interface_policy_leaf_policy_group.py index 8e8700a3d54..3ac7f55e195 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_leaf_policy_group.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_leaf_policy_group.py @@ -17,6 +17,9 @@ module: aci_interface_policy_leaf_policy_group short_description: Add Fabric Interface Policy Leaf Policy Groups on Cisco ACI fabrics. description: - Add Fabric Interface Policy Leaf Policy Groups on Cisco ACI fabrics. +notes: +- When using the module please select the appropriate link_aggregation_type (lag_type). + C(link) for Port Channel(PC), C(node) for Virtual Port Channel(VPC) and C(leaf) for Leaf Access Port Policy Group. - More information from the internal APIC class I(infra:AccBndlGrp), I(infra:AccPortGrp) at U(https://developer.cisco.com/site/aci/docs/apis/apic-mim-ref/). author: @@ -112,7 +115,7 @@ options: extends_documentation_fragment: aci ''' -# TODO: Add query examples +# FIXME: Add query examples EXAMPLES = r''' - name: Create a Port Channel (PC) Interface Policy Group aci_interface_policy_leaf_policy_group: @@ -158,7 +161,7 @@ EXAMPLES = r''' state: absent ''' -RETURN = ''' +RETURN = r''' current: description: The existing configuration from the APIC after the module has finished returned: success @@ -270,11 +273,11 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update({ - 'policy_group': dict(type='str', aliases=['name', 'policy_group_name']), + 'policy_group': dict(type='str', aliases=['name', 'policy_group_name']), # Not required for querying all objects 'description': dict(type='str', aliases=['descr']), # NOTE: Since this module needs to include both infra:AccBndlGrp (for PC and VPC) and infra:AccPortGrp (for leaf access port policy group): # NOTE: I'll allow the user to make the choice here (link(PC), node(VPC), leaf(leaf-access port policy group)) - 'lag_type': dict(type='str', aliases=['lag_type_name'], choices=['leaf', 'link', 'node']), + 'lag_type': dict(type='str', aliases=['lag_type_name'], choices=['leaf', 'link', 'node']), # Not required for querying all objects 'link_level_policy': dict(type='str', aliases=['link_level_policy_name']), 'cdp_policy': dict(type='str', aliases=['cdp_policy_name']), 'mcp_policy': dict(type='str', aliases=['mcp_policy_name']), @@ -371,7 +374,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class=aci_class_name, class_config=class_config_dict, @@ -491,10 +493,8 @@ def main(): ], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class=aci_class_name) - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_leaf_profile.py b/lib/ansible/modules/network/aci/aci_interface_policy_leaf_profile.py index 83f8c875d76..a63f6b29122 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_leaf_profile.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_leaf_profile.py @@ -17,6 +17,7 @@ module: aci_interface_policy_leaf_profile short_description: Manage Fabric interface policy leaf profiles on Cisco ACI fabrics (infra:AccPortP) description: - Manage Fabric interface policy leaf profiles on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(infra:AccPortP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -217,7 +218,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='infraAccPortP', class_config=dict( @@ -226,10 +226,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraAccPortP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_lldp.py b/lib/ansible/modules/network/aci/aci_interface_policy_lldp.py index f49c931689d..9f20b50dd72 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_lldp.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_lldp.py @@ -16,6 +16,7 @@ module: aci_interface_policy_lldp short_description: Manage LLDP interface policies on Cisco ACI fabrics (lldp:IfPol) description: - Manage LLDP interface policies on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(lldp:IfPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -33,13 +34,13 @@ options: aliases: [ descr ] receive_state: description: - - Enable or disable Receive state (FIXME!) + - Enable or disable Receive state. required: yes choices: [ disabled, enabled ] default: enabled transmit_state: description: - - Enable or Disable Transmit state (FIXME!) + - Enable or Disable Transmit state. required: false choices: [ disabled, enabled ] default: enabled @@ -176,7 +177,7 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - lldp_policy=dict(type='str', require=False, aliases=['name']), + lldp_policy=dict(type='str', require=False, aliases=['name']), # Not required for querying all objects description=dict(type='str', aliases=['descr']), receive_state=dict(type='raw'), # Turn into a boolean in v2.9 transmit_state=dict(type='raw'), # Turn into a boolean in v2.9 @@ -214,7 +215,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='lldpIfPol', class_config=dict( @@ -225,10 +225,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='lldpIfPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_mcp.py b/lib/ansible/modules/network/aci/aci_interface_policy_mcp.py index 352df42a939..710f90f60d0 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_mcp.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_mcp.py @@ -16,6 +16,7 @@ module: aci_interface_policy_mcp short_description: Manage MCP interface policies on Cisco ACI fabrics (mcp:IfPol) description: - Manage MCP interface policies on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(mcp:IfPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -204,7 +205,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='mcpIfPol', class_config=dict( @@ -214,10 +214,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='mcpIfPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_port_channel.py b/lib/ansible/modules/network/aci/aci_interface_policy_port_channel.py index a262262be7e..e1b47122b8b 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_port_channel.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_port_channel.py @@ -16,6 +16,7 @@ module: aci_interface_policy_port_channel short_description: Manage port channel interface policies on Cisco ACI fabrics (lacp:LagPol) description: - Manage port channel interface policies on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(lacp:LagPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -288,7 +289,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='lacpLagPol', class_config=dict( @@ -301,10 +301,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='lacpLagPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_policy_port_security.py b/lib/ansible/modules/network/aci/aci_interface_policy_port_security.py index 2a2f0f956dc..402649852d5 100644 --- a/lib/ansible/modules/network/aci/aci_interface_policy_port_security.py +++ b/lib/ansible/modules/network/aci/aci_interface_policy_port_security.py @@ -16,6 +16,7 @@ module: aci_interface_policy_port_security short_description: Manage port security on Cisco ACI fabrics (l2:PortSecurityPol) description: - Manage port security on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(l2:PortSecurityPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -204,7 +205,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='l2PortSecurityPol', class_config=dict( @@ -214,10 +214,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='l2PortSecurityPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_interface_selector_to_switch_policy_leaf_profile.py b/lib/ansible/modules/network/aci/aci_interface_selector_to_switch_policy_leaf_profile.py index 910caef2c80..c1bb36c3eb9 100644 --- a/lib/ansible/modules/network/aci/aci_interface_selector_to_switch_policy_leaf_profile.py +++ b/lib/ansible/modules/network/aci/aci_interface_selector_to_switch_policy_leaf_profile.py @@ -17,15 +17,13 @@ module: aci_interface_selector_to_switch_policy_leaf_profile short_description: Associates an Interface Selector Profile to a Switch Policy Leaf Profile (infra:RsAccPortP) description: - Associates an Interface Profile (Selector) to a Switch Policy Leaf Profile on Cisco ACI fabrics. +notes: +- This module requires an existing leaf profile, the module M(aci_switch_policy_leaf_profile) can be used for this. - More information from the internal APIC class I(infra:RsAccPortP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Bruno Calogero (@brunocalogero) version_added: '2.5' -notes: -- This module can be used with M(aci_switch_policy_leaf_profile). - One first creates a leaf profile (infra:NodeP), - Finally, associates an interface profile using the provided interface selector profile (infra:RsAccPortP) options: leaf_profile: description: @@ -185,8 +183,8 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - leaf_profile=dict(type='str', aliases=['leaf_profile_name']), - interface_selector=dict(type='str', aliases=['name', 'interface_selector_name', 'interface_profile_name']), + leaf_profile=dict(type='str', aliases=['leaf_profile_name']), # Not required for querying all objects + interface_selector=dict(type='str', aliases=['interface_profile_name', 'interface_selector_name', 'name']), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']) ) @@ -226,16 +224,13 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='infraRsAccPortP', - class_config=dict(tDn=interface_selector_tDn) + class_config=dict(tDn=interface_selector_tDn), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraRsAccPortP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_l3out_route_tag_policy.py b/lib/ansible/modules/network/aci/aci_l3out_route_tag_policy.py index ee7ad13a071..9b5f979ff87 100644 --- a/lib/ansible/modules/network/aci/aci_l3out_route_tag_policy.py +++ b/lib/ansible/modules/network/aci/aci_l3out_route_tag_policy.py @@ -16,14 +16,14 @@ module: aci_l3out_route_tag_policy short_description: Manage route tag policies on Cisco ACI fabrics (l3ext:RouteTagPol) description: - Manage route tag policies on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(l3ext:RouteTagPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: rtp: description: @@ -219,7 +219,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='l3extRouteTagPol', class_config=dict( @@ -228,10 +227,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='l3extRouteTagPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_rest.py b/lib/ansible/modules/network/aci/aci_rest.py index 8627815f57a..f64a94049d6 100644 --- a/lib/ansible/modules/network/aci/aci_rest.py +++ b/lib/ansible/modules/network/aci/aci_rest.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2017, Dag Wieers (@dagwieers) # 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 @@ -16,6 +17,15 @@ module: aci_rest short_description: Direct access to the Cisco APIC REST API description: - Enables the management of the Cisco ACI fabric through direct access to the Cisco APIC REST API. +- Thanks to the idempotent nature of the APIC, this module is idempotent and reports changes. +notes: +- Certain payloads are known not to be idempotent, so be careful when constructing payloads, + e.g. using C(status="created") will cause idempotency issues, use C(status="modified") instead. + More information in :ref:`the ACI documentation `. +- Certain payloads (and used paths) are known to report no changes happened when changes did happen. + This is a known APIC problem and has been reported to the vendor. A workaround for this issue exists. + More information in :ref:`the ACI documentation `. +- XML payloads require the C(lxml) and C(xmljson) python libraries. For JSON payloads nothing special is needed. - More information regarding the Cisco APIC REST API is available from U(http://www.cisco.com/c/en/us/td/docs/switches/datacenter/aci/apic/sw/2-x/rest_cfg/2_1_x/b_Cisco_APIC_REST_API_Configuration_Guide.html). author: @@ -25,7 +35,6 @@ requirements: - lxml (when using XML payload) - xmljson >= 0.1.8 (when using XML payload) - python 2.7+ (when using xmljson) -extends_documentation_fragment: aci options: method: description: @@ -52,14 +61,7 @@ options: - Name of the absolute path of the filname that includes the body of the http request being sent to the ACI fabric. aliases: [ config_file ] -notes: -- Certain payloads are known not to be idempotent, so be careful when constructing payloads, - e.g. using C(status="created") will cause idempotency issues, use C(status="modified") instead. - More information at U(https://github.com/ansible/community/wiki/Network:-ACI-Documentation#known-issues) -- Certain payloads (or used paths) are known to report no changes happened when changes did happen. - This is a known APIC problem and has been reported to the vendor. - More information at U(https://github.com/ansible/community/wiki/Network:-ACI-Documentation#known-issues) -- XML payloads require the C(lxml) and C(xmljson) python libraries. For JSON payloads nothing special is needed. +extends_documentation_fragment: aci ''' EXAMPLES = r''' @@ -313,8 +315,8 @@ def main(): mutually_exclusive=[['content', 'src']], ) - path = module.params['path'] content = module.params['content'] + path = module.params['path'] src = module.params['src'] # Report missing file @@ -380,15 +382,16 @@ def main(): if aci.params['private_key'] is not None: aci.cert_auth(path=path, payload=payload) + aci.method = aci.params['method'].upper() + # Perform request resp, info = fetch_url(module, aci.url, data=payload, headers=aci.headers, - method=aci.params['method'].upper(), + method=aci.method, timeout=aci.params['timeout'], use_proxy=aci.params['use_proxy']) - aci.method = aci.params['method'].upper() aci.response = info['msg'] aci.status = info['status'] diff --git a/lib/ansible/modules/network/aci/aci_static_binding_to_epg.py b/lib/ansible/modules/network/aci/aci_static_binding_to_epg.py index 5b54f57512b..52dd61b67e1 100644 --- a/lib/ansible/modules/network/aci/aci_static_binding_to_epg.py +++ b/lib/ansible/modules/network/aci/aci_static_binding_to_epg.py @@ -17,14 +17,14 @@ module: aci_static_binding_to_epg short_description: Bind static paths to EPGs on Cisco ACI fabrics (fv:RsPathAtt) description: - Bind static paths to EPGs on Cisco ACI fabrics. +notes: +- The C(tenant), C(ap), C(epg) used must exist before using this module in your playbook. + The M(aci_tenant), M(aci_ap), M(aci_epg) modules can be used for this. - More information from the internal APIC classes I(fv:RsPathAtt) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Bruno Calogero (@brunocalogero) version_added: '2.5' -notes: -- The C(tenant), C(ap), C(epg) used must exist before using this module in your playbook. - The M(aci_tenant), M(aci_ap), M(aci_epg) modules can be used for this. options: tenant: description: @@ -59,27 +59,31 @@ options: interface_mode: description: - Determines how layer 2 tags will be read from and added to frames. + - Values C(802.1p) and C(native) are identical. + - Values C(access) and C(untagged) are identical. + - Values C(regular), C(tagged) and C(trunk) are identical. - The APIC defaults the mode to C(trunk). - choices: [ untagged, 802.1p, trunk, regular, native, tagged, access ] + choices: [ 802.1p, access, native, regular, tagged, trunk, untagged ] default: trunk - aliases: [ mode, interface_mode_name ] + aliases: [ interface_mode_name, mode ] interface_type: description: - The type of interface for the static EPG deployement. - The APIC defaults the C(interface_type) to C(switch_port). - choices: [ switch_port, vpc, port_channel, fex ] + choices: [ fex, port_channel, switch_port, vpc ] default: switch_port - pod: + pod_id: description: - The pod number part of the tDn. - - C(pod) is usually an integer below 10. - aliases: [ pod_number ] + - C(pod_id) is usually an integer below 10. + aliases: [ pod, pod_number ] leafs: description: - The switch ID(s) that the C(interface) belongs to. - When C(interface_type) is C(switch_port), C(port_channel), or C(fex), then C(leafs) is a string of the leaf ID. - When C(interface_type) is C(vpc), then C(leafs) is a list with both leaf IDs. - aliases: [ paths, leaves, nodes, switches ] + - The C(leafs) value is usually something like '101' or '101-102' depending on C(connection_type). + aliases: [ leaves, nodes, paths, switches ] interface: description: - The C(interface) string value part of the tDn. @@ -109,9 +113,9 @@ EXAMPLES = r''' epg: accessport_epg1 encap_id: 222 deploy_immediacy: lazy - interface_mode: access + interface_mode: untagged interface_type: switch_port - pod: 1 + pod_id: 1 leafs: 101 interface: '1/7' state: present @@ -231,22 +235,18 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - tenant=dict(type='str', aliases=['tenant_name']), - ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), - epg=dict(type='str', aliases=['epg_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects + ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects + epg=dict(type='str', aliases=['epg_name']), # Not required for querying all objects encap_id=dict(type='int', aliases=['vlan', 'vlan_id']), primary_encap_id=dict(type='int', aliases=['primary_vlan', 'primary_vlan_id']), deploy_immediacy=dict(type='str', choices=['immediate', 'lazy']), - interface_mode=dict(type='str', choices=['untagged', '802.1p', 'trunk', 'regular', 'native', 'tagged', 'access'], - aliases=['mode', 'interface_mode_name']), - interface_type=dict(type='str', choices=['switch_port', 'vpc', 'port_channel', 'fex'], required=True), - # NOTE: C(pod) is usually an integer below 10. - pod=dict(type='int', aliases=['pod_number']), - # NOTE: C(leafs) is usually something like '101' or '101-102' depending on C(connection_type). - leafs=dict(type='list', aliases=['paths', 'leaves', 'nodes', 'switches']), - # NOTE: C(interface) is usually a policy group like: "test-IntPolGrp" or an interface of the following format: "1/7" depending on C(interface_type). + interface_mode=dict(type='str', choices=['802.1p', 'access', 'native', 'regular', 'tagged', 'trunk', 'untagged'], + aliases=['interface_mode_name', 'mode']), + interface_type=dict(type='str', default='switch_port', choices=['fex', 'port_channel', 'switch_port', 'vpc']), + pod_id=dict(type='int', aliases=['pod', 'pod_number']), # Not required for querying all objects + leafs=dict(type='list', aliases=['leaves', 'nodes', 'paths', 'switches']), interface=dict(type='str'), - # NOTE: C(extpaths) is only used if C(interface_type) is C(fex), it is usually something like '1011'(int) extpaths=dict(type='int'), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -255,9 +255,9 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ['state', 'absent', ['tenant', 'ap', 'epg', 'interface_type', 'pod', 'leafs', 'interface']], - ['state', 'present', ['tenant', 'ap', 'epg', 'encap_id', 'interface_type', 'pod', 'leafs', 'interface']], ['interface_type', 'fex', ['extpaths']], + ['state', 'absent', ['ap', 'epg', 'interface', 'leafs', 'pod_id', 'tenant']], + ['state', 'present', ['ap', 'encap_id', 'epg', 'interface', 'leafs', 'pod_id', 'tenant']], ], ) @@ -269,7 +269,7 @@ def main(): deploy_immediacy = module.params['deploy_immediacy'] interface_mode = module.params['interface_mode'] interface_type = module.params['interface_type'] - pod = module.params['pod'] + pod_id = module.params['pod_id'] # Users are likely to use integers for leaf IDs, which would raise an exception when using the join method leafs = [str(leaf) for leaf in module.params['leafs']] if leafs is not None: @@ -304,23 +304,20 @@ def main(): module.fail_json(msg='Valid VLAN assigments are from 1 to 4096') INTERFACE_MODE_MAPPING = { + '802.1p': 'native', 'access': 'untagged', - 'untagged': 'untagged', + 'native': 'native', + 'regular': 'regular', 'tagged': 'regular', 'trunk': 'regular', - 'regular': 'regular', - '802.1p': 'native', - 'native': 'native', + 'untagged': 'untagged', } + INTERFACE_TYPE_MAPPING = dict( - # NOTE: C(interface) can be a policy group like: 'test-IntPolGrp' or of following format: '1/7', C(leafs) can only be something like '101' - switch_port='topology/pod-{0}/paths-{1}/pathep-[eth{2}]'.format(pod, leafs, interface), - # NOTE: C(interface) can be a policy group like: 'test-IntPolGrp' or of following format: '1/7', C(leafs) can only be something like '101' - port_channel='topology/pod-{0}/paths-{1}/pathep-[eth{2}]'.format(pod, leafs, interface), - # NOTE: C(interface) can be a policy group like: 'test-IntPolGrp', C(leafs) can be something like '101-102' - vpc='topology/pod-{0}/protpaths-{1}/pathep-[{2}]'.format(pod, leafs, interface), - # NOTE: C(interface) can be of the following format: '1/7', C(leafs) can only be like '101', C(extpaths) can only be like '1011' - fex='topology/pod-{0}/paths-{1}/extpaths-{2}/pathep-[eth{3}]'.format(pod, leafs, extpaths, interface), + fex='topology/pod-{0}/paths-{1}/extpaths-{2}/pathep-[eth{3}]'.format(pod_id, leafs, extpaths, interface), + port_channel='topology/pod-{0}/paths-{1}/pathep-[eth{2}]'.format(pod_id, leafs, interface), + switch_port='topology/pod-{0}/paths-{1}/pathep-[eth{2}]'.format(pod_id, leafs, interface), + vpc='topology/pod-{0}/protpaths-{1}/pathep-[{2}]'.format(pod_id, leafs, interface), ) static_path = INTERFACE_TYPE_MAPPING[interface_type] @@ -358,7 +355,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvRsPathAtt', class_config=dict( @@ -370,10 +366,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvRsPathAtt') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_switch_leaf_selector.py b/lib/ansible/modules/network/aci/aci_switch_leaf_selector.py index b96005861d6..7d410c178ce 100644 --- a/lib/ansible/modules/network/aci/aci_switch_leaf_selector.py +++ b/lib/ansible/modules/network/aci/aci_switch_leaf_selector.py @@ -17,14 +17,14 @@ module: aci_switch_leaf_selector short_description: Add a leaf Selector with Node Block Range and Policy Group to a Switch Policy Leaf Profile on Cisco ACI fabrics description: - Add a leaf Selector with Node Block range and Policy Group to a Switch Policy Leaf Profile on Cisco ACI fabrics. +notes: +- This module is to be used with M(aci_switch_policy_leaf_profile) + One first creates a leaf profile (infra:NodeP) and then creates an associated selector (infra:LeafS), - More information from the internal APIC class I(infra:LeafS), I(infra:NodeBlk), I(infra:RsAccNodePGrp) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Bruno Calogero (@brunocalogero) version_added: '2.5' -notes: -- This module is to be used with M(aci_switch_policy_leaf_profile) - One first creates a leaf profile (infra:NodeP) and then creates an associated selector (infra:LeafS), options: description: description: @@ -223,8 +223,8 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update({ 'description': dict(type='str'), - 'leaf_profile': dict(type='str', aliases=['leaf_profile_name']), - 'leaf': dict(type='str', aliases=['name', 'leaf_name', 'leaf_profile_leaf_name', 'leaf_selector_name']), + 'leaf_profile': dict(type='str', aliases=['leaf_profile_name']), # Not required for querying all objects + 'leaf': dict(type='str', aliases=['name', 'leaf_name', 'leaf_profile_leaf_name', 'leaf_selector_name']), # Not required for querying all objects 'leaf_node_blk': dict(type='str', aliases=['leaf_node_blk_name', 'node_blk_name']), 'leaf_node_blk_description': dict(type='str'), 'from': dict(type='int', aliases=['node_blk_range_from', 'from_range', 'range_from']), @@ -268,14 +268,13 @@ def main(): module_object=leaf, ), # NOTE: infraNodeBlk is not made into a subclass because there is a 1-1 mapping between node block and leaf selector name - child_classes=['infraNodeBlk', 'infraRsAccNodePGrp'] + child_classes=['infraNodeBlk', 'infraRsAccNodePGrp'], ) aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='infraLeafS', class_config=dict( @@ -290,23 +289,21 @@ def main(): name=leaf_node_blk, from_=from_, to_=to_, - ) - ) + ), + ), ), dict( infraRsAccNodePGrp=dict( attributes=dict( tDn='uni/infra/funcprof/accnodepgrp-{0}'.format(policy_group), - ) - ) + ), + ), ), ], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraLeafS') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_switch_policy_leaf_profile.py b/lib/ansible/modules/network/aci/aci_switch_policy_leaf_profile.py index a627bf5b838..882c425314a 100644 --- a/lib/ansible/modules/network/aci/aci_switch_policy_leaf_profile.py +++ b/lib/ansible/modules/network/aci/aci_switch_policy_leaf_profile.py @@ -17,6 +17,7 @@ module: aci_switch_policy_leaf_profile short_description: Create switch policy leaf profiles on Cisco ACI fabrics (infra:NodeP) description: - Create switch policy leaf profiles on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(infra:NodeP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -26,7 +27,7 @@ options: leaf_profile: description: - The name of the Leaf Profile. - aliases: [ name, leaf_profile_name ] + aliases: [ leaf_profile_name, name ] description: description: - Description for the Leaf Profile. @@ -179,7 +180,7 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - leaf_profile=dict(type='str', aliases=['name', 'leaf_profile_name']), + leaf_profile=dict(type='str', aliases=['name', 'leaf_profile_name']), # Not required for querying all objects description=dict(type='str', aliases=['descr']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -203,26 +204,23 @@ def main(): aci_class='infraNodeP', aci_rn='infra/nprof-{0}'.format(leaf_profile), filter_target='eq(infraNodeP.name, "{0}")'.format(leaf_profile), - module_object=leaf_profile - ) + module_object=leaf_profile, + ), ) aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='infraNodeP', class_config=dict( name=leaf_profile, descr=description, - ) + ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='infraNodeP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_switch_policy_vpc_protection_group.py b/lib/ansible/modules/network/aci/aci_switch_policy_vpc_protection_group.py index 8579b154452..081da4e0193 100644 --- a/lib/ansible/modules/network/aci/aci_switch_policy_vpc_protection_group.py +++ b/lib/ansible/modules/network/aci/aci_switch_policy_vpc_protection_group.py @@ -17,6 +17,7 @@ module: aci_switch_policy_vpc_protection_group short_description: Create switch policy Explicit vPC Protection Group on Cisco ACI fabrics (fabric:ExplicitGEp, fabric:NodePEp). description: - Create switch policy Explicit vPC Protection Group on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(fabric:ExplicitGEp) and I(fabric:NodePEp) at U(https://developer.cisco.com/site/aci/docs/apis/apic-mim-ref/). author: @@ -188,7 +189,7 @@ from ansible.module_utils.basic import AnsibleModule def main(): argument_spec = aci_argument_spec() argument_spec.update( - protection_group=dict(type='str', aliases=['name', 'protection_group_name']), + protection_group=dict(type='str', aliases=['name', 'protection_group_name']), # Not required for querying all objects protection_group_id=dict(type='int', aliases=['id']), vpc_domain_policy=dict(type='str', aliases=['vpc_domain_policy_name']), switch_1_id=dict(type='int'), @@ -226,7 +227,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fabricExplicitGEp', class_config=dict( @@ -261,10 +261,8 @@ def main(): ], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fabricExplicitGEp') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_taboo_contract.py b/lib/ansible/modules/network/aci/aci_taboo_contract.py index 292ab9eaeb9..02db78c5856 100644 --- a/lib/ansible/modules/network/aci/aci_taboo_contract.py +++ b/lib/ansible/modules/network/aci/aci_taboo_contract.py @@ -17,14 +17,14 @@ module: aci_taboo_contract short_description: Manage taboo contracts on Cisco ACI fabrics (vz:BrCP) description: - Manage taboo contracts on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(vz:BrCP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: taboo_contract: description: @@ -246,7 +246,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='vzTaboo', class_config=dict( @@ -256,10 +255,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='vzTaboo') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_tenant.py b/lib/ansible/modules/network/aci/aci_tenant.py index 8428de946d6..2efcfae6e76 100644 --- a/lib/ansible/modules/network/aci/aci_tenant.py +++ b/lib/ansible/modules/network/aci/aci_tenant.py @@ -16,6 +16,7 @@ module: aci_tenant short_description: Manage tenants on Cisco ACI fabrics (fv:Tenant) description: - Manage tenants on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(fv:Tenant) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -202,9 +203,9 @@ def main(): ], ) - tenant = module.params['tenant'] description = module.params['description'] state = module.params['state'] + tenant = module.params['tenant'] aci = ACIModule(module) aci.construct_url( @@ -218,7 +219,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvTenant', class_config=dict( @@ -227,10 +227,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvTenant') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_tenant_action_rule_profile.py b/lib/ansible/modules/network/aci/aci_tenant_action_rule_profile.py index bf150d070cf..1877ab9f689 100644 --- a/lib/ansible/modules/network/aci/aci_tenant_action_rule_profile.py +++ b/lib/ansible/modules/network/aci/aci_tenant_action_rule_profile.py @@ -16,14 +16,14 @@ module: aci_tenant_action_rule_profile short_description: Manage action rule profiles on Cisco ACI fabrics (rtctrl:AttrP) description: - Manage action rule profiles on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(rtctrl:AttrP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: action_rule: description: @@ -210,20 +210,16 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='rtctrlAttrP', class_config=dict( name=action_rule, descr=description, ), - ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='rtctrlAttrP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_tenant_ep_retention_policy.py b/lib/ansible/modules/network/aci/aci_tenant_ep_retention_policy.py index 8f832835a5d..3e5cf7ef113 100755 --- a/lib/ansible/modules/network/aci/aci_tenant_ep_retention_policy.py +++ b/lib/ansible/modules/network/aci/aci_tenant_ep_retention_policy.py @@ -16,14 +16,14 @@ module: aci_tenant_ep_retention_policy short_description: Manage End Point (EP) retention protocol policies on Cisco ACI fabrics (fv:EpRetPol) description: - Manage End Point (EP) retention protocol policies on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(fv:EpRetPol) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Swetha Chunduri (@schunduri) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: tenant: description: @@ -231,7 +231,7 @@ BOUNCE_TRIG_MAPPING = dict(coop='protocol', rarp='rarp-flood') def main(): argument_spec = aci_argument_spec() argument_spec.update( - tenant=dict(type='str', aliases=['tenant_name']), # not required for querying all EPRs + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects epr_policy=dict(type='str', aliases=['epr_name', 'name']), bounce_age=dict(type='int'), bounce_trigger=dict(type='str', choices=['coop', 'flood']), @@ -304,7 +304,6 @@ def main(): aci.get_existing() if state == 'present': - # filter out module parameters with null values aci.payload( aci_class='fvEpRetPol', class_config=dict( @@ -319,10 +318,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvEpRetPol') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_tenant_span_dst_group.py b/lib/ansible/modules/network/aci/aci_tenant_span_dst_group.py index 13c9e71d2a3..e05e1e4ff03 100644 --- a/lib/ansible/modules/network/aci/aci_tenant_span_dst_group.py +++ b/lib/ansible/modules/network/aci/aci_tenant_span_dst_group.py @@ -16,14 +16,14 @@ module: aci_tenant_span_dst_group short_description: Manage SPAN destination groups on Cisco ACI fabrics (span:DestGrp) description: - Manage SPAN destination groups on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(span:DestGrp) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Dag Wieers (@dagwieers) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: dst_group: description: @@ -212,7 +212,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='spanDestGrp', class_config=dict( @@ -221,10 +220,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='spanDestGrp') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_tenant_span_src_group.py b/lib/ansible/modules/network/aci/aci_tenant_span_src_group.py index c1604494227..d6560313b79 100755 --- a/lib/ansible/modules/network/aci/aci_tenant_span_src_group.py +++ b/lib/ansible/modules/network/aci/aci_tenant_span_src_group.py @@ -16,14 +16,14 @@ module: aci_tenant_span_src_group short_description: Manage SPAN source groups on Cisco ACI fabrics (span:SrcGrp) description: - Manage SPAN source groups on Cisco ACI fabrics. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(span:SrcGrp) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: admin_state: description: @@ -225,7 +225,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='spanSrcGrp', class_config=dict( @@ -236,10 +235,8 @@ def main(): child_configs=[{'spanSpanLbl': {'attributes': {'name': dst_group}}}], ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='spanSrcGrp') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_tenant_span_src_group_to_dst_group.py b/lib/ansible/modules/network/aci/aci_tenant_span_src_group_to_dst_group.py index 168280e161e..2688754e2ee 100755 --- a/lib/ansible/modules/network/aci/aci_tenant_span_src_group_to_dst_group.py +++ b/lib/ansible/modules/network/aci/aci_tenant_span_src_group_to_dst_group.py @@ -16,14 +16,14 @@ module: aci_tenant_span_src_group_to_dst_group short_description: Manage SPAN source group to destination group bindings on Cisco ACI fabrics (span:SpanLbl) description: - Manage SPAN source groups' associated destinaton group on Cisco ACI fabrics. +notes: +- The C(tenant), C(src_group), and C(dst_group) must exist before using this module in your playbook. + The M(aci_tenant), M(aci_tenant_span_src_group), and M(aci_tenant_span_dst_group) modules can be used for this. - More information from the internal APIC class I(span:SrcGrp) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(tenant), C(src_group), and C(dst_group) must exist before using this module in your playbook. - The M(aci_tenant), M(aci_tenant_span_src_group), and M(aci_tenant_span_dst_group) modules can be used for this. options: description: description: @@ -172,10 +172,10 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update( description=dict(type='str', aliases=['descr']), - dst_group=dict(type='str'), - src_group=dict(type='str'), + dst_group=dict(type='str'), # Not required for querying all objects + src_group=dict(type='str'), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), - tenant=dict(type='str', aliases=['tenant_name']), + tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 protocol=dict(type='str', removed_in_version='2.6'), # Deprecated in v2.6 ) @@ -220,7 +220,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='spanSpanLbl', class_config=dict( @@ -229,10 +228,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='spanSpanLbl') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_vlan_pool.py b/lib/ansible/modules/network/aci/aci_vlan_pool.py index fdecbb7217b..79526ae1c64 100644 --- a/lib/ansible/modules/network/aci/aci_vlan_pool.py +++ b/lib/ansible/modules/network/aci/aci_vlan_pool.py @@ -18,6 +18,7 @@ module: aci_vlan_pool short_description: Manage VLAN pools on Cisco ACI fabrics (fvns:VlanInstP) description: - Manage VLAN pools on Cisco ACI fabrics. +notes: - More information from the internal APIC class I(fvns:VlanInstP) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: @@ -197,7 +198,7 @@ def main(): argument_spec = aci_argument_spec() argument_spec.update( description=dict(type='str', aliases=['descr']), - pool=dict(type='str', aliases=['name', 'pool_name']), + pool=dict(type='str', aliases=['name', 'pool_name']), # Not required for querying all objects pool_allocation_mode=dict(type='str', aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -238,20 +239,17 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvnsVlanInstP', class_config=dict( allocMode=pool_allocation_mode, descr=description, name=pool, - ) + ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvnsVlanInstP') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_vlan_pool_encap_block.py b/lib/ansible/modules/network/aci/aci_vlan_pool_encap_block.py index d7f6b701283..730d6e76f11 100644 --- a/lib/ansible/modules/network/aci/aci_vlan_pool_encap_block.py +++ b/lib/ansible/modules/network/aci/aci_vlan_pool_encap_block.py @@ -18,14 +18,14 @@ module: aci_vlan_pool_encap_block short_description: Manage encap blocks assigned to VLAN pools on Cisco ACI fabrics (fvns:EncapBlk) description: - Manage VLAN encap blocks that are assigned to VLAN pools on Cisco ACI fabrics. +notes: +- The C(pool) must exist in order to add or delete a encap block. - More information from the internal APIC class I(fvns:EncapBlk) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) - Dag Wieers (@dagwieers) version_added: '2.5' -requirements: -- The C(pool) must exist in order to add or delete a encap block. options: allocation_mode: description: @@ -227,11 +227,11 @@ def main(): argument_spec.update( allocation_mode=dict(type='str', aliases=['mode'], choices=['dynamic', 'inherit', 'static']), description=dict(type='str', aliases=['descr']), - pool=dict(type='str', aliases=['pool_name']), + pool=dict(type='str', aliases=['pool_name']), # Not required for querying all objects pool_allocation_mode=dict(type='str', aliases=['pool_mode'], choices=['dynamic', 'static']), - block_name=dict(type='str', aliases=['name']), - block_end=dict(type='int', aliases=['end']), - block_start=dict(type='int', aliases=["start"]), + block_name=dict(type='str', aliases=['name']), # Not required for querying all objects + block_end=dict(type='int', aliases=['end']), # Not required for querying all objects + block_start=dict(type='int', aliases=["start"]), # Not required for querying all objects state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) @@ -327,7 +327,6 @@ def main(): aci.get_existing() if state == 'present': - # Filter out module parameters with null values aci.payload( aci_class='fvnsEncapBlk', class_config={ @@ -336,13 +335,11 @@ def main(): "from": encap_start, "name": block_name, "to": encap_end, - } + }, ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvnsEncapBlk') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/modules/network/aci/aci_vrf.py b/lib/ansible/modules/network/aci/aci_vrf.py index d2a2afc3f2b..c7bec9bc224 100644 --- a/lib/ansible/modules/network/aci/aci_vrf.py +++ b/lib/ansible/modules/network/aci/aci_vrf.py @@ -17,14 +17,14 @@ short_description: Manage VRF (private networks aka. contexts) on Cisco ACI fabr description: - Manage VRF (private networks aka. contexts) on Cisco ACI fabrics. - Each context is a private network associated to a tenant, i.e. VRF. +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(aci_tenant) module can be used for this. - More information from the internal APIC class I(fv:Ctx) at U(https://developer.cisco.com/docs/apic-mim-ref/). author: - Jacob McGill (@jmcgill298) version_added: '2.4' -notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(aci_tenant) module can be used for this. options: tenant: description: @@ -247,10 +247,10 @@ def main(): module_object=vrf, ), ) + aci.get_existing() if state == 'present': - # Filter out module params with null values aci.payload( aci_class='fvCtx', class_config=dict( @@ -261,10 +261,8 @@ def main(): ), ) - # Generate config diff which will be used as POST request body aci.get_diff(aci_class='fvCtx') - # Submit changes if module not in check_mode and the proposed is different than existing aci.post_config() elif state == 'absent': diff --git a/lib/ansible/utils/module_docs_fragments/aci.py b/lib/ansible/utils/module_docs_fragments/aci.py index ac8e6801788..7585e614335 100644 --- a/lib/ansible/utils/module_docs_fragments/aci.py +++ b/lib/ansible/utils/module_docs_fragments/aci.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Dag Wieers -# Copyright 2017 Swetha Chunduri (@schunduri) +# Copyright: (c) 2017, Dag Wieers (@dagwieers) +# Copyright: (c) 2017, Swetha Chunduri (@schunduri) # This file is part of Ansible by Red Hat # @@ -83,12 +83,6 @@ options: type: bool default: 'yes' notes: -- By default, if an environment variable C(_proxy) is set on - the target host, requests will be sent through that proxy. This - behaviour can be overridden by setting a variable for this task - (see `setting the environment - `_), - or by using the C(use_proxy) option. -- HTTP redirects can redirect from HTTP to HTTPS so you should be sure that - your proxy environment for both protocols is correct. +- Please read :ref:`the ACI guide ` for more detailed information + on how to manage your ACI infrastructure using Ansible. ''' diff --git a/test/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml b/test/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml index 34ebe08d83b..75984d655e6 100644 --- a/test/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml +++ b/test/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Bruno Calogero +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_aep_to_domain/tasks/main.yml b/test/integration/targets/aci_aep_to_domain/tasks/main.yml index ed42bddaa29..29a43507d89 100644 --- a/test/integration/targets/aci_aep_to_domain/tasks/main.yml +++ b/test/integration/targets/aci_aep_to_domain/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_ap/tasks/main.yml b/test/integration/targets/aci_ap/tasks/main.yml index 73d1b27b0a9..6d3da16fd4d 100644 --- a/test/integration/targets/aci_ap/tasks/main.yml +++ b/test/integration/targets/aci_ap/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Jacob McGill +# Copyright: (c) 2017, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_contract/tasks/main.yml b/test/integration/targets/aci_contract/tasks/main.yml index dbb14e024bb..32519135c8c 100644 --- a/test/integration/targets/aci_contract/tasks/main.yml +++ b/test/integration/targets/aci_contract/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Jacob McGill +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_domain/tasks/l2dom.yml b/test/integration/targets/aci_domain/tasks/l2dom.yml index 69b8a849204..7bec569e598 100644 --- a/test/integration/targets/aci_domain/tasks/l2dom.yml +++ b/test/integration/targets/aci_domain/tasks/l2dom.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_domain/tasks/l3dom.yml b/test/integration/targets/aci_domain/tasks/l3dom.yml index 033e95f80c0..26aa694db9a 100644 --- a/test/integration/targets/aci_domain/tasks/l3dom.yml +++ b/test/integration/targets/aci_domain/tasks/l3dom.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_domain/tasks/main.yml b/test/integration/targets/aci_domain/tasks/main.yml index 2bc4ddeee8c..5a0585ef328 100644 --- a/test/integration/targets/aci_domain/tasks/main.yml +++ b/test/integration/targets/aci_domain/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_domain/tasks/phys.yml b/test/integration/targets/aci_domain/tasks/phys.yml index 58b55179ed8..6a8f6d77510 100644 --- a/test/integration/targets/aci_domain/tasks/phys.yml +++ b/test/integration/targets/aci_domain/tasks/phys.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_domain/tasks/vmm-vmware.yml b/test/integration/targets/aci_domain/tasks/vmm-vmware.yml index a77031aec74..a539ead6605 100644 --- a/test/integration/targets/aci_domain/tasks/vmm-vmware.yml +++ b/test/integration/targets/aci_domain/tasks/vmm-vmware.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml b/test/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml index 99f9ef5aa2e..2cbb936f42f 100644 --- a/test/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml +++ b/test/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2018, Dag Wieers (@dagwieers) +# Copyright: (c) 2018, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_encap_pool/tasks/main.yml b/test/integration/targets/aci_encap_pool/tasks/main.yml index e158bc0c4de..971b42bfebe 100644 --- a/test/integration/targets/aci_encap_pool/tasks/main.yml +++ b/test/integration/targets/aci_encap_pool/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Jacob McGill +# Copyright: (c) 2017, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_fabric_node/tasks/main.yml b/test/integration/targets/aci_fabric_node/tasks/main.yml index 327565583ad..9e08f8296e0 100644 --- a/test/integration/targets/aci_fabric_node/tasks/main.yml +++ b/test/integration/targets/aci_fabric_node/tasks/main.yml @@ -18,6 +18,7 @@ validate_certs: '{{ aci_validate_certs | default(false) }}' use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: info serial: ansible_test node_id: 105 state: absent @@ -32,6 +33,7 @@ validate_certs: '{{ aci_validate_certs | default(false) }}' use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug serial: ansible_test node_id: 105 switch: test @@ -132,9 +134,8 @@ - name: Verify query_all_fabric_nodes assert: that: - - cm_query_all_fabric_nodes.changed == nm_query_all_fabric_nodes.changed == false # doesn't return necessary information - # NOTE: Order of fabric_nodes is not stable between calls - #- cm_query_all_fabric_nodes == nm_query_all_fabric_nodes + - cm_query_all_fabric_nodes.changed == nm_query_all_fabric_nodes.changed == false + - cm_query_all_fabric_nodes == nm_query_all_fabric_nodes # QUERY A FABRIC NODE @@ -149,7 +150,7 @@ aci_fabric_node: <<: *aci_fabric_node_query serial: ansible_test - register: nm_query_fabric_node # doesn't return necessary information + register: nm_query_fabric_node - name: Verify query_fabric_node assert: @@ -198,7 +199,6 @@ serial: ansible_test register: nm_query_non_fabric_node -# TODO: Implement more tests - name: Verify query_non_fabric_node assert: that: diff --git a/test/integration/targets/aci_filter/tasks/main.yml b/test/integration/targets/aci_filter/tasks/main.yml index 73060e5de73..22599ed8f3f 100644 --- a/test/integration/targets/aci_filter/tasks/main.yml +++ b/test/integration/targets/aci_filter/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Dag Wieers +# Copyright: (c) 2017, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_filter_entry/tasks/main.yml b/test/integration/targets/aci_filter_entry/tasks/main.yml index 9eb8deb7e42..d54a7a41c93 100644 --- a/test/integration/targets/aci_filter_entry/tasks/main.yml +++ b/test/integration/targets/aci_filter_entry/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Jacob McGill +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml b/test/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml index ef252ec1b4b..6221af25dc6 100644 --- a/test/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml +++ b/test/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Bruno Calogero +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml b/test/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml index d70980cd509..bc295f18b7b 100644 --- a/test/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml +++ b/test/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Bruno Calogero +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_switch_leaf_policy_profile/tasks/main.yml b/test/integration/targets/aci_switch_leaf_policy_profile/tasks/main.yml index bb4f60ef1ca..a6234d96a27 100644 --- a/test/integration/targets/aci_switch_leaf_policy_profile/tasks/main.yml +++ b/test/integration/targets/aci_switch_leaf_policy_profile/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Bruno Calogero +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_switch_leaf_selector/tasks/main.yml b/test/integration/targets/aci_switch_leaf_selector/tasks/main.yml index 5ab82ecb037..c4e699a0355 100644 --- a/test/integration/targets/aci_switch_leaf_selector/tasks/main.yml +++ b/test/integration/targets/aci_switch_leaf_selector/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Bruno Calogero +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml b/test/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml index 61dff6dda3c..28eee13064a 100644 --- a/test/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml +++ b/test/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Bruno Calogero +# Copyright: (c) 2017, Bruno Calogero # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_tenant/tasks/main.yml b/test/integration/targets/aci_tenant/tasks/main.yml index 9087513efed..83de6ced485 100644 --- a/test/integration/targets/aci_tenant/tasks/main.yml +++ b/test/integration/targets/aci_tenant/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Dag Wieers +# Copyright: (c) 2017, Dag Wieers (@dagwieers) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/test/integration/targets/aci_vrf/tasks/main.yml b/test/integration/targets/aci_vrf/tasks/main.yml index 88c6d03f636..aa1c73b1709 100644 --- a/test/integration/targets/aci_vrf/tasks/main.yml +++ b/test/integration/targets/aci_vrf/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright 2017, Jacob McGill