Kroki - egységes felületen integrálja a diagramkészítő motorokat

Dokumentum vagy online diagramokat szövegből generálom Mermaid vagy PlantUML segítségével. A kroki ugyan nem diagramkészítő, de egységes felülten tucatnyi diagramkészítőt tud integrálni.

Krokival készült

Diagramkészítéshez általában a mermaid-ot vagy PlantUML-t használom. Az első javascript a másik java alapú és mindkettő MIT licenc alatt - korlátozás nélkül - használható. Napokban találtam rá a Kroki-ra ami ugyan nem diagramkészítő, de egységes felülten tucatnyi diagramkészítőt tud integrálni.

Támogatott diagramok

Nem sorolom fel az összes típust csak párat fogok kiemelni és leírom, hogy mire használható:

Diagram készítő motor Leírása
blockdiag, seqdiag, actdiag, nwdiag egy BlockDiag négyféle diagram: blokkdiagram, szekvencia-diagram, tevékenység-diagram és hálózati diagram készítő
BPMN XML-ben leírtak alapján egy BPMN ábrát készít
PlantUML UML diagramokat készít (9 féle) és hozzá még 4 más fajta (tevékenység, gantt, archimate, grafikus felület rajzoló)
ditaa Inkább érdekesség az ASCII karakterekből grafikus ábrát készítő motor
GraphViz Általános grafikon-megjelenítő szoftver (API) amit DOT nyelven lehet rajzolásra bírni
mermaid Markdown alapú weboldalak által is közkedvelt  JavaScript alap motor ami több diagramtípust (folyamatábra, szekvencia, gantt, class, állapotdiagram, kör diagram )
Svgbob Ditta-hoz hasonló, karakterekből ábrákat készítő motor
vega Saját deklaratív nyelven megírt diagramok készítéséhez. Nagyon figyelemre méltó projekt, a generált diagramok interaktívak is lehetnek.

A diagramkészítő eszközök nagyon jól használhatók online környezetben vagy dokumentáció készítésénél. Nagy előnyük, hogy a diagramokat nem grafikus felületen kell elkészíteni, hanem egy könnyebben karbantartható szöveges nyelvvel kell leírni amit a generátor értelmez és utána megrajzol.

A szakmai dokumentációkat

  • markdown vagy asciidoc leíró nyelvvel szerkesztem,
  • generátornak a pandoc-ot és asciidoctor-t használom
  • és hozzájuk az ábrákat egy megfelelő diagramkészítővel “írom” le.

Ennek a honlapnak a mostani motorja - a hexo - beépülő modulokon vagy szűrőkön keresztül támogat pár diagramkészítő munkáját, de közvetlenül a jelölőnyelvekbe is be lehet őket építeni. Például a pandoc, vagy asciidoctor motorok képesek a diagramkészítőket meghívni ezeket kezelni.

A Kroki teszteléshez készítettem példákat amit később bemutatok, de előbb lássuk a működési elvét.

Kroki telepítése és futtatása

Minden szükséges információ megtalálható a Kroki honlapján https://kroki.io/, itt sok példát is találunk és le is tesztelhetjük a diagramkészítő képességét.

Kroki CLI

Létezik kroki CLI parancssoros verzió amit innen lehet letölteni https://github.com/yuzutech/kroki-cli/releases/.

Segítséget a kroki convert -h paranccsal lehet kérni, de elsődleges információszerzés a honlap sokkal jobb. Egy uml konvertálása implicit formában így történik:

1
./kroki convert tesztabra.puml

Ez létrehozza a tesztabra.png ábránkat. A preferáltabb (explicit) formában minden lényeges paramétert megadhatunk:

1
./kroki convert tesztabra.puml --type plantuml --format png --out-file tesztabra.png

A fenti parancssorban láthatjuk, hogy több paramétert is tudunk állítani és beállítottuk, hogy png formátumban generálja ki az ábránkat.

