使用 Ansible 在 Route 53 中列出超过 100 条记录

Listing more than 100 records in Route 53 using Ansible

我目前正在项目中使用 route53_facts 模块。我在一个托管区域中有 250 个记录集。我很难列出该区域中的所有记录集。 Route 53 API 通过一次 return 页面 最多 100 条记录 来工作。为了检索下一页,您必须将 NextRecordName 响应值传递给 route53_facts 模块的 start_record_name: 字段(非常简单)。

我遇到的具体问题是让 Ansible 执行此操作。大概有人会使用循环来做到这一点,例如在伪代码中:

start
get 100 records
do until response does not contain NextRecordName:
    get 100 records (start_record_name=NextRecordName)
end

在 Ansible 中,我编写了以下任务来执行此操作:

- block:
  - name: List record sets in a given hosted zone
    route53_facts:
      query: record_sets
      hosted_zone_id: "/hostedzone/ZZZ1111112222"
      max_items: 100
      start_record_name: "{{ record_sets.NextRecordName | default(omit) }}"
    register: record_sets
    until: record_sets.NextRecordName is not defined
  when: "'{{ hosted_zone['Name'] }}' == 'test.example.com.'"

...但是,这并没有按预期工作。它不是不断翻阅响应直到没有更多记录,而是重复 return 前 100 条记录 ("the first page")。

正如我从 Ansible 调试输出中看到的那样,start_record_name: 重复 null:

"attempts": 2,
"changed": false,
"invocation": {
    "module_args": {
        "aws_access_key": null,
        "aws_secret_key": null,
        "change_id": null,
        "delegation_set_id": null,
        "dns_name": null,
        "ec2_url": null,
        "health_check_id": null,
        "health_check_method": "list",
        "hosted_zone_id": "/hostedzone/ZZZ1111112222",
        "hosted_zone_method": "list",
        "max_items": "100",
        "next_marker": null,
        "profile": null,
        "query": "record_sets",
        "region": null,
        "resource_id": null,
        "security_token": null,
        "start_record_name": null,
        "type": null,
        "validate_certs": true
    }
},

...我的猜测是 |默认(省略) 过滤器始终被执行。换句话说,record_sets.NextRecordName 从未在任务的此时初始化。

我希望有人可以帮助我让 Ansible return 来自 Route 53 中一个区域的所有记录。我想我已经被 Ansible 的循环行为所困扰。谢谢!

请注意 "as best I can tell:"

为了回答您的问题,until:register: 的交互方式似乎与 when:register: 的交互方式不同。我得到的最好的解释是 until: 的行为就像一个数据库事务:如果条件为假,它会回滚 register: 赋值,这意味着当再次尝试 until: 任务的主体时,它使用与第一次相同的参数。唯一使 until: 块不成为无限循环的是 retries: 值。

因此,在您的具体情况下,我认为这可以完成工作:

- name: initial record_set
  route53_facts:
  # bootstrap so the upcoming "when:" will evaluate correctly
  register: record_facts
- set_fact:
    # capture the initial answer
    records0: '{{ record_facts.ResourceRecordSets }}'
- name: rest of them
  route53_facts:
    start_record_name: '{{ record_facts.NextRecordName }}'
  register: record_facts
  when: record_facts.NextRecordName | default("")
  with_sequence: count=10
- set_fact:
    all_records: >-
      {{ record0 + (record_facts.results | 
           selectattr("ResourceRecordSets", "defined") |
           map(attribute="ResourceRecordSets") | list) }}

with_sequence: 是一个 hack,因为 loop:with_* 是语法糖)需要一个要迭代的项目列表,但考虑到返回的响应没有 NextRecordName 将导致 when: 失败,跳过它们,使(在您的情况下)3 到 10 项几乎立即解决。

那么您只需要从现在 listroute53_facts: 回复中提取实际响应数据,并将它们粘贴到初始回复中以获得完整列表。


综上所述,我现在确信 route53_facts:(以及将迭代负担推入剧本的任何其他 AWS 模块)行为是一个 bug.模块调用者已经有一个 max_items: 可供他们使用,但这是一个实现细节,即任何值都不能大于某个随机分页截止值。