Ansible-playbook does not working with dictionary and with_items loop!

I filed a bug issue on Ansible GitHub:

You keep saying that, but it isn’t doing what you think it’s doing. It’s simply printing the value of the dictionary. A much more informative debug task would be one that loops over the data the same way your ansible.builtin.group task does:

- name: Display loop items from test_global_groups
  ansible.builtin.debug:
    msg: '{{ item }}'
  loop: '{{ test_global_groups | dict2items }}'

The error from the second task - the ansible.builtin.group task - is telling you that the first conditional in your when: clause is broken. the item has no gid at the top level. It’s item.value.gid.

@flowerysong told you to look carefully and compare the working code (the first snippet in that post) to the broken code (the second snippet). You fixed the name:, gid:, state: and loop: lines, but you didn’t fix the when: conditions.
[Edit: on second reading, I see you didn’t actually fix those lines. My mistake.]

The most important next steps are to (a) read the error messages (b) believe them when they say there’s a problem with your code.

1 Like

Please stop doing that! The result you are seeing is exactly what should be produced given the inputs you’ve shown us. The bug tracker on GitHub is for pointing out things that need to be fixed in Ansible, not for explaining to users why their code doesn’t do what they expect. Filing errant bug reports wastes time of other people. This forum is the correct way to get help with these issues.

3 Likes

Okay, so you went with the dict2items option. Here is the code you were given for that:

    - name: User management set global groups macOS
      tags:
        - user_mgmt
        - admin_accounts
      ansible.builtin.group:
        name:  "{{ item.key }}"
        gid:   "{{ item.value.gid | mandatory }}"
        state: "{{ item.value.state | default('present') }}"
      loop: '{{ global_groups | dict2items  }}'
      when:
        - (item.value.state | default('present')) == 'present'

This is the code you ran:

- name: user management set global groups macOS
  tags:
    - user_mgmt
    - admin_accounts
  group:
    name: "{{ item.key }}"
    gid: "{{ item.gid }}"
    state: "{{ item.state | default('present') }}"
  loop: "{{ test_global_groups | dict2items }}"
  when:
    - (test_global_groups[item].state|default('present')) == 'present'

You see that they are different? Please make them not be different. Run the code you were told would work, and if it produces an error we can move on to fixing that error. Until then you’re just running into errors that you’ve already been told how to fix.

EDIT: Okay, they can be a little different, as a treat. Here’s yet another working solution that’s closer to how I would actually write the task, which means:

  • fixing the other condition that up until now we’ve been ignoring because it won’t result in an error.
  • removing the currently useless templating of state: (this can only ever result in present given the when: condition).
  • getting rid of the unnecessary mandatory.
- name: User management set global groups macOS
  tags:
    - user_mgmt
    - admin_accounts
  ansible.builtin.group:
    name: "{{ item.key }}"
    gid: "{{ item.value.gid }}"
    state: present
  loop: "{{ global_groups | dict2items }}"
  when:
    - (item.value.state | default('present')) == 'present'
    - item.key not in skip_groups
2 Likes

Let’s take your latest “bug report” step by step, since you either refuse to read the previous explanations or are incapable of asking questions about the parts that confuse you.

You were told to use:

gid: "{{ item.value.gid }}"

You instead used:

gid: "{{ item.gid }}"

then tried to claim that the resulting error is a bug in Ansible. It’s not.

You have:

global_groups:
  production_ansible:
    gid: 10001
  staging_ansible:
    gid: 20001
  grafana:
    gid: 10501
  prometheus:
    gid: 10502
  zookeeper:
    gid: 10503
  rundeck:
    gid: 10504
  nginx:
    gid: 10505
  gnupgserver:
    gid: 10506
  sequoia:
    gid: 10507

You want to loop over this, so you use loop with dict2items:

    - debug:
        msg: "{{ item }}"
      loop: "{{ global_groups | dict2items }}"

This outputs:

