KCL lang(Constraint-based Record & Functional Language) 介紹
July 10, 2023•349 words
最近發現一個新的程式語言,不過很少人提到,所以就自己寫一篇。
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 方面好用。