YAMLファイル生成のあれこれ

こんにちは河野です。
これはTECHSCORE Advent Calendar 2018 の3日目の記事です。

最近いろいろなツール、例えばCIとか、PaaSとかを触っているのですが、その設定ファイルにはYAMLが使われていることが多い気がします。

使い始めの頃はシンプルだった設定ファイルも、気づけば記述量が増えて見通しが悪くなります。また、Development, Staging, Productionのそれぞれで似たような内容だけどちょっとだけ違う、という設定ファイルをこしらえないといけないことがあります。

そうすると、簡単にYAMLファイルを記述したいとか、あわよくば共通化された部分とちょっとした差分を上手く管理したい、という欲求に駆られるものです。

今回はそういった気持ちで調べてみた、いくつかツールや方法などを紹介します。

YAMLのアンカー/エイリアスの機能

YAMLにはもともとアンカーとエイリアスの機能があります。これを使用すると、同じ記述を避けることができるようになります。例えば以下のようにできます。

これをパースした結果 group1, group2 は以下のようになります。

サンプルが実用的ではないですが、雰囲気はわかっていただけるかと思います。

Pros: YAMLの仕様に準拠しているので、多くのツールでサポートされている(はず)
Cons: 複数のファイルをまたがった共通化はできない

標準の仕様なのでおそらくたいていのツールでは使えると思うのですが、AWSのCloudFormationではサポートされてないみたいです。また複数のファイルをまたがって共通化できないというのもちょっと物足りなさがありますね。

参考

使用するツールでの拡張機能

ツールによっては、共通化のためのIncludeやTemplateの機能、実行時に値を渡すためのPropertiesやVariablesといった機能があります。

GitLab CI

GitLab CIでは異なるYAMLのファイルを引っ張ってくることができ、それを設定内容として利用することができます。
またVariablesの機能の組み合わせでは、includeした値を上書きすることもできます。

ベースとなるYAMLがこちらです。

CIが使用する.gitlab-ci.ymlでは以下のように設定します。

POSTGRES_USER, POSTGRES_PASSWORDは上書きされますし、productionのタスクはurlが上書きされます。タスクの内容自体はautodevops-template.ymlの内容が利用されます。

AWS CloudFormation

CloudFormationではParametersやMapping、また独自の関数があります。

EC2のインスタンスタイプはPrameterのInstanceTypeで設定された値が利用されます。

Mappingでは指定したキーに対応する値が利用できます。例えばap-northeast-1で実行された場合にはap-northeast-1.32に対応する値であるami-9c03a89dが使用されます。

これらの方法では以下のようなPros/Consがあります。

Pros: ツールに最適化された方法で設定の共通化が行え、複数のファイルをまたぐ共通化も可能になる
Cons: ツールが変わると再利用できなくなる。YAMLの拡張部分について学習する必要がある。

特にCloudFormationはすごいですね。でもなんか敷居の高さを感じてしまうし、書くのが大変だなぁという気持ちになります。

テンプレートエンジンを使う

YAML内部の項目や、与えるべきパラメータも動的に生成したいので、プログラムでやってしまおうというケースです。

Pythonでやる

CloudFormationのテンプレートを記述したいのですが、それに加えて

  • 初期パスワードの生成が必要
  • ユーザーが動的なためCloudFormationのParametersも動的に記述が必要

という理由で、実行時に使用するパラメータも生成してみた例です。

以下の例ではJinja2というテンプレートエンジンを使用しました。
処理するためのコードはこのようになります。ユーザーの情報はレンダリング処理の前に準備されている状態です。

YAMLになるテンプレート部分は以下のようになります。forを使用した繰り返しの記述ができるのが嬉しいですね。

これでCloudFormationのテンプレートを生成しています。

Pros: プログラムとテンプレートエンジンによる生成のため柔軟性が高い。好きなように生成できる。
Cons: 何度も使用する場合には、例外ケースなどを考慮する必要がある。ボリュームが大きくなるとめんどくさくなる

シェルスクリプト(コマンド)でなんとか

もっと楽にできないもんでしょうか。雑に以下のようにやってみました。

template.yamlを用意します。

そしてシェルスクリプトを用意します。create_yaml.shとしました。

これを実行すると、こんな感じになります!

template.yamlの中に記述されている変数をevalを使って評価することで値を埋め込むことができました。なんか手っ取り早さは一番のような気がします。

Pros: シンプルにできる
Cons: 共通化や値の上書きはややこしくなりそう

おわりに

ツールによる拡張機能が一番使いやすいと思いますが、Includeがサポートされてないツールだとなかなかつらいものがあります。代替の方法をいろいろと模索してみましたが、保守性を下げずに簡単に記述できる銀の弾丸的なものはないですね。

サボろうとせず地道に書く、というのが一番かもしれません。

Comments are closed, but you can leave a trackback: Trackback URL.