6

我有一个复杂的环境,包含多个系统的阶段和用户。

阶段是:dev,int等。

每个阶段都有一个应用程序的用户,我们称之为用户 john。这导致用户 johnd 用于 dev 和 johni 用于 int 等等。

为了抽象系统管理,由于阶段中的所有系统都是相同的,我创建了这个数据结构:

users:
  john:
    dev:
      name: "johnd"
    int:
      name: "johni"

现在我有一个角色“collect_user_information”,它从 LDAP 收集所有类型的信息,并在 set_fact 的帮助下将它们存储在一个变量中。

- name: Get the userhome out of LDAP
  shell: 'getent passwd {{ users[ user ][ stage ].name }} | cut -d: -f6'
  register: user_home

和 set_fact:

- name: set facts for LDAP user
  set_fact:
    "{{user}}":
      name: "{{ users[ user ][ stage ].name }}"
      home: "{{ user_home.stdout }}"

要转储变量,我使用:

- name: debug output for myuser
  debug: var="{{user}}"

调试输出看起来很有希望。

TASK [collect_user_information : debug output for user] *******
ok: [host1] => {
  "john": {
     "home": "/home/johni",-
     "name": "johni"
  }
}

现在我想执行一个角色来创建用户主页。

- { role: create_user_home, user: "john" }

首先,我转储变量的条目:

- name: debug role create_user_home output for variable user
  debug: var=user

TASK [create_user_home : debug role create_user_home output for variable user] ***********
ok: [host1] => {
    "user": "john"
}

- name: debug role create_user_home output for variable john
  debug: var={{ user }}

TASK [create_user_home : debug role create_user_home output for variable john] **********
ok: [host1] => {
    "john": {
        "home": "/home/johni",-
        "name": "johni"
    }
}       

现在我想使用这个数据结构。我想我可以通过引用“{{user.name}}”或“{{user['name']}}”来访问这些值,但两者都不起作用。

TASK [create_user_home : Create home directories for john] ***********************
fatal: [host1]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'ansible.parsing.yaml.objects.AnsibleUnicode object' has no attribute 'home'\n\nThe error appears to have been in '/etc/ansible/roles/create_user_home/tasks/main.yml': line 37, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n#-------------------------------------------------------------------------------\n- name: Create home directories for john\n  ^ here\n"}

那么,它是如何工作的?

4

2 回答 2

3

好的,我自己找到了解决方案。

首先,我在我的数据结构中创建了一个附加层(myuser)并使用了不同的符号。

- name: set facts for LDAP user
  set_fact:
  myuser: '{ "{{user}}": { "name": "{{ users[ user ][ stage ].name }}", "home": "{{ user_home.stdout }}", "gid": "{{ user_gid.stdout}}", "group": "{{ user_primarygroup.stdout }}" } }'

这会返回一个调试转储,如下所示:

TASK [collect_user_information : debug output for myuser] ***********
ok: [host1] => {
    "myuser": {
        "john": {
            "home": "/home/johni",
            "name": "johni"
        }
    }
}

现在我可以使用我的数据结构值了。请记住“用户”已通过参数传递给角色。

- name: Create home directories for user
  user:
    name: "{{ myuser[ user ].name }}"
    home: "{{ myuser[ user ].home }}"
    shell: "/bin/bash"
  register: "create_user_home"
  tags: [ 'user' ]

希望有帮助。

于 2017-06-13T17:04:43.253 回答
0

整个事情在这里太棘手了 - 你想定义一个动态变量,其中变量名称是用户名,例如。john, whilejohn是一个包含两个键的字典,它们是.name.home

您的第一次尝试失败,因为您试图引用user.namewhich 引用 dict 的键nameuser而不是 dict called john

由于您在某处定义了黄金字典users,因此您实际上并不需要使事情变得复杂。您始终可以使用users[user][stage].nameuser_home.stdout为 home dir 引用名称。

如果你觉得语法太麻烦。我们可以通过创建另一个字典来存储名称和主目录来恢复您原来的方法。在以下情况下,user始终指的是您正在配置的当前用户:

- name: set facts for LDAP user
  set_fact:
    user:
      name: "{{ users[username][stage].name }}"
      home: "{{ user_home.stdout }}"

以便您可以在任何后续任务中使用user.name和。user.home请注意第 4 行,我重命名了您传递给角色的 varusername以避免冲突。


更新:

支持多用户:

- name: Get the user home out of LDAP
  shell: 'getent passwd {{ users[item][stage].name }} | cut -d: -f6'
  register: homes
  with_items: "{{ users }}"

# item.item is the username, item.stdout is the home dir
- debug: msg="{{ users[item.item][stage].name }}'s home is {{ item.stdout }}"
  with_items: "{{ homes.results }}"

从使用带有循环的寄存器中了解更多信息。

于 2017-06-15T02:57:13.560 回答