使用 HTTP 获取 YAML 文件并将其用作 Ansible 剧本中的变量
Get a YAML file with HTTP and use it as a variable in an Ansible playbook
背景
我在网络服务器上有一个这样的 YAML 文件。我正在尝试阅读它并使用 Ansible 剧本在文件中创建用户帐户。
users:
- number: 20210001
name: Aoki Alice
id: alice
- number: 20210002
name: Bob Bryant
id: bob
- number: 20210003
name: Charlie Cox
id: charlie
我试过的
为了确认如何使用 include_vars
动态读取下载的 YAML 文件,我写了一个这样的剧本:
- name: Add users from list
hosts: workstation
tasks:
- name: Download yaml
get_url:
url: http://fqdn.of.webserver/path/to/yaml.yml
dest: "/tmp/tmp.yml"
notify:
- Read yaml
- List usernames
handlers:
- name: Read yaml
include_vars:
file: /tmp/tmp.yml
name: userlist
- name: List usernames
debug:
var: "{{ item }}"
loop: "{{ userlist.users }}"
问题
在处理程序 Read yaml
中,我收到以下错误消息。在目标机器 (workstation.example.com
) 上,/tmp/tmp.yml
被正确下载。
RUNNING HANDLER [Read yaml] *****
fatal: [workstation.example.com]: FAILED! => {"ansible facts": {"userlist": []},
"ansible included var files": [], "changed": false, "message": "Could not find o
r access '/tmp/tmp. yml' on the Ansible Controller.\nIf you are using a module a
nd expect the file to exist on the remote, see the remote src option"}
问题
如何使用 HTTP 获取 YAML 文件并将其用作 include_vars
的变量?
include_vars
任务在本地(控制)主机上查找文件,但您已将文件下载到远程主机上的 /tmp/tmp.yml
。有多种方法可以让它发挥作用。
也许最简单的方法就是 运行在控制机器上执行下载任务(注意 delegate_to
的使用):
tasks:
- name: Download yaml
delegate_to: localhost
get_url:
url: http://fqdn.of.webserver/path/to/yaml.yml
dest: "/tmp/tmp.yml"
notify:
- Read yaml
- List usernames
这会将文件下载到本地系统上的 /tmp/tmp.yml
,供 include_vars
使用。例如,如果我 运行 这个剧本(从我刚刚创建的示例要点中获取 YAML 内容)...
- hosts: target
gather_facts: false
tasks:
- name: Download yaml
delegate_to: localhost
get_url:
url: https://gist.githubusercontent.com/larsks/70d8ac27399cb51fde150902482acf2e/raw/676a1d17bcfc01b1a947f7f87e807125df5910c1/example.yaml
dest: "/tmp/tmp.yml"
notify:
- Read yaml
- List usernames
handlers:
- name: Read yaml
include_vars:
file: /tmp/tmp.yml
name: userlist
- name: List usernames
debug:
var: item
loop: "{{ userlist.users }}"
...它产生以下输出:
RUNNING HANDLER [Read yaml] ******************************************************************
ok: [target]
RUNNING HANDLER [List usernames] *************************************************************
ok: [target] => (item=bob) => {
"ansible_loop_var": "item",
"item": "bob"
}
ok: [target] => (item=alice) => {
"ansible_loop_var": "item",
"item": "alice"
}
ok: [target] => (item=mallory) => {
"ansible_loop_var": "item",
"item": "mallory"
}
旁注:根据我在你的剧本中看到的内容,我不确定你想要
在这里使用 notify
和处理程序。如果你 运行 你的剧本
第二次,什么都不会发生,因为文件 /tmp/tmp.yml
已经存在,因此不会调用处理程序。
另一种选择是使用 uri
模块将值检索到 Ansible 变量中,然后 from_yaml
过滤器对其进行解析。
类似于:
- name: Add users from list
hosts: workstation
tasks:
- name: Download YAML userlist
uri:
url: http://fqdn.of.webserver/path/to/yaml.yml
return_content: yes
register: downloaded_yaml
- name: Decode YAML userlist
set_fact:
userlist: "{{ downloaded_yaml.content | from_yaml }}"
注意uri
在Ansible Controller上工作,而get_url
在目标主机(或delegate_to
中指定的主机)上工作;根据您的网络配置,您可能需要使用不同的代理设置或防火墙规则来允许下载。
根据@Larsks 的回答,我制作了这个在我的环境中可以正常工作的剧本:
- name: Download users list
hosts: 127.0.0.1
connection: local
become: no
tasks:
- name: Download yaml
get_url:
url: http://fqdn.of.webserver/path/to/yaml/users.yml
dest: ./users.yml
- name: Add users from list
hosts: workstation
tasks:
- name: Read yaml
include_vars:
file: users.yml
- name: List usernames
debug:
msg: "{{ item.id }}"
loop: "{{ users }}"
点
运行 get_url
在控制主机上
如@Larsks 所说,您必须 运行 控制主机上的 get_url
模块,而不是目标主机。
在控制主机
上将become: no
添加到任务运行
没有"become: no",你会得到如下错误信息:
TASK [Gathering Facts] ******************************************************
fatal: [127.0.0.1]: FAILED! => {"ansible_facts": {}, "changed": false, "msg":
"The following modules failed to execute: setup\n setup: MODULE FAILURE\nSee
stdout/stderr for the exact error\n"}
使用connection: local
而不是local_action
如果像这样使用 local_action
而不是 connection: local
:
- name: test get_url
hosts: workstation
tasks:
- name: Download yaml
local_action:
module: get_url
url: http://fqdn.of.webserver/path/to/yaml/users.yml
dest: ./users.yml
- name: Read yaml
include_vars:
file: users.yml
- name: output remote yaml
debug:
msg: "{{ item.id }}"
loop: "{{ users }}"
您将收到以下错误消息:
TASK [Download yaml] ********************************************************
fatal: [workstation.example.com]: FAILED! => {"changed": false, "module_stde
rr": "sudo: a password is required\n", "module_stdout":"", "msg":"MODULE FAIL
URE\nSee stdout/stderr for the exact error", "rc": 1}
get_url
在控制主机上存储一个文件
在这种情况下,get_url
模块将 users.yml
存储在控制主机上(在当前目录中)。所以你必须删除 users.yml
如果你不想离开它。
背景
我在网络服务器上有一个这样的 YAML 文件。我正在尝试阅读它并使用 Ansible 剧本在文件中创建用户帐户。
users:
- number: 20210001
name: Aoki Alice
id: alice
- number: 20210002
name: Bob Bryant
id: bob
- number: 20210003
name: Charlie Cox
id: charlie
我试过的
为了确认如何使用 include_vars
动态读取下载的 YAML 文件,我写了一个这样的剧本:
- name: Add users from list
hosts: workstation
tasks:
- name: Download yaml
get_url:
url: http://fqdn.of.webserver/path/to/yaml.yml
dest: "/tmp/tmp.yml"
notify:
- Read yaml
- List usernames
handlers:
- name: Read yaml
include_vars:
file: /tmp/tmp.yml
name: userlist
- name: List usernames
debug:
var: "{{ item }}"
loop: "{{ userlist.users }}"
问题
在处理程序 Read yaml
中,我收到以下错误消息。在目标机器 (workstation.example.com
) 上,/tmp/tmp.yml
被正确下载。
RUNNING HANDLER [Read yaml] *****
fatal: [workstation.example.com]: FAILED! => {"ansible facts": {"userlist": []},
"ansible included var files": [], "changed": false, "message": "Could not find o
r access '/tmp/tmp. yml' on the Ansible Controller.\nIf you are using a module a
nd expect the file to exist on the remote, see the remote src option"}
问题
如何使用 HTTP 获取 YAML 文件并将其用作 include_vars
的变量?
include_vars
任务在本地(控制)主机上查找文件,但您已将文件下载到远程主机上的 /tmp/tmp.yml
。有多种方法可以让它发挥作用。
也许最简单的方法就是 运行在控制机器上执行下载任务(注意 delegate_to
的使用):
tasks:
- name: Download yaml
delegate_to: localhost
get_url:
url: http://fqdn.of.webserver/path/to/yaml.yml
dest: "/tmp/tmp.yml"
notify:
- Read yaml
- List usernames
这会将文件下载到本地系统上的 /tmp/tmp.yml
,供 include_vars
使用。例如,如果我 运行 这个剧本(从我刚刚创建的示例要点中获取 YAML 内容)...
- hosts: target
gather_facts: false
tasks:
- name: Download yaml
delegate_to: localhost
get_url:
url: https://gist.githubusercontent.com/larsks/70d8ac27399cb51fde150902482acf2e/raw/676a1d17bcfc01b1a947f7f87e807125df5910c1/example.yaml
dest: "/tmp/tmp.yml"
notify:
- Read yaml
- List usernames
handlers:
- name: Read yaml
include_vars:
file: /tmp/tmp.yml
name: userlist
- name: List usernames
debug:
var: item
loop: "{{ userlist.users }}"
...它产生以下输出:
RUNNING HANDLER [Read yaml] ******************************************************************
ok: [target]
RUNNING HANDLER [List usernames] *************************************************************
ok: [target] => (item=bob) => {
"ansible_loop_var": "item",
"item": "bob"
}
ok: [target] => (item=alice) => {
"ansible_loop_var": "item",
"item": "alice"
}
ok: [target] => (item=mallory) => {
"ansible_loop_var": "item",
"item": "mallory"
}
旁注:根据我在你的剧本中看到的内容,我不确定你想要
在这里使用 notify
和处理程序。如果你 运行 你的剧本
第二次,什么都不会发生,因为文件 /tmp/tmp.yml
已经存在,因此不会调用处理程序。
另一种选择是使用 uri
模块将值检索到 Ansible 变量中,然后 from_yaml
过滤器对其进行解析。
类似于:
- name: Add users from list
hosts: workstation
tasks:
- name: Download YAML userlist
uri:
url: http://fqdn.of.webserver/path/to/yaml.yml
return_content: yes
register: downloaded_yaml
- name: Decode YAML userlist
set_fact:
userlist: "{{ downloaded_yaml.content | from_yaml }}"
注意uri
在Ansible Controller上工作,而get_url
在目标主机(或delegate_to
中指定的主机)上工作;根据您的网络配置,您可能需要使用不同的代理设置或防火墙规则来允许下载。
根据@Larsks 的回答,我制作了这个在我的环境中可以正常工作的剧本:
- name: Download users list
hosts: 127.0.0.1
connection: local
become: no
tasks:
- name: Download yaml
get_url:
url: http://fqdn.of.webserver/path/to/yaml/users.yml
dest: ./users.yml
- name: Add users from list
hosts: workstation
tasks:
- name: Read yaml
include_vars:
file: users.yml
- name: List usernames
debug:
msg: "{{ item.id }}"
loop: "{{ users }}"
点
运行 get_url
在控制主机上
如@Larsks 所说,您必须 运行 控制主机上的 get_url
模块,而不是目标主机。
在控制主机
上将become: no
添加到任务运行
没有"become: no",你会得到如下错误信息:
TASK [Gathering Facts] ******************************************************
fatal: [127.0.0.1]: FAILED! => {"ansible_facts": {}, "changed": false, "msg":
"The following modules failed to execute: setup\n setup: MODULE FAILURE\nSee
stdout/stderr for the exact error\n"}
使用connection: local
而不是local_action
如果像这样使用 local_action
而不是 connection: local
:
- name: test get_url
hosts: workstation
tasks:
- name: Download yaml
local_action:
module: get_url
url: http://fqdn.of.webserver/path/to/yaml/users.yml
dest: ./users.yml
- name: Read yaml
include_vars:
file: users.yml
- name: output remote yaml
debug:
msg: "{{ item.id }}"
loop: "{{ users }}"
您将收到以下错误消息:
TASK [Download yaml] ********************************************************
fatal: [workstation.example.com]: FAILED! => {"changed": false, "module_stde
rr": "sudo: a password is required\n", "module_stdout":"", "msg":"MODULE FAIL
URE\nSee stdout/stderr for the exact error", "rc": 1}
get_url
在控制主机上存储一个文件
在这种情况下,get_url
模块将 users.yml
存储在控制主机上(在当前目录中)。所以你必须删除 users.yml
如果你不想离开它。