0
votes

Getting error when using an if/else condition to set a variable in a playbook on Red Hat.

I tried a few different permutations of quotes, brackets etc.

Executed as "ansible-playbook -e env=dev playbook.yaml"

Set Vars:

vars:

  certenv: "{{ '-eng.dev.' if {{env}} == 'eng' else '.dev.' if {{env}} == 'dev' else '.uat.' if {{env}} == 'stg' else '.prd.' if {{env}} == 'prd' }}"

Task

   - name: Update server.xml Cert

     lineinfile:

      dest: "{{tomcat}}/conf/server.xml"

      regexp: '^(.*)certificateFile(.*)$'

      line: 'certificateFile="{{tomcat}}/webapps/{{appwar}}/certificates/app{{certenv}}domain.cer"'

Error

fatal: [localhost]: FAILED! => {"msg": "An unhandled exception occurred while templating '{{ '-eng.dev.' if {{env}} == 'eng' else '.dev.' if {{env}} == 'dev' else '.uat.' if {{env}} == 'stg' else '.prd.' if {{env}} == 'prd' }}'. 
Error was a <class 'ansible.errors.AnsibleError'>, original message: template error while templating string: expected token ':', got '}'. String: {{ '-eng.dev.' if {{env}} == 'eng' else '.dev.' if {{env}} == 'dev' else '.uat.' if {{env}} == 'stg' else '.prd.' if {{env}} == 'prd' }}"}

Expecting the certenv variable to be set as ".dev." for example.

3
Why don't you try working with when? From ansible conditionals. - HermanTheGermanHesse
Did you try: certenv: "{{ '-eng.dev.' if env == 'eng' else '.dev.' if env == 'dev' else '.uat.' if env == 'stg' else '.prd.' if env == 'prd' }}" - WarrenG
@HermanTheGermanHesse - will look into "when" thanks. - danbee
@cpt_guy - I get " 'env' is undefined" - thanks for reply though - danbee
Have you got a variable called env? We're on the right track here I think. - WarrenG

3 Answers

0
votes

For jinja2, the syntax is:

vars:
  certenv: "{% if env == 'eng' %}-eng.dev.{% elif env == 'dev' %}.dev.{% elif env == 'stg' %}.uat.{% elif env == 'prd' %}.prd.{% endif %}"

You do not need to put the variables in {{...}} because they are inside the jinja2 markers {%...%}.

You can also make it more readable:

vars:
  certenv:
    "{% if env == 'eng' %}
        -eng.dev.
     {% elif env == 'dev' %}
        .dev.
     {% elif env == 'stg' %}
        .uat.
     {% elif env == 'prd' %}
        .prd.
     {% endif %}"
0
votes

An option would be to use selectattr and map. The play below

vars:
  cert_options:
    eng: "-eng.dev."
    dev: ".dev."
    stg: ".uat."
    prd: ".prd."
  env: "stg"
tasks:
  - set_fact:
      certenv: "{{ cert_options|dict2items|selectattr('key', 'match', env)|map(attribute='value')|list }}"
  - debug:
      var: item
    loop: "{{ certenv }}"

gives:

"item": ".uat."

This hint might help to solve the problem.

The fixed syntax of the code is below. (not tested)

- name: Update server.xml Cert
  lineinfile:
    dest: "{{ tomcat }}/conf/server.xml"
    regexp: "^(.*)certificateFile(.*)$"
    line: "certificateFile={{ tomcat }}/webapps/{{ appwar }}/certificates/app{{ certenv }}domain.cer"
0
votes

As per comments: Modify your variable to

certenv: "{{ '-eng.dev.' if env == 'eng' else '.dev.' if env == 'dev' else '.uat.' if env == 'stg' else '.prd.' if env == 'prd' }}"

and run your playbook with:

ansible-playbook myplaybook.yml -e "env=dev".