0

这个问题是关于 Ansible 中的循环,而不是关于 AWS,但为了清楚起见,我将使用 AWS 部署问题作为示例。

对于我们的部署脚本,我尝试遍历 Amazon EC2 容器服务中的一些集群。我最终要做的是重新启动集群上的每个服务。给定它的名称,我可以重新启动服务。但是我需要简单的名称,而不是完全限定的 ARN。所以我查找每个集群的服务并得到如下信息:

results:
- _ansible_item_result: true
  _ansible_no_log: false
  _ansible_parsed: true
  ansible_facts:
    services:
    - arn:aws:ecs:eu-central-1:55:service/test-services
  changed: false
  failed: false
  invocation:
    module_args:
      aws_access_key: null
      aws_secret_key: null
      cluster: services
      details: false
      ec2_url: null
      profile: null
      region: null
      security_token: null
      service: null
      validate_certs: true
  item: services
- _ansible_item_result: true
  _ansible_no_log: false
  _ansible_parsed: true
  ansible_facts:
    services:
    - arn:aws:ecs:eu-central-1:55:service/test-service
    - arn:aws:ecs:eu-central-1:55:service/frontend
    - arn:aws:ecs:eu-central-1:55:service/beats
  changed: false
  failed: false
  invocation:
    module_args:
      aws_access_key: null
      aws_secret_key: null
      cluster: test-service
      details: false
      ec2_url: null
      profile: null
      region: null
      security_token: null
      service: null
      validate_certs: true
  item: test-service    module_args:
  aws_access_key: null
  aws_secret_key: null
  cluster: test-service
  details: false
  ec2_url: null
  profile: null
  region: null
  security_token: null
  service: null
  validate_certs: true

项目:测试服务

现在我想用服务的短名称替换每个 ARN。例如: arn:aws:ecs:eu-central-1:55:service/test-service变成test-service.

替换后,我可以循环服务并通过将所需的计数设置为 0 来关闭它们(稍后我将再次打开它们):

- name: "Turn services off"
  ecs_service:
    name: "{{ item[1]}}"
    desired_count: 0
    task_definition: "{{ taskdefinitions[item[1]] }}"
    cluster: "{{ item[0].item }}"
    state: present
with_subelements:
    - "{{ result.results }}"
    - ansible_facts.services
register: turnOffServiceResult

taskdefinitions我在剧本中定义的简单字典在哪里:

taskdefinitions:
  services:
  - test-services
  test-xde-worker-service:
  - test-service

因此,在将上面显示的 AWS 列表放入变量后,result我尝试通过执行以下操作来进行正则表达式替换:

- set_fact:
  result:
    results:
      ansible_facts:
        services: "{{ result.results.1.ansible_facts.services | map('regex_replace', '.*/(.*?)$', '\\1' ) | list }}"

这很好用,但它显然只替换了一个集群的服务名称,并且我丢失了 dict 中的任何其他字段ansible_facts。后者可以接受,前者不行。那么问题来了:如何替换嵌套列表中的文本?另一个问题是跳过关闭不包含在 中的服务taskdefinitions,但这不是手头的问题。

4

1 回答 1

2

我不知道有任何内置方法可以就地修改复杂对象中的任意项(至少在当前的 Ansible 2.3 中)。

您可以从原始对象(使用selectmap(attribute=...)json_query等)中选择所需的项目,然后修改该缩减集/列表中的项目。在您使用 JMESPath 的假设示例中,喜欢result.results[].ansible_facts.services[]选择所有集群和map('regex_replace',...此列表中的所有服务。

或者迭代复杂对象并在循环内应用修改,例如:

- name: "Turn services off"
  ecs_service:
    name: "{{ myname }}"
    desired_count: 0
    task_definition: "{{ taskdefinitions[myname] }}"
    cluster: "{{ mycluster }}"
    state: present
  vars:
    mycluster: "{{ item[0].item }}"
    myname: "{{ item[1] | regex_search('[^/]*$') }}"
  with_subelements:
    - "{{ result.results }}"
    - ansible_facts.services
于 2017-09-06T14:18:46.007 回答