Подтвердить что ты не робот

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}}"
}
4b9b3361

Ответ 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}}"