A kroki-cli nem tud többet mint általában egy cli vagyis nem ő aki generál, hanem ehhez a feladathoz egy http szervert hív meg. Ez alapesetben a https://demo.kroki.io/, de ezt módosítani tudjuk paraméterekkel a kroki.yml fájlban. Nekem saját kroki szerverem van ami vagy egy jar fájl vagy éppen egy Docker konténer. Az én kroki.yml pereméter fájlom tartalma a következő:

kroki.yml
1
2
endpoint: 'http://localhost:8000'
timeout: '30s'

Vagyis a parancssoros kroki-cli az endpoint paraméterben levő http szervert hívja meg.

Kroki JAR

Ha szeretnénk a diagramgenerálást belső helyen tartani, akkor saját kroki szervert kell létrehozzunk.

A kroki JAVA alapú és beletettek minden olyan diagramgenerátort amit be tudtak integrálni. Azokat amelyek nem azokat külső programból próbálja meg elindítani. Vagyis ilyenkor CLI-ként működik.

Például a GraphViz vizualizációs program – ami a gépemen a dot paranccsal indítható – elérhetőnek kell lennie vagy külön paraméterben kell megadni az elérhetőségét. A jó hír, hogy a legtöbb diagramgenerátor azért integrálva van a kroki-server-0.7.1.jar fájlban.

Indítsuk el a krokit, úgy hogy megadjuk a GrapViz elérhetőségét is (ebben a példában ez nem jó helyre mutat):

1
java -DKROKI_DOT_BIN_PATH=/nem/jo/konyvtar/dot -jar kroki-server-0.7.1.jar

Amikor meghívjuk a kroki-cli-t akkor hibát fogunk kapni:

1
2
3
$ ./kroki convert graphviztest.gv --type graphviz --format png --out-file graphviztest.png
...
fail to generate the image {status: 500, body: Error 500: Internal Server Error}

A hiba a szervertől érkezik és ott a következőt látjuk:

hibára futott a kroki
1
2
3
4
17:21:09.052 [vert.x-eventloop-thread-0] INFO  i.k.server.service.DiagramHandler - Request received GET /graphviz/png/eNp8kM0OgjAQhO88xaYPoJEr8QTR-BsTH4CUsoFKsc3yczF9dxMELBI5zmTm282kMiNucojg5QFUTfKRQjVVjRSbzgZQPEEFW2An0oVkQWfO0mLTx53CHalF6hsAO6kwQV4PesbIRPylOJxIiwJp_YMDOPKWD8ouQP0F6AWp5DJ1qOyqU1w9Kte6NcZgjZPrLMxJl8imH9g_8_jzecLzYSzvteLPLBgR1rPeOwAA__-YWXCl
17:21:09.060 [vert.x-eventloop-thread-0] INFO i.k.server.service.DiagramHandler - Convert took 5ms
17:21:09.063 [vert.x-eventloop-thread-0] ERROR io.kroki.server.error.ErrorHandler - An error occurred
java.io.IOException: Cannot run program "/path/to/dot": error=2, No such file or directory

Hibát kaptunk, mert a dot futtató fájl nem volt elérhető. A hibanaplóból láthatunk még egy érdekességet (ami a kroki alapja is), hogy a kroki-cli egy http get paranccsal próbálta szóra bírni a kroki-server-t.

Kroki Docker

A haladóknak vagy mert haladunk a korral, használhatunk kroki konténert amit a Docker segítségével tudunk futtatni.

Ha még nincs Docker futtatónk, akkor azt innen kiindulva telepíthetjük https://docs.docker.com/get-docker/. Tételezzük fel, hogy már tudjuk futtatni a hello-world konténerünket, indítsuk el a kroki konténert és ellenőrizzük a futását:

Konténer indítása és ellenőrzése
1
2
3
4
$ sudo docker run -d yuzutech/kroki
$ sudo docker container ls
CONTAINER ID IMAGE COMMAND CREATED
9853918fdd63 yuzutech/kroki "/bin/sh -c 'exec ja…"

