From 091e7b78dfed5d8e67cdbec14fe60c75d7627acf Mon Sep 17 00:00:00 2001 From: Laur IVAN Date: Fri, 27 Feb 2026 07:07:56 +0100 Subject: [PATCH] feat: Add Atuin and Kubernetes schema publisher applications, migrate to the new apps directory structure, and update Prometheus ingress hostnames. --- .taskfiles/tools/Taskfile.yaml | 19 + .../{beta => apps}/communication/README.md | 0 .../apps/communication/kustomization.yaml | 12 + kubernetes/apps/communication/namespace.yaml | 7 + .../publish-k8s-schemas/app.ks.yaml | 16 + .../app/externalsecret.yaml | 21 + .../publish-k8s-schemas/app/helmrelease.yaml | 130 ++++++ .../app/kustomization.yaml | 16 + .../app/resources/generate-index.sh | 37 ++ .../app/resources/index.html | 391 ++++++++++++++++++ .../publish-k8s-schemas/kustomization.yaml | 6 + kubernetes/{beta => apps}/dev/README.md | 0 .../{beta => apps}/dev/atuin/app.ks.yaml | 0 .../dev/atuin/app/helmrelease.yaml | 0 .../dev/atuin/app/kustomization.yaml | 0 .../dev/atuin/app/ocirepository.yaml | 0 .../dev/atuin/kustomization.yaml | 0 .../{beta => apps}/dev/kustomization.yaml | 0 kubernetes/{beta => apps}/dev/namespace.yaml | 0 .../app/helmrelease.yaml | 14 +- 20 files changed, 662 insertions(+), 7 deletions(-) rename kubernetes/{beta => apps}/communication/README.md (100%) create mode 100644 kubernetes/apps/communication/kustomization.yaml create mode 100644 kubernetes/apps/communication/namespace.yaml create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/app.ks.yaml create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/app/externalsecret.yaml create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/app/helmrelease.yaml create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/app/kustomization.yaml create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/app/resources/generate-index.sh create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/app/resources/index.html create mode 100644 kubernetes/apps/communication/publish-k8s-schemas/kustomization.yaml rename kubernetes/{beta => apps}/dev/README.md (100%) rename kubernetes/{beta => apps}/dev/atuin/app.ks.yaml (100%) rename kubernetes/{beta => apps}/dev/atuin/app/helmrelease.yaml (100%) rename kubernetes/{beta => apps}/dev/atuin/app/kustomization.yaml (100%) rename kubernetes/{beta => apps}/dev/atuin/app/ocirepository.yaml (100%) rename kubernetes/{beta => apps}/dev/atuin/kustomization.yaml (100%) rename kubernetes/{beta => apps}/dev/kustomization.yaml (100%) rename kubernetes/{beta => apps}/dev/namespace.yaml (100%) diff --git a/.taskfiles/tools/Taskfile.yaml b/.taskfiles/tools/Taskfile.yaml index 46256f6..28e9793 100644 --- a/.taskfiles/tools/Taskfile.yaml +++ b/.taskfiles/tools/Taskfile.yaml @@ -12,3 +12,22 @@ tasks: - test -f {{.ROOT_DIR}}/.sops.yaml - test -f {{.SCRIPTS_DIR}}/bootstrap-apps.sh - test -f {{.SOPS_AGE_KEY_FILE}} + ping: + desc: Ping the available routes + dir: "{{.ROOT_DIR}}" + cmds: + - | + for route in $(kubectl get httproute -A -o jsonpath='{.items[*].spec.hostnames[*]}'); do + ip=$(nslookup $route 2>/dev/null | grep -A 1 "Name:" | grep "Address:" | head -n 1 | awk '{print $2}') || true + if [ -n "$ip" ]; then + echo "✔ $route ($ip)" + else + echo "✗ $route" + fi + done + true + preconditions: + - test -f {{.KUBECONFIG}} + - test -f {{.ROOT_DIR}}/.sops.yaml + - test -f {{.SCRIPTS_DIR}}/bootstrap-apps.sh + - test -f {{.SOPS_AGE_KEY_FILE}} diff --git a/kubernetes/beta/communication/README.md b/kubernetes/apps/communication/README.md similarity index 100% rename from kubernetes/beta/communication/README.md rename to kubernetes/apps/communication/README.md diff --git a/kubernetes/apps/communication/kustomization.yaml b/kubernetes/apps/communication/kustomization.yaml new file mode 100644 index 0000000..041a3b1 --- /dev/null +++ b/kubernetes/apps/communication/kustomization.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: communication + +components: + - ../../components/sops + - ../../components/repos/app-template + +resources: [] + #- ./namespace.yaml + #- ./publish-k8s-schemas diff --git a/kubernetes/apps/communication/namespace.yaml b/kubernetes/apps/communication/namespace.yaml new file mode 100644 index 0000000..5ac63ea --- /dev/null +++ b/kubernetes/apps/communication/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: _ + annotations: + kustomize.toolkit.fluxcd.io/prune: disabled diff --git a/kubernetes/apps/communication/publish-k8s-schemas/app.ks.yaml b/kubernetes/apps/communication/publish-k8s-schemas/app.ks.yaml new file mode 100644 index 0000000..8f2bd8c --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/app.ks.yaml @@ -0,0 +1,16 @@ +--- +# yaml-language-server: $schema=https://schemas.tholinka.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: publish-k8s-schemas + namespace: &namespace communication +spec: + interval: 1h + path: ./kubernetes/apps/communication/publish-k8s-schemas/app + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: *namespace diff --git a/kubernetes/apps/communication/publish-k8s-schemas/app/externalsecret.yaml b/kubernetes/apps/communication/publish-k8s-schemas/app/externalsecret.yaml new file mode 100644 index 0000000..ed34b4d --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/app/externalsecret.yaml @@ -0,0 +1,21 @@ +--- +# yaml-language-server: $schema=https://schemas.tholinka.dev/external-secrets.io/externalsecret_v1.json +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: &secret publish-k8s-schemas +spec: + refreshInterval: 12h + secretStoreRef: + kind: ClusterSecretStore + name: bitwarden + target: + name: *secret + creationPolicy: Owner + template: + data: + CLOUDFLARE_ACCOUNT_ID: '{{ .CLOUDFLARE_ACCOUNT_ID }}' + CLOUDFLARE_API_TOKEN: '{{ .CLOUDFLARE_K8S_SCHEMAS }}' + dataFrom: + - extract: + key: cloudflare diff --git a/kubernetes/apps/communication/publish-k8s-schemas/app/helmrelease.yaml b/kubernetes/apps/communication/publish-k8s-schemas/app/helmrelease.yaml new file mode 100644 index 0000000..4936cc7 --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/app/helmrelease.yaml @@ -0,0 +1,130 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: &app publish-k8s-schemas +spec: + interval: 1h + chartRef: + kind: OCIRepository + name: app-template + values: + controllers: + *app : + type: cronjob + cronjob: + backoffLimit: 3 + concurrencyPolicy: 'Replace' + failedJobsHistory: 1 + schedule: '0 */4 * * *' + successfulJobsHistory: 0 + + initContainers: + generate-schemas: + image: + repository: ghcr.io/bjw-s-labs/k8s-crd-extractor + tag: 2025.12.22@sha256:176cc556053abba6fda83eeb398531cd33c3092553cab8a49a736f68972c057b + command: [/usr/bin/catatonit, --, sh] + args: + - -c + - /app/crd-extractor.sh && exec sh /config/map/generate-index.sh + resources: + requests: + cpu: 10m + memory: 128Mi + limits: + memory: 2Gi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: { drop: [ALL] } + + containers: + app: + image: + repository: ghcr.io/bjw-s-labs/wrangler + tag: 4.68.1@sha256:6366b6eafbdf519d5391713ad247ab80bea7bcb3572387f5029aecb38570cc69 + envFrom: + - secretRef: + name: *app + args: + - pages + - deploy + - /data/crdSchemas + - --project-name + - kubernetes-schemas + resources: + requests: + cpu: 10m + memory: 128Mi + limits: + memory: 1Gi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: { drop: [ALL] } + defaultPodOptions: + restartPolicy: OnFailure + securityContext: + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + + persistence: + tmpfs: + type: emptyDir + advancedMounts: + *app : + generate-schemas: + - path: /config/.datree + subPath: data + - path: /tmp + subPath: tmp + app: + - path: /config + subPath: config + - path: /data + subPath: data + config: + type: configMap + name: *app + advancedMounts: + *app : + generate-schemas: + - path: /config/map + readOnly: true + + serviceAccount: + *app : {} + + rbac: + roles: + *app : + type: ClusterRole + rules: + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + - customresourcedefinitions/status + verbs: + - get + - list + - watch + - apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + - apiservices/status + verbs: + - get + - list + - watch + bindings: + *app : + type: ClusterRoleBinding + roleRef: + identifier: *app + subjects: + - identifier: *app diff --git a/kubernetes/apps/communication/publish-k8s-schemas/app/kustomization.yaml b/kubernetes/apps/communication/publish-k8s-schemas/app/kustomization.yaml new file mode 100644 index 0000000..0b1e0ad --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/app/kustomization.yaml @@ -0,0 +1,16 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - externalsecret.yaml + - helmrelease.yaml +configMapGenerator: + - name: publish-k8s-schemas + files: + - generate-index.sh=./resources/generate-index.sh + - index.html=./resources/index.html +generatorOptions: + disableNameSuffixHash: true + annotations: + kustomize.toolkit.fluxcd.io/substitute: disabled diff --git a/kubernetes/apps/communication/publish-k8s-schemas/app/resources/generate-index.sh b/kubernetes/apps/communication/publish-k8s-schemas/app/resources/generate-index.sh new file mode 100644 index 0000000..a8567ed --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/app/resources/generate-index.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +cd /config/.datree/crdSchemas/ + +echo "creating index" + +# Count stats +group_count=$(find . -maxdepth 1 -type d | wc -l) +group_count=$((group_count - 1)) +schema_count=$(find . -name "*.json" | wc -l) +updated=$(date -u +"%Y-%m-%d") + +echo "groups: $group_count - schemas: $schema_count" + +# Generate schema cards HTML +schemas_html="" +for dir in */; do + dir_name="${dir%/}" + file_count=$(find "$dir" -maxdepth 1 -name "*.json" | wc -l) + files_html="" + for file in "$dir"*.json; do + if [ -f "$file" ]; then + filename=$(basename "$file") + files_html="${files_html}${filename}" + fi + done + schemas_html="${schemas_html}
${dir_name}${file_count}
${files_html}
" +done + +# Copy template and inject data +cp /config/map/index.html index.html +sed -i "s||${schemas_html}|g" index.html +sed -i "s|
-
|
${group_count}
|g" index.html +sed -i "s|
-
|
${schema_count}
|g" index.html +sed -i "s|
-
|
${updated}
|g" index.html + +echo "index created" diff --git a/kubernetes/apps/communication/publish-k8s-schemas/app/resources/index.html b/kubernetes/apps/communication/publish-k8s-schemas/app/resources/index.html new file mode 100644 index 0000000..fb94b08 --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/app/resources/index.html @@ -0,0 +1,391 @@ + + + + + + + Kubernetes Schemas | tholinka.dev + + + + + +
+
+ +

