Ansible: как построить переменную из другой переменной, а затем извлечь ее значение
Вот моя проблема: мне нужно использовать одну переменную 'target_host', а затем добавить к ней значение _host, чтобы получить другое имя переменной, значение которой мне нужно.
Если вы посмотрите на мою книгу. Задача nbr 1,2,3 извлекает значение переменной, однако nbr 4 не может делать то, что я ожидаю. Есть ли другой способ добиться того же в недоступном?
---
- name: "Play to for dynamic groups"
hosts: local
vars:
- target_host: smtp
- smtp_host: smtp.max.com
tasks:
- name: testing
debug: msg={{ target_host }}
- name: testing
debug: msg={{ smtp_host }}
- name: testing
debug: msg={{ target_host }}_host
- name: testing
debug: msg={{ {{ target_host }}_host }}
Output:
TASK: [testing] ***************************************************************
ok: [127.0.0.1] => {
"msg": "smtp"
}
TASK: [testing] ***************************************************************
ok: [127.0.0.1] => {
"msg": "smtp.max.com"
}
TASK: [testing] ***************************************************************
ok: [127.0.0.1] => {
"msg": "smtp_host"
}
TASK: [testing] ***************************************************************
ok: [127.0.0.1] => {
"msg": "{{{{target_host}}_host}}"
}
Ответы
Ответ 1
Вам нужно поставить кавычки вокруг него:
- hosts: local
vars: [ target_host: smtp ]
tasks:
debug: msg="{{ target_host }}_host"
- изменить -
Кашьяп Мне нужно пройти еще один уровень, чем это. Представьте, что есть другая переменная 'smtp_host', и я хочу построить эту переменную в время выполнения с использованием другой переменной (target_host) и присоединение строки "_host". = {{{{target_host}} _ host}} - Макс
Мой плохой. Не читал достаточно внимательно.
Это (AFAIK) невозможно. Основное ограничение, которое мешает нам это делать (независимо от того, как вы его закручиваете), является "переменным расширением" в ansible - это однопроходный процесс, а для чего требуется несколько проходов.
Только [серьезные хакки], о которых я могу думать, следующие:
- Создайте динамическую книгу с помощью
template
и выполните ее.
- Я слышал, что двигатель Jinja2 выполняет многопроходную оценку. Может быть, если вы поместите эти строки в шаблон, а затем используйте фильтр
lookup('template', ...)
. К сожалению, у меня нет опыта работы с шаблонами Jinja2, поэтому не совсем уверен, что это даже вариант.
Ответ 2
Если у вас есть переменная типа
vars:
myvar: xxx
xxx_var: anothervalue
рабочий синтаксис:
- debug: msg={{ vars[myvar + '_var'] }}
предоставит вам аналог:
- debug: msg={{ xxx_var }}
Ответ 3
Вы можете использовать "hostvars" для передачи переменной, данные хоста могут быть загружены из групповых варов или хостов vars
ут
---
- name: "Play to for dynamic groups"
hosts: x0
vars:
- target_host: smtp
tasks:
- set_fact: smtp_host="smtp.max.com"
- set_fact: host_var_name={{target_host}}_host
- set_fact: dym_target_host={{hostvars[inventory_hostname][host_var_name]}}
- name: testing
debug: msg={{ target_host }}
- name: testing
debug: msg={{ smtp_host }}
- name: testing
debug: msg={{ target_host }}_host
- name: testing
debug: msg={{ dym_target_host }}
выход:
PLAY [Play to for dynamic groups] *********************************************
GATHERING FACTS ***************************************************************
ok: [x0]
TASK: [set_fact smtp_host="smtp.max.com"] *************************************
ok: [x0]
TASK: [set_fact host_var_name=smtp_host] **************************************
ok: [x0]
TASK: [set_fact dym_target_host={{hostvars[inventory_hostname][host_var_name]}}] ***
ok: [x0]
TASK: [testing] ***************************************************************
ok: [x0] => {
"msg": "smtp"
}
TASK: [testing] ***************************************************************
ok: [x0] => {
"msg": "smtp.max.com"
}
TASK: [testing] ***************************************************************
ok: [x0] => {
"msg": "smtp_host"
}
TASK: [testing] ***************************************************************
ok: [x0] => {
"msg": "smtp.max.com"
}
PLAY RECAP ********************************************************************
x0 : ok=8 changed=0 unreachable=0 failed=0
Ответ 4
В настоящее время я использую синтаксис типа Jinja 2. Я не думаю, что это отличное решение, но мне еще нужно найти что-то лучшее.
Позвольте мне привести пример с одной из моих абстрактных задач. См. Мою конфигурационную конфигурацию и примерную задачу ниже:
# Variables file, available in the task context
containers:
app:
image: mynamespace/myappcontainer:snapshot
web:
image: nginx:latest
db:
image: mariadb:latest
# Example task
- name: Start containers
docker_container:
name: "{{ item }}"
image: "{{ containers[item].image }}"
with_items:
- app
- web
- db
В приведенном выше примере я использую with_items
Ansible loop, который запускает задачу для каждого элемента и делает {{ item }}
переменная, доступная соответственно.
Это приводит к созданию 3 контейнеров Docker, каждый из которых имеет правильное имя контейнера, основанное на списке элементов, и правильное изображение, полученное из внешних переменных, которые я настроил.
Даже если этот пример использует with_items
, он, конечно, адаптируется к вашей проблеме с использованием ваших собственных переменных.
Хотя в этой ситуации это прекрасно работает, я боюсь, для этого нужны переменные, к которым вы хотите получить доступ, чтобы быть частью некоторой родительской переменной (containers
в этом примере). Поэтому я бы рекомендовал разделить переменные с помощью .
для построения иерархии, а не с помощью _
.
Переменная типа a.b.c
, где b
является динамической, будет доступна с помощью a[b].c
.
Переменная типа a.b
, где b
является динамической, будет доступна с помощью a[b]
.
Решение, которое вы использовали бы, может выглядеть как (untested):
- name: "Play to for dynamic groups"
hosts: local
vars:
- target: smtp
- hosts:
smtp: smtp.max.com
imap: imap.max.com
tasks:
- name: testing
debug: msg={{ hosts[target] }}
Обратите внимание, что переменные настроены несколько иначе, потому что структура иерархическая.
Ответ 5
У вас есть два способа выбора:
1. Общее использование.
vars:
- target_host: smtp
- smtp: smtp.max.com
tasks:
- name: testing
debug: msg={{ target_host }}
- name: testing
debug: msg={{ smtp }}
- name: testing
debug: msg={{ vars[target_host] }}
2. Используя факт
tasks:
- set_fact: target_host=smtp
- set_fact: smtp=smtp.max.com
- name: testing
debug: msg={{ target_host }}
- name: testing
debug: msg={{ smtp }}
- name: testing
debug: msg={{hostvars[inventory_hostname][target_host]}}
Ответ 6
Вы можете вложить свои поиски так:
---
- hosts: local
connection: local
gather_facts: no
vars:
target_host: smtp
lookup_host: "{{ target_host }}_host"
smtp_host: smtp.max.com
tasks:
- debug: var="{{ lookup_host }}"
Ответ 7
Мне кажется, вы можете просто использовать опцию var
вместо msg
:
debug: var="{{ target_host }}_host"
дает:
TASK [testing] ********************************************************************************************************************************
ok: [localhost] => {
"smtp_host": "smtp.max.com"
}
Ответ 8
Есть много ответов выше. Это мне очень помогло. Но я не нашел ни одного ответа, как сохранить эти переменные в файле vars-> main.yml. Поэтому вам нужно создать словарь в файле vars-> main.yml.
vars → main.yml file
cassandra_version: 2.1.16
file_sha_cassandra: "apache-cassandra-{{ cassandra_version }}_sha256"
# Create Dictionary here
cassandra:
apache-cassandra-2.1.16_sha256: "sha256: checksum_of_file"
##Add more variable
Теперь вам нужно вызвать это в файле task → main.yml:
---
- name: Down load Cassandra Binaries
get_url:
url: "file_url"
dest: "{{ base_directory }}"
checksum: "{{ cassandra[file_sha_cassandra] }}"
timeout: 800
Ответ 9
Вы можете попробовать глобальный массив var:
regions:
us-east-1:
endpoint: rds.us-east-1.amazonaws.com
cn-north-1:
endpoint: rds.cn-north-1.amazonaws.com.cn
cn-northwest-1:
endpoint: rds.cn-northwest-1.amazonaws.com.cn
И используйте его, чтобы получить значение в зависимости от другого:
region_endpoint: "{{ regions[region].endpoint}}"
В вашем случае:
target_host:
imap:
host: imap.max.com
smtp:
host: smtp.max.com
затем:
region_endpoint: "{{ target_host[service].host}}"