1.. _aci_guide:
2
3Cisco ACI Guide
4===============
5
6
7.. _aci_guide_intro:
8
9What is Cisco ACI ?
10-------------------
11
12Application Centric Infrastructure (ACI)
13........................................
14The Cisco Application Centric Infrastructure (ACI) allows application requirements to define the network. This architecture simplifies, optimizes, and accelerates the entire application deployment life cycle.
15
16
17Application Policy Infrastructure Controller (APIC)
18...................................................
19The APIC manages the scalable ACI multi-tenant fabric. The APIC provides a unified point of automation and management, policy programming, application deployment, and health monitoring for the fabric. The APIC, which is implemented as a replicated synchronized clustered controller, optimizes performance, supports any application anywhere, and provides unified operation of the physical and virtual infrastructure.
20
21The APIC enables network administrators to easily define the optimal network for applications. Data center operators can clearly see how applications consume network resources, easily isolate and troubleshoot application and infrastructure problems, and monitor and profile resource usage patterns.
22
23The Cisco Application Policy Infrastructure Controller (APIC) API enables applications to directly connect with a secure, shared, high-performance resource pool that includes network, compute, and storage capabilities.
24
25
26ACI Fabric
27..........
28The Cisco Application Centric Infrastructure (ACI) Fabric includes Cisco Nexus 9000 Series switches with the APIC to run in the leaf/spine ACI fabric mode. These switches form a "fat-tree" network by connecting each leaf node to each spine node; all other devices connect to the leaf nodes. The APIC manages the ACI fabric.
29
30The ACI fabric provides consistent low-latency forwarding across high-bandwidth links (40 Gbps, with a 100-Gbps future capability). Traffic with the source and destination on the same leaf switch is handled locally, and all other traffic travels from the ingress leaf to the egress leaf through a spine switch. Although this architecture appears as two hops from a physical perspective, it is actually a single Layer 3 hop because the fabric operates as a single Layer 3 switch.
31
32The ACI fabric object-oriented operating system (OS) runs on each Cisco Nexus 9000 Series node. It enables programming of objects for each configurable element of the system. The ACI fabric OS renders policies from the APIC into a concrete model that runs in the physical infrastructure. The concrete model is analogous to compiled software; it is the form of the model that the switch operating system can execute.
33
34All the switch nodes contain a complete copy of the concrete model. When an administrator creates a policy in the APIC that represents a configuration, the APIC updates the logical model. The APIC then performs the intermediate step of creating a fully elaborated policy that it pushes into all the switch nodes where the concrete model is updated.
35
36The APIC is responsible for fabric activation, switch firmware management, network policy configuration, and instantiation. While the APIC acts as the centralized policy and network management engine for the fabric, it is completely removed from the data path, including the forwarding topology. Therefore, the fabric can still forward traffic even when communication with the APIC is lost.
37
38
39More information
40................
41Various resources exist to start learning ACI, here is a list of interesting articles from the community.
42
43- `Adam Raffe: Learning ACI <https://adamraffe.com/learning-aci/>`_
44- `Luca Relandini: ACI for dummies <https://lucarelandini.blogspot.be/2015/03/aci-for-dummies.html>`_
45- `Cisco DevNet Learning Labs about ACI <https://learninglabs.cisco.com/labs/tags/ACI>`_
46
47
48.. _aci_guide_modules:
49
50Using the ACI modules
51---------------------
52The Ansible ACI modules provide a user-friendly interface to managing your ACI environment using Ansible playbooks.
53
54For instance ensuring that a specific tenant exists, is done using the following Ansible task using the aci_tenant module:
55
56.. code-block:: yaml
57
58    - name: Ensure tenant customer-xyz exists
59      aci_tenant:
60        host: my-apic-1
61        username: admin
62        password: my-password
63
64        tenant: customer-xyz
65        description: Customer XYZ
66        state: present
67
68A complete list of existing ACI modules is available on the content tab of the `ACI collection on Ansible Galaxy <https://galaxy.ansible.com/cisco/aci>`_.
69
70If you want to learn how to write your own ACI modules to contribute, look at the :ref:`Developing Cisco ACI modules <aci_dev_guide>` section.
71
72Querying ACI configuration
73..........................
74
75A module can also be used to query a specific object.
76
77.. code-block:: yaml
78
79    - name: Query tenant customer-xyz
80      aci_tenant:
81        host: my-apic-1
82        username: admin
83        password: my-password
84
85        tenant: customer-xyz
86        state: query
87      register: my_tenant
88
89Or query all objects.
90
91.. code-block:: yaml
92
93    - name: Query all tenants
94      aci_tenant:
95        host: my-apic-1
96        username: admin
97        password: my-password
98
99        state: query
100      register: all_tenants
101
102After registering the return values of the aci_tenant task as shown above, you can access all tenant information from variable ``all_tenants``.
103
104
105Running on the controller locally
106.................................
107As originally designed, Ansible modules are shipped to and run on the remote target(s), however the ACI modules (like most network-related modules) do not run on the network devices or controller (in this case the APIC), but they talk directly to the APIC's REST interface.
108
109For this very reason, the modules need to run on the local Ansible controller (or are delegated to another system that *can* connect to the APIC).
110
111
112Gathering facts
113```````````````
114Because we run the modules on the Ansible controller gathering facts will not work. That is why when using these ACI modules it is mandatory to disable facts gathering. You can do this globally in your ``ansible.cfg`` or by adding ``gather_facts: no`` to every play.
115
116.. code-block:: yaml
117   :emphasize-lines: 3
118
119    - name: Another play in my playbook
120      hosts: my-apic-1
121      gather_facts: no
122      tasks:
123      - name: Create a tenant
124        aci_tenant:
125          ...
126
127Delegating to localhost
128```````````````````````
129So let us assume we have our target configured in the inventory using the FQDN name as the ``ansible_host`` value, as shown below.
130
131.. code-block:: yaml
132   :emphasize-lines: 3
133
134    apics:
135      my-apic-1:
136        ansible_host: apic01.fqdn.intra
137        ansible_user: admin
138        ansible_password: my-password
139
140One way to set this up is to add to every task the directive: ``delegate_to: localhost``.
141
142.. code-block:: yaml
143   :emphasize-lines: 8
144
145    - name: Query all tenants
146      aci_tenant:
147        host: '{{ ansible_host }}'
148        username: '{{ ansible_user }}'
149        password: '{{ ansible_password }}'
150
151        state: query
152      delegate_to: localhost
153      register: all_tenants
154
155If one would forget to add this directive, Ansible will attempt to connect to the APIC using SSH and attempt to copy the module and run it remotely. This will fail with a clear error, yet may be confusing to some.
156
157
158Using the local connection method
159`````````````````````````````````
160Another option frequently used, is to tie the ``local`` connection method to this target so that every subsequent task for this target will use the local connection method (hence run it locally, rather than use SSH).
161
162In this case the inventory may look like this:
163
164.. code-block:: yaml
165   :emphasize-lines: 6
166
167    apics:
168      my-apic-1:
169        ansible_host: apic01.fqdn.intra
170        ansible_user: admin
171        ansible_password: my-password
172        ansible_connection: local
173
174But used tasks do not need anything special added.
175
176.. code-block:: yaml
177
178    - name: Query all tenants
179      aci_tenant:
180        host: '{{ ansible_host }}'
181        username: '{{ ansible_user }}'
182        password: '{{ ansible_password }}'
183
184        state: query
185      register: all_tenants
186
187.. hint:: For clarity we have added ``delegate_to: localhost`` to all the examples in the module documentation. This helps to ensure first-time users can easily copy&paste parts and make them work with a minimum of effort.
188
189
190Common parameters
191.................
192Every Ansible ACI module accepts the following parameters that influence the module's communication with the APIC REST API:
193
194    host
195        Hostname or IP address of the APIC.
196
197    port
198        Port to use for communication. (Defaults to ``443`` for HTTPS, and ``80`` for HTTP)
199
200    username
201        User name used to log on to the APIC. (Defaults to ``admin``)
202
203    password
204        Password for ``username`` to log on to the APIC, using password-based authentication.
205
206    private_key
207        Private key for ``username`` to log on to APIC, using signature-based authentication.
208        This could either be the raw private key content (include header/footer) or a file that stores the key content.
209        *New in version 2.5*
210
211    certificate_name
212        Name of the certificate in the ACI Web GUI.
213        This defaults to either the ``username`` value or the ``private_key`` file base name).
214        *New in version 2.5*
215
216    timeout
217        Timeout value for socket-level communication.
218
219    use_proxy
220        Use system proxy settings. (Defaults to ``yes``)
221
222    use_ssl
223        Use HTTPS or HTTP for APIC REST communication. (Defaults to ``yes``)
224
225    validate_certs
226        Validate certificate when using HTTPS communication. (Defaults to ``yes``)
227
228    output_level
229        Influence the level of detail ACI modules return to the user. (One of ``normal``, ``info`` or ``debug``) *New in version 2.5*
230
231
232Proxy support
233.............
234By default, if an environment variable ``<protocol>_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:`playbooks_environment`), or by using the ``use_proxy`` module parameter.
235
236HTTP redirects can redirect from HTTP to HTTPS so ensure that the proxy environment for both protocols is correctly configured.
237
238If proxy support is not needed, but the system may have it configured nevertheless, use the parameter ``use_proxy: no`` to avoid accidental system proxy usage.
239
240.. hint:: Selective proxy support using the ``no_proxy`` environment variable is also supported.
241
242
243Return values
244.............
245
246.. versionadded:: 2.5
247
248The following values are always returned:
249
250    current
251        The resulting state of the managed object, or results of your query.
252
253The following values are returned when ``output_level: info``:
254
255    previous
256        The original state of the managed object (before any change was made).
257
258    proposed
259        The proposed config payload, based on user-supplied values.
260
261    sent
262        The sent config payload, based on user-supplied values and the existing configuration.
263
264The following values are returned when ``output_level: debug`` or ``ANSIBLE_DEBUG=1``:
265
266    filter_string
267        The filter used for specific APIC queries.
268
269    method
270        The HTTP method used for the sent payload. (Either ``GET`` for queries, ``DELETE`` or ``POST`` for changes)
271
272    response
273        The HTTP response from the APIC.
274
275    status
276        The HTTP status code for the request.
277
278    url
279        The url used for the request.
280
281.. note:: The module return values are documented in detail as part of each module's documentation.
282
283
284More information
285................
286Various resources exist to start learn more about ACI programmability, we recommend the following links:
287
288- :ref:`Developing Cisco ACI modules <aci_dev_guide>`
289- `Jacob McGill: Automating Cisco ACI with Ansible <https://blogs.cisco.com/developer/automating-cisco-aci-with-ansible-eliminates-repetitive-day-to-day-tasks>`_
290- `Cisco DevNet Learning Labs about ACI and Ansible <https://learninglabs.cisco.com/labs/tags/ACI,Ansible>`_
291
292
293.. _aci_guide_auth:
294
295ACI authentication
296------------------
297
298Password-based authentication
299.............................
300If you want to log on using a username and password, you can use the following parameters with your ACI modules:
301
302.. code-block:: yaml
303
304    username: admin
305    password: my-password
306
307Password-based authentication is very simple to work with, but it is not the most efficient form of authentication from ACI's point-of-view as it requires a separate login-request and an open session to work. To avoid having your session time-out and requiring another login, you can use the more efficient Signature-based authentication.
308
309.. note:: Password-based authentication also may trigger anti-DoS measures in ACI v3.1+ that causes session throttling and results in HTTP 503 errors and login failures.
310
311.. warning:: Never store passwords in plain text.
312
313The "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 :ref:`playbooks_vault` for more information.
314
315
316Signature-based authentication using certificates
317.................................................
318
319.. versionadded:: 2.5
320
321Using signature-based authentication is more efficient and more reliable than password-based authentication.
322
323Generate certificate and private key
324````````````````````````````````````
325Signature-based authentication requires a (self-signed) X.509 certificate with private key, and a configuration step for your AAA user in ACI. To generate a working X.509 certificate and private key, use the following procedure:
326
327.. code-block:: bash
328
329    $ openssl req -new -newkey rsa:1024 -days 36500 -nodes -x509 -keyout admin.key -out admin.crt -subj '/CN=Admin/O=Your Company/C=US'
330
331Configure your local user
332`````````````````````````
333Perform the following steps:
334
335- Add the X.509 certificate to your ACI AAA local user at :guilabel:`ADMIN` » :guilabel:`AAA`
336- Click :guilabel:`AAA Authentication`
337- Check that in the :guilabel:`Authentication` field the :guilabel:`Realm` field displays :guilabel:`Local`
338- Expand :guilabel:`Security Management` » :guilabel:`Local Users`
339- Click the name of the user you want to add a certificate to, in the :guilabel:`User Certificates` area
340- Click the :guilabel:`+` sign and in the :guilabel:`Create X509 Certificate` enter a certificate name in the :guilabel:`Name` field
341
342  * If you use the basename of your private key here, you don't need to enter ``certificate_name`` in Ansible
343
344- Copy and paste your X.509 certificate in the :guilabel:`Data` field.
345
346You can automate this by using the following Ansible task:
347
348.. code-block:: yaml
349
350    - name: Ensure we have a certificate installed
351      aci_aaa_user_certificate:
352        host: my-apic-1
353        username: admin
354        password: my-password
355
356        aaa_user: admin
357        certificate_name: admin
358        certificate: "{{ lookup('file', 'pki/admin.crt') }}"  # This will read the certificate data from a local file
359
360.. note:: Signature-based authentication only works with local users.
361
362
363Use signature-based authentication with Ansible
364```````````````````````````````````````````````
365You need the following parameters with your ACI module(s) for it to work:
366
367.. code-block:: yaml
368   :emphasize-lines: 2,3
369
370    username: admin
371    private_key: pki/admin.key
372    certificate_name: admin  # This could be left out !
373
374or you can use the private key content:
375
376.. code-block:: yaml
377   :emphasize-lines: 2,3
378
379    username: admin
380    private_key: |
381        -----BEGIN PRIVATE KEY-----
382        <<your private key content>>
383        -----END PRIVATE KEY-----
384    certificate_name: admin  # This could be left out !
385
386
387.. 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.
388
389
390Using Ansible Vault to encrypt the private key
391``````````````````````````````````````````````
392.. versionadded:: 2.8
393
394To start, encrypt the private key and give it a strong password.
395
396.. code-block:: bash
397
398    ansible-vault encrypt admin.key
399
400Use a text editor to open the private-key. You should have an encrypted cert now.
401
402.. code-block:: bash
403
404    $ANSIBLE_VAULT;1.1;AES256
405    56484318584354658465121889743213151843149454864654151618131547984132165489484654
406    45641818198456456489479874513215489484843614848456466655432455488484654848489498
407    ....
408
409Copy and paste the new encrypted cert into your playbook as a new variable.
410
411.. code-block:: yaml
412
413    private_key: !vault |
414          $ANSIBLE_VAULT;1.1;AES256
415          56484318584354658465121889743213151843149454864654151618131547984132165489484654
416          45641818198456456489479874513215489484843614848456466655432455488484654848489498
417          ....
418
419Use the new variable for the private_key:
420
421.. code-block:: yaml
422
423    username: admin
424    private_key: "{{ private_key }}"
425    certificate_name: admin  # This could be left out !
426
427When running the playbook, use "--ask-vault-pass" to decrypt the private key.
428
429.. code-block:: bash
430
431    ansible-playbook site.yaml --ask-vault-pass
432
433
434More information
435````````````````
436- Detailed information about Signature-based Authentication is available from `Cisco APIC Signature-Based Transactions <https://www.cisco.com/c/en/us/td/docs/switches/datacenter/aci/apic/sw/kb/b_KB_Signature_Based_Transactions.html>`_.
437- More information on Ansible Vault can be found on the :ref:`Ansible Vault <vault>` page.
438
439
440.. _aci_guide_rest:
441
442Using ACI REST with Ansible
443---------------------------
444While already a lot of ACI modules exists in the Ansible distribution, and the most common actions can be performed with these existing modules, there's always something that may not be possible with off-the-shelf modules.
445
446The aci_rest module provides you with direct access to the APIC REST API and enables you to perform any task not already covered by the existing modules. This may seem like a complex undertaking, but you can generate the needed REST payload for any action performed in the ACI web interface effortlessly.
447
448
449Built-in idempotency
450....................
451Because the APIC REST API is intrinsically idempotent and can report whether a change was made, the aci_rest module automatically inherits both capabilities and is a first-class solution for automating your ACI infrastructure. As a result, users that require more powerful low-level access to their ACI infrastructure don't have to give up on idempotency and don't have to guess whether a change was performed when using the aci_rest module.
452
453
454Using the aci_rest module
455.........................
456The aci_rest module accepts the native XML and JSON payloads, but additionally accepts inline YAML payload (structured like JSON). The XML payload requires you to use a path ending with ``.xml`` whereas JSON or YAML require the path to end with ``.json``.
457
458When you're making modifications, you can use the POST or DELETE methods, whereas doing just queries require the GET method.
459
460For instance, if you would like to ensure a specific tenant exists on ACI, these below four examples are functionally identical:
461
462**XML** (Native ACI REST)
463
464.. code-block:: yaml
465
466    - aci_rest:
467        host: my-apic-1
468        private_key: pki/admin.key
469
470        method: post
471        path: /api/mo/uni.xml
472        content: |
473          <fvTenant name="customer-xyz" descr="Customer XYZ"/>
474
475**JSON** (Native ACI REST)
476
477.. code-block:: yaml
478
479    - aci_rest:
480        host: my-apic-1
481        private_key: pki/admin.key
482
483        method: post
484        path: /api/mo/uni.json
485        content:
486          {
487            "fvTenant": {
488              "attributes": {
489                "name": "customer-xyz",
490                "descr": "Customer XYZ"
491              }
492            }
493          }
494
495**YAML** (Ansible-style REST)
496
497.. code-block:: yaml
498
499    - aci_rest:
500        host: my-apic-1
501        private_key: pki/admin.key
502
503        method: post
504        path: /api/mo/uni.json
505        content:
506          fvTenant:
507            attributes:
508              name: customer-xyz
509              descr: Customer XYZ
510
511**Ansible task** (Dedicated module)
512
513.. code-block:: yaml
514
515    - aci_tenant:
516        host: my-apic-1
517        private_key: pki/admin.key
518
519        tenant: customer-xyz
520        description: Customer XYZ
521        state: present
522
523
524.. hint:: The XML format is more practical when there is a need to template the REST payload (inline), but the YAML format is more convenient for maintaining your infrastructure-as-code and feels more naturally integrated with Ansible playbooks. The dedicated modules offer a more simple, abstracted, but also a more limited experience. Use what feels best for your use-case.
525
526
527More information
528................
529Plenty of resources exist to learn about ACI's APIC REST interface, we recommend the links below:
530
531- `The ACI collection on Ansible Galaxy <https://galaxy.ansible.com/cisco/aci>`_
532- `APIC REST API Configuration Guide <https://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>`_ -- Detailed guide on how the APIC REST API is designed and used, incl. many examples
533- `APIC Management Information Model reference <https://developer.cisco.com/docs/apic-mim-ref/>`_ -- Complete reference of the APIC object model
534- `Cisco DevNet Learning Labs about ACI and REST <https://learninglabs.cisco.com/labs/tags/ACI,REST>`_
535
536
537.. _aci_guide_ops:
538
539Operational examples
540--------------------
541Here is a small overview of useful operational tasks to reuse in your playbooks.
542
543Feel free to contribute more useful snippets.
544
545
546Waiting for all controllers to be ready
547.......................................
548You can use the below task after you started to build your APICs and configured the cluster to wait until all the APICs have come online. It will wait until the number of controllers equals the number listed in the ``apic`` inventory group.
549
550.. code-block:: yaml
551
552    - name: Waiting for all controllers to be ready
553      aci_rest:
554        host: my-apic-1
555        private_key: pki/admin.key
556        method: get
557        path: /api/node/class/topSystem.json?query-target-filter=eq(topSystem.role,"controller")
558      register: topsystem
559      until: topsystem|success and topsystem.totalCount|int >= groups['apic']|count >= 3
560      retries: 20
561      delay: 30
562
563
564Waiting for cluster to be fully-fit
565...................................
566The below example waits until the cluster is fully-fit. In this example you know the number of APICs in the cluster and you verify each APIC reports a 'fully-fit' status.
567
568.. code-block:: yaml
569
570    - name: Waiting for cluster to be fully-fit
571      aci_rest:
572        host: my-apic-1
573        private_key: pki/admin.key
574        method: get
575        path: /api/node/class/infraWiNode.json?query-target-filter=wcard(infraWiNode.dn,"topology/pod-1/node-1/av")
576      register: infrawinode
577      until: >
578        infrawinode|success and
579        infrawinode.totalCount|int >= groups['apic']|count >= 3 and
580        infrawinode.imdata[0].infraWiNode.attributes.health == 'fully-fit' and
581        infrawinode.imdata[1].infraWiNode.attributes.health == 'fully-fit' and
582        infrawinode.imdata[2].infraWiNode.attributes.health == 'fully-fit'
583      retries: 30
584      delay: 30
585
586
587.. _aci_guide_errors:
588
589APIC error messages
590-------------------
591The following error messages may occur and this section can help you understand what exactly is going on and how to fix/avoid them.
592
593    APIC Error 122: unknown managed object class 'polUni'
594        In case you receive this error while you are certain your aci_rest payload and object classes are seemingly correct, the issue might be that your payload is not in fact correct JSON (for example, 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, which are easier to construct correctly and modify later.
595
596
597    APIC Error 400: invalid data at line '1'. Attributes are missing, tag 'attributes' must be specified first, before any other tag
598        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 precede any ``children``.
599
600
601    APIC Error 801: property descr of uni/tn-TENANT/ap-AP failed validation for value 'A "legacy" network'
602        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\\!#$%()*,-./:;@ _{|}~?&+]+ <https://pubhub-prod.s3.amazonaws.com/media/apic-mim-ref/docs/MO-fvAp.html#descr>`_, in general it must not include quotes or square brackets.
603
604
605.. _aci_guide_known_issues:
606
607Known issues
608------------
609The aci_rest module is a wrapper around the APIC REST API. As a result any issues related to the APIC will be reflected in the use of this module.
610
611All below issues either have been reported to the vendor, and most can simply be avoided.
612
613    Too many consecutive API calls may result in connection throttling
614        Starting with ACI v3.1 the APIC will actively throttle password-based authenticated connection rates over a specific threshold. 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 threshold within the nginx configuration, but using signature-based authentication is recommended.
615
616        **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.
617
618
619    Specific requests may not reflect changes correctly (`#35401 <https://github.com/ansible/ansible/issues/35041>`_)
620        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.
621
622        **NOTE:** A workaround is to register the task return values (for example, ``register: this``) and influence when the task should report a change by adding: ``changed_when: this.imdata != []``.
623
624
625    Specific requests are known to not be idempotent (`#35050 <https://github.com/ansible/ansible/issues/35050>`_)
626        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.
627
628        **NOTE:** A workaround is to avoid using ``status="created"`` and instead use ``status="modified"`` when idempotency is essential to your workflow..
629
630
631    Setting user password is not idempotent (`#35544 <https://github.com/ansible/ansible/issues/35544>`_)
632        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``.
633
634        **NOTE:** There is no workaround for this issue.
635
636
637.. _aci_guide_community:
638
639ACI Ansible community
640---------------------
641If you have specific issues with the ACI modules, or a feature request, or you like to contribute to the ACI project by proposing changes or documentation updates, look at the Ansible Community wiki ACI page at: https://github.com/ansible/community/wiki/Network:-ACI
642
643You will find our roadmap, an overview of open ACI issues and pull-requests, and more information about who we are. If you have an interest in using ACI with Ansible, feel free to join! We occasionally meet online to track progress and prepare for new Ansible releases.
644
645
646.. seealso::
647
648   `ACI collection on Ansible Galaxy <https://galaxy.ansible.com/cisco/aci>`_
649       View the content tab for a complete list of supported ACI modules.
650   :ref:`Developing Cisco ACI modules <aci_dev_guide>`
651       A walkthough on how to develop new Cisco ACI modules to contribute back.
652   `ACI community <https://github.com/ansible/community/wiki/Network:-ACI>`_
653       The Ansible ACI community wiki page, includes roadmap, ideas and development documentation.
654   :ref:`network_guide`
655       A detailed guide on how to use Ansible for automating network infrastructure.
656   `Network Working Group <https://github.com/ansible/community/tree/master/group-network>`_
657       The Ansible Network community page, includes contact information and meeting information.
658   ``#ansible-network`` on `irc.libera.chat <https://libera.chat/>`_
659       The #ansible-network IRC chat channel on libera.chat.
660   `User Mailing List <https://groups.google.com/group/ansible-project>`_
661       Have a question?  Stop by the google group!
662