Ansible Task Using 'ansible.builtin.unvault' lookup - ansible

The ansible code below takes an ansible vault (vault.yml) and then uses the ansible.builtin.unvault lookup to retrieve and save the entire vault as the variable full_vault. The output of the debug shows the code in json. This code is working as expected.
- name: Pull vault into Variable from encrypted YAML file
hosts: localhost
gather_facts: no
tasks:
- name: Get specific value from vault file
set_fact:
full_vault: "{{ lookup('ansible.builtin.unvault', 'vault.yml') | from_yaml }}"
- name: Display Vault
ansible.builtin.debug:
msg: "Vault: {{ full_vault }}"
The challenge I am having is trying to use the ansible.builtin.vault lookup to put the full_vault variable back into an ansible vault. How can I accomplish this in a single task?
I am using the environment variable ANSIBLE_VAULT_PASSWORD_FILE=pass.txt for encryption/decryption.

Your question and example is focusing on the ansible.builtin.unvault lookup which is abolutely not needed in your situation. The only case I can think of where this would be needed is if you fetch your vault password from an other system/app/source while running your playbook. But since it is available with classic env vars to ansible, you just have to use the encrypted file which will be decrypted on the fly.
For the rest of the example, let's imagine your vault.yml file contains (decrypted):
my_login: vip
my_pass: v3rys3cr3t
some_other_key: toto
Using the above encrypted file is as easy as
---
- hosts: localhost
gather_facts: false
vars_files:
- vault.yml
tasks:
- name: Dummy use of login and pass
ansible.builtin.debug:
msg: "Login in {{ my_login }} and password is {{ my_pass }}"
Now if you want to easily load that file with all its content, change a value for a key in the contained dict and push back the content encrypted with the same configured password, here is a first draft that you will probably have to enhanced. But it worked for my local test with your current configuration.
The update_vault.yml playbook
---
- hosts: localhost
gather_facts: false
vars:
vault_file: vault.yml
new_pass: n3ws3cr3t
tasks:
- name: Import vaulted variables in a namespace (for further easier manipulation)
ansible.builtin.include_vars:
file: "{{ vault_file }}"
name: my_vault
- name: Dummy task just to show above worked
debug:
msg:
- Login is {{ my_vault.my_login }}.
- Password is {{ my_vault.my_pass }}
- Some other key is {{ my_vault.some_other_key }}
- name: Update an element and push back to encrypted file
vars:
new_vault_content: "{{ my_vault | combine({'my_pass': new_pass}) }}"
vault_pass_file: "{{ lookup('ansible.builtin.env', 'ANSIBLE_VAULT_PASSWORD_FILE') }}"
vault_pass: "{{ lookup('ansible.builtin.file', vault_pass_file) }}"
copy:
content: "{{ new_vault_content | to_nice_yaml | ansible.builtin.vault(vault_pass) }}"
dest: "{{ vault_file }}"
decrypt: false
gives:
$ ansible-playbook update_vault.yml
PLAY [localhost] ***********************************************************************************************************************************************************************************************************************
TASK [Import vaulted variables in a namespace (for furthre easier manipulation)] *******************************************************************************************************************************************************
ok: [localhost]
TASK [Dummy task just to show above worked] ********************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"Login is vip.",
"Password is v3rys3cr3t",
"Some other key is toto"
]
}
TASK [Update an element and push back to encrypted file] *******************************************************************************************************************************************************************************
changed: [localhost]
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
And you can easilly check the file was correctly updated:
$ ansible-vault view vault.yml
my_login: vip
my_pass: n3ws3cr3t
some_other_key: toto
Note that the above playbook is not idempotent. If you run it a second time, the decrypted content of your file will stay identical (with the same new password), but the file will still be changed as the vault salt will change and the encrypted content will be different.

Related

Ansible How to store multiple "register" in one file with one playbook

