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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
+++
categories = ['Без рубрики']
date = '2021-02-13T22:08:19Z'
tags = ['go', 'it', 'разное']
title = 'Jsonnet'
image = 'logo.webp'
+++
Редко такое бывает, что случайно натыкаешься на какую-то технологию и она вызывает вау-эффект и буквально переворачивает всё верх дном. На днях для меня такой технологией стал [Jsonnet](https://jsonnet.org/) от Google.
В кратце, это надмножество JSON являющееся языком описания шаблонов. Пока звучит не очень круто, да? На деле это офигенный Тьюринг полный функциональный язык, результатом выполнения которого будет сформированый JSON (и не только) документ([или несколько документов](https://jsonnet.org/learning/getting_started.html#multi)).
[Если интересно, рекомендую сразу переходить к туториалу.](https://jsonnet.org/learning/tutorial.html)
# Почему же это круто?
Ну, во-первых, он реально мощный и простой. С его помощью можно формировать документы любой сложности.
Во-вторых, его можно встроить в свою программу на Go ([и не только, но на Go — проще всего](https://jsonnet.org/ref/bindings.html)), и это даст бесплатно мощный DSL для написания очень гибких конфигов.
В третьих, ну камон, приятно же когда компьютер берет на себя рутинную работу по формированию больших и сложных JSON’ов!
# Пример
Накидал простенький пример который формирует конфигурацию пайплайна для гипотетической CI системы:
```json
local map(arr, predicate) = // определяем функцию map
if std.length(arr) == 0 then
[]
else
[
predicate(arr[0])
] + map(arr[1:], predicate); // функциональненько!
local tasks = [['go1.14', '1.14-alpine'],['go1.15', '1.15-alpine'],['go1.16-RC', '1.16-rc-alpine']];
local commands = ['go build', 'go test']; // Общая часть
{ // Результирующий JSON
pipeline: map(tasks, function (task) { // Вызов map от tasks
name: task[0],
image: "golang:"+task[1],
commands: commands,
})
}
```
Результат:
```json
{
"pipeline": [
{
"commands": [
"go build",
"go test"
],
"image": "golang:1.14-alpine",
"name": "go1.14"
},
{
"commands": [
"go build",
"go test"
],
"image": "golang:1.15-alpine",
"name": "go1.15"
},
{
"commands": [
"go build",
"go test"
],
"image": "golang:1.16-rc-alpine",
"name": "go1.16-RC"
}
]
}
```
Круть же!
Да, на небольшом примере не очень показательно, но даже тут, скажем, при добавлении новой цели сборки будет достаточно слегка подправить массив tasks и автоматически сформируется все остальное, а не копипаст целой секции и ручная правка в нужных местах.
Я оставил за скобками то, что этот шаблонизатора позволяет формировать не только JSON но и фактически любой другой текстовый формат. И даже из одного скрипта формировать несколько документов разного формата. При этом локальные переменные будут использоваться общие. Теоретически, если упороться, можно одним скриптом сформировать весь /etc на новом сервере. Почему бы и нет?)
Не знаю смог ли передать ощущение своего восторга, но я охренеть как рад и жду выходных, чтобы с головой нырнуть в эту технологию, которая открывает столько новых интересных перспектив!
|