ansible version: 2.9
Hi.
How can I specify the hosts when I import a playbook with import_playbook?
My code (/project/first_pb.yml)
- import_playbook: /test/pb0.yml
hosts: atlanta
Q: "A method to pass specific family hosts to the imported playbook?"
A: There is no difference between a playbook imported or not. For example,
shell> cat pb-A.yml
- hosts: "{{ my_hosts|default('localhost') }}"
tasks:
- debug:
var: inventory_hostname
shell> ansible-playbook pb-A.yml -e my_hosts=host1
...
inventory_hostname: host1
shell> cat pb-B.yml
- import_playbook: pb-A.yml
shell> ansible-playbook pb-B.yml -e my_hosts=host1
...
inventory_hostname: host1
There are many options on how to pass specific hosts and groups to a playbook. For example, see:
Patterns: targeting hosts and groups
add_host module – Add a host and group to the ansible-playbook in-memory inventory
Inventory plugins (e.g. constructed)
I can filter play plabooks with "when: " condition, for example:
- import_playbook: /test/pb0.yml
when: hostname != host1a*
- import_playbook: /test/pb0.yml
when: '"north" not in hostname'
- import_playbook: /test/pb0.yml
when: '"west" in hostname'
Related
I have to pass the host on which the Ansible command will be executed through extra vars.
I don't know in advance to which hosts the tasks will be applied to, and, therefore, my inventory file is currently missing the hosts: variable.
If I understood from the article "How to pass extra variables to an Ansible playbook" correctly, overwriting hosts is only possible by having already composed groups of hosts.
From the post Ansible issuing warning about localhost I gathered that referencing hosts to be managed in an Ansible inventory is a must, however, I still have doubts about it since the usage of extra vars was not mentioned in the given question.
So my question is: What can i do in order to make this playbook work?
- hosts: "{{ host }}"
tasks:
- name: KLIST COMMAND
command: klist
register: klist_result
- name: TEST COMMAND
ansible.builtin.shell: echo hi > /tmp/test_result.txt
... referencing hosts to be managed in an Ansible inventory is a must
Yes, that's the case. Regarding your question
What can I do in order to make this playbook work? (annot. without a "valid" inventory file)
you could try with the following workaround.
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- add_host:
hostname: "{{ target_hosts }}"
group: dynamic
- hosts: dynamic
become: true
gather_facts: true
tasks:
- name: Show hostname
shell:
cmd: "hostname && who am i"
register: result
- name: Show result
debug:
var: result
A call with
ansible-playbook hosts.yml --extra-vars="target_hosts=test.example.com"
resulting into execution on
TASK [add_host] ***********
changed: [localhost]
PLAY [dynamic] ************
TASK [Show hostname] ******
changed: [test.example.com]
In any case it is recommended to check how to build your inventory.
Further Documentation
add_host module – Add a host (and alternatively a group) to the ansible-playbook in-memory inventory
I have an inventory file
[hosttype1]
Server
Server2
[hosttype2]
server3
server4
I am trying to read this as a whole into ansible. The file is used in the normal way to define hosts and types for code deploy, but I need to also read the full content for adding into a config file.
the inventory file differs for different environments being deployed, so there is no fixed location for it.
Is it possible to read the file and create a variable that I can then loop over and use the hosttype and a comparitor?
The easiest way is to use it as an inventory. For example
shell> cat hosts
[hosttype1]
Server
Server2
[hosttype2]
server3
server
shell> cat pb.yml
- hosts: localhost
vars:
my_groups: "{{ groups|difference(['all', 'ungrouped']) }}"
my_hosts: "{{ my_groups|map('extract', groups)|list }}"
my_inventory: "{{ dict(my_groups|zip(my_hosts)) }}"
tasks:
- debug:
var: my_inventory
gives
shell> ansible-playbook -i hosts pb.yml
PLAY [localhost] ******************************************************
TASK [debug] **********************************************************
ok: [localhost] =>
my_inventory:
hosttype1:
- Server
- Server2
hosttype2:
- server3
- server
Owing to needing some dependencies from ansible-galaxy, and other installed software such as ssh-pass, I can't find a way around having to run multiple playbooks sequentially.
Is there a way around this, or is this a feature to be added in future? I've seen it suggested that multiple playbooks may be put in a shell script but surely this is a job for a configuration management program such as ansible?
You can use import_playbook which is merely an import without any other functionality. For example the three playbooks below
shell> cat playA.yml
- hosts: localhost
tasks:
- debug:
msg: Play A
shell> cat playB.yml
- hosts: localhost
tasks:
- debug:
msg: Play B
shell> cat playC.yml
- hosts: localhost
tasks:
- debug:
msg: Play C
can be put into one playbook
shell> cat playABC.yml
- hosts: localhost
tasks:
- debug:
msg: Play A
- hosts: localhost
tasks:
- debug:
msg: Play B
- hosts: localhost
tasks:
- debug:
msg: Play C
, or can be imported into one playbook
shell> cat playABC-import.yml
- import_playbook: playA.yml
- import_playbook: playB.yml
- import_playbook: playC.yml
Both options give the same result. If you need smarter control of the playbooks use ansible-runner.
I'm trying to create a job role in Ansible to run yum install/update of packages, which will be provided by a 3rd party system as a .yml file to vars directory in a role with following convention: server01.yml, server02.yml, serverX.yml with variable in form packageList_serverNumber: 'list of packages'.
This variable will be read using a task:
- name: server update packages from host_vars
yum:
name: "{{ install_pkgs }}"
state: latest
This should point to host_vars file for specific host:
install_pkgs: "{{ packageList_server01 }}"
As this task should only run when the variable is defined, I was trying to use when clause with variable which will point to packageList_serverNumber. When I hardcode it, like below it is working:
when: packageList_server01 is defined
Can you please advise how to make it dynamic?
I was trying with:
when: packageList_{{hostvars[inventory_hostname]}} is defined
But unfortunately this is not working.
Use lookup plugin vars. Run the command below to see the details
shell> ansible-doc -t lookup vars
Given the vars files
shell> cat roles/test4/vars/server01.yml
packageList_server01: [pkg1, pkg2, pkg3]
shell> cat roles/test4/vars/server02.yml
packageList_server02: [pkg4, pkg5, pkg6]
shell> cat roles/test4/vars/server03.yml
packageList_server03: [pkg7, pkg8, pkg9]
read the vars, declare the variable install_pkgs, and use it
shell> cat roles/test4/tasks/main.yml
- include_vars: "vars/{{ inventory_hostname }}.yml"
- set_fact:
install_pkgs: "{{ lookup('vars', 'packageList_' ~ inventory_hostname) }}"
- debug:
msg: "Install {{ install_pkgs }}"
For example the playbook
- hosts: server01,server02,server03
gather_facts: false
roles:
- test4
gives (abridged)
TASK [test4 : debug] ****
ok: [server01] =>
msg: Install ['pkg1', 'pkg2', 'pkg3']
ok: [server03] =>
msg: Install ['pkg7', 'pkg8', 'pkg9']
ok: [server02] =>
msg: Install ['pkg4', 'pkg5', 'pkg6']
My question is somehow similar to the one posted here, but that doesn't quite answer it.
In my case I have an array containing multiple vars: entries, which I loop over when calling a certain role. The following examples shows the idea:
some_vars_file.yml:
redis_config:
- vars:
redis_version: 6.0.6
redis_port: 6379
redis_bind: 127.0.0.1
redis_databases: 1
- vars:
redis_version: 6.0.6
redis_port: 6380
redis_bind: 127.0.0.1
redis_databases: 1
playbook.yml:
...
- name: Install and setup redis
include_role:
name: davidwittman.redis
with_dict: "{{ dictionary }}"
loop: "{{ redis_config }}"
loop_control:
loop_var: dictionary
...
As far as I understand, this should just set the dictionary beginning with the vars node on every iteration, but it somehow doesn't. Is there any chance to get something like this to work, or do I really have to redefine all properties at the role call, populating them using with_items?
Given the role
shell> cat roles/davidwittman_redis/tasks/main.yml
- debug:
var: dictionary
Remove with_dict. The playbook
shell> cat playbook.yml
- hosts: localhost
vars_files:
- some_vars_file.yml
tasks:
- name: Install and setup redis
include_role:
name: davidwittman_redis
loop: "{{ redis_config }}"
loop_control:
loop_var: dictionary
gives
shell> ansible-playbook playbook.yml
PLAY [localhost] **********************************************
TASK [Install and setup redis] ********************************
TASK [davidwittman_redis : debug] *****************************
ok: [localhost] =>
dictionary:
vars:
redis_bind: 127.0.0.1
redis_databases: 1
redis_port: 6379
redis_version: 6.0.6
TASK [davidwittman_redis : debug] ******************************
ok: [localhost] =>
dictionary:
vars:
redis_bind: 127.0.0.1
redis_databases: 1
redis_port: 6380
redis_version: 6.0.6
Q: "Might there be an issue related to the variable population on role call?"
A: Yes. It can. See Variable precedence. vars_files is precedence 14. Any higher precedence will override it. Decide how to structure the data and optionally use include_vars (precedence 18). For example
shell> cat playbook.yml
- hosts: localhost
tasks:
- include_vars: some_vars_file.yml
- name: Install and setup redis
include_role:
name: davidwittman_redis
loop: "{{ redis_config }}"
loop_control:
loop_var: dictionary
Ultimately, command line --extra-vars would override all previous settings
shell> ansible-playbook playbook.yml --extra-vars "#some_vars_file.yml"
Q: "Maybe it is not possible to set the vars section directly via an external dictionary?"
A: It is possible, of course. The example in this answer clearly proves it.