Ansible store only the first output in a file
Example
I have 3 hosts inside the inventory
My playbook ask for memory info.
with
- name: Check memory
hosts: all
tasks:
- name: Check Memory
shell: free
register: memory_output
- name: save
lineinfile:
path: "mypc/test.log"
line: "--{{ memory_output.stdout }}% "
create: yes
delegate_to: localhost
output write in file sometimes all the hosts memory,sometimes only the first,sometimes only the last
How i append every result from every hosts in one file.
Sometimes it export all the results but not every time
For example, given the inventory
shell> cat hosts
test_11
test_12
test_13
declare the below variable and put it into the vars
vmstat: "{{ out.stdout|community.general.jc('vmstat') }}"
Get the free memory
- command: vmstat
register: out
- set_fact:
free_mem: "{{ vmstat.1.free_mem }}"
- debug:
var: free_mem
gives (abridged)
ok: [test_11] =>
free_mem: '3434124'
ok: [test_12] =>
free_mem: '3496908'
ok: [test_13] =>
free_mem: '3434992'
Q: "How to store multiple 'register' in one file with one playbook."
A: Write it to the log
- lineinfile:
create: true
path: /tmp/test.log
line: >-
{{ '%Y-%m-%d %H:%M:%S'|strftime() }}
{{ item }}
{{ hostvars[item].free_mem }}
loop: "{{ ansible_play_hosts }}"
delegate_to: localhost
run_once: true
gives
shell> cat /tmp/test.log
2022-09-12 13:39:48 test_11 3434124
2022-09-12 13:39:49 test_12 3496908
2022-09-12 13:39:49 test_13 3434992
Example of a complete playbook for testing
- hosts: test_11,test_12,test_13
vars:
vmstat: "{{ out.stdout|community.general.jc('vmstat') }}"
tasks:
- command: vmstat
register: out
- set_fact:
free_mem: "{{ vmstat.1.free_mem }}"
- debug:
var: free_mem
- lineinfile:
create: true
path: /tmp/test.log
line: >-
{{ '%Y-%m-%d %H:%M:%S'|strftime() }}
{{ item }}
{{ hostvars[item].free_mem }}
loop: "{{ ansible_play_hosts }}"
delegate_to: localhost
run_once: true
Here's the simplest example. Assuming that you are running ansible in controller machine and you have to append the output of executing tasks in remote machines. The host list will obviously be different for you and will have all the remote machines.
- hosts: localhost
tasks:
## Playbook to copy the file from controller machine to remote machine
- name: Copy the file from controller machine to remote machine
copy:
src: /tmp/tmpdir/output.txt
dest: /tmp/tmpdir/output.txt
## Playbook to store the shell output to a variable
- name: Store the output of the shell command to a variable
shell: "echo '\nHello World'"
register: output
- name: Print the output of the shell command
debug:
msg: "{{ output.stdout }}"
## Playbook to append output to a file
- name: Append output to a file
lineinfile:
path: /tmp/tmpdir/output.txt
line: "{{ output.stdout }}"
create: yes
## Playbook to copy the file from remote machine to controller machine
- name: Copy the file from remote machine to controller machine
fetch:
src: /tmp/tmpdir/output.txt
dest: /tmp/tmpdir/output.txt
flat: yes
After running it the third time
╰─ ansible-playbook test.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] *******************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [localhost]
TASK [Copy the file from controller machine to remote machine] *********************************************************************************************
ok: [localhost]
TASK [Store the output of the shell command to a variable] *************************************************************************************************
changed: [localhost]
TASK [Print the output of the shell command] ***************************************************************************************************************
ok: [localhost] => {
"msg": "\nHello World"
}
TASK [Append output to a file] *****************************************************************************************************************************
changed: [localhost]
TASK [Copy the file from remote machine to controller machine] *********************************************************************************************
ok: [localhost]
PLAY RECAP *************************************************************************************************************************************************
localhost : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
╰─ cat output.txt
Hello World
Hello World
Hello World
So on every machine you run the controller machine will get the latest file output. We will copy the file to remote, add contents to the file and then copy it back to controller. Continue the same until all the hosts have been completed.
If you want to take the result from selective servers then the last task can be replaced by following. Replace the hostnames with required values
## Playbook to copy the file from remote machine to controller machine if the hostname maches localhost1 or localhost2
- name: Copy the file from remote machine to controller machine if the hostname maches localhost1 or localhost2
fetch:
src: /tmp/tmpdir/output.txt
dest: /tmp/tmpdir/output.txt
flat: yes
fail_on_missing: yes
when: inventory_hostname == 'localhost1' or inventory_hostname == 'localhost2'

Errors when use "json_query" in Ansible

