Getting a with_dict error when reading through dict: - yaml

This may not be an issue on the module but certainly for me and I hope I can get an answer from here.
I am trying to run a play book with variables defined in group_vars folder. however when I run the playbook Ansible throws an error saying "fatal: [spine111] => with_dict expects a dict".
What am I doing wrong?
My /roles/tasks/main.yml is:
- name: peerlink.4094 configuration for peer1 only
cl_interface:
name: "{{ item.key }}"
ipv4: "{{ item.value.ipv4 }}"
alias_name: "{{ item.value.alias_name }}"
clagd_enable: "{{ item.value.clagd_enable }}"
clagd_peer_ip: "{{ item.value.clagd_peer_ip }}"
clagd_priority: "{{ item.value.clagd_priority }}"
clagd_sys_mac: "{{ item.value.clagd_sys_mac }}"
clagd_args: "{{ item.value.clagd_args }}"
applyconfig: 'yes'
with_dict: cl_interfaces[inventory_hostname]
notify: reload networking
tags: clagd
And my group_vars/peer output is:
cl_interface:
spine111:
peerlink.4094:
alias_name: "Clag_PeerLink"
ipv4: "169.254.1.1/30"
clagd_enable: "yes"
clagd_peer_ip: "169.254.1.2"
clagd_priority: "4096"
clagd_args: "-vm"
clagd_sys_mac: "00:00:00:00:00:01"
What am I doing wrong here?
Thanks in advance...

