如何在 ansible 的加壳器中将变量设置为列表?

how to set a variable as a list in packer for ansible?

当试图传递通常是 ansible 中的列表的 var 时,我无法在 packer 中执行此操作。

  provisioner "ansible" {
    playbook_file = "./ansible/houdini_module.yaml"
    extra_arguments = [
      "-vv",
      "--extra-vars",
      "houdini_major_version_list=[19.0]",
    ]
  }

在我的剧本中,如果我用 {{ houdini_major_version_list|length }} 测试 houdini_major_version_list 的长度,它说长度是 6,而它应该是 1。

在加壳器中使用 --extra-vars 传递列表的正确方法是什么?

问题是 key=value format 中的额外变量 -e, --extra-vars 始终是字符串。给定下面的变量,在代码的任何地方声明,

l: [19.0]

下面的任务结果符合预期

    - debug:
        msg: |-
          l|type_debug: {{ l|type_debug }}
          l|length: {{ l|length }}
          l.0|type_debug: {{ l.0|type_debug }}
          l.0: {{ l.0 }}
  msg: |-
    l|type_debug: list
    l|length: 1
    l.0|type_debug: float
    l.0: 19.0

但是,当您在命令行以 k=v 格式声明此变量时,类型为字符串且此字符串的长度为 6

shell> ansible-playbook playbook.yml -e l=[19.0]
...
  msg: |-
    l|type_debug: str
    l|length: 6
    l.0|type_debug: str
    l.0: [

要解决此问题,请使用 JSON string format

shell> ansible-playbook pb1.yml -e '{"l": [19.0]}'
...
  msg: |-
    l|type_debug: list
    l|length: 1
    l.0|type_debug: float
    l.0: 19.0

YAML 格式给出相同的结果

shell> ansible-playbook playbook.yml -e "l: [19.0]"

可选地,将变量放入 JSON or YAML file。声明更多变量时很实用。例如

shell> cat some_file.yml
l: [19.0]
k: [20.0]

会给

shell> ansible-playbook playbook2.yml -e "@some_file.yml"
...
  msg: |-
    l.0: 19.0
    k.0: 20.0

如果您无法更改命令的格式,请自行转换变量。例如,

    - set_fact:
        l_local: "{{ l.split('=')|last|from_yaml }}"
    - debug:
        msg: |-
          l_local|type_debug: {{ l_local|type_debug }}
          l_local|length: {{ l_local|length }}
          l_local.0|type_debug: {{ l_local.0|type_debug }}
          l_local.0: {{ l_local.0 }}

然后,命令给出

shell> ansible-playbook playbook.yml -e "l=[19.0]"
...
  msg: |-
    l_local|type_debug: list
    l_local|length: 1
    l_local.0|type_debug: float
    l_local.0: 19.0

您不能覆盖额外变量,即本例中的 l,因为 extra varshighest precedence

另一个答案有助于解释为什么类型不正确作为通过 CLI 输入到 Ansible 的变量。满足此要求并解决您的问题的 Packer HCL2 模板更新为:

provisioner "ansible" {
  playbook_file = "${path.root}/ansible/playbook.yaml"
  extra_arguments = [
    "-vv",
    "--extra-vars",
    jsonencode({ "houdini_major_version_list" = ["19.0"] }),
  ]
}

设置环境变量 PACKER_LOG=1 我们看到这会执行:

ansible-playbook ... -vv --extra-vars {"houdini_major_version_list":["19.0"]} ... /path/to/playbook.yaml

这表明 Packer 和 Ansible provisioner 之间的接口现在可以正确传递 list 类型变量。

请注意,jsonencode({ "houdini_major_version_list" = [19.0] 会导致 {"houdini_major_version_list":[19]},因为浮动会自动删除 .0