【问题标题】:How to use register in this context? (Ansible)在这种情况下如何使用寄存器? (安斯布尔)
【发布时间】:2020-07-28 06:59:02
【问题描述】:

感谢您抽出宝贵时间阅读本文(可能是愚蠢的问题)...

我有以下剧本:

- hosts: all 
  gather_facts: true
  vars:
    ansible_python_interpreter: /usr/bin/python  

  tasks:
    
    - name: Get shard status.  
      shell:
        cmd:  |
             mongo node1:27020 --eval "sh.status()" | grep shards -A 4 | awk -F ':|,|/' '{ print $2 " ", " ", $5,$7,$9}' | sed -e '1 i Shard Nodes' | column -t
      when: ansible_fqdn == 'node1'
      register: shards_status

    - name: Get replica status from SHARD1.
      shell:
        cmd:  |
             mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
      when: ansible_fqdn == 'node1'
      register: shard1   
 
    - name: Get replica status from SHARD2.
      shell:                               
        cmd:  |
             mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
      when: ansible_fqdn == 'node2'
      register: shard2 

    - name: Get replica status from SHARD3.
      shell:                               
        cmd:  |
             mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
      when: ansible_fqdn == 'node3'
      register: shard3 

    - name: Get replica status from SHARD4.
      shell:                               
        cmd:  |
             mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
      when: ansible_fqdn == 'node4'
      register: shard4

    - name: Append logs.
      lineinfile:
        dest: /tmp/status.txt
        line: "{{ item }}"
        insertafter: EOF      
      with_items:                                                                                                                                                                                           
        - "{{ shards_status.stdout }}"                                                                                                                                                                      
        - "{{ shard1.stdout }}" 
        - "{{ shard2.stdout }}"
        - "{{ shard3.stdout }}"
        - "{{ shard4.stdout }}"
      delegate_to: localhost

我想在一个文件 (/tmp/status.txt) 中包含上述变量 (shard1,2,3,4) 的结果。问题是,如果我运行 playbook,我会收到以下消息:

TASK [Append logs.] ****************************************************************************************************************************************************************************************
fatal: [node1]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
fatal: [node2]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
fatal: [node3]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}
fatal: [node4]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'stdout'"}

知道如何实现这一目标吗?

我已尝试访问 dic,仅从一个节点和多种解决方法运行该任务.. 但没有运气

【问题讨论】:

    标签: ansible


    【解决方案1】:

    我相信这次失败是因为每次你都在用 when: ansible_fqdn == 'node1'保护你的任务。

    因此,当 ansible 在 node1 中执行此 playbook 时,它会执行所有 node1 任务,然后当它到达 Append logs. 任务时,它会尝试从 node2 转储标准输出。但是由于我们在node1 中运行,所以node2 字典是空的,因此'dict object' has no attribute 'stdout'

    一种解决方案是给它一个默认值,例如

      with_items:                                                                                                                                                                                           
        - "{{ shards_status.stdout | default("") }}"                                                                                                                                                                      
        - "{{ shard1.stdout | default("") }}" 
        - "{{ shard2.stdout | default("") }}"
        - "{{ shard3.stdout | default("") }}"
        - "{{ shard4.stdout | default("") }}"
    

    default value for dictionary in jinja2 (ansible)


    但正确的解决方案是改变你的剧本和思维方式。

    有了这样的库存

    [mongo]
    shard1 get_shard_status=true
    shard2
    shard3
    shard4
    

    你的剧本可能看起来像这样

    - hosts: mongo
      vars:
        get_shard_status: false
    
      tasks:
        - name: get shard status
          shell: mongo node1:27020 --eval "sh.status()" | grep shards -A 4 | awk -F ':|,|/' '{ print $2 " ", " ", $5,$7,$9}' | sed -e '1 i Shard Nodes' | column -t
          register: shard_status
          when: get_shard_status
    
        - name: get the replica status
          shell: mongo --eval 'printjson(rs.status())' | grep -E "stateStr|name" | awk -F ':' '{ print $2 }' | sed 's/"//g'| sed 's/,//g'| xargs -n2 | sed -e '1 i Server Status' | column -t
          register: replicas
    
        - name: dump status to localhost
          lineinfile:
            line: "{{ shard_status + '\n' | default('') }}{{ replicas.stdout }}"
            state: present
            become: false
            dest: "/tmp/foobar"
          delegate_to: localhost
    

    通过这种方式,如果您有另一个 mongo 节点,您将只修改您的库存而不是您的剧本,而且您也不必使用 | default("") 保护 replicas.stdout,因为您总是在节点中执行它。

    【讨论】:

    • 这很好用!两种解决方案都很优雅,给了我想要的结果!!非常感谢!
    • 记得遵守 SO 礼节,如果是,请将答案标记为已接受,stackoverflow.com/help/someone-answers
    • 完成!再次感谢!遗憾的是我仍然没有投票的特权,但我接受了你的回答:))
    猜你喜欢
    • 1970-01-01
    • 2013-06-09
    • 2011-04-16
    • 2022-01-23
    • 2015-11-30
    • 2017-05-16
    • 2012-10-06
    • 2011-05-18
    • 2019-11-29
    相关资源
    最近更新 更多