Alex
Alex

Reputation: 91

Ansible: Extract json objects from file based on a list

I have a json file like so

{
  "service_accounts": {
    "sql-automation": "Automation Service account for Cloud SQL Instances",
    "gke-proxy": "GKE proxy account",
    "gke-node": "Default GKE nodes service account",
    "syncdata": "Data sync between environments",
  }
}

Then I have another json file with the default access the accounts need (this is a template file)

{
    "key_gen_auths": {
        "worker": [{
            "role": "roles/iam.serviceAccountKeyAdmin",
            "members": [
                "serviceAccount:dataprovisioning@{{ project_id }}.iam.gserviceaccount.com"
            ]
        }],
        "gke-node": [{
            "role": "roles/iam.serviceAccountUser",
            "members": [
                "serviceAccount:deployment-automation@{{ project_id }}.iam.gserviceaccount.com"
            ]
        }],
        "sql-automation": [{
            "role": "roles/iam.serviceAccountUser",
            "members": [
                "serviceAccount:deployment-automation@{{ project_id }}.iam.gserviceaccount.com"
            ]
        }]
    }
}

Then in the playbook, i would like to say: If the service account exists in the service_accounts file, extract that object from key_gen_auths if it exists there (if it doesnt exist in key_gen_auths ignore). Ive looked at several options, like selectattr, combine, difference, but im no further than when i started really, and wonder if im just better with a when statement if i can find the right syntax, any help would be appreciated.

- name: Play for reading json
  hosts: localhost
  vars:
    project_id: 123
  tasks:
  - name: acct_list
    set_fact:
      acct_list: "{{ lookup('template', 'acct_list.json') }}"
  - name: key_auth_default
    set_fact:
      keyauth_default: "{{ lookup('template', 'key_auths.json') }}"

  - name:
    set_fact:
      access_file: "{{ item }}"
    with_items: "{{ keyauth_default.key_gen_auths }}"
    when: item in acct_list.service_accounts

  - debug:
      var: access_file


Upvotes: 3

Views: 212

Answers (2)

Jack
Jack

Reputation: 6198

Well, I think this shows the data you want, in debug, and you can use that with set_fact as you see fit:

- name: Play for reading json
  hosts: localhost
  vars_files:
  - acct_list.json
  - key_auths.json
  vars:
    project_id: 123
  tasks:

  - debug:
      msg: "{{ key_gen_auths[item] | default('Not Found') }}"
    loop: "{{ service_accounts.keys() }}"
    ignore_errors: yes

Upvotes: 1

Vladimir Botka
Vladimir Botka

Reputation: 68254

You can read the files without lookup

  vars_files:
    - acct_list.json
    - key_auths.json
  vars:
    project_id: 123

give

  service_accounts:
    gke-node: Default GKE nodes service account
    gke-proxy: GKE proxy account
    sql-automation: Automation Service account for Cloud SQL Instances
    syncdata: Data sync between environments

  key_gen_auths:
    gke-node:
    - members:
      - serviceAccount:[email protected]
      role: roles/iam.serviceAccountUser
    sql-automation:
    - members:
      - serviceAccount:[email protected]
      role: roles/iam.serviceAccountUser
    worker:
    - members:
      - serviceAccount:[email protected]
      role: roles/iam.serviceAccountKeyAdmin

Q: "If the service account exists in service_accounts extract that object from key_gen_auths."

A: Get the lists of the keys from the dictionaries. Then the intersect of these lists gives the existing service accounts

  service_accounts_list: "{{ service_accounts.keys()|list }}"
  key_gen_auths_list: "{{ key_gen_auths.keys()|list }}"
  service_account_exists: "{{ service_accounts_list|intersect(key_gen_auths_list) }}"

give

  service_accounts_list: [sql-automation, gke-proxy, gke-node, syncdata]
  key_gen_auths_list: [worker, gke-node, sql-automation]
  service_account_exists: [sql-automation, gke-node]

Use the list of existing accounts to extract the objects and create a dictionary

  access_file: "{{ dict(service_account_exists|
                        zip(service_account_exists|map('extract', key_gen_auths))) }}"

give

  access_file:
    gke-node:
    - members:
      - serviceAccount:[email protected]
      role: roles/iam.serviceAccountUser
    sql-automation:
    - members:
      - serviceAccount:[email protected]
      role: roles/iam.serviceAccountUser

Example of the complete playbook for testing

- hosts: localhost

  vars_files:
    - acct_list.json
    - key_auths.json

  vars:

    project_id: 123
    service_accounts_list: "{{ service_accounts.keys()|list }}"
    key_gen_auths_list: "{{ key_gen_auths.keys()|list }}"
    service_account_exists: "{{ service_accounts_list|intersect(key_gen_auths_list) }}"
    access_file: "{{ dict(service_account_exists|
                          zip(service_account_exists|map('extract', key_gen_auths))) }}"
  tasks:

    - debug:
        var: service_accounts
    - debug:
        var: key_gen_auths

#  If the service account exists in service_accounts
#  extract those objects from key_gen_auths

    - debug:
        var: service_accounts_list|to_yaml
    - debug:
        var: key_gen_auths_list|to_yaml
    - debug:
        var: service_account_exists|to_yaml
    - debug:
        var: access_file

Upvotes: 2

Related Questions