I need to read from a config file which needs to contain a list. The list needs to be passed to a role as argument.
---
- name: run command on localhost
hosts: localhost
tasks:
- name: read variables from file
shell: cat {{ conf1/TMP.txt }}
register: contents
- name: role to trigger the run script process
hosts: otherhost
roles:
- { role: run_script, applist: "{{ contents }}" }
The content of the conf1/TMP.txt file is as follows:
[ 'a', 'b', 'c', 'd' ]
The above mentioned code segment is not working but the following code segment works:
---
- name: main yml file to trigger the whole process
hosts: otherhost
roles:
- { role: run_script, applist: [ 'a', 'b', 'c', 'd' ] }
Try using a lookup filter instead of a shell command. Example below..
---
- name: run command on localhost
hosts: localhost
tasks:
- set_fact:
contents: "{{ lookup('file', 'tmp.txt') }}"
- debug: var=contents
- name: role to trigger the run script process
hosts: localhost
roles:
- { role: foo, applist: "{{ contents }}" }
The output of debug should look like this
ok: [localhost] => {
"foo": [
"1",
"2",
"3",
"4"
]}
Related
I hava this situation:
A play that run in localhost use include_task for create, on the fly with add_host, two sub-group extracting only one host from two group that are present in the inventory file.
Another play in the same yaml file use this group as hosts (host:sub-group).
This is the inventory file:
all:
children:
group_one:
hosts:
hostA01:
ansible_host: host1a
hostA02:
ansible_host: host2a
hostA03:
ansible_host: host3a
vars:
cluster: hosta
vip: 192.168.10.10
home: /cluster/hosta
user: usr_hosta
pass: pass_hosta
group_two:
hosts:
hostB01:
ansible_host: host1b
hostB02:
ansible_host: host2b
hostB03:
ansible_host: host3b
vars:
cluster: hostb
vip: 192.168.10.20
home: /cluster/hostb
user: usr_hostb
pass: pass_hostb
other groups...
I have created the sub groups, with add_host, for each group in inventoty file. The name the sub-groups add the prefix "sub-" to inventory original groups, like sub-(one/two/etc..)
In hostvars i retrieve this situation:
"groups": {
"all": [
"hostA01",
"hostA02",
"hostA03",
"hostB01",
"hostB02",
"hostB03",
"other_host_from _other groups"
],
"group_one": [
"hostA01",
"hostA02",
"hostA03"
],
"group_two": [
"hostB01",
"hostB02",
"hostB03"
],
"other_group": [
"other_host",
.....
],
"sub-group_one": [
"hostA01"
],
"sub_group_two": [
"hostB01"
],
"sub-other_group": [
"other_first_host"
],
"ungrouped": []
},
"vars_for_group": {
"group_one": {
"cluster: hosta
"vip: 192.168.10.10
"home: /cluster/hosta
"user: usr_hosta
"pass: pass_hosta,
"ansible_host": "host1a",
"host": "hostA01"
},
"group_two": {
"cluster: hostb
"vip: 192.168.10.20
"home: /cluster/hostb
"user: usr_hostb
"pass: pass_hostb,
"ansible_host": "host1b",
"host": "hostB01"
},
"otehr_groups": {
.......
},
},
"inventory_hostname": "127.0.0.1",
"inventory_hostname_short": "127",
"module_setup": true,
"playbook_dir": ""/home/foo/playbook",
"choice": "'sub-two'"
}
}
The environment variable "choice" in the last line of hostvars derives from other tool and indicates the group on which the final user wants to operate (one, two, ..., all).
Now, my playbook is:
---
- hosts: 127.0.0.1
become: yes
gather_facts: yes
remote_user: root
tasks:
- name: include news_groups
ansible.builtin.include_tasks:
newsgroups.yaml
vars:
choice: "{{ lookup('env','CHOICE') }}"
- hosts: "{{ hostvars['localhost']['groups']['{{ hostvars['localhost']['choice'] }}'] }}"
name: second_play
become: yes
gather_facts: no
remote_user: root
tasks:
- hosts: all
name: other play
gather_facts: no
vars:
other_vars:...
tasks:
.....
Unfortunately this line don't work.
- hosts: "{{ hostvars['localhost']['groups']['{{ hostvars['localhost']['choice'] }}'] }}"
I have made several attempts with many different configuration and different sintax (without {{...}}, with or without "double quotes" and 'single quote' but it always seems syntactically wrong or still cannot find the group indicated by the variable. Or, maybe could it also be that the approach is wrong?
Any suggestions?
Thanks in advance
I'm trying to create a playbook that's going to create multiple files in a number of different directories. The input variables are env & region and both are lists. I've then combined them to display all the different combinations.
What I want is to then loop through all the different folder paths by accessing the values of each individual list, and this is where I'm stuck.
---
- hosts: localhost
gather_facts: false
become: no
vars:
application_name: test
region: [us-east-1, us-east-2]
env: [test,prod]
tasks:
- name: allregions_and_enviroments
set_fact:
all_comb: "{{ region|product(env) }}"
- debug:
var: all_comb
- name: Create new TF file
template:
src: template.j2
dest: /Users/user/Documents/ansibletemplate/{{item[0]}}/{{item[1]}}/ab-{{application_name}}.tf
with_nested: all_comb
The output of the merged list is this:
ok: [localhost] => {
"all_comb": [
[
"us-east-1",
"test"
],
[
"us-east-1",
"prod"
],
[
"us-east-2",
"test"
],
[
"us-east-2",
"prod"
]
]
}
In the directory path, I want it to loop through the region and then the environment and create a file in ..../us-east-1/test/abc.tf then move on to the next.
Any assistance will be greatly appreciated.
Thanks!
I need to access the values from role defaults in the context of other hosts in the inventory. While the values defined in the inventory are available, the role defaults are not.
The following example demonstrates my problem:
#inventory.yml:
all:
hosts:
srv01:
ansible_connection: local
user_name: srv-1-user
domain: example.com
srv02:
ansible_connection: local
user_name: srv-2-user
domain: example.net
#role-a/defaults.yml
user_email_address: {{ user_name }}#{{ domain }}
#role-a/main.yml
- set_fact:
_values: "{{ _values | default([]) + [hostvars[item]['user_email_address'] | default(user_email_address)] }}"
with_inventory_hostnames:
- all
- name: output
debug: var=_values
#site.yml
#!/usr/bin/env ansible-playbook
- hosts: all
tasks:
- import_role:
name: role-a
tags: 'role-a'
#command:
ansible-playbook -i inventory.yml site.yml
The code above generates (as expected) the following output:
ok: [srv02] => {
"_values": [
"srv-2-user#example.net",
"srv-2-user#example.net"
]
}
ok: [srv01] => {
"_values": [
"srv-1-user#example.com",
"srv-1-user#example.com"
]
}
What I need is the following output:
ok: [srv02] => {
"_values": [
"srv-1-user#example.net",
"srv-2-user#example.net"
]
}
ok: [srv01] => {
"_values": [
"srv-1-user#example.com",
"srv-2-user#example.com"
]
}
It is not viable defining all values in the inventory. This problem makes role defaults in this context unusable for me.
Any help or suggestion is appreciated.
You could define user_email_address as
user_email_address: "{{ hostvars[item]['user_name'] }}#{{ hostvars[item]['domain'] }}"
to take advantage of the lazy loading.
The first key of my host_var has a :. Like so,
---
openconfig-vlan:vlans:
vlan:
- vlan-id: '1001'
config:
vlan-id: 1001
name: test22
status: ACTIVE
However, I cannot seem to find a way to escape it so I can loop over the list within vlan.
Playbook
---
- name: Configure Devices via Native
hosts: ios
gather_facts: no
tasks:
- name: Create VLAN
ios_vlan:
vlan_id: "{{ item.config.vlan-id }}"
name: "{{ item.config.name }}"
state: present
with_items: "{{ openconfig-vlan:vlans['vlan'] }}"
Error
TASK [Create VLAN] ********************************************************************************************************************************************************************
fatal: [ios1]: FAILED! => {"msg": "template error while templating string: expected token 'end of print statement', got ':'. String: {{ openconfig-vlan:vlans['vlan'] }}"}
Any ideas? Thanks,
Q: "The first key of my host_var has a :. Like so,"
openconfig-vlan:vlans:
A: There are variables in in host_var no keys. Quoting from Creating valid variable names:
"Variable names should be letters, numbers, and underscores. Variables should always start with a letter."
There is only one idea available. Fix the syntax.
FWIW. For example, include the erroneous host_vars and put it into a valid variable. The play below
- hosts: localhost
tasks:
- include_vars:
file: vars-1-data.yml
name: test_var
- debug:
var: test_var['openconfig-vlan:vlans']
with the data
$ cat vars-1-data.yml
openconfig-vlan:vlans:
vlan:
- vlan-id: '1001'
config:
vlan-id: 1001
name: test22
status: ACTIVE
works as expected
"test_var['openconfig-vlan:vlans']": {
"vlan": [
{
"config": {
"name": "test22",
"status": "ACTIVE",
"vlan-id": 1001
},
"vlan-id": "1001"
}
]
}
I'm using Ansible to install packages on a new deployment. I have a pre-defined list of dicts in a variable.
I want to open an interface to update this list using Jenkins.
My list looks like this:
package_list: [
{'name': 'python-devel', 'apt': 'python-dev'},
{'name': 'python-pip'},
{'name': 'postgresql-devel'},
...
]
The way I communicate Jenkins input to Ansible is using environment variables. I can pass a list of additional packages to be installed and read it as part of my Ansible configuration.
Question is: How I convert a list of strings, to a list of dictionaries matches the structure of my package_list?
For example:
ENV:
PACKAGES=gcc,vim,ntp
ANSIBLE:
additional_packages = [
{'name': 'gcc'},
{'name': 'vim'},
{'name': 'ntp'}
]
Is it even possible?
i believe this playbook will get you where you want. it assumes you have the env variable: PACKAGES=gcc,vim,ntp
it converts the string variable to a list (split by ,), and then in another loop it converts to a list of dictionaries:
playbook:
- hosts: localhost
gather_facts: false
vars:
tasks:
- name: pick up env variable, convert to list
set_fact:
PACKAGES: "{{ lookup('env', 'PACKAGES').split(',') }}"
- name: create dict list variable
set_fact:
PACKAGES_DICT: "{{ PACKAGES_DICT|default([]) + [{'name': item}] }}"
with_items:
- "{{ PACKAGES }}"
- name: print results
debug:
var: PACKAGES_DICT
results:
TASK [print results] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
"PACKAGES_DICT": [
{
"name": "gcc"
},
{
"name": "vim"
},
{
"name": "ntp"
}
]
}
hope this helps
EDIT
refining the code, removing the set_fact task, declaring the PACKAGES variable in vars section:
- hosts: localhost
gather_facts: false
vars:
PACKAGES: "{{ lookup('env', 'PACKAGES').split(',') }}"
tasks:
- name: create dict list variable
set_fact:
PACKAGES_DICT: "{{ PACKAGES_DICT|default([]) + [{'name': item}] }}"
with_items:
- "{{ PACKAGES }}"
- name: print results
debug:
var: PACKAGES_DICT
Using Ansible, list should be written that way:
package_list:
- name: "gcc"
- name: "vim"
- name: "ntp
so to get that list from the string you can do that way:
vars:
package_list: "{{ packages.split(',').values() | list }}"