Ansible
來自 JSON 格式的 Ansible jinja2 模板作為額外變數提供
我有這個 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 -%}
一個帶有 yaml 文件vhosts.ym l 的 ansible 角色,其中包含如下定義:
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'
我也嘗試過使用循環而不是with_items但沒有運氣。
我了解在使用額外變數時,提供的內容是 JSON 格式,但我無法找到另一種方法將 vhosts.yml 中的內容作為單個條目的額外變數傳遞。有什麼辦法可以使它起作用嗎?
也許有更好的方法嗎?
您正在傳遞一個對象/字典,但您的程式碼需要一個列表。您需要在傳入時將其包裝在列表中,或者在使用時考慮不同的可能結構。
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