Ansible - tower_host bulk delete host from inventories - ansible

I would like to remove a host from all the inventories it is part of.
I tried something like this, but that does not work:
---
- hosts: [MYHOST]
tasks:
- name: "Test deletion"
tower_host:
name: "{{ vm_hostname }}"
inventory:
- "RedHat"
- "RedHat-Hors-Prod"
- "RedHat-Prod"
state: absent
...
Is this possible without create 3 differents tasks?
Thanks

The way to do this is by using a loop:
---
- hosts: pransibleapp
tasks:
- name: "Test deletion"
tower_host:
name: "{{ vm_hostname }}"
inventory: "{{ item }}"
state: absent
.
.
loop:
- "RedHat"
- "RedHat-Hors-Prod"
- "RedHat-Prod"
Doc : https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#iterating-over-a-simple-list

Related

Replacement with regex

I tried to trim the custom facts but it will not give me expected result. My entire code as below.
---
- name: Extarcting the Value
hosts: localhost
gather_facts: no
connection: local
vars:
app_brach: onkar-test
vars_files:
- common.yml
tasks:
- name: setting the facts
set_fact:
app_name_list: "{{ app_name_list|default([])) + [item.name] }}'
loop: "{{apps_to_deploy}}"
- name: display information
debug:
var: app_name_list
- name: resetting the fact
set_fact:
app_name_list: "{{ item | reject('search', '{{app_branch'}} | list }}"
loop: app_name_list
- name: display new list
debug:
var: app_name_list1
and my common.yml is as below.
---
apps_to_deploy:
- name: jaw-app-worker-{{app_branch}}
version: 1.0.0
- name: jaw-pat-valid-{{app_branch}}
version: 1.0.1
basically first I want to assign app_name_list with app_branch which is vriable and again need to reset app_name_list custome facts by removing app_branch variable.

Ansible filter dict based on key presence and list values

I have this variable :
components:
comp_one:
name: first_component
remote_server_path: "/tmp/path/one"
binaries:
- test
- test_two
comp_two:
name: second_component
remote_server_path: "/tmp/path/two"
binaries:
- ed_test
- ed_test_2
comp_three:
name: third_component
remote_server_path: "/tmp/path/three"
What I'm trying to achieve, is to only keep sub-dictionaries of components that has key binaries, and the filter those binaries using my group_names. Also, D'd like to only keep dict keys binaries and remote_server_path.
For example, if i have this hosts.yaml :
---
all:
children:
kubernetes_dev:
children:
ed_test:
hosts:
host_one:
ansible_host: XXX.XXX.XXX.XXX
ansible_ssh_user: ansible
test_two:
hosts:
host_one:
ansible_host: XXX.XXX.XXX.XXX
ansible_ssh_user: ansible
test:
hosts:
host_one:
ansible_host: XXX.XXX.XXX.XXX
ansible_ssh_user: ansible
The expected output would be :
comp_one:
remote_server_path: "/tmp/path/one"
binaries:
- test
- test_two
comp_two:
remote_server_path: "/tmp/path/two"
binaries:
- ed_test
I've successfully filtered the comp_three dict using this :
- name: Debug
ansible.builtin.debug:
msg: "{{ item }}"
with_items: "{{ components | dict2items | selectattr('value.binaries', 'defined') }}"
But, I can't figure out a way to only select binaries and remote_server_path keys while filtering with my `group_names.
Does anyone can't help me find a clean way to do this ?
Regards,
Use group_names. This is: "List of groups the current host is part of.". For the host host_one in the inventory hosts.yaml this is
group_names: [ed_test, test, test_two]
Convert the dictionary components to list and test intersect of binaries and group_names. Default to empty list if the attribute binaries is missing
- set_fact:
selected_list: "{{ selected_list|d([]) + [_item] }}"
loop: "{{ components|dict2items }}"
when: my_groups|length > 0
vars:
_item: "{{ item|combine(my_value) }}"
my_value: "{{ {'value': {'binaries': my_groups,
'remote_server_path': item.value.remote_server_path}} }}"
my_groups: "{{ item.value.binaries|d([])|intersect(group_names) }}"
gives
selected_list:
- key: comp_one
value:
binaries:
- test
- test_two
remote_server_path: /tmp/path/one
- key: comp_two
value:
binaries:
- ed_test
remote_server_path: /tmp/path/two
Conver the list into a dictionary
- set_fact:
selected_dict: "{{ selected_list|items2dict }}"
gives the expected result
selected_dict:
comp_one:
binaries:
- test
- test_two
remote_server_path: /tmp/path/one
comp_two:
binaries:
- ed_test
remote_server_path: /tmp/path/two
Example of a complete playbook
- hosts: all
vars:
components:
comp_one:
name: first_component
remote_server_path: /tmp/path/one
binaries:
- test
- test_two
comp_two:
name: second_component
remote_server_path: /tmp/path/two
binaries:
- ed_test
- ed_test_2
comp_three:
name: third_component
remote_server_path: /tmp/path/three
tasks:
- set_fact:
selected_list: "{{ selected_list|d([]) + [_item] }}"
loop: "{{ components|dict2items }}"
when: my_groups|length > 0
vars:
_item: "{{ item|combine(my_value) }}"
my_value: "{{ {'value': {'binaries': my_groups,
'remote_server_path': item.value.remote_server_path}} }}"
my_groups: "{{ item.value.binaries|d([])|intersect(group_names) }}"
- set_fact:
selected_dict: "{{ selected_list|items2dict }}"
- debug:
var: selected_dict

