如何检查字典的嵌套列表中的项目是否在另一个字典列表中存在?

时间:2019-09-01 11:16:27

标签: ansible citrix netscaler

您好,开发者社区!

这是我在这里的第一篇文章:-)我对Ansible比较陌生,想在以下方面获得一些帮助。我正在尝试创建一些脚本来管理Citrix NetScaler VPX上的功能。在这种特定情况下,我想部署一个包含已定义SSL密码的SSL密码组。 我在YAML文件中定义了以下数据结构:

nsapp_sslciphergroup:
  - ciphergroupname:                   "TEST_1"
    sslcipher:
      - ciphername:                    "TLS1.3-AES256-GCM-SHA384"
        cipherpriority:                "1"
      - ciphername:                    "TLS1.3-CHACHA20-POLY1305-SHA256"
        cipherpriority:                "2"
      - ciphername:                    "TLS1.3-AES128-GCM-SHA256"
        cipherpriority:                "3"

  - ciphergroupname:                   "TEST_2"
    sslcipher:
      - ciphername:                    "TLS1.2-ECDHE-RSA-AES256-GCM-SHA384"
        cipherpriority:                "1"
      - ciphername:                    "TLS1.2-ECDHE-RSA-AES128-GCM-SHA256"
        cipherpriority:                "2"
      - ciphername:                    "TLS1.2-ECDHE-ECDSA-AES256-GCM-SHA384"
        cipherpriority:                "3"

NetScaler本身不允许再次将相同的密码绑定到给定的密码组中,因此在进行任何更改之前,我需要以某种方式检查该密码组及其绑定是否已经存在。因此,第一次运行是可以的,但是任何连续运行都会失败,因为给定的密码名已绑定到密码组。 当前代码如下:

- name: "Add SSL ciphergroup binding(s)"
  netscaler_nitro_request:
    <<: *nitro_login
    operation: add
    resource: sslcipher_sslciphersuite_binding
    name: ""
    attributes:
          ciphergroupname: "{{ item.0.ciphergroupname }}"
          ciphername: "{{ item.1.ciphername }}"
          cipherpriority: "{{ item.1.cipherpriority }}"
  register: add_sslcipher_sslciphersuite_binding_result
  with_subelements:
    - "{{ nsapp_sslciphergroup }}"
    - "sslcipher"
    - skip_missing: true

为了在再次运行脚本之前检查当前配置是什么,我有以下代码:

- name: "Check if SSL ciphergroup binding(s) are already defined"
  netscaler_nitro_request:
    <<: *nitro_login
    operation: get
    resource: sslcipher_sslciphersuite_binding
    name: "{{ item.ciphergroupname }}"
    attributes:
          ciphergroupname: "{{ item.ciphergroupname }}"
  register: get_sslcipher_sslciphersuite_binding_result
  with_items: "{{ nsapp_sslciphergroup }}"

如果已经使用绑定定义了密码组,则此代码将得出以下结果(在“ get_sslcipher_sslciphersuite_binding_result”变量中注册) (并且对于“ TEST_2”组也具有类似的输出,并且具有各自的绑定):

"nitro_object": [
    {
        "ciphergroupname": "TEST_1", 
        "ciphername": "TLS1.3-AES256-GCM-SHA384", 
        "cipherpriority": "1", 
        "description": "TLSv1.3 Kx=any      Au=any  Enc=AES-GCM(256) Mac=AEAD   HexCode=0x1302", 
        "peflags": "4", 
        "stateflag": "512"
    }, 
    {
        "ciphergroupname": "TEST_1", 
        "ciphername": "TLS1.3-CHACHA20-POLY1305-SHA256", 
        "cipherpriority": "2", 
        "description": "TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD   HexCode=0x1303", 
        "peflags": "4", 
        "stateflag": "512"
    }, 
    {
        "ciphergroupname": "TEST_1", 
        "ciphername": "TLS1.3-AES128-GCM-SHA256", 
        "cipherpriority": "3", 
        "description": "TLSv1.3 Kx=any      Au=any  Enc=AES-GCM(128) Mac=AEAD   HexCode=0x1301", 
        "peflags": "4", 
        "stateflag": "512"
    }
], 

