2017-09-06 89 views
0

这个问题关于Ansible中的循环,而不是AWS中的循环,但为了清晰起见,我将使用AWS部署问题作为示例。如何用正则表达式替换Ansible中的嵌套值

对于我们的部署脚本,我试图循环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 

所以后,我得到如上图所示为一个变量result我尝试用正则表达式替换做以下的AWS列表:

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

这工作正常,但它显然只取代了一个集群的服务名称,并且我丢失了字典ansible_facts中的任何其他字段。后者是可以接受的,前者不可以。所以这里是一个问题:我如何替换嵌套列表中的文本?另一个问题是跳过关闭taskdefinitions中未包含的服务,但这不在眼前。

+0

为什么传递给'ecs_service'时更换整个字典里面的价值观和不呢? –

+0

好点,我试着在传递变量时使用过滤器,但这似乎并不奏效。您会注意到我使用'item [1]'作为命名索引来查找task_definition。如果你能告诉我如何在那里应用过滤器,我会非常高兴,我无法让它工作。我也很确定某人在某个时候需要过滤嵌套列表中的一些值。因此更普遍的问题。 – titusn

回答

2

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

您可以从原始对象(如select,map(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 
+0

这听起来很有希望,我会试试看,然后回到这里。 – titusn

+0

是的,使用变量做了工作。事实证明,我以前的尝试也奏效了,但我在调用UpdateService操作时一直收到错误消息'发生错误(ClientException):系列包含无效字符.'显然,我刚刚做出了noob错误,并导致返回一个列表而不是一个单一的值。正则表达式的改进也是很好的一个。 – titusn

+0

出于好奇,你为什么在答复中写下我没有提供有效数据?我认为一切都在问题中,我只是匿名了我们的帐号和一些服务名称。 – titusn