jinja2 Ansible过滤字典

时间:2018-07-20 22:06:29

标签: ansible jinja2

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

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

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

我的数据源的一个关键方面是在删除访问权限后,不应删除任何元数据,即用户XYZ在10天内的密码比sudo少。如此多的方面都有一个状态字段,该状态字段可能是活动无效,或者在使用sudo规范 grant 撤销。

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

当规范处于“ 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代码段

- 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"

1 个答案:

答案 0 :(得分:0)

最后,我通过创建一个自定义过滤器以供在我的剧本中使用,以解析组成用户的嵌套字典来完成此操作:

#!/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
        }

这最终使用户从上面列出的来源变平为所需的输出。