TASK [debug] *******************************************************************
ok: [localhost] => (item={'key': 'production_ansible', 'value': {'gid': 10001}}) => {
    "msg": {
        "key": "production_ansible",
        "value": {
            "gid": 10001
        }
    }
}
ok: [localhost] => (item={'key': 'staging_ansible', 'value': {'gid': 20001}}) => {
    "msg": {
        "key": "staging_ansible",
        "value": {
            "gid": 20001
        }
    }
}
ok: [localhost] => (item={'key': 'grafana', 'value': {'gid': 10501}}) => {
    "msg": {
        "key": "grafana",
        "value": {
            "gid": 10501
        }
    }
}
ok: [localhost] => (item={'key': 'prometheus', 'value': {'gid': 10502}}) => {
    "msg": {
        "key": "prometheus",
        "value": {
            "gid": 10502
        }
    }
}
ok: [localhost] => (item={'key': 'zookeeper', 'value': {'gid': 10503}}) => {
    "msg": {
        "key": "zookeeper",
        "value": {
            "gid": 10503
        }
    }
}
ok: [localhost] => (item={'key': 'rundeck', 'value': {'gid': 10504}}) => {
    "msg": {
        "key": "rundeck",
        "value": {
            "gid": 10504
        }
    }
}
ok: [localhost] => (item={'key': 'nginx', 'value': {'gid': 10505}}) => {
    "msg": {
        "key": "nginx",
        "value": {
            "gid": 10505
        }
    }
}
ok: [localhost] => (item={'key': 'gnupgserver', 'value': {'gid': 10506}}) => {
    "msg": {
        "key": "gnupgserver",
        "value": {
            "gid": 10506
        }
    }
}
ok: [localhost] => (item={'key': 'sequoia', 'value': {'gid': 10507}}) => {
    "msg": {
        "key": "sequoia",
        "value": {
            "gid": 10507
        }
    }
}

You can clearly see that these items do not have gid as a top-level key, so it’s expected that templating {{ item.gid }} will result in an error.

    - debug:
        msg: "{{ item.gid }}"
      loop: "{{ global_groups | dict2items }}"
TASK [debug] *******************************************************************
[ERROR]: Task failed: Finalization of task args for 'ansible.builtin.debug' failed: Error while resolving value for 'msg': object of type 'dict' has no attribute 'gid'

They do have a top-level value key that contains gid, so accessing it the way you were told to five days ago will work.

    - debug:
        msg: "{{ item.value.gid }}"
      loop: "{{ global_groups | dict2items }}"
TASK [debug] *******************************************************************
ok: [localhost] => (item={'key': 'production_ansible', 'value': {'gid': 10001}}) => {
    "msg": 10001
}
ok: [localhost] => (item={'key': 'staging_ansible', 'value': {'gid': 20001}}) => {
    "msg": 20001
}
ok: [localhost] => (item={'key': 'grafana', 'value': {'gid': 10501}}) => {
    "msg": 10501
}
ok: [localhost] => (item={'key': 'prometheus', 'value': {'gid': 10502}}) => {
    "msg": 10502
}
ok: [localhost] => (item={'key': 'zookeeper', 'value': {'gid': 10503}}) => {
    "msg": 10503
}
ok: [localhost] => (item={'key': 'rundeck', 'value': {'gid': 10504}}) => {
    "msg": 10504
}
ok: [localhost] => (item={'key': 'nginx', 'value': {'gid': 10505}}) => {
    "msg": 10505
}
ok: [localhost] => (item={'key': 'gnupgserver', 'value': {'gid': 10506}}) => {
    "msg": 10506
}
ok: [localhost] => (item={'key': 'sequoia', 'value': {'gid': 10507}}) => {
    "msg": 10507
}

Now please, stop wasting your time and use the working code that you were given instead of clinging to the broken code that you already know doesn’t work.

3 Likes

