Ansible set_facts by localhost json 文件并复制到远程主机

Ansible set_facts by localhost json file and copy to remote hosts

我正在尝试将 json 文件从我的本地主机复制到远程主机,并使用 json“版本”键值作为目标文件名中的参数。

JSON:

{"name": "test", "version": 3}

YML:

---
- name: Get json file version
  hosts: locahost
  become: true
  tasks:
    - name: Register licenses file
      command: "cat conf/licenses.json"
      register: result

    - name: Save the json data
      set_fact:
        jsondata: "{{ result.stdout | from_json }}"

    - name: Save licenses file version
      set_fact:
        file_version: "{{ jsondata | json_query(jmesquery) }}"
      vars:
        jmesquery: 'version'

- name: Deploy Licenses File
  hosts: hosts
  become: true
  tasks:
    - name: Copy licenses file
      copy:
        src: "conf/licenses.json"
        dest: "/tmp/licenses_{{ file_version }}.json"

当我 运行 上面的剧本时,部署许可证文件密钥找不到 file_version 事实,即使我可以看到它已成功保存在 Get json文件版本密钥。

设置file_version事实:

ok: [localhost] => {
    "ansible_facts": {
        "file_version": "1"
    },
    "changed": false
}

错误:

The task includes an option with an undefined variable. The error was: 'file_version' is undefined

我认为事实保存在给定的主机粒度上,而不是每个剧本启动的全局事实。

我目前的解决方法是将密钥组合到一个任务中,然后它就可以正常工作,但我更喜欢一次获取版本,而不是为每个远程主机重复一次。

要访问另一台主机的事实,您始终可以使用 hostvars special variable

因此,在您的情况下:

dest: "/tmp/licenses_{{ hostvars.localhost.file_version }}.json"

现在,您实际上不需要两场比赛那么复杂,并且完全可以做到:

- name: Deploy Licenses File
  hosts: hosts
  become: true

  tasks:
    - name: Copy licenses file
      copy:
        src: "{{ _licence_file }}"
        dest: "/tmp/licenses_{{ file_version }}.json"
      vars:
        _licence_file: conf/licenses.json
        file_version: >-
          {{ (lookup('file', _licence_file) | from_json).version }}

第一个游戏仅在 localhost 运行。因此,在第一个游戏中声明的变量仅对 localhost 可用。这是第二个playhost无法使用变量的原因

The error was: 'file_version' is undefined

运行一次任务在所有主机的第一个块中播放。这样变量将在第二个游戏中对所有主机可用。例如,下面的简化剧本可以完成这项工作

- hosts: all
  tasks:
    - block:
        - include_vars:
            file: licenses.json
            name: jsondata
        - set_fact:
            file_version: "{{ jsondata.version }}"
      run_once: true

- hosts: hosts
  tasks:
    - copy:
        src: licenses.json
        dest: "/tmp/licenses_{{ file_version }}.json"

在远程主机创建文件

shell> ssh admin@test_11 cat /tmp/licenses_3.json
{"name": "test", "version": 3}

代码可以进一步简化。下面的单人游戏也可以做到这一点

- hosts: hosts
  tasks:
    - include_vars:
        file: licenses.json
        name: jsondata
      run_once: true
    - copy:
        src: licenses.json
        dest: "/tmp/licenses_{{ jsondata.version }}.json"