fetching contents of json file and modifying the content using ansible - ansible

I have JSON file with contents
env_variables.json
{ "server": "{{server}}" , "notes": "{{notes}}" }
and ansible-playbook as below: (to upload a lambda with the environment variables)
playbook.yml
- hosts: localhost
vars:
server: localhost
notes: hello this is localhost
tasks:
- name: Lambda creation/updation
lambda:
name: ansible_test
state: present
region: "eu-west-1"
role: 'arn:aws:iam::xyz:role/xyz_lambda'
zip_file: '{{ item.path }}'
runtime: 'python3.6'
environment_variables: "{{ lookup('file','/env_variables.json') | from_json }}"
handler: 'lambda_function.lambda_handler'
How can I use the above-mentioned "env_variables.json" file format to insert the environment variables with values mentioned in the "vars" directive of playbook.yml?

Use include_vars for that.
- name: Load data from json
include_vars: file=/env_variables.json
If this file is outside of normal lookup pathes, you can use set_fact module:
- name: Load data from json
set_fact:
loaded_data: '{{ lookup('file','/env_variables.json') | from_json }}'

Related

ansible set_stats to display output one after another

I have a code
- set_stats:
data:
wspi_output: "{{ wspi_output.value }}"
- set_stats:
data:
hostname: "{{ inventory_hostname }}"
when called the set_stats variable in another playbook I get the output in the variable section as shown below.
{
"wspi_output": "https://welcome.com:8531https://welcome1.com:8531",
"hostname": "xxxyyzz.xyz.comabcrzzz.xyz.com"
}
My second playbook reads the set_stats variables as shown below:
- name: content of set_stats
debug:
var: wspi_output
- name: get the hostname
debug:
var: hostname
- name: output the set_stats variable to csv
copy:
content: '{{ wspi_output }} , {{ hostname }}'
dest: /tmp/wspi_output.csv
mode: 0755
Is it possible to show something like
{
"wspi_output": "https://welcome.com:8531 , "hostname": "xxxyyzz.xyz.com"
"wspi_output": "https://welcome1.com:8531","hostname": "abcrzzz.xyz.com"
}

How to include variables from roles (vars) directory ansible?

I have my ansible playbook which basically create a new Virtual machine from template in esxi what , i have to convert the playbook into roles. I am new to ansible so i don't know how to call my hard coded variables from roles(install)->vars directory .
This is my playbook
---
# create a new VM from a template
- name: VM from template
hosts: localhost
gather_facts: false
connection: local
vars:
vcenter_hostname: vcenter-app
vcenter_user: john#doe
vcenter_pass: blabla6
esxhost: esx-4.cbalo.fr
datastore: VM-PROD-02-NORMAL
vmtemplate: Centos7-template
name: "newvm2"
notes: Ansible Test
dumpfacts: False
tasks:
- name: Create VM from template
vmware_guest:
validate_certs: False
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_user }}"
password: "{{ vcenter_pass }}"
esxi_hostname: "{{ esxhost }}"
datacenter: CD06
folder: Test
name: "{{ name }}"
template: "{{ vmtemplate }}"
hardware:
memory_mb: "{{ vm_memory | default(1024) }}"
wait_for_ip_address: True
state: present
register: newvm2
I have divide this into my role(install)->tasks->main.yml like this
---
- name: Create VM from template
vmware_guest:
validate_certs: False
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_user }}"
password: "{{ vcenter_pass }}"
esxi_hostname: "{{ esxhost }}"
datacenter: CD06
folder: Test
name: "{{ name }}"
template: "{{ vmtemplate }}"
hardware:
memory_mb: "{{ vm_memory | default(1024) }}"
wait_for_ip_address: True
state: present
register: newvm2
Then in my main directory i create new file run.yml and include my role
---
# create a new VM from a template
- name: VM from template
hosts: localhost
gather_facts: false
connection: local
roles:
- install
The issue is i don't know how to call vars from roles->vars directory as you can see in my playbook i have hard code variables. I need to get or set the variable in file and call it from that file.
**vcenter_hostname: vcenter-app
vcenter_user: john#doe
vcenter_pass: blabla6
esxhost: esx-4.cbalo.fr
datastore: VM-PROD-02-NORMAL
vmtemplate: Centos7-template
name: "newvm2"
datacenter: CD06
folder: Test**
Variables in ansible are a set of values that will replace certain place-holders. You supply them when running your playbook and they will "trickle down" if you include roles etc. Check the documentation to find out about variable precedence in ansible.
So what you want to do is to put your variable-assignments in your inventory (you can split out variables in separate files as well, using group_vars) and then use the -i path/to/inventory.yml on your ansible-playbook command.
A structure could look like that:
my-ansible/
roles/
my-role/
tasks/
main.yaml
defaults/
main.yaml # contains default values for your variables
inventory/
inventory.yaml # contains hosts and variable assignments
run.yaml
Then, you can run it like that:
ansible-playbook -i inventory/inventory.yaml run.yaml
Hints:
Don't use my-role/vars as it is very hard to override variable assignments in there. (See variable precedence)
defaults/main.yaml is not necessary, but can be handy for variables you rarely change