"search" a string in "when:" conditional statement?

In the following playbook, I have to use search in a when: statement. Can you please tell me what is wrong with the statement when: item.name is search (domain_list)? domain_list is an array variable defined in files.yml as shown below.
---
- hosts: localhost
gather_facts: False
connection: local
vars_files:
- files.yml
vars:
infra:
- name: ironman.vcloud-lab.com
connection_state: CONNECTED
- name: hulk.vcloud-lab.com
connection_state: CONNECTED
- name: captain.vcloud-lab.com
connection_state: DISCONNECTED
- name: hawkeye.vcloud-lab.com
connection_state: DISCONNECTED
tasks:
- name: Filter list of only connected esxi
set_fact:
esxilist: "{{esxilist | default([]) + [item]}}"
with_items: "{{infra}}"
when: item.name is search (domain_list) ## <= please correct me here, it doesn't work
- name: Show connected esxi list information
debug:
var: esxilist
files.yml
---
domain_list:
- ironman
- captain
Select the short name and test the presence in the list. For example, use regex_replace
- name: Filter list of only connected esxi
set_fact:
esxilist: "{{ esxilist|default([]) + [item] }}"
loop: "{{ infra }}"
when: _short in domain_list
vars:
_short: "{{ item.name|regex_replace('^(.*?)\\.(.*)$', '\\1') }}"
gives
esxilist:
- connection_state: CONNECTED
name: ironman.vcloud-lab.com
- connection_state: DISCONNECTED
name: captain.vcloud-lab.com
The next option is to split the string and select the first item. For example
vars:
_short: "{{ item.name.split('.')|first }}"
gives the same result.
See How to create a Minimal, Reproducible Example. For example
- hosts: localhost
vars:
domain_list: [a, b]
infra:
- {name: a.vcloud-lab.com, state: CONNECTED}
- {name: b.vcloud-lab.com, state: DISCONNECTED}
- {name: c.vcloud-lab.com, state: CONNECTED}
tasks:
- set_fact:
l1: "{{ l1|default([]) + [item] }}"
with_items: "{{ infra }}"
when: _short in domain_list
vars:
_short: "{{ item.name.split('.')|first }}"
- debug:
var: l1

How to set fact witch is visible on all hosts in Ansible role

