Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible register result of multiple commands

Tags:

I was given a task to verify some routing entries for all Linux server and here is how I did it using an Ansible playbook

---   - hosts: Linux     serial: 1      tasks:       - name: Check first         command: /sbin/ip route list xxx.xxx.xxx.xxx/24         register: result         changed_when: false        - debug: msg="{{result.stdout}}"        - name: Check second         command: /sbin/ip route list xxx.xxx.xxx.xxx/24         register: result         changed_when: false        - debug: msg="{{result.stdout}}" 

You can see I have to repeat same task for each routing entry and I believe I should be able to avoid this. I tried use with_items loop but got following error message

One or more undefined variables: 'dict object' has no attribute 'stdout' 

is there a way to register variable for each command and loop over them one by one ?

like image 751
Ask and Learn Avatar asked Aug 07 '15 05:08

Ask and Learn


People also ask

How do I register multiple variables in Ansible?

No, this is not possible. Ansible (as of current version 2.4) does not allow to register partial output of the module (or several different parts of it). You can register only full result and extract parts of it in the tasks to follow.

How do I register Ansible output?

In Ansible, you can run any shell command on your Ansible hosts, the hosts you will be configuring with Ansible. These shell commands may have outputs. By default, the output is ignored. If you want to store the output in a variable and use it later, then you can use the Ansible register module.

How do I register variables in Ansible?

Ansible registers are used when you want to capture the output of a task to a variable. You can then use the value of these registers for different scenarios like a conditional statement, logging etc. The variables will contain the value returned by the task. The common return values are documented in Ansible docs.


2 Answers

Starting in Ansible 1.6.1, the results registered with multiple items are stored in result.results as an array. So you can use result.results[0].stdout and so on.

Testing playbook:

--- - hosts: localhost   gather_facts: no   tasks:     - command: "echo {{item}}"       register: result       with_items: [1, 2]     - debug:         var: result 

Result:

$ ansible-playbook -i localhost, test.yml  PLAY [localhost] **************************************************************   TASK: [command echo {{item}}] *************************************************  changed: [localhost] => (item=1) changed: [localhost] => (item=2)  TASK: [debug ] ****************************************************************  ok: [localhost] => {     "var": {         "result": {             "changed": true,              "msg": "All items completed",              "results": [                 {                     "changed": true,                      "cmd": [                         "echo",                          "1"                     ],                      "delta": "0:00:00.002502",                      "end": "2015-08-07 16:44:08.901313",                      "invocation": {                         "module_args": "echo 1",                          "module_name": "command"                     },                      "item": 1,                      "rc": 0,                      "start": "2015-08-07 16:44:08.898811",                      "stderr": "",                      "stdout": "1",                      "stdout_lines": [                         "1"                     ],                      "warnings": []                 },                  {                     "changed": true,                      "cmd": [                         "echo",                          "2"                     ],                      "delta": "0:00:00.002516",                      "end": "2015-08-07 16:44:09.038458",                      "invocation": {                         "module_args": "echo 2",                          "module_name": "command"                     },                      "item": 2,                      "rc": 0,                      "start": "2015-08-07 16:44:09.035942",                      "stderr": "",                      "stdout": "2",                      "stdout_lines": [                         "2"                     ],                      "warnings": []                 }             ]         }     } }  PLAY RECAP ********************************************************************  localhost                  : ok=2    changed=1    unreachable=0    failed=0    
like image 141
yaegashi Avatar answered Sep 29 '22 03:09

yaegashi


A slightly different situation, which took a while to figure out. If you want to use the results of multiple items, but for changed_when, then the register variable will not have a var.results! Instead, changed_when, is evaluated for each item, and you can just directly use the register var.

Simple example, which will result in changed: false:

- action: command echo {{item}}   register: out   changed_when: "'z' in out.stdout"   with_items:     - hello     - foo     - bye 

Another example:

- name: Create fulltext index for faster text searches.   mysql_db: name={{SO_database}} state=import target=/tmp/fulltext-{{item.tableName}}-{{item.columnName}}.sql   with_items:      - {tableName: Posts,  columnName: Title}     - {tableName: Posts,  columnName: Body}     - {tableName: Posts,  columnName: Tags}     - {tableName: Comments, columnName: Text}   register: createfulltextcmd   changed_when: createindexcmd.msg.find('already exists') == -1 

Finally, when you do want to loop through results in other contexts, it does seem a bit tricky to programmatically access the index as that is not exposed. I did find this one example that might be promising:

- name: add hosts to known_hosts shell: 'ssh-keyscan -H {{item.host}}>> /home/testuser/known_hosts' with_items:   - { index: 0, host: testhost1.test.dom }   - { index: 1, host: testhost2.test.dom }   - { index: 2, host: 192.168.202.100 } when: ssh_known_hosts.results[{{item.index}}].rc == 1 
like image 38
gameweld Avatar answered Sep 29 '22 03:09

gameweld