Ansible:当"当"时,我如何避免注册变量?条件是*不符合?

时间:2016-01-05 21:46:46

标签: ansible ansible-playbook

我有以下Ansible Playbook代码:

- name: Users | Generate password for user (Debian/Ubuntu)
  shell: makepasswd --chars=20
  register: make_password
  when: ansible_distribution in ['Debian', 'Ubuntu']

- name: Users | Generate password for user (Fedora)
  shell: makepasswd -m 20 -M 20
  register: make_password
  when: ansible_distribution in ['Fedora', 'Amazon']

- name: Users | Generate password for user (CentOS)
  shell: mkpasswd -l 20
  register: make_password
  when: ansible_distribution in ['CentOS']

- name: debug
  debug: var=make_password

哪个输出:

TASK: [users | debug] 
ok: [127.0.0.1] => {
                     "var": {
                       "make_password": {
                         "changed": false,
                         "skipped": true
                       }
                     }
                   }

...因为无论register条件如何,每个when块都会被执行。

我如何解决此问题,以便在make_password条件未满足时when不会被覆盖?

或者如果这是你可以看到的我想要完成的错误方法,请告诉我一个更好的方法。

4 个答案:

答案 0 :(得分:7)

不幸的是,这是预期的行为。来自Ansible Variables

  

注意   如果任务失败或被跳过,则仍会注册该变量   失败或跳过状态,唯一的方法是避免注册   变量使用标记

我不知道如何使用标签来解决您的问题。

编辑:我发现了一种方法,尽管是一种粗糙的解决方案。存储结果,以免被覆盖

  - set_fact: mypwd="{{make_password}}"
    when: make_password.changed

所以你的代码看起来像是:

- name: Users | Generate password for user (Debian/Ubuntu)
  shell: makepasswd --chars=20
  register: make_password
  when: ansible_distribution in ['Debian', 'Ubuntu']

- set_fact: mypwd="{{make_password}}"
  when: make_password.changed

- name: Users | Generate password for user (Fedora)
  shell: makepasswd -m 20 -M 20
  register: make_password
  when: ansible_distribution in ['Fedora', 'Amazon']

- set_fact: mypwd="{{make_password}}"
  when: make_password.changed

- name: Users | Generate password for user (CentOS)
  shell: mkpasswd -l 20
  register: make_password
  when: ansible_distribution in ['CentOS']

- set_fact: mypwd="{{make_password}}"
  when: make_password.changed

- name: debug
  debug: var=mypwd

答案 1 :(得分:3)

通常,对于在不同发行版上运行不同的任务,我倾向于包含一个特定于发行版的剧本,然后将其有条件地包含在main.yml中。

所以一个例子看起来像这样:

main.yml:

- include: tasks/Debian.yml
  when: ansible_distribution in ['Debian', 'Ubuntu']

- include: tasks/Fedora.yml
  when: ansible_distribution in ['Fedora', 'Amazon']

- include: tasks/Centos.yml
  when: ansible_distribution in ['CentOS']

- name: debug
  debug: var=make_password

Debian.yml

- name: Users | Generate password for user (Debian/Ubuntu)
  shell: makepasswd --chars=20
  register: make_password

显然重复其他两个发行版。

这样你就可以让main.yml只运行可以在任何发行版上运行的角色的所有通用任务,但是那些需要不同的东西可以在一个特定于发行版的剧本中。因为include是有条件的,所以如果不满足条件,它甚至不会加载任务,因此不应该注册该变量。

答案 2 :(得分:2)

如何在var文件中定义一个dict?

cat vars.yml

make_password: {
                'Debian':'makepasswd --chars=20',
                'Ubuntu':'makepasswd --chars=20',
                'Fedora':'makepasswd -m 20 -M 20',
                'Amazon':'makepasswd -m 20 -M 20',
                'CentOS':'mkpasswd -l 20'
                }

cat test.yml

---
- hosts: "{{ host }}"
  remote_user: root
  vars_files:
    - vars.yml 
 tasks:
    - name: get mkpasswd
      debug: var="{{ make_password[ansible_distribution] }}"

运行结果:

TASK: [get mkpasswd]
ok: [10.10.10.1] => {
    "mkpasswd -l 20": "mkpasswd -l 20"
}

答案 3 :(得分:-1)

将所有变体放入shell脚本然后运行该脚本而不是多个Ansible任务可能是有意义的。

脚本可以检测操作系统或只是对传递的参数做出反应。

#!/bin/bash

case "$1" in
"Debian" | "Ubuntu")
    makepasswd --chars=20
    ;;
"Fedora" | "Amazon")
    makepasswd -m 20 -M 20
    ;;
"CentOS")
    mkpasswd -l 20
    ;;
*)
    echo "Unexpected distribution" 1>&2
    exit 1
    ;;
esac

将此内容放在角色的脚本文件夹make_password.sh中,然后将其命名为:

- name: Users | Generate password for user
  script: make_password.sh {{ ansible_distribution }}
  register: make_password

另一个想法:您似乎实际上是远程生成密码,注册输出,然后在其他任务中使用它。如果您可以保证Ansible主主机始终属于同一类型,并且并非每个团队成员都使用不同的分发,则只需在本地运行该任务即可。

假设你使用Ubuntu:

- name: Users | Generate password for user
  shell: makepasswd --chars=20
  delegate_to: localhost
  register: make_password

任务在您通过delegate_to运行Ansible的主机上本地执行。