Posted at

yamlやJsonのチェック(Lint)ができるCUEの紹介


yamlやJsonのDSLが辛い

昨今、kubernetesを初めとして、yamlやJsonでconfigを書く機会が多くなっています。

独自記法を覚えるのがつらい。

私「ここは文字列?数値?省略したらどうなる?」

また、台帳管理をyamlで行うケースもあるかと思いますが、yamlの型管理がしたい。

私「文字列のみってreadmeに書いたのに、数値が入ってる・・・」


CUEはyamlやJson上のデータに対して、型を定義し、そのチェックをしてくれるツールです。


この記事を読むと得られること


  • CUEに関して何となく分かる

  • CUEを使ってyamlの型チェックを行える


CUEとは

CUEとは


CUE is an open source language, with a rich set APIs and tooling, for defining, generating, and validating all kinds of data: configuration, APIs, database schemas, code, … you name it.


簡単に言うと、あらゆるデータの定義ができる言語だと言っています。

実際に、様々なデータのvalidationやdefinitionが行えます。

提供は2つの形式です

- goのsdk

- CLI

今回はCLIを中心に紹介していきます。


CUEでyamlの型定義をし、チェックする

CUEはいろいろなことが出来るのですが、今回は型定義を行い、それをもとにyamlのチェックをします。

なので、役割として

- CUEは型の定義

- yamlは値の定義

とします。

ちなみにCUE単体で、型の定義とデータの定義ができますが、今回はyamlを使う前提にします。

需要もそっちのほうがありそうですし。

例として以下のyamlのチェックを実行していきます。

プロジェクトのルールを守っていないyamlをCUEで発見していきます。

apiVersion: extensions/v1beta1 # 今は"apps/v1"

kind: Deployment
metadata:
name: deployment-example
spec:
replicas: 3 # replicasは3未満に制限
template:
metadata:
labels:
app: deployment-example
spec:
containers:
- name: sample
image: sample # docker imageのtagの省略禁止
ports:
- containerPort: 80

コメントで書いたルールをチェックするCUEが以下です。以降、この二つのファイルを例に説明していきます。

package kubernetes

apiVersion: "apps/v1" // apiVersionを指定
spec: {
replicas: <3 & int // 3未満を指定
template spec containers: [{image: =~"^[a-z][a-zA-Z0-9]*:[a-zA-Z0-9!-/:-@¥[-`{-~]+"}] // tagの明記を指定
}


Types are Values

CUEのドキュメントを読んでいると、まず出てくる怪文書が「Types are Values.」

型と値は違うだろーー!!という気持ちになりますが、読み込むと意味が分かりました。

せっかくなので簡単に解説します。

上記のCUEのapiVersionreplicasのところで型と値が同じように扱われています。

これがTypes are Values.の効果です。型と値を区別しなくてよくなり、記法が簡単になります。


型と値を「集合」と読み替える

集合です。数学の集合です。

例えばintは整数型を意味しますが、これをint = {Z(Zは整数の全集合)}だと思ってください。

そうすると、{1} ⊆ intが成り立ちます。

stringでも同じです。string = {文字列の全集合}であり、{"apps/v1"} ⊆ stringです。

つまり、CUEのapiVersion: "apps/v1"は値を指定しているわけではなく、{"apps/v1"}を指定しているわけです。

型とか値とか考えずに集合で考えると理解しやすいと思います。


型定義方法cook book


和集合を定義したい

"sample" | "text"

"sample"という文字列か"text"という文字列のどちらかを許可する場合。


積集合を定義したい

>3 & int

3より大きい、かつ整数を許可する場合。


文字列の範囲を表現したい

"[a-z]"

任意の小文字アルファベット1文字を許可する場合(正規表現が使えるということです)。


yamlの型チェックをしてみる

今回はCUEのCLIを使ってチェックしてみます。

cue vet deployment.yaml check.cue

これを実行するだけでチェックしてくれます。簡単!

以下が結果です。

apiVersion: conflicting values "extensions/v1beta1" and "apps/v1":

./network_socket.yml:1:14
./policy/policy.cue:3:13
spec.replicas: invalid value 3 (out of bound int & <3):
./policy/policy.cue:6:12
./network_socket.yml:5:44
spec.template.spec.containers.0.image: invalid value "sample" (does not match =~"^[a-z][a-zA-Z0-9]*:[a-zA-Z0-9!-/:-@¥[-`{-~]+"):
./policy/policy.cue:7:37
./network_socket.yml:13:12

確かに怒られています。


最後に

CUEのツールはCIに組み込んで初めて真価を発揮すると思います。

各種設定ファイルをcommitすると、CIが走り、問題があれば教えてくれる・・・素晴らしい仕組みです。

yamlやjsonで設定ファイルを書く人は一度CUEを試してみても良いかもしれません。

ただし、yamlやjsonのチェックがCUEで全て満たせるとも思えないので、サクッとチェックしてみたい人向けです。

(がっつりやりたい人は自分でチェックスクリプトを書いた方が良さそうです。)