在 ansible 模板化 yaml 中使用 jinja if 子句(通过模板查找)

Using jinja if clause in ansible templated yaml (through template lookup )

我使用带有动态定义的 ansible k8s 模块,我用

调用它
- name: install some tool
  k8s:
    state: present
    definition: "{{ lookup('template', '{{item}}') }}"
    context: "{{ cluster_name}}"
  loop:
    - "tool_template.yaml"

并且在模板中,我希望有一个条件块使用来自 ansible 角色的变量(is_major 在这种情况下)

metadata:
      labels:
        app: tool_name

      {% if is_major | bool %}
      annotations:
        ad.datadoghq.com/container.check_names: '["openmetrics"]'
        ad.datadoghq.com/container.init_configs: '[{}]'
        ad.datadoghq.com/container.instances: |
          [{
          "prometheus_url": "http://pathto:port/,
          "namespace": "myapp",
          "metrics": ["somemetric*"]
          }]
      {% endif %}

不幸的是,这会引发一个可靠的异常,并且在文档中找不到关于如何做到这一点的线索(至少在最近的文档中)可能是我正在制作 yaml 模板的事实。所以搜索 solution/workaround

ansible 版本 2.9

编辑:完整错误(带有 vvv)

The full traceback is:
    Traceback (most recent call last):
File "/home/username/.ansible/tmp/ansible-tmp-1588716858.967364-29993-207569799864998/AnsiballZ_k8s.py", line 102, in <module>
    _ansiballz_main()
    File "/home/username/.ansible/tmp/ansible-tmp-1588716858.967364-29993-207569799864998/AnsiballZ_k8s.py", line 94, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
    File "/home/username/.ansible/tmp/ansible-tmp-1588716858.967364-29993-207569799864998/AnsiballZ_k8s.py", line 40, in invoke_module
    runpy.run_module(mod_name='ansible.modules.clustering.k8s.k8s', init_globals=None, run_name='__main__', alter_sys=True)
    File "/home/username/.pyenv/versions/3.6.6/lib/python3.6/runpy.py", line 205, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
    File "/home/username/.pyenv/versions/3.6.6/lib/python3.6/runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
    File "/home/username/.pyenv/versions/3.6.6/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
    File "/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/modules/clustering/k8s/k8s.py", line 279, in <module>
    File "/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/modules/clustering/k8s/k8s.py", line 275, in main
    File "/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/module_utils/k8s/raw.py", line 145, in __init__
    File "/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/module_utils/k8s/raw.py", line 145, in <listcomp>
    File "/home/username/.local/lib/python3.6/site-packages/yaml/__init__.py", line 130, in load_all
    yield loader.get_data()
    File "/home/username/.local/lib/python3.6/site-packages/yaml/constructor.py", line 37, in get_data
    return self.construct_document(self.get_node())
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 27, in get_node
    return self.compose_document()
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 55, in compose_document
    node = self.compose_node(None, None)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 84, in compose_node
    node = self.compose_mapping_node(anchor)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 133, in compose_mapping_node
    item_value = self.compose_node(node, item_key)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 84, in compose_node
    node = self.compose_mapping_node(anchor)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 133, in compose_mapping_node
    item_value = self.compose_node(node, item_key)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 84, in compose_node
    node = self.compose_mapping_node(anchor)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 133, in compose_mapping_node
    item_value = self.compose_node(node, item_key)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 84, in compose_node
    node = self.compose_mapping_node(anchor)
    File "/home/username/.local/lib/python3.6/site-packages/yaml/composer.py", line 127, in compose_mapping_node
    while not self.check_event(MappingEndEvent):
    File "/home/username/.local/lib/python3.6/site-packages/yaml/parser.py", line 98, in check_event
    self.current_event = self.state()
    File "/home/username/.local/lib/python3.6/site-packages/yaml/parser.py", line 428, in parse_block_mapping_key
    if self.check_token(KeyToken):
    File "/home/username/.local/lib/python3.6/site-packages/yaml/scanner.py", line 116, in check_token
    self.fetch_more_tokens()
    File "/home/username/.local/lib/python3.6/site-packages/yaml/scanner.py", line 223, in fetch_more_tokens
    return self.fetch_value()
    File "/home/username/.local/lib/python3.6/site-packages/yaml/scanner.py", line 579, in fetch_value
    self.get_mark())
    yaml.scanner.ScannerError: mapping values are not allowed here
    in "<unicode string>", line 18, column 24:
    annotations:
    ^
    failed: [localhost] (item=aks/monitor/datadog/datadog-agent-daemonset.yaml) => {
        "ansible_loop_var": "item",
        "changed": false,
        "item": "aks/monitor/datadog/datadog-agent-daemonset.yaml",
        "module_stderr": "Traceback (most recent call last):\n  File \"/home/username/.ansible/tmp/ansible-tmp-1588716858.967364-29993-207569799864998/AnsiballZ_k8s.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/home/username/.ansible/tmp/ansible-tmp-1588716858.967364-29993-207569799864998/AnsiballZ_k8s.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/username/.ansible/tmp/ansible-tmp-1588716858.967364-29993-207569799864998/AnsiballZ_k8s.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible.modules.clustering.k8s.k8s', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/home/username/.pyenv/versions/3.6.6/lib/python3.6/runpy.py\", line 205, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/home/username/.pyenv/versions/3.6.6/lib/python3.6/runpy.py\", line 96, in _run_module_code\n    mod_name, mod_spec, pkg_name, script_name)\n  File \"/home/username/.pyenv/versions/3.6.6/lib/python3.6/runpy.py\", line 85, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/modules/clustering/k8s/k8s.py\", line 279, in <module>\n  File \"/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/modules/clustering/k8s/k8s.py\", line 275, in main\n  File \"/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/module_utils/k8s/raw.py\", line 145, in __init__\n  File \"/tmp/ansible_k8s_payload_d7uua9ug/ansible_k8s_payload.zip/ansible/module_utils/k8s/raw.py\", line 145, in <listcomp>\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/__init__.py\", line 130, in load_all\n    yield loader.get_data()\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/constructor.py\", line 37, in get_data\n    return self.construct_document(self.get_node())\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 27, in get_node\n    return self.compose_document()\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 55, in compose_document\n    node = self.compose_node(None, None)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 84, in compose_node\n    node = self.compose_mapping_node(anchor)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 133, in compose_mapping_node\n    item_value = self.compose_node(node, item_key)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 84, in compose_node\n    node = self.compose_mapping_node(anchor)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 133, in compose_mapping_node\n    item_value = self.compose_node(node, item_key)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 84, in compose_node\n    node = self.compose_mapping_node(anchor)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 133, in compose_mapping_node\n    item_value = self.compose_node(node, item_key)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 84, in compose_node\n    node = self.compose_mapping_node(anchor)\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/composer.py\", line 127, in compose_mapping_node\n    while not self.check_event(MappingEndEvent):\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/parser.py\", line 98, in check_event\n    self.current_event = self.state()\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/parser.py\", line 428, in parse_block_mapping_key\n    if self.check_token(KeyToken):\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/scanner.py\", line 116, in check_token\n    self.fetch_more_tokens()\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/scanner.py\", line 223, in fetch_more_tokens\n    return self.fetch_value()\n  File \"/home/username/.local/lib/python3.6/site-packages/yaml/scanner.py\", line 579, in fetch_value\n    self.get_mark())\nyaml.scanner.ScannerError: mapping values are not allowed here\n  in \"<unicode string>\", line 18, column 24:\n                annotations:\n                           ^\n",
        "module_stdout": "",
        "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
        "rc": 1
    }

