Search code examples
amazon-ec2ansibleansible-2.xansible-inventory

Is there any way to use environmental variables inside Ansible's AWS dynamic inventory file (aws_ec2)


I'd like to use an environmental variable inside aws_ec2 inventory file for the simple case of being able to easily separate different environments. Let's take this configuration as an example:

plugin: aws_ec2

filters:
  #tag:Cust_code: "01"
  tag:Cust_code: "{{ lookup('env','CUSTOMER_CODE') }}"

While the first line works (commented out), the second obviously doesn't and an empty host list is returned:

$ export CUSTOMER_CODE="01"
$ echo $CUSTOMER_CODE
01
$ ansible-inventory -i inventory/aws_ec2.yaml --graph
@all:
  |--@aws_ec2:
  |--@ungrouped:

I've read that the reason is because jinja2 templates are not supported in inventory files, even though they seem to work for some specific parameters according to this post - https://stackoverflow.com/a/72241930/19407408 .

I don't want to use dynamic inventory script because I feel it might be too complicated and I don't understand the official documentation for it. I also would prefer not to use different inventory files for different environments as I already have to use 2 different inventory files for the same environment (because for some hosts I need to use "ansible_host: private_ip_address" via compose and for jumphosts I can't). Although the latter will have to be the solution if there's no better alternative.

Has anyone been able to come up with a clever solution to this problem?


Solution

  • No, filters: (and its exclude_filters: and include_filters: siblings) are not jinja2 aware. The good thing about ansible being open source is that one can see under the hood how things work:

    • _query applies the include and exclude filters
      • ansible_dict_to_boto3_filter_list merely pivots the tag:Name=whatever over to [{"Name":"tag:Name","Values":["whatever"]}] format that boto wants, without further touching the key nor the values
      • _get_instances_by_region just calls describe-instances with those filters, again, without involving jinja2

    Depending on how many instances the unfiltered list contains, using groups: or keyed_groups: may be an option along with a parameterized - hosts: in your playbook (e.g. - hosts: cust_code{{ CUSTOMER_CODE }})

    Otherwise, I'd guess your best bet would be to use add_host: in a separate play in the playbook, since that allows you to have almost unlimited customization:

    - hosts: localhost
      tasks:
      - add_host: ...
        groups:
        - cust_code_machines
    
    - hosts: cust_code_machines
      tasks:
      - debug: msg="off to the races"