When use json_query in Ansible, got the error along with my code as shown below.
The Python used in Ansible is 3.6.8, and used the same version installed jmespath: pip install jmespath, so, this should not be the issue. The Ansible code should be fine as well.
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: no filter named 'json_query'. String: {{ jsondata | json_query(jmesquery) }}"
The following is the Ansible codes:
---
- name: ReadJsonfile
hosts: localhost
tasks:
- name: Display the JSON file content
shell: cat config.json
register: result
- name: save the JSON data to a Variable as a Fact
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: setDomainName
set_fact:
domain_name: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.name'
- name: setDomainUsername
set_fact:
domain_username: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.user'
- name: setDomainPassword
set_fact:
domain_password: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.password'
- name: setadmin_Listenport
set_fact:
admin_ListenPort: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.admin.listenport'
- name: Debug the values
debug: msg=" Admin Listen Port => {{ admin_ListenPort }}, DomainName => {{ domain_name }}, DomainUserName => {{ domain_username }} , Domain Password => {{ domain_password }}"
From the error message, I suspect you are using ansible 2.10
The json_query filter is part of the community.general collection which needs to be installed separately starting from this version (this is clearly stated in the documentation)
ansible-galaxy collection install community.general
That being said:
your actual jmespath queries will not return what you expect
using shell to get a file content from remote is a bad practice
that's lots of set_facts and json_query to simply get data that is readily available
Since yaml is a strict superset of json, any valid json is also a valid yaml. In your case, you only have to load the content of the file and you have the data.
One solution is to fetch the file locally and then use include_vars.
In this particular case, using slurp looks like the best option.
This is what (I believe, since you did not provide an example) your config file looks like. I pushed that file in /tmp/config.json for my example.
{
"domain": {
"name": "toto",
"user": "doejohn",
"password": "sosecret",
"admin": {
"listenport": 5501
}
}
}
This is the demo playbook
---
- name: Load remote json content demo
hosts: localhost
gather_facts: false
vars:
config_file: /tmp/config.json
# Of course the below vars will fire errors
# if you call them before slurping data from remote.
# Note: loading `data` in a jinja expression on its own
# forces to transform it back rom string to json data.
# You can accomplish the same result in one go
# using the `from_json` filter
# i.e. => domain: "{{ (slurped_config.content | b64decode | from_json).domain }}"
data: "{{ slurped_config.content | b64decode }}"
domain: "{{ data.domain }}"
# Note2: the above will work and adapt to N hosts in your play: you will get
# the correct data for each host in every task.
tasks:
- name: Slurp config file content
slurp:
src: "{{ config_file }}"
register: slurped_config
- name: Show result
vars:
message: |-
name is: {{ domain.name }}
user is: {{ domain.user }}
password is: {{ domain.password }}
port is: {{ domain.admin.listenport }}
debug:
msg: "{{ message.split('\n') }}"
which gives:
PLAY [Load remote json content demo] ******************************************************
TASK [Slurp config file content] **********************************************************
Wednesday 21 April 2021 17:57:47 +0200 (0:00:00.010) 0:00:00.010 *******
ok: [localhost]
TASK [Show result] ************************************************************************
Wednesday 21 April 2021 17:57:48 +0200 (0:00:00.199) 0:00:00.209 *******
ok: [localhost] => {
"msg": [
"name is: toto",
"user is: doejohn",
"password is: sosecret",
"port is: 5501"
]
}
PLAY RECAP ********************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Wednesday 21 April 2021 17:57:48 +0200 (0:00:00.027) 0:00:00.237 *******
===============================================================================
Slurp config file content ---------------------------------------------------------- 0.20s
Show result ------------------------------------------------------------------------ 0.03s

Generate Ansible fact once (per host)

