diff --git a/data_converion/tomd.py b/data_converion/tomd.py
new file mode 100644
index 0000000..147b965
--- /dev/null
+++ b/data_converion/tomd.py
@@ -0,0 +1,5 @@
+import tomd
+
+tomd.Tomd('
h1
').markdown
+# or
+tomd.convert('h1
')
\ No newline at end of file
diff --git a/data_transfer/Add Container Inventory to Directus.ipynb b/data_transfer/Add Container Inventory to Directus.ipynb
new file mode 100644
index 0000000..2d3046b
--- /dev/null
+++ b/data_transfer/Add Container Inventory to Directus.ipynb
@@ -0,0 +1,127 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2bec1b04-f1ab-4165-a4ea-cc890cc9e5ec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!python -m pip install gql"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dca88210-18db-45ee-9949-7010b92dbae7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "import os\n",
+ "import pprint\n",
+ "\n",
+ "import requests\n",
+ "from gql import Client, gql\n",
+ "from gql.transport.requests import RequestsHTTPTransport\n",
+ "\n",
+ "cwd = os.getcwd()\n",
+ "print(cwd)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7374f89e-23f8-407d-967b-c76e7d6d93a2",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "with open(\"/home/jovyan/code/directus/docker.json\") as f:\n",
+ " scrubbed_records = json.load(f)\n",
+ "\n",
+ "# print(scrubbed_records[0])\n",
+ "item = scrubbed_records[0]\n",
+ "name = item[\"Name\"]\n",
+ "image = item[\"Config\"][\"Image\"]\n",
+ "# print(name)\n",
+ "# print(image)\n",
+ "image = image.replace(\":latest\", \"\")\n",
+ "name = name.replace(\"/\", \"\")\n",
+ "print(name)\n",
+ "print(image)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2b300a9-f7c0-4863-9696-29e92e6cedc8",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "for x in scrubbed_records:\n",
+ " # pprint.pprint(x)\n",
+ " item = x\n",
+ " name = item[\"Name\"]\n",
+ " image = item[\"Config\"][\"Image\"]\n",
+ " image = image.replace(\":latest\", \"\")\n",
+ " name = name.replace(\"/\", \"\")\n",
+ " print(name)\n",
+ " print(image)\n",
+ " input_set = {\"id\": name, \"image\": image, \"name\": name, \"raw\": item}\n",
+ "\n",
+ " my_headers = {\n",
+ " \"Authorization\": os.getenv(directus_token),\n",
+ " \"Content-Type\": \"application/json\",\n",
+ " }\n",
+ " response = requests.post(\n",
+ " \"https://cms.donavanaldrich.com/items/containers\",\n",
+ " headers=my_headers,\n",
+ " json=(input_set),\n",
+ " )\n",
+ " print(response.json())"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.9.13 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ },
+ "toc-autonumbering": false,
+ "toc-showcode": false,
+ "toc-showtags": false,
+ "vscode": {
+ "interpreter": {
+ "hash": "340e956ee656efd8fdfb480dc033c937d9b626f8b21073bd1b5aa2a469586ea6"
+ }
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/data_transfer/Add Homebrew Inventory to Directusa.ipynb b/data_transfer/Add Homebrew Inventory to Directusa.ipynb
new file mode 100644
index 0000000..d5a3c4c
--- /dev/null
+++ b/data_transfer/Add Homebrew Inventory to Directusa.ipynb
@@ -0,0 +1,326 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2bec1b04-f1ab-4165-a4ea-cc890cc9e5ec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!python -m pip install gql"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7374f89e-23f8-407d-967b-c76e7d6d93a2",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import csv\n",
+ "\n",
+ "with open(\"/home/jovyan/code/directus/homebrew.txt\") as f:\n",
+ " reader = csv.reader(f)\n",
+ " for row in reader:\n",
+ " item = row[0]\n",
+ " print(item)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f0367eee-e052-4184-b016-8ecb0dd1aa32",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "for x in scrubbed_records:\n",
+ " # pprint.pprint(x)\n",
+ " image = image.replace(\":latest\", \"\")\n",
+ " name = name.replace(\"/\", \"\")\n",
+ " data = x"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2b300a9-f7c0-4863-9696-29e92e6cedc8",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "for x in scrubbed_records:\n",
+ " item = x\n",
+ " name = item[\"Name\"]\n",
+ " image = item[\"Config\"][\"Image\"]\n",
+ " image = image.replace(\":latest\", \"\")\n",
+ " name = name.replace(\"/\", \"\")\n",
+ " print(name)\n",
+ " print(image)\n",
+ " input_set = {\"id\": name, \"image\": image, \"name\": name, \"raw\": item}\n",
+ "\n",
+ " my_headers = {\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " \"Content-Type\": \"application/json\",\n",
+ " }\n",
+ " response = requests.post(\n",
+ " \"https://cms.donavanaldrich.com/items/containers\",\n",
+ " headers=my_headers,\n",
+ " json=(input_set),\n",
+ " )\n",
+ " print(response.json())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a4dc5471-3df9-4d52-865e-ca9202d472a3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# https://formulae.brew.sh/api/cask.json"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "74566291-5fb8-455a-b674-03c0733c6700",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'appcast': None,\n",
+ " 'artifacts': [['0 A.D..app'],\n",
+ " {'signal': {},\n",
+ " 'trash': '~/Library/Saved Application '\n",
+ " 'State/com.wildfiregames.0ad.savedState'}],\n",
+ " 'auto_updates': None,\n",
+ " 'caveats': None,\n",
+ " 'conflicts_with': None,\n",
+ " 'container': None,\n",
+ " 'depends_on': {'macos': {'>=': ['10.12']}},\n",
+ " 'desc': 'Real-time strategy game',\n",
+ " 'full_token': '0-ad',\n",
+ " 'homepage': 'https://play0ad.com/',\n",
+ " 'installed': None,\n",
+ " 'name': ['0 A.D.'],\n",
+ " 'outdated': False,\n",
+ " 'sha256': 'd1a2073dee3435d8a78bf289206248c9ed6be5e17f4ba1ac8412caf6d0eae0b0',\n",
+ " 'tap': 'homebrew/cask',\n",
+ " 'token': '0-ad',\n",
+ " 'url': 'https://releases.wildfiregames.com/0ad-0.0.25b-alpha-osx64.dmg',\n",
+ " 'version': '0.0.25b-alpha',\n",
+ " 'versions': {}}\n"
+ ]
+ }
+ ],
+ "source": [
+ "import json\n",
+ "import os\n",
+ "import pprint\n",
+ "\n",
+ "import requests\n",
+ "\n",
+ "my_headers = {\"Content-Type\": \"application/json\"}\n",
+ "raw_casks = requests.get(\"https://formulae.brew.sh/api/cask.json\")\n",
+ "\n",
+ "casks = raw_casks.json()\n",
+ "\n",
+ "# pprint.pprint(casks[0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7b3f64e7-019a-4c21-9de2-5c84bd22640f",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "for cask in casks:\n",
+ " name = cask[\"name\"][0]\n",
+ " desc = cask[\"desc\"]\n",
+ " homepage = cask[\"homepage\"]\n",
+ " url = cask[\"url\"]\n",
+ " tap = cask[\"tap\"]\n",
+ " full_name = cask[\"full_token\"]\n",
+ " print(full_token)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "1d6f86f0-91ab-4773-aba3-ace57852f9e4",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'raw' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m/tmp/ipykernel_9736/2986828884.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mcategory\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"cask\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0minput_set\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m\"id\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mfull_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"description\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mdesc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"homepage\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mhomepage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"tap\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mtap\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"raw\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mraw\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"category\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mcategory\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 13\u001b[0m response = requests.post(\n\u001b[1;32m 14\u001b[0m \u001b[0;34m\"https://cms.donavanaldrich.com/items/all_homebrews\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mNameError\u001b[0m: name 'raw' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "my_headers = {\"Authorization\": \"os.env(directus_token)\", \"Content-Type\": \"application/json\"}\n",
+ "\n",
+ "for cask in casks:\n",
+ " name = cask[\"name\"][0]\n",
+ " desc = cask[\"desc\"]\n",
+ " homepage = cask[\"homepage\"]\n",
+ " url = cask[\"url\"]\n",
+ " tap = cask[\"tap\"]\n",
+ " full_name = cask[\"full_token\"]\n",
+ " category = \"cask\"\n",
+ " # raw\n",
+ "\n",
+ " input_set = {\n",
+ " \"id\": full_name,\n",
+ " \"description\": desc,\n",
+ " \"homepage\": homepage,\n",
+ " \"tap\": tap,\n",
+ " \"raw\": cask,\n",
+ " \"category\": category,\n",
+ " }\n",
+ " response = requests.post(\n",
+ " \"https://cms.donavanaldrich.com/items/all_homebrews\",\n",
+ " headers=my_headers,\n",
+ " json=(input_set),\n",
+ " )\n",
+ " print(response.json())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ecab5d16-91a5-4a3d-9772-516410b8ce76",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# https://formulae.brew.sh/api/formula.json"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "762b9c4d-dbfb-45dc-a24f-ca1a3a3bbbcf",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "my_headers = {\"Content-Type\": \"application/json\"}\n",
+ "raw_brews = requests.get(\"https://formulae.brew.sh/api/formula.json\")\n",
+ "\n",
+ "brews = raw_brews.json()\n",
+ "\n",
+ "pprint.pprint(brews[0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9bb9a11e-4343-421c-820d-ef927e02532f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for brew in brews:\n",
+ " name = brew[\"name\"]\n",
+ " desc = brew[\"desc\"]\n",
+ " homepage = brew[\"homepage\"]\n",
+ " url = brew[\"urls\"][\"stable\"][\"url\"]\n",
+ " tap = brew[\"tap\"]\n",
+ " full_name = brew[\"full_name\"]\n",
+ " print(urls)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9630a738-10ef-40a0-b666-097b0ab02c06",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "my_headers = {\"Authorization\": \"os.env(directus_token)\", \"Content-Type\": \"application/json\"}\n",
+ "\n",
+ "for brew in brews:\n",
+ " name = brew[\"name\"]\n",
+ " desc = brew[\"desc\"]\n",
+ " homepage = brew[\"homepage\"]\n",
+ " url = brew[\"urls\"][\"stable\"][\"url\"]\n",
+ " tap = brew[\"tap\"]\n",
+ " full_name = brew[\"full_name\"]\n",
+ " category = \"brew\"\n",
+ "\n",
+ " input_set = {\n",
+ " \"id\": full_name,\n",
+ " \"description\": desc,\n",
+ " \"homepage\": homepage,\n",
+ " \"tap\": tap,\n",
+ " \"raw\": brew,\n",
+ " \"category\": category,\n",
+ " }\n",
+ " response = requests.post(\n",
+ " \"https://cms.donavanaldrich.com/items/all_homebrews\",\n",
+ " headers=my_headers,\n",
+ " json=(input_set),\n",
+ " )\n",
+ " print(response.json())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b835d52d-88bd-49f5-a1e3-d2b3c56e4fb2",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ },
+ "toc-autonumbering": false,
+ "toc-showcode": false,
+ "toc-showtags": false,
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/data_transfer/Add Inventories to wiki.ipynb b/data_transfer/Add Inventories to wiki.ipynb
new file mode 100644
index 0000000..be552a6
--- /dev/null
+++ b/data_transfer/Add Inventories to wiki.ipynb
@@ -0,0 +1,324 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2bec1b04-f1ab-4165-a4ea-cc890cc9e5ec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pip install gql"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "dca88210-18db-45ee-9949-7010b92dbae7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "import os\n",
+ "import pprint\n",
+ "\n",
+ "import requests\n",
+ "from gql import Client, gql\n",
+ "from gql.transport.requests import RequestsHTTPTransport\n",
+ "\n",
+ "cwd = os.getcwd()\n",
+ "print(cwd)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "7374f89e-23f8-407d-967b-c76e7d6d93a2",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "active_workflow\n",
+ "automaticmode/active_workflow\n"
+ ]
+ }
+ ],
+ "source": [
+ "data_json = os.env(PATH)\n",
+ "\n",
+ "\n",
+ "with open(data_json) as f:\n",
+ " scrubbed_records = json.load(f)\n",
+ "\n",
+ "# print(scrubbed_records[0])\n",
+ "item = scrubbed_records[0]\n",
+ "name = item[\"Name\"]\n",
+ "image = item[\"Config\"][\"Image\"]\n",
+ "# print(name)\n",
+ "# print(image)\n",
+ "image = image.replace(\":latest\", \"\")\n",
+ "name = name.replace(\"/\", \"\")\n",
+ "print(name)\n",
+ "print(image)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f0367eee-e052-4184-b016-8ecb0dd1aa32",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "for x in scrubbed_records:\n",
+ " # pprint.pprint(x)\n",
+ " image = image.replace(\":latest\", \"\")\n",
+ " name = name.replace(\"/\", \"\")\n",
+ " data = x"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2b300a9-f7c0-4863-9696-29e92e6cedc8",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "for x in scrubbed_records:\n",
+ " # pprint.pprint(x)\n",
+ " item = x\n",
+ " name = item[\"Name\"]\n",
+ " image = item[\"Config\"][\"Image\"]\n",
+ " image = image.replace(\":latest\", \"\")\n",
+ " name = name.replace(\"/\", \"\")\n",
+ " print(name)\n",
+ " print(image)\n",
+ " input_set = {\"id\": name, \"image\": image, \"name\": name, \"raw\": item}\n",
+ "\n",
+ " my_headers = {\"Authorization\": \"os.env(directus_token)\", \"Content-Type\": \"application/json\"}\n",
+ " response = requests.post(\n",
+ " \"https://cms.donavanaldrich.com/items/containers\",\n",
+ " headers=my_headers,\n",
+ " json=(input_set),\n",
+ " )\n",
+ " print(response.json())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "927fe89f-9660-4681-884b-f258fc669b88",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pip install gql[all] aiohttp\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "id": "a4dc5471-3df9-4d52-865e-ca9202d472a3",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'RequestsHTTPTransport' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m/tmp/ipykernel_7244/3689489481.py\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m sample_transport = RequestsHTTPTransport(\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"http://directus:8055/graphql\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0muse_json\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m headers={\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\"Content-type\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m\"application/json\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mNameError\u001b[0m: name 'RequestsHTTPTransport' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "\n",
+ "sample_transport = RequestsHTTPTransport(\n",
+ " url=\"http://directus:8055/graphql\",\n",
+ " use_json=True,\n",
+ " headers={\n",
+ " \"Content-type\": \"application/json\",\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " },\n",
+ " verify=True,\n",
+ " retries=3,\n",
+ ")\n",
+ "\n",
+ "client = Client(\n",
+ " transport=sample_transport,\n",
+ " fetch_schema_from_transport=True,\n",
+ ")\n",
+ "\n",
+ "query = gql(\n",
+ " '''\n",
+ " query {\n",
+ " pages {\n",
+ " single(id: 3) {\n",
+ " id\n",
+ " path\n",
+ " locale\n",
+ " title\n",
+ " description\n",
+ " contentType\n",
+ " isPublished\n",
+ " isPrivate\n",
+ " privateNS\n",
+ " createdAt\n",
+ " updatedAt\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "'''\n",
+ ")\n",
+ "\n",
+ "# params = { \"title\": article_attributes_data-posted-on }\n",
+ "\n",
+ "result = client.execute(query, variable_values=params)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "48935cc6-c7c7-43f7-9fb7-c34bd457c903",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import asyncio\n",
+ "\n",
+ "from gql import gql, Client\n",
+ "from gql.transport.aiohttp import AIOHTTPTransport\n",
+ "\n",
+ "transport = AIOHTTPTransport(\n",
+ " url=\"http://wiki:3000/graphql\",\n",
+ " headers={\n",
+ " \"Content-type\": \"application/json\",\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " },\n",
+ ")\n",
+ "\n",
+ "# Create a GraphQL client using the defined transport\n",
+ "# client = Client(transport=transport, fetch_schema_from_transport=True)\n",
+ "client = Client(transport=transport, fetch_schema_from_transport=False)\n",
+ "# client = Client(transport=transport, fetch_schema_from_transport=True)\n",
+ "\n",
+ "query = gql(\n",
+ " '''\n",
+ " query pageList {\n",
+ " pages {\n",
+ " list(locale: \"en\") {\n",
+ " id\n",
+ " path\n",
+ " locale\n",
+ " title\n",
+ " description\n",
+ " contentType\n",
+ " isPublished\n",
+ " isPrivate\n",
+ " privateNS\n",
+ " createdAt\n",
+ " updatedAt\n",
+ " tags\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "'''\n",
+ ")\n",
+ "\n",
+ "\n",
+ "\n",
+ "# result = await session.execute(query)\n",
+ "# print(result)\n",
+ "result = await client.execute_async(query)\n",
+ "print(result)\n",
+ "\n",
+ " \n",
+ "# asyncio.run(main())\n",
+ "# Execute the query on the transport\n",
+ "# result = await client.execute_async(query)\n",
+ "# print(result)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cfe2738f-7b10-45e2-bb31-38e8820b1ed6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from gql import gql, Client\n",
+ "from gql.transport.aiohttp import AIOHTTPTransport\n",
+ "\n",
+ "# Select your transport with a defined url endpoint\n",
+ "transport = AIOHTTPTransport(url=\"https://countries.trevorblades.com/\")\n",
+ "\n",
+ "# Create a GraphQL client using the defined transport\n",
+ "client = Client(transport=transport, fetch_schema_from_transport=True)\n",
+ "\n",
+ "# Provide a GraphQL query\n",
+ "query = gql(\n",
+ " \"\"\"\n",
+ " query getContinents {\n",
+ " continents {\n",
+ " code\n",
+ " name\n",
+ " }\n",
+ " }\n",
+ "\"\"\"\n",
+ ")\n",
+ "\n",
+ "# Execute the query on the transport\n",
+ "result = client.execute(query)\n",
+ "print(result)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.8.9 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.9"
+ },
+ "toc-autonumbering": false,
+ "toc-showcode": false,
+ "toc-showtags": false,
+ "vscode": {
+ "interpreter": {
+ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
+ }
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/data_transfer/Add Linkace Inventory to Directus.ipynb b/data_transfer/Add Linkace Inventory to Directus.ipynb
new file mode 100644
index 0000000..bfe865c
--- /dev/null
+++ b/data_transfer/Add Linkace Inventory to Directus.ipynb
@@ -0,0 +1,198 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "5a2a0654",
+ "metadata": {},
+ "source": [
+ "curl --request GET \\\n",
+ " --url https://demo.linkace.org/api/v1/links \\\n",
+ " --header 'Authorization: Bearer undefined' \\\n",
+ " --header 'Content-Type: application/json' \\\n",
+ " --header 'accept: application/json'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "60990b52",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ebef409e-ddc1-4cc4-bd4d-a4839ba62d66",
+ "metadata": {},
+ "source": [
+ "## Pull links from Linkace"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "02d6d963-538a-47c1-957f-06c7ea7c7497",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "import os\n",
+ "import pprint\n",
+ "import urllib.parse\n",
+ "import sys\n",
+ "import requests\n",
+ "\n",
+ "my_headers = {\n",
+ " \"Authorization\": os.env(LINKACE_TOKEN),\n",
+ " \"Content-Type\": \"application/json\",\n",
+ " \"Accept\": \"application/json\",\n",
+ "}\n",
+ "\n",
+ "response = requests.get(\n",
+ " \"http://linkace/api/v1/links\",\n",
+ " headers=my_headers,\n",
+ ")\n",
+ "\n",
+ "initial = response.json()\n",
+ "\n",
+ "last = initial['last_page']\n",
+ "\n",
+ "links = []\n",
+ "\n",
+ "for x in range(1, last + 1):\n",
+ " response = requests.get(\n",
+ " \"http://linkace/api/v1/links?page=\" + str(x),\n",
+ " headers=my_headers,\n",
+ " )\n",
+ " result = response.json()\n",
+ " data = result['data']\n",
+ " links = links + data\n",
+ " \n",
+ "out_file = open(\"links.json\", \"w\")\n",
+ "json.dump(links, out_file, indent = 2)\n",
+ "out_file.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e6a27401-cc7d-4ffe-834d-2f051dce7025",
+ "metadata": {},
+ "source": [
+ "## Update Links in Directus"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "f2b300a9-f7c0-4863-9696-29e92e6cedc8",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [
+ {
+ "ename": "JSONDecodeError",
+ "evalue": "[Errno Expecting value] : 0",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)",
+ "File \u001b[0;32m/opt/conda/lib/python3.9/site-packages/requests/models.py:910\u001b[0m, in \u001b[0;36mResponse.json\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 909\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 910\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mcomplexjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 911\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m JSONDecodeError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 912\u001b[0m \u001b[38;5;66;03m# Catch JSON-related errors and raise as requests.JSONDecodeError\u001b[39;00m\n\u001b[1;32m 913\u001b[0m \u001b[38;5;66;03m# This aliases json.JSONDecodeError and simplejson.JSONDecodeError\u001b[39;00m\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.9/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 344\u001b[0m parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 345\u001b[0m parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.9/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m 333\u001b[0m \u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m 334\u001b[0m \u001b[38;5;124;03mcontaining a JSON document).\u001b[39;00m\n\u001b[1;32m 335\u001b[0m \n\u001b[1;32m 336\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.9/json/decoder.py:355\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m 354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[0;32m--> 355\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m JSONDecodeError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpecting value\u001b[39m\u001b[38;5;124m\"\u001b[39m, s, err\u001b[38;5;241m.\u001b[39mvalue) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28mNone\u001b[39m\n\u001b[1;32m 356\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m obj, end\n",
+ "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)",
+ "\nDuring handling of the above exception, another exception occurred:\n",
+ "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)",
+ "Input \u001b[0;32mIn [7]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 8\u001b[0m headers \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 9\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAuthorization\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mos.env(directus_token)\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mContent-Type\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mapplication/json\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 11\u001b[0m }\n\u001b[1;32m 12\u001b[0m response \u001b[38;5;241m=\u001b[39m requests\u001b[38;5;241m.\u001b[39mpatch(\n\u001b[1;32m 13\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttp://directus:8055/items/bookmarks/\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mstr\u001b[39m(myid),\n\u001b[1;32m 14\u001b[0m headers\u001b[38;5;241m=\u001b[39mheaders,\n\u001b[1;32m 15\u001b[0m json\u001b[38;5;241m=\u001b[39m(link),\n\u001b[1;32m 16\u001b[0m )\n\u001b[0;32m---> 17\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mjson\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m)\n",
+ "File \u001b[0;32m/opt/conda/lib/python3.9/site-packages/requests/models.py:917\u001b[0m, in \u001b[0;36mResponse.json\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 915\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m RequestsJSONDecodeError(e\u001b[38;5;241m.\u001b[39mmessage)\n\u001b[1;32m 916\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 917\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m RequestsJSONDecodeError(e\u001b[38;5;241m.\u001b[39mmsg, e\u001b[38;5;241m.\u001b[39mdoc, e\u001b[38;5;241m.\u001b[39mpos)\n",
+ "\u001b[0;31mJSONDecodeError\u001b[0m: [Errno Expecting value] : 0"
+ ]
+ }
+ ],
+ "source": [
+ "for link in links:\n",
+ " url = link['url']\n",
+ " myid = link.pop(\"id\")\n",
+ " parsed_url = urllib.parse.urlparse(url)\n",
+ " domain = parsed_url.netloc\n",
+ " pdom = domain.replace(\"www.\", \"\")\n",
+ " link['domain'] = pdom\n",
+ " headers = {\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " \"Content-Type\": \"application/json\",\n",
+ " }\n",
+ " response = requests.patch(\n",
+ " \"http://directus:8055/items/bookmarks/\" + str(myid),\n",
+ " headers=headers,\n",
+ " json=(link),\n",
+ " )\n",
+ " print(response.json())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b9d5bb9f-be1e-4db2-b0a3-d0d179e6b6a6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import urllib.parse\n",
+ "import sys\n",
+ "\n",
+ "link = links[1]\n",
+ "url = link['url']\n",
+ "myid = link.pop(\"id\")\n",
+ "print(link)\n",
+ "parsed_url = urllib.parse.urlparse(url)\n",
+ "domain = parsed_url.netloc\n",
+ "pdom = domain.replace(\"www.\", \"\")\n",
+ "print(pdom)\n",
+ "link['domain'] = pdom\n",
+ "\n",
+ "\n",
+ "print(link)\n",
+ "\n",
+ "print(myid)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.8.9 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.9"
+ },
+ "toc-autonumbering": false,
+ "toc-showcode": false,
+ "toc-showtags": false,
+ "vscode": {
+ "interpreter": {
+ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
+ }
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/data_transfer/Add traefic routers.ipynb b/data_transfer/Add traefic routers.ipynb
new file mode 100644
index 0000000..9a6cead
--- /dev/null
+++ b/data_transfer/Add traefic routers.ipynb
@@ -0,0 +1,124 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "ebef409e-ddc1-4cc4-bd4d-a4839ba62d66",
+ "metadata": {},
+ "source": [
+ "## Retrieve list of active proxy endpoints\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "02d6d963-538a-47c1-957f-06c7ea7c7497",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ConnectionError",
+ "evalue": "HTTPConnectionPool(host='traefik', port=8080): Max retries exceeded with url: /api/http/routers (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'))",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mgaierror\u001b[0m Traceback (most recent call last)",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connection.py:174\u001b[0m, in \u001b[0;36mHTTPConnection._new_conn\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 173\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m--> 174\u001b[0m conn \u001b[39m=\u001b[39m connection\u001b[39m.\u001b[39;49mcreate_connection(\n\u001b[1;32m 175\u001b[0m (\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_dns_host, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mport), \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mtimeout, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mextra_kw\n\u001b[1;32m 176\u001b[0m )\n\u001b[1;32m 178\u001b[0m \u001b[39mexcept\u001b[39;00m SocketTimeout:\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/util/connection.py:72\u001b[0m, in \u001b[0;36mcreate_connection\u001b[0;34m(address, timeout, source_address, socket_options)\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[39mreturn\u001b[39;00m six\u001b[39m.\u001b[39mraise_from(\n\u001b[1;32m 69\u001b[0m LocationParseError(\u001b[39mu\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m'\u001b[39m\u001b[39m%s\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m, label empty or too long\u001b[39m\u001b[39m\"\u001b[39m \u001b[39m%\u001b[39m host), \u001b[39mNone\u001b[39;00m\n\u001b[1;32m 70\u001b[0m )\n\u001b[0;32m---> 72\u001b[0m \u001b[39mfor\u001b[39;00m res \u001b[39min\u001b[39;00m socket\u001b[39m.\u001b[39;49mgetaddrinfo(host, port, family, socket\u001b[39m.\u001b[39;49mSOCK_STREAM):\n\u001b[1;32m 73\u001b[0m af, socktype, proto, canonname, sa \u001b[39m=\u001b[39m res\n",
+ "File \u001b[0;32m/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/socket.py:918\u001b[0m, in \u001b[0;36mgetaddrinfo\u001b[0;34m(host, port, family, type, proto, flags)\u001b[0m\n\u001b[1;32m 917\u001b[0m addrlist \u001b[39m=\u001b[39m []\n\u001b[0;32m--> 918\u001b[0m \u001b[39mfor\u001b[39;00m res \u001b[39min\u001b[39;00m _socket\u001b[39m.\u001b[39;49mgetaddrinfo(host, port, family, \u001b[39mtype\u001b[39;49m, proto, flags):\n\u001b[1;32m 919\u001b[0m af, socktype, proto, canonname, sa \u001b[39m=\u001b[39m res\n",
+ "\u001b[0;31mgaierror\u001b[0m: [Errno 8] nodename nor servname provided, or not known",
+ "\nDuring handling of the above exception, another exception occurred:\n",
+ "\u001b[0;31mNewConnectionError\u001b[0m Traceback (most recent call last)",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connectionpool.py:703\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 702\u001b[0m \u001b[39m# Make the request on the httplib connection object.\u001b[39;00m\n\u001b[0;32m--> 703\u001b[0m httplib_response \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_make_request(\n\u001b[1;32m 704\u001b[0m conn,\n\u001b[1;32m 705\u001b[0m method,\n\u001b[1;32m 706\u001b[0m url,\n\u001b[1;32m 707\u001b[0m timeout\u001b[39m=\u001b[39;49mtimeout_obj,\n\u001b[1;32m 708\u001b[0m body\u001b[39m=\u001b[39;49mbody,\n\u001b[1;32m 709\u001b[0m headers\u001b[39m=\u001b[39;49mheaders,\n\u001b[1;32m 710\u001b[0m chunked\u001b[39m=\u001b[39;49mchunked,\n\u001b[1;32m 711\u001b[0m )\n\u001b[1;32m 713\u001b[0m \u001b[39m# If we're going to release the connection in ``finally:``, then\u001b[39;00m\n\u001b[1;32m 714\u001b[0m \u001b[39m# the response doesn't need to know about the connection. Otherwise\u001b[39;00m\n\u001b[1;32m 715\u001b[0m \u001b[39m# it will also try to release it and we'll have a double-release\u001b[39;00m\n\u001b[1;32m 716\u001b[0m \u001b[39m# mess.\u001b[39;00m\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connectionpool.py:398\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 397\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[0;32m--> 398\u001b[0m conn\u001b[39m.\u001b[39;49mrequest(method, url, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mhttplib_request_kw)\n\u001b[1;32m 400\u001b[0m \u001b[39m# We are swallowing BrokenPipeError (errno.EPIPE) since the server is\u001b[39;00m\n\u001b[1;32m 401\u001b[0m \u001b[39m# legitimately able to close the connection after sending a valid response.\u001b[39;00m\n\u001b[1;32m 402\u001b[0m \u001b[39m# With this behaviour, the received response is still readable.\u001b[39;00m\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connection.py:239\u001b[0m, in \u001b[0;36mHTTPConnection.request\u001b[0;34m(self, method, url, body, headers)\u001b[0m\n\u001b[1;32m 238\u001b[0m headers[\u001b[39m\"\u001b[39m\u001b[39mUser-Agent\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m _get_default_user_agent()\n\u001b[0;32m--> 239\u001b[0m \u001b[39msuper\u001b[39;49m(HTTPConnection, \u001b[39mself\u001b[39;49m)\u001b[39m.\u001b[39;49mrequest(method, url, body\u001b[39m=\u001b[39;49mbody, headers\u001b[39m=\u001b[39;49mheaders)\n",
+ "File \u001b[0;32m/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py:1252\u001b[0m, in \u001b[0;36mHTTPConnection.request\u001b[0;34m(self, method, url, body, headers, encode_chunked)\u001b[0m\n\u001b[1;32m 1251\u001b[0m \u001b[39m\"\"\"Send a complete request to the server.\"\"\"\u001b[39;00m\n\u001b[0;32m-> 1252\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_send_request(method, url, body, headers, encode_chunked)\n",
+ "File \u001b[0;32m/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py:1298\u001b[0m, in \u001b[0;36mHTTPConnection._send_request\u001b[0;34m(self, method, url, body, headers, encode_chunked)\u001b[0m\n\u001b[1;32m 1297\u001b[0m body \u001b[39m=\u001b[39m _encode(body, \u001b[39m'\u001b[39m\u001b[39mbody\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[0;32m-> 1298\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mendheaders(body, encode_chunked\u001b[39m=\u001b[39;49mencode_chunked)\n",
+ "File \u001b[0;32m/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py:1247\u001b[0m, in \u001b[0;36mHTTPConnection.endheaders\u001b[0;34m(self, message_body, encode_chunked)\u001b[0m\n\u001b[1;32m 1246\u001b[0m \u001b[39mraise\u001b[39;00m CannotSendHeader()\n\u001b[0;32m-> 1247\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_send_output(message_body, encode_chunked\u001b[39m=\u001b[39;49mencode_chunked)\n",
+ "File \u001b[0;32m/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py:1007\u001b[0m, in \u001b[0;36mHTTPConnection._send_output\u001b[0;34m(self, message_body, encode_chunked)\u001b[0m\n\u001b[1;32m 1006\u001b[0m \u001b[39mdel\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_buffer[:]\n\u001b[0;32m-> 1007\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49msend(msg)\n\u001b[1;32m 1009\u001b[0m \u001b[39mif\u001b[39;00m message_body \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 1010\u001b[0m \n\u001b[1;32m 1011\u001b[0m \u001b[39m# create a consistent interface to message_body\u001b[39;00m\n",
+ "File \u001b[0;32m/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py:947\u001b[0m, in \u001b[0;36mHTTPConnection.send\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 946\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mauto_open:\n\u001b[0;32m--> 947\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mconnect()\n\u001b[1;32m 948\u001b[0m \u001b[39melse\u001b[39;00m:\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connection.py:205\u001b[0m, in \u001b[0;36mHTTPConnection.connect\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mconnect\u001b[39m(\u001b[39mself\u001b[39m):\n\u001b[0;32m--> 205\u001b[0m conn \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_new_conn()\n\u001b[1;32m 206\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_prepare_conn(conn)\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connection.py:186\u001b[0m, in \u001b[0;36mHTTPConnection._new_conn\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[39mexcept\u001b[39;00m SocketError \u001b[39mas\u001b[39;00m e:\n\u001b[0;32m--> 186\u001b[0m \u001b[39mraise\u001b[39;00m NewConnectionError(\n\u001b[1;32m 187\u001b[0m \u001b[39mself\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mFailed to establish a new connection: \u001b[39m\u001b[39m%s\u001b[39;00m\u001b[39m\"\u001b[39m \u001b[39m%\u001b[39m e\n\u001b[1;32m 188\u001b[0m )\n\u001b[1;32m 190\u001b[0m \u001b[39mreturn\u001b[39;00m conn\n",
+ "\u001b[0;31mNewConnectionError\u001b[0m: : Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known",
+ "\nDuring handling of the above exception, another exception occurred:\n",
+ "\u001b[0;31mMaxRetryError\u001b[0m Traceback (most recent call last)",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/requests/adapters.py:489\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 488\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m chunked:\n\u001b[0;32m--> 489\u001b[0m resp \u001b[39m=\u001b[39m conn\u001b[39m.\u001b[39;49murlopen(\n\u001b[1;32m 490\u001b[0m method\u001b[39m=\u001b[39;49mrequest\u001b[39m.\u001b[39;49mmethod,\n\u001b[1;32m 491\u001b[0m url\u001b[39m=\u001b[39;49murl,\n\u001b[1;32m 492\u001b[0m body\u001b[39m=\u001b[39;49mrequest\u001b[39m.\u001b[39;49mbody,\n\u001b[1;32m 493\u001b[0m headers\u001b[39m=\u001b[39;49mrequest\u001b[39m.\u001b[39;49mheaders,\n\u001b[1;32m 494\u001b[0m redirect\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m,\n\u001b[1;32m 495\u001b[0m assert_same_host\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m,\n\u001b[1;32m 496\u001b[0m preload_content\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m,\n\u001b[1;32m 497\u001b[0m decode_content\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m,\n\u001b[1;32m 498\u001b[0m retries\u001b[39m=\u001b[39;49m\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mmax_retries,\n\u001b[1;32m 499\u001b[0m timeout\u001b[39m=\u001b[39;49mtimeout,\n\u001b[1;32m 500\u001b[0m )\n\u001b[1;32m 502\u001b[0m \u001b[39m# Send the request.\u001b[39;00m\n\u001b[1;32m 503\u001b[0m \u001b[39melse\u001b[39;00m:\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/connectionpool.py:787\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 785\u001b[0m e \u001b[39m=\u001b[39m ProtocolError(\u001b[39m\"\u001b[39m\u001b[39mConnection aborted.\u001b[39m\u001b[39m\"\u001b[39m, e)\n\u001b[0;32m--> 787\u001b[0m retries \u001b[39m=\u001b[39m retries\u001b[39m.\u001b[39;49mincrement(\n\u001b[1;32m 788\u001b[0m method, url, error\u001b[39m=\u001b[39;49me, _pool\u001b[39m=\u001b[39;49m\u001b[39mself\u001b[39;49m, _stacktrace\u001b[39m=\u001b[39;49msys\u001b[39m.\u001b[39;49mexc_info()[\u001b[39m2\u001b[39;49m]\n\u001b[1;32m 789\u001b[0m )\n\u001b[1;32m 790\u001b[0m retries\u001b[39m.\u001b[39msleep()\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/urllib3/util/retry.py:592\u001b[0m, in \u001b[0;36mRetry.increment\u001b[0;34m(self, method, url, response, error, _pool, _stacktrace)\u001b[0m\n\u001b[1;32m 591\u001b[0m \u001b[39mif\u001b[39;00m new_retry\u001b[39m.\u001b[39mis_exhausted():\n\u001b[0;32m--> 592\u001b[0m \u001b[39mraise\u001b[39;00m MaxRetryError(_pool, url, error \u001b[39mor\u001b[39;00m ResponseError(cause))\n\u001b[1;32m 594\u001b[0m log\u001b[39m.\u001b[39mdebug(\u001b[39m\"\u001b[39m\u001b[39mIncremented Retry for (url=\u001b[39m\u001b[39m'\u001b[39m\u001b[39m%s\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m): \u001b[39m\u001b[39m%r\u001b[39;00m\u001b[39m\"\u001b[39m, url, new_retry)\n",
+ "\u001b[0;31mMaxRetryError\u001b[0m: HTTPConnectionPool(host='traefik', port=8080): Max retries exceeded with url: /api/http/routers (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'))",
+ "\nDuring handling of the above exception, another exception occurred:\n",
+ "\u001b[0;31mConnectionError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m/Users/donaldrich/Projects/secrets/code/unpublished/directus/Add traefic routers.ipynb Cell 2\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mrequests\u001b[39;00m\n\u001b[1;32m 5\u001b[0m my_headers \u001b[39m=\u001b[39m {\n\u001b[1;32m 6\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mContent-Type\u001b[39m\u001b[39m\"\u001b[39m: \u001b[39m\"\u001b[39m\u001b[39mapplication/json\u001b[39m\u001b[39m\"\u001b[39m,\n\u001b[1;32m 7\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mAccept\u001b[39m\u001b[39m\"\u001b[39m: \u001b[39m\"\u001b[39m\u001b[39mapplication/json\u001b[39m\u001b[39m\"\u001b[39m,\n\u001b[1;32m 8\u001b[0m }\n\u001b[0;32m---> 10\u001b[0m response \u001b[39m=\u001b[39m requests\u001b[39m.\u001b[39;49mget(\n\u001b[1;32m 11\u001b[0m \u001b[39m\"\u001b[39;49m\u001b[39mhttp://traefik:8080/api/http/routers\u001b[39;49m\u001b[39m\"\u001b[39;49m,\n\u001b[1;32m 12\u001b[0m headers\u001b[39m=\u001b[39;49mmy_headers,\n\u001b[1;32m 13\u001b[0m )\n\u001b[1;32m 16\u001b[0m initial \u001b[39m=\u001b[39m response\u001b[39m.\u001b[39mjson()\n\u001b[1;32m 19\u001b[0m \u001b[39mfor\u001b[39;00m x \u001b[39min\u001b[39;00m initial:\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/requests/api.py:73\u001b[0m, in \u001b[0;36mget\u001b[0;34m(url, params, **kwargs)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mget\u001b[39m(url, params\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[1;32m 63\u001b[0m \u001b[39mr\u001b[39m\u001b[39m\"\"\"Sends a GET request.\u001b[39;00m\n\u001b[1;32m 64\u001b[0m \n\u001b[1;32m 65\u001b[0m \u001b[39m :param url: URL for the new :class:`Request` object.\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[39m :rtype: requests.Response\u001b[39;00m\n\u001b[1;32m 71\u001b[0m \u001b[39m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 73\u001b[0m \u001b[39mreturn\u001b[39;00m request(\u001b[39m\"\u001b[39;49m\u001b[39mget\u001b[39;49m\u001b[39m\"\u001b[39;49m, url, params\u001b[39m=\u001b[39;49mparams, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/requests/api.py:59\u001b[0m, in \u001b[0;36mrequest\u001b[0;34m(method, url, **kwargs)\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[39m# By using the 'with' statement we are sure the session is closed, thus we\u001b[39;00m\n\u001b[1;32m 56\u001b[0m \u001b[39m# avoid leaving sockets open which can trigger a ResourceWarning in some\u001b[39;00m\n\u001b[1;32m 57\u001b[0m \u001b[39m# cases, and look like a memory leak in others.\u001b[39;00m\n\u001b[1;32m 58\u001b[0m \u001b[39mwith\u001b[39;00m sessions\u001b[39m.\u001b[39mSession() \u001b[39mas\u001b[39;00m session:\n\u001b[0;32m---> 59\u001b[0m \u001b[39mreturn\u001b[39;00m session\u001b[39m.\u001b[39;49mrequest(method\u001b[39m=\u001b[39;49mmethod, url\u001b[39m=\u001b[39;49murl, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/requests/sessions.py:587\u001b[0m, in \u001b[0;36mSession.request\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 582\u001b[0m send_kwargs \u001b[39m=\u001b[39m {\n\u001b[1;32m 583\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mtimeout\u001b[39m\u001b[39m\"\u001b[39m: timeout,\n\u001b[1;32m 584\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mallow_redirects\u001b[39m\u001b[39m\"\u001b[39m: allow_redirects,\n\u001b[1;32m 585\u001b[0m }\n\u001b[1;32m 586\u001b[0m send_kwargs\u001b[39m.\u001b[39mupdate(settings)\n\u001b[0;32m--> 587\u001b[0m resp \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49msend(prep, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49msend_kwargs)\n\u001b[1;32m 589\u001b[0m \u001b[39mreturn\u001b[39;00m resp\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/requests/sessions.py:701\u001b[0m, in \u001b[0;36mSession.send\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 698\u001b[0m start \u001b[39m=\u001b[39m preferred_clock()\n\u001b[1;32m 700\u001b[0m \u001b[39m# Send the request\u001b[39;00m\n\u001b[0;32m--> 701\u001b[0m r \u001b[39m=\u001b[39m adapter\u001b[39m.\u001b[39;49msend(request, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 703\u001b[0m \u001b[39m# Total elapsed time of the request (approximately)\u001b[39;00m\n\u001b[1;32m 704\u001b[0m elapsed \u001b[39m=\u001b[39m preferred_clock() \u001b[39m-\u001b[39m start\n",
+ "File \u001b[0;32m~/Library/Python/3.8/lib/python/site-packages/requests/adapters.py:565\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 561\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39misinstance\u001b[39m(e\u001b[39m.\u001b[39mreason, _SSLError):\n\u001b[1;32m 562\u001b[0m \u001b[39m# This branch is for urllib3 v1.22 and later.\u001b[39;00m\n\u001b[1;32m 563\u001b[0m \u001b[39mraise\u001b[39;00m SSLError(e, request\u001b[39m=\u001b[39mrequest)\n\u001b[0;32m--> 565\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mConnectionError\u001b[39;00m(e, request\u001b[39m=\u001b[39mrequest)\n\u001b[1;32m 567\u001b[0m \u001b[39mexcept\u001b[39;00m ClosedPoolError \u001b[39mas\u001b[39;00m e:\n\u001b[1;32m 568\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mConnectionError\u001b[39;00m(e, request\u001b[39m=\u001b[39mrequest)\n",
+ "\u001b[0;31mConnectionError\u001b[0m: HTTPConnectionPool(host='traefik', port=8080): Max retries exceeded with url: /api/http/routers (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'))"
+ ]
+ }
+ ],
+ "source": [
+ "import json\n",
+ "import re\n",
+ "import requests\n",
+ "\n",
+ "my_headers = {\n",
+ " \"Content-Type\": \"application/json\",\n",
+ " \"Accept\": \"application/json\",\n",
+ "}\n",
+ "\n",
+ "response = requests.get(\n",
+ " \"http://traefik:8080/api/http/routers\",\n",
+ " headers=my_headers,\n",
+ ")\n",
+ "\n",
+ "\n",
+ "initial = response.json()\n",
+ "\n",
+ "\n",
+ "for x in initial:\n",
+ " service = x[\"rule\"]\n",
+ " find = re.findall(\"Host\\(`([^\\)]+)`\\)\", service)\n",
+ " try:\n",
+ " print(find[0])\n",
+ " except:\n",
+ " pass"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.10.4 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.9"
+ },
+ "toc-autonumbering": false,
+ "toc-showcode": false,
+ "toc-showtags": false,
+ "vscode": {
+ "interpreter": {
+ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
+ }
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/data_transfer/Directus query.ipynb b/data_transfer/Directus query.ipynb
new file mode 100644
index 0000000..fb2abe4
--- /dev/null
+++ b/data_transfer/Directus query.ipynb
@@ -0,0 +1,86 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "927fe89f-9660-4681-884b-f258fc669b88",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pip install gql[all] aiohttp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a4dc5471-3df9-4d52-865e-ca9202d472a3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import asyncio\n",
+ "\n",
+ "from gql import Client, gql\n",
+ "from gql.transport.aiohttp import AIOHTTPTransport\n",
+ "\n",
+ "transport = AIOHTTPTransport(\n",
+ " url=\"http://directus:8055/graphql\",\n",
+ " headers={\n",
+ " \"Content-type\": \"application/json\",\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " },\n",
+ ")\n",
+ "\n",
+ "client = Client(transport=transport, fetch_schema_from_transport=False)\n",
+ "\n",
+ "query = gql(\n",
+ " \"\"\"\n",
+ " query {\n",
+ " pages {\n",
+ " id\n",
+ " }\n",
+ " }\n",
+ "\"\"\"\n",
+ ")\n",
+ "\n",
+ "result = await client.execute_async(query)\n",
+ "print(result)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f9429bdb-d291-49ce-8191-9977b3624f97",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.12"
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/data_transfer/Wiki-js query.ipynb b/data_transfer/Wiki-js query.ipynb
new file mode 100644
index 0000000..bbbb944
--- /dev/null
+++ b/data_transfer/Wiki-js query.ipynb
@@ -0,0 +1,128 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "c5130422",
+ "metadata": {},
+ "source": [
+ "# Bulk upload data via GraphQL endpoint"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "0019cd52-56b8-4f1d-82f5-55137f05456b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "zsh:1: no matches found: gql[all]\n",
+ "Note: you may need to restart the kernel to use updated packages.\n"
+ ]
+ }
+ ],
+ "source": [
+ "pip install gql[all] aiohttp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "6658fd82-d8db-4a80-a103-3f015c851e69",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [
+ {
+ "ename": "ModuleNotFoundError",
+ "evalue": "No module named 'gql'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m/Users/donaldrich/Projects/secrets/code/unpublished/directus/Wiki-js query.ipynb Cell 3\u001b[0m in \u001b[0;36m| \u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39masyncio\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mgql\u001b[39;00m \u001b[39mimport\u001b[39;00m Client, gql\n\u001b[1;32m 4\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mgql\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39mtransport\u001b[39;00m\u001b[39m.\u001b[39;00m\u001b[39maiohttp\u001b[39;00m \u001b[39mimport\u001b[39;00m AIOHTTPTransport\n\u001b[1;32m 6\u001b[0m transport \u001b[39m=\u001b[39m AIOHTTPTransport(\n\u001b[1;32m 7\u001b[0m url\u001b[39m=\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mhttp://wiki:3000/graphql\u001b[39m\u001b[39m\"\u001b[39m,\n\u001b[1;32m 8\u001b[0m headers\u001b[39m=\u001b[39m{\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 11\u001b[0m },\n\u001b[1;32m 12\u001b[0m )\n",
+ "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'gql'"
+ ]
+ }
+ ],
+ "source": [
+ "import asyncio\n",
+ "\n",
+ "from gql import Client, gql\n",
+ "from gql.transport.aiohttp import AIOHTTPTransport\n",
+ "\n",
+ "transport = AIOHTTPTransport(\n",
+ " url=\"http://wiki:3000/graphql\",\n",
+ " headers={\n",
+ " \"Content-type\": \"application/json\",\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " },\n",
+ ")\n",
+ "\n",
+ "client = Client(transport=transport, fetch_schema_from_transport=False)\n",
+ "\n",
+ "query = gql(\n",
+ " \"\"\"\n",
+ " query pageList {\n",
+ " pages {\n",
+ " list(locale: \"en\") {\n",
+ " id\n",
+ " path\n",
+ " locale\n",
+ " title\n",
+ " description\n",
+ " contentType\n",
+ " isPublished\n",
+ " isPrivate\n",
+ " privateNS\n",
+ " createdAt\n",
+ " updatedAt\n",
+ " tags\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "\"\"\"\n",
+ ")\n",
+ "\n",
+ "result = await client.execute_async(query)\n",
+ "print(result)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.8.9 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.9"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
+ }
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/templating/Dashmachine Config Template.ipynb b/templating/Dashmachine Config Template.ipynb
new file mode 100644
index 0000000..b02459c
--- /dev/null
+++ b/templating/Dashmachine Config Template.ipynb
@@ -0,0 +1,1560 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f6b2c601-3b50-4514-9e5a-382400244bab",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "%%sh\n",
+ "rm templates/template.test\n",
+ "\n",
+ "cat << EOF >> templates/template.test\n",
+ "\n",
+ "[Settings]\n",
+ "theme = dark\n",
+ "accent = purple\n",
+ "background = None\n",
+ "roles = admin,user,public_user\n",
+ "home_access_groups = admin_only\n",
+ "settings_access_groups = admin_only\n",
+ "custom_app_title = DashMachine\n",
+ "sidebar_default = open\n",
+ "tags = {\"name\": \"foo\", \"icon\": \"home\", \"sort_pos\": \"2\"}\n",
+ "\n",
+ "[admin]\n",
+ "role = admin\n",
+ "password = os.getenv(password)\n",
+ "confirm_password = os.getenv(password)\n",
+ "\n",
+ "{% for item in items %}\n",
+ "\n",
+ "[{{ item.service }}]\n",
+ "prefix = https://\n",
+ "url = {{ item.url }}\n",
+ "{% if item.icon_url %}\n",
+ "icon = item.icon_url\n",
+ "sidebar_icon = item.icon_url\n",
+ "{% else %}\n",
+ "icon = static/images/apps/{{ item.service }}.png\n",
+ "sidebar_icon = static/images/apps/{{ item.service }}.png\n",
+ "{% endif %}\n",
+ "description = default\n",
+ "open_in = iframe\n",
+ "# data_sources = $0_http,$0_health,$0_ping,$0_rest\n",
+ "tags = default\n",
+ "# groups = admin_only\n",
+ "\n",
+ "{% endfor %}\n",
+ "\n",
+ "{# a comment #}\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5e0c08bd-aaff-4236-9b79-df5e2aa14a3e",
+ "metadata": {
+ "jupyter": {
+ "source_hidden": true
+ },
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "%%sh\n",
+ "cat << EOF >> template.ini\n",
+ "\n",
+ "[$0_curl]\n",
+ "platform curl\n",
+ "resource = http://$0.com\n",
+ "value_template My IP: [{value.ip}}\n",
+ "response_type = json\n",
+ "\n",
+ "[$0_rest]\n",
+ "platform = rest\n",
+ "resource = http://$0/api\n",
+ "value_template = {{value}}\n",
+ "method = post\n",
+ "authentication = basic\n",
+ "username = my_username\n",
+ "password = my_password\n",
+ "payload = {\"var1\": \"hi\", \"var2\": 1}\n",
+ "headers {\"Content-Type\": \"application/json\"}\n",
+ "verify = false\n",
+ "\n",
+ "[$0_ping]\n",
+ "platform = ping\n",
+ "resource = 192.168.1.1\n",
+ "[$0_http]\n",
+ "platform = http_status\n",
+ "resource = https://your-website.com/api\n",
+ "method = get\n",
+ "authentication = basic\n",
+ "username = my_username\n",
+ "password = my_password\n",
+ "headers = {\"Content-Type\": \"application/json\"}\n",
+ "return_codes = 2XX, 3XX\n",
+ "\n",
+ "[$0_health]\n",
+ "platform = healthchecks\n",
+ "prefix = http://\n",
+ "host = localhost\n",
+ "port = 8080\n",
+ "api_key = {{ Healthchecks project API Key }}\n",
+ "project {{ Healthchecks project name }}\n",
+ "verify = true\n",
+ "value_template = { { value_template }}\n",
+ "\n",
+ "[$0]\n",
+ "prefix = https://\n",
+ "url = your-website.com\n",
+ "icon = static/images/apps/$0.png\n",
+ "sidebar_icon = static/images/apps/{{ name }}.png\n",
+ "description = default\n",
+ "open_in = iframe\n",
+ "data_sources = $0_http,$0_health,$0_ping,$0_rest\n",
+ "tags = default\n",
+ "groups = admin_only\n",
+ "\n",
+ "EOF"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 40,
+ "id": "ad3a0cde-8e53-403d-bbb6-6fc95c392093",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "import os\n",
+ "import pprint\n",
+ "\n",
+ "import requests\n",
+ "\n",
+ "headers = {\n",
+ " \"Authorization\": \"os.env(directus_token)\",\n",
+ " \"Content-Type\": \"application/json\",\n",
+ "}\n",
+ "response = requests.get(\n",
+ " \"https://cms.donavanaldrich.com/items/containers\", headers=headers\n",
+ ")\n",
+ "data = response.json()\n",
+ "\n",
+ "items = data[\"data\"]\n",
+ "# name = (items[0]['id'])\n",
+ "\n",
+ "# t = Template(\"Jinja {{ name }}!\")\n",
+ "# t.render(name=items[0]['id'])\n",
+ "#"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "id": "3fc3ac9f-22bf-495b-9a23-214219d04543",
+ "metadata": {
+ "scrolled": true,
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "import json\n",
+ "import re\n",
+ "\n",
+ "import requests\n",
+ "\n",
+ "my_headers = {\n",
+ " \"Content-Type\": \"application/json\",\n",
+ " \"Accept\": \"application/json\",\n",
+ "}\n",
+ "\n",
+ "response = requests.get(\n",
+ " \"http://traefik:8080/api/http/routers\",\n",
+ " headers=my_headers,\n",
+ ")\n",
+ "\n",
+ "initial = response.json()\n",
+ "# pprint.pprint(initial)\n",
+ "items = []\n",
+ "\n",
+ "for x in initial:\n",
+ " rule = x[\"rule\"]\n",
+ " service = x[\"service\"]\n",
+ " find = re.findall(\"Host\\(`([^\\)]+)`\\)\", rule)\n",
+ " if find:\n",
+ " item = {\"service\": x[\"service\"], \"url\": find[0]}\n",
+ " else:\n",
+ " pass\n",
+ " items.append(item)\n",
+ "# print(items)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "id": "147949bd-d0a7-4ebc-af12-b21d3d8fa0b3",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[{'service': 'active_workflow', 'url': 'workflow.donavanaldrich.com'},\n",
+ " {'service': 'alertmanager', 'url': 'alertmanager.donavanaldrich.com'},\n",
+ " {'service': 'ansible', 'url': 'ansible.donavanaldrich.com'},\n",
+ " {'service': 'apprise', 'url': 'notify.donavanaldrich.com'},\n",
+ " {'service': 'authelia', 'url': 'authelia.donavanaldrich.com'},\n",
+ " {'service': 'bitwarden2', 'url': 'password.donavanaldrich.com'},\n",
+ " {'service': 'blackbox', 'url': 'blackbox.donavanaldrich.com'},\n",
+ " {'service': 'browserless', 'url': 'browserless.donavanaldrich.com'},\n",
+ " {'service': 'cachet', 'url': 'cachet.donavanaldrich.com'},\n",
+ " {'service': 'caddy', 'url': 'caddy.donavanaldrich.com'},\n",
+ " {'service': 'chronograf', 'url': 'chronograf.donavanaldrich.com'},\n",
+ " {'service': 'cloudflare', 'url': 'cloudflare.donavanaldrich.com'},\n",
+ " {'service': 'cron', 'url': 'cron.donavanaldrich.com'},\n",
+ " {'service': 'cronicle', 'url': 'cronicle.donavanaldrich.com'},\n",
+ " {'service': 'cyberchef', 'url': 'cyberchef.donavanaldrich.com'},\n",
+ " {'service': 'dashmachine', 'url': 'menu.donavanaldrich.com'},\n",
+ " {'service': 'directus', 'url': 'cms.donavanaldrich.com'},\n",
+ " {'service': 'dozzle', 'url': 'dozzle.donavanaldrich.com'},\n",
+ " {'service': 'elastichq', 'url': 'elastic.donavanaldrich.com'},\n",
+ " {'service': 'gatus', 'url': 'gatus.donavanaldrich.com'},\n",
+ " {'service': 'grafana', 'url': 'grafana.donavanaldrich.com'},\n",
+ " {'service': 'hass-configurator', 'url': 'home-config.donavanaldrich.com'},\n",
+ " {'service': 'healthcheck', 'url': 'health.donavanaldrich.com'},\n",
+ " {'service': 'homeassistant', 'url': 'home.donavanaldrich.com'},\n",
+ " {'service': 'homebridge', 'url': 'homebridge.donavanaldrich.com'},\n",
+ " {'service': 'homer', 'url': 'homer.donavanaldrich.com'},\n",
+ " {'service': 'huginn', 'url': 'huginn.donavanaldrich.com'},\n",
+ " {'service': 'influx', 'url': 'influx.donavanaldrich.com'},\n",
+ " {'service': 'jackett', 'url': 'jackett.donavanaldrich.com'},\n",
+ " {'service': 'jupyter', 'url': 'jupyter.donavanaldrich.com'},\n",
+ " {'service': 'kong', 'url': 'api.donavanaldrich.com'},\n",
+ " {'service': 'kong', 'url': 'kong.donavanaldrich.com'},\n",
+ " {'service': 'konga', 'url': 'konga.donavanaldrich.com'},\n",
+ " {'service': 'lidarr', 'url': 'lidarr.donavanaldrich.com'},\n",
+ " {'service': 'linkace', 'url': 'bookmarks.donavanaldrich.com'},\n",
+ " {'service': 'mattermost', 'url': 'chat.donavanaldrich.com'},\n",
+ " {'service': 'metabase', 'url': 'analytics.donavanaldrich.com'},\n",
+ " {'service': 'minio', 'url': 'minio.donavanaldrich.com'},\n",
+ " {'service': 'monica', 'url': 'monica.donavanaldrich.com'},\n",
+ " {'service': 'netdata', 'url': 'netdata.donavanaldrich.com'},\n",
+ " {'service': 'nextcloud', 'url': 'cloud.donavanaldrich.com'},\n",
+ " {'service': 'nodejs-dev', 'url': 'dev.donavanaldrich.com'},\n",
+ " {'service': 'nodejs', 'url': 'node.donavanaldrich.com'},\n",
+ " {'service': 'nodered', 'url': 'nodered.donavanaldrich.com'},\n",
+ " {'service': 'opsdroid', 'url': 'droid.donavanaldrich.com'},\n",
+ " {'service': 'overseerr', 'url': 'media.donavanaldrich.com'},\n",
+ " {'service': 'paperless', 'url': 'docs.donavanaldrich.com'},\n",
+ " {'service': 'pdf-rendering-srv', 'url': 'pdf-render.donavanaldrich.com'},\n",
+ " {'service': 'pgadmin', 'url': 'pgadmin.donavanaldrich.com'},\n",
+ " {'service': 'pgweb', 'url': 'pgweb.donavanaldrich.com'},\n",
+ " {'service': 'phpmyadmin', 'url': 'mysql.donavanaldrich.com'},\n",
+ " {'service': 'pihole', 'url': 'pihole.donavanaldrich.com'},\n",
+ " {'service': 'plex', 'url': 'plex.donavanaldrich.com'},\n",
+ " {'service': 'portainer', 'url': 'portainer.donavanaldrich.com'},\n",
+ " {'service': 'prometheus', 'url': 'prometheus.donavanaldrich.com'},\n",
+ " {'service': 'promtail', 'url': 'promtail.donavanaldrich.com'},\n",
+ " {'service': 'proxmox', 'url': 'proxmox.donavanaldrich.com'},\n",
+ " {'service': 'pushgateway', 'url': 'pushgateway.donavanaldrich.com'},\n",
+ " {'service': 'pyload', 'url': 'pyload.donavanaldrich.com'},\n",
+ " {'service': 'radarr', 'url': 'radarr.donavanaldrich.com'},\n",
+ " {'service': 'redis', 'url': 'redis.donavanaldrich.com'},\n",
+ " {'service': 'request-baskets', 'url': 'requests.donavanaldrich.com'},\n",
+ " {'service': 'requestrr', 'url': 'requestrr.donavanaldrich.com'},\n",
+ " {'service': 'router', 'url': 'router.donavanaldrich.com'},\n",
+ " {'service': 'script-server', 'url': 'script.donavanaldrich.com'},\n",
+ " {'service': 'scrutiny', 'url': 'disk.donavanaldrich.com'},\n",
+ " {'service': 'snmp', 'url': 'snmp.donavanaldrich.com'},\n",
+ " {'service': 'sonarr', 'url': 'sonarr.donavanaldrich.com'},\n",
+ " {'service': 'speedtest', 'url': 'speedtest.donavanaldrich.com'},\n",
+ " {'service': 'splash', 'url': 'splash.donavanaldrich.com'},\n",
+ " {'service': 'sshwifty', 'url': 'ssh.donavanaldrich.com'},\n",
+ " {'service': 'swagger-editor', 'url': 'swagger.donavanaldrich.com'},\n",
+ " {'service': 'api@internal', 'url': 'traefik.donavanaldrich.com'},\n",
+ " {'service': 'transmission', 'url': 'transmission.donavanaldrich.com'},\n",
+ " {'service': 'ubooquity-admin', 'url': 'books.donavanaldrich.com'},\n",
+ " {'service': 'vault', 'url': 'vault.donavanaldrich.com'},\n",
+ " {'service': 'vpn', 'url': 'vpn.donavanaldrich.com'},\n",
+ " {'service': 'vscode', 'url': 'code.donavanaldrich.com'}]\n"
+ ]
+ }
+ ],
+ "source": [
+ "deduplicated_list = []\n",
+ "deduped_keys = list()\n",
+ "for y in items:\n",
+ " key = y['url']\n",
+ " if key not in deduped_keys:\n",
+ " deduped_keys.append(key)\n",
+ " deduplicated_list.append(y)\n",
+ "\n",
+ "pprint.pprint(deduplicated_list)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "id": "fc0c7be4-acdb-4468-9428-c15f682b4c1e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "('\\n'\n",
+ " '[Settings]\\n'\n",
+ " 'theme = dark\\n'\n",
+ " 'accent = purple\\n'\n",
+ " 'background = None\\n'\n",
+ " 'roles = admin,user,public_user\\n'\n",
+ " 'home_access_groups = admin_only\\n'\n",
+ " 'settings_access_groups = admin_only\\n'\n",
+ " 'custom_app_title = DashMachine\\n'\n",
+ " 'sidebar_default = open\\n'\n",
+ " 'tags = {\"name\": \"foo\", \"icon\": \"home\", \"sort_pos\": \"2\"}\\n'\n",
+ " '\\n'\n",
+ " '[admin]\\n'\n",
+ " 'role = admin\\n'\n",
+ " 'password = 69\\n'\n",
+ " 'confirm_password = ibanez69\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[active_workflow]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = workflow.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/active_workflow.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/active_workflow.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[alertmanager]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = alertmanager.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/alertmanager.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/alertmanager.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[ansible]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = ansible.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/ansible.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/ansible.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[apprise]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = notify.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/apprise.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/apprise.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[authelia]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = authelia.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/authelia.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/authelia.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[bitwarden2]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = password.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/bitwarden2.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/bitwarden2.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[blackbox]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = blackbox.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/blackbox.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/blackbox.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[browserless]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = browserless.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/browserless.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/browserless.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[cachet]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cachet.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/cachet.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/cachet.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[caddy]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = caddy.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/caddy.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/caddy.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[chronograf]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = chronograf.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/chronograf.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/chronograf.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[cloudflare]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cloudflare.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/cloudflare.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/cloudflare.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[cron]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cron.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/cron.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/cron.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[cronicle]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cronicle.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/cronicle.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/cronicle.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[cyberchef]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cyberchef.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/cyberchef.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/cyberchef.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[dashmachine]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = menu.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/dashmachine.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/dashmachine.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[directus]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cms.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/directus.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/directus.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[dozzle]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = dozzle.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/dozzle.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/dozzle.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[elastichq]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = elastic.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/elastichq.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/elastichq.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[gatus]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = gatus.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/gatus.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/gatus.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[grafana]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = grafana.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/grafana.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/grafana.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[hass-configurator]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = home-config.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/hass-configurator.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/hass-configurator.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[healthcheck]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = health.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/healthcheck.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/healthcheck.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[homeassistant]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = home.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/homeassistant.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/homeassistant.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[homebridge]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = homebridge.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/homebridge.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/homebridge.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[homer]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = homer.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/homer.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/homer.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[huginn]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = huginn.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/huginn.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/huginn.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[influx]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = influx.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/influx.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/influx.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[jackett]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = jackett.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/jackett.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/jackett.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[jupyter]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = jupyter.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/jupyter.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/jupyter.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[kong]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = api.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/kong.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/kong.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[kong]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = kong.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/kong.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/kong.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[konga]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = konga.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/konga.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/konga.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[lidarr]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = lidarr.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/lidarr.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/lidarr.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[linkace]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = bookmarks.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/linkace.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/linkace.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[mattermost]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = chat.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/mattermost.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/mattermost.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[metabase]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = analytics.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/metabase.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/metabase.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[minio]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = minio.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/minio.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/minio.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[monica]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = monica.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/monica.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/monica.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[netdata]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = netdata.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/netdata.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/netdata.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[nextcloud]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = cloud.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/nextcloud.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/nextcloud.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[nodejs-dev]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = dev.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/nodejs-dev.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/nodejs-dev.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[nodejs]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = node.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/nodejs.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/nodejs.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[nodered]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = nodered.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/nodered.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/nodered.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[opsdroid]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = droid.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/opsdroid.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/opsdroid.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[overseerr]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = media.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/overseerr.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/overseerr.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[paperless]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = docs.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/paperless.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/paperless.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[pdf-rendering-srv]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = pdf-render.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/pdf-rendering-srv.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/pdf-rendering-srv.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[pgadmin]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = pgadmin.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/pgadmin.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/pgadmin.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[pgweb]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = pgweb.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/pgweb.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/pgweb.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[phpmyadmin]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = mysql.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/phpmyadmin.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/phpmyadmin.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[pihole]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = pihole.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/pihole.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/pihole.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[plex]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = plex.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/plex.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/plex.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[portainer]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = portainer.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/portainer.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/portainer.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[prometheus]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = prometheus.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/prometheus.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/prometheus.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[promtail]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = promtail.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/promtail.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/promtail.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[proxmox]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = proxmox.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/proxmox.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/proxmox.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[pushgateway]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = pushgateway.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/pushgateway.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/pushgateway.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[pyload]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = pyload.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/pyload.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/pyload.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[radarr]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = radarr.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/radarr.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/radarr.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[redis]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = redis.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/redis.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/redis.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[request-baskets]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = requests.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/request-baskets.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/request-baskets.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[requestrr]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = requestrr.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/requestrr.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/requestrr.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[router]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = router.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/router.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/router.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[script-server]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = script.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/script-server.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/script-server.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[scrutiny]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = disk.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/scrutiny.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/scrutiny.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[snmp]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = snmp.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/snmp.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/snmp.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[sonarr]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = sonarr.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/sonarr.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/sonarr.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[speedtest]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = speedtest.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/speedtest.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/speedtest.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[splash]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = splash.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/splash.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/splash.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[sshwifty]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = ssh.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/sshwifty.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/sshwifty.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[swagger-editor]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = swagger.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/swagger-editor.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/swagger-editor.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[api@internal]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = traefik.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/api@internal.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/api@internal.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[transmission]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = transmission.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/transmission.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/transmission.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[ubooquity-admin]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = books.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/ubooquity-admin.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/ubooquity-admin.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[vault]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = vault.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/vault.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/vault.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[vpn]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = vpn.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/vpn.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/vpn.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '[vscode]\\n'\n",
+ " 'prefix = https://\\n'\n",
+ " 'url = code.donavanaldrich.com\\n'\n",
+ " '\\n'\n",
+ " 'icon = static/images/apps/vscode.png\\n'\n",
+ " 'sidebar_icon = static/images/apps/vscode.png\\n'\n",
+ " '\\n'\n",
+ " 'description = default\\n'\n",
+ " 'open_in = iframe\\n'\n",
+ " '# data_sources = sh_http,sh_health,sh_ping,sh_rest\\n'\n",
+ " 'tags = default\\n'\n",
+ " '# groups = admin_only\\n'\n",
+ " '\\n'\n",
+ " '\\n'\n",
+ " '\\n')\n"
+ ]
+ }
+ ],
+ "source": [
+ "from jinja2 import Environment, FileSystemLoader, select_autoescape\n",
+ "\n",
+ "items = deduplicated_list\n",
+ "\n",
+ "env = Environment(\n",
+ " loader=FileSystemLoader([\"templates\"]),\n",
+ " # autoescape=select_autoescape()\n",
+ ")\n",
+ "\n",
+ "t = env.get_template(\"template.test\")\n",
+ "pprint.pprint(t.render(item=items[0], items=items))\n",
+ "#\n",
+ "with open(\"test.ini\", \"w\") as external_file:\n",
+ " # add_text = \"This text will be added to the file\"\n",
+ " print(t.render(item=items[0], items=items), file=external_file)\n",
+ " external_file.close()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6c539205-93cd-4b0a-9a0d-6c88696ee92a",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.9.13 64-bit",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "b0fa6594d8f4cbf19f97940f81e996739fb7646882a419484c72d19e05852a7e"
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/templating/template.test b/templating/template.test
new file mode 100644
index 0000000..ae3ec55
--- /dev/null
+++ b/templating/template.test
@@ -0,0 +1,43 @@
+
+
+
+
+ My Webpage
+
+
+
+
+[{{ name }}]
+prefix = https://
+url = your-website.com
+icon = static/images/apps/sh.png
+sidebar_icon = static/images/apps/{{ name }}.png
+description = default
+open_in = iframe
+data_sources = sh_http,sh_health,sh_ping,sh_rest
+tags = default
+groups = admin_only
+
+ {# a comment #}
+
+
+
+
+[{{ name }}]
+prefix = https://
+url = your-website.com
+icon = static/images/apps/sh.png
+sidebar_icon = static/images/apps/{{ name }}.png
+description = default
+open_in = iframe
+data_sources = sh_http,sh_health,sh_ping,sh_rest
+tags = default
+groups = admin_only
+
+ {# a comment #}
+ | | | | |