Ansible playbook可同时处理Linux和Windows主机

Ansible playbook可同时处理Linux和Windows主机,ansible,ansible-playbook,ansible-2.x,Ansible,Ansible Playbook,Ansible 2.x,尝试编写一个剧本,检查一组服务器(Linux和Windows主机)上是否存在一组文件,如果存在,则替换这些文件 以下是我到目前为止的情况: --- - hosts: "{{hosts}}" vars: scripts: - check_blackout.pl - check_empty.pl tasks: - name: windows stat with_items: "{{scripts}}" win_stat: pat

尝试编写一个剧本,检查一组服务器(Linux和Windows主机)上是否存在一组文件,如果存在,则替换这些文件

以下是我到目前为止的情况:

---
- hosts: "{{hosts}}"
  vars:
    scripts:
      - check_blackout.pl
      - check_empty.pl
  tasks:
    - name: windows stat
      with_items: "{{scripts}}"
      win_stat: path=D:\scripts\{{item}}
      register: windows_stat
      when: "'windows' in group_names"
    - name: other stat
      with_items: "{{scripts}}"
      stat: path=/usr/local/bin/{{item}}
      register: other_stat
      remote_user: "{{script_owner | default(ansible_user)}}"
      when: "'windows' not in group_names"
    - name: windows debug
      with_items: "{{windows_stat.results}}"
      debug: var={{item.item}}
      when: "{{item.stat.exists}}"
    - name: other debug
      with_items: "{{other_stat.results}}"
      debug: var={{item.item}}
      when: "{{item.stat.exists}}"
...
当我在Windows和Linux主机上运行此程序进行测试时,我得到以下结果:

[ansible@vmhklftpscdv1 ~]$ ansible-playbook test.yml -e "hosts=vmhkge1jasdev01,jdeesbkup" --ask-vault-pass
Vault password: 

PLAY [vmhkge1jasdev01,jdeesbkup] ************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************
ok: [vmhkge1jasdev01]
ok: [jdeesbkup]

TASK [windows stat] *************************************************************************************************************************************************************
skipping: [jdeesbkup] => (item=check_blackout.pl) 
skipping: [jdeesbkup] => (item=check_empty.pl) 
ok: [vmhkge1jasdev01] => (item=check_blackout.pl)
ok: [vmhkge1jasdev01] => (item=check_empty.pl)

TASK [other stat] ***************************************************************************************************************************************************************
skipping: [vmhkge1jasdev01] => (item=check_empty.pl) 
skipping: [vmhkge1jasdev01] => (item=check_blackout.pl) 
ok: [jdeesbkup] => (item=check_blackout.pl)
ok: [jdeesbkup] => (item=check_empty.pl)

TASK [windows debug] ************************************************************************************************************************************************************
skipping: [vmhkge1jasdev01] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'check_empty.pl', 'invocation': {'module_name': u'win_stat'}}) 
skipping: [vmhkge1jasdev01] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'check_blackout.pl', 'invocation': {'module_name': u'win_stat'}}) 
fatal: [jdeesbkup]: FAILED! => {"failed": true, "msg": "The conditional check '{{item.stat.exists}}' failed. The error was: error while evaluating conditional ({{item.stat.exists}}): 'dict object' has no attribute 'stat'\n\nThe error appears to have been in '/home/ansible/test.yml': line 19, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      when: \"'windows' not in group_names\"\n    - name: windows debug\n      ^ here\n"}

TASK [other debug] **************************************************************************************************************************************************************
fatal: [vmhkge1jasdev01]: FAILED! => {"failed": true, "msg": "The conditional check '{{item.stat.exists}}' failed. The error was: error while evaluating conditional ({{item.stat.exists}}): 'dict object' has no attribute 'stat'\n\nThe error appears to have been in '/home/ansible/test.yml': line 23, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      when: \"{{item.stat.exists}}\"\n    - name: other debug\n      ^ here\n"}
        to retry, use: --limit @/home/ansible/test.retry

