diff --git a/milky-way/environments/default/digests.libsonnet b/milky-way/environments/default/digests.libsonnet index 2007a34..784f3f5 100644 --- a/milky-way/environments/default/digests.libsonnet +++ b/milky-way/environments/default/digests.libsonnet @@ -1 +1 @@ -import 'milky-way/lib/digests.libsonnet' +import 'milky-way/lib/images.libsonnet' diff --git a/milky-way/lib/CLAUDE.md b/milky-way/lib/CLAUDE.md index b0ab514..5f938ea 100644 --- a/milky-way/lib/CLAUDE.md +++ b/milky-way/lib/CLAUDE.md @@ -86,38 +86,38 @@ to cross-reference resources, and the helpers in `utils.libsonnet`: Drive pod labels and Service selectors off one `spec.selector.matchLabels` (`{} + this.deployment.spec.selector.matchLabels`) so they can't drift apart. -## Pin images by digest, default from `digests.libsonnet` +## Pin images by digest, default from `images.libsonnet` Give every service a default `image` parameter, and make that default resolve to an **immutable digest**, never a floating tag. -- **Our own (whale-built) images:** the default should come from `digests.libsonnet` — never +- **Our own (whale-built) images:** the default should come from `images.libsonnet` — never hand-write the digest. Default the param to - `digests[""].fullyQualifiedImageReferencePinned`, exactly as + `images[""].fullyQualifiedImageReferencePinned`, exactly as `test-example-whale-image-digest.libsonnet` does: ```jsonnet - local digests = import 'milky-way/lib/digests.libsonnet'; + local images = import 'milky-way/lib/images.libsonnet'; // ... - image=digests["example-image"].fullyQualifiedImageReferencePinned, + image=images["example-image"].fullyQualifiedImageReferencePinned, ``` Those digests are read from `exports/whale/digests/.txt` (written by `nix run ./flake-profiles/whale#whale-push-`), so the pin tracks the build automatically — when you push a new image, the default updates with it. To onboard a new whale image, add it - to the `raw` map in `digests.libsonnet`. -- **Third-party images with a known digest:** centralize them in `digests.libsonnet` too — add a + to the `raw` map in `images.libsonnet`. +- **Third-party images with a known digest:** centralize them in `images.libsonnet` too — add a `raw` entry whose digest is a `{ hash, tagHint? }` object and default the param to - `digests[""].fullyQualifiedImageReferencePinned`. `hash` (`sha256:…`) is what's enforced; + `images[""].fullyQualifiedImageReferencePinned`. `hash` (`sha256:…`) is what's enforced; the optional `tagHint` (e.g. `v3.41.1`) is folded back in for readability, rendering `repo:tagHint@sha256:…`. An image shared by several consumers (e.g. `traefik/whoami` across the tailscale smoke tests) uses one `digestFor` object per consumer → - `digests.whoami.fullyQualifiedImageReferencePinnedFor`. -- **Third-party images without a digest (tag-only):** still centralize them in `digests.libsonnet` + `images.whoami.fullyQualifiedImageReferencePinnedFor`. +- **Third-party images without a digest (tag-only):** still centralize them in `images.libsonnet` rather than inlining a bare tag string — add a `raw` entry and default the param to its derived reference. A single-service image uses `defaultTag` → - `digests[""].fullyQualifiedImageReferenceTagged`; an image shared by several services at + `images[""].fullyQualifiedImageReferenceTagged`; an image shared by several services at (possibly) different versions (e.g. `busybox` used as an init/helper image) gets one `tagFor` property per consumer → - `digests.busybox.fullyQualifiedImageReferenceTaggedFor`. These tagged references are + `images.busybox.fullyQualifiedImageReferenceTaggedFor`. These tagged references are **DEPRECATED** — they exist to migrate off inline tag strings and to give one editing point per image; prefer a real digest pin whenever one is available. (When no tag is specified upstream, use `latest`, matching Kubernetes' default.) diff --git a/milky-way/lib/calibre-web-automated.libsonnet b/milky-way/lib/calibre-web-automated.libsonnet index 13bb0eb..9a9a7dd 100644 --- a/milky-way/lib/calibre-web-automated.libsonnet +++ b/milky-way/lib/calibre-web-automated.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/lib/utils.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; local defaultAppName = "calibre-web-auto"; { @@ -7,7 +7,7 @@ local defaultAppName = "calibre-web-auto"; domain, name=defaultAppName, namespace="default", - image=digests["calibre-web-automated"].fullyQualifiedImageReferenceTagged, + image=images["calibre-web-automated"].fullyQualifiedImageReferenceTagged, timezone="UTC", ):: { local this = self, diff --git a/milky-way/lib/ddns-updater.libsonnet b/milky-way/lib/ddns-updater.libsonnet index 5e86faf..46f9af5 100644 --- a/milky-way/lib/ddns-updater.libsonnet +++ b/milky-way/lib/ddns-updater.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/lib/utils.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; { new( @@ -7,7 +7,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; domain, // Ingress host for the web UI name='ddns-updater', namespace='default', - image=digests["ddns-updater"].fullyQualifiedImageReferenceTagged, + image=images["ddns-updater"].fullyQualifiedImageReferenceTagged, port=8000, ):: { local this = self, diff --git a/milky-way/lib/example-zfs-generic-iscsi.libsonnet b/milky-way/lib/example-zfs-generic-iscsi.libsonnet index a8b86c4..d251336 100644 --- a/milky-way/lib/example-zfs-generic-iscsi.libsonnet +++ b/milky-way/lib/example-zfs-generic-iscsi.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/environments/default/utils.jsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; local defaultAppName = "iscsi-test"; { new( @@ -36,7 +36,7 @@ local defaultAppName = "iscsi-test"; containers: [ { name: "writer", - image: digests.busybox.fullyQualifiedImageReferenceTaggedForExampleZfs, + image: images.busybox.fullyQualifiedImageReferenceTaggedForExampleZfs, command: [ "sh", "-c", diff --git a/milky-way/lib/gluetun-leak-test.libsonnet b/milky-way/lib/gluetun-leak-test.libsonnet index ca438da..3705fc5 100644 --- a/milky-way/lib/gluetun-leak-test.libsonnet +++ b/milky-way/lib/gluetun-leak-test.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/lib/utils.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; // VPN leak-test for the qbittorrent + gluetun pod. It continuously verifies that the torrent // client's egress is the VPN exit, never the home/ISP IP, and exercises a REAL torrent magnet @@ -38,7 +38,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; // real gate is exit-org != home-org. Set e.g. '(?i)nord|tefincom|m247|datacamp' to also require a match. expectedVpnOrgRegex='', checkIntervalSeconds=300, - image=digests.python.fullyQualifiedImageReferencePinned, + image=images.python.fullyQualifiedImageReferencePinned, ):: { local this = self, diff --git a/milky-way/lib/gluetun.libsonnet b/milky-way/lib/gluetun.libsonnet index 89039ef..34ff732 100644 --- a/milky-way/lib/gluetun.libsonnet +++ b/milky-way/lib/gluetun.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/lib/utils.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; // gluetun VPN-sidecar BUILDER (https://github.com/qdm12/gluetun). Unlike the other libs this does // NOT return a Deployment -- it returns embeddable fragments that a HOST lib (e.g. qbittorrent) @@ -37,7 +37,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; // the methanol cluster: pod 10.42.0.0/16, service 10.43.0.0/16). Re-check if networking changes. firewallOutboundSubnets='10.42.0.0/16,10.43.0.0/16', firewallInputPorts=[controlPort], // host adds its app port (e.g. WebUI) too - image=digests.gluetun.fullyQualifiedImageReferencePinned, + image=images.gluetun.fullyQualifiedImageReferencePinned, ):: { local this = self, assert vpnType == 'wireguard' || vpnType == 'openvpn' diff --git a/milky-way/lib/http-echo.libsonnet b/milky-way/lib/http-echo.libsonnet index 7ec2889..35ac54e 100644 --- a/milky-way/lib/http-echo.libsonnet +++ b/milky-way/lib/http-echo.libsonnet @@ -1,9 +1,9 @@ local utils = import "milky-way/lib/utils.libsonnet"; -local digests = import "milky-way/lib/digests.libsonnet"; +local images = import "milky-way/lib/images.libsonnet"; { new( name="http-echo", - image=digests["http-echo"].fullyQualifiedImageReferenceTagged, + image=images["http-echo"].fullyQualifiedImageReferenceTagged, port=5678, ):: { local this = self, diff --git a/milky-way/lib/digests.libsonnet b/milky-way/lib/images.libsonnet similarity index 99% rename from milky-way/lib/digests.libsonnet rename to milky-way/lib/images.libsonnet index 9a79440..8164469 100644 --- a/milky-way/lib/digests.libsonnet +++ b/milky-way/lib/images.libsonnet @@ -1,4 +1,4 @@ -local digests = { +local images = { local this = self, // Render a pinned image reference from a digest object { hash, tagHint? }. The hash (e.g. @@ -110,4 +110,4 @@ local digests = { for field in std.objectFields(this.embellished) }, }; -digests.public +images.public diff --git a/milky-way/lib/kata-microvm-test.libsonnet b/milky-way/lib/kata-microvm-test.libsonnet index 63c9dc6..aa02064 100644 --- a/milky-way/lib/kata-microvm-test.libsonnet +++ b/milky-way/lib/kata-microvm-test.libsonnet @@ -1,10 +1,10 @@ local kataRuntimeClass = import "milky-way/lib/kata-runtime-class.libsonnet"; -local digests = import "milky-way/lib/digests.libsonnet"; +local images = import "milky-way/lib/images.libsonnet"; { new( name="kata-microvm-test", namespace="test-k8s", - image=digests.busybox.fullyQualifiedImageReferenceTaggedForKataMicrovmTest, + image=images.busybox.fullyQualifiedImageReferenceTaggedForKataMicrovmTest, ):: { local this = self, diff --git a/milky-way/lib/openclaw.libsonnet b/milky-way/lib/openclaw.libsonnet index 2b51658..d5de39a 100644 --- a/milky-way/lib/openclaw.libsonnet +++ b/milky-way/lib/openclaw.libsonnet @@ -1,6 +1,6 @@ local utils = import 'milky-way/lib/utils.libsonnet'; local kataRuntimeClass = import 'milky-way/lib/kata-runtime-class.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; // OpenClaw AI agent gateway. We draw on OpenClaw's official k8s manifests // (https://docs.openclaw.ai/install/kubernetes) but follow this repo's convention instead of @@ -21,7 +21,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; geminiApiKey, // -> GEMINI_API_KEY (the google/* provider) name='openclaw', namespace='openclaw', // OPENCLAW_NAMESPACE equivalent - image=digests.openclaw.fullyQualifiedImageReferenceTagged, + image=images.openclaw.fullyQualifiedImageReferenceTagged, port=18789, model='google/gemini-3-flash-preview', tailscaleHostname='openclaw', // -> https://openclaw..ts.net @@ -29,7 +29,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; // origin https://..ts.net is allowed storageClassName='my-custom-zfs-generic-iscsi', storageSize='10Gi', - initImage=digests.busybox.fullyQualifiedImageReferenceTaggedForOpenclaw, + initImage=images.busybox.fullyQualifiedImageReferenceTaggedForOpenclaw, debugIdle=false, // when true: replace the gateway with a no-op idle command and // drop the probes so the pod stays up WITHOUT running the gateway. // Lets you `kubectl exec` in to repair ~/.openclaw (e.g. a bad diff --git a/milky-way/lib/qbittorrent.libsonnet b/milky-way/lib/qbittorrent.libsonnet index 6498b84..ff36534 100644 --- a/milky-way/lib/qbittorrent.libsonnet +++ b/milky-way/lib/qbittorrent.libsonnet @@ -1,6 +1,6 @@ local utils = import 'milky-way/lib/utils.libsonnet'; local gluetun = import 'milky-way/lib/gluetun.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; // Headless qbittorrent whose traffic is forced through a VPN by an embedded gluetun sidecar (see // lib/gluetun.libsonnet). gluetun + qbittorrent share one network namespace (same pod), and @@ -17,7 +17,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; wireguardPrivateKey, // positional, required -> gluetun (NordVPN/WireGuard) name='qbittorrent', namespace='default', - image=digests.qbittorrent.fullyQualifiedImageReferencePinned, + image=images.qbittorrent.fullyQualifiedImageReferencePinned, webuiPort=8080, tailscaleHostname='qbittorrent', // -> https://qbittorrent..ts.net serverCountries='United States', @@ -26,7 +26,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; mediaClaimName='mdata', // external shared RWX media PVC (defined in main.jsonnet) mediaMountPath='/data', // whole media volume mounted here downloadsSubdir='downloads/qbittorrent', // qbittorrent's save dir within the media volume - initImage=digests.busybox.fullyQualifiedImageReferenceTaggedForQbittorrent, + initImage=images.busybox.fullyQualifiedImageReferenceTaggedForQbittorrent, ):: { local this = self, local controlPort = 8000, // gluetun control server (publicip route) diff --git a/milky-way/lib/test-example-whale-image-digest.libsonnet b/milky-way/lib/test-example-whale-image-digest.libsonnet index 0ebb31c..2897a2f 100644 --- a/milky-way/lib/test-example-whale-image-digest.libsonnet +++ b/milky-way/lib/test-example-whale-image-digest.libsonnet @@ -1,10 +1,10 @@ -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; { new( name="test-example-whale-image-digest", namespace="test-k8s", - // Pinned by manifest digest from exports/whale/digests/, via the shared digests lib. - image=digests["example-image"].fullyQualifiedImageReferencePinned, + // Pinned by manifest digest from exports/whale/digests/, via the shared images lib. + image=images["example-image"].fullyQualifiedImageReferencePinned, ):: { local this = self, diff --git a/milky-way/lib/test-tailscale-operator-ingress.libsonnet b/milky-way/lib/test-tailscale-operator-ingress.libsonnet index 1539a60..086c760 100644 --- a/milky-way/lib/test-tailscale-operator-ingress.libsonnet +++ b/milky-way/lib/test-tailscale-operator-ingress.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/lib/utils.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; // A minimal smoke test for the Tailscale operator's L7 Ingress path // (`ingressClassName: tailscale`). It deploys a single whoami pod, a ClusterIP @@ -15,7 +15,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; name='test-ts-ingress', namespace='test-k8s', // whoami echoes the request + headers, making a successful proxy hop self-evident. - image=digests.whoami.fullyQualifiedImageReferencePinnedForTailscaleOperatorIngressTest, + image=images.whoami.fullyQualifiedImageReferencePinnedForTailscaleOperatorIngressTest, ):: { local this = self, diff --git a/milky-way/lib/test-tailscale-operator-network-L3.libsonnet b/milky-way/lib/test-tailscale-operator-network-L3.libsonnet index f75fa4d..dd89c1e 100644 --- a/milky-way/lib/test-tailscale-operator-network-L3.libsonnet +++ b/milky-way/lib/test-tailscale-operator-network-L3.libsonnet @@ -1,5 +1,5 @@ local utils = import 'milky-way/lib/utils.libsonnet'; -local digests = import 'milky-way/lib/digests.libsonnet'; +local images = import 'milky-way/lib/images.libsonnet'; // A minimal smoke test for the Tailscale operator's L3 tailnet-exposure path // (a `ProxyGroup` of type `ingress` + a `Service` of `type: LoadBalancer` with @@ -54,7 +54,7 @@ local digests = import 'milky-way/lib/digests.libsonnet'; name='test-ts-l3', namespace='test-k8s', // whoami echoes the request + headers, making a successful proxy hop self-evident. - image=digests.whoami.fullyQualifiedImageReferencePinnedForTailscaleOperatorNetworkL3Test, + image=images.whoami.fullyQualifiedImageReferencePinnedForTailscaleOperatorNetworkL3Test, replicas=1, // ProxyGroup proxy replicas (the doc uses 2; 1 keeps the test light) ):: { local this = self,