jsonansible

ansible , how to replace and filter json data?


I am trying to write ansible code first time to handle json.

I have a file in my /home/ which has following json data.

here is the input json

  "acl": [
    {
      "browse": true,
      "create": false
    },
    {
      "browse": false,
      "create": true
    }
  ],
  "groups": [
    {
      "name": "abc",
      "location": "texas"
    },
    {
      "name": "def",
      "location": "austin"
    }
  ],
  "users": [
    {
      "name": "admin",
      "description": "administrator",
      "password": "windows2011"
    },
    {
      "name": "testuser",
      "description": "guest",
      "password": "testpassword"
    }
  ]
}

I want to update password of the user in user's object where name is admin

so i that output file has updated password for user admin. the output file should be located in /home/location with _updated.json extension.

the output json should like this

{
  "acl": [
    {
      "browse": true,
      "create": false
    },
    {
      "browse": false,
      "create": true
    }
  ],
  "groups": [
    {
      "name": "abc",
      "location": "texas"
    },
    {
      "name": "def",
      "location": "austin"
    }
  ],
  "users": [
    {
      "name": "admin",
      "description": "administrator",
      "password": "updatedpassword"
    },
    {
      "name": "testuser",
      "description": "guest",
      "password": "testpassword"
    }
  ]
}

ansible code which i have written so far-

---
- name: Update admin user password in JSON file
  hosts: localhost
  gather_facts: no
  tasks:
    - name: Read the JSON file
      ansible.builtin.command:
        cmd: cat /home/conf.json
      register: json_content

Thank you.


Solution

  •   input_file: data.json
    

    and read it into a dictionary

        - include_vars:
            file: "{{ input_file }}"
            name: data
    

    gives

      data:
        acl:
        - browse: true
          create: false
        - browse: false
          create: true
        groups:
        - location: texas
          name: abc
        - location: austin
          name: def
        users:
        - description: administrator
          name: admin
          password: windows2011
        - description: guest
          name: testuser
          password: testpassword
    
      users:
        - name: admin
          password: updatedpassword
    

    and merge them

      update: "{{ [data.users, users] | community.general.lists_mergeby('name')
                                      | community.general.dict_kv('users') }}"
    

    gives

      update:
        users:
        - description: administrator
          name: admin
          password: updatedpassword
        - description: guest
          name: testuser
          password: testpassword
    
      data_update: "{{ [data, update] | combine }}"
    

    gives

      data_update:
        acl:
        - browse: true
          create: false
        - browse: false
          create: true
        groups:
        - location: texas
          name: abc
        - location: austin
          name: def
        users:
        - description: administrator
          name: admin
          password: updatedpassword
        - description: guest
          name: testuser
          password: testpassword
    
        - copy:
            dest: "{{ output_file }}"
            content: |
              {{ data_update | to_nice_json }}
          vars:
            arr: "{{ input_file | splitext | list }}"
            output_file: "{{ arr.0 }}_updated{{ arr.1 }}"
    

    gives what you want

    shell> diff data.json data_updated.json 
    26c26
    <             "password": "windows2011"
    ---
    >             "password": "updatedpassword"
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        input_file: data.json
    
        users:
          - name: admin
            password: updatedpassword
    
        update: "{{ [data.users, users] | community.general.lists_mergeby('name')
                                        | community.general.dict_kv('users') }}"
        data_update: "{{ [data, update] | combine }}"
    
      tasks:
    
        - include_vars:
            file: "{{ input_file }}"
            name: data
    
        - debug:
            var: data
        - debug:
            var: update
        - debug:
            var: data_update
    
        - copy:
            dest: "{{ output_file }}"
            content: |
              {{ data_update | to_nice_json }}
          vars:
            arr: "{{ input_file | splitext | list }}"
            output_file: "{{ arr.0 }}_updated{{ arr.1 }}"