IK.AM


Dev > Carvel > ytt

ytt(YAML Templating Tool)入門 - Templating編

Created on Wed Aug 19 2020 • Last Updated on Thu Aug 27 2020N/A Views

🏷️ YAML | ytt | k14s | Carvle

yttはスタンドアローンで使えるYAMLのテンプレートツールです。同じ領域のツールとしては

がありますが、テンプレートツールとしてのyttの特徴としては

  • YAMLそのものを記述する(YAMLとしてvalid)
  • YAMLのコメントとしてPython-likeなStarlark言語を記述することで動的な表現ができる

各ツールとの比較の詳細はこちら

他のツールが専用の言語を使うのに比べ、yttはあくまでもYAML+コメントなので心理的な導入のハードルは低いかもしれません。
もちろんytt用に文法は覚える必要はありますが、言語部分もPythonを使ったことがあれば覚えやすいかもしれません。

ただし、yttはただのテンプレートツールとは異なり、overlay機能を持っています。これはYAMLの一部を書き換えたり、追加したり、削除したりできる強力な機能で、
KubernetesのKustomizeやBOSHのOperation filesと同じような機能です。

つまり、Templating + Overlayが大きなyttの機能です。
本記事ではTemplating機能のみフォーカスします。Overlay機能については次の記事で説明します。

yttの仕様はこちらです。

目次

インストール

こちらからバイナリをダウンロードするか、

curl -sL https://k14s.io/install.sh | bash

あるいは

brew tap k14s/tap
brew install ytt

でインストールできます。

基本的な書き方

yttのYAMLは次の形式のコメントを使用します。それ以外のコメント(普通のYAMLのコメント)を書くとエラーになります。
エラーを許容する場合は--ignore-unknown-commentsオプションをつける必要があります。

#! YAMLのコメント

#@ Starlark言語の値またはコード

YAMLの値の部分にStarlarkの値を使って次のconfig.ymlを作成します。

null_value: #@ None
boolean_true: #@ True
boolean_false: #@ False

string_value: #@ "Hello World!"
string_format: #@ "Hello {}!".format("ytt")

list_value: #@ ["a", "b", "c"]
list_range: #@ list(range(0, 5))

map_value: #@ {"a": 100, "b": 200, "c": "Hello"}

このファイルをyttコマンドに入力すると次のような出力を得られます。

$ ytt -f config.yml
null_value: null
boolean_true: true
boolean_false: false
string_value: Hello World!
string_format: Hello ytt!
list_value:
- a
- b
- c
list_range:
- 0
- 1
- 2
- 3
- 4
map_value:
  a: 100
  b: 200
  c: Hello

Python同様にリスト内包表記も利用できます。

servers: #@ ["server-{}".format(x) for x in range(5)]

次のような出力結果になります。

$ ytt -f config.yml
servers:
- server-0
- server-1
- server-2
- server-3
- server-4

変数

変数の定義と参照ができます。

#@ message = "Hello!"
#@ coins = {
#@   "penny": 1,
#@   "nickel": 5,
#@   "dime": 10,
#@   "quarter": 25,
#@ }

message: #@ message
conis: #@ coins
dime: #@ coins["dime"]

conin_keys: #@ coins.keys()
conin_values: #@ coins.values()

次のような出力結果になります。

$ ytt -f config.yml
message: Hello!
conis:
  penny: 1
  nickel: 5
  dime: 10
  quarter: 25
dime: 10

conin_keys:
- penny
- nickel
- dime
- quarter
conin_values:
- 1
- 5
- 10
- 25

関数

関数の定義、呼び出しができます。

#@ def twice(x):
#@    return x * 2
#@ end

foo: #@ twice(7)
list: #@ [twice(x) for x in [1, 2, 3]]

Python/Starlarkとは異なり、関数の定義はendで閉じる必要があります。

次のような出力結果になります。

$ ytt -f config.yml
foo: 14
list:
- 2
- 4
- 6

YAML Fragmentを関数として定義することもできます。

#@ def labels():
organization: demo
space: develop
#@ end

labels: #@ labels()

次のような出力結果になります。

$ ytt -f config.yml
labels:
  organization: demo
  space: develop

If文

If文が利用できます。これもendが必要です。

#@ enabled = True
#@ if enabled:
foo: enabled
#@ else:
foo: disabled
#@ end

次のような出力結果になります。

$ ytt -f config.yml
foo: enabled

if/elseを一行で表現することもできます。

foo: #@ "enabled" if enabled else "disabled" 

