Using a variable inside a jinja loop

Hi there,

I have a play with a role that creates a load balancer template. I’ve successfully tested it in my dev environment, using

{% for host in groups[‘dev-web’] %}
server {{ host }} {{ host }}:80
{% endfor %}

the ‘dev-web’ group is defined in my inventory, as well as ‘stage-web’, ‘prod-web’, etc. What I’d like to do is change this template so that it can be used in any environment. I am already passing a parameter upon calling the play, --extra-vars “deploy_env=dev”. In the play itself I can use this variable to determine on which balancer the template gets applied, by using something like this:

  • hosts: [ ‘{{ deploy_env }}-bal’ ]
    serial: 1
    vars_files:
  • /var/lib/ansible/vars/{{ deploy_env }}.yml
    roles:
  • role: “haproxy-webbal”

However, if I try something similar in the template, e.g.

{% for host in groups[‘{{ deploy_env }}-web’] %}
server {{ host }} {{ host }}:80
{% endfor %}

I get this error:

fatal: [stage-webbal-06.aws.primal.com] => {‘msg’: “One or more undefined variables: ‘dict object’ has no attribute ‘{{ deploy_env }}-varnish’”, ‘failed’: True}

It seems that {{ deploy_env }} is not being expanded, and it’s being taken as a literal. Is this because it’s within the {% %} section? If so, then what is the correct syntax for doing this? Alternatively, is there a cleaner way to approach this?

When inside the {% %} part you are inside of jinja and don't need
special syntax to tell it that your using jinja variables. Something
like this should work:

{% for host in groups[deploy_env + '-web'] %}
    server {{ host }} {{ host }}:80
{% endfor %}

Access your var inside the “{% %}” block without a “{{ }}” surrounding and use string concatenation like this:

d’oh! I should have known that. Thanks a bunch!

"

  • hosts: [ ‘{{ deploy_env }}-bal’ ]

"

This is gross and I would recommend not doing this.

Instead consider seperating your different environments into different inventory files (-i production), and having the host group just named “bal” in this case. You can still put nodes in different groups and keep your group_vars/ and host_vars/ directories all together.

I like that idea.

Right now we’re in a transition phase because I’ve inherited a horrible Puppet configuration that does unspeakably stupid/evil things. I actually have a rudimentary inventory script that polls puppetdb - eventually I’ll put that monstrosity to rest, but for now it’s convenient. Right now I still need to pass in the deploy_env variable because some configurations require it and I haven’t gotten around to having the inventory script define them, but once that’s in place I’ll definitively go with your suggestion and make environment-specific inventories.