ansible

get the value from a dict using filter


I have a dictionary, not a dict list, let's say I read a dict from JSON file something.json has content {"a": "b"}

I would like to extract the value using a filter, so I could process that with more filters

# Expecting 'lookup('file', 'something.json') | from_json | ???' gives the value 'b'
- debug:
    msg: "{{ lookup('file', 'something.json') | from_json | ??? | urlencode() }}"

I searched that all other examples are for dict list, but I only have a dict here


Solution

  • Given the file below

    shell> cat something.json 
    {"a": "b"}
    

    Q: "Get the value from a dict using a filter."

    A: I read your question: "Get the value from a hash without knowing the key." There are many options:

    1. Include the variable from the file to a dictionary, e.g. d1, and display the first value
    - hosts: localhost
      tasks:
        - include_vars:
            file: something.json
            name: d1
        - debug:
            msg: "{{ d1.values() | first }}"
    

    gives

    shell> ansible-playbook pb.yml
    
    PLAY [localhost] *****************************************************************************
    
    TASK [include_vars] **************************************************************************
    ok: [localhost]
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      msg: b
    
    PLAY RECAP ***********************************************************************************
    localhost: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    1. You can put the declarations into the vars
    - hosts: localhost
      vars:
        d1: "{{ lookup('file', 'something.json') }}"
        v1: "{{ d1.values() | first }}"
      tasks:
        - debug:
            var: v1
        - debug:
            var: d1 | type_debug
        - debug:
            var: d1
    

    gives

    PLAY [localhost] *****************************************************************************
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      v1: b
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      d1|type_debug: dict
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      d1:
        a: b
    
    PLAY RECAP ***********************************************************************************
    localhost: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    1. Use json_query
    - hosts: localhost
      vars:
        d1: "{{ lookup('file', 'something.json') }}"
        v1: "{{ d1 | json_query('values(@)') | first }}"
      tasks:
        - debug:
            var: v1
    

    gives

    PLAY [localhost] *****************************************************************************
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      v1: b
    
    PLAY RECAP ***********************************************************************************
    localhost: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    All the above options assume the file is available at the controller. If the file is at the remote host:

    1. Use slurp
    - hosts: localhost
      vars:
        d1: "{{ out.content|b64decode }}"
        v1: "{{ d1.values() | first }}"
      tasks:
        - slurp:
            src: "{{ playbook_dir }}/something.json"
          register: out
        - debug:
            var: v1
    

    gives

    PLAY [localhost] *****************************************************************************
    
    TASK [slurp] *********************************************************************************
    ok: [localhost]
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      v1: b
    
    PLAY RECAP ***********************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    1. You can also register the output of cat
    - hosts: localhost
      vars:
        d1: "{{ out.stdout }}"
        v1: "{{ d1.values() | first }}"
      tasks:
        - command:
            cmd: "cat something.json"
            chdir: "{{ playbook_dir }}"
          register: out
        - debug:
            var: v1
    

    gives

    PLAY [localhost] *****************************************************************************
    
    TASK [command] *******************************************************************************
    changed: [localhost]
    
    TASK [debug] *********************************************************************************
    ok: [localhost] => 
      v1: b
    
    PLAY RECAP ***********************************************************************************
    localhost: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0