elseが不要でかつ、1ブロックだけを制御したい場合はif/endで省略できます。

#@ enabled = True
#@ if/end enabled:
foo: enabled

For文

For文が利用できます。これもendが必要です。

#@ for i in range(5):
- #@ i
#@ end

次のような出力結果になります。

$ ytt -f config.yml
- 0
- 1
- 2
- 3
- 4

次のような書き方もできます。

#@ foo = ["a", 1], ["b", 2], ["c", 3]
#@ for a, i in foo:
- key: #@ a
  value: #@ i
#@ end

次のような出力結果になります。

$ ytt -f config.yml
- key: a
  value: 1
- key: b
  value: 2
- key: c
  value: 3

モジュール作成

関数の定義を別ファイルに外部化して、モジュールとして読み込むことができます。

次のdemo.lib.ymlを用意します。

#@ def labels():
organization: demo
space: develop
#@ end

load("モジュール名", "関数名", "関数名", ...)で関数を読み込めます。

#@ load("demo.lib.yml", "labels")

labels: #@ labels()

次のような出力結果になります。

$ ytt -f config.yml -f demo.lib.yml
labels:
  organization: demo
  space: develop

モジュールファイルは拡張子の前に.libが必要です。これがないとマルチドキュメントなYAMLとして、出力結果に含まれてしまいます。

モジュールはStarlarkでも記述できます。

# demo.star
def square(x):
  return x * x
end
#@ load("demo.star", "square")

value: #@ square(7)

次のような出力結果になります。

$ ytt -f config.yml -f demo.star   
value: 49

組み込みライブラリの利用

組み込みyttライブラリが用意されています。

https://github.com/k14s/ytt/blob/develop/docs/lang-ref-ytt.md

yttライブラリのbase64モジュールを使う例です。

#@ load("@ytt:base64", "base64")
#@ raw_value = "Hello World!"
value: #@ base64.encode(raw_value)

次のような出力結果になります。

$ ytt -f config.yml
value: SGVsbG8gV29ybGQh

Note: yttでは次のように用語を使っています。

  • モジュール ... YAMLや関数などを含む単一ファイル
  • パッケージ ... モジュールを含む単一ディレクトリ
  • ライブラリ ... パッケージの集合

https://github.com/k14s/ytt/blob/develop/docs/lang-ref-load.md#terminology

カスタムライブラリの作成

_ytt_libディレクトリにカスタムライブラリを作成できます。
外部プロジェクトをgit submoduleで取得したり、vendirで取得した場合に配置する良いです。

簡単なサンプルとしてhttps://github.com/making/demo-libを取り込みましょう。

mkdir -p _ytt_lib/github.com/making/demo-lib
curl -sL https://github.com/making/demo-lib/archive/master.tar.gz | tar -xzvf - -C _ytt_lib/github.com/making/demo-lib --strip-components=1

次のディレクトリ構造になります。