Kubernetes Schemas

+

CRD JSON schemas from the tholinka.dev cluster

+
+ +
+

Usage

+
+ # yaml-language-server: $schema=https://schemas.tholinka.dev/{group}/{kind}_{version}.json +
+
+ +
+ +
+ +
+
+
-
+
API Groups
+
+
+
-
+
Schemas
+
+
+
-
+
Last Updated
+
+
+ +
+ +
+ + +
+ + + + + diff --git a/kubernetes/apps/communication/publish-k8s-schemas/kustomization.yaml b/kubernetes/apps/communication/publish-k8s-schemas/kustomization.yaml new file mode 100644 index 0000000..7aacfdb --- /dev/null +++ b/kubernetes/apps/communication/publish-k8s-schemas/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ./app.ks.yaml diff --git a/kubernetes/beta/dev/README.md b/kubernetes/apps/dev/README.md similarity index 100% rename from kubernetes/beta/dev/README.md rename to kubernetes/apps/dev/README.md diff --git a/kubernetes/beta/dev/atuin/app.ks.yaml b/kubernetes/apps/dev/atuin/app.ks.yaml similarity index 100% rename from kubernetes/beta/dev/atuin/app.ks.yaml rename to kubernetes/apps/dev/atuin/app.ks.yaml diff --git a/kubernetes/beta/dev/atuin/app/helmrelease.yaml b/kubernetes/apps/dev/atuin/app/helmrelease.yaml similarity index 100% rename from kubernetes/beta/dev/atuin/app/helmrelease.yaml rename to kubernetes/apps/dev/atuin/app/helmrelease.yaml diff --git a/kubernetes/beta/dev/atuin/app/kustomization.yaml b/kubernetes/apps/dev/atuin/app/kustomization.yaml similarity index 100% rename from kubernetes/beta/dev/atuin/app/kustomization.yaml rename to kubernetes/apps/dev/atuin/app/kustomization.yaml diff --git a/kubernetes/beta/dev/atuin/app/ocirepository.yaml b/kubernetes/apps/dev/atuin/app/ocirepository.yaml similarity index 100% rename from kubernetes/beta/dev/atuin/app/ocirepository.yaml rename to kubernetes/apps/dev/atuin/app/ocirepository.yaml diff --git a/kubernetes/beta/dev/atuin/kustomization.yaml b/kubernetes/apps/dev/atuin/kustomization.yaml similarity index 100% rename from kubernetes/beta/dev/atuin/kustomization.yaml rename to kubernetes/apps/dev/atuin/kustomization.yaml diff --git a/kubernetes/beta/dev/kustomization.yaml b/kubernetes/apps/dev/kustomization.yaml similarity index 100% rename from kubernetes/beta/dev/kustomization.yaml rename to kubernetes/apps/dev/kustomization.yaml diff --git a/kubernetes/beta/dev/namespace.yaml b/kubernetes/apps/dev/namespace.yaml similarity index 100% rename from kubernetes/beta/dev/namespace.yaml rename to kubernetes/apps/dev/namespace.yaml diff --git a/kubernetes/apps/observability/kube-prometheus-stack/app/helmrelease.yaml b/kubernetes/apps/observability/kube-prometheus-stack/app/helmrelease.yaml index f96fbf8..84197e9 100644 --- a/kubernetes/apps/observability/kube-prometheus-stack/app/helmrelease.yaml +++ b/kubernetes/apps/observability/kube-prometheus-stack/app/helmrelease.yaml @@ -25,12 +25,12 @@ spec: main: enabled: true hostnames: - - alertmanager.tholinka.dev + - alertmanager.laurivan.com parentRefs: - name: envoy-internal namespace: network annotations: - gethomepage.dev/enabled: 'true' + gethomepage.dev/enabled: "true" gethomepage.dev/group: Observability gethomepage.dev/name: Alertmanager gethomepage.dev/icon: alertmanager.svg @@ -40,7 +40,7 @@ spec: name: alertmanager global: resolveTimeout: 5m - externalUrl: https://alertmanager.tholinka.dev + externalUrl: https://alertmanager.laurivan.com resources: requests: cpu: 10m @@ -68,20 +68,20 @@ spec: main: enabled: true hostnames: - - prometheus.tholinka.dev + - prometheus.laurivan.com parentRefs: - name: envoy-internal namespace: network annotations: - gethomepage.dev/enabled: 'true' + gethomepage.dev/enabled: "true" gethomepage.dev/group: Observability gethomepage.dev/name: Prometheus gethomepage.dev/icon: prometheus.svg gethomepage.dev/pod-selector: operator.prometheus.io/name=kube-prometheus-stack gethomepage.dev/widget.type: prometheus - gethomepage.dev/widget.url: 'http://kube-prometheus-stack-prometheus.observability.svc.cluster.local.:9090' + gethomepage.dev/widget.url: "http://kube-prometheus-stack-prometheus.observability.svc.cluster.local.:9090" prometheusSpec: - externalUrl: https://prometheus.tholinka.dev + externalUrl: https://prometheus.laurivan.com version: v2.55.1 # override 'unsupported Prometheus version' error for prompp image: registry: mirror.gcr.io