在“命令”任务中动态传递 json 作为参数

在“命令”任务中动态传递 json 作为参数

我的剧本中有这项任务:

- name: Update instance tags
    command: oci compute instance update -c {{ compartment }} --freeform-tags {{ tag_var_json }}

根据Oracle 文档对于此命令,参数--freeform-tags接受一个代表标签键值对的 json。我需要在剧本本身中动态创建此 json,因此在运行该任务之前,我有这个用于测试目的:

  - name: Create a json object to use as tag
    set_fact:
      tag_var: '{ "test": "thisisatest" }'
    set_fact:
      tag_var_json: "{{ tag_var | to_json }}"

但我一定是做错了什么,因为我一直收到这个错误:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'tag_var' is undefined

有没有更简单的方法可以在剧本中直接创建 json 并将其作为参数传递给该参数?

谢谢。

答案1

这里有两件事。首先,您创建的 YAML 已被解析器接受,但其行为方式略有出乎意料(并且会在当前版本的 Ansible 中产生警告)。

  - name: Create a json object to use as tag
    set_fact:
      tag_var: '{ "test": "thisisatest" }'
    set_fact:
      tag_var_json: "{{ tag_var | to_json }}"

YAML 中的键是唯一的;当解析器遇到相同键的第二个实例时,它会丢弃第一个实例。由于您已重复set_fact,因此这相当于:

  - name: Create a json object to use as tag
    set_fact:
      tag_var_json: "{{ tag_var | to_json }}"

然而,纠正语法错误仍然会导致失败。

  - name: Create a json object to use as tag
    set_fact:
      tag_var: '{ "test": "thisisatest" }'
      tag_var_json: "{{ tag_var | to_json }}"

在任务运行之前必须对参数set_fact进行模板化,此时 tag_var 仍然未定义(因为该任务正在定义它。)

将此任务写成两个单独的任务是一种正确的方法:

  - name: Create a tag object
    set_fact:
      tag_var:
        test: thisisatest

  - name: Create a JSON string for tagging
    set_fact: 
      tag_var_json: "{{ tag_var | to_json }}"

但是,set_fact这完全不是必需的。您可以直接在使用它的任务上设置 var,这样既更高效,又使其范围更紧密。

- name: Update instance tags
    command: oci compute instance update -c {{ compartment }} --freeform-tags "{{ tag_var | to_json }}"
  vars:
    tag_var:
      test: thisisatest

相关内容