从Ansible寄存器中选择特定数据

时间:2015-04-16 09:14:47

标签: amazon-web-services amazon-ec2 ansible vpc

我非常感谢有关正确选择ansible寄存器数据的一些帮助。 以下代码几乎有效...... :)

我在这里创建了一个AWS VPC,我在'vpc'中注册了这些信息。 然后我参考vpc。

  - name: Create VPC and Subnets
    ec2_vpc:
      state: present
      cidr_block: '{{ ip-range}}'
      resource_tags: { "Name": "{{ vpc_name }}" }
      region: '{{ region }}'
      subnets:
        - cidr: '{{ pub-subneta }}'
          az: '{{ region }}a'
          resource_tags: { "Name": "Public Subnet 1" }

        - cidr: '{{ pub-subnetb }}'
          az: '{{ region }}b'
          resource_tags: { "Name": "Public Subnet 2" }

        - cidr: '{{ priv-subnet1 }}'
          az: '{{ region }}a'
          resource_tags: { "Name": "Private Subnet 1" }

        - cidr: '{{ priv-subnet2 }}'
          az: '{{ region }}b'
          resource_tags: { "Name": "Private Subnet 2" }
      internet_gateway: True
    register: vpc

效果很好。它使用4个子网创建VPC。 然后,我想在特定的子网中启动一个NAT实例,我尝试通过如下指定子网来实现:

- name: Create NAT instance
  ec2:
    state: present
    key_name: '{{ ssh_key_name }}'
    instance_type: '{{ nat_instance_type }}'
    image: '{{ nat_ami }}'
    region: '{{ region }}'
    wait: yes
    instance_tags:
      Name: "natsrv01"
      Description: "NAT Server"
    assign_public_ip: yes
    source_dest_check: false
    vpc_subnet_id: '{{ vpc.subnets[0].id }}'

这是它无法正常工作的地方。 我假设寄存器将按照定义/创建的顺序包含信任,但事实并非如此。

使用调试我可以看到4个子网在寄存器中是随机顺序。例如在一次尝试中,“公共子网2”由'vpc.subnets [0] .id'标识,而在另一次尝试中,“私有子网2”是列表中的第一个。

有人可以建议我如何可靠和安全请从寄存器中反复选择“Public Subnet 1”?

vpc寄存器的完整输出是:

 ok: [localhost] => {
 "vpc": {
     "changed": true,
     "invocation": {
         "module_args": "",
         "module_name": "ec2_vpc"
     },
     "subnets": [
         {
             "az": "eu-west-1b",
             "cidr": REDACTED,
             "id": "subnet-REDACTED",
             "resource_tags": {
                 "Name": "Private Subnet B"
             }
         },
         {
             "az": "eu-west-1c",
             "cidr": REDACTED,
             "id": "subnet-REDACTED",
             "resource_tags": {
                 "Name": "Private Subnet C"
             }
         },
         {
             "az": "eu-west-1a",
             "cidr": REDACTED,
             "id": "subnet-REDACTED",
             "resource_tags": {
                 "Name": "Public Subnet A"
             } 
         },
         {
             "az": "eu-west-1c",
             "cidr": REDACTED,
             "id": "subnet-REDACTED",
             "resource_tags": {
                 "Name": "Public Subnet C"
             }
         },
         {
             "az": "eu-west-1b",
             "cidr": REDACTED,
             "id": "subnet-REDACTED",
             "resource_tags": {
                 "Name": "Public Subnet B"
             }
         },
         {
             "az": "eu-west-1a",
             "cidr": REDACTED,
             "id": "subnet-REDACTED",
             "resource_tags": {
                 "Name": "Private Subnet A"
             }
         }
     ], 
     "vpc": {
         "cidr_block": "REDACTED",
         "dhcp_options_id": "dopt-53eb0f36",
         "id": "vpc-REDACTED",
         "region": "eu-west-1",
         "state": "pending"
     },
     "vpc_id": "vpc-REDACTED"
 }
}

2 个答案:

答案 0 :(得分:2)

这样的事可能有用:

- name: Find the first public subnet
  set_fact: vpc_subnet_id="{{ item.id }}"
  when: item.resource_tags.Name == "Public Subnet 1"
  with_items: vpc.subnets

答案 1 :(得分:2)

您还可以尝试编写子网过滤器,如下所示:

vpc_subnet_id: "{{ vpc.subnets | subnet_name_filter() }}"

使用以下方法创建文件/ansible_plugins/filter_plugins/core.py:

def subnet_name_filter(list):
  return [x for x in list if x.resource_tags.Name == "Public Subnet 1"]

class FilterModule(object):
  def filters(self):
    return {          
      'subnet_name_filter': subnet_name_filter
    }

编辑ansible.cfg,以及我们启用自定义filter_plugins的uncomment the line。该路径可以是相对的,并且ansible将查找相对于找到ansible.cfg的位置的插件。我有我的ansible.cfg,并且所有插件都已检入我的git repo中。例如。

编辑:

如果你重构,你也可以删除自定义插件中的硬编码:

def subnet_name_filter(list, restagname):
  return [x for x in list if x.resource_tags.Name == restagname]

并使用

vpc_subnet_id: "{{ vpc.subnets | subnet_name_filter('Public Subnet 1') }}"