I would like to generate a password and some other values when they do not exist yet.
Something like this:
- name: Retrieve or generate my_password
generated_fact:
shell: some shell command
name: my_password
I have a working approach but am really unhappy with it since it is very verbose and error prone:
- name: Generate my_password
shell: some shell command
register: generate_password_task
when: ansible_local.convoluted.bs.my_password is not defined
- name: Store my_password as local fact
ini_file:
path: "/etc/ansible/facts.d/convoluted.fact"
section: bs
option: my_password
value: "{{ generate_password_task.stdout }}"
when: generate_password_task.changed
- name: Reload Ansible local facts
setup: filter=ansible_local
when: generate_password_task.changed
Is there a high level abstraction for this task along the lines of the first code snippet? Or some other approach more sane than what I currently have?
The basic approach is the right one. There are few imperfections I see. One of them is 'dependence chain', when different tasks are depend on different conditions. It's hard to debug.
So, improvement one is to make a single condition:
- block:
when: ansible_local.convoluted.bs.my_password is not defined
- name: Generate my_password
shell: some shell command
register: generate_password_task
- name: Store my_password as local fact
ini_file:
path: "/etc/ansible/facts.d/convoluted.fact"
section: bs
option: my_password
value: "{{ generate_password_task.stdout }}"
- name: Reload Ansible local facts
setup: filter=ansible_local
The second trick is to use meta: end_host, it allows to terminate play for the specific host without errors and additional skips.
- hosts: ...
tasks:
- meta: end_play
when: ansible_local.convoluted.bs.my_password is defined
- name: Generate my_password
shell: some shell command
register: generate_password_task
- name: Store my_password as local fact
ini_file:
path: "/etc/ansible/facts.d/convoluted.fact"
section: bs
option: my_password
value: "{{ generate_password_task.stdout }}"
- name: Reload Ansible local facts
setup: filter=ansible_local
But you need to keep it as a separate play to use it with 'end_host'.
Here would be my approach, in two tasks.
Note that this has been checked when:
The ini file does not exists
The ini file is present but there is no bs section
The ini file is present, have a bs section, but the section does not include a my_password option
The ini file is present, have a bs section, but the option my_password is empty
The ini file is present, have a bs section and have a value for the option my_password
The cases 1 to 4 does end in a change of the ini file with a newly generated password, when the last case ends in a skipped task.
And here are the two tasks doing this:
- set_fact:
actual_password: "{{ lookup('ini', 'my_password section=bs file=/etc/ansible/facts.d/convoluted.fact', errors='ignore') }}"
- ini_file:
path: /etc/ansible/facts.d/convoluted.fact
section: bs
option: my_password
value: "{{ lookup('password', '/dev/null chars=ascii_letters,digits,hexdigits,punctuation') }}"
when: actual_password|length == 0
Those are using
the ini lookup in order to confirm that the ini and value are not yet set
the password plugin to generate a password
The condition (when: actual_password|length == 0) to write the ini is based on experimentation
Thanks to the errors='ignore' syntax in the ini lookup, the variable actual_password ends up being an empty string if the file or section does not exists, because both those cases are causing the lookup to return an error
If the section exists but does not contains the option then the lookup ends up returning an empty array []
If the option is there but empty, the lookup return that empty string
Knowing all that is making the test relevant: []|length == 0 and ''|length == 0 are both true.
A last note on the password plugin, yes it does write a file on your controller host, but you are not forced to consider it, use it, or even, well, store it.
The plugin return the password, so you can easily use it as you would for any other variable in the value attribute of your ini_file module.
And then, if you don't want to store it on the controller host, do as you would do for anything you don't care about in linux, redirect it to /dev/null, either way, the password is in your ini file now.
And if you need to re-use that same password later in the playbook, just store it via an extra set_fact
- set_fact:
actual_password: "{{ lookup('ini', 'my_password section=bs file=/etc/ansible/facts.d/convoluted.fact', errors='ignore') }}"
- block:
- set_fact:
new_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits,hexdigits,punctuation') }}"
- ini_file:
path: /etc/ansible/facts.d/convoluted.fact
section: bs
option: my_password
value: "{{ new_password }}"
when: actual_password|length == 0
Given this playbook:
- hosts: local
gather_facts: no
tasks:
- set_fact:
actual_password: "{{ lookup('ini', 'my_password section=bs file=/etc/ansible/facts.d/convoluted.fact', errors='ignore') }}"
- ini_file:
path: /etc/ansible/facts.d/convoluted.fact
section: bs
option: my_password
value: "{{ lookup('password', '/dev/null chars=ascii_letters,digits,hexdigits,punctuation') }}"
when: actual_password|length == 0
Here is a double run of it:
/ansible # cat /etc/ansible/facts.d/convoluted.fact
cat: can't open '/etc/ansible/facts.d/convoluted.fact': No such file or directory
/ansible # ansible-playbook play.yml
PLAY [local] ***********************************************************************************************************************************************************************************************
TASK [set_fact] ********************************************************************************************************************************************************************************************
[WARNING]: Unable to find '/etc/ansible/facts.d/convoluted.fact' in expected paths (use -vvvvv to see paths)
ok: [local]
TASK [ini_file] ********************************************************************************************************************************************************************************************
changed: [local]
PLAY RECAP *************************************************************************************************************************************************************************************************
local : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
/ansible # cat /etc/ansible/facts.d/convoluted.fact
[bs]
my_password = fnI;L3FpR5207,8,jxGP
/ansible # ansible-playbook play.yml
PLAY [local] ***********************************************************************************************************************************************************************************************
TASK [set_fact] ********************************************************************************************************************************************************************************************
ok: [local]
TASK [ini_file] ********************************************************************************************************************************************************************************************
skipping: [local]
PLAY RECAP *************************************************************************************************************************************************************************************************
local : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

