从 Ansible 寄存器中选择特定数据
Selecting specific data from an Ansible register
我真的很感激能在 ansible 中正确 selecting 从寄存器中获取数据的帮助。
以下代码 almost 有效...:)
我这里创建一个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 }}'
这是它没有按预期工作的地方。
我假设寄存器将按照 defined/created 的顺序包含信息,但事实并非如此。
使用调试我可以看到这 4 个子网在寄存器中的顺序是随机的。例如在一次尝试中,"Public Subnet 2" 被 'vpc.subnets[0].id' 识别,而在另一次尝试中,"private Subnet 2" 是列表中的第一个。
有人可以建议我如何从寄存器可靠地重复 select "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"
}
}
类似这样的方法可能有效:
- 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
您也可以尝试如下编写子网过滤器:
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 和 uncomment the line 我们启用自定义 filter_plugins 的地方。该路径可以是相对的,ansible 将查找相对于 ansible.cfg 所在位置的插件。例如,我的 ansible.cfg 和所有插件都已签入我的 git 存储库。
编辑:
如果重构如下,您还可以删除自定义插件中的硬编码:
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') }}"
我真的很感激能在 ansible 中正确 selecting 从寄存器中获取数据的帮助。 以下代码 almost 有效...:)
我这里创建一个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 }}'
这是它没有按预期工作的地方。 我假设寄存器将按照 defined/created 的顺序包含信息,但事实并非如此。
使用调试我可以看到这 4 个子网在寄存器中的顺序是随机的。例如在一次尝试中,"Public Subnet 2" 被 'vpc.subnets[0].id' 识别,而在另一次尝试中,"private Subnet 2" 是列表中的第一个。
有人可以建议我如何从寄存器可靠地重复 select "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"
}
}
类似这样的方法可能有效:
- 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
您也可以尝试如下编写子网过滤器:
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 和 uncomment the line 我们启用自定义 filter_plugins 的地方。该路径可以是相对的,ansible 将查找相对于 ansible.cfg 所在位置的插件。例如,我的 ansible.cfg 和所有插件都已签入我的 git 存储库。
编辑:
如果重构如下,您还可以删除自定义插件中的硬编码:
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') }}"