我正在在“ with_subelements”部分之后添加“ when”子句,但是脚本的add部分始终希望运行。

有人可以建议检查“ get_sslcipher_sslciphersuite_binding_result”变量是否包含给定密码组的给定密码名的正确方法是什么吗?

非常感谢!

2 个答案:

答案 0 :(得分:0)

解决方案是让模块报告故障并测试错误代码

failed_when: 
  - add_sslcipher_sslciphersuite_binding_result.nitro_errorcode != 0
  - add_sslcipher_sslciphersuite_binding_result.nitro_errorcode != 3741

鉴于模块在成功更新资源时返回“ 0”,可能有可能使

成为幂等
changed_when:
  - add_sslcipher_sslciphersuite_binding_result.nitro_errorcode == 0


不是幂等的。

  问:NetScaler同样不允许将相同的密码再次绑定到给定的密码组中,因此在进行任何更改之前,我需要以某种方式检查密码组及其绑定是否已经存在。因此,可以进行第一次运行,但是任何连续运行都会失败,因为给定的密码名已经绑定到了密码组。当前代码如下:

- name: "Add SSL ciphergroup binding(s)"
  netscaler_nitro_request:
    <<: *nitro_login
    operation: add
    resource: sslcipher_sslciphersuite_binding
    name: ""
    attributes:
          ciphergroupname: "{{ item.0.ciphergroupname }}"
          ciphername: "{{ item.1.ciphername }}"
          cipherpriority: "{{ item.1.cipherpriority }}"
  register: add_sslcipher_sslciphersuite_binding_result
  with_subelements:
    - "{{ nsapp_sslciphergroup }}"
    - "sslcipher"
    - skip_missing: true
  

大多数NetScaler REST API查询都以这种方式工作,根本没有幂等性。

A:幂等是Ansible的关键功能。引用自Glossary

  

幂等:如果一次执行的结果与重复执行而没有任何干预动作的结果完全相同,则该操作是幂等的。

文档中没有迹象表明模块netscaler_nitro_request可能不是幂等的。

答案 1 :(得分:0)

刚砍死它:-) “指定的密码已经绑定了更高的优先级”的NS错误代码为 3741 。只需在fail_when条件下添加它即可。

- name: "Add SSL ciphergroup binding(s) if they do *NOT* exist"
  netscaler_nitro_request:
    <<: *nitro_login
    operation: add
    resource: sslcipher_sslciphersuite_binding
    name: ""
    attributes:
          ciphergroupname: "{{ item.0.ciphergroupname }}"
          ciphername: "{{ item.1.ciphername }}"
          cipherpriority: "{{ item.1.cipherpriority }}"
  register: add_sslcipher_sslciphersuite_binding_result
  until: ( add_sslcipher_sslciphersuite_binding_result is succeeded )
  retries: 6
  delay: 5
  with_subelements:
    - "{{ nsapp_sslciphergroup }}"
    - "sslcipher"
    - skip_missing: true
  failed_when: ( (add_sslcipher_sslciphersuite_binding_result.nitro_errorcode != 0) and (add_sslcipher_sslciphersuite_binding_result.nitro_errorcode != 3741) )
- debug: 
    var: add_sslcipher_sslciphersuite_binding_result
  tags: [ never, debug ]
- assert:
    that: ( (add_sslcipher_sslciphersuite_binding_result.results[{{ item }}].nitro_errorcode == 0) or (add_sslcipher_sslciphersuite_binding_result.results[{{ item }}].nitro_errorcode == 3741) )
    fail_msg: "[ERROR] Operation failed!"
    success_msg: "[OK] Operation successful." 
  loop: "{{ nsapp_sslciphergroup }}" 
  loop_control:
    index_var: item