あなたの期待がどこから来るか、私は知りませんが、それはありますYAMLのtrivial to check there is no special meaning for $
, _
, '/' nor :
if not followed by a space。 gitlabにはあるかもしれないが、あなたが期待している方法があることを強く疑う。あなたの期待を形式化するために
、あなたは(同じマッピングから)任意のキー$
が先行し、_
または/
により、スカラーの終わりで終了し、そのキーの値を「拡大」されようとしていることを前提としています。 _
はそのようなターミネータでなければならず、そうでなければ$PROJECT_$PACKAGE
は正しく拡張されません。
は今、キーと値のペアを追加することを検討:
BREAKING_TEST: /opt/project/build/package/bundle
か、_
はターミネータであるだけに展開することを暗示ルールに従ってください:
BREAKING_TEST: $PACKAGE_PATH
これはに拡大することになっています。
BREAKING_TEST: project_PATH
bash
のようなこのようなあいまい性プログラムを防止するには("$PROJECT"_PATH
対$PROJECT_PATH
)の変数名を引用符で囲みますが、より初期のやり方では、締め付けの開始と終了の文字を使用することです。 {
および}
,$%
および%
)、クランプ文字を通常のテキストとして使用する特別な規則があります。
本当に間違ったことを言ったように、これはうまくいかないでしょう。
YAMLファイルを前処理することは難しくありません。 Python(ただし、{
はYAMLで特別な意味があることに注意してください)、jinja2の助けを借りて可能です:変数を読み込んで、置き換えができなくなるまで変数を使って元のテキストを展開します。
しかし、それはすべて区切り文字をインテリジェントに選択することから始まります。また、あなたの "変数"はYAMLテキストで順序付けされているように見えますが、あなたのプログラムでdict/hash/mappingとして構築されているときはそのような保証はありません。
<<
と>>
を使用します。
次のプログラム(つまり、その通常の意味を保つために
<<
をエスケープに対処していない)で拡大し、あなたの元を生成し、
variables:
PROJECT: project
PACKAGE: package
PROD: <<PROJECT>>_<<PACKAGE>>
STAGE: <<PROD>>_stage
PACKAGE_PATH: /opt/<<PROJECT>>/build/<<PACKAGE>>
BUILD_PATH: /opt/<<PROJECT>>/build/<<PACKAGE>>/bundle
CONTAINER_IMAGE: registry.example.com/<<PROJECT>>/<<PACKAGE>>:e2
、YAML正確に。
import sys
from ruamel import yaml
def expand(s, d):
max_recursion = 100
while '<<' in s:
res = ''
max_recursion -= 1
if max_recursion < 0:
raise NotImplementedError('max recursion exceeded')
for idx, chunk in enumerate(s.split('<<')):
if idx == 0:
res += chunk # first chunk is before <<, just append
continue
try:
var, rest = chunk.split('>>', 1)
except ValueError:
raise NotImplementedError('delimiters have to balance "{}"'.format(chunk))
if var not in d:
res += '<<' + chunk
else:
res += d[var] + rest
s = res
return s
with open('template.yaml') as fp:
yaml_str = fp.read()
variables = yaml.safe_load(yaml_str)['variables']
data = yaml.round_trip_load(expand(yaml_str, variables))
yaml.round_trip_dump(data, sys.stdout, indent=2)