PLAY RECAP **********************************************************************************************************************************************************************
jdeesbkup                  : ok=2    changed=0    unreachable=0    failed=1   
vmhkge1jasdev01            : ok=2    changed=0    unreachable=0    failed=1   

[ansible@vmhklftpscdv1 ~]$ 
有什么办法让它工作吗?
我尝试了各种组合,包括在检查结果之前检查组成员:

  when: "'windows' in group_names and {{item.stat.exists}}"
然而,即使条件的第一部分为false,Ansible似乎仍会检查
item.stat
字段


或者我的基本方法是错误的,我应该把这些任务分成不同的剧本吗?

是的,你是对的<带有_项的代码>在之前和时进行评估。您可以添加默认的空列表以避免错误:

- name: other debug
  with_items: "{{other_stat.results | default([]) }}"
  debug: var={{item}}
  when: "{{item.stat.exists | default(false)}}"

让它工作,这里是成功的剧本和输出:

---
- hosts: "{{hosts}}"
  vars:
    scripts:
      - run.pl
  tasks:
    - name: win_stat
      with_items: scripts
      win_stat: path="D:\scripts\{{item}}"
      register: "win_result"
      when: "'windows' in group_names"
    - name: other_stat
      with_items: scripts
      stat: path="/usr/local/bin/{{item}}"
      register: "other_result"
      when: "'windows' not in group_names"
    - debug: var=win_result
    - debug: var=other_result
    - with_items: "{{ win_result.results }}"
      debug: msg="{{item.item}}"
      when: "not (item.skipped | default(false))"
    - with_items: "{{ other_result.results}}"
      debug: msg="{{item.item}}"
      when: "not (item.skipped | default(false))"
...


[ansible@vmhklftpscdv1 ~]$ ansible-playbook debug.yml -e "hosts=jdeesbkup,vmhkge1jasdev01" --ask-vault-pass
Vault password: 

PLAY [jdeesbkup,vmhkge1jasdev01] **************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [jdeesbkup]
ok: [vmhkge1jasdev01]

TASK [win_stat] *******************************************************************************************************************************************
skipping: [jdeesbkup] => (item=scripts) 
ok: [vmhkge1jasdev01] => (item=scripts)

TASK [other_stat] *****************************************************************************************************************************************
skipping: [vmhkge1jasdev01] => (item=scripts) 
ok: [jdeesbkup] => (item=scripts)

TASK [debug] **********************************************************************************************************************************************
ok: [jdeesbkup] => {
    "win_result": {
        "changed": false, 
        "msg": "All items completed", 
        "results": [
            {
                "_ansible_item_result": true, 
                "_ansible_no_log": false, 
                "changed": false, 
                "item": "scripts", 
                "skip_reason": "Conditional check failed", 
                "skipped": true
            }
        ]
    }
}
ok: [vmhkge1jasdev01] => {
    "win_result": {
        "changed": false, 
        "msg": "All items completed", 
        "results": [
            {
                "_ansible_item_result": true, 
                "_ansible_no_log": false, 
                "_ansible_parsed": true, 
                "changed": false, 
                "invocation": {
                    "module_name": "win_stat"
                }, 
                "item": "scripts", 
                "stat": {
                    "exists": false
                }
            }
        ]
    }
}

TASK [debug] **********************************************************************************************************************************************
ok: [jdeesbkup] => {
    "other_result": {
        "changed": false, 
        "msg": "All items completed", 
        "results": [
            {
                "_ansible_item_result": true, 
                "_ansible_no_log": false, 
                "_ansible_parsed": true, 
                "changed": false, 
                "invocation": {
                    "module_args": {
                        "checksum_algorithm": "sha1", 
                        "follow": false, 
                        "get_attributes": true, 
                        "get_checksum": true, 
                        "get_md5": true, 
                        "get_mime": true, 
                        "path": "/usr/local/bin/scripts"
                    }, 
                    "module_name": "stat"
                }, 
                "item": "scripts", 
                "stat": {
                    "exists": false
                }
            }
        ]
    }
}
ok: [vmhkge1jasdev01] => {
    "other_result": {
        "changed": false, 
        "msg": "All items completed", 
        "results": [
            {
                "_ansible_item_result": true, 
                "_ansible_no_log": false, 
                "changed": false, 
                "item": "scripts", 
                "skip_reason": "Conditional check failed", 
                "skipped": true
            }
        ]
    }
}