$ tree .
.
|-- _ytt_lib
|   `-- github.com
|       `-- making
|           `-- demo-lib
|               `-- demo.star
`-- config.yml

config.ymlでこのgithub.com/making/demo-libライブラリのdemo.starモジュールを使用します。

#@ load("@github.com/making/demo-lib:demo.star", "square")

value: #@ square(7)

次のような出力結果が得られます。

$ ytt -f .
value: 49

詳細は

Assert

yttライブラリのassertモジュールで入力チェックができます。

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

#@ foo = 200

foo: #@ foo if foo > 150 else assert.fail("'foo' must be greater than 150.")

nullチェックは次のように記述できます。

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

#@ iaas = "vsphere"
iaas: #@ iaas or assert.fail("'iaas' is required!")

これは次の例の短縮版です。

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

#@ iaas = "vsphere"
iaas: #@ iaas if iaas else assert.fail("'iaas' is required!")

Dataの外部化

変更可能な設定項目を外部YAMLに切り出すことができます。

次のvalues.ymlに設定項目を記述します。#@data/valuesアノテーションをつけてください。

#@data/values
---
vsphere:
  hostname: vcsa-01.example.com
  username: administrator@vsphere.local	
  password: VMware1!

yttライブラリのdataモジュールを使って読み込みます。
#@data/valuesアノテーションをつけたファイルをyttコマンドの入力に含めると、data.values.xxxxxで参照できるようにんります。

#@ load("@ytt:data", "data")
iaas-configurations:
- vcenter_host: #@ data.values.vsphere.hostname
  vcenter_username: #@ data.values.vsphere.username
  vcenter_password: #@ data.values.vsphere.password

次のように結合されて出力されます。

$ ytt -f config.yml -f values.yml
iaas-configurations:
- vcenter_host: vcsa-01.example.com
  vcenter_username: administrator@vsphere.local
  vcenter_password: VMware1!

設定項目はyttコマンドの-vオプションで上書きできます。

$ ytt -f config.yml -f values.yml -v vsphere.password=password
iaas-configurations:
- vcenter_host: vcsa-01.example.com
  vcenter_username: administrator@vsphere.local
  vcenter_password: password

JSONを読み込む例も紹介します。Terraformなど別のツールの結果がJSONとして出力され、それをそのまま読み込みたいケースを想定します。

次のvalues.jsonがあるとします。

{
  "vsphere": {
    "hostname": "vcsa-01.example.com",
    "password": "VMware1!",
    "username": "administrator@vsphere.local"
  }
}

JSONファイルを文字列として読み込み、jsonモジュールでdecodeします。

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

#@ values = json.decode(data.read("values.json"))
iaas-configurations:
- vcenter_host: #@ values["vsphere"]["hostname"]
  vcenter_username: #@ values["vsphere"]["username"]
  vcenter_password: #@ values["vsphere"]["password"]

次のような出力結果を得られます。

$ ytt -f config.yml -f values.json
iaas-configurations:
- vcenter_host: vcsa-01.example.com
  vcenter_username: administrator@vsphere.local
  vcenter_password: VMware1!

同様にyamlモジュールでデコードする例をみてみます。

次のConcoursepipeline.ymlで、Taskのconfig以下のYAMLを別ファイルに外出ししたい場合。

jobs:
- name: hello-world
  plan:
  - task: say-hello
    config:
      platform: linux
      image_resource:
        type: docker-image
        source:
          repository: ubuntu
          tag: bionic
      run:
        path: bash
        args: 
        - -c
        - |
          echo "Hello, world!"

切り出したTaskファイルをhello.lib.ymlというファイル名で保存します。ファイル名に.libを含めるのは、読み込まれた際にマルチドキュメントなYAMLとして出力されないようにするためです。

platform: linux
image_resource:
  type: docker-image
  source:
    repository: ubuntu
    tag: bionic
run:
  path: bash
  args:
  - -c
  - |
    echo "Hello, world!"

pipeline.ymlで、このhello.lib.ymldataモジュールで文字列としてとして読み込み、yamlモジュールでdecodeし、configに設定します。

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

jobs:
- name: hello-world
  plan:
  - task: say-hello
    config: #@ yaml.decode(data.read("hello.lib.yml"))

次のようなディレクトリ構造にします。

$ tree .
.
├── pipeline.yml
└── tasks
    └── hello.lib.yml

次のコマンドで一つのpipelineに結合されます。

$ ytt -f pipeline.yml -f tasks                        
jobs:
- name: hello-world
  plan:
  - task: say-hello
    config:
      platform: linux
      image_resource:
        type: docker-image
        source:
          repository: ubuntu
          tag: bionic
      run:
        path: bash
        args:
        - -c
        - echo "Hello, world!"

Textテンプレート

最初に"文字列".format(...)で文字列内に変数を埋める例を紹介しましたが、複数行の文字列に変数を埋め込みたい時は
@yaml/text-templated-stringsアノテーションをつけると便利です。

次のようなファイルが、

#@ customer_name = "John Doe"

#@yaml/text-templated-strings
message: |
  Dear (@= customer_name @),

  Thanks for reading this blog post.

  Best regards,
  @making

次のように出力されます。

$ ytt -f config.yml                        
message: |-
  Dear John Doe,

  Thanks for reading this blog post.

  Best regards,
  @making

テンプレートの部分は別ファイルに切り出せます。message_body.lib.txtに次の内容を記述し、

(@ def message_body(customer_name): -@)
Dear (@= customer_name @),

Thanks for reading this blog post.

Best regards,
@making
(@- end @)

次のように読み込めば、

#@ load("message_body.lib.txt", "message_body")
#@ customer_name = "John Doe"
message: #@ message_body(customer_name)

次のように出力されます。

$ ytt -f config.yml -f message_body.lib.txt
message: |-
  Dear John Doe,

  Thanks for reading this blog post.

  Best regards,
  @making

yttのTemplating機能を見てきました。次の記事はYAMLの柔軟な加工に便利なOverlay機能を見ます。

Found a mistake? Update the entry.