Search code examples
ansiblejinja2ansible-template

Find substring in ansible_hostname


I need to check all the cities in the country variable list to see if they contain the city name in the Ansible hostname variable.

It means running hosts can contain a city name in its own hostname.

- name:  Find city
  gather_facts: true
  hosts: 10.72.45.12
  vars:
    counties:
      Canada: ["ontario", "toronto", "montreal"]
      Germany: ["berlin", "munich", "hamburg"]
      USA: ["chicago", "ostin", "seattle"]
  tasks:

         - name: Getting counties by city
           set_fact:
             country: >-
               {% for city in counties %}
               {% if '{{ city }}' in '{{ ansible_hostname }}' %}
               Canada
               {% elif '{{ city }}' in '{{ ansible_hostname }}' %}
               Germany
               {% elif '{{ city }}' in '{{ ansible_hostname }}' %}
               USA
               {% else %}
               Earth
               {% endif %}
               {% endfor %}

         - debug:
            var: country

Solution

  • Some errors in your code

    • Jinja delimiters do not nest. If you are inside a statement delimiter {% ... %}, you do not need an expression delimiter {{ ... }}:
      {% if city in ansible_hostname %}
      
    • You will need a nested loop, as the cities are in a list in your countries dictionary
    • The syntax to loop on a dictionary is a little bit different than the one to loop on a list:
      {% for key, value in my_dict.items() %}
      

    With all this, you can construct the two tasks:

    - set_fact:
        country: >-
          {% for country, cities in countries.items() -%}
            {% for city in cities if city in ansible_hostname -%}
              {{ country }}
            {%- endfor %}
          {%- endfor %}
      vars:
        countries:
          Canada: ["ontario", "toronto", "montreal"]
          Germany: ["berlin", "munich", "hamburg"]
          USA: ["chicago", "austin", "seattle"]
    
    - debug:
        var: country | default('Earth', true)
    

    Which could yield something like:

    ok: [foo_ontario_bar] => 
      country | default('Earth', true): Canada
    ok: [foo_berlin_bar] => 
      country | default('Earth', true): Germany
    ok: [foo_seattle_bar] => 
      country | default('Earth', true): USA
    ok: [foo_brussels_bar] => 
      country | default('Earth', true): Earth