Search code examples
ansibletaskdata-extractionansible-tower

Extract value from output and send to next task


I am trying to define a template in Ansible Tower, where I want to extract the id for the Active Controller in Kafka Broker and then use this value in another template / task that will perform the rolling restart but will make sure the active controller is started last

When I run this Ansible task

- name: Find active controller
  shell: '/bin/zookeeper-shell 192.168.129.227 get /controller'
  register: resultAC

I get the below result. I want to extract the brokerid and assign the value of 2 to a variable that can be used in a different task in the same template or pass it to another template when the templates are part of a workflow definition.

I tried using resultAC.stdout_lines[5].brokerid but that does not work.

The structure of resultAC:

{
    "resultAC": {
        "stderr_lines": [],
        "changed": true,
        "end": "2020-08-19 07:36:01.950347",
        "stdout": "Connecting to 192.168.129.227\n\nWATCHER::\n\nWatchedEvent state:SyncConnected type:None path:null\n{\"version\":1,\"brokerid\":2,\"timestamp\":\"1597241391146\"}",
        "cmd": "/bin/zookeeper-shell 192.168.129.227 get /controller",
        "failed": false,
        "delta": "0:00:02.843972",
        "stderr": "",
        "rc": 0,
        "stdout_lines": [
            "Connecting to 192.168.129.227",
            "",
            "WATCHER::",
            "",
            "WatchedEvent state:SyncConnected type:None path:null",
            "{\"version\":1,\"brokerid\":2,\"timestamp\":\"1597241391146\"}"
        ],
        "start": "2020-08-19 07:35:59.106375"
    },
    "_ansible_verbose_always": true,
    "_ansible_no_log": false,
    "changed": false
}

Solution

  • Because your JSON is just part of a list of strings, it is not parsed or considered as a JSON.
    You will have to use the Ansible filter from_json in order to parse it back to a dictionary.

    Given the playbook:

    - hosts: all
      gather_facts: no
      vars: 
        resultAC:
          stdout_lines: 
            - "Connecting to 192.168.129.227"
            - ""
            - "WATCHER::"
            - ""
            - "WatchedEvent state:SyncConnected type:None path:null"
            - "{\"version\":1,\"brokerid\":2,\"timestamp\":\"1597241391146\"}"
          
      tasks:
        - debug: 
            msg: "{{ (resultAC.stdout_lines[5] | from_json).brokerid }}"
    

    This gives the recap:

    PLAY [all] *************************************************************************************************************************************************************
    
    TASK [debug] ***********************************************************************************************************************************************************
    ok: [localhost] => {
        "msg": "2"
    }
    
    PLAY RECAP *************************************************************************************************************************************************************
    localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
    

    Going further, maybe I would select and match the JSON in the stdout_lines list, just in case it is not always at the sixth line:

    - hosts: all
      gather_facts: no
      vars: 
        resultAC:
          stdout_lines: 
            - "Connecting to 192.168.129.227"
            - ""
            - "WATCHER::"
            - ""
            - "WatchedEvent state:SyncConnected type:None path:null"
            - "{\"version\":1,\"brokerid\":2,\"timestamp\":\"1597241391146\"}"
          
      tasks:
        - debug: 
            msg: "{{ (resultAC.stdout_lines | select('match','{.*\"brokerid\":.*}') | first | from_json).brokerid }}"