From 1cfdb459ac2340127a7d75b90eb056930e2ee4ea Mon Sep 17 00:00:00 2001 From: Kees van Loenen Date: Tue, 10 Feb 2026 17:27:15 +0100 Subject: [PATCH] Added Dockhand custom-api widget --- widgets/dockhand/README.md | 167 +++++++++++++++++++++++++++++++++++ widgets/dockhand/meta.yml | 3 + widgets/dockhand/preview.png | Bin 0 -> 19283 bytes 3 files changed, 170 insertions(+) create mode 100644 widgets/dockhand/README.md create mode 100644 widgets/dockhand/meta.yml create mode 100644 widgets/dockhand/preview.png diff --git a/widgets/dockhand/README.md b/widgets/dockhand/README.md new file mode 100644 index 00000000..e44c1f94 --- /dev/null +++ b/widgets/dockhand/README.md @@ -0,0 +1,167 @@ +![](preview.png) + +```yaml +- type: custom-api + title: Dockhand + title-url: ${DOCKHAND_URL} + cache: 1h + + url: ${DOCKHAND_URL}/api/environments?env=1 + + subrequests: + containers: + url: ${DOCKHAND_URL}/api/containers?env=1 + images: + url: ${DOCKHAND_URL}/api/images?env=1 + networks: + url: ${DOCKHAND_URL}/api/networks?env=1 + volumes: + url: ${DOCKHAND_URL}/api/volumes?env=1 + stacks: + url: ${DOCKHAND_URL}/api/stacks?env=1 + + template: | + + + {{ $containers := (.Subrequest "containers").JSON.Array "" }} + {{ $images := (.Subrequest "images").JSON.Array "" }} + {{ $networks := (.Subrequest "networks").JSON.Array "" }} + {{ $volumes := (.Subrequest "volumes").JSON.Array "" }} + {{ $stacks := (.Subrequest "stacks").JSON.Array "" }} + + {{ $running := 0 }} + {{ $stopped := 0 }} + {{ range $containers }} + {{ if eq (.String "state") "running" }} + {{ $running = add $running 1 }} + {{ else }} + {{ $stopped = add $stopped 1 }} + {{ end }} + {{ end }} + +
+ +
+
{{ $running }}
+ + + + + + +
+ +
+
{{ $stopped }}
+ + + + + + +
+ +
+ +
{{ len $images }}
+
+
Images
+ + {{ $unused := 0 }} + {{ $totalBytes := 0 }} + {{ range $images }} + {{ if eq (.Int "containers") 0 }} + {{ $unused = add $unused 1 }} + {{ end }} + {{ $totalBytes = add $totalBytes (.Int "size") }} + {{ end }} + + {{ $totalGB := div $totalBytes 1073741824 }} + {{ $decimal := mod (div $totalBytes 1048576) 1024 }} + +
+
Unused images:
+
{{ $unused }}
+
+
+
Total size:
+
{{ printf "%d.%02d GB" $totalGB $decimal }}
+
+
+ + + + + +
+ +
+
{{ len $volumes }}
+ + + + + +
+ +
+
+
Networks
+ {{ range $networks }} +
+
{{ .String "name" }}
+
+ {{ $cfg := .Array "ipam.config" }} + {{ if gt (len $cfg) 0 }} + {{ (index $cfg 0).String "subnet" }} + {{ else }} + — + {{ end }} +
+
+ {{ end }} +
+
{{ len $networks }}
+ + + + + + + +
+ +
+
{{ len $stacks }}
+ + + + + +
+ +
+``` + +## Environment variables + +- `DOCKHAND_URL` - The URL for your running Dockhand container, including port but without trailing slash, e.g.: 'http://192.168.1.2:2283', or 'https://dockhand.example.com' + +## Dockhand environment + +- Update the number in `?env=1` to match the environment of which you want to display information + diff --git a/widgets/dockhand/meta.yml b/widgets/dockhand/meta.yml new file mode 100644 index 00000000..55bfbf8f --- /dev/null +++ b/widgets/dockhand/meta.yml @@ -0,0 +1,3 @@ +title: Dockhand +description: Show most important information from Dockhand: number of running/stopped containers, images, volumes, networks and stacks +author: keesvanloenen \ No newline at end of file diff --git a/widgets/dockhand/preview.png b/widgets/dockhand/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..f27acfc4b7127cff59f1dd2885251d2d4339632a GIT binary patch literal 19283 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