TASK [debug] **********************************************************************************************************************************************
skipping: [jdeesbkup] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': u'scripts', 'changed': False}) 
ok: [vmhkge1jasdev01] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'scripts', 'invocation': {'module_name': u'win_stat'}}) => {
    "item": {
        "changed": false, 
        "invocation": {
            "module_name": "win_stat"
        }, 
        "item": "scripts", 
        "stat": {
            "exists": false
        }
    }, 
    "msg": "scripts"
}

TASK [debug] **********************************************************************************************************************************************
---
- hosts: "{{hosts}}"
  vars:
    scripts:
      - run.pl
  tasks:
    - name: win_stat
      with_items: scripts
      win_stat: path="D:\scripts\{{item}}"
      register: "win_result"
      when: "'windows' in group_names"
    - name: other_stat
      with_items: scripts
      stat: path="/usr/local/bin/{{item}}"
      register: "other_result"
      when: "'windows' not in group_names"
    - debug: var=win_result
    - debug: var=other_result
    - with_items: "{{ win_result.results }}"
      debug: msg="{{item.item}}"
      when: "not (item.skipped | default(false))"
    - with_items: "{{ other_result.results}}"
      debug: msg="{{item.item}}"
      when: "not (item.skipped | default(false))"
#      when: "'windows' in group_names and  {{item.stat.exists}}"
#    - name: win_test
#      with_items: {{win_result.results}}
#      debug: var="{{item}}"
#      when: "'windows' in group_names and  {{item.stat.exists}}"

    ~                                                                                                                                                          
    ~                                                                                                                                                          
    ~                                                                                                                                                          
    skipping: [vmhkge1jasdev01] => (item={'skipped': True, '_ansible_no_log': False, 'skip_reason': u'Conditional check failed', '_ansible_item_result': True, 'item': u'scripts', 'changed': False}) 
    ok: [jdeesbkup] => (item={'_ansible_parsed': True, u'stat': {u'exists': False}, '_ansible_item_result': True, '_ansible_no_log': False, u'changed': False, 'item': u'scripts', 'invocation': {'module_name': u'stat', u'module_args': {u'checksum_algorithm': u'sha1', u'get_checksum': True, u'follow': False, u'path': u'/usr/local/bin/scripts', u'get_md5': True, u'get_mime': True, u'get_attributes': True}}}) => {
        "item": {
            "changed": false, 
            "invocation": {
                "module_args": {
                    "checksum_algorithm": "sha1", 
                    "follow": false, 
                    "get_attributes": true, 
                    "get_checksum": true, 
                    "get_md5": true, 
                    "get_mime": true, 
                    "path": "/usr/local/bin/scripts"
                }, 
                "module_name": "stat"
            }, 
            "item": "scripts", 
            "stat": {
                "exists": false
            }
        }, 
        "msg": "scripts"
    }

    PLAY RECAP ************************************************************************************************************************************************
    jdeesbkup                  : ok=5    changed=0    unreachable=0    failed=0   
    vmhkge1jasdev01            : ok=5    changed=0    unreachable=0    failed=0   

那根本没什么区别。仍然获取“dict对象”没有属性“stat”错误消息。条件检查“{item.stat.exists | default(false)}}”失败dict对象没有属性“stat”。是的,很抱歉,我理解它很难重现,这是由于在Windows和Linux主机上运行游戏造成的问题,我正在尝试生成更简单的测试用例,但运气不太好。当然不用担心。我已经开始工作了,我将编辑问题,并提供更多关于我实际想要达到的目标的细节(抱歉,我知道有点晚了),以及我开始工作的剧本。感谢你花时间来帮助我,我会支持你的答案,但不会接受,希望没问题。我不知道原因是什么。我用
| default(false)
更新了我的答案,您发送了一条简单的错误消息作为响应。然后你让我从零开始一步一步地调试所有东西,而事实上它正在工作。