Right now if attributes are used in module documentation, it’s mostly the standard attributes defined in ansible/lib/ansible/plugins/doc_fragments/action_common_attributes.py at devel · ansible/ansible · GitHub, i.e. check_mode
, diff_mode
, platform
, action_group
, and in special cases a few more. I haven’t seen the attributes feature used for self-defined attributes yet (but maybe I missed them, hints are welcome).
In any case, I’ve been longer thinking about using them to document more aspects, especially related to idempotency. Most modules are supposed to be idempotent, i.e. when you run them twice in the row with the same arguments, there should be no changes. Some modules cannot do that, for example because they execute user-supplied commands without understanding them, like ansible.builtin.command
, or because they operate with APIs that do not allow to determine whether a change is actually needed or not, and you cannot find it out after executing the corresponding action either. Sometimes this also depends on module options; for example force=true
sometimes disables idempotency, especially if the module’s output is not fully deterministic (example: force regeneration of a private key). Figuring out whether a module is idempotent, resp. under which conditions it is idempotent can be quite a lot of work (if the module documentation is long), especially if the result is “it’s not documented”. So being able to see this information on a glance would be very helpful, since idempotency is one of the main pillars of how Ansible should work.
So I went ahead and introduced an attribute idempotent
in some of the collections I maintain, and use it for all modules with support: none
, support: partial
, or support: full
- the former two with details
that describe why and/or under which conditions the module is (not) idempotent -, and sometimes support: N/A
(again with details
). Here’s a list of the PRs, links to the collection documentation on the Ansible devel
docsite, and a link to the attributes of an example module from the collection:
- community.crypto:
- PR: Add 'idempotent' attribute by felixfontein · Pull Request #833 · ansible-collections/community.crypto · GitHub
- Docs: Community.Crypto — Ansible Community Documentation
- Example attributes: community.crypto.x509_certificate module – Generate and/or check OpenSSL certificates — Ansible Community Documentation
- community.dns:
- community.docker:
- community.hrobot:
- community.routeros:
- community.sops:
While working on this, I was wondering about a very related question: which parameters of a module will be used for updates, and which are only used for creation / when an action is applied, and for which the behavior is configurable? This is another aspect that’s sometimes also summed up under idempotency: if you run a task twice, but in the second invocation modify a parameter, does or under which conditions does the module update the managed object accordingly? Again, the general consensus is that modules should update the objects the manage to match the provided parameters, but there are a lot of cases where that isn’t possible or potentially destructive (an object has to be destroyed and re-created, which can lead to data loss for volumes, partitions, private keys, …) and thus potentially also configurable (the module cannot say whether reformatting a disk is acceptable or not if someone adjusted a parameter of the task). And then there’s interaction with parameters set / modified from outside the module (say a property that’s not supported by the module). Some of these things are documented, some others are not and result in bug reports from users who assume that the module should behave differently. Sometimes users don’t read the documentation, but if they do it would be great if that information is easy to find.
Again, here I think attributes are really helpful. The big question here is: should this also be summed up under idempotent
? Or should there be another - or more than one - new attributes?