【问题标题】:Create a new array with SecurityGroupIds instead of SecurityGroupNames with Ansible使用 SecurityGroupIds 而不是使用 Ansible 的 SecurityGroupNames 创建一个新数组
【发布时间】:2020-07-30 10:52:05
【问题描述】:

我对 Ansible 比较陌生,我很难理解如何执行以下场景: 我有一个带有 AWS 安全组名称的数组,如下所示

['Security-Group-Name1', 'SecurityGroup-Name2', 'SecurityGroup-Name3']

但是,我想要的是拥有一组 SecurityGroupId。使用 Ansible,我可以选择 ec2_group_info 作为检索有关安全组的信息的选项。到目前为止一切顺利...

现在是我的问题。我需要使用 ec2_group_info 遍历上面的数组,设置我需要的安全组的名称并将检索到的 Id 返回到一个新数组中,所以最后我有这样的东西。

['Security-Group-Id1', 'SecurityGroup-Id2', 'SecurityGroup-Id3']

我知道我需要使用带有某种动态索引的循环。但我不太清楚如何在 Ansible 中执行此操作。

我知道 Ansible Docs 的最新循环部分,我发现它们不仅仅是令人困惑...... https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

编辑:

这是根据需要工作的当前代码:

- name: Installing pip if not existing on host
  pip:
    name: boto3

- name: Get SecurityGroupId information
  ec2_group_info:
    filters:
      group_name: ['SG-One', 'SG-Two']
      vpc_id: 'vpc-id'
  register: my_groups

- set_fact:
    my_group_ids: '{{ my_groups.security_groups | map(attribute="group_id") | list }}'

- debug:
    msg: "{{ my_groups }}"

- debug:
    msg: "{{ my_group_ids }}"

这是结果:

TASK [Gathering Facts] *************************************************** 
ok: [localhost]

TASK [machine-provisioning : Installing pip if not existing on host] ************
ok: [localhost]

TASK [machine-provisioning : Get SecurityGroupId information] ************************* 
ok: [localhost]

TASK [machine-provisioning : set_fact] *********************************
ok: [localhost]

TASK [machine-provisioning : debug] ***********************************************
ok: [localhost] => {
"msg": [
    "sg-00000000",
    "sg-11111111"
]

}

【问题讨论】:

  • group_name: "['SG-One', 'SG-Two']" 不是list,它是一个包含python-y 语法的字符串;具有讽刺意味的是,由于 yaml 的工作方式,如果您只是删除外部的 ",它将变成一个列表
  • 我对此感到非常困惑的是,我需要在为动态变量使用括号时添加外部“,但在引用 yaml 中的列表时不需要它。谢谢,我会试试这个。
  • 是的,你需要加上引号,因为 (deep sigh) jinja2 使用 { 作为其插值语法的开始字符,但是那个字符也是合法的 yaml,所以 yaml 解析器认为 @987654331 @ 是 "thing": {},但有一个虚假的主体(因为在 JSON 中你不能拥有 { {。如果你在 ansible 体验的早期就被卡住了,你真的应该停下来阅读教程
  • 如果“null 是十亿美元的错误”,那么 Dag 选择使用 jinja2 而不自定义其变量和块语法是 ansible 的“百万美元错误”;他们实际上确实允许您 customize it for templates,这只是 ansible 本身就是愚蠢的
  • 只是想让您知道这是有效的,非常感谢您的建议,我将开始阅读一些教程以更好地了解语法规则的工作原理,再次感谢!

标签: amazon-web-services loops ansible aws-security-group


【解决方案1】:

在有关循环的链接页面上,您将观察到 register: 的使用,这是您捕获 ec2_group_info: 查找结果的方式,然后使用 map jinja filter 从结果列表;你必须将map 的输出输入list 过滤器,因为map 和其他一些是python 生成器,因此需要一个终端操作来实现它们的数据。 set_fact: 是 ansible 的“赋值”方式

- ec2_group_info:
    filters:
      group_name: '{{ the_group_names }}'
      vpc_id: '{{ my_vpc_id }}'
  register: my_groups
- set_fact:
    my_group_ids: '{{ my_groups.security_groups | map(attribute="group_id") | list }}'

产量:

ok: [localhost] => {"ansible_facts": {"my_group_ids": ["sg-0c5c277ed1edafb54", "sg-7597a123"]}, "changed": false}

【讨论】:

  • 好的,让我回顾一下,以便我正确理解这一点。当我将数组传递给 the_group_names 时,它将为每个 group_name 返回一个信息对象,并将其作为数组值保存到 my_groups 中。从那里我将使用 set_fact 和 map(attribute="SecurityGroupId") 过滤该对象中的 SecurityGroupId 信息,并根据该信息创建一个数组,该数组保存到 my_group_ids 中,我理解正确吗?
  • 这就是我所期望的,是的;您的情况有点独特,因为 ec2_group_info 接受一个数组并在其结果中返回一个数组,这意味着在这种情况下您不需要 with_items:,因为您通常会使用更多“单一目的”事实收集任务
  • 这很有趣,好吧,我会测试一下,看看它的表现如何
  • 好的,我在上面进行了测试,当我在过滤器 group_name 中使用单个值时它确实有效,例如 group_name: "SG-Name1" 但是当我在数组中使用多个值时它不起作用,例如group_name: ['SG-Name1', 'SG-Name2', 'SG-Name3'] 我需要如何编写它才能使用数组?
  • edit your question 显示实际的剧本及其结果,而不是尝试将代码放入 cmets(它们对此很糟糕)。我只是在本地测试它,它按照我说的做了,我忘记在过滤器中包含vpc_id: 的星号,这可能会影响结果
猜你喜欢
  • 2020-05-11
  • 2021-09-30
  • 2015-12-15
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-19
相关资源
最近更新 更多