Search code examples
ansibleconditional-statements

In Ansible playbooks how can i set a variable depending on inventory_hostname filtering matching a list of predefined values?


I'm trying to assign a variable in my playbook for later use based on hostname:

(without revealing actual hostnames)

  • ...p........001
  • ...s........001
  • ...t........001
  • etc...

and a list to assign depending on the 4th letter from the hostname

  • Production
  • Staging
  • Test
  • etc...

based on the 4th letter in the hostname, I want to set myvar per hostname which I run this playbook against:

  • if p, myvar = Production
  • if s, myvar = Staging
  • if t, myvar = Test

I have tried, and decided that the 4th letter can be captured from the hostname as so:

inventory_hostname[3]

This method seems to work:

  - name: Some task
    set_fact:
      **myvar**: Production
    when: inventory_hostname[3] == "p"

  - name: Some task 2
    set_fact:
      **myvar**: Staging
    when: inventory_hostname[3] == "s"

  - name: Some task 3
    set_fact:
      **myvar**: Test
    when: inventory_hostname[3] == "t"

  - name: Content of myvar?
    debug:
      msg: "{{ myvar }}"
    when: myvar is defined

The output is as follows, which appears to work:

TASK [Prod environment?] ********************************************************************************************
ok: [...p........001]
    
TASK [Stage environment?] ********************************************************************************************
skipping: [...p........001]
    
TASK [Test environment?] ********************************************************************************************
skipping: [...p........001]
    
TASK [Content of myvar?] ********************************************************************************************
ok: [...p........001] => {
        "msg": "Production"
    }

I assume the solution might be a single task which literally translates to something like:

- name: Some task
  set_fact:
    **myvar**: if inventory_hostname[3] == p or s or t and this exists in {{ varfile }} set Production or Staging or Test

I want to either:

  1. Reduce the number of tasks required to work this variable out by either doing a "loop and replace" based on the 4th character match, but I cant figure out the best way to do this within a playbook.
  2. Accept a better solution to this problem.

Solution

  • Create a dictionary myvar_dict, declare myvar and put it into the group_vars

    shell> cat group_vars/all/myvar.yml
    myvar_dict:
      p: Production
      s: Staging
      t: Test
      default: Sales
    myvar: "{{ myvar_dict[inventory_hostname.3]|default(myvar_dict.default) }}"
    

    Given the inventory

    shell> cat hosts
    001production
    001staging
    001test
    007business
    

    The playbook

    - hosts: all
      tasks:
        - debug:
            var: myvar
    

    gives

    TASK [debug] ************************************************************************************
    ok: [001production] => 
      myvar: Production
    ok: [001staging] => 
      myvar: Staging
    ok: [001test] => 
      myvar: Test
    ok: [007business] => 
      myvar: Sales
    

    Create the dictionary from the list

    Given the list

      myvar_list: [Production, Staging, Test]
    

    declare the default and create a dictionary

      myvar_default: {default: Sales}
      myvar_dict: "{{ dict(myvar_list|map('first')|map('lower')|
                           zip(myvar_list))|
                      combine(myvar_default) }}"
    

    gives

      myvar_dict:
        default: Sales
        p: Production
        s: Staging
        t: Test
    

    Example of a complete playbook for testing

    - hosts: all
    
      vars:
    
        myvar_list: [Production, Staging, Test]
    
        myvar_default: {default: Sales}
        myvar_dict: "{{ dict(myvar_list|map('first')|map('lower')|
                             zip(myvar_list))|
                        combine(myvar_default) }}"
    
        myvar: "{{ myvar_dict[inventory_hostname.3]|default(myvar_dict.default) }}"
    
      tasks:
    
        - debug:
            var: myvar_dict
          run_once: true
    
        - debug:
            var: myvar