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

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".

Related

Create Local File With Ansible Template From Variables

I'm running an ansible playbook against a number of ec2 instances to check if a directory exists.
---
- hosts: all
become: true
tasks:
- name: Check if foo is installed
stat:
path:
/etc/foo
register: path
- debug: msg="{{path.stat.exists}}"
And I would like to generate a localfile that lists the private IP addresses of the ec2 instances and states whether or not the directory foo does exist.
I can get the private IP addresses of the instances with this task
- name: Get info from remote
shell: curl http://169.254.169.254/latest/meta-data/local-ipv4
register: bar
- debug: msg="{{bar.stdout}}"
How do I create a local file with content
IP address: 10.100.0.151 directory foo - false
IP address: 10.100.0.152 directory foo - true
I've tried adding a block for this as such
- hosts: localhost
become: false
vars:
installed: "{{bar.stdout}}"
status: "{{path.stat.exists}}"
local_file: "./Report.txt"
tasks:
- name: Create local file with info
copy:
dest: "{{ local_file }}"
content: |
"IP address {{ installed }} foo - {{ status }}"
But it doesn't look like I can read values of variables from earlier steps.
What am I doing wrong please?
A similar question has been answered here.
Basically what you want is to reference it through the host var variable.
This should work.
- hosts: localhost
become: false
vars:
local_file: "./Report.txt"
tasks:
- name: Create local file with info
lineinfile:
path: "{{ local_file }}"
line:
"IP Address: {{ hostvars[item]['bar'].stdout }} - Installed: {{ hostvars[item]['path'].stat.exists }}"
with_items: "{{ query('inventory_hostnames', 'all') }}"
And this should populate your local ./Report.txt file, with the info you need.
I've used the ec2_metadata_facts module to get the IP address us ingansible_ec2_local_ipv4
I've also created the directory /tmp/testdir on the second host.
- hosts: test_hosts
gather_facts: no
vars:
directory_name: /tmp/testdir
tasks:
- ec2_metadata_facts:
- name: check if directory '{{ directory_name }}' exsists
stat:
path: "{{ directory_name }}"
register: path
# I make the outputfile empty
# because the module lineinfile(as I know) can't overwrite a file
# but appends line to the old content
- name: create empty output file
copy:
content: ""
dest: outputfile
delegate_to: localhost
- name: write output to outputfile
lineinfile:
dest: outputfile
line: "IP Address: {{ ansible_ec2_local_ipv4 }} {{ directory_name }} - {{ path.stat.exists }}"
state: present
with_items: "{{ groups.all }}"
# with_items: "{{ ansible_play_hosts }}" can also be used here
delegate_to: localhost
The outputfile looks like:
IP Address: xxx.xx.x.133 /tmp/testdir - False
IP Address: xxx.xx.x.45 /tmp/testdir - True

Ansible: Get Variable with inventory_hostname

I have the following passwords file vault.yml:
---
server1: "pass1"
server2: "pass2"
server3: "pass3"
I am loading these values in a variable called passwords:
- name: Get Secrets
set_fact:
passwords: "{{ lookup('template', './vault.yml')|from_yaml }}"
delegate_to: localhost
- name: debug it
debug:
var: passwords.{{ inventory_hostname }}
The result of the debugging task shows me the result I want to get: The password for the specific host.
But if I set the following in a variables file:
---
ansible_user: root
ansible_password: passwords.{{ inventory_hostname }}
This will not give me the desired result. The ansible_password takes "passwords" literally and not as a variable.
How can I achieve the same result I got when debugging the passwords.{{ inventory_hostname }}?
Regarding the part
... if I set the following in a variables file ...
I am not sure since I miss some information about your use case and data flow. However, in general the syntax ansible_password: "{{ PASSWORDS[inventory_hostname] }}" might work for you.
---
- hosts: localhost
become: false
gather_facts: false
vars:
PASSWORDS:
SERVER1: "pass1"
SERVER2: "pass2"
SERVER3: "pass3"
localhost: "pass_local"
tasks:
- name: Debug var
debug:
var: PASSWORDS
- name: Set Fact 'ansible_password'
set_fact:
ansible_password: "{{ PASSWORDS[inventory_hostname] }}"
- name: Debug var
debug:
var: ansible_password
In that way you can access a element by name.

Why Ansible Playbook skip variable value in a file?

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?

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?

Ansible: using group vars in tasks

In Ansible, i want to trigger selected tasks based on hosts.
My inventory:
[appserver]
ip1
ip2
[webserver]
ip3
ip4
And my main.yml file will be like this
- name : Playbook
hosts: all
user: username
become: yes
gather_facts: True
tasks:
- name: Task 1
replace:
path: "somepath"
regexp: "{{ oldvalue }}"
replace: "{{ newvalue }}"
backup: yes
- name: Task 2
replace:
path: "somepath"
regexp: "{{ oldvalue }}"
replace: "{{ newvalue }}"
backup: yes
How do I run this particular task1 on appserver group and task2 on webserver group. Is there any best way to achieve this without using ansible tags?
- hosts: appserver
user: username
become: yes
gather_facts: True
tasks:
- name: Task 1
replace:
path: "somepath"
regexp: "{{ oldvalue }}"
replace: "{{ newvalue }}"
backup: yes
- hosts: webserver
user: username
become: yes
gather_facts: True
tasks:
- name: Task 2
replace:
path: "somepath"
regexp: "{{ oldvalue }}"
replace: "{{ newvalue }}"
backup: yes
After posting, I saw #Zeitounator's comment.

Resources