Einfache Konfiguration mit dem FabAccess Config Generator
Wolfram vom MakerSpace Leipzig hat 2024 ein umfangreiches Tool - den FabAccess Config Generator - entwickelt, um eine Konfiguration (bffh.dhall
) anhanganhand einer Maschinenliste im CSV-Format zu erzeugen.
Funktionsumfang
- Generierung von Maschinen
- Generierung von Rollen
- Generierung von Aktoren
- Generierung von einfachen Aktoren-Verbindungen
- Export einer gesonderten Rollenliste (interne ID & Anzeigename der Rolle)
- Abbildung der Struktur mittels Mermaid-Diagramm
- Direkte Aktualisierung einer bestehenden
bffh.dhall
Funktionsweise
Die CSV-Datei enthält pro Zeile einen Eintrag für eine Maschine. Neben Angaben zur Maschine selbst (ID, Wiki-URL etc.) werden Angaben zum Bereich vermerkt, in dem sich die Maschine befindet. Aus den Angaben zu den Bereichen werden dann alle Rollen abgeleitet.
Vollständige Dokumentation
Hier ist nur eine kurze Erklärung über das HowTo abgebildet. Eine umfangreiche und aktuelle Dokumentation findest du hier: https://elem74.github.io/fabaccess-config-generator-docs
Installation
Das Tool kann direkt auf dem Server oder auf einem beliebigen Client installiert werden. Das ist Geschmackssache.
cd /opt/fabinfra/
git clone https://github.com/elem74/fabaccess-config-generator.git
cd fabaccess-config-generator/
Konfigurationsdatei maschinenliste.csv editieren
vim maschinenliste.csv
http://docs.fab-access.org/data-fabaccess-config-generator/maschinenliste.csv
Sonstige Anpassungen
Alle weiteren Erklärungen zum Konzept und zu verschiedenen Einstellmöglichkeiten finden sich im Repository unter https://github.com/elem74/fabaccess-config-generator/tree/main?tab=readme-ov-file#nutzung-des-python-skripts
Output erzeugen
python3 config-generator.py
Das Tool schreibt automatisch ins Unterverzeichnis output/
die folgenden Dateien:
bffh-dhall-data.txt
Die Beispiel Dhall Daten sehen dabei wie folgt aus:
bffh-dhall-data.txt
roles = {
Admin = {
permissions = [
"bffh.users.manage",
"bffh.users.info",
"bffh.users.admin",
"beispielw.*",
]
},
_manager_schichtleitung = {
permissions = [
"beispielw.*",
]
},
beispielw_holz_manager = {
permissions = [
"beispielw.holz.*",
]
},
beispielw_holz_bandsaege_user = {
permissions = [
"beispielw.holz.bandsaege.disclose.*",
"beispielw.holz.bandsaege.read.*",
"beispielw.holz.bandsaege.write.*",
]
},
beispielw_holz_hobelmaschine_user = {
permissions = [
"beispielw.holz.hobelmaschine.disclose.*",
"beispielw.holz.hobelmaschine.read.*",
"beispielw.holz.hobelmaschine.write.*",
]
},
beispielw_holz_holzcnc_user = {
permissions = [
"beispielw.holz.holzcnc.disclose.*",
"beispielw.holz.holzcnc.read.*",
"beispielw.holz.holzcnc.write.*",
]
},
beispielw_holz_user = {
permissions = [
"beispielw.holz.disclose.*",
"beispielw.holz.read.*",
"beispielw.holz.write.*",
]
},
beispielw_textil_manager = {
permissions = [
"beispielw.textil.*",
]
},
beispielw_textil_user = {
permissions = [
"beispielw.textil.disclose.*",
"beispielw.textil.read.*",
"beispielw.textil.write.*",
]
},
beispielw_fablab_manager = {
permissions = [
"beispielw.fablab.*",
]
},
beispielw_fablab_3dprint_manager = {
permissions = [
"beispielw.fablab.3dprint.*",
]
},
beispielw_fablab_3dprint_user = {
permissions = [
"beispielw.fablab.3dprint.disclose.*",
"beispielw.fablab.3dprint.read.*",
"beispielw.fablab.3dprint.write.*",
]
},
beispielw_fablab_laser_manager = {
permissions = [
"beispielw.fablab.laser.*",
]
},
beispielw_fablab_laser_user = {
permissions = [
"beispielw.fablab.laser.disclose.*",
"beispielw.fablab.laser.read.*",
"beispielw.fablab.laser.write.*",
]
},
beispielw_siebdruck_manager = {
permissions = [
"beispielw.siebdruck.*",
]
},
beispielw_siebdruck_user = {
permissions = [
"beispielw.siebdruck.disclose.*",
"beispielw.siebdruck.read.*",
"beispielw.siebdruck.write.*",
]
},
beispielw_drucker = {
permissions = [
"beispielw.siebdruck.disclose.a3drucker",
"beispielw.siebdruck.read.a3drucker",
"beispielw.siebdruck.write.a3drucker",
"beispielw.buero.disclose.drucker",
"beispielw.buero.read.drucker",
"beispielw.buero.write.drucker",
]
},
beispielw_buero_manager = {
permissions = [
"beispielw.buero.*",
]
},
},
machines = {
beispielw-holz-bandsaege-bandsaege = {
name = "Bandsäge",
description = "Bandsäge im Holzbereich",
wiki = "",
category = "Holzwerkstatt",
disclose = "beispielw.holz.bandsaege.disclose.bandsaege",
read = "beispielw.holz.bandsaege.read.bandsaege",
write = "beispielw.holz.bandsaege.write.bandsaege",
manage = "beispielw.holz.bandsaege.manage.bandsaege",
},
beispielw-holz-hobelmaschine-hobelmaschine = {
name = "Hobelmaschine",
description = "Hobelmaschine im Holzbereich",
wiki = "",
category = "Holzwerkstatt",
disclose = "beispielw.holz.hobelmaschine.disclose.hobelmaschine",
read = "beispielw.holz.hobelmaschine.read.hobelmaschine",
write = "beispielw.holz.hobelmaschine.write.hobelmaschine",
manage = "beispielw.holz.hobelmaschine.manage.hobelmaschine",
},
beispielw-holz-holzcnc-holzcncfraese = {
name = "CNC-Fräse",
description = "CNC Fräse im Holzbereich",
wiki = "",
category = "Holzwerkstatt",
disclose = "beispielw.holz.holzcnc.disclose.holzcncfraese",
read = "beispielw.holz.holzcnc.read.holzcncfraese",
write = "beispielw.holz.holzcnc.write.holzcncfraese",
manage = "beispielw.holz.holzcnc.manage.holzcncfraese",
},
beispielw-holz-kappsaege = {
name = "Kappsäge",
description = "Kappsäge mit allgemeiner Einweisung Holz",
wiki = "",
category = "Holzwerkstatt",
disclose = "beispielw.holz.disclose.kappsaege",
read = "beispielw.holz.read.kappsaege",
write = "beispielw.holz.write.kappsaege",
manage = "beispielw.holz.manage.kappsaege",
},
beispielw-holz-bandschleifer = {
name = "Bandschleifer",
description = "Bandschleifer mit allgemeiner Einweisung Holz",
wiki = "",
category = "Holzwerkstatt",
disclose = "beispielw.holz.disclose.bandschleifer",
read = "beispielw.holz.read.bandschleifer",
write = "beispielw.holz.write.bandschleifer",
manage = "beispielw.holz.manage.bandschleifer",
},
beispielw-holz-staenderbohrmaschine = {
name = "Ständerbohrmaschine",
description = "Ständerbohrmaschine mit allgemeiner Einweisung Holz",
wiki = "",
category = "Holzwerkstatt",
disclose = "beispielw.holz.disclose.staenderbohrmaschine",
read = "beispielw.holz.read.staenderbohrmaschine",
write = "beispielw.holz.write.staenderbohrmaschine",
manage = "beispielw.holz.manage.staenderbohrmaschine",
},
beispielw-textil-naehmaschine1 = {
name = "Nähmaschine 1",
description = "Nähmaschine Nummer 1",
wiki = "",
category = "Textilwerkstatt",
disclose = "beispielw.textil.disclose.naehmaschine1",
read = "beispielw.textil.read.naehmaschine1",
write = "beispielw.textil.write.naehmaschine1",
manage = "beispielw.textil.manage.naehmaschine1",
},
beispielw-textil-naehmaschine2 = {
name = "Nähmaschine 2",
description = "Nähmaschine Nummer 2",
wiki = "",
category = "Textilwerkstatt",
disclose = "beispielw.textil.disclose.naehmaschine2",
read = "beispielw.textil.read.naehmaschine2",
write = "beispielw.textil.write.naehmaschine2",
manage = "beispielw.textil.manage.naehmaschine2",
},
beispielw-fablab-3dprint-3ddrucker1 = {
name = "3D-Drucker 1",
description = "3D-Drucker Modell 111",
wiki = "",
category = "FabLab",
disclose = "beispielw.fablab.3dprint.disclose.3ddrucker1",
read = "beispielw.fablab.3dprint.read.3ddrucker1",
write = "beispielw.fablab.3dprint.write.3ddrucker1",
manage = "beispielw.fablab.3dprint.manage.3ddrucker1",
},
beispielw-fablab-3dprint-3ddrucker2 = {
name = "3D-Drucker 2",
description = "3D-Drucker Modell 222",
wiki = "",
category = "FabLab",
disclose = "beispielw.fablab.3dprint.disclose.3ddrucker2",
read = "beispielw.fablab.3dprint.read.3ddrucker2",
write = "beispielw.fablab.3dprint.write.3ddrucker2",
manage = "beispielw.fablab.3dprint.manage.3ddrucker2",
},
beispielw-fablab-laser-laser3000 = {
name = "Lasercutter",
description = "Modell Laser3000",
wiki = "https://www.fiktivedoku.de",
category = "FabLab",
disclose = "beispielw.fablab.laser.disclose.laser3000",
read = "beispielw.fablab.laser.read.laser3000",
write = "beispielw.fablab.laser.write.laser3000",
manage = "beispielw.fablab.laser.manage.laser3000",
},
beispielw-fablab-laser-kuehlung3000 = {
name = "Kühlung",
description = "Modell Kühlung3000",
wiki = "",
category = "FabLab",
disclose = "beispielw.fablab.laser.disclose.kuehlung3000",
read = "beispielw.fablab.laser.read.kuehlung3000",
write = "beispielw.fablab.laser.write.kuehlung3000",
manage = "beispielw.fablab.laser.manage.kuehlung3000",
},
beispielw-siebdruck-sdbelichter = {
name = "SD-Belichter",
description = "Belichter für die Siebe",
wiki = "",
category = "Siebdruck",
disclose = "beispielw.siebdruck.disclose.sdbelichter",
read = "beispielw.siebdruck.read.sdbelichter",
write = "beispielw.siebdruck.write.sdbelichter",
manage = "beispielw.siebdruck.manage.sdbelichter",
},
beispielw-siebdruck-a3drucker = {
name = "A3-Drucker",
description = "A3 Drucker im Siebdruck Bereich",
wiki = "",
category = "Siebdruck",
disclose = "beispielw.siebdruck.disclose.a3drucker",
read = "beispielw.siebdruck.read.a3drucker",
write = "beispielw.siebdruck.write.a3drucker",
manage = "beispielw.siebdruck.manage.a3drucker",
},
beispielw-buero-drucker = {
name = "Drucker",
description = "",
wiki = "",
category = "Büro",
disclose = "beispielw.buero.disclose.drucker",
read = "beispielw.buero.read.drucker",
write = "beispielw.buero.write.drucker",
manage = "beispielw.buero.manage.drucker",
},
},
actors = {
tasmota_1 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 1",
}
},
tasmota_2 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 2",
}
},
tasmota_6 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 6",
}
},
tasmota_7 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 7",
}
},
tasmota_8 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 8",
}
},
tasmota_9 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 9",
}
},
tasmota_10 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 10",
}
},
tasmota_11 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 11",
}
},
tasmota_12 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 12",
}
},
tasmota_13 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 13",
}
},
tasmota_14 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 14",
}
},
tasmota_15 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 15",
}
},
tasmota_16 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 16",
}
},
tasmota_17 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 17",
}
},
tasmota_18 =
{
module = "Process",
params =
{
cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py",
args = "--host mqtt --tasmota 18",
}
},
},
actor_connections = [
{ machine = "beispielw-holz-bandsaege-bandsaege", actor = "tasmota_1" },
{ machine = "beispielw-holz-hobelmaschine-hobelmaschine", actor = "tasmota_2" },
{ machine = "beispielw-holz-holzcnc-holzcncfraese", actor = "tasmota_6" },
{ machine = "beispielw-holz-kappsaege", actor = "tasmota_7" },
{ machine = "beispielw-holz-bandschleifer", actor = "tasmota_8" },
{ machine = "beispielw-holz-staenderbohrmaschine", actor = "tasmota_9" },
{ machine = "beispielw-textil-naehmaschine1", actor = "tasmota_10" },
{ machine = "beispielw-textil-naehmaschine2", actor = "tasmota_11" },
{ machine = "beispielw-fablab-3dprint-3ddrucker1", actor = "tasmota_12" },
{ machine = "beispielw-fablab-3dprint-3ddrucker2", actor = "tasmota_13" },
{ machine = "beispielw-fablab-laser-laser3000", actor = "tasmota_14" },
{ machine = "beispielw-fablab-laser-kuehlung3000", actor = "tasmota_15" },
{ machine = "beispielw-siebdruck-sdbelichter", actor = "tasmota_16" },
{ machine = "beispielw-siebdruck-a3drucker", actor = "tasmota_17" },
{ machine = "beispielw-buero-drucker", actor = "tasmota_18" },
],
mermaid-code.txt
Der Beispiel Mermaid Code sieht wie folgt aus und kann in https://mermaid.live gerendet werden.
mermaid-code.txt
%%{init: {"flowchart" : {"curve" : "linear"}}}%%
flowchart TD
subgraph legende["<b>Legende</b><p style="text-align:left;">👑 = Administrator
🛠️ = Manager
👷♂️ = Benutzer
👩🚀 = Benutzer (Alternativrolle)"]
end
subgraph root["
<p style="font-size: 2em">Infrastruktur</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>👑_Admin FabAccess<br>🛠️_Manager Schichtleitung</p></p>
<p style="text-align: left; margin-top: 0px;"></p>
<p style="opacity: 0;">.</p>
"]
end
subgraph root_beispielw["
<p style="font-size: 1.75em">Beispielwerkstatt </p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Beispielwerkstatt </p></p>
<p style="text-align: left; margin-top: 0px;"></p>
<p style="opacity: 0;">.</p>
"]
end
root ------ root_beispielw
root_beispielw ---- root_beispielw_buero_wrapper
subgraph root_beispielw_buero_wrapper["<p style="opacity: 0;">.</p>"]
style root_beispielw_buero_wrapper stroke: none, fill: none
subgraph root_beispielw_buero["
<p style="font-size: 1.5em">Büro</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Büro<br>👷♂️Benutzer Büro<br>👩🚀Benutzer Druckernutzung</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>Drucker (👩🚀Benutzer Druckernutzung)</p>
<p style="opacity: 0;">.</p>
"]
end
subgraph filler_root_beispielw_buero_1["
<p style="opacity: 0;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</p>"]
end
style filler_root_beispielw_buero_1 fill: none, stroke: none
root_beispielw_buero~~~~~~filler_root_beispielw_buero_1
subgraph filler_root_beispielw_buero_2["
<p style="opacity: 0;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</p>"]
end
style filler_root_beispielw_buero_2 fill: none, stroke: none
filler_root_beispielw_buero_1~~~~~filler_root_beispielw_buero_2
end
root_beispielw ---- root_beispielw_fablab_wrapper
subgraph root_beispielw_fablab_wrapper["<p style="opacity: 0;">.</p>"]
style root_beispielw_fablab_wrapper stroke: none, fill: none
subgraph root_beispielw_fablab["
<p style="font-size: 1.5em">FabLab</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager FabLab<br>👷♂️Benutzer FabLab</p></p>
<p style="text-align: left; margin-top: 0px;"></p>
<p style="opacity: 0;">.</p>
"]
end
subgraph root_beispielw_fablab_3dprint["
<p style="font-size: 1.25em">3D-Druck</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager FabLab 3D-Druck<br>👷♂️Benutzer FabLab 3D-Druck</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>3D-Drucker 1<br>3D-Drucker 2</p>
<p style="opacity: 0;">.</p>
"]
end
root_beispielw_fablab ------ root_beispielw_fablab_3dprint
subgraph root_beispielw_fablab_laser["
<p style="font-size: 1.25em">Laser</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager FabLab Laser<br>👷♂️Benutzer FabLab Laser</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>Lasercutter<br>Kühlung</p>
<p style="opacity: 0;">.</p>
"]
end
root_beispielw_fablab ------ root_beispielw_fablab_laser
end
root_beispielw ---- root_beispielw_holz_wrapper
subgraph root_beispielw_holz_wrapper["<p style="opacity: 0;">.</p>"]
style root_beispielw_holz_wrapper stroke: none, fill: none
subgraph root_beispielw_holz["
<p style="font-size: 1.5em">Holzwerkstatt</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Holzwerkstatt<br>👷♂️Benutzer Holzwerkstatt</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>Kappsäge<br>Bandschleifer<br>Ständerbohrmaschine</p>
<p style="opacity: 0;">.</p>
"]
end
subgraph root_beispielw_holz_bandsaege["
<p style="font-size: 1.25em">Bandsäge</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Holzwerkstatt Bandsäge<br>👷♂️Benutzer Holzwerkstatt Bandsäge</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>Bandsäge</p>
<p style="opacity: 0;">.</p>
"]
end
root_beispielw_holz ------ root_beispielw_holz_bandsaege
subgraph root_beispielw_holz_hobelmaschine["
<p style="font-size: 1.25em">Hobelmaschine</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Holzwerkstatt Hobelmaschine<br>👷♂️Benutzer Holzwerkstatt Hobelmaschine</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>Hobelmaschine</p>
<p style="opacity: 0;">.</p>
"]
end
root_beispielw_holz ------ root_beispielw_holz_hobelmaschine
subgraph root_beispielw_holz_holzcnc["
<p style="font-size: 1.25em">CNC-Fräse</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Holzwerkstatt CNC-Fräse<br>👷♂️Benutzer Holzwerkstatt CNC-Fräse</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>CNC-Fräse</p>
<p style="opacity: 0;">.</p>
"]
end
root_beispielw_holz ------ root_beispielw_holz_holzcnc
end
root_beispielw ---- root_beispielw_siebdruck_wrapper
subgraph root_beispielw_siebdruck_wrapper["<p style="opacity: 0;">.</p>"]
style root_beispielw_siebdruck_wrapper stroke: none, fill: none
subgraph root_beispielw_siebdruck["
<p style="font-size: 1.5em">Siebdruck</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Siebdruck<br>👷♂️Benutzer Siebdruck<br>👩🚀Benutzer Druckernutzung</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>SD-Belichter<br>A3-Drucker (👩🚀Benutzer Druckernutzung)</p>
<p style="opacity: 0;">.</p>
"]
end
subgraph filler_root_beispielw_siebdruck_1["
<p style="opacity: 0;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</p>"]
end
style filler_root_beispielw_siebdruck_1 fill: none, stroke: none
root_beispielw_siebdruck~~~~~~filler_root_beispielw_siebdruck_1
subgraph filler_root_beispielw_siebdruck_2["
<p style="opacity: 0;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</p>"]
end
style filler_root_beispielw_siebdruck_2 fill: none, stroke: none
filler_root_beispielw_siebdruck_1~~~~~filler_root_beispielw_siebdruck_2
end
root_beispielw ---- root_beispielw_textil_wrapper
subgraph root_beispielw_textil_wrapper["<p style="opacity: 0;">.</p>"]
style root_beispielw_textil_wrapper stroke: none, fill: none
subgraph root_beispielw_textil["
<p style="font-size: 1.5em">Textilwerkstatt</p><p style="text-align: left; margin-top: 20px;"><b><center>Rollen</center></b>🛠️Manager Textilwerkstatt<br>👷♂️Benutzer Textilwerkstatt</p></p>
<p style="text-align: left; margin-top: 0px;"><b><center>Maschinen</center></b>Nähmaschine 1<br>Nähmaschine 2</p>
<p style="opacity: 0;">.</p>
"]
end
subgraph filler_root_beispielw_textil_1["
<p style="opacity: 0;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</p>"]
end
style filler_root_beispielw_textil_1 fill: none, stroke: none
root_beispielw_textil~~~~~~filler_root_beispielw_textil_1
subgraph filler_root_beispielw_textil_2["
<p style="opacity: 0;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</p>"]
end
style filler_root_beispielw_textil_2 fill: none, stroke: none
filler_root_beispielw_textil_1~~~~~filler_root_beispielw_textil_2
end
roles.csv
http://docs.fab-access.org/data-fabaccess-config-generator/roles.csv