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

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

Related

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.

Loop through variables in task that has another list embedded in the variables

I am looking to loop through a list of variables. I have it looping through the of variables using with_items, however the catch is there is a list within that variables list that needs to have a different subset / number of variables that i need to iterate through as well.
I have tried different filters to include with_nested, with_subelements, and with_items. I know that they are moving towards loops as the primary driver moving forward so any solution ideally would leverage the ansible path moving forward. I am looking at having an "inner" loop or an external task that will iterate through the vlans_list and input that data as its to that point.
group Variables
vnic_templates:
- name: vNIC-A
fabric: A
mac_pool: testmac1
mtu: 1500
org_dn: org-root
redundancy_type: none
state: present
template_type: initial-template
vlans_list: ### THE PROBLEM CHILD
- name: vlan2
native: 'no'
state: present
- name: vlan3
native: 'no'
state: present
The actual task - i have issues when i have to input multiple vlans. The vnic template will have a 1 to one relationship however the vlans_list could be 1 vnic_template to many vlans.
ucs_vnic_template:
hostname: "{{ ucs_manager_hostname }}"
username: "{{ ucs_manager_username }}"
password: "{{ ucs_manager_password }}"
name: "{{ item.name }}"
fabric: "{{ item.fabric }}"
mac_pool: "{{ item.mac_pool }}"
mtu: "{{ item.mtu }}"
org_dn: "{{ item.org_dn }}"
redundancy_type: "{{ item.redundancy_type }}"
state: "{{ item.state }}"
template_type: "{{ item.template_type }}"
vlans_list:
- name: "{{ item.1.name }}"
native: "{{ item.1.native }}"
state: "{{ item.1.present }}"
# loop: "{{ vnic_templates | subelements('vlans_list') }}"
with_items:
- "{{ vnic_templates }}"
I am starting down the road of adding an include vlan_list.yml outside of this task but no familiar with out to do that.
Actual results are
The task includes an option with an undefined variable. The error was: 'item' is undefined\n\n
I need the create a single vnic template with multiple vlans defined in that list.
Another engineer i work with was able to solve the question. By the way the variables are laid out we were able to easily just change the code
Change this:
vlans_list:
- name: "{{ item.1.name }}"
native: "{{ item.1.native }}"
state: "{{ item.1.present }}"
To this:
vlans_list: "{{ item.vlans_list }}"
Full Code listed below.
- name: Add vNIC Templates
ucs_vnic_template:
hostname: "{{ ucs_manager_hostname }}"
username: "{{ ucs_manager_username }}"
password: "{{ ucs_manager_password }}"
name: "{{ item.name }}"
fabric: "{{ item.fabric }}"
mac_pool: "{{ item.mac_pool }}"
mtu: "{{ item.mtu }}"
org_dn: "{{ item.org_dn }}"
redundancy_type: "{{ item.redundancy_type }}"
state: "{{ item.state }}"
template_type: "{{ item.template_type }}"
vlans_list: "{{ item.vlans_list }}"
with_items:
- "{{ vnic_templates }}"

Start Cloudformation stacks in parallel from ansible

I am starting multiple cloudformation stacks in a "with_items" loop in ansible like this:
- name: Create CF stack in AWS
cloudformation:
stack_name: "{{ item.name }}"
state: "present"
template: "{{ item.name }}.py.json"
template_parameters: "{{ item.template_parameters }}"
with_items: "{{ CF_TEMPLATE_ITEMS }}"
Can I somehow make ansible start this stacks in parallel?
Using asynchronous tasks in a fire-and-forget scheme (and waiting for them to finish in a separate task) should work since ansible 2.0:
- name: Create CF stack in AWS
async: 100
poll: 0
cloudformation:
stack_name: "{{ item.name }}"
state: "present"
template: "{{ item.name }}.py.json"
template_parameters: "{{ item.template_parameters }}"
with_items: "{{ CF_TEMPLATE_ITEMS }}"
register: cf_stack_async_results
- async_status:
jid: "{{item.ansible_job_id}}"
with_items: cf_stack_async_results.results
register: cf_stack_async_poll_results
until: cf_stack_async_poll_results.finished
retries: 30

how to get the exit status of the each task in ansible

I have 3 task in my ansible yml file as below.
---
- name: Instance provisioning
local_action:
module: ec2
region: "{{ vpc_region }}"
key_name: "{{ ec2_keypair }}"
instance_type: "{{ instance_type }}"
image: "{{ ec2_image}}"
zone: "{{ public_az }}"
volumes:
- device_name: "{{ device }}"
volume_type: "{{ instance_volumetype }}"
volume_size: "{{ volume }}"
delete_on_termination: "{{ state }}"
instance_tags:
Name: "{{ instance_name }}_{{ release_name }}_APACHE"
environment: "{{ env_type }}"
vpc_subnet_id: "{{ public_id }}"
assign_public_ip: "{{ public_ip_assign }}"
group_id: "{{ sg_apache }},{{ sg_internal }}"
wait: "{{ wait_type }}"
register: ec2
- name: adding group to inventory file
lineinfile:
dest: "/etc/ansible/hosts"
regexp: "^\\[{{ release_name }}\\]"
line: "[{{ release_name }}]"
state: present
- name: adding apache ip to hosts
lineinfile:
dest: "/etc/ansible/hosts"
line: "{{ item.private_ip }} name=apache dns={{ item.public_dns_name }}
with_items: ec2.instances
Now i want to check the exit status of each task whether it is success or failure.
If any one of the task fails my other task should not execute.
Please advice how to write an ansible playbook
In your first task, you have register the output to ec2.
now use fail module to stop the play if the task fails.
Ex.
register: ec2
fail:
when: "ec2.rc == 1"
here rc is the return code of the command .. we are assuming 1 for fail and 0 for success.
use fail module after every task.
Let me know if it works for you ..
Register a variable in each task and then check it in the next task. See http://docs.ansible.com/ansible/playbooks_tests.html#task-results
This is already the default behavior in Ansible. If a task fails, the Playbook aborts and reports the failure. You don't need to build in any extra functionality around this.
Maybe playbook blocks and it's error handling is to help you?
Kumar
if You want to check each task output if it is success or failure do this,
---
- name: Instance provisioning
local_action:
module: ec2
region: "{{ vpc_region }}"
key_name: "{{ ec2_keypair }}"
instance_type: "{{ instance_type }}"
image: "{{ ec2_image}}"
zone: "{{ public_az }}"
volumes:
- device_name: "{{ device }}"
volume_type: "{{ instance_volumetype }}"
volume_size: "{{ volume }}"
delete_on_termination: "{{ state }}"
instance_tags:
Name: "{{ instance_name }}_{{ release_name }}_APACHE"
environment: "{{ env_type }}"
vpc_subnet_id: "{{ public_id }}"
assign_public_ip: "{{ public_ip_assign }}"
group_id: "{{ sg_apache }},{{ sg_internal }}"
wait: "{{ wait_type }}"
register: ec2
- name: adding group to inventory file
lineinfile:
dest: "/etc/ansible/hosts"
regexp: "^\\[{{ release_name }}\\]"
line: "[{{ release_name }}]"
state: present
when: ec2 | changed
register: fileoutput
- name: adding apache ip to hosts
lineinfile:
dest: "/etc/ansible/hosts"
line: "{{ item.private_ip }} name=apache dns={{ item.public_dns_name }}
with_items: ec2.instances
when: fileoutput | changed
In your code register a variable in each and every Task if The Task has Changed to True, The Followed Task will execute otherwise it will skip that Task.

Getting a with_dict error when reading through dict:

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 :(

Resources