TFW you’ve filed your seventeeth bug report for your invalid code that doesn’t work to suddenly start working and people keep asking you to read what they write

1 Like

The syntax is correct!

How do I debug and trace it to a package in python and/or ansible please?

I’ve been trying to figure this out forever!

1 Like

I made a python virtual environment for python and I still get the same error!

How do I isolate it further please?

The error is not related to your environment. It is a result of running invalid code. You have been told how to fix your code multiple times, and I am now done trying to help you.

2 Likes

No, it is not correct. Below, I’ve commented out the broken lines of your code, and inserted the correct lines below each of them.

- name: user management set global groups macOS
  tags:
    - user_mgmt
    - admin_accounts
  group:
    name: "{{ item.key }}"
  # gid: "{{ item.gid }}"        # Broken: "item" has no "gid" at the top level.
    gid: "{{ item.value.gid }}"  # Fixed!
  # state: "{{ item.state | default('present') }}"  # Broken: if "state" exists,
  #   it would be inside the "item.value" dict.
    state: "{{ item.value.state | default('present') }}"
  loop: "{{ test_global_groups | dict2items }}"
  when:
  # - (test_global_groups[item].state|default('present')) == 'present' # Broken:
  #     "item" is a dict, not a string that you can use as an index into "test_global_groups".
    - (test_global_groups[item.key].state | default('present')) == 'present'
  # - item not in skip_groups  # Broken: "item" is a dict. It will never be "in skip_groups".
    - item.key not in skip_groups # Maybe fixed: is "skip_groups" a list?

You must fix all four of these problems or your task will continue to fail.

[Technically, the syntax is “correct”. It’s that the expressions are invalid; they don’t match the structure of the data, and therefore the task won’t run as it is.]

Please do ask any questions you still have, and post whatever YAML inputs and resulting errors that aren’t clear to you. But repeatedly posting that there’s nothing wrong with your code when experienced users have repeatedly said otherwise has cost you many unproductive days, so you may want to reconsider that strategy; it hasn’t worked yet.

1 Like

Buddy, don’t keep opening issues about this in the homebrew github repository either. Issue with ansible-playbook with loops! Playbook and role say · Issue #245465 · Homebrew/homebrew-core · GitHub this isn’t a problem with homebrew or Ansible. Open source contributors and maintainers are already stretched very thin, they don’t need bogus issues like this gumming up legitimate issues. Just implement the code the two people here have given you.

1 Like

Too bad!

I filed a bug again with Homebrew and Ansible:

Last week - six days ago now - you said

Why did you take that suggestion and not any of the other suggestions?

If someone in one of those other projects’ bug trackers asked you to try this or that or the other thing, would you do it then? What do you expect people in those other projects to do for you that hasn’t been done here? How important to you is getting this play working? Not very, evidently, because fixing this is much easier that filing bogus bug reports in multiple projects. At this point, it no longer appears you’re seeking help with this code, but I don’t know what you’re really playing at.

Three hours ago I gave you working code that will fix your problem. Have you run it yet?

3 Likes

@Gittes Hi,
I’m part of the Ansible Community Engineering team at Red Hat (who run this forum, and look after Ansible on GitHub).

It seems like you’ve gotten stuck, and are asking for help on the Ansible Forum, which is the right thing to do.

However you appear to be opening multiple GitHub issues (and against homebrew) about the same issue, as well this forum post and this one.

I can see multiple people have kindly offered you guidance, including giving you code to test.

When you signed up for your Ansible Forum account, you acknowledged and said you’d follow the Ansible Code of Conduct

Your actions

  • Only use this forum thread
  • Carefully read the replies
  • Rather than saying “it doesn’t work” include a clear Ansible Tasks and the the full output and error message

If you continue to spam you will be banned from Ansible Forum and Ansible’s GitHub organization.

4 Likes

Who do I contact on this forum via email to delete these post and conversation please?

How do I get someone to also delete this conversation thread too please?