I found the answer with the help of Jason https://community.cumulusnetworks.com/cumulus/topics/getting-a-with-dict-error-when-reading-through-dict
There was an additional "s" when the discretionary was being called. :(
And by the way there was one more error in my variable file that was related to indenting... I had 2 spaces instead of 4 :(

Related

Ansbile issue replacing variables

I am new to ansible and I am using variables to use awx polls, the case is that when I want to use these variables in the get_url task
- name: Download Artifact
get_url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
username: "{{ username }}"
password: "{{ password }}"
When I launch an ansible-playbook from my local I get this error
The offending line appears to be:
get_url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Does anyone know what can be due?
I think the problem is with the missing url key (docs)
Try the following
- name: Download Artifact
get_url:
url: "{{ url_artifact }}"
dest: "/tmp/artifacts/{{ app_name }}"
username: "{{ username }}"
password: "{{ password }}"

Ansible "item is undefined" when using {{ item }} in "vars" section

I have some codes like below, I want to iterate each host in groups['A'] and groups['B'] to create the group.
- name: Create a group
group:
name: "test_group"
state: "present"
delegate_to: "{{ item }}"
vars:
ansible_ssh_user: "{{ lookup('env', 'USER') }}#user#{{ item }}"
with_items:
- "{{ groups['A'] }}"
- "{{ groups['B'] }}"
Because I want to modify the ansible ssh connection user to connect to the "delegate_to" host, I override the ansible_ssh_user in this task, but it won't work and give me the error message like
FAILED! => {"msg": "'item' is undefined"}
But if I comment out the lines of
vars:
ansible_ssh_user: "{{ lookup('env', 'USER') }}#user#{{ item }}"
It gives no errors.
try changing the var to:
ansible_ssh_user: "{{ lookup('env', 'USER') }}#user#{{ ansible_hostname }}
this works fine for me:
- name: 'install public key on every server'
authorized_key:
user: '{{ myuser}}'
key: "{{ myuser.ssh_public_key }}"
delegate_to: '{{ item }}'
with_items:
- '{{ groups["A"] }}'
- '{{ groups["B"] }}'
- '{{ groups["C"] }}'
maybe you could try
but before I delegated a set_fact and recovered it locally...
Finally, I got a workaround, it involves all groups I need to use in my playbook.
And use "when" condition like
delegate_to: "{{ item }}"
with_items:
- "{{ groups['A'] }}"
- "{{ groups['B'] }}"
when: "inventory_hostname == item"
to let the task only run on the hosts mentioned in the "with_items" section.
It's not a very cool workaround but works for me...
Thank you for looking at this problem!

ERROR! couldn't resolve module/action 'kube'

I use the kubespray v2.11.2 to setup a kubernetes cluster. However, the error occurred with "couldn't resolve module/action 'kube'" :
- name: Kubernetes Apps | Add policies, roles, bindings for PodSecurityPolicy
kube:
name: "{{ item.item.name }}"
kubectl: "{{ bin_dir }}/kubectl"
resource: "{{ item.item.type }}"
filename: "{{ kube_config_dir }}/{{ item.item.file }}"
state: "latest"
register: result
until: result is succeeded
retries: 10
delay: 6
with_items: "{{ psp_manifests.results }}"
when:
- inventory_hostname == groups['kube-master'][0]
- not item is skipped
loop_control:
label: "{{ item.item.file }}"
which is in https://github.com/kubernetes-sigs/kubespray/blob/324106e91e3febdf75228b0883fff170bb28984c/roles/kubernetes-apps/cluster_roles/tasks/main.yml#L43
Is there I miss something to create a "new" module/action with 'kube'?
Thanks in advance!
Ok, let me answer by myself.
Obviously, the reason is 'kube' module absent. So, it must be somewhere to define the 'kube' module.
Yes, it is in the kubespray/library/kube.py

Ansible - skip undefined variable in dict

I`m using ipa_user module to setup users. There is variable passsword which force new password.
For some users (when var is not in dict) I would like to skip it in iteration, but it always fail.
This is snippet from my playbook. Ansible version is 2.7
task:
- name: adding ipa users
ipa_user:
name: "{{ item.value.login }}"
state: "{{ item.value.state }}"
givenname: "{{ item.value.givenname }}"
sn: "{{ item.value.surname }}"
mail: "{{ item.value.mail }}"
telephonenumber: "{{ item.value.telephonenumber }}"
title: "{{ item.value.title }}"
password: "{{ item.value.password }}" <<- to be skipped if not found
ipa_host: ipa.gdi.telekom.de
ipa_user: admin
ipa_pass: "{{ ipa_pass }}"
with_dict: "{{ipausers}}"
when: item.key in ipausers.keys()
register: output_ipa_users
Log:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'password'\n\nThe error appears to have been in '/builds/gitlab/infra/user-management/roles/free-ipa/tasks/main.yml': line 13, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: adding ipa users\n ^ here\n"}
Note: I tried it with:
with_dict: "{{ipausers|default({})}}"
ignore_errors: yes
without success
Not sure if it'll be much help to you now but for others than stumble on this post, I ended up with something like below for a similar problem. I'm using Ansible 2.7.8.
- name: Creating user accounts...
user:
name: "{{ item.name }}"
state: "{{ item.state }}"
comment: "{{ item.comment | default(omit) }}"
group: "{{ item.groups is defined | ternary((item.groups|default([]))[0], omit) }}"
groups: "{{ item.groups | default(omit) }}"
password: "{{ item.password_hash | default(omit) }}"
uid: "{{ item.uid | default(omit) }}"
with_items: "{{ managed_users }}"
The solution is
group: "{{ item.groups is defined | ternary((item.groups|default([]))[0], omit) }}"
If groups isn't in item then Ansible will omit the group part of this tasks but jinja2 will evaluate item.groups[0] anyway. So to allow for this we have to use item.groups|default([]) so jinja2 uses an empty list when groups isn't defined instead of throwing a 'dict object' has no attribute error. The omit part is similar to the default(omit) filter where Ansible simply omits the option from the task.
Lubo's problem is a little simpler so using just default(omit) filter should work. That said as password is required so the entire task should be skipped with a conditional.
- name: adding ipa users
ipa_user:
name: "{{ item.value.login }}"
state: "{{ item.value.state }}"
givenname: "{{ item.value.givenname }}"
sn: "{{ item.value.surname }}"
mail: "{{ item.value.mail }}"
telephonenumber: "{{ item.value.telephonenumber }}"
title: "{{ item.value.title }}"
password: "{{ item.value.password | default(omit) }}" #<-- would be omitted
ipa_host: ipa.gdi.telekom.de
ipa_user: admin
ipa_pass: "{{ ipa_pass }}"
with_dict: "{{ipausers}}"
when: item.key in ipausers.keys() and item.key.password is defined #<-- second check for when password is not defined.
register: output_ipa_users
If you want to completely skip the ipa_user module execution when password is not defined, check for its presence in your when clause:
when: item.value.password | default('') | length > 0
If you want to execute the ipa_user module without specifying a password for user if it does not exists, use the omit placeholder in your module params:
password: "{{ item.value.password | default(omit) }}"
Note: your current when clause can be removed. It will always return true as you are looping over a dict and later checking if the current key in the loop is part of that dict.
There is a special omit variable to omit module parameters.
password: "{{ item.value.password|default(omit) }}"
To make a playbook or a role reusable it is a good idea to declare all parameters of a module in the task and default(omit) parameters that are not required.

Ansible : defined variable or output from ansible task as a variable

Hi I am trying to get a task setup which is as below.
- name: Create a route53 record for RDS instance.
route53:
state: present
aws_access_key: "{{ aws_create_route53_record.access_key }}"
aws_secret_key: "{{ aws_create_route53_record.secret_key }}"
zone: "{{ aws_create_route53_record.zone }}"
hosted_zone_id: "{{ aws_create_route53_record.id }}"
type: "{{ aws_create_route53_record.type }}"
value: "{{ aws_create_route53_record.value }}"
record: "{{ aws_create_route53_record.record }}"
private_zone: "{{ aws_create_route53_record.private_zone }}"
ttl: 30
Now I know passing variable from group_vars/all.yml I can define aws_create_route53_record.value in group_vars/all.yml and use it however in certain cases there is possibility where I am going to use this task as role and want to pass aws_create_route53_record.value runtime from previous task to this one and use it in creation of route53 record. for e.g. creating a rds instance using ansible task and use rds endpoint as value for route53_record
Any suggestion would help a lot. Thanks
Note: I've checked rds module page for return values which I thought would use instantly to solve this however there is no provision for endpoint return in it.
I was able to solve my problem by using a variable in my task and initially assigning it the value of group_vars variable and putting a condition that if after assigning a value of group_vars variable, variable is still blank then take a value from last task. Below is the code snippet which works fine. You would need to register variable from previous task as endpoint_host
---
-
name: "Set facts of record value"
set_fact:
record_value: "{{ aws_create_route53_record.value }}"
-
name: "If record value not present, Look for endpoint-host variable"
set_fact:
record_value: "{{ endpoint_host }}"
when: "aws_create_route53_record.value == \"\""
-
name: "Create a route53 record for RDS instance."
route53:
aws_access_key: "{{ aws_create_route53_record.access_key }}"
aws_secret_key: "{{ aws_create_route53_record.secret_key }}"
hosted_zone_id: "{{ aws_create_route53_record.hosted_zone_id }}"
private_zone: "{{ aws_create_route53_record.private_zone }}"
record: "{{ aws_create_route53_record.record }}"
state: present
ttl: 30
type: "{{ aws_create_route53_record.type }}"
value: "{{ record_value }}"
zone: "{{ aws_create_route53_record.zone }}"
Hope this helps.

Resources