I'm setting fact in a role:
- name: Check if manager already configured
shell: >
docker info | perl -ne 'print "$1" if /Swarm: (\w+)/'
register: swarm_status
- name: Init cluster
shell: >-
docker swarm init
--advertise-addr "{{ ansible_default_ipv4.address }}"
when: "'active' not in swarm_status.stdout_lines"
- name: Get worker token
shell: docker swarm join-token -q worker
register: worker_token_result
- set_fact:
worker_token: "{{ worker_token_result.stdout }}"
Then I want to access worker_token on another hosts. Here's my main playbook, the fact is defined in the swarm-master role
- hosts: swarm_cluster
become: yes
roles:
- docker
- hosts: swarm_cluster:&manager
become: yes
roles:
- swarm-master
- hosts: swarm_cluster:&node
become: yes
tasks:
- debug:
msg: "{{ worker_token }}"
I'm getting undefined variable. How to make it visible globally?
Of course it works perfectly if I run debug on the same host.
if your goal is just to access worker_token from on another host, you can use hostvars variable and iterate through the group where you've defined your variable like this:
- hosts: swarm_cluster:&node
tasks:
- debug:
msg: "{{ hostvars[item]['worker_token'] }}"
with_items: "{{ groups['manager'] }}"
If your goal is to define the variable globally, you can add a step to define a variable on all hosts like this:
- hosts: all
tasks:
- set_fact:
worker_token_global: "{{ hostvars[item]['worker_token'] }}"
with_items: "{{ groups['manager'] }}"
- hosts: swarm_cluster:&node
tasks:
- debug:
var: worker_token_global

How to pass results back from include_tasks

Started to learn ansible yesterday, so I believe I may risk XY problem here, but still…
The main yml:
- hosts: localhost
vars_files:
[ "users.yml" ]
tasks:
- name: manage instances
#include_tasks: create_instance.yml
include_tasks: inhabit_instance.yml
with_dict: "{{users}}"
register: res
- name: print
debug: msg="{{res.results}}"
inhabit_instance.yml:
- name: Get instance info for {{ item.key }}
ec2_instance_facts:
profile: henryaws
filters:
"tag:name": "{{item.key}}"
instance-state-name: running
register: ec2
- name: print
debug:
msg: "IP: {{ec2.instances.0.public_ip_address}}"
So that's that IP that I'd like to have on the top level. Haven't found anything right away about return values of the include block…
Well, I've found some way that suits me, maybe it's even canonical?
main.yml:
- hosts: localhost
vars_files:
[ "users.yml" ]
vars:
ec_results: {}
tasks:
- name: manage instances
#include_tasks: create_instance.yml
include_tasks: inhabit_instance.yml
with_dict: "{{users}}"
register: res
inhabit_instance.yml:
- name: Get instance info for {{ item.key }}
ec2_instance_facts:
profile: henryaws
filters:
"tag:name": "{{item.key}}"
instance-state-name: running
register: ec2
- name: update
set_fact:
ec_results: "{{ ec_results|combine({ item.key: ec2.instances.0.public_ip_address }) }}"
Thanks for you answer - this helped me to find an answer to my issue when my task was called in a loop - my solution was just to use lists so for your example above, the solution would be:
The main yml:
- hosts: localhost
vars_files:
[ "users.yml" ]
vars:
ec_results: []
tasks:
- name: manage instances
#include_tasks: create_instance.yml
include_tasks: inhabit_instance.yml
with_dict: "{{users}}"
- name: print
debug: msg="{{ec_results}}"
inhabit_instance.yml:
- name: Get instance info for {{ item.key }}
ec2_instance_facts:
profile: henryaws
filters:
"tag:name": "{{item.key}}"
instance-state-name: running
register: ec2
- name: Add IP to results
set_fact:
ec_results: "{{ ec_results + [ec2.instances.0.public_ip_address] }}"
In my code, include_tasks was in a loop so then ec_results contained a list of the results from each iteration of the loop

Resources