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 模板的示例。
尝试将 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 模板的示例。