Why Ansible Playbook skip variable value in a file? - ansible

I have a file contain:
ansible_var:
- '0.0.0.0'
- '1.1.1.1'
- 'variable_01'
I tried to call the ansible_var list in my playbook:
- hosts: myhost
vars:
- test_var: "{{ lookup('vars', ansible_var) }}"
tasks:
- debug:
var: test_var
- name: load yaml file
include_vars:
dir: "./yaml"
files_matching: "file.yaml"
Somehow it read '0.0.0.0' and '1.1.1.1' and skipped 'variable_01'. The output:
> "test_var": [
> "0.0.0.0",
> "1.1.1.1"
> ]
Why is this happen and how to fix this?

Related

Ansible - Using a var from an inventory

I am using ansible inventory file my_inv.yml where I have something this:
all:
hosts:
localhost:
ansible_connection: local
children:
my_env1:
hosts:
my_env.app.domain.com
vars:
my_var_1: "True"
my_var_2: '123'
my_env2:
hosts:
my_env2.app.domain.com
vars:
my_var_1: "True"
my_var_2: '123'
...
I am running a script (myscript.sh env) to call a playbook. Inside that script, It's something like this:
ENVIR="${1}"
ansible-playbook -i inventory/my_inv.yml --extra-vars "ENV=$ENVIR MY_VAR={{hostvars[ENV]['my_var_1']}"
So I want to capture my_var_1 (value true) for my_env1, and send it in the extra-vars. This is not working. How can I do this?
you could launch this playbook by specifying the var ENV in the command:
- name: "tips4"
hosts: all
gather_facts: false
tasks:
- debug:
msg: "{{ hostvars[inventory_hostname].group_names.0}}"
- debug:
msg: "{{ hostvars[inventory_hostname]['my_var_1']}}"
when: "hostvars[inventory_hostname].group_names.0 == ENV"
- set_fact:
toto: "{{ hostvars[inventory_hostname]['my_var_1']}}"
when: "hostvars[inventory_hostname].group_names.0 == ENV"
- debug:
msg: "{{ toto}}"
when: toto is defined

ansible regex_replace IP change

I would like to modify vars for drupal configuration file settings.php with ansible and regex_replace module. My initial var is an IP xxx.xxx.xxx.xxx and I want this as my new var xxx\.xxx\.xxx\.xxx
My playbook:
---
- hosts: localhost
remote_user: cal
become: yes
become_user: cal
tasks:
- set_fact:
ip_front: "10.11.12.13"
ip_front_back: "{{ ip_front | regex_replace('\\.', '\\.') }}"
- name: "show all var"
debug:
msg:
- "{{ ip_front }}"
- "{{ ip_front_ok }}"
Output:
ok: [localhost] => {
"msg": [
"10.11.12.13",
"10\\.11\\.12\\.13"
]
}
How can I use pattern to resolve it?

How to write varibles/hard code values in nested json in ansible?

