Answers: <p>This can be done with two tasks with loops:</p>
  <pre class="lang-yaml prettyprint-override"><code># tasks/packages.yml
  - name: pkgs | Ensure Good 
    package:
      name: &quot;{{ item }}&quot;
      state: present
    loop: &quot;{{ packages['present'] }}&quot;
  
  - name: pkgs | Ensure Bad
    package:
      name: &quot;{{ item }}&quot;
      state: absent
    loop: &quot;{{ packages['absent'] }}&quot;
  </code></pre>
  <p>This will loop over all of the items in the list that you define and ensure that they are either <code>present</code> or <code>absent</code>.</p>
  <p>You could also use a shorthand:</p>
  <pre class="lang-yaml prettyprint-override"><code># tasks/packages.yml
  - name: pkgs | Ensure Good 
    package:
      name: &quot;{{ packages['present'] }}&quot;
      state: present
  
  - name: pkgs | Ensure Bad
    package:
      name: &quot;{{ packages['absent'] }}&quot;
      state: absent
  </code></pre>
  <p>This would run faster, since you don't have a list of tasks, but a task with a list, but you would lose some visibility into which packages you're actually ensuring the state of.</p>
  <p>Caveats:</p>
  <p>Ensure that there is no overlap between the two lists. One way would be to make an assertion on the lists before you run the task:</p>
  <pre class="lang-yaml prettyprint-override"><code>- name: ensure no overlap between good and bad
    assert:
      that: &quot;{{ packages['present'] | intersect(packages['absent'] }} == [] }}&quot;
  </code></pre>
  <p>Also ensure that the lists are not empty.</p>
  <p>To answer your final question:</p>
  <blockquote>
  <p>Q: are there best practices about managing the state of &quot;entities&quot; on the configured infrastructure?</p>
  </blockquote>
  <p>It is usually <em>my</em> practice (I wouldn't call it &quot;best&quot;, but take it for what it's worth) to declare the explicit state of a resource. It's quite difficult to do this exhaustively for packages that should be <code>absent</code> - this is something akin to maintaining a &quot;blacklist&quot;. One approach might to be start from a policy and implement specific controls in it. <em>IE</em> for ssh config ensure that protocol v1 is absent, <em>etc</em>.</p>
  
Answers: CC BY-SA 4.0
Answers: 2021-01-14T07:35:04.043Z
Answers: 2021-01-14T08:31:43.983Z
Answers: 2021-01-14T08:31:43.983Z
Answers: Bruce Becker
Body: <p>Ansible lists a nice set of best practices <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html" rel="nofollow noreferrer">in its documentation</a>. One of the items is:</p>
  <blockquote>
  <h3>Always mention the state</h3>
  <p>For many modules, the <code>state</code> parameter is optional. Different modules have different default settings for <code>state</code>, and some modules support several <code>state</code> settings. Explicitly setting <code>state=present</code> or <code>state=absent</code> makes playbooks and roles clearer.</p>
  </blockquote>
  <p>In my case the main point isn't so much about making playbooks or roles clearer, instead my goal is to manage the presence/absence of items throughout the lifetime of my servers.</p>
  <p>Probably many of you have had the issue of installing package <code>xyz</code> as a &quot;bread'n'butter&quot; package on your machines, but a few months later it turns out your workflow has changed and you don't really need <code>xyz</code> anymore. Or it was replaced by <code>xyz-ng</code> ... or what have you ...</p>
  <p>So now it's time to express somehow to remove that <code>xyz</code> package consistently across your infrastructure. In my case with Debian/Ubuntu I'd use the <code>apt</code> module with <code>state=absent</code> for the respective packages. No surprise.</p>
  <p>However, I'd like to factor this into my roles from the outset. As an example it would be nice to have a dictionary variable (as an example):</p>
  <pre><code>packages:
    present:
    - elinks
    absent:
    - lynx
  </code></pre>
  <p>This way the presence and absence would dynamically be managed by variables and I can use <code>when:</code> to cover for an empty list and so on; potentially even by including a task dynamically and passing along a <code>state</code> variable that coincides with the key in the dictionary.</p>
  <p>Another case where this must have come up for someone before is the creation of local users, or has everyone moved to directory services? When someone leaves the company I'd like to be able to put that someone on a list populated with usernames to be put into a locked state.</p>
  <p>However, since there <em>are</em> established best practices for Ansible in general, I was wondering:</p>
  <p><strong>Q:</strong> are there best practices about managing the state of &quot;entities&quot; on the configured infrastructure?</p>
  
