Search code examples
jsonamazon-web-servicesansibletags

formatting json tags in ansible between aws commands


I need to replace my EBS volumes but need to keep the tags. I have to use aws cli.- I basically have problem to feed the tag information from one aws command output to the other aws command input due to differences of expected format.

I first loop through the volumes with describe-volumes command and collect the tags for each volumes. Something like this

- name: Tags of my EBS volumes
  become: yes
  shell: |
    aws ec2 describe-volumes --volume-ids {{ item.stdout }} --query "Volumes[*].Tags" --output json 
  with_items: "{{ ebsvolumeids.results }}"
  register: ebsvolumetags

This will give a similar formatted output:

    "stdout": "[\n    [\n        {\n            \"Key\": \"cost-center\",\n            \"Value\": \"22222223222\"\n        },\n        {\n            \"Key\": \"LastBackup\",\n            \"Value\": \"2022.01.01\"\n        }\n    ]\n]",

When I want to create a new replacement volume from a snapshot and want to apply the tags the command would like this:

  shell:
    aws ec2 create-volume --snapshot-id <snap-xxxxxxxx> \
    --volume-type gp2 --tag-specifications \
    'ResourceType=volume,Tags={{ item.stdout }}'
  with_items: "{{ ebsvolumetags.results }}"

where I would loop through the output of the previous command. However create-volume command expects a format for Tags like this:

[{Key=LastBackup,Value=2022.01.01},{Key=cost-center,Value=22222223222}]

So for example the correct syntax would be:

aws ec2 create-volume --snapshot-id <snap-xxxxxxxx> --volume-type gp2 --tag-specifications \
'ResourceType=volume,Tags=[{Key=LastBackup,Value=2022.01.01},{Key=cost-center,Value=22222223222}]'

No double quotes. No colons just equal signs. One less deep structure because output had too many [] brackets.

I tried to shape the output of the first command with different ways, for the second to accept but no luck:

  • chain of replace filters
  • using of from_json on the stdout but still didn't like it
  • have the output as text and replacing \n and \t

Anybody has an idea how to achieve this? Thanks


Solution

  • Ansible shell module should only be used as a last resort. That being said, It appears this is a data formatting issue as "Tags" cannot be passed as json to the command "aws ec2 create-volume".

    A workaround would be to convert the tags from json to the correct format (which follows the pattern: [{Key=key1,Value=value1},{Key=key2,Value=value2},{Key=key3,Value=value3},...]) and pass it as a string literal to the aws command. Please refer to the playbook below:

    ---
        - hosts: localhost
          gather_facts: no
          vars:
            tags: ''
          tasks:
          - name: Tags of my EBS volumes
            become: yes
            shell: |
               aws ec2 describe-volumes --volume-ids {{ item.stdout }} --query "Volumes[*].Tags" \
               --output json
            register: ebsvolumetags
    
          - name: Create tags variable
            set_fact:
              tags: "{{ tags + '{Key=' + item.Key + ',' + 'Value=' + item.Value + '},' }}"
            loop: "{{ ebsvolumetags.stdout | from_json | first }}"
    
          - name: Create EBS volume with the same tags
            become: yes
            shell: |
                 aws ec2 create-volume --snapshot-id <snap-xxxxxxx> --volume-type gp2 \
                 --tag-specifications 'ResourceType=volume,Tags=[{{ tags[:-1] }}]' \
                 --availability-zone <us-east-xx>