yispはjsonnetやcueなどと同様、データ記述言語の1つです。「イスプ」と読みます。yaml+lispでyispです。
yisp既存のデータ記述言語と異なり、①構文がyamlそのままであること、②lisp-likeな評価機構をもっていること の2点が特徴です。
主な用途としてはkubernetesのマニフェストやGrafanaのダッシュボードなどの設定ファイルを生成するために活用できますが、その他yaml及びjsonを設定ファイルとして利用するシステムにおいて、yispを用いることでより柔軟な設定が可能になります。
基本
最もシンプルやyispの例は次のようになります。
helloworld.yaml
1
2
3
4
5
|
mystring: !yisp
- concat
- hello
- ' '
- world
|
yamlのタグ機能を使って、生データの任意の場所から「ここから評価を行う」ということを指示します。
これをyispで評価します。
1
|
yisp build helloworld.yaml
|
すると、次のyamlが出力されます。
result
1
|
mystring: "hello world"
|
この例では、
- !yispの外側の構造はそのままyamlとして出力されている
- !yispの中身はlisp-likeな構文で書かれ、concat(hello, ’ ‘, world)が評価されている
の2点が重要です。
つかえる演算子のリストはドキュメントにありますが、実装からドキュメント反映にラグがある場合があるのでコードのここを見た方が早かったりします。
モジュール
他のファイルを名前付きでインポートすることができ、モジュールのように利用することができます。
例えば次のようなテンプレートを定義したファイルを作ります。
template.yaml
1
2
3
4
5
6
7
8
9
10
11
12
|
!yisp &mkpod
- lambda
- [name, image]
- !quote
apiVersion: v1
kind: Pod
metadata:
name: *name
spec:
containers:
- name: *name
image: *image
|
import構文をつかってこのファイルを読み込み、*template.mkpod
で呼び出します。
template-use.yaml
1
2
3
4
5
6
7
8
|
!yisp
- import
- ["template", "./template.yaml"]
---
!yisp
- *template.mkpod
- mypod1
- myimage1
|
こうして評価すると、次のようなyamlが出力されます。
result
1
2
3
4
5
6
7
8
|
apiVersion: v1
kind: Pod
metadata:
name: mypod1
spec:
containers:
- name: mypod1
image: myimage1
|
型
yispではjsonschemaのような形式型オブジェクトを作成し、型チェックやキャストを行うことができます。
たとえば次のようなyamlを書きます。
type.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
!yisp &Person
- schema
- !quote
type: object
properties:
name:
type: string
age:
type: integer
required:
- name
- age
---
!yisp &FormatPerson
- lambda
- [!Person person] #引数に!Personタグを付けて型を指定。型名はアンカーで定義したものも参照できる。
- - format
- "%s is %d years old"
- *person.name
- *person.age
---
!yisp
- *FormatPerson
- name: "John Doe"
age: 30
|
これは1つめのドキュメントでPerson
型を定義し、2つめのドキュメントでその型を受け取る関数FormatPerson
を定義しています。
実行結果はつぎのようになります。
次に、たとえばageの値を文字列にしてしまった状態で実行してみます。
wrong-age-type.yaml
1
2
3
4
|
!yisp
- *FormatPerson
- name: "John Doe"
age: "30"
|
すると、intを期待していたのにstringが来たというエラーが出力されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
> 06/08 05:58 ~/git/yisp$ go run . build test.yaml
Error: object does not satisfy type (expected int, got string)
/home/totegamma/git/yisp/test.yaml
==================================
23 |---
24 |!yisp
25 |- *FormatPerson
26 |- name: "John Doe"
^ object does not satisfy type (expected int, got string)
27 | age: "30"
28 |
Traceback:
object does not satisfy type (expected int, got string) at /home/totegamma/git/yisp/test.yaml:26:3
failed to apply function at /home/totegamma/git/yisp/test.yaml:24:1
> 06/08 05:59 ~/git/yisp$
|
ageの入力をそもそもなくすと、次のエラーが表示されます。
1
|
Error: object does not satisfy type (missing required property: age)
|
また、型チェックは関数呼び出しだけでなくassert-type
オペレーターでも行えます。
1
2
3
4
5
|
!yisp
- assert-type
- *Person
- name: "John Doe"
age: "30"
|
go-runによる外部プラグイン呼び出し
yispは非常に強力な表現力を持っていますが、ありとあらゆるロジックをyispで書くのは旨味が薄いです。
そのため、yispではgo-run
オペレーターを使ってGoのパッケージをcil呼び出しすることができます。
例えばhelmchartからマニフェストを生成する例は次のようになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
!yisp &helm-template
- lambda
- [props]
- - go-run
- pkg: github.com/totegamma/yisp-helm-adapter@v0.1.0
args: !quote
- *props.repo
- *props.release
- *props.version
stdin:
- to-yaml
- *props.values
---
!yisp
- *helm-template
- repo: "https://charts.concrnt.net/"
release: "concrnt"
version: "0.7.13"
values:
meilisearch:
enabled: true
|
最初の例では簡単のためにhelm-template関数を同じファイル内で定義していましたが、オススメはGoのレポジトリに含めておき、ネットワークリソースをimportして使うことです。
たとえば、yisp-helm-adapterであればこのようにimportして呼び出すことができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
!yisp
- import
- ["helmchart", "https://raw.githubusercontent.com/totegamma/yisp-helm-adapter/refs/heads/main/helm-chart.yaml"]
---
!yisp
- *helmchart.template
- repo: "https://charts.concrnt.net/"
release: "concrnt"
version: "0.7.13"
values:
meilisearch:
enabled: true
|
エキシビション
yispは(必要以上に)lispとして実装されているので、例えば不動点コンビネーターの一つであるZコンビネーターによる無名再起のプログラムなども正常に動作します。
z-combinator.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
!yisp
&Z
- lambda
- [f]
- - - lambda
- [x]
- - *f
- - lambda
- [v]
- - - *x
- *x
- *v
- - lambda
- [x]
- - *f
- - lambda
- [v]
- - - *x
- *x
- *v
---
!yisp
- - *Z
- - lambda
- [self]
- - lambda
- [n]
- - if
- [<=, *n, 1]
- 1
- - "*"
- *n
- - *self
- - "-"
- *n
- 1
- 5
# => 120
|
その他記事
珍しく自ブログ以外でも照会記事を書いているので、よければそちらも併せてどうぞ。
qiita
dev.to(英語!)