【问题标题】:jinja2 Ansible filter dictionaryjinja2 Ansible 过滤器字典
【发布时间】:2018-07-20 22:06:28
【问题描述】:

我从事 ansible 已经有一段时间了,但最近开始做一些更高级的事情,例如从外部来源提取数据以驱动操作。这导致我不得不更深入地研究 ansible 如何允许对变量进行逻辑和解析,这需要我对 jinja2 进行一些研究。

在我的剧本中,我试图从 etcd 中提取数据,允许我构建授权的 sudo 规范文件,然后我将其传递给角色以添加到适当的系统中。

我的数据源除了存储构建规范所需的数据外,还有用于审计和日志记录目的的元数据。

我的数据源的一个关键方面是在删除访问权限时不应删除任何元数据,即用户 XYZ 在 10 天内没有密码 sudo。很多方面都有一个状态字段,可能是 activeinactive 或者在 sudo specs grantrevoke 的情况下>.

我已经成功构建了一个查找,它可以拉回类似于下面的字典 - 然后我使用后续的 ansible 语句对其进行解析。我能够成功处理和提取所有数据,但其规范处于 grant 状态的组/用户除外。

当规范处于“授予”状态时,我需要提取 linuxName 字段,以传递给配置 sudo 的角色。

我尝试了许多过滤器的变体,其中大多数最终导致我收到拒绝或类似消息,或者 NULL 值而不是我想要的值列表。

有人知道如何实现这一点吗?

提前致谢。

样本数据

ok: [serverName] => {
    "sudoInfraSpecs": [
        {
            "infra_admins": {
                "addedBy": "someUser",
                "commands": "FULL_SUDO",
                "comment": "platform support admins",
                "dateAdded": "20180720",
                "defaults": "!requiretty",
                "hosts": "SERVERS",
                "name": "infra_admins",
                "operators": "ROOT",
                "state": "active",
                "tags": "PASSWD",
                "users": {
                    "admingroup1": {
                        "addedBy": "someUser",
                        "dateAdded": "20180719",
                        "linuxName": "%admingroup1",
                        "name": "admingroup1",
                        "state": "grant"
                    },
                    "admingroup2": {
                        "addedBy": "someUser",
                        "dateAdded": "20180719",
                        "linuxName": "%admingroup2",
                        "name": "admingroup2",
                        "state": "grant"
                    }
                }
            },
            "ucp_service_account": {
                "addedBy": "someUser",
                "commands": "FULL_SUDO",
                "comment": "platform service account",
                "dateAdded": "20180720",
                "defaults": "!requiretty",
                "hosts": "SERVERS",
                "name": "platform_service_account",
                "operators": "ROOT",
                "state": "active",
                "tags": "NOPASSWD,LOG_OUTPUT",
                "users": {
                    "platformUser": {
                        "addedBy": "someUser",
                        "dateAdded": "20180719",
                        "linuxName": "platformUser",
                        "name": "platformUser",
                        "state": "grant"
                    }
                }
            }
        }
    ]
}

Ansible sn-p

- name: Translate infraAdmins sudoers specs from etcd into a list for processing [1]
  set_fact:
    tempInfraSpecs:
      name: "{{ item.value.name}}"
      comment: "{{ item.value.comment }}"
      users: "{{ item.value.users | list }}"
      hosts: "{{ item.value.hosts.split(',') }}"
      operators: "{{ item.value.operators.split(',') }}"
      tags: "{{ item.value.tags.split(',') }}"
      commands: "{{ item.value.commands.split(',') }}"
      defaults: "{{ item.value.defaults.split(',') }}"
  with_dict: "{{ sudoInfraSpecs }}"
  when: item.value.state == 'active'
  register: tempsudoInfraSpecs

- name: Translate infraAdmins sudoers specs from etcd into a list for processing [2]
  set_fact:
    sudoInfraSpecs_fact: "{{ tempsudoInfraSpecs.results | selectattr('ansible_facts','defined')| map(attribute='ansible_facts.tempInfraSpecs') | list }}"

粗略的期望输出字典:

sudoInfraSpecs:
      - infra_admins:
          addedBy: someUser
          commands: FULL_SUDO
          comment: platform support admins
          dateAdded: '20180720'
          defaults: "!requiretty"
          hosts: SERVERS
          name: infra_admins
          operators: ROOT
          state: active
          tags: PASSWD
          users:
              "%admingroup1"
              "%admingroup2"
      - ucp_service_account:
          addedBy: someUser
          commands: FULL_SUDO
          comment: platform service account
          dateAdded: '20180720'
          defaults: "!requiretty"
          hosts: SERVERS
          name: platform_service_account
          operators: ROOT
          state: active
          tags: NOPASSWD,LOG_OUTPUT
          users:
              "platformUser"

【问题讨论】:

  • 你能修改从 etcd 中提取的数据的格式吗?如果您返回一个平面对象列表,可能带有name: infra_admins,那么在它们上使用selectattr() 会容易得多。使用当前格式,如果遍历结果列表,您需要提取每个对象的顶级键名,例如:{% for i in sudoInfraSpecs %} {% if i[i.keys()[0]]["state"] == "active" %} {{ i }} {% endif %} {% endfor %}
  • 我是否认为这样做更适合我用作模板的 .j2 文件,然后在剧本中?
  • 是的,在模板/默认文件中隐藏所有这些复杂性肯定会容易得多 - 然后你可以使用一些临时变量等。我想在一个衬里做到这一点,但它'看起来会很糟糕。

标签: ansible jinja2


【解决方案1】:

最后我创建了一个自定义过滤器,用于解析构成用户的嵌套字典:

#!/usr/bin/python
def getSpecActiveMembers(my_dict):
    thisSpecActiveMembers = []
    for i, value in my_dict.iteritems():
        if value['state'] == 'grant':
            thisSpecActiveMembers.append(value['linuxName'])
    return thisSpecActiveMembers

class FilterModule(object):
    def filters(self):
        return {
            'getSpecActiveMembers': getSpecActiveMembers
        }

这最终将用户从上面列出的源扁平化到所需的输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    相关资源
    最近更新 更多