Ansible:将字典组合成特定的列表项,嵌套在字典中

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

我定义了一个主剧本,它通过 import_playbook 调用另一个准备剧本。

准备剧本返回 S3 存储库的凭据,var 目前称为“service_secrets”,它是一个字典(见下文)。该字典需要附加到product.dependency 的最后一项中。选择特定列表项的指示器可以只是“Source=S3”。

---
- name: 'Preparation'
  ansible.builtin.import_playbook: 'playbook_preparation.yml'
  vars:
    product:
      name: 'mssql'
      dependencies:
        - Name: 'SqlServer'
          Source: 'psgallery'
          Type: 'psmodule'
        - Name: 'SqlServerDsc'
          Source: 'psgallery'
          Type: 'dscmodule'
        - Name: 'AWSPowershell.NetCore'
          Source: 'psgallery'
          Type: 'psmodule'
        - Name: 'ComputerManagementDsc'
          Source: 'psgallery'
          Type: 'dscmodule'
        - Name: >-
            {{
              ["mssql", ci.attributes.input_parameters.mssql.version,
              ci.attributes.input_parameters.mssql.edition,
              ci.attributes.input_parameters.mssql.language]
              | join("_")
            }}
          Source: 'S3'
          Type: 'iso'
          Bucket: 'repository'

新事实“service_secrets”看起来像这样:

        "service_secrets": {
            "Access_key_id": "abc",
            "Access_key_secret": "defghi",
            "Bucket": "repository",
            "Endpoint": "https://s3.abc.com"
        }

我尝试摆弄组合(),但我无法将service_secrets放入最后一个列表项中。

    - name: DEBUG
      debug:
        msg: '{{ product | combine({"dependencies": [service_secrets]}, list_merge="append") }}'
      loop: '{{ product.dependencies }}'
      when: 'item.Source == "S3"'

这将导致:

ok: [localhost] => (item={'Name': 'mssql_2022_standard_en', 'Source': 'S3', 'Type': 'iso', 'Bucket': 'repository'}) => {
    "msg": {
        "dependencies": [
            {
                "Name": "SqlServer",
                "Source": "psgallery",
                "Type": "psmodule"
            },
            {
                "Name": "SqlServerDsc",
                "Source": "psgallery",
                "Type": "dscmodule"
            },
            {
                "Name": "AWSPowershell.NetCore",
                "Source": "psgallery",
                "Type": "psmodule"
            },
            {
                "Name": "ComputerManagementDsc",
                "Source": "psgallery",
                "Type": "dscmodule"
            },
            {
                "Bucket": "repository",
                "Name": "mssql_2022_standard_en",
                "Source": "S3",
                "Type": "iso"
            },
            {
                "Access_key_id": "abc",
                "Access_key_secret": "defgh",
                "Bucket": "repository",
                "Endpoint": "https://s3.abc.com"
            }
        ],
        "name": "mssql"
    }
}

更清楚地说:product.dependency 的最后两个列表项应该是一项。

list dictionary filter ansible jinja2
1个回答
0
投票

有多种方法可以实现这一目标,我想向您展示两种不同的方法,因为两者都有优点和缺点。

您的初始数据

vars:
  dependencies:
    - Name: 'SqlServer'
      Source: 'psgallery'
      Type: 'psmodule'
    - Name: 'SqlServerDsc'
      Source: 'psgallery'
      Type: 'dscmodule'
    - Name: 'AWSPowershell.NetCore'
      Source: 'psgallery'
      Type: 'psmodule'
    - Name: 'ComputerManagementDsc'
      Source: 'psgallery'
      Type: 'dscmodule'
    - Name: mssql_2022_standard_en
      Source: 'S3'
      Type: 'iso'
      Bucket: 'repository'
    - Name: 'AnotherDependency_notFromS3'
      Source: 'psgallery'
      Type: 'dscmodule'

  service_secrets:
    Access_key_id: abc
    Access_key_secret: defghi
    Bucket: repository
    Endpoint: https://s3.abc.com

变体 1 - 按源拆分、丰富并重新组合

可以在单个任务中实现,无需在单独的任务中准备数据。首先,您的

