Выбор конкретных данных из регистра Ansible
Буду очень признателен за помощь в правильном выборе данных из регистра в 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
Это хорошо работает. Создает VPC с 4 подсетями. Затем я хочу запустить экземпляр 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 подсети расположены в случайном порядке в регистре. например, с одной попытки "Public Subnet 2" была идентифицирована "vpc.subnets[0].id", а с другой попытки "private Subnet 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 ответа
Нечто подобное может работать:
- 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 и раскомментируйте строку, в которой мы включаем пользовательские 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') }}"