Словарь Ansible: неявная оценка всех значений? - PullRequest
1 голос
/ 16 мая 2019

Я немного озадачен поведением Ansible: похоже, когда я запрашиваю значение одного ключа, он оценивает все значения в словаре.

Вот мой случай. У меня есть словарь с двумя ключами: dev и prod. Значение каждого ключа определяется с помощью специального выражения Jinja2, которое включает в себя дешифрование с использованием AWS KMS. Примерно это выглядит так:

mydict:
  dev: '{{ "dev-ciphertext" | kms_decrypt }}'
  prod: '{{ "prod-ciphertext" | kms_decrypt }}'

kms_decrypt - это пользовательский фильтр, который расшифровывает зашифрованный текст. Поскольку среды dev и prod разделены, а книга воспроизведения работает в контексте шифрования, действительном только для одной из этих сред, можно оценить только одно выражение за один раз . Попытка получить значение из другого ключа завершится неудачей.

Итак, допустим, что playbook работает в контексте dev, и когда я оцениваю mydict['dev'], я ожидаю, что он вернет расшифрованный dev-ciphertext. Однако на самом деле я получаю ошибку при дешифровании prod-ciphertext, поскольку контекст шифрования не совпадает.

Я могу проиллюстрировать то же поведение в более простом примере. Вместо того, чтобы воссоздавать механизм дешифрования, я просто определил одно из значений словаря через неопределенную переменную:

- hosts: localhost
  become: no
  vars:
    dev_value: '123'
    mydict:
     dev: '{{ dev_value }}'
     prod: '{{ prod_value }}'
  tasks:
    - debug:
        msg: "{{ mydict['dev'] }}"

Несмотря на то, что mydict['prod'] никогда не запрашивается явным образом, я все равно получаю сообщение об ошибке, указывающее, что его невозможно оценить:

TASK [debug] *********************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'prod_value' is undefined\n\nThe error appears to have been in 'ansible/test.yml': line 9, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - debug:\n      ^ here\n"}

Я понимаю, что существует множество способов обойти эту проблему, но кто-нибудь может объяснить, почему значения всего словаря оцениваются, когда запрашивается только один ключ? Это не имеет смысла для меня - по крайней мере, с точки зрения производительности.

1 Ответ

1 голос
/ 16 мая 2019

Шаблоны Jinja отображаются при любых обстоятельствах - нет такой вещи, как "lazy jinja", только отложенные задачи через when: или аналогичные средства защиты

Так что, если у вас еще нет my_dict["dev"] разбросаны по всему коду, тогда я бы предложил использовать разумное имя, например my_env или что-то подобное, и объявить только одно значение, которое имеет значение для активной среды:

- hosts: localhost
  become: no
  vars:
    dev_value: '123'
  tasks:
  - set_fact:
      my_env: '{{ "prod-ciphertext" | kms_decrypt }}'
    when: some_environment_variable == "prod"
  - set_fact:
      my_env: '{{ "dev-ciphertext" | kms_decrypt }}'
    when: some_environment_variable == "dev"

В противном случае вы можете защититьвыражения - которые для ясности всегда будут оцениваться - возвращают значения по умолчанию, если они неприменимы:

- hosts: localhost
  become: no
  vars:
    dev_value: '123'
    my_dict:
      prod: '{{ ("prod-ciphertext" | kms_decrypt)
               if the_magic_env == "prod" else {} }}'
      dev: '{{ ("dev-ciphertext" | kms_decrypt)
               if the_magic_env == "dev" else {} }}'
  tasks:
    - debug:
        msg: "{{ mydict['dev'] }}"
...