Formatting the dict items with debug

Hi,

I have the below output from my playbook using

  • debug:
    msg: “{{ result.stdout }}”

TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
“msg”: {
“access_token”: “xxxxxxxxxx”,
“expires_in”: 43200,
“token_type”: “xxxxxx”
}
}

and when I tried to filter the access token alone , with map by
“{{ result.stdout | map(‘extract’, access_token) }}” ., it errors as below

The task includes an option with an undefined variable. The error was: ‘access_token’ is undefined\n\n

and when I tried to filter the access token alone , with map by
msg: “{{ result.stdout | map(attribute=‘access_token’) }}” ., it errors as below

What I am missing here to get the desired output here?

What is your desired output then??

I need only the output or the value of the below(trying to set_fact the access_token)
access_token": “xxxxxxxxxx”

Try piping it through from_json first

Is there any reason you can’t just use result.stdout.access_token?

$ cat debug-token.yml

  • name: debug vars
    hosts: localhost
    gather_facts: no

vars:
result:
stdout:
access_token: xxxxxxxxxx
expires_in: 4320
token_type: yyyyyyyyyy

tasks:

  • name: debug the result
    ansible.builtin.debug:
    var: result

  • name: extract the token
    ansible.builtin.debug:
    msg: “{{ result.stdout.access_token }}”

$ ansible-playbook debug-token.yml

PLAY [debug vars] **********************************************************************************************************

TASK [debug the result] ****************************************************************************************************
ok: [localhost] => {
“result”: {
“stdout”: {
“access_token”: “xxxxxxxxxx”,
“expires_in”: 4320,
“token_type”: “yyyyyyyyyy”
}
}
}

TASK [extract the token] ***************************************************************************************************
ok: [localhost] => {
“msg”: “xxxxxxxxxx”
}

when I try with

  • debug:
    msg: “{{ result }}”

the output is

TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
“msg”: {
“changed”: true,
“cmd”: “curl -X POST ‘https://xxxxxx.com/auth/login’ -H ‘Content-Type: application/json’ -d @.mycred.json”,
– trimmed lines ----
“rc”: 0,
– trimmed lines ----
“stdout”: “{"access_token":"XXXXX","token_type":"Bearer","expires_in":86400}”,
“stdout_lines”: [
“{"access_token":"XXXXX","token_type":"Bearer","expires_in":86400}”
]
}
}

The output for the

  • debug:
    msg: “{{ result.stdout |from_json }}”

is

TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
“msg”: {
“access_token”: “XXXXXX”,
“expires_in”: 86400,
“token_type”: “Bearer”
}
}

when I use the

  • debug:
    msg: “{{ result.stdout.access_token }}”

the error is

TASK [debug] **************************************************************************************************************************
fatal: [localhost]: FAILED! => {“msg”: “The task includes an option with an undefined variable. The error was: ‘ansible.utils.unsafe_proxy.AnsibleUnsafeText object’ has no attribute ‘access_token’\n\nThe error appears to be in ‘/home/user/check.yml’: line 32, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n”}

Yes, so you should combine them like:

  • debug:
    msg: “{{ (result.stdout|from_json).access_token }}”

It worked and its my miss again to combine it … :slight_smile:

- debug:
        msg: "{{ result.stdout }}"

ok: [localhost] => {
    "msg": {
        "access_token": "xxxxxxxxxx",
        "expires_in": 43200,
        "token_type": "xxxxxx"
    }
}

For example, given the file

cat /tmp/test.json

{
"access_token": "xxxxxxxxxx",
"expires_in": 43200,
"token_type": "xxxxxx"
}

The value of *result.stdout* is *AnsibleUnsafeText*. What you see
depends on the callback. The below play

cat pb.yml

- hosts: all
  tasks:
    - command: cat /tmp/test.json
      register: result
    - debug:
        var: result.stdout

gives JSON with the default callback

ANSIBLE_STDOUT_CALLBACK=default ansible-playbook pb.yml

  ...
ok: [localhost] => {
    "result.stdout": {
        "access_token": "xxxxxxxxxx",
        "expires_in": 43200,
        "token_type": "xxxxxx"
    }
}

The same task gives YAML with the yaml callback

ANSIBLE_STDOUT_CALLBACK=yaml ansible-playbook pb2.yml

  ...
ok: [localhost] =>
  result.stdout:
    access_token: xxxxxxxxxx
    expires_in: 43200
    token_type: xxxxxx

You can test the type of the attribute *stdout*

    - debug:
        var: result.stdout|type_debug

gives

  result.stdout|type_debug: AnsibleUnsafeText

filter the access token alone

Convert the text to dictionary and get the *access_token* as well.
It's up to you where you put the vars

  vars:

    test_data: "{{ result.stdout|from_json }}"
    access_token: "{{ test_data.access_token }}"

Example of a complete playbook for testing

cat pb.yml

- hosts: all

  vars:

    test_data: "{{ result.stdout|from_json }}"
    access_token: "{{ test_data.access_token }}"

  tasks:

    - command: cat /tmp/test.json
      register: result
    - debug:
        var: result.stdout
    - debug:
        var: result.stdout|type_debug
    - debug:
        var: test_data|type_debug
    - debug:
        var: test_data
    - debug:
        var: access_token

Thanks Vladimir … rich info for me …