Carpe Diem

備忘録

yttでテンプレートの変数に外部ファイルから値を注入する

背景

前回はyttに基本的な使い方を説明しました。

christina04.hatenablog.com

今回は少し実践的に、変数を外部ファイルとして扱ってサービス毎だったりdev/prdといった環境毎にYAMLを生成できるようにします。

環境

  • ytt 0.44.3

イメージ図

前回はテンプレートにベタ書きしていた値を変数に入れていましたが、今回は外部ファイルから注入します。
フローとしては以下で、一番最初に処理されます。

ref: https://carvel.dev/ytt/docs/v0.44.0/how-it-works/

※今回Overlaysは扱わないです

Data Values

外部から値を注入したい時はData Valuesという機能を使います。

以下のように2つの種類のファイルを用意します。

  • テンプレート(1つだけ)
  • 外部データファイル(環境毎に分ける)

テンプレート(template.yml)

#@ load("@ytt:data", "data")

env: #@ data.values.env
labels: #@ data.values.labels

ポイントは以下です。

  • #@ load("@ytt:data", "data")でデータを外部から読み込むことを宣言する
  • #@ data.values.xxxで読み込んだファイルの値を使う

外部データファイル(values.yml)

#@data/values
---
env: dev
labels:
  key1: value1
  key2: value2

ポイントは以下です。

生成結果

$ ytt -f template.yml -f values.yml
env: dev
labels:
  key1: value1
  key2: value2

Data Values Schema

Data Valuesを使う上で

  • 型を指定したい
  • 初期値を設定したい

といった時はData Values Schemaを使います。

以下のように3つの種類のファイルを用意します。

  • テンプレート(1つだけ)
  • Schema(1つだけ)
  • 外部データファイル(環境毎に分ける)

テンプレート(template.yml)

#@ load("@ytt:data", "data")

env: #@ data.values.env
labels: #@ data.values.labels

先ほどと同様です。

Schema(schema.yml)

#@data/values-schema
---
env: dev
labels:
  key1: 0
  key2: False

ポイントは以下です。

外部データファイル(values.yml)

#@data/values
---
env: prd
labels:
  key1: 10

Schemaの型に合わせた値を入れます。

生成結果

各ファイルを指定して生成します。

$ ytt -f template.yml -f schema.yml -f values.yml

以下のようにschemaの初期値はそのままで、values.ymlで上書きしたYAMLが生成されます。

env: prd
labels:
  key1: 10
  key2: false

Schemaに違反していると

例えばSchemaの型と異なる型を入れようとすると、

#@data/values
---
env: prd
labels:
  key1: foo

以下のようにビルド時にコケるようになります。

ytt: Error: Overlaying data values (in following order: values.yml):
One or more data values were invalid
====================================

values.yml:
    |
  5 |   key1: foo
    |

    = found: string
    = expected: integer (by schema.yml:5)

Forループにも適用可能

以下のようにfor loopのパターンでもスキーマを適用可能です。

loop_template.yml

#@ load("@ytt:data", "data")

#@ for service in data.values.services:
---
env: #@ service.env
labels: #@ service.labels
#@ end

loop_schema.yml

#@data/values-schema
---
services:
  - env: dev
    labels:
      key1: 0
      key2: False

loop_values.yml

for loopのため複数のvalueを入力します。

#@data/values
---
services:
  - env: dev
    labels:
      key1: 20
  - env: prd
    labels:
      key1: 10

生成結果

$ ytt -f loop_template.yml -f loop_schema.yml -f loop_values.yml

以下のようにschemaは1要素だけで適用されます。

env: dev
labels:
  key1: 20
  key2: false
---
env: prd
labels:
  key1: 10
  key2: false

その他

スペースがあったりなかったりするのは?

#@の後にスペースがあったりなかったりしますが、以下の違いがあります。

  • アノテーションの場合はスペースがない
    • Ex) #@data/values
  • ディレクティブの場合はスペースがある
    • Ex) #@ if

ref: https://carvel.dev/ytt/docs/v0.44.0/faq/#when-should-i-include-a-space-in-my-ytt-comment-does-it-matter-is-it-load-or--load-overlaymatch-or--overlaymatch

アノテーションとディレクティブの違い

ざっくり説明すると以下です。

要素 説明
アノテーション YAMLのツリー内のノードにメタデータを付与する
ディレクティブ 引数の実行を指示する

サンプルコード

今回のサンプルコードはこちらです。

github.com

まとめ

yttでテンプレートの変数に外部ファイルから値を注入する方法を説明しました。
これができるとサービス毎、環境毎にYAMLを同じフォーマットで生成できるので運用が楽になります。

参考