在同一映射中交叉引用 Ansible 變數
如何定義一個 Ansible 變數,其值是同一映射結構中的另一個變數?
為了允許變數的合理命名空間,我定義了這樣的映射結構,其中一些值依賴於同一結構中的其他變數:
acme: directory: hostname: "acme-staging-v02.api.letsencrypt.org" letsencrypt: config_dir: "/etc/letsencrypt" keys_dir: "{{ letsencrypt.config_dir }}/keys" csrs_dir: "{{ letsencrypt.config_dir }}/csr" certs_dir: "{{ letsencrypt.config_dir }}/certs" accounts_dir: "{{ letsencrypt.config_dir }}/accounts" csr_file: "{{ letsencrypt.csrs_dir }}/{{ site_domain }}.csr" account_key_file: "{{ letsencrypt.csrs_dir }}/{{ acme.directory.hostname }}" email_address: "certificate-reminders@{{ site_domain }}"
這失敗了,因為 Ansible 無法解析在同一資料結構中引用其他值的值:
在模板字元串中檢測到遞歸循環:{{letsencrypt.config_dir }}/keys
所以我認為查找
vars
將允許推遲該解決方案:acme: directory: hostname: "acme-staging-v02.api.letsencrypt.org" letsencrypt: config_dir: "/etc/letsencrypt" keys_dir: "{{ lookup('vars', 'letsencrypt.config_dir') }}/keys" csrs_dir: "{{ lookup('vars', 'letsencrypt.config_dir') }}/csr" certs_dir: "{{ lookup('vars', 'letsencrypt.config_dir') }}/certs" accounts_dir: "{{ lookup('vars', 'letsencrypt.config_dir') }}/accounts" csr_file: "{{ lookup('vars', 'letsencrypt.csrs_dir') }}/{{ site_domain }}.csr" account_key_file: >- {{ lookup('vars', 'letsencrypt.csrs_dir') }}/{{ acme.directory.hostname }} email_address: "certificate-reminders@{{ site_domain }}"
這失敗了,因為 Ansible 正在嘗試立即解決該查找:
未找到具有此名稱的變數:letsencrypt.config_dir
當然我可以把它們分開,所以它們是單獨的變數。但是,這違背了我將強相關變數全部分組在同一個命名空間中的目的。
那麼什麼將允許我定義資料結構,以便某些值可以依賴於同一結構中的其他變數?
(感謝@michael-hampton 提供了這個答案。)
如Ansible 問題#8603中所述,配置解析器正在讀取變數值並立即嘗試呈現它在定義變數時遇到的模板。當模板引用尚未完全定義的變數時,這會導致解析失敗。
‘rquelibari’的評論給出了很好的分析:
這個特性實際上是明確定義的,就意味著一件事。對於這種“反向引用”,語法和語義(就邏輯而言)都得到了很好的定義。
$$ … $$
並詳細解釋這是如何發生的。
‘cmpunches’隨後的評論直接說明了所需的解決方案:
這個問題是 ansibles 使用 yaml 解析器的插值功能而不是載入 yaml 對象並進行第二次插值的直接結果。這不僅僅是一個 jinja 錯誤,這是 ansible 中的一個實現錯誤。請檢查。載入為原始字元串,然後在第二遍中處理初始化的對象成員應該可以解決這個問題。
因此,直到 Ansible 中的 YAML 解析器被更正以將變數值讀取為純文字而不嘗試立即渲染模板(因此推遲渲染直到所有變數都被定義),值中的這種交叉引用還不能在 Ansible 變數中完成.