可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a playbook that runs different roles on different hosts.
Is it possible to pass a variable from one role running on one host to another role on another host running within the same playbook run? Or any workaround ?
playbook
host1
role1
here I get some variables: var1 var2 ...etc
host2
role2
here I need to use var1 var2 ... etc from the above host/role
The task in role1 that sets teh variable db
looks like this:
- shell: cd /ACE/conf && grep ^db.url local1.properties | awk -F/ '{print $4}' | awk -F? '{print $1}'
register: db
UPDATE: On the first host the values are dynamic, it's like a configuration file that is always updated. After I store the values in variables on host1 with the role1 I then move to the host2, run the role2 and do stuff with those values from variables stored by host1.
I tried with hostvars:
{{ hostvars.LBL.db.stdout }}
{{ hostvars['LBL']['db'] }}
{{ hostvars['LBL']['db']['stdout'] }}
and I get error:
in get_variables raise Exception("host not found: %s" % hostname) Exception: host not found: LBL
LBL exists in hosts as on it I run the first role
I set a variable on one host and I want that variable to be available to the other host. All this within a single playbook. Can it be done ?
hostvars is not working using it like this:
---
- name: test hostvars host1
hosts: LBL
tasks:
- command: "ls /bin"
register: ls_out
- name: test hostvars host2
hosts: LM
tasks:
- debug:
var: "{{ hostvars['LBL']['ls_out']['stdout'] }}"
error:
fatal: [10.104.148.138] => host not found: LBL
/etc/ansible/hosts
[root@NS1 ansible]# cat /etc/ansible/hosts
[LBL]
10.104.148.136
[LM]
10.104.148.138
回答1:
The problem is in your inventory.
This message:
fatal: [10.104.148.138] => host not found: LBL
is because LBL
is a group and not a host. Group LBL
has one host in it: 10.104.148.136
Do one of the following:
1. Change your inventory (/etc/ansible/hosts
) to:
LBL ansible_ssh_host=10.104.148.136
LM ansible_ssh_host=10.104.148.138
2. or if you really know what you're doing and LBL
is a group and you wanna keep it that way then access the variable with:
{{ hostvars['10.104.148.136']['db']['stdout'] }}
Again LBL is a group not a host. More info.
回答2:
This topic is complicated, and there are two different answers depending on what you want.
Access a variable defined in one role inside other for the same host
Example:
---
- hosts: host1
- roles:
- role1
- role2
Goal: You want to access some variable from role1 inside role2.
Use set_fact
module.
Inside role1:
name: save precious value
set_fact:
pantsu: shiroi
Inside role2:
name: Nozoki...
debug: msg="Color is {{ pantsu }}"
Access to static variable for one host (or group) to other
Example:
[group_foo]
host1
host2
[group_bar]
host3
host4
group_vars/group_foo
important_value=bla-bla-ba
Goal: You want to use it in playbook for group2.
This is much trickier to do.
Inside group_vars/group_bar
other_var: '{{hostvars[groups["group_foo"][0]].important_value}}'
You can use other indexes besides '0'.
回答3:
Here's my solution. My task was to sync data between two servers and I wanted to pass in the server names like this: ansible-playbook sync.yaml -e "source=host1 destination=host2"
Here's the main playbook:
---
- name: get_sync_facts
hosts: "{{ source }}"
roles:
- set_sync_facts
- name: sync
hosts: "{{ destination }}"
roles:
- get_sync_facts
- sync
Here's the set_sync_facts role:
---
- set_fact: src_media_dir='/some/dir/'
- set_fact: src_user='myuser'
- set_fact: src_host='1.1.1.1'
- set_fact: src_port=12345
- set_fact: src_db_user='dbuser'
- set_fact: src_db_password='something'
- set_fact: src_db_name='some_db'
(I actually derived some of these from tasks and others from host vars but you get the point)
And here's the get_sync_facts role:
---
- set_fact: src_media_dir={{ hostvars[source]['src_media_dir'] }}
- set_fact: src_user={{ hostvars[source]['src_user'] }}
- set_fact: src_host={{ hostvars[source]['src_host'] }}
- set_fact: src_port={{ hostvars[source]['src_port'] }}
- set_fact: src_db_user={{ hostvars[source]['src_db_user'] }}
- set_fact: src_db_password={{ hostvars[source]['src_db_password'] }}
- set_fact: src_db_name={{ hostvars[source]['src_db_name'] }}
You could do without this and just reference hostvars directly in your plays but this seemed easier to maintain as it corresponds directly with the set_sync_facts role.
回答4:
it is quite old topic, but maybe it will be helpfull to somebody. I used sed to get hostname based on "target" specified in extra parameters.
To use this "target" group must contain only 1 hostname.
My inventory hosts:
[ansible_local]
localhost
[machine1]
machine1.domain.tld
upgrade_packages.yml
---
- hosts: '{{ target }}'
sudo: yes
tasks:
- name: check for Debian system
shell: /bin/false
when: ansible_pkg_mgr != "apt"
- name: full-upgrade all packages
apt: update_cache=yes upgrade=full
register: upgrade_result
- hosts: ansible_local
tasks:
- name: find out host from target
shell: /bin/sed -n -e '/^\[{{ target }}\]$/,/^\[.*\]$/ { /^\[/d; /^$/d; p; }' {{ inventory_file }}
register: target_inventory
- name: Display all facts from target machine (change when to true if needed)
debug: var=hostvars[target_inventory.stdout]
when: false
- name: Display upgrade result on ansible_local node
debug: var=hostvars[target_inventory.stdout].upgrade_result.msg
Invoke with: ansible-playbook ./upgrade-packages.yml -e "target=machine1" -v
回答5:
I had a similar setup where there are three hosts h1,h2,h3 and on each of them I wanted to define a fact { "important_fact": "foo" }
(and bar, and baz, respectively)
To obtain a list containing all the different important_facts on all hosts, you can do this like so:
- set_fact:
important_facts_list: "{{ hostvars | json('*.important_fact') }}"
run_once: yes
delegate_to: h1
important_facts_list
will contain [ 'foo', 'bar', 'baz' ]
, and you can now iterate over them using with_items
.