Create VLANs only if they don't exist on a Nexus switch

I'm trying to create an Ansible playbook which should create VLANs defined in file vlans.dat on a Cisco Nexus switch only when they don't exist on device.
File vlans.dat contains:
---
vlans:
- { vlan_id: 2, name: TEST }
And Ansible file:
---
- name: Verify and create VLANs
hosts: switches_group
gather_facts: no
vars_files:
- vlans.dat
tasks:
- name: Get Nexus facts
nxos_facts:
register: data
- name: Create new VLANs only
nxos_vlan:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
state: "{{item.state | default('present') }}"
with_items: "{{ vlans }}"
when: item.vlan_id not in data.ansible_facts.vlan_list
In the when statement I'm trying to limit execution only to the case when vlan_id (defined in the file) doesn't exist in the vlan_list gathered by nxos_facts module. Unfortunately it gets executed even when the vlan_id already exists in the vlan_list and I don't know why?
PLAY [Verify and create VLANs]
TASK [Get Nexus facts]
ok: [10.1.1.1]
TASK [Create new VLANs only]
ok: [10.1.1.1] => (item={u'name': u'TEST', u'vlan_id': 2})
TASK [debug]
skipping: [10.1.1.1]
PLAY RECAP
10.1.1.1 : ok=2 changed=0 unreachable=0 failed=0
Can you help me with that or provide some solution what I'm doing wrong here?
It appears you have stumbled upon a side-effect of YAML having actual types. Because in {vlan_id: 2} the 2 is an int but the list is strings. As you might imagine {{ 1 in ["1"] }} is False.
There are two ways out of that situation: make the vlan_id a string via - { vlan_id: "2" } or coerce the vlan_id to a string just for testing the list membership:
when: (item.vlan_id|string) not in data.ansible_facts.vlan_list

Ansible - read inventory hosts and variables to group_vars/all file

