Set a variable according to another variable

Viewed 290

I am working on a gitlab-ci project.
I have a variable A that I retrieve from a form.
I have to set another variable B in my playbook.

If A matches a certain regex, B should be ' -p A' else B should be an empty string ''.
This should be written in an Ansible file.

I have tried

- set_fact: 
  B="{{ ' -p ' + A}}"
  when: A is regex("^\\d{1,8}$")

but it didn't work.
Can someone help me?

2 Answers

You do have three issues, I would say:

  1. you should use an inline if expression of Jinja rather than a when
  2. the backslash of the digit pattern have to be escaped to produce a valid in YAML: \\d
  3. I guess the regex do not match what you think it does, to match between one and eight digit(s), the quantifier have to be used with a comma (,) to separate the minimum and the maximum repetition of the previous pattern, not a dash (-): \\d{1,8}

All together

 - set_fact: 
     B: "{{ ' -p ' ~ migration_time if A is regex('^\\d{1,8}$') else '' }}"

Given the playbook:

- hosts: localhost
  gather_facts: no

  tasks:
    - set_fact: 
        B: "{{ ' -p ' ~ migration_time if A is regex('^\\d{1,8}$') else '' }}"
      vars:
        A: 20220127
        migration_time: 2022-01-27
    
    - debug:
        var: B

This would yield:

TASK [set_fact] *************************************************************
ok: [localhost]

TASK [debug] ****************************************************************
ok: [localhost] => 
  B: ' -p 2022-01-27'

Now, if my assumptions on your regex not matching what you meant are incorrect, here is a valid playbook matching that exact scenario.

Given the playbook:

- hosts: localhost
  gather_facts: no

  tasks:
    - set_fact: 
        B: "{{ ' -p ' ~ migration_time if A is regex('^\\d{1-8}$') else '' }}"
      vars:
        ## This is the value that will make `A` match,
        ## but, I do suspect this is not what you meant
        ## and I guess you meant `^\\d{1,8}$`, rather in your regex.
        A: '1{1-8}' 
        migration_time: 2022-01-27
    
    - debug:
        var: B

This yields:

TASK [set_fact] *************************************************************
ok: [localhost]

TASK [debug] ****************************************************************
ok: [localhost] => 
  B: ' -p 2022-01-27'

Q: "If A matches a certain regex, B should be ' -p A' else B should be an empty string ''."

A: Use the filter ternary, e.g.

  B: "{{ (A is regex('^\\d{1,8}$'))|ternary(' -p ' ~ A, '') }}"

Test it

    - debug:
        msg: 'A: {{ A }} -> B: "{{ B }}"'
      loop:
        - 1234567
        - 12345678
        - 123456789
        - xyz12345
      loop_control:
        loop_var: A

gives (abridged)

  msg: 'A: 1234567 -> B: " -p 1234567"'
  msg: 'A: 12345678 -> B: " -p 12345678"'
  msg: 'A: 123456789 -> B: ""'
  msg: 'A: xyz12345 -> B: ""'

Q: "This should be written in an Ansible file."

A: You can put it into a file if you want to, e.g.

shell> cat set_B.yml 
B: "{{ (A is regex('^\\d{1,8}$'))|ternary(' -p ' ~ A, '') }}"

Then you can use it in many ways, e.g. use include_vars

    - include_vars: set_B.yml

or put it into the group_vars, host_vars, ... See Variable precedence: Where should I put a variable?

Related