dependencies
列表被分成元素
Source == 'S3'
是或否。

拆分与

rejectattr()
selectattr()
函数一起使用。属性
Source == 'S3'
被拒绝或过滤掉(选定)的元素。

对于源为 S3 的所有元素,都会添加 service_secrets。 service_secrets 使用

map()
添加,从而对列表中的每个元素执行
combine(service_secrets)

然后将两个单独的列表再次附加在一起。

我认为这是实现这一点的 Ansible 方式。缺点是您的

dependencies
列表的排序顺序可能与开始时不同。比较两个结果的排序顺序。但是,如果顺序不重要,我会推荐这种方法。

任务代码

- name: Variant 1 - split by Source, enrich and recombine
  debug:
    msg: "{{ dependencies_not_s3 + dependencies_s3 }}"
  vars:
    dependencies_not_s3: "{{ dependencies | rejectattr('Source', 'eq', 'S3') }}"
    dependencies_s3: "{{ dependencies | selectattr('Source', 'eq', 'S3') | map('combine', service_secrets) }}"

结果

TASK [Variant 1 - split by Source, enrich and recombine] ************
ok: [localhost] => {
    "msg": [
        {
            "Name": "SqlServer",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "SqlServerDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Name": "AWSPowershell.NetCore",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "ComputerManagementDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Name": "AnotherDependency_notFromS3",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Access_key_id": "abc",
            "Access_key_secret": "defghi",
            "Bucket": "repository",
            "Endpoint": "https://s3.abc.com",
            "Name": "mssql_2022_standard_en",
            "Source": "S3",
            "Type": "iso"
        }
    ]
}

变体 2 - 迭代依赖项

在第二个变体中,您迭代

dependencies
列表作为初始集,并使用
set_fact
模块
创建一个新列表。根据来源,新项目首先使用 service_secrets 进行丰富。

dependencies
列表中的每个条目都需要任务的迭代步骤,但这可确保保留
dependencies
列表的原始排序顺序。

如果您对以空新变量开头的不同依赖项列表多次执行此操作,请小心。

任务代码

- name: Variant 2 - iterate over dependencies
  set_fact:
    extended_dependencies: "{{ (extended_dependencies | default([])) + [new_item] }}"
  vars:
    new_item: "{{ item | combine(service_secrets) if item.Source == 'S3' else item }}"
  with_items: "{{ dependencies }}"

- name: Print result from Variant 2
  debug:
    var: extended_dependencies

结果

TASK [Variant 2 - iterate over dependencies] **************************************************************************
ok: [localhost] => (item={'Name': 'SqlServer', 'Source': 'psgallery', 'Type': 'psmodule'})
ok: [localhost] => (item={'Name': 'SqlServerDsc', 'Source': 'psgallery', 'Type': 'dscmodule'})
ok: [localhost] => (item={'Name': 'AWSPowershell.NetCore', 'Source': 'psgallery', 'Type': 'psmodule'})
ok: [localhost] => (item={'Name': 'ComputerManagementDsc', 'Source': 'psgallery', 'Type': 'dscmodule'})
ok: [localhost] => (item={'Name': 'mssql_2022_standard_en', 'Source': 'S3', 'Type': 'iso', 'Bucket': 'repository'})
ok: [localhost] => (item={'Name': 'AnotherDependency_notFromS3', 'Source': 'psgallery', 'Type': 'dscmodule'})

TASK [Print result from Variant 2] ************************************************************************************
ok: [localhost] => {
    "extended_dependencies": [
        {
            "Name": "SqlServer",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "SqlServerDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Name": "AWSPowershell.NetCore",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "ComputerManagementDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Access_key_id": "abc",
            "Access_key_secret": "defghi",
            "Bucket": "repository",
            "Endpoint": "https://s3.abc.com",
            "Name": "mssql_2022_standard_en",
            "Source": "S3",
            "Type": "iso"
        },
        {
            "Name": "AnotherDependency_notFromS3",
            "Source": "psgallery",
            "Type": "dscmodule"
        }
    ]
}
© www.soinside.com 2019 - 2024. All rights reserved.