Ansible jinja2 在 selectattr 中转义点键

问题描述 投票:0回答:2

我目前正在尝试循环 k8s_facts 的子集。我的事实看起来像:

{
  "resources": [
  { 
    "metadata": {
      "annotations": {
         "com.foo.bar/name": "foo",
         "com.foo.bar/foo-name": "baz"
       },
       "creationTimestamp": "2018-12-20T02:29:50Z",
       "name": "foo-bar"
    }
  },
  ...

我想过滤

com.foo.bar/foo-name
键的特定值。因为按键有
.
-
/
,所以与 Jinja2
selectattr
功能配合不好。我尝试做类似的事情,但徒劳:

- debug:
    msg: "{{ item }}"
    loop: "{{ my_fact.resources | selectattr('metadata.annotations[\\'com.foo.bar/foo-name\\']', 'defined') | selectattr('metadata.annotations[\\'com.foo.bar/foo-name\\']', 'match', 'baz') | list }}"
  loop_control: 
    label: "{{ item.metadata.name }}"

执行前一个时,出现此错误:

fatal: [<redacted>]: FAILED! => {"msg": "template error while templating string: expected token ',', got 'com'. String: {{ my_fact.resources | selectattr('metadata.annotations[\\\\'com.foo.bar/foo-name\\\\']', 'defined') | selectattr('metadata.annotations[\\\\'com.foo.bar/foo-name\\\\']', 'match', 'baz') | list }}"}

我的问题是,如何转义 Jinja2 中包含点的复杂字符串?

ansible jinja2
2个回答
5
投票

当我在 ansible 中进入逃离地狱时,我倾向于利用 yaml 折叠和文字块语法。优点是它可以让你编写 jinja 块而不必用引号将它们括起来,这消除了一个引用级别,因此也消除了一个转义级别。

就你的情况而言,我认为你可以使用

json_query
过滤器直接切入主题,而不是通过管道传递一长串过滤器。

这是一个演示手册:

---
- name: Test var names with dots
  hosts: localhost
  gather_facts: false

  vars:
    my_fact: {
      "resources": [
        {
          "metadata": {
            "annotations": {
              "com.foo.bar/name": "foo",
              "com.foo.bar/foo-name": "baz"
            },
            "creationTimestamp": "2018-12-20T02:29:50Z",
            "name": "foo-bar"
          }
        },
        {
          "metadata": {
            "annotations": {
              "com.foo.bar/name": "toto",
              "com.foo.bar/foo-name": "titi"
            },
            "creationTimestamp": "2018-12-21T02:30:50Z",
            "name": "foo-bla"
          }
        },
        {
          "metadata": {
            "annotations": {
              "com.foo.bar/name": "johnsmith",
              "com.foo.bar/foo-name": "baz"
            },
            "creationTimestamp": "2018-12-22T02:31:50Z",
            "name": "foo-john"
          }
        }
      ]
    }

  tasks:
    - name: Show results where metadata.annotations."com.foo.bar/foo-name"=='baz'
      vars:
        query: >-
          [?(metadata.annotations."com.foo.bar/foo-name")=='baz']
      debug:
        msg: "{{ item }}"
      loop: "{{ my_fact.resources | json_query(query) }}"
      loop_control:
        label: "{{ item.metadata.name }}"

结果

PLAY [Test var names with dots] *******************************************************************************************************************************************************************************************

TASK [Show results where metadata.annotations."com.foo.bar/foo-name"=='baz'] **********************************************************************************************************************************************
ok: [localhost] => (item=foo-bar) => {
    "msg": {
        "metadata": {
            "annotations": {
                "com.foo.bar/foo-name": "baz",
                "com.foo.bar/name": "foo"
            },
            "creationTimestamp": "2018-12-20T02:29:50Z",
            "name": "foo-bar"
        }
    }
}
ok: [localhost] => (item=foo-john) => {
    "msg": {
        "metadata": {
            "annotations": {
                "com.foo.bar/foo-name": "baz",
                "com.foo.bar/name": "johnsmith"
            },
            "creationTimestamp": "2018-12-22T02:31:50Z",
            "name": "foo-john"
        }
    }
}

PLAY RECAP ****************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


1
投票

问:“我想过滤 com.foo.bar/foo-name 键的特定值”

A:下面的json_query可以完成这项工作

  q1: '[?metadata.annotations."com.foo.bar/foo-name"==`baz`]'
  r1: "{{ resources|json_query(q1) }}"

给予

  r1:
  - metadata:
      annotations:
        com.foo.bar/foo-name: baz
        com.foo.bar/name: foo
      creationTimestamp: '2018-12-20T02:29:50Z'
      name: foo-bar

用于测试的完整剧本示例

- hosts: all

  vars:
    resources:
      - metadata:
          annotations:
            com.foo.bar/foo-name: baz
            com.foo.bar/name: foo
          creationTimestamp: '2018-12-20T02:29:50Z'
          name: foo-bar

    q1: '[?metadata.annotations."com.foo.bar/foo-name"==`baz`]'
    r1: "{{ resources|json_query(q1) }}"

  tasks:

    - debug:
        var: r1
© www.soinside.com 2019 - 2024. All rights reserved.