Google 部署管理器:MANIFEST_EXPANSION_USER_ERROR 多行变量

Google Deployment manager: MANIFEST_EXPANSION_USER_ERROR multiline variables

尝试将 Google 部署管理器与 YAML 和带有多行变量的 Jinja 结合使用,例如:

startup_script_passed_as_variable: |
  line 1
  line 2
  line 3

以后:

{% if 'startup_script_passed_as_variable' in properties %}
    - key: startup-script
      value: {{properties['startup_script_passed_as_variable'] }}
{% endif %}

给出 MANIFEST_EXPANSION_USER_ERROR:

ERROR: (gcloud.deployment-manager.deployments.create) Error in Operation operation-1432566282260-52e8eed22aa20-e6892512-baf7134:

MANIFEST_EXPANSION_USER_ERROR
Manifest expansion encountered the following errors: while scanning a simple key in "" could not found expected ':' in ""

尝试过(失败):

{% if 'startup_script' in properties %}
        - key: startup-script
          value: {{ startup_script_passed_as_variable }}
{% endif %}

还有

{% if 'startup_script' in properties %}
        - key: startup-script
          value: | 
            {{ startup_script_passed_as_variable }}
{% endif %}

{% if 'startup_script' in properties %}
        - key: startup-script
          value: | 
            {{ startup_script_passed_as_variable|indent(12) }}
{% endif %}

问题出在 YAML 和 Jinja 的结合上。 Jinja 对变量进行了转义,但未能缩进它,因为 YAML 在作为变量传递时会要求它。

相关:https://github.com/saltstack/salt/issues/5480

解决方案:将多行变量作为数组传递

startup_script_passed_as_variable: 
    - "line 1"
    - "line 2"
    - "line 3"

如果您的值以 # 开头(GCE 上的启动脚本就是这样,即 #!/bin/bash),引号很重要,否则它将被视为注释。

{% if 'startup_script' in properties %}
        - key: startup-script
          value: 
{% for line in properties['startup_script'] %}
            {{line}}
{% endfor %}
{% endif %}

由于 Google 部署管理器的问答 material 不多,所以将其放在这里。

在 Jinja 中没有干净的方法可以做到这一点。正如您自己指出的那样,因为 YAML 是一种对空格敏感的语言,所以很难有效地模板化。

一种可能的破解方法是将字符串 属性 拆分为一个列表,然后遍历该列表。

例如,提供 属性:

startup-script: |
  #!/bin/bash
  python -m SimpleHTTPServer 8080

您可以在您的 Jinja 模板中使用它:

{% if 'startup_script' in properties %}
      - key: startup-script
      value: |
{% for line in properties['startup-script'].split('\n') %}
        {{ line }}
{% endfor %}

这里还有一个full working example这个。

此方法可行,但一般情况下,人们开始考虑使用 python 模板时就会出现这种情况。因为您正在使用 python 中的对象模型,所以您不必处理缩进问题。例如:

'metadata': {
    'items': [{
        'key': 'startup-script',
        'value': context.properties['startup_script']
    }]
}

可以在 Metadata From File 示例中找到 python 模板的示例。