Ansible access same variables from multiple Json files

I have multiple .json files on local host where I place my playbook:
json-file-path/{{ testName }}.json
{{ testName }}.json are: testA.json, testB.json, testC.json ... etc.
All .json files have same keys with different values like this:
json-file-path/testA.json:
{
“a_key”: “a_value1”
“b_key”: “b_value1”
}
json-file-path/testB.json:
{
“a_key”: “a_value2”
“b_key”: “b_value2”
}
json-file-path/testC.json:
{
“a_key”: “a_value3”
“b_key”: “b_value3”
}
.....
I need to access the key-value variables from all .json files and if the values meet some condition, I will perform some task in target host. For example, I have:
a_value1=3
a_value2=4
a_value3=1
I go through my .json file one by one, if a_key[value]>3, I will copy this .json file to target host, otherwise skip the task. In this case, I will only copy testC.json to target host.
How would I achieve this? I was thinking of re-constructing my .json files using {{ testName }} as dynamic key of dict like this:
{
“testName”: “testA”
{
“a_key”: “a_value1”
“b_key”: “b_value1”
}
So I can access my variable as {{ testName}}.a_key. So far I haven’t been able to achieve this.
I have tried the following in my playbook:
—-
- host: localhost
tasks:
- name: construct json files
vars:
my_vars:
a_key: “{{ a_value }}”
b_key: “{{ b_value }}”
with_dict: “{{ testName }}”
copy:
content: “{{ my_vars | to_nice_json }}”
dest: /json-file-path/{{ testName }}.json
My updated playbook are:
/mypath/tmp/include.yaml:
—-
- hosts: remote_hostName
tasks:
- name: load json files
set_fact:
json_data: “{{ lookup(‘file’, item) | from_json }}”
- name: copy json file if condition meets
copy:
src: “{{ item }}”
dest: “{{ /remote_host_path/tmp}}/{{item | basename }}”
delegate_to: “{{ remote_hostName }}”
when: json_data.a_key|int>5
/mypath/test.yml:
—-
- hosts: localhost
vars:
local_src_ dir: /mypath/tmp
remote_host: remote_hostName
remote_dest_dir: /remote_host_path/tmp
tasks:
- name: looping
include: include.yaml
with_fileglob:
- “{{ local_src_dir }}/*json”
All json files on localhost under /mypath/tmp/.
Latest version of playbook. It is working now:
/mypath/tmp/include.yaml:
—-
- name: loafing json flies
include_vars:
file: “{{ item }}”
name: json_data
- name: copy json file to remote if condition meets
copy:
src: “{{ item }}”
dest: ‘/remote_host_path/tmp/{{item | basename}}’
delegate_to: “{{ remote_host }}”
when: json_data.a_key > 5
/mypath/test.yml:
—-
- hosts: localhost
vars:
local_src_dir: /mypath/tmp
remote_host: remote_hostName
remote_dest_dir: /remote_host_path/tmp
tasks:
- name: looping json files
include: include.yaml
with_fileglob:
- “{{ local_src_dir }}”/*json”
I am hoping that I have understood your requirements correctly, and that this helps move you forward.
Fundamentally, you can load each of the JSON files so you can query the values as native Ansible variables. Therefore you can loop through all the files, read each one, compare the value you are interested in and then conditionally copy to your remote host via a delegated task. Therefore, give this a try:
Create an include file include.yaml:
---
# 'item' contains a path to a local JSON file on each pass of the loop
- name: Load the json file
set_fact:
json_data: "{{ lookup('file', item) | from_json }}"
- name: Delegate a copy task to the remote host conditionally
copy:
src: "{{ item }}"
dest: "{{ remote_dest_dir }}/{{ item | basename }}"
delegate_to: "{{ remote_host }}"
when: json_data.a_key > value_threshold
then in your playbook:
---
- hosts: localhost
connection: local
# Set some example vars, tho these could be placed in a variety of places
vars:
local_src_dir: /some/local/path
remote_host: <some_inventory_hostname>
remote_dest_dir: /some/remote/path
value_threshold: 3
tasks:
- name: Loop through all *json files, passing matches to include.yaml
include: include.yaml
loop: "{{ lookup('fileglob', local_src_dir + '/*json').split(',') }}"
Note: As you are running an old version of Ansible, you may need older alternate syntax for all of this to work:
In your include file:
- name: Load the json file
set_fact:
include_vars: "{{ item }}"
- name: Delegate a copy task to the remote host conditionally
copy:
src: "{{ item }}"
dest: "{{ remote_dest_dir }}/{{ item | basename }}"
delegate_to: "{{ remote_host }}"
when: a_key > value_threshold
and in your playbook:
- name: Loop through all *json files, passing matches to include.yaml
include: include.yaml
with_fileglob:
- "{{ local_src_dir }}/*json"

Inline encrypted variable not JSON serializable

I'm trying to understand how to encrypt single variables with vault. First I encrypt the string with ansible-vault encrypt_string -n -p, then I write the output into my playbook. When I execute the playbook it says that the decrypted string isn't JSON serializable.
Encrypted string: "inline_name"
I also tried it with inline_name and inlinename, every time with the same result.
My playbook:
---
- name: Build System
hosts: dev
tasks:
- name: Create
mysql_db:
state: present
name: !vault |
$ANSIBLE_VAULT;1.1;AES256
39613261386438623937643062636166663638633062323939343734306334346537613233623064
3761633832326365356231633338396132646532313861350a316666376566616633376238313636
39343833306462323534623238333639663734626662623731666239366566643636386261643164
3861363730336331660a316165633232323732633364346636363764623639356562336536636136
6364
login_host: "{{ mysql_host }}"
login_user: "{{ mysql_user }}"
login_password: "{{ mysql_pass }}"
- name: Check if can access plain text vars
debug:
msg: "{{ my_plain_txt }}"
Error message:
An exception occurred during task execution. To see the full traceback, use -vvv.
The error was: TypeError: u'"inline_name"' is not JSON serializable
fatal: [127.0.0.1]: FAILED! => {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}
Add task-level variable:
- name: Create
mysql_db:
state: present
name: "{{ mysql_name }}"
login_host: "{{ mysql_host }}"
login_user: "{{ mysql_user }}"
login_password: "{{ mysql_pass }}"
vars:
mysql_name: !vault |
$ANSIBLE_VAULT;1.1;AES256
39613261386438623937643062636166663638633062323939343734306334346537613233623064
3761633832326365356231633338396132646532313861350a316666376566616633376238313636
39343833306462323534623238333639663734626662623731666239366566643636386261643164
3861363730336331660a316165633232323732633364346636363764623639356562336536636136
6364
Double-quotes could explain this error but not for me. Look at the entire error/warning to see what is attempting to parse json. In my case....
[WARNING]: Failure using method (v2_runner_on_ok) in callback plugin
(): u'secret_value' is not JSON serializable
An older AWX callback plugin called json.load and logged a warning along with secrets in plain text. It needed an upgrade.
i have implemented same for sending email using mail module and it's working as expected.
ansible-vault encrypt_string yourgmailapppassword --name gmail_password
use above method to encrypt gmail app password using ansible vault string option and define encrypted variable into the playbook.
cat fetch-users-deatils.yml
- name: Linux servers user audit report preparation
hosts: "{{ HOSTS }}"
roles:
- user-collections
- name: Refreshing user Dashboard & sending email from localhost
hosts: localhost
become: false
vars:
- gmail_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62613232383962323430633831113465356231563163366235353034393230656331663436646233
3266353862303738303737383530313664356135336661390a336562613436626665333833323030
61393135643433313930643337363465343332353716333831222766376137396430426361663633
6233313433633231320a663435636230636431643731333166366435346564316331323361633566
38622138392437888466666535323432653034323936353961646233613437343831
tasks:
- name: Collecting the user details information and recreating the users dashboard
script: dashboard_user.sh
tags: user_dashboard
- name: User Audit data output file stored on below location
debug:
msg:
/tmp/user_collection/user_details.csv
- name: 'Sending Ansible users report email'
mail:
host: smtp.gmail.com
subtype: html
port: 587
password: "{{ gmail_password }}"
to: abcdefghijkl#gmail.com
from: abcdefghijkl#gmail.com
username: abcdefghijkl#gmail.com
subject: User details report
attach: /tmp/user_collection/user_details.csv
body: <pre> {{ lookup('file', '/tmp/user_collection/user_details.csv') }} </pre>
delegate_to: localhost
below is ansible playbook execution command
ansible-playbook fetch-users-deatils.yml -e "HOSTS=all" --ask-vault-pass

Getting variable values from url

i am new to ansible and i am trying to achieve the following,
This is the sample playbook, here i am creating a reg key called "test" under HKLM:\SOFTWARE\myapp\Desk\ and i am adding 2 entries with items called hello and hi and i am assigning single same value "world" to both hello and hi.
i want to get the value for hello and hi from some file which will be stored in a repository or some url ..the value will be different for hello and hi.. is this possible ?
---
- hosts: web
tasks:
- name: Create and add reg entries
win_regedit:
path: HKLM:\SOFTWARE\myapp\Desk\Test
entry: "{{ item }}"
data: world
type: string
state: present
with_items:
- hello
- hi
Update:
Some improvement here for a newbie, i am able to iterate through with_items with key value , but i want to have a file with key:value and i want the ansible to iterate through all the left side keys and create them and also fill them with the right side values..that is the entry in win_Regedit should have key and data should have values
---
- hosts: web
tasks:
- name: Create and add reg entries
win_regedit:
path: HKLM:\SOFTWARE\myapp\Desk\Test
entry: "{{ item.regkey }}"
data: "{{ item.regvalue}}"
type: string
state: present
with_items:
- regkey: hello
regvalue: world
- regkey: hi
regvalue: universe
To include variable from some file, you can use the include_vars module:
include_vars:
file: vars.yml
Edit What you want to do is probably something like below (did not try the win_regedit as I don't have any windows node):
Create a vars.yml:
---
var1: 'key1'
var2: 'key2'
d1: "{
'{{var1}}': 'val1',
'{{var2}}': 'val2'
}"
Then launch the following playbook (see the with_dict statement):
---
- hosts: localhost
remote_user: my_user
tasks:
- name: pull var_file
url: http://example.com/path/to/vars
dest: /path/to/vars.yml
mode: 0440
- name: include_vars
include_vars:
/path/to/vars.yml
- name: Create and add reg entries
win_regedit:
path: HKLM:\SOFTWARE\myapp\Desk\Test
entry: "{{ item.key }}"
data: "{{ item.value}}"
type: string
state: present
with_dict: "{{d1}}"
Kudos to this answer for the with_dict trick
Use uri module.
---
- hosts: localhost
remote_user: my_user
tasks:
- name: pull var_file
uri:
url: http://example.com/path/to/vars
method: GET
return_content: yes
register: vars_from_url
- name: Create and add reg entries
win_regedit:
path: HKLM:\SOFTWARE\myapp\Desk\Test
entry: "{{ item.key }}"
data: "{{ item.value}}"
type: string
state: present
with_dict: "{{ vars_from_url.content }}"

Resources