【问题标题】:Apply when conditional to nested lists with Ansible, not just to top-level one在有条件的情况下应用于使用 Ansible 的嵌套列表,而不仅仅是顶级列表
【发布时间】:2020-04-08 13:23:34
【问题描述】:

所以我遇到了 Ansible + AWS EC2 这个致命问题。

如果磁盘类型为“io1”,则应指定“iops”,否则不应指定。 如果我想让磁盘类型可配置,我必须在何时申请,但它不起作用:

- name: Provision AWS Instances
  ec2:
    instance_type: "{{ ec2_instance_type }}"
    image: "{{ ec2_ami_id }}"
    ...
    volumes:
      - device_name: "{{ ec2_root_disk_name }}"
        volume_type: "{{ ec2_root_disk_type }}"
        volume_size: "{{ ec2_root_disk_size }}"
        delete_on_termination: "{{ ec2_root_disk_delete_on_termination }}"
        iops: "{{ ec2_root_disk_iops }}"
        when: ec2_root_disk_type == 'io1'
      - device_name: "{{ ec2_root_disk_name }}"
        volume_type: "{{ ec2_root_disk_type }}"
        volume_size: "{{ ec2_root_disk_size }}"
        delete_on_termination: "{{ ec2_root_disk_delete_on_termination }}"
        when: ec2_root_disk_type != 'io1'

但是,这个嵌套的“when”条件没有被处理,驱动器被添加了两次:

"volumes": [
    {
        "delete_on_termination": "true", 
        "device_name": "/dev/sda1", 
        "iops": "100", 
        "volume_size": "30", 
        "volume_type": "gp2", 
        "when": "ec2_root_disk_type == 'io1'"
    }, 
    {
        "delete_on_termination": "true", 
        "device_name": "/dev/sda1", 
        "volume_size": "30", 
        "volume_type": "gp2", 
        "when": "ec2_root_disk_type != 'io1'"
    }, 
]

我可以在整个命令中添加“何时”,但我最多可以有 5 个驱动器,所以这意味着复制它超过 32 次。

是否可以在嵌套列表上使 Ansible 进程“何时”?

是否可以将这个列表组装到一个变量中,在这个命令中引用它? Ansible 的文档对非字符串的结构化变量保持沉默。也许我可以以某种方式应用集合过滤?

这里推荐的行动方案是什么?我想每个人在尝试创建可配置类型的卷时都会遇到这个确切的问题。

【问题讨论】:

    标签: amazon-ec2 scripting ansible


    【解决方案1】:

    在库存中指定卷,而不是在剧本中。

    例如,group_vars/with_iops.yml 文件:

    volumes:
      - device_name: "{{ ec2_root_disk_name }}"
        volume_type: "{{ ec2_root_disk_type }}"
        volume_size: "{{ ec2_root_disk_size }}"
        delete_on_termination: "{{ ec2_root_disk_delete_on_termination }}"
        iops: "{{ ec2_root_disk_iops }}"
    

    group_vars/without_iops.yml 文件:

    volumes:
      - device_name: "{{ ec2_root_disk_name }}"
        volume_type: "{{ ec2_root_disk_type }}"
        volume_size: "{{ ec2_root_disk_size }}"
        delete_on_termination: "{{ ec2_root_disk_delete_on_termination }}"
    

    剧情:

    - name: Provision AWS Instances
      ec2:
        instance_type: "{{ ec2_instance_type }}"
        image: "{{ ec2_ami_id }}"
        ...
        volumes: "{{ volumes }}"
    

    【讨论】:

    • 这看起来很有趣,但现在我有两个配置文件。我无法从 yml 获取变量(可以吗?)所以我基本上需要进行两次配置。
    • 是的,您有两个配置文件:一个用于需要 iops 的主机组,一个用于不需要 iops 的主机组。是的,这些组中的主机可以访问这些 yaml 文件中的变量。
    • 我想我可以在一个 .yml 文件中列出所有磁盘 如何从 jinja2 引用给定的卷?例如。我可以做 {{ volumes[1].volume_size }} 等吗?
    • 仅仅因为你可以做某事并不意味着它是一个好主意。您有一些需要 iops 的主机,而另一些则不需要,对吗?
    • 不,我想通过 group_vars 使其完全可配置
    【解决方案2】:

    您可以使用内联条件,例如:

    - device_name: "{{ ec2_root_disk_name }}"
      volume_type: "{{ ec2_root_disk_type }}"
      volume_size: "{{ ec2_root_disk_size }}"
      delete_on_termination: "{{ ec2_root_disk_delete_on_termination }}"
      iops: "{{ ec2_root_disk_iops if ec2_root_disk_type == 'io1' }}"
    

    【讨论】:

    • 很好,但我也可以将整个设备(列表项)设为可选吗?我想要可选的驱动器。我一定会检查那个。
    • 如果我执行ec2_root_disk_iops if ec2_root_disk_type == 'io1' else '',则结果 JSON 中仍然存在属性,并且 AWS 调用仍然失败。如果我做else 0,仍然失败。如果 type != 'io1',AWS 根本不需要这个属性。
    【解决方案3】:

    我实际上已经在我的剧本的library/action_plugins/ 中添加了一个空的自定义python 模块和一个相应的动作插件。在这个插件中,我通过形成我需要的卷列表来处理输入参数,并使用改进的参数调用ec2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多