Tags: <ansible>
Title: Managing state (e.g. presence/absence) in Ansible, any established best practices?
UserDisplayName: 0xC0000022L
ThreadText: # Managing state (e.g. presence/absence) in Ansible, any established best practices?
  
  (Asked by: username_0 on 2021-01-13)
  
  Ansible lists a nice set of best practices [in its documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html). One of the items is:
  
  > ### Always mention the state
  >
  > For many modules, the `state` parameter is optional. Different modules have different default settings for `state`, and some modules support several `state` settings. Explicitly setting `state=present` or `state=absent` makes playbooks and roles clearer.
  
  In my case the main point isn't so much about making playbooks or roles clearer, instead my goal is to manage the presence/absence of items throughout the lifetime of my servers.
  
  Probably many of you have had the issue of installing package `xyz` as a "bread'n'butter" package on your machines, but a few months later it turns out your workflow has changed and you don't really need `xyz` anymore. Or it was replaced by `xyz-ng` ... or what have you ...
  
  So now it's time to express somehow to remove that `xyz` package consistently across your infrastructure. In my case with Debian/Ubuntu I'd use the `apt` module with `state=absent` for the respective packages. No surprise.
  
  However, I'd like to factor this into my roles from the outset. As an example it would be nice to have a dictionary variable (as an example):
  
  ```
  packages:
    present:
    - elinks
    absent:
    - lynx
  
  ```
  
  This way the presence and absence would dynamically be managed by variables and I can use `when:` to cover for an empty list and so on; potentially even by including a task dynamically and passing along a `state` variable that coincides with the key in the dictionary.
  
  Another case where this must have come up for someone before is the creation of local users, or has everyone moved to directory services? When someone leaves the company I'd like to be able to put that someone on a list populated with usernames to be put into a locked state.
  
  However, since there *are* established best practices for Ansible in general, I was wondering:
  
  **Q:** are there best practices about managing the state of "entities" on the configured infrastructure?
  
  **Tags:** ansible
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-01-14. Score: 3 | Accepted answer
  
  This can be done with two tasks with loops:
  
  ```yaml
  # tasks/packages.yml
  - name: pkgs | Ensure Good 
    package:
      name: "{{ item }}"
      state: present
    loop: "{{ packages['present'] }}"
  
  - name: pkgs | Ensure Bad
    package:
      name: "{{ item }}"
      state: absent
    loop: "{{ packages['absent'] }}"
  
  ```
  
  This will loop over all of the items in the list that you define and ensure that they are either `present` or `absent`.
  
  You could also use a shorthand:
  
  ```yaml
  # tasks/packages.yml
  - name: pkgs | Ensure Good 
    package:
      name: "{{ packages['present'] }}"
      state: present
  
  - name: pkgs | Ensure Bad
    package:
      name: "{{ packages['absent'] }}"
      state: absent
  
  ```
  
  This would run faster, since you don't have a list of tasks, but a task with a list, but you would lose some visibility into which packages you're actually ensuring the state of.
  
  Caveats:
  
  Ensure that there is no overlap between the two lists. One way would be to make an assertion on the lists before you run the task:
  
  ```yaml
  - name: ensure no overlap between good and bad
    assert:
      that: "{{ packages['present'] | intersect(packages['absent'] }} == [] }}"
  
  ```
  
  Also ensure that the lists are not empty.
  
  To answer your final question:
  
  > Q: are there best practices about managing the state of "entities" on the configured infrastructure?
  
  It is usually *my* practice (I wouldn't call it "best", but take it for what it's worth) to declare the explicit state of a resource. It's quite difficult to do this exhaustively for packages that should be `absent` - this is something akin to maintaining a "blacklist". One approach might to be start from a policy and implement specific controls in it. *IE* for ssh config ensure that protocol v1 is absent, *etc*.
  
  
  ---
  
  