Шаблон Ansible jinja2 из формата JSON предоставляется как дополнительные-vars

У меня есть этот шаблон jinja2:

# {{ ansible_managed }}

{% for vhost in nginx_vhosts %}
{%- if vhost.name == item.name -%}

# redirect www to non-www
server {
    listen {{ nginx_port }};
    listen [::]:{{ nginx_port }};
    port_in_redirect off;

    server_name www.{{ vhost.name }};
    return 301 http://{{ vhost.name }}$request_uri;
}
{%- endif -%}
{%- endfor -%}

Роль ansible с файлом yaml vhosts.ym l, содержащая такие определения:

nginx_vhosts:
      - name: "test1.com"
        repo: "git1"
        branch: master
        state: present
      - name: "test2.com"
        repo: "git2"
        branch: master
        state: present
...
      - name: "test101.com"
        repo: "git101"
        branch: master
        state: present

Задача внутри playbook.yml:

- name: "Generate nginx vhost configuration file"
  template:
    src: templates/nginx-vhost-template.j2
    dest: "{{ nginx_vhosts_dir }}/{{ item.name }}.conf"
    owner: "{{ nginx_user }}"
    group: "{{ nginx_group }}"
    mode: 0640
  with_items:
    - "{{ nginx_vhosts }}"
  when:
    - item.state == 'present'
  notify:
    - nginx-restart

Я запустил такс, например :

ansible-playbook -l web1 playbook.yml --tags=nginx-vhost-config

, который работает нормально, он создаст из шаблона файл конфигурации nginx vhost на удаленном сервере как domain1.com.conf и так далее для всех найденных определений.

Предполагая, что в файле vhosts.yml у меня есть test1.com до test100.com, я добавлю, скажем, test101.com и хочу запускать задачи строго для этого test101.com, а не для всех предыдущих хостов. Поэтому я попробовал что-то вроде этого :

ansible-playbook -l web1 playbook.yml --tags=nginx-vhost-config -e "{ 'nginx_vhosts': { 'name': 'test101.com', 'state': 'present', 'repo': 'git101', 'branch': 'master' }}"

. Проблема в том, что это приводит к ошибке при попытке заменить значения из шаблона jinja2.

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.errors.AnsibleUndefinedVariable: 'ansible.parsing.yaml.objects.AnsibleUnicode object' has no attribute 'name'

Я также пытался использовать цикл вместо с _элементами , но безуспешно.

Я понимаю, что при использовании дополнительных-переменных предоставляемое содержимое предоставляется в формате JSON, но я не смог найти другого способа передать содержимое из vhosts.yml в качестве дополнительных переменных для одной записи. Есть ли способ сделать это функциональным?

Возможно, есть лучший подход?

0
задан 7 October 2021 в 06:11
1 ответ

Вы передаете объект/словарь, но ваш код ожидает список. Вам нужно либо обернуть его в список, когда вы его передаете, либо учитывать различные возможные структуры при его использовании.

Сначала вам следует уменьшить количество мест, ссылающихся на nginx_vhosts, используя текущий элемент цикла непосредственно в вашем шаблоне:

# {{ ansible_managed }}

# redirect www to non-www
server {
    listen {{ nginx_port }};
    listen [::]:{{ nginx_port }};
    port_in_redirect off;

    server_name www.{{ item.name }};
    return 301 http://{{ item.name }}$request_uri;
}

Затем вы можете немного изменить структуру, которую вы передаете:

"{ 'nginx_vhosts': [{ 'name': 'test101.com', 'state': 'present', 'repo': 'git101', 'branch': 'master' }]}"

Или изменить ваш цикл немного:

- name: "Generate nginx vhost configuration file"
  template:
    src: templates/nginx-vhost-template.j2
    dest: "{{ nginx_vhosts_dir }}/{{ item.name }}.conf"
    owner: "{{ nginx_user }}"
    group: "{{ nginx_group }}"
    mode: "0640"
  loop: "{{ [ nginx_vhosts ] | flatten }}"
  when:
    - item.state == 'present'
  notify:
    - nginx-restart
1
ответ дан 7 October 2021 в 13:25

Теги

Похожие вопросы