JaneD
JaneD

Reputation: 199

ansible parsing json into include_tasks loop

I have the following json file called cust.json :

{
 "customer":{
        "CUST1":{
                "zone":"ZONE1",
                "site":"ASIA"
        },
       "CUST2":{
                "zone":"ZONE2",
                "site":"EUROPE"
        }
    }
}

I am using this json file in my main.yml to get a list of customers (CUST1 and CUST2).

main.yml:

- name: Include the vars
  include_vars:
    file: "{{ playbook_dir }}/../default_vars/cust.json"
    name: "cust_json"

- name: Generate customer config 
  include_tasks: create_config.yml
  loop: "{{ cust_json.customer }}"

I was hoping the loop will basically pass each customer's code (eg CUST1) to create_config.yml, so that something like the following can happen:

create_config.yml:

- name: Create customer config 
  block:
    - name: create temporary file for customer
      tempfile:
        path: "/tmp"
        state: file
        prefix: "my customerconfig_{{ item }}."
        suffix: ".tgz"
      register: tempfile

    - name: Setup other things
      include_tasks: "othercustconfigs.yml"


Which will result in :

  1. The following files being generated : /tmp/mycustomerconfig_CUST1 and /tmp/mycustomerconfig_CUST2
  2. The tasks within othercustconfigs.yml be run for CUST1 and CUST2.

Questions :

  1. Running the ansible, it fails at this point:
TASK [myrole : Generate customer config ] ************************************************************************************************************************************************************

fatal: [127.0.0.1]: FAILED! => {
    "msg": "Invalid data passed to 'loop', it requires a list, got this instead: {u'CUST1': {u'site': u'ASIA', u'zone': u'ZONE1'}, u'CUST2': {u'site': u'EUROPE', u'zone': uZONE2'}}. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."
}

How do I loop the JSON so that it would get the list of customers (CUST1 and CUST2) correctly? loop: "{{ cust_json.customer }}" clearly doesnt work.

  1. If I manage to get the above working, is it possible to pass the result of the loop to the next include_tasks: "othercustconfigs.yml ? SO basically, passing the looped items from main.yml , then to config.yml, and then to othercustconfigs.yml. Is this possible?

Thanks!! J

Upvotes: 0

Views: 254

Answers (1)

Zeitounator
Zeitounator

Reputation: 44615

cust_json.customer is a hashmap containing one key for each customer, not a list.

The dict2items filter can transform this hashmap into a list of elements each containing a key and value attribute, e.g:

- key: "CUST1"
  value:
    zone: "ZONE1"
    site: "ASIA"
- key: "CUST2"
  value:
    zone: "ZONE2"
    site: "EUROPE"

With this in mind, you can transform your include to the following:

- name: Generate customer config 
  include_tasks: create_config.yml
  loop: "{{ cust_json.customer | dict2items }}"

and the relevant task in your included file to:

    - name: create temporary file for customer
      tempfile:
        path: "/tmp"
        state: file
        prefix: "my customerconfig_{{ item.key }}."
        suffix: ".tgz"
      register: tempfile

Of course you can adapt all this to use the value element where needed, e.g. item.value.site

You can see the following documentations for in depth info and alternative solutions:

Upvotes: 1

Related Questions