Ansible register result of multiple commands

后端 未结 4 1682
醉话见心
醉话见心 2021-02-01 19:33

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

            


        
相关标签:
4条回答
  • 2021-02-01 19:49

    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
    
    0 讨论(0)
  • 2021-02-01 19:50

    If what you need is to register the output of two commands separately, use different variable names.

    ---
    - hosts: Linux
      serial: 1
      tasks:
      - name: Check first
        command: /sbin/ip route list xxx.xxx.xxx.xxx/24
        register: result0
        changed_when: false
    
      - debug: msg="{{result0.stdout}}"
    
      - name: Check second
        command: /sbin/ip route list xxx.xxx.xxx.xxx/24
        register: result1
        changed_when: false
    
      - debug: msg="{{result1.stdout}}"
    
    0 讨论(0)
  • 2021-02-01 19:54

    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   
    
    0 讨论(0)
  • 2021-02-01 20:01

    Posting because I can't comment yet

    Relating to gameweld's answer, since Ansible 2.5 there's another way to accessing the iteration index.

    From the docs:

    Tracking progress through a loop with index_var

    New in version 2.5.

    To keep track of where you are in a loop, use the index_var directive with loop_control. This directive specifies a variable name to contain the current loop index:

    - name: count our fruit
      debug:
        msg: "{{ item }} with index {{ my_idx }}"
      loop:
        - apple
        - banana
        - pear
      loop_control:
        index_var: my_idx
    

    This also allows you to gather results from an array and act later to the same array, taking into account the previous results

    - name: Ensure directories exist
      file:
        path: "{{ item }}"
        state: directory
      loop:
        - "mouse"
        - "lizard"
      register: reg
    
    - name: Do something only if directory is new
      debug:
        msg: "New dir created with name '{{ item }}'"
      loop:
       - "mouse"
       - "lizard"
      loop_control:
        index_var: index
      when: reg.results[index].changed
    

    Please note that the "mouse lizard" array should be exactly the same

    0 讨论(0)
提交回复
热议问题