Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

conditional statements - Create ansible list variable with jinja2

The following code is in the defaults/main.yml file for a role:

  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 %}"

The first 3 conditional statements work fine, where the file_env var is set to a single value, but when trying to set the file_env var to a list (the last elif statement), it doesn't work:

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}

Here is the task that generates the above error:

- 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"

How can I set the file_env var to a list?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. If your are going to loop over your var, you should always return a list (with single element when needed) to avoid possible tricky errors. You simply need to modify your loop expression to the following:

    loop: "{{ file_env }}"
    
  2. Your template expressions are not using white space control which will end up with new lines in the output when they should not appear.

  3. Your variable definition is hardly readable (and makes me think you have a deeper project architecture issue but that's an other story). Taking into account point 1 above, I suggest you refactor to the following more readable, sustainable and working form using a key/value mapping in a dict and getting the corresponding value in your final 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] }}"
    

    Alternatively, you can reverse the definition in the dict (i.e. list environments for every file) which is slightly less verbose but leads to a more complicated expression to get the result

    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 }}"
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...