DEV Community

Cover image for Detangling Ansible, loop and json_query
baffledmystic
baffledmystic

Posted on

Detangling Ansible, loop and json_query

Ansible comes pretty handy when aiming to automate your infrastructure.
However, in my experience over 2+ years, combining Ansible with loops can easily reach brain-wracking complexity.

Following from my playbook demonstrates how json_query is essential to navigate a JSON jungle.
Of course, there can be other approaches but, json_query simplifies it best in my opinion.

The task at hand:

  1. register the output of a looped module to a variable.
  2. check the 'results' in the output for 'failed' or 'changed' booleans to decide actions in the next module.

Sounds simple right? Not quite ..

Trial #1:

  - name: PUT files in bucket
    amazon.aws.aws_s3:
      bucket: "{{ arch_bucket }}"
      object: "{{ item.path|basename }}"
      src: "{{ item.path }}"
      mode: put
      aws_ca_bundle: "/path/to/bundle.pem"
      aws_access_key: "{{ bucket_access_key }}"
      aws_secret_key: "{{ bucket_secret_key }}"
      s3_url: "{{ cloud_url }}"
      validate_certs: yes
    loop: "{{ files_to_archive }}"
    register: archive_files_op

  - name: Delete files successfully archived
    file:
      path: "{{ item.path }}"
      state: absent
    loop: "{{ archive_files_op | json_query(del_query) }}"
    vars:
        del_query: "results[?changed == 'True' && failed == 'False'].item"
Enter fullscreen mode Exit fullscreen mode

For some reason, the json_query doesn't like using standard comparison operators for the booleans and an error is reported:

fatal: [target.node.com]: FAILED! => {"msg": "template error while templating string: expected token ',', got 'True'. String: {{ archive_files_op | json_query('results[?changed=='True' && failed=='False'].item.path') }}"}
Enter fullscreen mode Exit fullscreen mode

After hours of trying, this is what worked to my satisfaction:

  - name: PUT files in bucket
    amazon.aws.aws_s3:
    ..<snip-snip>..
    loop: "{{ files_to_archive }}"
    register: archive_files_op

  - name: Delete files successfully archived
    file:
      path: "{{ item.path }}"
      state: absent
    loop: "{{ archive_files_op | json_query(del_query) }}"
    vars:
      del_query: "results[?!failed && changed].item"
Enter fullscreen mode Exit fullscreen mode

Happy automating!

Top comments (0)