A kroki konténerünk fut és a 8000 porton várja a http hívásokat. Ha belenézünk a konténerbe, akkor azt látjuk, hogy fut benne a kroki-server.jar, ami nem meglepő. Ezen felül találunk pár paramétert ami arra utal, hogy a konténerünkbe megtalálható még elég sok diagramgenerátor futtatója is:

Konténerben található diagram generátorok
1
2
3
4
5
6
7
8
9
"Env": [
"KROKI_SVGBOB_BIN_PATH=/rust/bin/svgbob",
"KROKI_ERD_BIN_PATH=/haskell/bin/erd",
"KROKI_DOT_BIN_PATH=/usr/bin/dot",
"KROKI_NOMNOML_BIN_PATH=/node/bin/nomnoml",
"KROKI_VEGA_BIN_PATH=/node/bin/vega",
"KROKI_WAVEDROM_BIN_PATH=/node/bin/wavedrom",
"KROKI_BYTEFIELD_BIN_PATH=/node/bin/bytefield"
]

Hurrá 😃, majdnem teljes a 20-as lista. A hiányzókat mint a bpmn, mermaid és blockdiag újabb társ-konténereken keresztül érhetjük el. Ezek a társ konténerek a következők:

1
2
3
yuzutech/kroki-blockdiag
yuzutech/kroki-mermaid
yuzutech/kroki-bpmn

Ezeket egyenként is elindíthatjuk a fentebb leírt módon, de használhatjuk a docker-compose-t aminek a segítségével összefoghatjuk a konténereket. A docker-compose konfigurálását YAML fájlban tehetjük meg. A mi esetünkben ez így nézne ki:

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: "3"
services:
core:
image: yuzutech/kroki
environment:
- KROKI_BLOCKDIAG_HOST=blockdiag
- KROKI_MERMAID_HOST=mermaid
- KROKI_BPMN_HOST=bpmn
ports:
- "8000:8000"
blockdiag:
image: yuzutech/kroki-blockdiag
ports:
- "8001:8001"
mermaid:
image: yuzutech/kroki-mermaid
ports:
- "8002:8002"
bpmn:
image: yuzutech/kroki-bpmn
ports:
- "8003:8003"

Már csak futtatni kell:

Indítsuk el az összes kroki konténert
1
2
3
4
5
6
$ sudo docker-compose up -d
Creating network "kroki_default" with the default driver
Creating kroki_core_1 ... done
Creating kroki_mermaid_1 ... done
Creating kroki_bpmn_1 ... done
Creating kroki_blockdiag_1 ... done

És innentől egyetlen egy pontból http://localhost:8000 elérhetjük a kroki teljes funkcionalitását.

Kroki GET és POST

A kroki-server-t HTTP GET vagy POST kérésekkel lehet szóra bírni. A két módszer egy példán keresztül mutatom be.

Készítsünk egy marketing blokkdiagramot:

1
2
3
4
5
6
7
8
blockdiag {
Kroki -> diagramot -> "generál";
Kroki -> "nagyon jól" -> "működik!";

Kroki [color = "greenyellow"];
generál [color = "red"];
"működik!" [color = "gold"];
}

Kroki GET módszer

A fenti forráskódot konvertáljuk base64 kódolással, de előtte tömörítjük. A kroki honlapján egy python példa van erre, de ezt most helyettesítem linuxos parancsokkal:

Tömörítés -> Base64 kódolás és -> URL komfortá tétel
1
2
cat bd.txt | zlib-flate -compress | base64 -w0 | sed 's/+/-/g; s/\//_/g';
eJxLyslPzk7JTExXqOZSUPAuys_OVNC1UwCJFCXm5peAOErpqXmpRYcX5ihZI6tRyktMr8zPU8g6vDlHCSyQe3Rj9uFtKZnZikCVcKXRyfk5-UUKtkBzilJT8ypTc3Lyy5ViQWbBDEZSU5SaApFDNg3ZjPwcsIJaLgANbD6U

