KCL lang(Constraint-based Record & Functional Language) 介紹

最近發現一個新的程式語言,不過很少人提到,所以就自己寫一篇。

KCL lang 是一種 data language,用來產生 yaml。它與 template language 不同的地方在於, language 可以做到資料與邏輯分開,而 template engine 則是資料與邏輯混雜在一起。

KCL 和 yaml 不同的地方在於 KCL 是程式語言,所以可以有變數與函數的觀念。而 yaml 只是一種格式,所以沒什麼特殊功能。

KCL 的語法和 terraform 與 python 相似,所以你會這兩個程式語言,你很快就可以上手了。

一個簡單的 kubernetes deployment 範例

apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
    name = "nginx"
    labels.app = "nginx"
}
spec = {
    replicas = 3
    selector.matchLabels = metadata.labels
    template.metadata.labels = metadata.labels
    template.spec.containers = [
        {
            name = metadata.name
            image = "${metadata.name}:1.14.2"
            ports = [{ containerPort = 80 }]
        }
    ]
}

過去在寫 kubernetes yaml 時,labels 的部分經常需要 Repeat youself。但是在上面的例子,你可以使用變數來表達一樣的部分。

如果 template 下的 labels 有額外的屬性,則可以用下面語法(不知道為啥不能直接用 metadata.labels,可能是 bug 吧)

_labels = {
    app = "nginx"
}
_extra_labels = {
    env = "dev"
}

apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
    name = "nginx"
    labels = _labels
}
spec = {
    replicas = 3
    selector.matchLabels = metadata.labels
    template.metadata.labels = {**_labels, **_extra_labels}
    template.spec.containers = [
        {
            name = metadata.name
            image = "${metadata.name}:1.14.2"
            ports = [{ containerPort = 80 }]
        }
    ]
}

如果你的 containerPort 是由一個 list 決定,則可以寫成

_labels = {
    app = "nginx"
}
_extra_labels = {
    env = "dev"
}

apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
    name = "nginx"
    labels = _labels
}
spec = {
    replicas = 3
    selector.matchLabels = metadata.labels
    template.metadata.labels = {**_labels, **_extra_labels}
    template.spec.containers = [
        {
            name = metadata.name
            image = "${metadata.name}:1.14.2"
            ports = [{ containerPort = i } for i in [80, 443]]
        }
    ]
}

將 list 變成變數,下指令時帶入

_labels = {
    app = "nginx"
}
_extra_labels = {
    env = "dev"
}

apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
    name = "nginx"
    labels = _labels
}
spec = {
    replicas = 3
    selector.matchLabels = metadata.labels
    template.metadata.labels = {**_labels, **_extra_labels}
    template.spec.containers = [
        {
            name = metadata.name
            image = "${metadata.name}:1.14.2"
            ports = [{ containerPort = i } for i in ports]
        }
    ]
}
kcl ~/b.k -D 'ports=["80", "443"]'

除了用來產生資料外,KCL也可以用來做資料驗證,如 a.json 內容如下

{
  "a": 123
}

a.k 內容如下

schema Data:
  a: str

你可以用下面指令進行驗證

kcl-vet a.json a.k

他還有 rules 功能,不過目前還沒搞懂,就下次再說了

總結,這是一個有潛力的程式語言,可以減少設定檔沒必要的重複部分。對於產生 kubernetes yaml, helm yaml 方面好用。


You'll only receive email when they publish something new.

More from kjelly
All posts