如何使用Ansible找到一个免费的VPC CIDR块?

时间:2015-09-17 22:24:03

标签: python yaml ansible cidr vpc

我在AWS中有一套现有的VPC,每个都有自己的CIDR块:

vpc1:20.0.0.0/16 vpc2:20.10.0.0/16

现在,我正在尝试编写一个剧本,它会拉入现有的VPC列表,然后找到一个可用的CIDR(例如在上面的示例中,下一个可用的将是20.20.0.0 / 16,虽然我并不太关心保持顺序)。

我知道这样做可以使用两个列表:

- name: Loop over all possible CIDRs
    debug: msg="Found a free CIDR {{ item }}"
    with_items: all_potential_cidrs
    when: "\"{{ item }}\" not in {{ currently_used_cidrs }}"

但是,我获取现有CIDR列表的方式是:

- name: Get list of VPCs and their CIDR blocks
  command: aws ec2 describe-vpcs --output json
  register: cli_output

- name: Register variables
  set_fact:
  current_vpcs: "{{ cli_output.stdout | from_json }}"

该命令返回以下数据(采用JSON格式):

{
    "Vpcs": [
        {
            "VpcId": "vpc-4aad0c23",
            "InstanceTenancy": "default",
            "Tags": [
                {
                    "Value": "vpc1",
                    "Key": "Name"
                }
            ],
            "State": "available",
            "DhcpOptionsId": "dopt-ff6b238f",
            "CidrBlock": "20.0.0.0/16",
            "IsDefault": false
        },
        {
            "VpcId": "vpc-d4101abc",
            "InstanceTenancy": "default",
            "Tags": [
                {
                    "Value": "vpc2",
                    "Key": "Name"
                }
            ],
            "State": "available",
            "DhcpOptionsId": "dopt-eaaab38c",
            "CidrBlock": "20.10.0.0/16",
            "IsDefault": false
        }
    ]
}

允许获取所有CIDR块如下:

- name: Print filtered VPCs and their subnets
  debug: msg="VPC ID {{ item.VpcId }}, VPC CIDR block {{ item.CidrBlock }}"
  with_items: current_vpcs.Vpcs

但是," CidrBlock"是列表项的属性,我无法在"当"声明,需要一个List:

when: "{{ item }}" not in {{ list_of_cidrs }}"

我怎样才能选择" CidrBlock"每个" Vpcs"项目并将其转换为自己的列表,以便将其传递给"当:...不在......"声明?

1 个答案:

答案 0 :(得分:0)

您可以使用Jinja's map filter将VPC String列表转换为仅包含CIDR块的列表。

我不确定你想要完成什么这个剧本,但这里有一个例子,它允许你将“Vpcs”项目列表转换为item的{​​{1}}字符串列表每个vpc项目。

你可以看到它的工作原理:

CidrBlock

假设您设置了- name: Print just the CIDRS debug: msg='{{ current_vpcs.Vpcs|map(attribute="CidrBlock")|list }}' ,则上面的行输出

current_vpcs

完整的工作示例:

TASK: [Print just the CIDRS] **************************************************
ok: [localhost] => {
    "msg": "[u'20.0.0.0/16', u'20.10.0.0/16']"
 }

--- - name: ok hosts: localhost gather_facts: no vars: all_available_cidrs: - "20.0.0.0/16" - "20.10.0.0/16" - "20.20.0.0/16" tasks: - name: Get list of VPCs and their CIDR blocks command: aws ec2 describe-vpcs --output json register: cli_output - name: Register variables set_fact: current_vpcs: "{{ cli_output.stdout | from_json }}" - name: Print VPCs and their subnets debug: msg="VPC ID {{ item.VpcId }}, VPC CIDR block {{ item.CidrBlock }}" with_items: current_vpcs.Vpcs - name: extract list_of_cidrs into fact set_fact: list_of_cidrs: '{{ current_vpcs.Vpcs|map(attribute="CidrBlock")|list|to_json }}' - name: Print just the CIDRS debug: var=list_of_cidrs - name: Print available unused cidrs debug: msg="available unused VPC CIDR block {{ item }}" with_items: all_available_cidrs when: '"{{ item }}" not in {{ list_of_cidrs }}' 转换为列表current_vpcs.Vpcs的行是:

["20.0.0.0/16", "20.10.0.0/16"]

注意:有必要使用set_fact: list_of_cidrs: '{{ current_vpcs.Vpcs|map(attribute="CidrBlock")|list|to_json }}' 让Jinja正确模拟|list|to_json语句。 in返回一个生成器,其表示不能用作Jinja map语句的参数。可能有更简洁的方法来执行此操作,但使用in是人们在This ticket

中找到的解决方案

修改:添加变量|list|to_json以使完整示例更接近原始问题