A bdiag.dot fájlban levő szövegből generált krikszkraksz a mi kulcsunk a diagramhoz. A varázslat, hogy a nem URL konform karaktereket átdolgozzuk. Ezt a kulcsot felhasználva hívjuk meg a kroki-t.

1
curl "http://localhost:8000/blockdiag/png/eJxLyslPzk7JTExXqOZSUPAuys_OVNC1UwCJFCXm5peAOErpqXmpRYcX5ihZI6tRyktMr8zPU8g6vDlHCSyQe3Rj9uFtKZnZikCVcKXRyfk5-UUKtkBzilJT8ypTc3Lyy5ViQWbBDEZSU5SaApFDNg3ZjPwcsIJaLgANbD6U" --output blockdiag-abra.png

Az végeredmény a lenti ábra lett. Hogy mitől GET? Hát attól, hogy a curl alapesetben GET üzenettel küldte el a kérést (böngészte). A fenti példát kipróbálhatjuk úgy is, hogy a böngészőbe másoljuk be a kérést és ott fogjuk megkapni az ábrát.

blockdiag-abra.png

Elsőnek bonyolultnak tűnhet a folyamat, de kezdő rendszergazda vagy programozó is tudna hozzá egy szkriptet vagy programot írni.

Mivel ez egy statikusan generált blog, itt illik a blog motorral generáltatni az ábrát. Egy picit módosítva a forrásszöveget, a hexo-filter-kroki által generált ábra így néz ki.

Ezt az ábrát a hexo-filter-kroki generálta. Mivel a beállításban azt adtam meg, hogy inline generáljon ezért beágyazta <svg></svg> közzé. Ezért is van az, hogy az ábrában levő szöveget ki is lehet választan. Az előző ábrához képest az eltérést a forrásszövegben történt módosítás okozza.

Kroki POST módszer

Itt megspórolhatjuk a base64 kódolást, mert a HTTP POST csomagküldés esetében nem a webcímbe tesszük be a kérést, hanem egy JSON fájlba.

kroki-post.json
1
2
3
4
5
{
"diagram_source": "actdiag {\r\n write -> convert -> image\r\n\r\n lane user {\r\n label = \"User\"\r\n write [label = \"Writing text\"];\r\n image [label = \"Get diagram image\"];\r\n }\r\n lane Kroki {\r\n convert [label = \"Convert text to image\"];\r\n }\r\n}",
"diagram_type": "actdiag",
"output_format": "png"
}

Ez azért néz ki ilyen bután, mert JSON esetében a diagram_source kulcs szöveget kell tartalmazzon, de a diagramleíró tele van soremelés, idézőjel meg minden más oda nem illő karakterrel. Ezért a forrást először konvertáltuk sima szöveggé.

Most is a curl a barátunk, de most nem csak webcímet hívunk, hanem csomagot is küldünk, amit a --data paraméter határoz meg.

1
$ curl -H "Content-Type: application/json" --data @kroki-post.json http://localhost:8000/ --output actiag-abra2.png

Az eredmény a következő lett.

actiag-abra2.png

Összefoglalás

Pandoc-hoz még nem találtam olyan szűrőt ami ki tudná használni a kroki lehetőségeit.

Asciidoctor-hoz van egy asciidoctor-kroki kiterjesztés amivel a teljes kroki diagram palettát be tudjuk a dokumentációnkba ágyazni.

Már említettem, hogy ezeket az oldalakat a hexo motor generálja és ezekhez a példákhoz a hexo-filter-kroki szűrő segítségével generálta ki.

A tesztek során megszerettem, mert önnálóan és konténerből is egyszerűen lehet használni. Céges szintem egy kroki szerver lefedi a diagramgenerálás feladatait és nem szükséges gépenként telepíteni.

Ajánlani tudom mindenkinek aki generált diagramokat szeretne készíteni és nem akar a diagramszerkesztő motorok telepítésével bajlódni. Azt megteszi helyettünk a kroki.