I'm trying to create a json file with hard codes valuesas a output in nested json.But the second play is overwriting the first play value.So do we have any best option to do this?
I have tried with to_nice_json template to copy the variable to json file.But not able to keep multiple variable values in imported_var to copy to json file
---
- hosts: localhost
connection: local
gather_facts: false
tasks:
- name: load var from file
include_vars:
file: /tmp/var.json
name: imported_var
- name: Checking mysqld status
shell: service mysqld status
register: mysqld_stat
ignore_errors: true
- name: Checking mysqld status
shell: service httpd status
register: httpd_stat
ignore_errors: true
- name: append mysqld status to output json
set_fact:
imported_var: "{{ imported_var | combine({ 'status_checks':[{'mysqld_status': (mysqld_stat.rc == 0)|ternary('good', 'bad') }]})}}"
# - name: write var to file
# copy:
# content: "{{ imported_var | to_nice_json }}"
# dest: /tmp/final.json
- name: append httpd status to output json
set_fact:
imported_var: "{{ imported_var| combine({ 'status_checks':[{'httpd_status': (httpd_stat.rc == 0)|ternary('good', 'bad') }]})}}"
# - debug:
# var: imported_var
- name: write var to file
copy:
content: "{{ imported_var | to_nice_json }}"
dest: /tmp/final.json
Expected result:
{
"status_checks": [
{
"mysqld_status": "good"
"httpd_status": "good"
}
]
}
Actual result:
{
"status_checks": [
{
"httpd_status": "good"
}
]
}
You're trying to perform the sort of data manipulation that Ansible really isn't all that good at. Any time you attempt to modify an existing variable -- especially if you're trying to set a nested value -- you're making life complicated. Having said that, it is possible to do what you want. For example:
---
- hosts: localhost
gather_facts: false
vars:
imported_var: {}
tasks:
- name: Checking sshd status
command: systemctl is-active sshd
register: sshd_stat
ignore_errors: true
- name: Checking httpd status
command: systemctl is-active httpd
register: httpd_stat
ignore_errors: true
- set_fact:
imported_var: "{{ imported_var|combine({'status_checks': []}) }}"
- set_fact:
imported_var: >-
{{ imported_var|combine({'status_checks':
imported_var.status_checks + [{'sshd_status': (sshd_stat.rc == 0)|ternary('good', 'bad')}]}) }}
- set_fact:
imported_var: >-
{{ imported_var|combine({'status_checks':
imported_var.status_checks + [{'httpd_status': (httpd_stat.rc == 0)|ternary('good', 'bad')}]}) }}
- debug:
var: imported_var
On my system (which is running sshd but is not running httpd, this will output:
TASK [debug] **********************************************************************************
ok: [localhost] => {
"imported_var": {
"status_checks": [
{
"sshd_status": "good"
},
{
"httpd_status": "bad"
}
]
}
}
You could dramatically simplify the playbook by restructuring your data. Make status_checks a top level variable, and instead of having it be a list, have it be a dictionary that maps a service name to the corresponding status. Combine this with some loops and you end up with something that is dramatically simpler:
---
- hosts: localhost
gather_facts: false
tasks:
# We can use a loop here instead of writing a separate task
# for each service.
- name: Checking service status
command: systemctl is-active {{ item }}
register: services
ignore_errors: true
loop:
- sshd
- httpd
# Using a loop in the previous task means we can use a loop
# when creating the status_checks variable, which again removes
# a bunch of duplicate code.
- name: set status_checks variable
set_fact:
status_checks: "{{ status_checks|default({})|combine({item.item: (item.rc == 0)|ternary('good', 'bad')}) }}"
loop: "{{ services.results }}"
- debug:
var: status_checks
The above will output:
TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => {
"status_checks": {
"httpd": "bad",
"sshd": "good"
}
}
If you really want to add this information to your imported_var, you can do that in a single task:
- set_fact:
imported_var: "{{ imported_var|combine({'status_checks': status_checks}) }}"

ansible vars_files and extra_vars to read input

looking to pass the dict to read a set of key value pairs based on the location. When values are hardcoded to the playbook, it works fine but calling through extra_vars giving an error message. Not sure even if it supports. appreciate, your thoughts and inputs.
ansible-playbook play3.yml -e '{"var1":"loc2"}' -vv
play3.yml
---
- name: testing
hosts: localhost
connection: local
gather_facts: no
vars_files:
- var_file.yml
tasks:
- debug:
msg: "{{ var1['first'] }}"
var_file.yml
---
loc1:
first: name1
last: name2
loc2:
first: python
last: perl
...
"Anything's possible in an animated cartoon." -Bugs Bunny
This playook:
---
- name: testing
hosts: localhost
connection: local
gather_facts: no
vars_files:
- var_file.yml
tasks:
- debug:
var: "{{ item }}.first"
with_items: "{{ var1 }}"
Gave me this output:
TASK [debug] **********************************************************************************************************************************
task path: /home/jack/Ansible/CANES/PLAYBOOKS/play3.yml:9
ok: [localhost] => (item=None) => {
"loc2.first": "python"
}

Is it possible to use variable in path with lineinfile ansible module?

I have a playbook
---
- hosts: 127.0.0.1
connection: local
vars:
WORK_DIR: /somefolder
tasks:
- debug:
msg: "{{ WORK_DIR }}"
- lineinfile:
path: /somefolder/some.file
regexp: '"display_name":'
line: ' "display_name": "another_name",'
works fine and I have a debug
ok: [127.0.0.1] => {
"msg": "/somefolder"
}
but when I try to use variable in path like
- hosts: 127.0.0.1
connection: local
vars:
WORK_DIR: /somefolder
tasks:
- debug:
msg: "{{ WORK_DIR }}"
- lineinfile:
path: "{{ WORK_DIR }}"/some.file
regexp: '"display_name":'
line: ' "display_name": "another_name",'
there is an error
- lineinfile:
path: "{{ WORK_DIR }}"/some.file
^ here
The question is why ? Is this a bug or feature or something else ?
Quotes misuse.
You should use path: "{{ WORK_DIR }}/some.file".

Resources