I have a dummy doubt that keeps me stuck for a long time. I have a very banal inventory file with hosts and variables:
[lb]
10.112.84.122
[tomcat]
10.112.84.124
[jboss5]
10.112.84.122
...
[tests:children]
lb
tomcat
jboss5
[default:children]
tests
[tests:vars]
data_base_user=NETWIN-4.3
data_base_password=NETWIN
data_base_encrypted_password=
data_base_host=10.112.69.48
data_base_port=1521
data_base_service=ssdenwdb
data_base_url=jdbc:oracle:thin:#10.112.69.48:1521/ssdenwdb
The problem is that I need to access all these hosts and variables, in the inventory file, from the group_vars/all file.
I've tried the following manners to access the host IP:
{{ lb }}
"{{ hostvars[lb] }}"
"{{ hostvars['lb'] }}"
{{ hostvars[lb] }}
To access a host variable I tried:
"{{ hostvars[tests].['data_base_host'] }}"
All of them are wrong!!! Can anyone help me find out the best practice to access hosts and variables, not from a playbook but from a variables file?
EDIT:
Ok. Let's clarify.
Problem: Use a host declared in the inventory file in a variable file, let's say: group_vars/all.
Example: I have a DB host with IP:10.112.83.37.
Inventory file:
[db]
10.112.83.37
In the group:vars/all file I want to use that IP to build a variable.
group_vars/all file:
data_base_url=jdbc:oracle:thin:#{{ db }}:1521/ssdenwdb
In a template I use the variable built in the group_vars/all file.
Template file:
oracle_url = {{ data_base_url }}
The problem is that the {{ db }} variable in the group_vars/all file is not replaced by the DB host IP. The user can only edit the inventory file.
- name: host
debug: msg="{{ item }}"
with_items:
- "{{ groups['tests'] }}"
This piece of code will give the message:
'10.112.84.122'
'10.112.84.124'
as groups['tests'] basically return a list of unique ip addresses ['10.112.84.122','10.112.84.124'] whereas groups['tomcat'][0] returns 10.112.84.124.
If you want to programmatically access the inventory entries to include them in a task for example. You can refer to it like this:
{{ hostvars.tomcat }}
This returns you a structure with all variables related with that host. If you want just an IP address (or hostname), you can refer to it like this:
{{ hostvars.jboss5.ansible_ssh_host }}
Here is a list of variables which you can refer to: click. Moreover, you can declare a variable and set it with for example result of some step in a playbook.
- name: Change owner and group of some file
file: path=/tmp/my-file owner=new-owner group=new-group
register: chown_result
Then if you play this step on tomcat, you can access it from jboss5 like this:
- name: Print out the result of chown
debug: msg="{{ hostvars.tomcat.chown_result }}"
Just in case if the problem is still there,
You can refer to ansible inventory through ‘hostvars’, ‘group_names’, and ‘groups’ ansible variables.
Example:
To be able to get ip addresses of all servers within group "mygroup", use the below construction:
- debug: msg="{{ hostvars[item]['ansible_eth0']['ipv4']['address'] }}"
with_items:
- "{{ groups['mygroup'] }}"
Considering your previous example:
inventory file:
[db]
10.112.83.37
group_vars/all
data_base_url=jdbc:oracle:thin:#{{ db }}:1521/ssdenwdb
template file:
oracle_url = {{ data_base_url }}
You might want to replace your group_vars/all with
data_base_url="jdbc:oracle:thin:#{{ groups['db'][0] }}:1521/ssdenwdb"
Yes the example by nixlike works very well.
Inventory:
[docker-host]
myhost1 user=barbara
myhost2 user=heather
playbook:
---
- hosts: localhost
connection: local
tasks:
- name: loop debug inventory hostnames
debug:
msg: "the docker host is {{ item }}"
with_inventory_hostnames: docker-host
- name: loop debug items
debug:
msg: "the docker host is {{ hostvars[item]['user'] }}"
with_items: "{{ groups['docker-host'] }}"
output:
ansible-playbook ansible/tests/vars-test-local.yml
PLAY [localhost]
TASK [setup]
******************************************************************* ok: [localhost]
TASK [loop debug inventory hostnames]
****************************************** ok: [localhost] => (item=myhost2) => {
"item": "myhost2",
"msg": "the docker host is myhost2" } ok: [localhost] => (item=myhost1) => {
"item": "myhost1",
"msg": "the docker host is myhost1" }
TASK [loop debug items]
******************************************************** ok: [localhost] => (item=myhost1) => {
"item": "myhost1",
"msg": "the docker host is barbara" } ok: [localhost] => (item=myhost2) => {
"item": "myhost2",
"msg": "the docker host is heather" }
PLAY RECAP
********************************************************************* localhost : ok=3 changed=0 unreachable=0
failed=0
thanks!
If you want to refer one host define under /etc/ansible/host in a task or role, the bellow link might help:
https://www.middlewareinventory.com/blog/ansible-get-ip-address/
If you want to have your vars in files under group_vars, just move them here. Vars can be in the inventory ([group:vars] section) but also (and foremost) in files under group_vars or hosts_vars.
For instance, with your example above, you can move your vars for group tests in the file group_vars/tests :
Inventory file :
[lb]
10.112.84.122
[tomcat]
10.112.84.124
[jboss5]
10.112.84.122
...
[tests:children]
lb
tomcat
jboss5
[default:children]
tests
group_vars/tests file :
data_base_user=NETWIN-4.3
data_base_password=NETWIN
data_base_encrypted_password=
data_base_host=10.112.69.48
data_base_port=1521
data_base_service=ssdenwdb
data_base_url=jdbc:oracle:thin:#10.112.69.48:1521/ssdenwdb

Resources