title: Ansible: how to remove AWS IAM group with an inline policy defined? (Ansible claims "changed" without performing the action)
body: <p>When AWS IAM group has an inline policy defined, the following Ansible task does not remove the group, although task status claims "changed":</p>
  
  <pre><code>- name: Ensure group {{ group_name }} exists
    iam:
      iam_type: group
      name: "{{ group_name }}"
      state: absent
  </code></pre>
  
  <p>The <code>iam</code> module doc page contains a <a href="https://docs.ansible.com/ansible/iam_policy_module.html#notes" rel="nofollow noreferrer">note</a>:</p>
  
  <blockquote>
    <p>Currently boto does not support the removal of Managed Policies, the module will not work removing/adding managed policies.</p>
  </blockquote>
  
  <p>but this is an <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html" rel="nofollow noreferrer">inline policy, not a managed one</a>.</p>
  
  <p>As a workaround, because the return JSON contains <code>delete_group</code> key, I can at least cause the task to fail by adding:</p>
  
  <pre><code>  register: deletion_result
    failed_when: not deletion_result.delete_group
  </code></pre>
  
  <p>But why does it claim "changed" when the action was not performed (and it knows that, because <code>delete_group</code> is set to either true or false)?</p>
  
  <p>Is it a bug in Ansible, or am I missing something?</p>
  
  <p>And the big question: how to remove the group with a defined inline policy using Ansible?</p>
  
  <hr>
  
  <p><strong>MCVE</strong></p>
  
  <ul>
  <li><p>My play (create group, assign policy, delete group, delete group - again to show the problem):</p>
  
  <pre><code>---
  - hosts: localhost
    connection: local
    gather_facts: no
  
    vars:
      group_name: test_group_01
      policy_name: test_policy_01
  
    tasks:
      - name: Ensure group {{ group_name }} exists
        iam:
          iam_type: group
          name: "{{ group_name }}"
          state: present
  
      - name: Ensure policy {{ policy_name }} exists and is assigned to group {{ group_name }}
        iam_policy:
          iam_type: group
          iam_name: "{{ group_name }}"
          policy_name: "{{ policy_name }}"
          policy_document: ./policy.j2
          state: present
  
      - name: Ensure group {{ group_name }} does not exist
        iam:
          iam_type: group
          name: "{{ group_name }}"
          state: absent
  
      - name: Ensure group {{ group_name }} does not exist
        iam:
          iam_type: group
          name: "{{ group_name }}"
          state: absent
  </code></pre>
  
  <p><code>policy.json</code> (not relevant for results, just for completeness):</p>
  
  <pre><code>{
      "Version": "2012-10-17",
      "Statement": [
          {
              "Sid": "Stmt2017010101",
              "Effect": "Allow",
              "Action": [
                  "s3:ListBucket"
              ],
              "Resource": [
                  "arn:aws:s3:::my_bucket"
              ]
          }
      ]
  }
  </code></pre></li>
  <li><p>The actual result:</p>
  
  <pre><code>PLAY [localhost] ***************************************************************
  
  TASK [Ensure group test_group_01 exists] ***************************************
  changed: [localhost]
  
  TASK [Ensure policy test_policy_01 exists and is assigned to group test_group_01] ***
  changed: [localhost]
  
  TASK [Ensure group test_group_01 does not exist] *******************************
  changed: [localhost]
  
  TASK [Ensure group test_group_01 does not exist] *******************************
  changed: [localhost]
  
  PLAY RECAP *********************************************************************
  localhost                  : ok=4    changed=4    unreachable=0    failed=0
  </code></pre></li>
  <li><p>Expected result:</p>
  
  <pre><code>PLAY [localhost] ***************************************************************
  
  TASK [Ensure group test_group_01 exists] ***************************************
  changed: [localhost]
  
  TASK [Ensure policy test_policy_01 exists and is assigned to group test_group_01] ***
  changed: [localhost]
  
  TASK [Ensure group test_group_01 does not exist] *******************************
  changed: [localhost]
  
  TASK [Ensure group test_group_01 does not exist] *******************************
  ok: [localhost]
  
  PLAY RECAP *********************************************************************
  localhost                  : ok=4    changed=3    unreachable=0    failed=0
  </code></pre></li>
  </ul>