您不能将 {{ }} 放在 {{ }} 中,因此请尝试删除多余的块:

- name: install some tool
  k8s:
    state: present
    definition: "{{ lookup('template', item) }}"
    context: "{{ cluster_name}}"
  with_items:
    - "tool_template.yaml"

你可能应该删除模板条件中的缩进,条件之前的空格被添加到下一行的空格中,因为条件标记后面的换行符被删除,这导致 anotations 映射为双缩进,这不是预期的。

您当前的模板结果是:

metadata:
  labels:
    app: tool_name

      annotations:
    ad.datadoghq.com/container.check_names: '["openmetrics"]'
    ad.datadoghq.com/container.init_configs: '[{}]'
    ad.datadoghq.com/container.instances: |
      [{
      "prometheus_url": "http://pathto:port/,
      "namespace": "myapp",
      "metrics": ["somemetric*"]
      }]

模板应如下所示:

metadata:
  labels:
    app: tool_name

{% if is_major | bool %}
  annotations:
    ad.datadoghq.com/container.check_names: '["openmetrics"]'
    ad.datadoghq.com/container.init_configs: '[{}]'
    ad.datadoghq.com/container.instances: |
      [{
      "prometheus_url": "http://pathto:port/,
      "namespace": "myapp",
      "metrics": ["somemetric*"]
      }]
{% endif %}

失败是件好事,因为如果之前的映射达到相同的缩进级别,它只会在部署中输入错误的值,或者在最好的情况下输入错误的值。

阅读更多关于 Jinja2 中空白的信息:https://jinja.palletsprojects.com/en/2.11.x/templates/#whitespace-control

您还可以通过使用 trim_blockslstrip_blocks 标志来控制更多行为。