Search code examples
amazon-web-servicesansibletagsamazon-iam

How to tag AWS resources using the variables defined in vars_file on ansible?


I am trying to create an IAM role with tag by Ansible using the following task.

- hosts: localhost
  gather_facts: no
  vars_files:
    - variables.yml
  tasks:
    - name: Create IAM role for EKS cluster
      community.aws.iam_role:
        name: eks-role
        state: present
        tags:
          "{{ global_tags.created_by.name }}": "{{ global_tags.created_by.value }}"
        wait: true
        assume_role_policy_document: "{{ lookup('file','iam-resources/eks-role_assume_role_policy_document.json') }}"
        managed_policies:
          - AmazonEKSClusterPolicy
      register: eks_role_created

However, I got an error when

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: botocore.exceptions.ClientError: An error occurred (ValidationError) when calling the CreateRole operation: 1 validation error detected: Value '{{ global_tags.created_by.name }}' at 'tags.1.member.key' failed to satisfy constraint: Member must satisfy regular expression pattern: [\p{L}\p{Z}\p{N}_.:/=+\-@]+

This is how I defined the variable in variables.yml

global_tags:
  created_by:
    name: owner
    value: ansible

I tried to print "{{ global_tags.created_by.name }}" and "{{ global_tags.created_by.value }}" by debug msg which works fine. Can anyone tell the reason?


Solution

  • From your error message and an empirical guess, it seems that the content of the tags attribute for iam_role is passed directly to the module and that keys in you dict are not going through the jinja2 template system.

    There are several workarounds to this problem but I'll focus on the ones which look the best to me in this situation.

    To start with, you could simply modify your global_tags variable as follow:

    global_tags:
      created_by:
        owner: ansible
    

    And then in your task:

        - name: Create IAM role for EKS cluster
          community.aws.iam_role:
            # cut for legibility
            tags: "{{ global_tags.created_by }}"
            # cut
    

    If you do not want to change your source var, an other solution in that case would be to construct the entire dict inside a single jinja2 template var:

        - name: Create IAM role for EKS cluster
          community.aws.iam_role:
            # cut for legibility
            tags: "{{ {global_tags.created_by.name: global_tags.created_by.value} }}"
            # cut