如何使用 Ansible 找到免费的 VPC CIDR 块?
How to find a free VPC CIDR block with Ansible?
我在 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" 是列表项的 属性,我无法在 "when" 语句中使用它,这需要一个列表:
when: "{{ item }}" not in {{ list_of_cidrs }}"
我如何获取每个 "Vpcs" 项目的 "CidrBlock" 属性 并将其变成它自己的列表,以便将其传递给 "when: ... not in ..."声明?
您可以使用 Jinja's map filter.
将 VPC item
的列表变成仅包含 CIDR 块的列表
我不太确定您要完成此剧本的内容,但这里有一个示例,可让您将 "Vpcs" 项列表转换为 [=每个 vpc 项目的 15=]。
您可以看到它正在运行:
- 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 }}'
注意:有必要使用|list|to_json
让Jinja正确地模板化in
语句。 map
returns 一个生成器,其表示不能用作 Jinja in
语句的参数。可能有更简洁的方法来执行此操作,但使用 |list|to_json
是人们在 This ticket
中找到的解决方案
编辑:添加变量all_available_cidrs
以使完整示例更接近原始问题
我在 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" 是列表项的 属性,我无法在 "when" 语句中使用它,这需要一个列表:
when: "{{ item }}" not in {{ list_of_cidrs }}"
我如何获取每个 "Vpcs" 项目的 "CidrBlock" 属性 并将其变成它自己的列表,以便将其传递给 "when: ... not in ..."声明?
您可以使用 Jinja's map filter.
将 VPCitem
的列表变成仅包含 CIDR 块的列表
我不太确定您要完成此剧本的内容,但这里有一个示例,可让您将 "Vpcs" 项列表转换为 [=每个 vpc 项目的 15=]。
您可以看到它正在运行:
- 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 }}'
注意:有必要使用|list|to_json
让Jinja正确地模板化in
语句。 map
returns 一个生成器,其表示不能用作 Jinja in
语句的参数。可能有更简洁的方法来执行此操作,但使用 |list|to_json
是人们在 This ticket
编辑:添加变量all_available_cidrs
以使完整示例更接近原始问题