我定义了一个主剧本,它通过 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 的最后两个列表项应该是一项。
有多种方法可以实现这一目标,我想向您展示两种不同的方法,因为两者都有优点和缺点。
您的初始数据
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
可以在单个任务中实现,无需在单独的任务中准备数据。首先,您的
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"
}
]
}
在第二个变体中,您迭代
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"
}
]
}