Syntax to pass dynamic variables to include_tasks along with with_item in Ansible playbook - ansible

Executing parent.yml which in turn calls child.yml playbook for execution with dynamic variables.
Variables from parent.yml aren`t interpolated inside child.yml playbook. Correct me if I am using correct syntax?
Parent.yml
- name: Main playbook to call MySQL backup
hosts: localhost
gather_facts: no
tasks:
- include_task: child.yml
vars:
var1: "{{ item.name }}"
var2: "{{ item.db_name }}"
with_items:
- { name: '10.10.10.01', db_name: 'prod1' }
- { name: '10.10.10.02', db_name: 'prod2' }
child.yml (Takes mysqldump from managed DB)
- name: MySQL dump
hosts: localhost
#gather_facts: no
#vars:
# v1: "{{ var1 }}"
# v2: "{{ var2 }}"
tasks:
- name: Executing the shell script
shell: 'mysqldump -h "{{ var1 }}" -u"ansi" -p"*****" "{{ var2 }}"| gzip > /tmp/mysql_dump/"{{ var2 }}"_`date +%Y%m%d-%H%M`.gz'
fatal: [127.0.0.1]: FAILED! => {"reason": "no action detected in task. This often indicates a misspelled module name, or incorrect module path.\n\nThe error appears to be in '/home/ansible/playbooks/DBpatch/Linux/child.yml': line 1, 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: MySQL dump\n ^ here\n"}

include_task expects a list of tasks but you give it a complete playbook.
Child.yml should only contain what is currently below the line "tasks:".
See also https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_includes.html

Related

ansible playbook: print custom message if hosts variable is not defined

The simple playbook
---
- name: NTP client
# hosts: all:!ntpserver
hosts: "{{ target_hosts }}"
roles:
- ntp_client
can be executed using
ansible-playbook -i hosts.yml -e target_hosts=<target host> <path to playbook> --ask-become-pass
This works just fine when target_hosts is set. In case target_hosts isn't set it obviously fails with
ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: 'target_hosts' is undefined
How do I print a custom message such as
The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'.
Note, I am aware that a default can be set via a hosts line like
hosts: "{{ target_hosts | default('all:!ntpserver') }}"
Add a localhost play for validating input arguments as given below. This will fail with a custom message if the 'target_hosts' var is not defined.
---
- name: Validate target_host variable
hosts: localhost
tasks:
- fail:
msg: The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'.
when: target_hosts is not defined
- name: NTP client
# hosts: all:!ntpserver
hosts: "{{ target_hosts }}"
roles:
- ntp_client
Use the filter mandatory. For example,
- hosts: "{{ target_hosts|mandatory('The variable target_hosts is mandatory') }}"
Example of a complete playbook
shell> cat pb.yml
- hosts: "{{ target_hosts|mandatory(err001) }}"
vars:
err001: >-
The variable 'target_hosts' is not set,
use e.g. '-e target_hosts=all:!ntpserver'
tasks:
- debug:
msg: hello
gives
shell> ansible-playbook pb.yml
ERROR! The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'

Ansible - set_fact syntax issue

In the below playbook, can someone please tell me what is wrong with the syntax of the final set_fact statement. If i explicitly specify the hostname R9 (as per the first set_fact), then it works without issue. But if I assign a variable to have a value of R9, and then use this in the final set_fact statement, I get the error shown below. Argh.
---
- hosts: all
gather_facts: no
vars:
ansible_network_os: ios
ansible_connection: network_cli
tasks:
- ios_command:
commands: show ip arp
register: results
- set_fact:
some_var: "{{ hostvars['R9'].results }}"
- set_fact:
hostname: "R9"
- set_fact:
another_var: "{{ hostvars['{{hostname}}'].results }}"
- debug:
var=some_var
- debug:
var=another_var
Error:
fatal: [R7]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: "hostvars['{{hostname}}']" is undefined
The error appears to be in '/root/ansible/Rapid/testsetfact.yml': line 20, column 6, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- set_fact:
^ here
fatal: [R9]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: "hostvars['{{hostname}}']" is undefined
The error appears to be in '/root/ansible/Rapid/testsetfact.yml': line 20, column 6, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- set_fact:
^ here
you can use the inventory_hostname for your purpose:
- set_fact:
another_var: "{{ hostvars[inventory_hostname].results }}"

Ansible - 'when' is not a valid attribute for a Play

I'm trying to figure out how to "remove" the warning message [WARNING]: Could not match supplied host pattern, ignoring: ps_nodes, by fixing the root cause. The root cause for me is that when we do Linux machine creation we will have the ps_nodes hosts empty. So, I was trying to add the block: + when: (os_type|capitalize) == "Windows", to assure that Play to only execute when os_type is a Windows creation.
How can I achieve that? Because, what I'm trying is to use the when condiction, but looks like it's not possible, and I'm not sure what to search anymore.
Code example:
- name: "Start handling of vm specific delete scripts for Windows machines"
block:
hosts: ps_nodes
any_errors_fatal: false
gather_facts: false
vars:
private_ip_1: "{{ hostvars['localhost']['_private_ip_1']|default('') }}"
scripts: "{{ hostvars['localhost']['scripts'] }}"
sh_script_dir: "{{ hostvars['localhost']['sh_script_dir'] }}"
cred_base_hst: "{{ hostvars['localhost']['cred_base_hst'] }}"
cred_base_gst: "{{ hostvars['localhost']['cred_base_gst'] }}"
newline: "\n"
tasks:
- import_tasks: roles/script/tasks/callWindowsScripts.yml
when: action == 'delete'
when: (os_type|capitalize) == "Windows"
Error using 'when' for a Play:
ERROR! 'when' is not a valid attribute for a Play
The error appears to be in '/opt/projectX/playbooks/create_vm.yml': line 265, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
##############################################################################
- name: \"Start handling of vm specific delete scripts for Windows machines\"
^ here
I think the problem is the indentation. Use 'and':
- name: "Start handling of vm specific delete scripts for Windows machines"
block:
hosts: ps_nodes
any_errors_fatal: false
gather_facts: false
vars:
private_ip_1: "{{ hostvars['localhost']['_private_ip_1']|default('') }}"
scripts: "{{ hostvars['localhost']['scripts'] }}"
sh_script_dir: "{{ hostvars['localhost']['sh_script_dir'] }}"
cred_base_hst: "{{ hostvars['localhost']['cred_base_hst'] }}"
cred_base_gst: "{{ hostvars['localhost']['cred_base_gst'] }}"
newline: "\n"
tasks:
- import_tasks: roles/script/tasks/callWindowsScripts.yml
when: action == 'delete' and (os_type|capitalize) == "Windows"
Got it,
What if you use a host that exists, like localhost, check the number of hosts in ps_nodes and delegate_to them?
Something like this:
hosts: localhost
vars:
tasks:
- import_tasks: roles/script/tasks/callWindowsScripts.yml
delegate_to: ps_nodes
when: {{ ps_nodes | length > 0}}
Same issue and fixed by "indent":
- hosts: test
roles:
- role: test
vars:
k: 1
when: "'dbg' in ansible_run_tags"

Ansible Script Module Not Interpreting Variable

I am having an issue with the Ansible script module interpreting a with_items variable.
vsa_deploy_config/tasks/main.yml:
- name: Create VSA scripts for center
template:
src: vsa_deploy.ps1.j2
dest: "/opt/ansible/roles/vsa_deploy_config/files/{{ item.vsa_hostname }}.ps1"
when: target == "local"
with_items:
- "{{ vsa_center }}"
- name: Deploy VSAs on Center
script: "files/{{ item.vsa_hostname }}.ps1"
register: out
when: target == "win_center"
- debug: var=out
with_items:
- "{{ vsa_center }}"
vsa_deploy_config/vars/main.yml:
---
vsa_center:
- vcsa_hostname: 10.10.10.74
vcsa_username: administrator#vsphere.local
vcsa_password: password
vcsa_datacenter: DataCenter1
vsa_rdm_lun: 02000000006006bf1d58d25a1020d292f8fcfb22b3554353432d4d
vsa_hostname: sm01-ct01
vsa_mgmt_ip: 10.10.10.75
vsa_mgmt_netmask: 255.255.255.192
vsa_mgmt_gw: 10.10.10.65
vsa_mgmt_ns: 10.10.10.92
vsa_mgmt_pg: SC-MGMT
vsa_mgmt_moref: Network:network-13
vsa_iscsi_ip: 192.168.2.1
vsa_iscsi_netmask: 255.255.255.0
vsa_iscsi_pg: ISCSI
vsa_iscsi_moref: Network:network-22
vsa_mirror_ip: 192.168.5.1
vsa_mirror_netmask: 255.255.255.0
vsa_mirror_pg: Mirror
vsa_mirror_moref: Network:network-23
esxi_hostname: 10.10.10.72
esxi_datastore: DS-01
- vcsa_hostname: 10.10.10.74
vcsa_username: administrator#vsphere.local
vcsa_password: password
vcsa_datacenter: DataCenter1
vsa_rdm_lun: 02000000006006bf1d58d25dd0210bb356a78344e5554353432d4d
vsa_hostname: sm02-ct01
vsa_mgmt_ip: 10.10.10.76
vsa_mgmt_netmask: 255.255.255.192
vsa_mgmt_gw: 10.10.10.65
vsa_mgmt_ns: 10.10.10.92
vsa_mgmt_pg: SC-MGMT
vsa_mgmt_moref: Network:network-13
vsa_iscsi_ip: 192.168.2.2
vsa_iscsi_netmask: 255.255.255.0
vsa_iscsi_pg: ISCSI
vsa_iscsi_moref: Network:network-22
vsa_mirror_ip: 192.168.5.2
vsa_mirror_netmask: 255.255.255.0
vsa_mirror_pg: Mirror
vsa_mirror_moref: Network:network-23
esxi_hostname: 10.2.120.73
esxi_datastore: DS-02
When I run the playbook I get the following error:
TASK [vsa_deploy_config : Deploy VSAs on Center] *******************************************************************************
fatal: [auto-win1.lab.com]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'item' is undefined\n\nThe error appears to have been in '/opt/ansible/roles/vsa_deploy_config/tasks/main.yml': line 10, 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: Deploy VSAs on Center\n ^ here\n"}
to retry, use: --limit #/opt/ansible/powershell.retry
The first task using the template module interprets the item.vsa_hostname variable correctly, but the script module does not. Is the script module not capable of using with_items?
There is no with_items for your script task:
- name: Deploy VSAs on Center # -\
script: "files/{{ item.vsa_hostname }}.ps1" # \
register: out # / This is task1
when: target == "win_center" # -/
- debug: var=out # -\
with_items: # > This is task2
- "{{ vsa_center }}" # -/
I guess you'd want to move debug to the very bottom:
- name: Deploy VSAs on Center
script: "files/{{ item.vsa_hostname }}.ps1"
register: out
when: target == "win_center"
with_items: "{{ vsa_center }}"
- debug: var=out
P.S. also there is no need to feed unnecessary nested list into with_items.
just move the line - debug: var=out to the end of the file and it will work

Return Variable from Included Ansible Playbook

I have seen how to register variables within tasks in an ansible playbook and then use those variables elsewhere in the same playbook, but can you register a variable in an included playbook and then access those variables back in the original playbook?
Here is what I am trying to accomplish:
This is my main playbook:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
roles:
- some_role
sub-playbook.yml:
---
- hosts: localhost
tasks:
- name: Collect info from Jenkins Job
script: whatever.py --url "{{ job_url }}"
register: jenkins_artifacts
I'd like to be able to access the jenkins_artifacts results back in main_playbook if possible. I know you can access it from other hosts in the same playbook like this: "{{ hostvars['localhost']['jenkins_artifacts'].stdout_lines }}"
Is it the same idea for sharing across playbooks?
I'm confused what this question is about. Just use the variable name jenkins_artifacts:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
debug:
var: jenkins_artifacts
This might seem complicated but I love doing this in my Playbooks:
rc defines the name of the variable which contains the return value
ar gives the arguments to the include tasks
master.yml:
- name: verify_os
include_tasks: "verify_os/main.yml"
vars:
verify_os:
rc: "isos_present"
ar:
image: "{{ os.ar.to_os }}"
verify_os/main.yml:
---
- name: check image on device
ios_command:
commands:
- "sh bootflash: | inc {{ verify_os.ar.image }}"
register: image_check
- name: check if available
shell: "printf '{{ image_check.stdout_lines[0][0] }}\n' | grep {{ verify_os.ar.image }} | wc -l"
register: image_available
delegate_to: localhost
- set_fact: { "{{ verify_os.rc }}": "{{ true if image_available.stdout == '1' else false }}" }
...
I can now use the isos_present variable anywhere in the master.yml to access the returned value.

Resources