因此,我正在运行一个 ansible 角色,该角色在 defaults/role 文件夹中有一个文件 main.yml。该文件的内容如下:
---
api_secrets:
'API_PROFILE': "{{ api_profile }}"
'SERVER_ADDRESS': "{{ server_address }}"
'MGMT_SERVER_ADDRESS': "{{ management_server_address }}"
现在我想将其添加到 api_secrets 块中,在管理服务器地址像这样:
{% if '"port" in mgmt_ports' %}
'MGMT_SERVER_PORT': "{{ management_server_port1 }}"
'MGMT_SERVER_USER': "{{ user1 }}"
{% else %}
'MGMT_SERVER_PORT': "{{ management_server_port2 }}"
'MGMT_SERVER_USER': "{{ user2 }}"
{% endif %}
完成此处的所有内容后,将在服务器上创建一个包含上述内容的文件,当然还会用变量的实际值替换它们。
无论我如何尝试,它总是会导致不同的错误。我尝试使用“{% if ... endif %}”,也尝试使用“”
错误可能是这样的:
ERROR! Syntax Error while loading YAML.
found character that cannot start any token
The error appears to be in '/opt/ansible/roles/api/defaults/main.yml': line 55, column 2, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
{% if '"port" in mgmt_ports' %}
^ here
我也尝试过这样的方法:
"{% if (port in mgmt_ports) %}
'MGMT_SERVER_PORT': "{{ management_server_port1 }}"
{% else %}
'MGMT_SERVER_PORT': "{{ management_server_port2 }}"
{% endif %}"
在这种情况下,错误是:
ERROR! Syntax Error while loading YAML.
could not find expected ':'
The error appears to be in '/opt/ansible/roles/api/defaults/main.yml': line 56, column 24, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
"{% if (port in mgmt_ports) %}
'MGMT_SERVER_PORT': "{{ management_server_port1 }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
正确的做法是什么?
我知道使用 jinja2 模板会更容易,但是剧本就是这样创建的,我必须坚持使用这种方法。
答案1
变量的模板化发生在 YAML 解析步骤之后,因此您不能以这种方式使用它来模板化 YAML。
最简单的方法是将条件移到各个 Jinja 表达式中:
api_secrets:
API_PROFILE: "{{ api_profile }}"
SERVER_ADDRESS: "{{ server_address }}"
MGMT_SERVER_ADDRESS: "{{ management_server_address }}"
MGMT_SERVER_PORT: "{{ management_server_port1 if 'port' in mgmt_ports else management_server_port2 }}"
MGMT_SERVER_USER: "{{ user1 if 'port' in mgmt_ports else user2 }}"
您也可以使用 Jinja 语句,尽管这会使相同结果的值稍微长一些。
api_secrets:
API_PROFILE: "{{ api_profile }}"
SERVER_ADDRESS: "{{ server_address }}"
MGMT_SERVER_ADDRESS: "{{ management_server_address }}"
MGMT_SERVER_PORT: "{% if 'port' in mgmt_ports %}{{ management_server_port1 }}{% else %}{{ management_server_port2 }}{% endif %}"
MGMT_SERVER_USER: "{% if 'port' in mgmt_ports %}{{ user1 }}{% else %}{{ user2 }}{% endif %}"
答案2
Ansible 不适用于处理 If-Else 语句。
正如您在问题底部提到的那样,使用 jinja2 模板会更容易,但它不仅会更容易,而且还会使其成为正确的方法。
因此,不要试图用 if-else 语句弄乱你的 yaml 文件,而是创建一个带有所需模板参数的 jinja2 文件(看起来你已经获得了 jinja2 模板结构!)并使用该文件创建一个配置文件。
然后,您可以执行模板命令,将模板使用正确的参数包含在正确的位置。
“剧本就是这样制定的,我必须坚持这种方法”大喊,无论是谁想出这个政策,要么没有安全感,要么就是个孩子。