Regex 如何用正则表达式替换Ansible中的嵌套值

Regex 如何用正则表达式替换Ansible中的嵌套值,regex,loops,ansible,devops,ansible-facts,Regex,Loops,Ansible,Devops,Ansible Facts,这个问题是关于Ansible中的循环,不是关于AWS,但为了清楚起见,我将使用AWS部署问题作为示例 对于我们的部署脚本,我尝试在AmazonEC2容器服务中循环一些集群。我最终要做的是重新启动集群上的每个服务。我能够重新启动一个服务,因为它的名称。但是,我需要的是简单的名称,而不是完全限定的ARN。因此,我查找每个集群的服务,得到如下结果: results: - _ansible_item_result: true _ansible_no_log: false _ansible_par

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

对于我们的部署脚本,我尝试在AmazonEC2容器服务中循环一些集群。我最终要做的是重新启动集群上的每个服务。我能够重新启动一个服务,因为它的名称。但是,我需要的是简单的名称,而不是完全限定的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:服务/测试服务
变为
测试服务

更换后,我可以对服务进行循环,并通过将所需计数设置为0将其关闭(稍后我将再次打开):

其中,
taskdefinitions
是我在剧本中定义的一个简单指令:

taskdefinitions:
  services:
  - test-services
  test-xde-worker-service:
  - test-service
因此,在我将上面显示的AWS列表放入变量
result
后,我尝试通过执行以下操作来替换regex:

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

这很好,但它显然只替换了一个集群的服务名称,并且我丢失了dict
ansible\u facts
中的任何其他字段。后者是可以接受的,前者不是。问题是:如何替换嵌套列表中的文本?另一个问题是跳过关闭未包含在
任务定义中的服务,但这不是当前的问题。

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

您可以从原始对象中选择所需的项(使用
select
map(attribute=…)
json\u query
,等等),然后修改缩减集/列表中的项。在您使用JMESPath的假设示例中,比如
result.results[].ansible_facts.services[]
选择所有集群中的所有服务,并
映射('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

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

您可以从原始对象(使用
select
map(attribute=…)
json\u query
,等等)中选择所需的项,然后修改缩减的集合/列表中的项。在您的假设示例中,使用类似于JMESPath的
result.results[].ansible\u facts.services[]
选择所有集群中的所有服务,并映射('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

为什么在传递到
ecs\u服务时不替换整个dict中的值呢?
?很好的一点,我在传递变量时尝试使用过滤器,但似乎不起作用。您会注意到我使用了
项[1]
作为查找任务定义的命名索引。如果您能告诉我如何在那里应用筛选器,我将非常高兴,因为我无法让它工作。我也非常确定在某个时候,有人需要筛选嵌套列表中的一些值。因此,更一般的问题是:为什么要在整个dict中替换值,而不是在传递到
时替换值>ecs_服务
?很好,我在传递变量时尝试使用过滤器,但似乎不起作用。您会注意到我使用了
项[1]
作为查找任务定义的命名索引。如果您能告诉我如何在那里应用筛选器,我将非常高兴,因为我无法让它工作。我也非常确定某个人在某个时候需要筛选嵌套列表中的某些值。因此,这是一个更一般的问题。这听起来很有希望,我将尝试并返回这里。是的,使用VAR确实有效。结果表明,我以前的尝试也有效,但我一直收到错误消息
发生错误(ClientException)调用UpdateService操作时:Family包含无效字符。
显然我刚刚犯了一个noob错误,结果返回的是一个列表而不是一个值。正则表达式的改进也很好。出于好奇,你为什么在回答中写下我没有提供有效数据?我想一切都是正确的问题是,我刚刚匿名了我们的账号和一些服务名称。@titusn太好了,问题解决了。至于数据,请原谅,仔细查看后,它似乎有点失真yaml(第一行无效)这是用双引号括起来的。我喜欢样本数据准备好复制粘贴的时候…谢谢你的反馈。我改进了样本数据,因为我知道有人可能想要复制粘贴它。这听起来很有希望,我会尝试一下,然后回到这里。是的,使用vars确实有效。结果表明我以前的尝试也有效,但我不断获取错误消息
发生错误(ClientException)调用UpdateService操作时:Family包含无效字符。
显然我刚刚犯了一个noob错误,结果返回的是一个列表而不是一个值。正则表达式的改进也很好。出于好奇,你为什么在回答中写下我没有提供有效数据?我想一切都是正确的问题是,我刚刚匿名了我们的账号和一些服务名称。@titusn太好了,问题解决了。至于数据,请原谅,仔细查看后,它似乎有点失真yaml(第一行无效)这是双引号包围。我喜欢当样本数据准备好复制粘贴…感谢您的反馈。我改进了样本数据,因为我知道有人可能想要复制粘贴它。