使用 jinja2 创建 ansible 列表变量

Create ansible list variable with jinja2

以下代码在角色的 defaults/main.yml 文件中:

  file_env: "{% if cf_env is equalto 'cf10_dev' %}\
  dev\
  {% elif cf_env is equalto 'cf10_stg' %}\
  stg\
  {% elif (cf_env is equalto 'cf10_prd') or (cf_env is equalto 'cf10_prd_ext') %}\
  prd\
  {% elif cf_env is equalto 'cf11' %}\
  [dev, prd]
  {% endif %}"

前 3 个条件语句工作正常,其中 file_env var 设置为单个值,但是当尝试将 file_env var 设置为列表时(最后一个 elif 语句),它不起作用:

failed: [server-new.xxx.com] (item=[dev, prd] ) => {"ansible_loop_var": "item", "changed": false, "item": "[dev, prd] ", "msg": "Destination /opt/coldfusion11/[dev, prd] 01/bin/jvm.config does not exist !", "rc": 257}

这是生成上述错误的任务:

- name: Update jvm.config for coldfusion11 server
  lineinfile:
    path: /opt/coldfusion11/{{ item }}01/bin/jvm.config
    regexp: '^java.home'
    line: 'java.home=/usr/lib/jvm/jre-openjdk'
  loop:
    - "{{ file_env }}"
  notify:
    - handler_create_script_list
    - handler_restart_coldfusion10
  when:
    - cf_env == "cf11"

如何将 file_env 变量设置为列表?

我认为您的问题是它将变量解释为字符串,字面意思是 '[dev, prd] '(根据错误消息判断,最后是 space)。

我想你想试试 https://serverfault.com/a/913936/512181

中建议的不同格式
  1. 如果您要遍历您的 var,您应该始终 return 一个列表(需要时使用单个元素)以避免可能出现棘手的错误。您只需将 loop 表达式修改为以下内容:

    loop: "{{ file_env }}"
    
  2. 您的模板表达式没有使用 white space control,这将在输出中出现不应该出现的新行。

  3. 你的变量定义很难读(这让我觉得你有更深层次的项目架构问题,但那是另一回事了)。考虑到上面的第 1 点,我建议您使用字典中的 key/value 映射并在最终 var

    中获取相应的值,重构为以下更具可读性、可持续性和工作性的形式
    files_by_env
      cf10_dev:
        - dev
      cf10_stg:
        - stg
      cf10_prd:
        - prd
      cf10_prd_ext:
        - prd
      cf11:
       - dev
       - prd
    
    file_env: "{{ files_by_env[cf_env] }}"
    

    或者,您可以反转 dict 中的定义(即列出每个文件的环境),这稍微不那么冗长,但会导致更复杂的表达式来获得结果

    env_by_file:
      dev:
        - cf10_dev
        - cf11
      stg:
        - cf10_stg
      prd:
        - cf10_prd
        - cf10_prd_ext
        - cf11
    
    file_env: "{{ env_by_file | dict2items | selectattr('value', 'contains', cf_env) | map(attribute='key') | list }}"