mirror of
https://github.com/dredx/prole.git
synced 2026-09-24 15:54:32 +00:00
Rename Prole storage objects to Synology and sync deployment updates
- Rename iSCSI storage class and PV/PVC selectors/labels from prole to synology across k8s and OpenTofu manifests\n- Update CNPG/OpenBao/Garage/monitoring init flows, render helpers, and mock scripts for synology-backed storage objects\n- Integrate related UI/core/service config/version updates and add supporting regression tests for CNPG storage/image behavior\n- Keep storage reconciliation tests aligned with current CNPG affinity output Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
parent
0262bd4be2
commit
9b9d6fdc88
83
_adopt_replica_pvcs.sh
Normal file
83
_adopt_replica_pvcs.sh
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
NS=prole-db
|
||||||
|
CLUSTER_UID=$(kubectl get cluster prole-db -n "$NS" -o jsonpath='{.metadata.uid}' 2>/dev/null)
|
||||||
|
echo "Cluster UID: $CLUSTER_UID"
|
||||||
|
|
||||||
|
echo "=== Pausing CNPG controller ==="
|
||||||
|
kubectl scale deployment cnpg-controller-manager -n cnpg-system --replicas=0
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
echo "=== Cleaning up serial 8+ PVCs and jobs ==="
|
||||||
|
for serial in 8 9 10; do
|
||||||
|
kubectl delete pvc "prole-db-${serial}" "prole-db-${serial}-wal" -n "$NS" --ignore-not-found 2>/dev/null || true
|
||||||
|
kubectl delete job -n "$NS" -l "cnpg.io/instanceName=prole-db-${serial}" --ignore-not-found 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Patching replica PVCs with full CNPG labels/annotations ==="
|
||||||
|
for serial in 3 7; do
|
||||||
|
# Data PVC
|
||||||
|
kubectl patch pvc "prole-db-${serial}" -n "$NS" --type=merge -p "{
|
||||||
|
\"metadata\": {
|
||||||
|
\"labels\": {
|
||||||
|
\"app.kubernetes.io/component\": \"database\",
|
||||||
|
\"app.kubernetes.io/managed-by\": \"cloudnative-pg\",
|
||||||
|
\"app.kubernetes.io/name\": \"postgresql\",
|
||||||
|
\"cnpg.io/cluster\": \"prole-db\",
|
||||||
|
\"cnpg.io/instanceName\": \"prole-db-${serial}\",
|
||||||
|
\"cnpg.io/instanceRole\": \"replica\",
|
||||||
|
\"cnpg.io/pvcRole\": \"PG_DATA\",
|
||||||
|
\"role\": \"replica\"
|
||||||
|
},
|
||||||
|
\"annotations\": {
|
||||||
|
\"cnpg.io/nodeSerial\": \"${serial}\",
|
||||||
|
\"cnpg.io/operatorVersion\": \"1.28.1\",
|
||||||
|
\"cnpg.io/pvcStatus\": \"ready\"
|
||||||
|
},
|
||||||
|
\"ownerReferences\": [{
|
||||||
|
\"apiVersion\": \"postgresql.cnpg.io/v1\",
|
||||||
|
\"controller\": true,
|
||||||
|
\"kind\": \"Cluster\",
|
||||||
|
\"name\": \"prole-db\",
|
||||||
|
\"uid\": \"${CLUSTER_UID}\"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
echo " Patched prole-db-${serial}"
|
||||||
|
|
||||||
|
# WAL PVC
|
||||||
|
kubectl patch pvc "prole-db-${serial}-wal" -n "$NS" --type=merge -p "{
|
||||||
|
\"metadata\": {
|
||||||
|
\"labels\": {
|
||||||
|
\"app.kubernetes.io/component\": \"database\",
|
||||||
|
\"app.kubernetes.io/managed-by\": \"cloudnative-pg\",
|
||||||
|
\"app.kubernetes.io/name\": \"postgresql\",
|
||||||
|
\"cnpg.io/cluster\": \"prole-db\",
|
||||||
|
\"cnpg.io/instanceName\": \"prole-db-${serial}\",
|
||||||
|
\"cnpg.io/instanceRole\": \"replica\",
|
||||||
|
\"cnpg.io/pvcRole\": \"PG_WAL\",
|
||||||
|
\"role\": \"replica\"
|
||||||
|
},
|
||||||
|
\"annotations\": {
|
||||||
|
\"cnpg.io/nodeSerial\": \"${serial}\",
|
||||||
|
\"cnpg.io/operatorVersion\": \"1.28.1\",
|
||||||
|
\"cnpg.io/pvcStatus\": \"ready\"
|
||||||
|
},
|
||||||
|
\"ownerReferences\": [{
|
||||||
|
\"apiVersion\": \"postgresql.cnpg.io/v1\",
|
||||||
|
\"controller\": true,
|
||||||
|
\"kind\": \"Cluster\",
|
||||||
|
\"name\": \"prole-db\",
|
||||||
|
\"uid\": \"${CLUSTER_UID}\"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
echo " Patched prole-db-${serial}-wal"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Resuming CNPG controller ==="
|
||||||
|
kubectl scale deployment cnpg-controller-manager -n cnpg-system --replicas=1
|
||||||
|
echo "Done — CNPG should now create instance pods for serials 3 (pi) and 7 (merlin)"
|
||||||
|
sleep 20
|
||||||
|
kubectl get pods,jobs -n "$NS" -o wide 2>/dev/null | grep -v "Completed\|initdb"
|
||||||
|
kubectl get cluster prole-db -n "$NS" -o jsonpath='Phase: {.status.phase} Ready: {.status.readyInstances}/{.spec.instances}{"\n"}' 2>/dev/null
|
||||||
92
_fix_replica_merlin.sh
Normal file
92
_fix_replica_merlin.sh
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
NS=prole-db
|
||||||
|
|
||||||
|
echo "=== Pausing CNPG controller ==="
|
||||||
|
kubectl scale deployment cnpg-controller-manager -n cnpg-system --replicas=0
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
echo "=== Cleaning up all pending/failed replica PVCs and jobs ==="
|
||||||
|
# Keep prole-db-1 (primary) and prole-db-3 (pi replica). Delete everything else.
|
||||||
|
for serial in 2 4 5 6 7 8 9; do
|
||||||
|
kubectl delete pvc "prole-db-${serial}" "prole-db-${serial}-wal" -n "$NS" --ignore-not-found 2>/dev/null || true
|
||||||
|
kubectl delete job -n "$NS" -l "cnpg.io/instanceName=prole-db-${serial}" --ignore-not-found 2>/dev/null || true
|
||||||
|
done
|
||||||
|
echo "Cleaned up stale PVCs and jobs"
|
||||||
|
|
||||||
|
echo "=== Clearing Released PV claimRefs ==="
|
||||||
|
for pv in synology-iscsi-d002-data synology-iscsi-d002-wal; do
|
||||||
|
kubectl patch pv "$pv" --type=json \
|
||||||
|
-p '[{"op":"remove","path":"/spec/claimRef"}]' 2>/dev/null || \
|
||||||
|
kubectl patch pv "$pv" --type=merge \
|
||||||
|
-p '{"spec":{"claimRef":{"name":"","uid":"","namespace":""}}}' 2>/dev/null || true
|
||||||
|
echo " Patched $pv"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Waiting for d002 PVs to become Available ==="
|
||||||
|
for pv in synology-iscsi-d002-data synology-iscsi-d002-wal; do
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
phase=$(kubectl get pv "$pv" -o jsonpath='{.status.phase}' 2>/dev/null)
|
||||||
|
echo " $pv: $phase"
|
||||||
|
if [[ "$phase" == "Available" ]]; then break; fi
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Getting CNPG PVC labels from existing prole-db-3 PVC ==="
|
||||||
|
CNPG_LABELS=$(kubectl get pvc prole-db-3 -n "$NS" -o jsonpath='{.metadata.labels}' 2>/dev/null || echo "{}")
|
||||||
|
echo " Labels: $CNPG_LABELS"
|
||||||
|
|
||||||
|
# Determine next serial CNPG will use (latestGeneratedNode + 1)
|
||||||
|
NEXT_SERIAL=$(kubectl get cluster prole-db -n "$NS" -o jsonpath='{.status.latestGeneratedNode}' 2>/dev/null || echo "4")
|
||||||
|
NEXT_SERIAL=$((NEXT_SERIAL + 1))
|
||||||
|
echo "=== Pre-binding prole-db-${NEXT_SERIAL} PVCs to d002 (merlin) ==="
|
||||||
|
|
||||||
|
kubectl create -f - <<YAML
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-${NEXT_SERIAL}
|
||||||
|
namespace: ${NS}
|
||||||
|
labels:
|
||||||
|
cnpg.io/cluster: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-${NEXT_SERIAL}-wal
|
||||||
|
namespace: ${NS}
|
||||||
|
labels:
|
||||||
|
cnpg.io/cluster: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-wal
|
||||||
|
YAML
|
||||||
|
echo "Created pre-bound PVCs for serial ${NEXT_SERIAL}"
|
||||||
|
|
||||||
|
echo "=== Waiting for PVCs to bind ==="
|
||||||
|
for pvc in "prole-db-${NEXT_SERIAL}" "prole-db-${NEXT_SERIAL}-wal"; do
|
||||||
|
for i in $(seq 1 20); do
|
||||||
|
phase=$(kubectl get pvc "$pvc" -n "$NS" -o jsonpath='{.status.phase}' 2>/dev/null)
|
||||||
|
echo " $pvc: $phase"
|
||||||
|
if [[ "$phase" == "Bound" ]]; then break; fi
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Resuming CNPG controller ==="
|
||||||
|
kubectl scale deployment cnpg-controller-manager -n cnpg-system --replicas=1
|
||||||
|
echo "Done — CNPG will create prole-db-${NEXT_SERIAL}-join targeting merlin.prole.org"
|
||||||
|
sleep 15
|
||||||
|
kubectl get jobs,pods -n "$NS" -o wide | grep -v "Completed\|initdb"
|
||||||
9
_import_pi.sh
Normal file
9
_import_pi.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Importing knoe-db:18-140 to pi.prole.org..."
|
||||||
|
docker save myrddin.prole.org:5000/knoe-db:18-140 \
|
||||||
|
| ssh -o StrictHostKeyChecking=no -o BatchMode=yes \
|
||||||
|
-o ServerAliveInterval=30 -o ServerAliveCountMax=20 \
|
||||||
|
-i ~/.ssh/id_ed25519_ansible ansible@pi.prole.org \
|
||||||
|
"sudo k3s ctr images import -" 2>&1 | tail -5
|
||||||
|
echo "Done importing to pi."
|
||||||
|
kubectl get jobs,pods -n prole-db -o wide 2>/dev/null | grep -v "Completed\|initdb"
|
||||||
8
_monitor_run.sh
Normal file
8
_monitor_run.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
for i in $(seq 1 90); do
|
||||||
|
sleep 10
|
||||||
|
if ! pgrep -f "prole.sh.*service/prole.cfg" >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
tail -60 /tmp/prole_run.log
|
||||||
9
_patch_cluster.sh
Normal file
9
_patch_cluster.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
cp k8s/prole/prole-db.yaml deploy/opentofu/k3s/manifests/prole/prole-db.yaml
|
||||||
|
echo "Mirrored prole-db.yaml to opentofu"
|
||||||
|
kubectl patch cluster prole-db -n prole-db --type=merge -p \
|
||||||
|
'{"spec":{"imageName":"myrddin.prole.org:5000/knoe-db:18-140","affinity":{"podAntiAffinityType":"preferred","nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"node.kubernetes.io/instance-type","operator":"In","values":["k3s"]}]}]}}}}}'
|
||||||
|
echo "Patched live cluster"
|
||||||
|
sleep 5
|
||||||
|
kubectl get pods -n prole-db -o wide
|
||||||
80
_prebind_pvcs.sh
Normal file
80
_prebind_pvcs.sh
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Pre-bind CNPG PVCs to specific Synology iSCSI PVs so CNPG schedules replicas
|
||||||
|
# on the correct nodes (merlin=d002, pi=d003) rather than defaulting to myrddin.
|
||||||
|
set -euo pipefail
|
||||||
|
NS=prole-db
|
||||||
|
|
||||||
|
# Delete any pending (unbound) PVCs for replicas 2 and 3
|
||||||
|
for pvc in prole-db-2 prole-db-2-wal prole-db-3 prole-db-3-wal; do
|
||||||
|
phase=$(kubectl get pvc "$pvc" -n "$NS" -o jsonpath='{.status.phase}' 2>/dev/null || true)
|
||||||
|
if [[ "$phase" == "Pending" || -z "$phase" ]]; then
|
||||||
|
kubectl delete pvc "$pvc" -n "$NS" --ignore-not-found
|
||||||
|
echo "Deleted pending PVC: $pvc"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Pre-bind replica-2 PVCs → synology-iscsi-d002 on merlin.prole.org
|
||||||
|
kubectl apply -f - <<'YAML'
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-2
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 29Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-2-wal
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 29Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-wal
|
||||||
|
YAML
|
||||||
|
|
||||||
|
# Pre-bind replica-3 PVCs → synology-iscsi-d003 on pi.prole.org
|
||||||
|
kubectl apply -f - <<'YAML'
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-3
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 29Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d003-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-3-wal
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 29Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d003-wal
|
||||||
|
YAML
|
||||||
|
|
||||||
|
echo "Waiting for PVCs to bind..."
|
||||||
|
sleep 5
|
||||||
|
kubectl get pvc -n "$NS"
|
||||||
|
|
||||||
|
# Delete the stuck pod so CNPG recreates it with correct affinity
|
||||||
|
kubectl delete pod -n "$NS" -l cnpg.io/instanceName=prole-db-2 --ignore-not-found
|
||||||
|
echo "Done — CNPG will recreate replica-2 pod targeting merlin.prole.org"
|
||||||
56
_rebind_d002.sh
Normal file
56
_rebind_d002.sh
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
NS=prole-db
|
||||||
|
|
||||||
|
# Release d002 PVs by deleting old prole-db-2 PVCs
|
||||||
|
kubectl delete pvc prole-db-2 prole-db-2-wal -n "$NS" --ignore-not-found
|
||||||
|
echo "Deleted prole-db-2 PVCs"
|
||||||
|
|
||||||
|
# Wait for PVs to become Available again
|
||||||
|
for pv in synology-iscsi-d002-data synology-iscsi-d002-wal; do
|
||||||
|
for i in $(seq 1 20); do
|
||||||
|
phase=$(kubectl get pv "$pv" -o jsonpath='{.status.phase}' 2>/dev/null || echo "")
|
||||||
|
if [[ "$phase" == "Available" ]]; then
|
||||||
|
echo " PV $pv is Available"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Pre-bind prole-db-4 PVCs to d002 PVs on merlin
|
||||||
|
kubectl apply -f - <<'YAML'
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-4
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 29Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-4-wal
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 29Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-wal
|
||||||
|
YAML
|
||||||
|
echo "Created prole-db-4 PVCs pre-bound to d002 (merlin)"
|
||||||
|
|
||||||
|
# Delete the stuck prole-db-4-join Job so CNPG recreates it reading the new PVCs
|
||||||
|
kubectl delete job -n "$NS" -l cnpg.io/instanceName=prole-db-4 --ignore-not-found
|
||||||
|
echo "Deleted prole-db-4-join Job — CNPG will recreate targeting merlin"
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
kubectl get pvc,pods -n "$NS" | grep -v "Completed\|initdb"
|
||||||
50
_rebind_d002b.sh
Normal file
50
_rebind_d002b.sh
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
NS=prole-db
|
||||||
|
|
||||||
|
# Delete the job first, then the PVCs CNPG created with wrong volumeName
|
||||||
|
kubectl delete job -n "$NS" -l cnpg.io/instanceName=prole-db-4 --ignore-not-found
|
||||||
|
kubectl delete pvc prole-db-4 prole-db-4-wal -n "$NS" --ignore-not-found
|
||||||
|
echo "Deleted prole-db-4 job and PVCs"
|
||||||
|
|
||||||
|
# Wait for d002 PVs to become Available
|
||||||
|
for pv in synology-iscsi-d002-data synology-iscsi-d002-wal; do
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
phase=$(kubectl get pv "$pv" -o jsonpath='{.status.phase}' 2>/dev/null || echo "")
|
||||||
|
echo " $pv: $phase"
|
||||||
|
if [[ "$phase" == "Available" ]]; then break; fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Pre-bind with 1Gi (matching CNPG cluster spec size)
|
||||||
|
kubectl create -f - <<'YAML'
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-4
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prole-db-4-wal
|
||||||
|
namespace: prole-db
|
||||||
|
spec:
|
||||||
|
accessModes: [ReadWriteOnce]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: synology-iscsi
|
||||||
|
volumeName: synology-iscsi-d002-wal
|
||||||
|
YAML
|
||||||
|
echo "Created prole-db-4 PVCs pre-bound to d002 (merlin)"
|
||||||
|
sleep 8
|
||||||
|
kubectl get pvc -n "$NS"
|
||||||
13
conf/database_versions.json
Normal file
13
conf/database_versions.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"postgresql": {
|
||||||
|
"stable": "16",
|
||||||
|
"current": "17",
|
||||||
|
"latest": "18"
|
||||||
|
},
|
||||||
|
"percona": {
|
||||||
|
"stable": "16",
|
||||||
|
"current": "17",
|
||||||
|
"latest": "18",
|
||||||
|
"v18": "18"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
; Prole Master Configuration File
|
; Prole Master Configuration File
|
||||||
; Generated by install.py on 2026-03-22 05:28:56
|
; Generated by install.py on 2026-03-22 21:34:24
|
||||||
; This file is used as input for Ansible deployment and k8s cluster creation.
|
; This file is used as input for Ansible deployment and k8s cluster creation.
|
||||||
|
|
||||||
[User]
|
[User]
|
||||||
@ -36,7 +36,7 @@ dependencies.opentofu.install = true
|
|||||||
dependencies.python.install = true
|
dependencies.python.install = true
|
||||||
dependencies.verify_all = false
|
dependencies.verify_all = false
|
||||||
disk_selection.disk_type = local
|
disk_selection.disk_type = local
|
||||||
disk_selection.local_path = /Users/chrisfu
|
disk_selection.local_path = /Users/chrisfu/dev/prole/prole-tools-app/dist
|
||||||
disk_selection.removable_mount =
|
disk_selection.removable_mount =
|
||||||
env_setup.NAMESPACE = ${NAMESPACE}
|
env_setup.NAMESPACE = ${NAMESPACE}
|
||||||
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||||
@ -49,9 +49,9 @@ init_cluster.at_rest_encryption_enabled = true
|
|||||||
init_cluster.cluster_env = dev
|
init_cluster.cluster_env = dev
|
||||||
init_cluster.deployment_target = prole-dev-cluster
|
init_cluster.deployment_target = prole-dev-cluster
|
||||||
init_cluster.gitops_enabled = false
|
init_cluster.gitops_enabled = false
|
||||||
init_cluster.k3s_server_url =
|
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
||||||
init_cluster.k3s_token =
|
init_cluster.k3s_token = ${PROLE_SECRET:v1:zaODrWdgRwk4Mn5f:5l3tyJapMmolvCe1YR8LpyfZZm_E4mApbEDdTwYdbIZ_hotg6TV6e19P60a8JAV_3CIKqgNBhGJ4wp_LY3o-5P-BJS8zs118bcPi3doRYItAQfRI9mPp0myMtKRb01xO7iWMY__t9M09m_tPsKd3LN_sobbpNNQRwxeY2w==}
|
||||||
init_cluster.kerberos_enabled = false
|
init_cluster.kerberos_enabled = true
|
||||||
init_cluster.mode = k3d
|
init_cluster.mode = k3d
|
||||||
init_cluster.start_cluster = true
|
init_cluster.start_cluster = true
|
||||||
init_cluster.supabase_enabled = false
|
init_cluster.supabase_enabled = false
|
||||||
@ -60,35 +60,35 @@ init_cnpg_deploy.run_deploy = true
|
|||||||
init_db_build.run_build = true
|
init_db_build.run_build = true
|
||||||
init_password.db_host_port = 5432
|
init_password.db_host_port = 5432
|
||||||
init_password.db_namespace = ${NAMESPACE}
|
init_password.db_namespace = ${NAMESPACE}
|
||||||
init_password.db_password = ${PROLE_SECRET:v1:Ug4MMDdbizuLhRxp:7_zShAVRIyTwzI230RPi0DZkaYyec25z}
|
init_password.db_password = ${PROLE_SECRET:v1:vb6MFP3JQ8ZA-kCH:P09DQs-Tf_unwlEZGjQiQug9imzKxk7z}
|
||||||
init_password.db_password_confirm = ${PROLE_SECRET:v1:Ug4MMDdbizuLhRxp:7_zShAVRIyTwzI230RPi0DZkaYyec25z}
|
init_password.db_password_confirm = ${PROLE_SECRET:v1:vb6MFP3JQ8ZA-kCH:P09DQs-Tf_unwlEZGjQiQug9imzKxk7z}
|
||||||
init_password.db_username = root
|
init_password.db_username = root
|
||||||
init_password.generate_ssh_key = true
|
init_password.generate_ssh_key = true
|
||||||
init_scripts.run_scripts = true
|
init_scripts.run_scripts = true
|
||||||
kerberos_config.enabled = false
|
kerberos_config.enabled = true
|
||||||
kerberos_config.kdc =
|
kerberos_config.kdc = 10.0.0.3
|
||||||
kerberos_config.password = ${PROLE_SECRET:v1:HY4WS78rVJaooM8W:JXfyvQkXR-Pg3Hg5FCItCMNfTIsXlW_mNDTEHElowhJ9zv2z}
|
kerberos_config.password = ${PROLE_SECRET:v1:vYQE4jE-zNwvWosG:LB5ajSn0j84cLnbtg6x8o-jjIwdZh5ELNW1h1pp012xDcy7R}
|
||||||
kerberos_config.realm =
|
kerberos_config.realm = PROLE.ORG
|
||||||
kerberos_config.test_connection = false
|
kerberos_config.test_connection = false
|
||||||
kerberos_config.user = administrator
|
kerberos_config.user = administrator
|
||||||
network_scan.run = true
|
network_scan.run = true
|
||||||
ollama_config.model =
|
ollama_config.model =
|
||||||
ollama_config.server_host =
|
ollama_config.server_host = fairyland.prole.org
|
||||||
ollama_config.server_port = 11434
|
ollama_config.server_port = 11434
|
||||||
|
|
||||||
[Global]
|
[Global]
|
||||||
; Variables used by name in more than one place or assumed global scope
|
; Variables used by name in more than one place or assumed global scope
|
||||||
CLUSTER_ENV = dev
|
CLUSTER_ENV = dev
|
||||||
DB_HOST_PORT = 5432
|
DB_HOST_PORT = 5432
|
||||||
DB_PASSWORD = ${PROLE_SECRET:v1:UfmNthRE-DSKbvW2:F64wGEHyh2iCF0MbYgKOUU_y4PQnzMhk}
|
DB_PASSWORD = ${PROLE_SECRET:v1:RdWFdqimNbYIof7M:rIB4trg7FLDfUWzYoXLFsU-1BUywEDE4}
|
||||||
DEPLOYMENT_MODE = k3d
|
DEPLOYMENT_MODE = k3d
|
||||||
DEPLOYMENT_TARGET = prole-dev-cluster
|
DEPLOYMENT_TARGET = prole-dev-cluster
|
||||||
DOCKER_PRELOAD = false
|
DOCKER_PRELOAD = false
|
||||||
NAMESPACE = knoe-db
|
NAMESPACE = knoe-db
|
||||||
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
||||||
PROLE_DB_USER = root
|
PROLE_DB_USER = root
|
||||||
PROLE_K3S_SERVER =
|
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
||||||
PROLE_K3S_TOKEN =
|
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:zaODrWdgRwk4Mn5f:5l3tyJapMmolvCe1YR8LpyfZZm_E4mApbEDdTwYdbIZ_hotg6TV6e19P60a8JAV_3CIKqgNBhGJ4wp_LY3o-5P-BJS8zs118bcPi3doRYItAQfRI9mPp0myMtKRb01xO7iWMY__t9M09m_tPsKd3LN_sobbpNNQRwxeY2w==}
|
||||||
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
||||||
SERVICE_NAMESPACE = knoe-system
|
SERVICE_NAMESPACE = knoe-system
|
||||||
|
|
||||||
@ -107,12 +107,18 @@ ANSIBLE_INVENTORY = /Users/chrisfu/dev/prole/infrastructure/inventory
|
|||||||
ANSIBLE_REALM = PROLE.ORG
|
ANSIBLE_REALM = PROLE.ORG
|
||||||
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","merlin.prole.org":"10.0.0.6","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["pi.prole.org","merlin.prole.org"],"k3s_hosts:children":["k3s_servers","k3s_agents"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"ssl_hosts":["myrddin.prole.org"],"mariadb_primary":["merlin.prole.org"],"mariadb_replica":["raspberry.prole.org"],"mariadb:children":["mariadb_primary","mariadb_replica"],"merlin_bootstrap":["merlin"]},"hosts":{"merlin":"10.0.0.6","merlin.prole.org":"10.0.0.6","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":["k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
|
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","merlin.prole.org":"10.0.0.6","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["pi.prole.org","merlin.prole.org"],"k3s_hosts:children":["k3s_servers","k3s_agents"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"ssl_hosts":["myrddin.prole.org"],"mariadb_primary":["merlin.prole.org"],"mariadb_replica":["raspberry.prole.org"],"mariadb:children":["mariadb_primary","mariadb_replica"],"merlin_bootstrap":["merlin"]},"hosts":{"merlin":"10.0.0.6","merlin.prole.org":"10.0.0.6","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":["k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
|
||||||
KDC_ANSIBLE_DETECTED = 10.0.0.3
|
KDC_ANSIBLE_DETECTED = 10.0.0.3
|
||||||
|
KDC_AUTO_DETECTED = 10.0.0.3
|
||||||
|
KERBEROS_AUTO_ENABLED = True
|
||||||
|
|
||||||
[Port Forwards]
|
[Port Forwards]
|
||||||
; No configuration values captured yet for this section.
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
[System Environment]
|
[System Environment]
|
||||||
; No configuration values captured yet for this section.
|
PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||||
|
PROLE_DATA = /Users/chrisfu/dev/prole/data
|
||||||
|
PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
||||||
|
PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
||||||
|
|
||||||
[Monitoring]
|
[Monitoring]
|
||||||
; No configuration values captured yet for this section.
|
; No configuration values captured yet for this section.
|
||||||
@ -121,10 +127,16 @@ KDC_ANSIBLE_DETECTED = 10.0.0.3
|
|||||||
; No configuration values captured yet for this section.
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
[Ollama]
|
[Ollama]
|
||||||
; No configuration values captured yet for this section.
|
OLLAMA_HOST = http://fairyland.prole.org:11434
|
||||||
|
OLLAMA_SERVERS = fairyland.prole.org:11434,k3d.localhost:11434,morgoth.prole.org:11434
|
||||||
|
OLLAMA_SERVER_HOST = fairyland.prole.org
|
||||||
|
OLLAMA_SERVER_PORT = 11434
|
||||||
|
|
||||||
[Optional Features]
|
[Optional Features]
|
||||||
|
AT_REST_ENCRYPTION_ENABLED = True
|
||||||
GITOPS_ENABLED = False
|
GITOPS_ENABLED = False
|
||||||
|
KERBEROS_ENABLED = True
|
||||||
|
SUPABASE_ENABLED = False
|
||||||
|
|
||||||
[GitOps]
|
[GitOps]
|
||||||
; No configuration values captured yet for this section.
|
; No configuration values captured yet for this section.
|
||||||
@ -133,7 +145,9 @@ GITOPS_ENABLED = False
|
|||||||
; No configuration values captured yet for this section.
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
[Initialize Cluster]
|
[Initialize Cluster]
|
||||||
; No configuration values captured yet for this section.
|
ENVIRONMENT = dev
|
||||||
|
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||||
|
K3S_TOKEN = ${PROLE_SECRET:v1:zaODrWdgRwk4Mn5f:5l3tyJapMmolvCe1YR8LpyfZZm_E4mApbEDdTwYdbIZ_hotg6TV6e19P60a8JAV_3CIKqgNBhGJ4wp_LY3o-5P-BJS8zs118bcPi3doRYItAQfRI9mPp0myMtKRb01xO7iWMY__t9M09m_tPsKd3LN_sobbpNNQRwxeY2w==}
|
||||||
|
|
||||||
[Dev Cluster (k3d)]
|
[Dev Cluster (k3d)]
|
||||||
CLUSTER_ENV = dev
|
CLUSTER_ENV = dev
|
||||||
@ -144,20 +158,21 @@ MODE = k3d
|
|||||||
[Service Cluster (k3s)]
|
[Service Cluster (k3s)]
|
||||||
CLUSTER_ENV = prole-service-cluster
|
CLUSTER_ENV = prole-service-cluster
|
||||||
DISPLAY_NAME = prole-service-cluster
|
DISPLAY_NAME = prole-service-cluster
|
||||||
K3S_SERVER_URL =
|
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||||
K3S_TOKEN =
|
K3S_TOKEN = ${PROLE_SECRET:v1:zaODrWdgRwk4Mn5f:5l3tyJapMmolvCe1YR8LpyfZZm_E4mApbEDdTwYdbIZ_hotg6TV6e19P60a8JAV_3CIKqgNBhGJ4wp_LY3o-5P-BJS8zs118bcPi3doRYItAQfRI9mPp0myMtKRb01xO7iWMY__t9M09m_tPsKd3LN_sobbpNNQRwxeY2w==}
|
||||||
MODE = k3s
|
MODE = k3s
|
||||||
PIPELINE_URL = http://127.0.0.1:8080
|
PIPELINE_URL = http://127.0.0.1:8080
|
||||||
|
|
||||||
[Prod Cluster (k8s)]
|
[Prod Cluster (k8s)]
|
||||||
ARTIFACTS_DIR = /private/var/folders/rt/pywlnmxj3dn7t5552vwdcpp80000gn/T/pytest-of-chrisfu/pytest-54/test_encryption_toggle0/data/staging
|
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
|
||||||
CLUSTER_ENV = prole-prod-cluster
|
CLUSTER_ENV = prole-prod-cluster
|
||||||
DISPLAY_NAME = prole-prod-cluster
|
DISPLAY_NAME = prole-prod-cluster
|
||||||
MODE = k8s
|
MODE = k8s
|
||||||
PIPELINE_URL = http://127.0.0.1:8080
|
PIPELINE_URL = http://127.0.0.1:8080
|
||||||
|
|
||||||
[Docker Build]
|
[Docker Build]
|
||||||
; No configuration values captured yet for this section.
|
LOCAL_REGISTRY = localhost:5000
|
||||||
|
LOCAL_REGISTRY_INTERNAL = k3d-prole-registry.localhost:5000
|
||||||
|
|
||||||
[Initialization Scripts]
|
[Initialization Scripts]
|
||||||
; No configuration values captured yet for this section.
|
; No configuration values captured yet for this section.
|
||||||
|
|||||||
@ -1,180 +0,0 @@
|
|||||||
; Prole Master Configuration File
|
|
||||||
; Generated by install.py on 2026-03-21 13:37:28
|
|
||||||
; This file is used as input for Ansible deployment and k8s cluster creation.
|
|
||||||
|
|
||||||
[User]
|
|
||||||
; User-editable values; derived values below reference these by default.
|
|
||||||
; No user values captured yet for this section.
|
|
||||||
|
|
||||||
[Inputs]
|
|
||||||
; Screen-scoped inputs used for unattended replays (-S)
|
|
||||||
build.deploy_env = Dev
|
|
||||||
build.run_build = false
|
|
||||||
database_options.distribution = percona
|
|
||||||
database_options.ext.dblink = true
|
|
||||||
database_options.ext.pg_buffercache = true
|
|
||||||
database_options.ext.pg_freespacemap = true
|
|
||||||
database_options.ext.pg_repack = true
|
|
||||||
database_options.ext.pg_stat_monitor = true
|
|
||||||
database_options.ext.pg_stat_statements = true
|
|
||||||
database_options.ext.pgaudit = true
|
|
||||||
database_options.ext.pgbadger = true
|
|
||||||
database_options.ext.pgcrypto = true
|
|
||||||
database_options.ext.pgrowlocks = true
|
|
||||||
database_options.ext.pgvector = true
|
|
||||||
database_options.ext.postgis = true
|
|
||||||
database_options.ext.postgres_fdw = true
|
|
||||||
database_options.version_type = v18
|
|
||||||
dependencies.ansible.install = true
|
|
||||||
dependencies.auto_install_missing = true
|
|
||||||
dependencies.brew.install = true
|
|
||||||
dependencies.docker.install = true
|
|
||||||
dependencies.k3d.install = true
|
|
||||||
dependencies.kubectl.install = true
|
|
||||||
dependencies.kubectx.install = true
|
|
||||||
dependencies.opentofu.install = true
|
|
||||||
dependencies.python.install = true
|
|
||||||
dependencies.verify_all = false
|
|
||||||
disk_selection.disk_type = local
|
|
||||||
disk_selection.local_path = /Users/chrisfu/dev/prole/prole-tools-app/dist
|
|
||||||
disk_selection.removable_mount =
|
|
||||||
env_setup.NAMESPACE = ${NAMESPACE}
|
|
||||||
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
|
||||||
env_setup.PROLE_DATA = /Users/chrisfu/dev/prole/data
|
|
||||||
env_setup.PROLE_HOME = /Users/chrisfu/dev/prole
|
|
||||||
env_setup.PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
|
||||||
env_setup.PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
|
||||||
init_cluster.argocd_enabled = false
|
|
||||||
init_cluster.at_rest_encryption_enabled = true
|
|
||||||
init_cluster.cluster_env = service
|
|
||||||
init_cluster.deployment_target = prole-service-cluster
|
|
||||||
init_cluster.gitops_enabled = false
|
|
||||||
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
|
||||||
init_cluster.k3s_token = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
|
||||||
init_cluster.kerberos_enabled = true
|
|
||||||
init_cluster.mode = k3s
|
|
||||||
init_cluster.start_cluster = true
|
|
||||||
init_cluster.supabase_enabled = false
|
|
||||||
init_cnpg_deploy.force_rollout = false
|
|
||||||
init_cnpg_deploy.run_deploy = true
|
|
||||||
init_db_build.run_build = true
|
|
||||||
init_password.db_host_port = 5432
|
|
||||||
init_password.db_namespace = ${NAMESPACE}
|
|
||||||
init_password.db_password =
|
|
||||||
init_password.db_password_confirm =
|
|
||||||
init_password.db_username = root
|
|
||||||
init_password.generate_ssh_key = true
|
|
||||||
init_scripts.run_scripts = true
|
|
||||||
kerberos_config.enabled = true
|
|
||||||
kerberos_config.kdc = 10.0.0.3
|
|
||||||
kerberos_config.password = ${PROLE_SECRET:v1:71ROfYyYysQDJDpX:0K4cB3p9nnMb1yi2OImqUm-pa9Zg21JYTmYHzYB_7czTKMQJ}
|
|
||||||
kerberos_config.realm = PROLE.ORG
|
|
||||||
kerberos_config.test_connection = false
|
|
||||||
kerberos_config.user = administrator
|
|
||||||
network_scan.run = true
|
|
||||||
ollama_config.model =
|
|
||||||
ollama_config.server_host = fairyland.prole.org
|
|
||||||
ollama_config.server_port = 11434
|
|
||||||
|
|
||||||
[Global]
|
|
||||||
; Variables used by name in more than one place or assumed global scope
|
|
||||||
CLUSTER_ENV = service
|
|
||||||
DB_HOST_PORT = 5432
|
|
||||||
DB_PASSWORD =
|
|
||||||
DEPLOYMENT_MODE = k3s
|
|
||||||
DEPLOYMENT_TARGET = prole-service-cluster
|
|
||||||
DOCKER_PRELOAD = false
|
|
||||||
NAMESPACE = prole-db
|
|
||||||
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
|
||||||
PROLE_DB_USER = root
|
|
||||||
PROLE_HOME = $HOME/dev/prole
|
|
||||||
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
|
||||||
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
|
||||||
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
|
||||||
SERVICE_NAMESPACE = knoe-system
|
|
||||||
|
|
||||||
[Welcome]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Dependencies]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Network]
|
|
||||||
AD_DC_HOST = myrddin.prole.org
|
|
||||||
AD_DC_IP = 10.0.0.3
|
|
||||||
ANSIBLE_DOMAIN = prole.org
|
|
||||||
ANSIBLE_INFRASTRUCTURE = /Users/chrisfu/dev/prole/infrastructure
|
|
||||||
ANSIBLE_INVENTORY = /Users/chrisfu/dev/prole/infrastructure/inventory
|
|
||||||
ANSIBLE_REALM = PROLE.ORG
|
|
||||||
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","merlin.prole.org":"10.0.0.6","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["pi.prole.org","merlin.prole.org"],"k3s_hosts:children":["k3s_servers","k3s_agents"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"ssl_hosts":["myrddin.prole.org"],"mariadb_primary":["merlin.prole.org"],"mariadb_replica":["raspberry.prole.org"],"mariadb:children":["mariadb_primary","mariadb_replica"],"merlin_bootstrap":["merlin"]},"hosts":{"merlin":"10.0.0.6","merlin.prole.org":"10.0.0.6","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":["k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
|
|
||||||
KDC_ANSIBLE_DETECTED = 10.0.0.3
|
|
||||||
KDC_AUTO_DETECTED = 10.0.0.3
|
|
||||||
KERBEROS_AUTO_ENABLED = True
|
|
||||||
|
|
||||||
[Port Forwards]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[System Environment]
|
|
||||||
PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
|
||||||
PROLE_DATA = /Users/chrisfu/dev/prole/data
|
|
||||||
PROLE_HOME = /Users/chrisfu/dev/prole
|
|
||||||
PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
|
||||||
PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
|
||||||
|
|
||||||
[Monitoring]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Kerberos Authentication]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Ollama]
|
|
||||||
OLLAMA_HOST = http://fairyland.prole.org:11434
|
|
||||||
OLLAMA_SERVERS = fairyland.prole.org:11434,k3d.localhost:11434,morgoth.prole.org:11434
|
|
||||||
OLLAMA_SERVER_HOST = fairyland.prole.org
|
|
||||||
OLLAMA_SERVER_PORT = 11434
|
|
||||||
|
|
||||||
[Optional Features]
|
|
||||||
GITOPS_ENABLED = False
|
|
||||||
|
|
||||||
[GitOps]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Database Creation]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Initialize Cluster]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Dev Cluster (k3d)]
|
|
||||||
CLUSTER_ENV = dev
|
|
||||||
DISPLAY_NAME = knoe-dev-cluster
|
|
||||||
KUBECTL_CONTEXT =
|
|
||||||
MODE = k3d
|
|
||||||
|
|
||||||
[Service Cluster (k3s)]
|
|
||||||
CLUSTER_ENV = prole-service-cluster
|
|
||||||
DISPLAY_NAME = prole-service-cluster
|
|
||||||
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
|
||||||
K3S_TOKEN = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
|
||||||
MODE = k3s
|
|
||||||
PIPELINE_URL = http://127.0.0.1:8080
|
|
||||||
|
|
||||||
[Prod Cluster (k8s)]
|
|
||||||
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
|
|
||||||
CLUSTER_ENV = prole-prod-cluster
|
|
||||||
DISPLAY_NAME = prole-prod-cluster
|
|
||||||
MODE = k8s
|
|
||||||
PIPELINE_URL = http://127.0.0.1:8080
|
|
||||||
|
|
||||||
[Docker Build]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Initialization Scripts]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
|
|
||||||
[Deployment]
|
|
||||||
MODE = k3s
|
|
||||||
TARGET = prole-service-cluster
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
; No configuration values captured yet for this section.
|
|
||||||
1
conf/service/prole.cfg
Symbolic link
1
conf/service/prole.cfg
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
service/prole.cfg
|
||||||
195
conf/service/prole.cfg.legacy.1774223813
Normal file
195
conf/service/prole.cfg.legacy.1774223813
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
; Prole Master Configuration File
|
||||||
|
; Generated by install.py on 2026-03-22 16:46:41
|
||||||
|
; This file is used as input for Ansible deployment and k8s cluster creation.
|
||||||
|
|
||||||
|
[User]
|
||||||
|
; User-editable values; derived values below reference these by default.
|
||||||
|
; No user values captured yet for this section.
|
||||||
|
|
||||||
|
[Inputs]
|
||||||
|
; Screen-scoped inputs used for unattended replays (-S)
|
||||||
|
build.deploy_env = Dev
|
||||||
|
build.run_build = false
|
||||||
|
database_options.distribution = percona
|
||||||
|
database_options.ext.dblink = true
|
||||||
|
database_options.ext.pg_buffercache = true
|
||||||
|
database_options.ext.pg_freespacemap = true
|
||||||
|
database_options.ext.pg_repack = true
|
||||||
|
database_options.ext.pg_stat_monitor = true
|
||||||
|
database_options.ext.pg_stat_statements = true
|
||||||
|
database_options.ext.pgaudit = true
|
||||||
|
database_options.ext.pgbadger = true
|
||||||
|
database_options.ext.pgcrypto = true
|
||||||
|
database_options.ext.pgrowlocks = true
|
||||||
|
database_options.ext.pgvector = true
|
||||||
|
database_options.ext.postgis = true
|
||||||
|
database_options.ext.postgres_fdw = true
|
||||||
|
database_options.version_type = v18
|
||||||
|
dependencies.ansible.install = true
|
||||||
|
dependencies.auto_install_missing = true
|
||||||
|
dependencies.brew.install = true
|
||||||
|
dependencies.docker.install = true
|
||||||
|
dependencies.k3d.install = true
|
||||||
|
dependencies.kubectl.install = true
|
||||||
|
dependencies.kubectx.install = true
|
||||||
|
dependencies.opentofu.install = true
|
||||||
|
dependencies.python.install = true
|
||||||
|
dependencies.verify_all = false
|
||||||
|
disk_selection.disk_type = local
|
||||||
|
disk_selection.local_path = /Users/chrisfu/dev/prole/prole-tools-app/dist
|
||||||
|
disk_selection.removable_mount =
|
||||||
|
env_setup.NAMESPACE = ${NAMESPACE}
|
||||||
|
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||||
|
env_setup.PROLE_DATA = /Users/chrisfu/dev/prole/data
|
||||||
|
env_setup.PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
env_setup.PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
||||||
|
env_setup.PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
||||||
|
init_cluster.argocd_enabled = false
|
||||||
|
init_cluster.at_rest_encryption_enabled = true
|
||||||
|
init_cluster.cluster_env = service
|
||||||
|
init_cluster.deployment_target = prole-service-cluster
|
||||||
|
init_cluster.gitops_enabled = false
|
||||||
|
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
||||||
|
init_cluster.k3s_token = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
||||||
|
init_cluster.kerberos_enabled = true
|
||||||
|
init_cluster.mode = k3s
|
||||||
|
init_cluster.start_cluster = true
|
||||||
|
init_cluster.supabase_enabled = false
|
||||||
|
init_cnpg_deploy.force_rollout = false
|
||||||
|
init_cnpg_deploy.run_deploy = true
|
||||||
|
init_db_build.run_build = true
|
||||||
|
init_password.db_host_port = 5432
|
||||||
|
init_password.db_namespace = ${NAMESPACE}
|
||||||
|
init_password.db_password = ${PROLE_SECRET:v1:LtY6hRqgZOeWP8OX:wWt4cT0CS2c4GZPB1RpSAo9cIFhLYvhw}
|
||||||
|
init_password.db_password_confirm = ${PROLE_SECRET:v1:LtY6hRqgZOeWP8OX:wWt4cT0CS2c4GZPB1RpSAo9cIFhLYvhw}
|
||||||
|
init_password.db_username = root
|
||||||
|
init_password.generate_ssh_key = true
|
||||||
|
init_scripts.run_scripts = true
|
||||||
|
kerberos_config.enabled = true
|
||||||
|
kerberos_config.init_authority = false
|
||||||
|
kerberos_config.kdc = 10.0.0.3
|
||||||
|
kerberos_config.password = ${PROLE_SECRET:v1:71ROfYyYysQDJDpX:0K4cB3p9nnMb1yi2OImqUm-pa9Zg21JYTmYHzYB_7czTKMQJ}
|
||||||
|
kerberos_config.realm = PROLE.ORG
|
||||||
|
kerberos_config.test_connection = false
|
||||||
|
kerberos_config.user = administrator
|
||||||
|
network_scan.run = true
|
||||||
|
ollama_config.model =
|
||||||
|
ollama_config.server_host = fairyland.prole.org
|
||||||
|
ollama_config.server_port = 11434
|
||||||
|
|
||||||
|
[Global]
|
||||||
|
; Variables used by name in more than one place or assumed global scope
|
||||||
|
ARGOCD_NAMESPACE = argocd
|
||||||
|
CLUSTER_ENV = service
|
||||||
|
DB_HOST_PORT = 5432
|
||||||
|
DB_PASSWORD = ${PROLE_SECRET:v1:NmgNZUhCsk-p0_DF:VB1tKREj45eEWcnN1GAlcGV6b_Lrl9sx}
|
||||||
|
DEPLOYMENT_MODE = k3s
|
||||||
|
DEPLOYMENT_TARGET = prole-service-cluster
|
||||||
|
DOCKER_IMPORT_DIR =
|
||||||
|
DOCKER_PRELOAD = false
|
||||||
|
NAMESPACE = prole-db
|
||||||
|
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
||||||
|
PROLE_DB_USER = root
|
||||||
|
PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
||||||
|
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
||||||
|
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
||||||
|
REGISTRY_NAMESPACE = knoe-system
|
||||||
|
SERVICE_NAMESPACE = knoe-system
|
||||||
|
|
||||||
|
[Welcome]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Dependencies]
|
||||||
|
STATUS = All installed
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
AD_DC_HOST = myrddin.prole.org
|
||||||
|
AD_DC_IP = 10.0.0.3
|
||||||
|
ANSIBLE_DOMAIN = prole.org
|
||||||
|
ANSIBLE_INFRASTRUCTURE = /Users/chrisfu/dev/prole/infrastructure
|
||||||
|
ANSIBLE_INVENTORY = /Users/chrisfu/dev/prole/infrastructure/inventory
|
||||||
|
ANSIBLE_REALM = PROLE.ORG
|
||||||
|
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","merlin.prole.org":"10.0.0.6","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["pi.prole.org","merlin.prole.org"],"k3s_hosts:children":["k3s_servers","k3s_agents"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"ssl_hosts":["myrddin.prole.org"],"mariadb_primary":["merlin.prole.org"],"mariadb_replica":["raspberry.prole.org"],"mariadb:children":["mariadb_primary","mariadb_replica"],"merlin_bootstrap":["merlin"]},"hosts":{"merlin":"10.0.0.6","merlin.prole.org":"10.0.0.6","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":["k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
|
||||||
|
KDC_ANSIBLE_DETECTED = 10.0.0.3
|
||||||
|
KDC_AUTO_DETECTED = 10.0.0.3
|
||||||
|
KERBEROS_AUTO_ENABLED = True
|
||||||
|
|
||||||
|
[Port Forwards]
|
||||||
|
PORT_FORWARD_K3S_MAPPING_1 = id=argocd;namespace=argocd;target=svc/argocd-server;address=0.0.0.0;hostPort=8081;servicePort=80;protocol=TCP;description=ArgoCD
|
||||||
|
PORT_FORWARD_K3S_MAPPING_2 = id=garage;namespace=knoe-system;target=svc/garage;address=0.0.0.0;hostPort=3900;servicePort=3900;protocol=TCP;description=Garage S3
|
||||||
|
PORT_FORWARD_K3S_MAPPING_3 = id=openbao;namespace=knoe-system;target=svc/openbao;address=0.0.0.0;hostPort=8200;servicePort=8200;protocol=TCP;description=OpenBao
|
||||||
|
PORT_FORWARD_K3S_MAPPING_4 = id=opentofu;namespace=knoe-system;target=svc/opentofu;address=0.0.0.0;hostPort=8080;servicePort=8080;protocol=TCP;description=OpenTofu
|
||||||
|
PORT_FORWARD_K3S_MAPPING_5 = id=dashboard;namespace=kubernetes-dashboard;target=svc/kubernetes-dashboard-kong-proxy;address=127.0.0.1;hostPort=8443;servicePort=443;protocol=TCP;description=Kubernetes Dashboard
|
||||||
|
PORT_FORWARD_K3S_MAPPING_6 = id=postgres;namespace=${NAMESPACE};target=svc/prole-db-rw;address=0.0.0.0;hostPort=5432;servicePort=5432;protocol=TCP;description=PostgreSQL (primary)
|
||||||
|
PORT_FORWARD_K3S_MAPPING_7 = id=prometheus;namespace=monitoring;target=svc/kps-kube-prometheus-stack-prometheus;address=127.0.0.1;hostPort=9090;servicePort=9090;protocol=TCP;description=Prometheus UI
|
||||||
|
PORT_FORWARD_K3S_MAPPING_8 = id=grafana;namespace=monitoring;target=svc/kps-grafana;address=0.0.0.0;hostPort=3000;servicePort=80;protocol=TCP;description=Grafana UI
|
||||||
|
|
||||||
|
[System Environment]
|
||||||
|
NAMESPACE = prole-db
|
||||||
|
PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||||
|
PROLE_DATA = /Users/chrisfu/dev/prole/data
|
||||||
|
PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
||||||
|
PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
||||||
|
|
||||||
|
[Monitoring]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Kerberos Authentication]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Ollama]
|
||||||
|
OLLAMA_HOST = http://fairyland.prole.org:11434
|
||||||
|
OLLAMA_SERVERS = fairyland.prole.org:11434,k3d.localhost:11434,morgoth.prole.org:11434
|
||||||
|
OLLAMA_SERVER_HOST = fairyland.prole.org
|
||||||
|
OLLAMA_SERVER_PORT = 11434
|
||||||
|
|
||||||
|
[Optional Features]
|
||||||
|
AT_REST_ENCRYPTION_ENABLED = true
|
||||||
|
GITOPS_ENABLED = false
|
||||||
|
KERBEROS_ENABLED = true
|
||||||
|
SUPABASE_ENABLED = false
|
||||||
|
|
||||||
|
[GitOps]
|
||||||
|
|
||||||
|
[Database Creation]
|
||||||
|
DB_NAME = prole-db
|
||||||
|
DB_USER = root
|
||||||
|
|
||||||
|
[Initialize Cluster]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Dev Cluster (k3d)]
|
||||||
|
CLUSTER_ENV = k3d-knoe-dev-cluster
|
||||||
|
DISPLAY_NAME = knoe-dev-cluster
|
||||||
|
KUBECTL_CONTEXT = service
|
||||||
|
MODE = k3d
|
||||||
|
|
||||||
|
[Service Cluster (k3s)]
|
||||||
|
CLUSTER_ENV = prole-service-cluster
|
||||||
|
DISPLAY_NAME = prole-service-cluster
|
||||||
|
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||||
|
K3S_TOKEN = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
||||||
|
MODE = k3s
|
||||||
|
PIPELINE_URL = http://127.0.0.1:8080
|
||||||
|
|
||||||
|
[Prod Cluster (k8s)]
|
||||||
|
ARTIFACTS_DIR =
|
||||||
|
CLUSTER_ENV = prole-prod-cluster
|
||||||
|
DISPLAY_NAME = prole-prod-cluster
|
||||||
|
MODE = k8s
|
||||||
|
PIPELINE_URL = http://127.0.0.1:8080
|
||||||
|
|
||||||
|
[Docker Build]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Initialization Scripts]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Deployment]
|
||||||
|
MODE = k3s
|
||||||
|
TARGET = prole-service-cluster
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
STATUS = Failed
|
||||||
195
conf/service/service/prole.cfg
Normal file
195
conf/service/service/prole.cfg
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
; Prole Master Configuration File
|
||||||
|
; Generated by install.py on 2026-03-22 20:46:43
|
||||||
|
; This file is used as input for Ansible deployment and k8s cluster creation.
|
||||||
|
|
||||||
|
[User]
|
||||||
|
; User-editable values; derived values below reference these by default.
|
||||||
|
; No user values captured yet for this section.
|
||||||
|
|
||||||
|
[Inputs]
|
||||||
|
; Screen-scoped inputs used for unattended replays (-S)
|
||||||
|
build.deploy_env = Dev
|
||||||
|
build.run_build = false
|
||||||
|
database_options.distribution = percona
|
||||||
|
database_options.ext.dblink = true
|
||||||
|
database_options.ext.pg_buffercache = true
|
||||||
|
database_options.ext.pg_freespacemap = true
|
||||||
|
database_options.ext.pg_repack = true
|
||||||
|
database_options.ext.pg_stat_monitor = true
|
||||||
|
database_options.ext.pg_stat_statements = true
|
||||||
|
database_options.ext.pgaudit = true
|
||||||
|
database_options.ext.pgbadger = true
|
||||||
|
database_options.ext.pgcrypto = true
|
||||||
|
database_options.ext.pgrowlocks = true
|
||||||
|
database_options.ext.pgvector = true
|
||||||
|
database_options.ext.postgis = true
|
||||||
|
database_options.ext.postgres_fdw = true
|
||||||
|
database_options.version_type = v18
|
||||||
|
dependencies.ansible.install = true
|
||||||
|
dependencies.auto_install_missing = true
|
||||||
|
dependencies.brew.install = true
|
||||||
|
dependencies.docker.install = true
|
||||||
|
dependencies.k3d.install = true
|
||||||
|
dependencies.kubectl.install = true
|
||||||
|
dependencies.kubectx.install = true
|
||||||
|
dependencies.opentofu.install = true
|
||||||
|
dependencies.python.install = true
|
||||||
|
dependencies.verify_all = false
|
||||||
|
disk_selection.disk_type = local
|
||||||
|
disk_selection.local_path = /Users/chrisfu/dev/prole/prole-tools-app/dist
|
||||||
|
disk_selection.removable_mount =
|
||||||
|
env_setup.NAMESPACE = ${NAMESPACE}
|
||||||
|
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||||
|
env_setup.PROLE_DATA = /Users/chrisfu/dev/prole/data
|
||||||
|
env_setup.PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
env_setup.PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
||||||
|
env_setup.PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
||||||
|
init_cluster.argocd_enabled = false
|
||||||
|
init_cluster.at_rest_encryption_enabled = true
|
||||||
|
init_cluster.cluster_env = service
|
||||||
|
init_cluster.deployment_target = prole-service-cluster
|
||||||
|
init_cluster.gitops_enabled = false
|
||||||
|
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
||||||
|
init_cluster.k3s_token = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
||||||
|
init_cluster.kerberos_enabled = true
|
||||||
|
init_cluster.mode = k3s
|
||||||
|
init_cluster.start_cluster = true
|
||||||
|
init_cluster.supabase_enabled = false
|
||||||
|
init_cnpg_deploy.force_rollout = false
|
||||||
|
init_cnpg_deploy.run_deploy = true
|
||||||
|
init_db_build.run_build = true
|
||||||
|
init_password.db_host_port = 5432
|
||||||
|
init_password.db_namespace = ${NAMESPACE}
|
||||||
|
init_password.db_password = ${PROLE_SECRET:v1:vz4oaR5QA3zIJWDs:blYR6vqpY0e_GqGWFufDwlY4yxXWXrGF}
|
||||||
|
init_password.db_password_confirm = ${PROLE_SECRET:v1:vz4oaR5QA3zIJWDs:blYR6vqpY0e_GqGWFufDwlY4yxXWXrGF}
|
||||||
|
init_password.db_username = root
|
||||||
|
init_password.generate_ssh_key = true
|
||||||
|
init_scripts.run_scripts = true
|
||||||
|
kerberos_config.enabled = true
|
||||||
|
kerberos_config.init_authority = false
|
||||||
|
kerberos_config.kdc = 10.0.0.3
|
||||||
|
kerberos_config.password = ${PROLE_SECRET:v1:71ROfYyYysQDJDpX:0K4cB3p9nnMb1yi2OImqUm-pa9Zg21JYTmYHzYB_7czTKMQJ}
|
||||||
|
kerberos_config.realm = PROLE.ORG
|
||||||
|
kerberos_config.test_connection = false
|
||||||
|
kerberos_config.user = administrator
|
||||||
|
network_scan.run = true
|
||||||
|
ollama_config.model =
|
||||||
|
ollama_config.server_host = fairyland.prole.org
|
||||||
|
ollama_config.server_port = 11434
|
||||||
|
|
||||||
|
[Global]
|
||||||
|
; Variables used by name in more than one place or assumed global scope
|
||||||
|
ARGOCD_NAMESPACE = argocd
|
||||||
|
CLUSTER_ENV = service
|
||||||
|
DB_HOST_PORT = 5432
|
||||||
|
DB_PASSWORD = ${PROLE_SECRET:v1:NmgNZUhCsk-p0_DF:VB1tKREj45eEWcnN1GAlcGV6b_Lrl9sx}
|
||||||
|
DEPLOYMENT_MODE = k3s
|
||||||
|
DEPLOYMENT_TARGET = prole-service-cluster
|
||||||
|
DOCKER_IMPORT_DIR =
|
||||||
|
DOCKER_PRELOAD = false
|
||||||
|
NAMESPACE = prole-db
|
||||||
|
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
||||||
|
PROLE_DB_USER = root
|
||||||
|
PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
||||||
|
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
||||||
|
PROLE_OPENTOFU_URL = http://myrddin.prole.org:8080
|
||||||
|
REGISTRY_NAMESPACE = knoe-system
|
||||||
|
SERVICE_NAMESPACE = knoe-system
|
||||||
|
|
||||||
|
[Welcome]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Dependencies]
|
||||||
|
STATUS = All installed
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
AD_DC_HOST = myrddin.prole.org
|
||||||
|
AD_DC_IP = 10.0.0.3
|
||||||
|
ANSIBLE_DOMAIN = prole.org
|
||||||
|
ANSIBLE_INFRASTRUCTURE = /Users/chrisfu/dev/prole/infrastructure
|
||||||
|
ANSIBLE_INVENTORY = /Users/chrisfu/dev/prole/infrastructure/inventory
|
||||||
|
ANSIBLE_REALM = PROLE.ORG
|
||||||
|
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","merlin.prole.org":"10.0.0.6","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["pi.prole.org","merlin.prole.org"],"k3s_hosts:children":["k3s_servers","k3s_agents"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"ssl_hosts":["myrddin.prole.org"],"mariadb_primary":["merlin.prole.org"],"mariadb_replica":["raspberry.prole.org"],"mariadb:children":["mariadb_primary","mariadb_replica"],"merlin_bootstrap":["merlin"]},"hosts":{"merlin":"10.0.0.6","merlin.prole.org":"10.0.0.6","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":["k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
|
||||||
|
KDC_ANSIBLE_DETECTED = 10.0.0.3
|
||||||
|
KDC_AUTO_DETECTED = 10.0.0.3
|
||||||
|
KERBEROS_AUTO_ENABLED = True
|
||||||
|
|
||||||
|
[Port Forwards]
|
||||||
|
PORT_FORWARD_K3S_MAPPING_1 = id=argocd;namespace=argocd;target=svc/argocd-server;address=0.0.0.0;hostPort=8081;servicePort=80;protocol=TCP;description=ArgoCD
|
||||||
|
PORT_FORWARD_K3S_MAPPING_2 = id=garage;namespace=knoe-system;target=svc/garage;address=0.0.0.0;hostPort=3900;servicePort=3900;protocol=TCP;description=Garage S3
|
||||||
|
PORT_FORWARD_K3S_MAPPING_3 = id=openbao;namespace=knoe-system;target=svc/openbao;address=0.0.0.0;hostPort=8200;servicePort=8200;protocol=TCP;description=OpenBao
|
||||||
|
PORT_FORWARD_K3S_MAPPING_4 = id=opentofu;namespace=knoe-system;target=svc/opentofu;address=0.0.0.0;hostPort=8080;servicePort=8080;protocol=TCP;description=OpenTofu
|
||||||
|
PORT_FORWARD_K3S_MAPPING_5 = id=dashboard;namespace=kubernetes-dashboard;target=svc/kubernetes-dashboard-kong-proxy;address=127.0.0.1;hostPort=8443;servicePort=443;protocol=TCP;description=Kubernetes Dashboard
|
||||||
|
PORT_FORWARD_K3S_MAPPING_6 = id=postgres;namespace=${NAMESPACE};target=svc/prole-db-rw;address=0.0.0.0;hostPort=5432;servicePort=5432;protocol=TCP;description=PostgreSQL (primary)
|
||||||
|
PORT_FORWARD_K3S_MAPPING_7 = id=prometheus;namespace=monitoring;target=svc/kps-kube-prometheus-stack-prometheus;address=127.0.0.1;hostPort=9090;servicePort=9090;protocol=TCP;description=Prometheus UI
|
||||||
|
PORT_FORWARD_K3S_MAPPING_8 = id=grafana;namespace=monitoring;target=svc/kps-grafana;address=0.0.0.0;hostPort=3000;servicePort=80;protocol=TCP;description=Grafana UI
|
||||||
|
|
||||||
|
[System Environment]
|
||||||
|
NAMESPACE = prole-db
|
||||||
|
PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||||
|
PROLE_DATA = /Users/chrisfu/dev/prole/data
|
||||||
|
PROLE_HOME = /Users/chrisfu/dev/prole
|
||||||
|
PROLE_LOGS = /Users/chrisfu/dev/prole/logs
|
||||||
|
PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
|
||||||
|
|
||||||
|
[Monitoring]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Kerberos Authentication]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Ollama]
|
||||||
|
OLLAMA_HOST = http://fairyland.prole.org:11434
|
||||||
|
OLLAMA_SERVERS = fairyland.prole.org:11434,k3d.localhost:11434,morgoth.prole.org:11434
|
||||||
|
OLLAMA_SERVER_HOST = fairyland.prole.org
|
||||||
|
OLLAMA_SERVER_PORT = 11434
|
||||||
|
|
||||||
|
[Optional Features]
|
||||||
|
AT_REST_ENCRYPTION_ENABLED = true
|
||||||
|
GITOPS_ENABLED = false
|
||||||
|
KERBEROS_ENABLED = true
|
||||||
|
SUPABASE_ENABLED = false
|
||||||
|
|
||||||
|
[GitOps]
|
||||||
|
|
||||||
|
[Database Creation]
|
||||||
|
DB_NAME = prole-db
|
||||||
|
DB_USER = root
|
||||||
|
|
||||||
|
[Initialize Cluster]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Dev Cluster (k3d)]
|
||||||
|
CLUSTER_ENV = k3d-knoe-dev-cluster
|
||||||
|
DISPLAY_NAME = knoe-dev-cluster
|
||||||
|
KUBECTL_CONTEXT = service
|
||||||
|
MODE = k3d
|
||||||
|
|
||||||
|
[Service Cluster (k3s)]
|
||||||
|
CLUSTER_ENV = prole-service-cluster
|
||||||
|
DISPLAY_NAME = prole-service-cluster
|
||||||
|
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||||
|
K3S_TOKEN = ${PROLE_SECRET:v1:_r5tIPt5VZcr0SrV:e2_sHY49gG2i-vhQZr-42M1kekln4D4ZHq6tJrDRCn8f4KOVSn59rndLt4PuHmsebPSPP4tGHZV0MaVtdBMm4RJmk9IXbqV7BjSNruK2SXi62NOXIIUWZGNcVIOFjmv7EovfOifo3nye8142zKDspTeyo5Y2KY6qGLtS2g==}
|
||||||
|
MODE = k3s
|
||||||
|
PIPELINE_URL = http://myrddin.prole.org:8080
|
||||||
|
|
||||||
|
[Prod Cluster (k8s)]
|
||||||
|
ARTIFACTS_DIR =
|
||||||
|
CLUSTER_ENV = prole-prod-cluster
|
||||||
|
DISPLAY_NAME = prole-prod-cluster
|
||||||
|
MODE = k8s
|
||||||
|
PIPELINE_URL = http://myrddin.prole.org:8080
|
||||||
|
|
||||||
|
[Docker Build]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Initialization Scripts]
|
||||||
|
; No configuration values captured yet for this section.
|
||||||
|
|
||||||
|
[Deployment]
|
||||||
|
MODE = k3s
|
||||||
|
TARGET = prole-service-cluster
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
STATUS = Failed
|
||||||
@ -71,8 +71,8 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: garage
|
synology.storage/role: garage
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-data
|
name: synology-iscsi-d001-data
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/data
|
path: /synology/d001/data
|
||||||
@ -27,17 +27,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-wal
|
name: synology-iscsi-d001-wal
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/wal
|
path: /synology/d001/wal
|
||||||
@ -53,17 +53,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-garage
|
name: synology-iscsi-d001-garage
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: garage
|
synology.storage/role: garage
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/garage
|
path: /synology/d001/garage
|
||||||
@ -79,17 +79,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d002-data
|
name: synology-iscsi-d002-data
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
prole.storage/volume: d002
|
synology.storage/volume: d002
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d002/data
|
path: /synology/d002/data
|
||||||
@ -105,17 +105,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d002-wal
|
name: synology-iscsi-d002-wal
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
prole.storage/volume: d002
|
synology.storage/volume: d002
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d002/wal
|
path: /synology/d002/wal
|
||||||
@ -131,17 +131,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d003-data
|
name: synology-iscsi-d003-data
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
prole.storage/volume: d003
|
synology.storage/volume: d003
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d003/data
|
path: /synology/d003/data
|
||||||
@ -157,17 +157,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d003-wal
|
name: synology-iscsi-d003-wal
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
prole.storage/volume: d003
|
synology.storage/volume: d003
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d003/wal
|
path: /synology/d003/wal
|
||||||
@ -183,17 +183,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d003-grafana
|
name: synology-iscsi-d003-grafana
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: grafana
|
synology.storage/role: grafana
|
||||||
prole.storage/volume: d003
|
synology.storage/volume: d003
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d003/grafana
|
path: /synology/d003/grafana
|
||||||
@ -209,17 +209,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d002-prometheus
|
name: synology-iscsi-d002-prometheus
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: prometheus
|
synology.storage/role: prometheus
|
||||||
prole.storage/volume: d002
|
synology.storage/volume: d002
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 20Gi
|
storage: 20Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d002/prometheus
|
path: /synology/d002/prometheus
|
||||||
@ -235,17 +235,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-openbao
|
name: synology-iscsi-d001-openbao
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: openbao
|
synology.storage/role: openbao
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/openbao
|
path: /synology/d001/openbao
|
||||||
|
|||||||
@ -51,7 +51,7 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: openbao
|
synology.storage/role: openbao
|
||||||
|
|||||||
@ -4,27 +4,23 @@ metadata:
|
|||||||
name: prole-db
|
name: prole-db
|
||||||
spec:
|
spec:
|
||||||
instances: 3
|
instances: 3
|
||||||
imageName: k3d-prole-registry:5000/knoe-db:18-138
|
imageName: k3d-prole-registry:5000/knoe-db:18-140
|
||||||
postgresUID: 100
|
postgresUID: 100
|
||||||
postgresGID: 101
|
postgresGID: 101
|
||||||
maxSyncReplicas: 1
|
maxSyncReplicas: 1
|
||||||
affinity:
|
affinity:
|
||||||
# CloudNativePG uses its own affinity schema (not corev1.Affinity). See: `kubectl explain cluster.spec.affinity`
|
# CloudNativePG uses its own affinity schema (not corev1.Affinity). See: `kubectl explain cluster.spec.affinity`
|
||||||
enablePodAntiAffinity: true
|
enablePodAntiAffinity: true
|
||||||
podAntiAffinityType: required
|
podAntiAffinityType: preferred
|
||||||
topologyKey: kubernetes.io/hostname
|
topologyKey: kubernetes.io/hostname
|
||||||
tolerations:
|
|
||||||
- key: "node-role.kubernetes.io/control-plane"
|
|
||||||
operator: "Exists"
|
|
||||||
effect: "NoSchedule"
|
|
||||||
nodeAffinity:
|
nodeAffinity:
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
nodeSelectorTerms:
|
nodeSelectorTerms:
|
||||||
- matchExpressions:
|
- matchExpressions:
|
||||||
- key: prole.org/node-role
|
- key: node.kubernetes.io/instance-type
|
||||||
operator: In
|
operator: In
|
||||||
values:
|
values:
|
||||||
- db
|
- k3s
|
||||||
|
|
||||||
postgresql:
|
postgresql:
|
||||||
parameters:
|
parameters:
|
||||||
@ -92,10 +88,10 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
walStorage:
|
walStorage:
|
||||||
size: 1Gi
|
size: 1Gi
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
@ -104,9 +100,9 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
monitoring:
|
monitoring:
|
||||||
enablePodMonitor: false
|
enablePodMonitor: false
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
apiVersion: storage.k8s.io/v1
|
apiVersion: storage.k8s.io/v1
|
||||||
kind: StorageClass
|
kind: StorageClass
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi
|
name: synology-iscsi
|
||||||
provisioner: kubernetes.io/no-provisioner
|
provisioner: kubernetes.io/no-provisioner
|
||||||
reclaimPolicy: Retain
|
reclaimPolicy: Retain
|
||||||
volumeBindingMode: WaitForFirstConsumer
|
volumeBindingMode: WaitForFirstConsumer
|
||||||
@ -101,9 +101,9 @@ CERT_MANAGER_MANIFEST_URL=${CERT_MANAGER_MANIFEST_URL:-}
|
|||||||
CERT_MANAGER_FALLBACK_VERSION=${CERT_MANAGER_FALLBACK_VERSION:-1.19.3}
|
CERT_MANAGER_FALLBACK_VERSION=${CERT_MANAGER_FALLBACK_VERSION:-1.19.3}
|
||||||
|
|
||||||
# Protected storage requirements (k3s only)
|
# Protected storage requirements (k3s only)
|
||||||
PROLE_CNPG_STORAGE_CLASS=${PROLE_CNPG_STORAGE_CLASS:-prole-iscsi}
|
PROLE_CNPG_STORAGE_CLASS=${PROLE_CNPG_STORAGE_CLASS:-synology-iscsi}
|
||||||
PROLE_PROTECTED_DATA_PATH=${PROLE_PROTECTED_DATA_PATH:-/prole/d001/data}
|
PROLE_PROTECTED_DATA_PATH=${PROLE_PROTECTED_DATA_PATH:-/synology/d001/data}
|
||||||
PROLE_PROTECTED_WAL_PATH=${PROLE_PROTECTED_WAL_PATH:-/prole/d001/wal}
|
PROLE_PROTECTED_WAL_PATH=${PROLE_PROTECTED_WAL_PATH:-/synology/d001/wal}
|
||||||
|
|
||||||
if [[ "$ACTION" != "deploy" && "$ACTION" != "rollout" && "$ACTION" != "force-rollout" ]]; then
|
if [[ "$ACTION" != "deploy" && "$ACTION" != "rollout" && "$ACTION" != "force-rollout" ]]; then
|
||||||
if [[ -n "${2:-}" ]]; then
|
if [[ -n "${2:-}" ]]; then
|
||||||
@ -265,9 +265,9 @@ validate_cnpg_manifest_storage() {
|
|||||||
wal_sc="$v"
|
wal_sc="$v"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [[ -n "$block" && "$line" =~ prole\.storage/role: ]]; then
|
if [[ -n "$block" && "$line" =~ synology\.storage/role: ]]; then
|
||||||
local r
|
local r
|
||||||
r=$(printf '%s' "$line" | sed -E 's/^.*prole\.storage\/role:[[:space:]]*//; s/[[:space:]]+$//')
|
r=$(printf '%s' "$line" | sed -E 's/^.*synology\.storage\/role:[[:space:]]*//; s/[[:space:]]+$//')
|
||||||
if [[ "$block" == "storage" && -z "$data_role" ]]; then
|
if [[ "$block" == "storage" && -z "$data_role" ]]; then
|
||||||
data_role="$r"
|
data_role="$r"
|
||||||
elif [[ "$block" == "wal" && -z "$wal_role" ]]; then
|
elif [[ "$block" == "wal" && -z "$wal_role" ]]; then
|
||||||
@ -283,7 +283,7 @@ validate_cnpg_manifest_storage() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$data_role" != "data" || "$wal_role" != "wal" ]]; then
|
if [[ "$data_role" != "data" || "$wal_role" != "wal" ]]; then
|
||||||
echo "ERROR: CNPG Cluster manifest must include explicit PV selectors for Prole storage (prole.storage/role=data and prole.storage/role=wal)." >&2
|
echo "ERROR: CNPG Cluster manifest must include explicit PV selectors for Prole storage (synology.storage/role=data and synology.storage/role=wal)." >&2
|
||||||
echo "Got selector roles: data='${data_role:-<missing>}', wal='${wal_role:-<missing>}'" >&2
|
echo "Got selector roles: data='${data_role:-<missing>}', wal='${wal_role:-<missing>}'" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -307,8 +307,8 @@ validate_cnpg_runtime_storage() {
|
|||||||
local data_sc wal_sc data_role wal_role
|
local data_sc wal_sc data_role wal_role
|
||||||
data_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.storageClassName // empty')
|
data_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.storageClassName // empty')
|
||||||
wal_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.storageClassName // empty')
|
wal_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.storageClassName // empty')
|
||||||
data_role=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.selector.matchLabels["prole.storage/role"] // empty')
|
data_role=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.selector.matchLabels["synology.storage/role"] // empty')
|
||||||
wal_role=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.selector.matchLabels["prole.storage/role"] // empty')
|
wal_role=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.selector.matchLabels["synology.storage/role"] // empty')
|
||||||
|
|
||||||
if [[ "$data_sc" != "$sc" || "$wal_sc" != "$sc" ]]; then
|
if [[ "$data_sc" != "$sc" || "$wal_sc" != "$sc" ]]; then
|
||||||
echo "ERROR: Live CNPG Cluster storageClassName must be '${sc}' for both data and walStorage (got data='${data_sc:-<missing>}', wal='${wal_sc:-<missing>}')." >&2
|
echo "ERROR: Live CNPG Cluster storageClassName must be '${sc}' for both data and walStorage (got data='${data_sc:-<missing>}', wal='${wal_sc:-<missing>}')." >&2
|
||||||
@ -366,9 +366,9 @@ validate_cnpg_runtime_storage() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
case "$pv_path" in
|
case "$pv_path" in
|
||||||
/prole/*) ;;
|
/synology/*) ;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: Bound PV '${pv}' path '${pv_path}' is not under /prole/. Refusing deployment." >&2
|
echo "ERROR: Bound PV '${pv}' path '${pv_path}' is not under /synology/. Refusing deployment." >&2
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -448,16 +448,20 @@ wait_for_apiserver_ready() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensure_namespace() {
|
ensure_namespace() {
|
||||||
if [[ -z "${PROLE_NAMESPACE:-}" ]]; then
|
require_namespace_configured
|
||||||
echo "ERROR: PROLE_NAMESPACE is empty. Set NAMESPACE in conf/prole.cfg." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if ! kubectl get namespace "$PROLE_NAMESPACE" >/dev/null 2>&1; then
|
if ! kubectl get namespace "$PROLE_NAMESPACE" >/dev/null 2>&1; then
|
||||||
echo "Creating namespace '$PROLE_NAMESPACE' ..."
|
echo "Creating namespace '$PROLE_NAMESPACE' ..."
|
||||||
kubectl create namespace "$PROLE_NAMESPACE" >/dev/null 2>&1 || true
|
kubectl create namespace "$PROLE_NAMESPACE" >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_namespace_configured() {
|
||||||
|
if [[ -z "${PROLE_NAMESPACE:-}" ]]; then
|
||||||
|
echo "ERROR: PROLE_NAMESPACE is empty. Set NAMESPACE in conf/prole.cfg." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
kubectl_apply_retry() {
|
kubectl_apply_retry() {
|
||||||
local namespace="${1:-}"
|
local namespace="${1:-}"
|
||||||
local attempts=${2:-8}
|
local attempts=${2:-8}
|
||||||
@ -540,6 +544,17 @@ get_latest_image() {
|
|||||||
echo "knoe-db:${pg_version}-${release}"
|
echo "knoe-db:${pg_version}-${release}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_desired_cnpg_image() {
|
||||||
|
local image
|
||||||
|
if [[ "$VERSION" == "latest" || -z "$VERSION" ]]; then
|
||||||
|
image=$(get_latest_image)
|
||||||
|
else
|
||||||
|
image="knoe-db:$VERSION"
|
||||||
|
fi
|
||||||
|
image=$(resolve_cnpg_image "$image")
|
||||||
|
printf '%s' "$image"
|
||||||
|
}
|
||||||
|
|
||||||
_cnpg_current_image_name() {
|
_cnpg_current_image_name() {
|
||||||
if ! kubectl -n "$NAMESPACE" get cluster "$CNPG_CLUSTER_NAME" >/dev/null 2>&1; then
|
if ! kubectl -n "$NAMESPACE" get cluster "$CNPG_CLUSTER_NAME" >/dev/null 2>&1; then
|
||||||
echo ""
|
echo ""
|
||||||
@ -1287,6 +1302,151 @@ apply_prole_manifest_file() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_prole_k3s_registry_host_for_cache() {
|
||||||
|
# Best-effort host:port for the k3s registry, used as an optional cache source in k3d mode.
|
||||||
|
# Intentionally avoids k3d registry names and localhost-ish endpoints.
|
||||||
|
local r="${PROLE_K3S_REGISTRY:-${K3S_REGISTRY_HOST:-${LOCAL_REGISTRY_INTERNAL:-${LOCAL_REGISTRY:-}}}}"
|
||||||
|
|
||||||
|
r="${r#http://}"
|
||||||
|
r="${r#https://}"
|
||||||
|
|
||||||
|
case "${r}" in
|
||||||
|
"")
|
||||||
|
r="myrddin.prole.org:5000"
|
||||||
|
;;
|
||||||
|
localhost:5000|127.0.0.1:5000|*.localhost|*.localhost:5000)
|
||||||
|
r="myrddin.prole.org:5000"
|
||||||
|
;;
|
||||||
|
k3d-*|*/k3d-*)
|
||||||
|
r="myrddin.prole.org:5000"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf '%s' "$r"
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_build_knoe_db_image() {
|
||||||
|
# Build the knoe-db image with BuildKit and optional cache source.
|
||||||
|
# Args: <tag> <context_dir> [cache_ref]
|
||||||
|
local tag="$1"
|
||||||
|
local context_dir="$2"
|
||||||
|
local cache_ref="${3:-}"
|
||||||
|
|
||||||
|
local ssh_args=()
|
||||||
|
if [[ -n "${SSH_AUTH_SOCK:-}" ]]; then
|
||||||
|
ssh_args+=(--ssh default)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker buildx version >/dev/null 2>&1; then
|
||||||
|
# Prefer an isolated docker-container builder to avoid host snapshot/cache corruption.
|
||||||
|
local builder_name="${PROLE_BUILDX_BUILDER:-prole-buildkit}"
|
||||||
|
if ! docker buildx inspect "$builder_name" >/dev/null 2>&1; then
|
||||||
|
docker buildx create --name "$builder_name" --driver docker-container --use >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
docker buildx use "$builder_name" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
local cache_args=()
|
||||||
|
if [[ -n "$cache_ref" ]]; then
|
||||||
|
cache_args+=(--cache-from "type=registry,ref=${cache_ref}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker buildx build \
|
||||||
|
--pull \
|
||||||
|
--tag "$tag" \
|
||||||
|
--load \
|
||||||
|
"${ssh_args[@]}" \
|
||||||
|
"${cache_args[@]}" \
|
||||||
|
"$context_dir"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback to docker build (still BuildKit-enabled); cache-from here only works if the cache image is present locally.
|
||||||
|
local cache_from_args=()
|
||||||
|
if [[ -n "$cache_ref" ]]; then
|
||||||
|
docker pull "$cache_ref" >/dev/null 2>&1 || true
|
||||||
|
cache_from_args+=(--cache-from "$cache_ref")
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOCKER_BUILDKIT=1 docker build \
|
||||||
|
--pull \
|
||||||
|
"${ssh_args[@]}" \
|
||||||
|
"${cache_from_args[@]}" \
|
||||||
|
-t "$tag" \
|
||||||
|
"$context_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Import a Docker image directly to each k3s node via SSH + 'k3s ctr images import'.
|
||||||
|
# Used as a last-resort fallback when the in-cluster registry is unreachable and
|
||||||
|
# the kubectl port-forward push also fails (e.g. registry service not yet deployed).
|
||||||
|
# Respects optional PROLE_SSH_KEY (path to private key) and K3S_SSH_USER env vars.
|
||||||
|
_import_image_to_k3s_nodes() {
|
||||||
|
local image="$1"
|
||||||
|
local ssh_user="${K3S_SSH_USER:-${ANSIBLE_USER:-ansible}}"
|
||||||
|
local ssh_key_args=()
|
||||||
|
# Auto-detect the SSH key: explicit override → ~/.ssh/id_ed25519_ansible (ansible user key)
|
||||||
|
# → prole ssh-keys dir → ssh-agent default.
|
||||||
|
local _auto_key_ansible="${HOME}/.ssh/id_ed25519_ansible"
|
||||||
|
local _auto_key_prole="${PROLE_HOME:-$SCRIPT_DIR/..}/ssh-keys/id_prole_ed25519"
|
||||||
|
local _ssh_key="${PROLE_SSH_KEY:-${K3S_SSH_KEY:-}}"
|
||||||
|
if [[ -z "$_ssh_key" && -f "$_auto_key_ansible" ]]; then
|
||||||
|
_ssh_key="$_auto_key_ansible"
|
||||||
|
elif [[ -z "$_ssh_key" && -f "$_auto_key_prole" ]]; then
|
||||||
|
_ssh_key="$_auto_key_prole"
|
||||||
|
fi
|
||||||
|
if [[ -n "$_ssh_key" && -f "$_ssh_key" ]]; then
|
||||||
|
ssh_key_args=(-i "$_ssh_key")
|
||||||
|
fi
|
||||||
|
|
||||||
|
local nodes=()
|
||||||
|
mapfile -t nodes < <(kubectl get nodes \
|
||||||
|
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null || true)
|
||||||
|
if [[ ${#nodes[@]} -eq 0 ]]; then
|
||||||
|
echo " WARN: No k3s nodes found for direct image import." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local tar_file
|
||||||
|
tar_file=$(mktemp /tmp/prole-img-XXXXXX.tar)
|
||||||
|
echo " Saving image '$image' for k3s node import ..."
|
||||||
|
if ! docker save "$image" -o "$tar_file" 2>/dev/null; then
|
||||||
|
echo " WARN: docker save failed for '$image'." >&2
|
||||||
|
rm -f "$tar_file" 2>/dev/null || true
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local imported=0
|
||||||
|
for node in "${nodes[@]}"; do
|
||||||
|
# Skip nodes that already have the image in k3s containerd.
|
||||||
|
if ssh -o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=10 \
|
||||||
|
"${ssh_key_args[@]}" "${ssh_user}@${node}" \
|
||||||
|
"sudo k3s ctr images ls 2>/dev/null | grep -qF '${plain_image}'" 2>/dev/null; then
|
||||||
|
echo " ✓ Image already in k3s containerd on '$node'; skipping import."
|
||||||
|
imported=$((imported + 1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo " Importing '$image' to k3s node '$node' ..."
|
||||||
|
if ssh -o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=30 \
|
||||||
|
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \
|
||||||
|
"${ssh_key_args[@]}" "${ssh_user}@${node}" \
|
||||||
|
"sudo k3s ctr images import -" < "$tar_file" >/dev/null 2>&1; then
|
||||||
|
echo " ✓ Image imported on node '$node'."
|
||||||
|
imported=$((imported + 1))
|
||||||
|
else
|
||||||
|
echo " WARN: Failed to import image on node '$node'; skipping." >&2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -f "$tar_file" 2>/dev/null || true
|
||||||
|
if [[ $imported -eq 0 ]]; then
|
||||||
|
echo " WARN: Image import failed on all k3s nodes." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo " ✓ Image '$image' imported on $imported/${#nodes[@]} k3s node(s)."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
_push_to_k3s_registry() {
|
_push_to_k3s_registry() {
|
||||||
local image="$1"
|
local image="$1"
|
||||||
local push_host="${LOCAL_REGISTRY:-${LOCAL_REGISTRY_INTERNAL:-myrddin.prole.org:5000}}"
|
local push_host="${LOCAL_REGISTRY:-${LOCAL_REGISTRY_INTERNAL:-myrddin.prole.org:5000}}"
|
||||||
@ -1434,6 +1594,7 @@ _ensure_prole_db_image() {
|
|||||||
local prole_db_dir="${PROLE_DB_BUILD_CONTEXT_DIR:-${runtime_home}/build/${mode_key}/knoe-db}"
|
local prole_db_dir="${PROLE_DB_BUILD_CONTEXT_DIR:-${runtime_home}/build/${mode_key}/knoe-db}"
|
||||||
local source_db_dir="${PROLE_HOME:-$SCRIPT_DIR/..}/prole-db"
|
local source_db_dir="${PROLE_HOME:-$SCRIPT_DIR/..}/prole-db"
|
||||||
local plain_image="${image##*/}" # e.g. knoe-db:18-088
|
local plain_image="${image##*/}" # e.g. knoe-db:18-088
|
||||||
|
local k3s_cache_ref=""
|
||||||
|
|
||||||
if [[ ! -f "$prole_db_dir/Dockerfile" ]]; then
|
if [[ ! -f "$prole_db_dir/Dockerfile" ]]; then
|
||||||
if [[ -d "$source_db_dir" ]]; then
|
if [[ -d "$source_db_dir" ]]; then
|
||||||
@ -1446,6 +1607,32 @@ _ensure_prole_db_image() {
|
|||||||
|
|
||||||
if [[ "${PROLE_MODE:-}" == "k3s" ]]; then
|
if [[ "${PROLE_MODE:-}" == "k3s" ]]; then
|
||||||
echo "Pre-flight: ensuring image '$image' is available in k3s registry/import path ..."
|
echo "Pre-flight: ensuring image '$image' is available in k3s registry/import path ..."
|
||||||
|
# Step 1 (k3s): if the CNPG cluster already exists and is running with this exact image
|
||||||
|
# the image is already present in k3s containerd on the nodes — skip push entirely.
|
||||||
|
local _k3s_current_image _k3s_ready
|
||||||
|
_k3s_current_image=$(kubectl get cluster "${CNPG_CLUSTER_NAME:-prole-db}" \
|
||||||
|
-n "${CNPG_NAMESPACE:-${NAMESPACE:-prole-db}}" \
|
||||||
|
-o jsonpath='{.spec.imageName}' 2>/dev/null || true)
|
||||||
|
_k3s_ready=$(kubectl get cluster "${CNPG_CLUSTER_NAME:-prole-db}" \
|
||||||
|
-n "${CNPG_NAMESPACE:-${NAMESPACE:-prole-db}}" \
|
||||||
|
-o jsonpath='{.status.readyInstances}' 2>/dev/null || true)
|
||||||
|
if [[ "$_k3s_current_image" == "$image" && "${_k3s_ready:-0}" -gt 0 ]]; then
|
||||||
|
echo " ✓ CNPG cluster already running with image '$image'; no push needed."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
# Step 1b: check if image already exists in the registry via a quick manifest HEAD request.
|
||||||
|
local _reg_host="${LOCAL_REGISTRY:-${LOCAL_REGISTRY_INTERNAL:-myrddin.prole.org:5000}}"
|
||||||
|
_reg_host="${_reg_host#http://}"; _reg_host="${_reg_host#https://}"
|
||||||
|
local _img_name="${plain_image%%:*}" _img_tag="${plain_image##*:}"
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
if curl -k -fsS -m 3 \
|
||||||
|
"https://${_reg_host}/v2/${_img_name}/manifests/${_img_tag}" >/dev/null 2>&1 \
|
||||||
|
|| curl -fsS -m 3 \
|
||||||
|
"http://${_reg_host}/v2/${_img_name}/manifests/${_img_tag}" >/dev/null 2>&1; then
|
||||||
|
echo " ✓ Image '$image' already present in registry at '${_reg_host}'; no push needed."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Auto-detect active k3d cluster name
|
# Auto-detect active k3d cluster name
|
||||||
local cluster_name="${K3D_CLUSTER_NAME:-}"
|
local cluster_name="${K3D_CLUSTER_NAME:-}"
|
||||||
@ -1454,6 +1641,13 @@ _ensure_prole_db_image() {
|
|||||||
fi
|
fi
|
||||||
cluster_name="${cluster_name:-knoe-dev-cluster}"
|
cluster_name="${cluster_name:-knoe-dev-cluster}"
|
||||||
|
|
||||||
|
# In k3d mode, optionally consult the k3s registry as a cache/source of truth before building.
|
||||||
|
local k3s_host
|
||||||
|
k3s_host=$(_prole_k3s_registry_host_for_cache)
|
||||||
|
if [[ -n "${k3s_host:-}" ]]; then
|
||||||
|
k3s_cache_ref="${k3s_host}/${plain_image}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Pre-flight: verifying image '$image' is available in k3d cluster '$cluster_name' ..."
|
echo "Pre-flight: verifying image '$image' is available in k3d cluster '$cluster_name' ..."
|
||||||
|
|
||||||
# Step 1: check if already present in k3d containerd with matching digest
|
# Step 1: check if already present in k3d containerd with matching digest
|
||||||
@ -1526,6 +1720,18 @@ _ensure_prole_db_image() {
|
|||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Step 3b (k3d only): try to reuse a previously-built image from the k3s registry.
|
||||||
|
# If present, retag it to the desired image name and push/import into the k3d cluster.
|
||||||
|
if [[ "${PROLE_MODE:-}" == "k3d" && -n "${k3s_cache_ref:-}" && "${k3s_cache_ref}" != "${image}" ]]; then
|
||||||
|
if docker image inspect "$k3s_cache_ref" >/dev/null 2>&1 || docker pull "$k3s_cache_ref" >/dev/null 2>&1; then
|
||||||
|
echo " ✓ Found '$plain_image' in k3s registry (${k3s_cache_ref}); re-tagging for k3d as '$image' ..."
|
||||||
|
docker tag "$k3s_cache_ref" "$image" 2>/dev/null || true
|
||||||
|
_push_to_k3d_registry "$image" "$cluster_name"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
echo " (cache) '$plain_image' not present in k3s registry (${k3s_cache_ref}); building locally ..."
|
||||||
|
fi
|
||||||
|
|
||||||
# Step 4: image not found anywhere — build from source then push + import
|
# Step 4: image not found anywhere — build from source then push + import
|
||||||
if [[ ! -f "$prole_db_dir/Dockerfile" ]]; then
|
if [[ ! -f "$prole_db_dir/Dockerfile" ]]; then
|
||||||
echo "ERROR: Dockerfile not found in '$prole_db_dir'; cannot build knoe-db image." >&2
|
echo "ERROR: Dockerfile not found in '$prole_db_dir'; cannot build knoe-db image." >&2
|
||||||
@ -1537,7 +1743,7 @@ _ensure_prole_db_image() {
|
|||||||
echo " Image '$image' not found in k3d, Docker daemon, or docker-import dir."
|
echo " Image '$image' not found in k3d, Docker daemon, or docker-import dir."
|
||||||
fi
|
fi
|
||||||
echo " Building knoe-db image from '$prole_db_dir' ..."
|
echo " Building knoe-db image from '$prole_db_dir' ..."
|
||||||
if ! docker build -t "$plain_image" "$prole_db_dir"; then
|
if ! _docker_build_knoe_db_image "$plain_image" "$prole_db_dir" "${k3s_cache_ref:-}"; then
|
||||||
echo "ERROR: docker build failed for image '$plain_image'." >&2
|
echo "ERROR: docker build failed for image '$plain_image'." >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -2538,14 +2744,14 @@ restore_cnpg_cluster() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycle_released_prole_iscsi_pvs() {
|
recycle_released_prole_iscsi_pvs() {
|
||||||
# StorageClass `prole-iscsi` uses `Retain` PV reclaim policy. After a CNPG reset, PVs can remain
|
# StorageClass `synology-iscsi` uses `Retain` PV reclaim policy. After a CNPG reset, PVs can remain
|
||||||
# in `Released` with a stale `claimRef`, which prevents new PVCs (same names) from binding.
|
# in `Released` with a stale `claimRef`, which prevents new PVCs (same names) from binding.
|
||||||
# In that case, CNPG init jobs remain `Pending` with "didn't find available persistent volumes".
|
# In that case, CNPG init jobs remain `Pending` with "didn't find available persistent volumes".
|
||||||
echo "Recycling Released prole-iscsi PVs (clearing stale claimRefs) for namespace '$NAMESPACE' ..."
|
echo "Recycling Released synology-iscsi PVs (clearing stale claimRefs) for namespace '$NAMESPACE' ..."
|
||||||
local pvs
|
local pvs
|
||||||
pvs=$(kubectl get pv -o json \
|
pvs=$(kubectl get pv -o json \
|
||||||
| jq -r --arg ns "$NAMESPACE" '.items[]
|
| jq -r --arg ns "$NAMESPACE" '.items[]
|
||||||
| select(.spec.storageClassName == "prole-iscsi")
|
| select(.spec.storageClassName == "synology-iscsi")
|
||||||
| select(.status.phase == "Released")
|
| select(.status.phase == "Released")
|
||||||
| select((.spec.claimRef.namespace // "") == $ns)
|
| select((.spec.claimRef.namespace // "") == $ns)
|
||||||
| .metadata.name' 2>/dev/null || true)
|
| .metadata.name' 2>/dev/null || true)
|
||||||
@ -2827,8 +3033,22 @@ get_latest_cnpg_version() {
|
|||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
ensure_tools
|
ensure_tools
|
||||||
ensure_namespace
|
require_namespace_configured
|
||||||
wait_for_apiserver_ready 180
|
wait_for_apiserver_ready 180
|
||||||
|
|
||||||
|
local desired_image current_image
|
||||||
|
desired_image=$(_desired_cnpg_image)
|
||||||
|
current_image=$(_cnpg_current_image_name)
|
||||||
|
|
||||||
|
if [[ -n "$current_image" && "$current_image" == "$desired_image" ]]; then
|
||||||
|
echo "✓ Namespace '$NAMESPACE' already contains CNPG cluster '$CNPG_CLUSTER_NAME' using image '$desired_image'; no re-deploy needed."
|
||||||
|
echo " (Use 'update'/'reload' if you intended to re-apply manifests.)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_enforce_namespace_image_policy "$desired_image" || return 1
|
||||||
|
|
||||||
|
ensure_namespace
|
||||||
attempt_backup_if_active
|
attempt_backup_if_active
|
||||||
ensure_cnpg_operator
|
ensure_cnpg_operator
|
||||||
pin_cnpg_controller
|
pin_cnpg_controller
|
||||||
@ -2906,6 +3126,21 @@ update_reload() {
|
|||||||
|
|
||||||
deploy_cluster() {
|
deploy_cluster() {
|
||||||
ensure_tools
|
ensure_tools
|
||||||
|
require_namespace_configured
|
||||||
|
|
||||||
|
wait_for_apiserver_ready 180
|
||||||
|
|
||||||
|
local image current_image_before
|
||||||
|
image=$(_desired_cnpg_image)
|
||||||
|
current_image_before=$(_cnpg_current_image_name)
|
||||||
|
|
||||||
|
if [[ -n "$current_image_before" && "$current_image_before" == "$image" ]]; then
|
||||||
|
echo "✓ Namespace '$NAMESPACE' already contains CNPG cluster '$CNPG_CLUSTER_NAME' using image '$image'; skipping deploy."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_enforce_namespace_image_policy "$image" || return 1
|
||||||
|
|
||||||
ensure_namespace
|
ensure_namespace
|
||||||
ensure_cnpg_operator
|
ensure_cnpg_operator
|
||||||
pin_cnpg_controller
|
pin_cnpg_controller
|
||||||
@ -2913,13 +3148,6 @@ deploy_cluster() {
|
|||||||
|
|
||||||
ensure_prole_protected_storage
|
ensure_prole_protected_storage
|
||||||
|
|
||||||
local image
|
|
||||||
if [[ "$VERSION" == "latest" || -z "$VERSION" ]]; then
|
|
||||||
image=$(get_latest_image)
|
|
||||||
else
|
|
||||||
image="knoe-db:$VERSION"
|
|
||||||
fi
|
|
||||||
image=$(resolve_cnpg_image "$image")
|
|
||||||
sync_manifest_image "$image"
|
sync_manifest_image "$image"
|
||||||
|
|
||||||
generate_tls_if_missing
|
generate_tls_if_missing
|
||||||
@ -2949,11 +3177,20 @@ deploy_cluster() {
|
|||||||
kubectl cnpg restart "$CNPG_CLUSTER_NAME" -n "$NAMESPACE" || true
|
kubectl cnpg restart "$CNPG_CLUSTER_NAME" -n "$NAMESPACE" || true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${PROLE_UPGRADE:-0}" == "1" && -n "$current_image_before" && "$current_image_before" != "$image" ]]; then
|
||||||
|
echo "Upgrade requested; forcing CNPG rollout to ensure pods pick up image '$image' ..."
|
||||||
|
if kubectl cnpg version >/dev/null 2>&1; then
|
||||||
|
kubectl cnpg restart "$CNPG_CLUSTER_NAME" -n "$NAMESPACE" || true
|
||||||
|
else
|
||||||
|
force_rollout || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
preflight_image() {
|
preflight_image() {
|
||||||
ensure_tools
|
ensure_tools
|
||||||
ensure_namespace
|
require_namespace_configured
|
||||||
_ensure_prole_db_image
|
_ensure_prole_db_image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
GARAGE_FILES=(
|
GARAGE_FILES=(
|
||||||
"$GARAGE_MANIFEST_DIR/storageclass-prole-iscsi.yaml"
|
"$GARAGE_MANIFEST_DIR/storageclass-synology-iscsi.yaml"
|
||||||
"$GARAGE_MANIFEST_DIR/iscsi-pvs.yaml"
|
"$GARAGE_MANIFEST_DIR/iscsi-pvs.yaml"
|
||||||
"$GARAGE_MANIFEST_DIR/garage-configmap.yaml"
|
"$GARAGE_MANIFEST_DIR/garage-configmap.yaml"
|
||||||
"$GARAGE_MANIFEST_DIR/garage-statefulset.yaml"
|
"$GARAGE_MANIFEST_DIR/garage-statefulset.yaml"
|
||||||
@ -133,7 +133,7 @@ k3d_cleanup_pending_pvc() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
selector=$(kubectl get pvc data-garage-0 -n "$NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
selector=$(kubectl get pvc data-garage-0 -n "$NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
||||||
if printf '%s' "$selector" | grep -q "prole.storage/"; then
|
if printf '%s' "$selector" | grep -q "synology.storage/"; then
|
||||||
echo "Removing pending Garage PVC with selector for k3d local-path ..."
|
echo "Removing pending Garage PVC with selector for k3d local-path ..."
|
||||||
kubectl delete statefulset "$GARAGE_NAME" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete statefulset "$GARAGE_NAME" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
kubectl delete pvc data-garage-0 -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete pvc data-garage-0 -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
@ -160,6 +160,24 @@ apply_manifests() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if [[ $diff_rc -ne 1 ]]; then
|
if [[ $diff_rc -ne 1 ]]; then
|
||||||
|
# For immutable StatefulSet VolumeClaimTemplates, kubectl diff itself returns an
|
||||||
|
# error (diff_rc != 1 but contains the immutable spec error). Handle it here.
|
||||||
|
if [[ "$(basename "$f")" == "garage-statefulset.yaml" ]] \
|
||||||
|
&& echo "$diff_out" | grep -q "updates to statefulset spec"; then
|
||||||
|
echo "WARN: Garage StatefulSet VolumeClaimTemplates changed (diff-stage); deleting and recreating ..."
|
||||||
|
kubectl delete statefulset "$GARAGE_NAME" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
|
local _pvc_sc_d
|
||||||
|
_pvc_sc_d=$(kubectl get pvc "data-garage-0" -n "$NAMESPACE" \
|
||||||
|
-o jsonpath='{.spec.storageClassName}' 2>/dev/null || true)
|
||||||
|
if [[ -n "$_pvc_sc_d" && "$_pvc_sc_d" != "synology-iscsi" ]]; then
|
||||||
|
echo " Removing stale PVC 'data-garage-0' (storageClass: $_pvc_sc_d) ..."
|
||||||
|
kubectl delete pvc "data-garage-0" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
printf '%s' "$rendered" | kubectl apply --validate=false -n "$NAMESPACE" -f -
|
||||||
|
GARAGE_APPLY_CHANGED=1
|
||||||
|
GARAGE_STATEFULSET_CHANGED=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
echo "$diff_out" >&2
|
echo "$diff_out" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -175,6 +193,23 @@ apply_manifests() {
|
|||||||
&& echo "$output" | grep -q "updates to statefulset spec"; then
|
&& echo "$output" | grep -q "updates to statefulset spec"; then
|
||||||
echo "WARN: Garage StatefulSet immutable in k3d; skipping apply."
|
echo "WARN: Garage StatefulSet immutable in k3d; skipping apply."
|
||||||
continue
|
continue
|
||||||
|
elif [[ "$(basename "$f")" == "garage-statefulset.yaml" ]] \
|
||||||
|
&& echo "$output" | grep -q "updates to statefulset spec"; then
|
||||||
|
# VolumeClaimTemplates are immutable; delete the StatefulSet (PVCs are orphaned/preserved)
|
||||||
|
# and recreate so the new storageClass name takes effect.
|
||||||
|
echo "WARN: Garage StatefulSet VolumeClaimTemplates changed; deleting and recreating ..."
|
||||||
|
kubectl delete statefulset "$GARAGE_NAME" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
|
local _pvc_sc
|
||||||
|
_pvc_sc=$(kubectl get pvc "data-garage-0" -n "$NAMESPACE" \
|
||||||
|
-o jsonpath='{.spec.storageClassName}' 2>/dev/null || true)
|
||||||
|
if [[ -n "$_pvc_sc" && "$_pvc_sc" != "synology-iscsi" ]]; then
|
||||||
|
echo " Removing stale PVC 'data-garage-0' (storageClass: $_pvc_sc) ..."
|
||||||
|
kubectl delete pvc "data-garage-0" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
printf '%s' "$rendered" | kubectl apply --validate=false -n "$NAMESPACE" -f -
|
||||||
|
GARAGE_APPLY_CHANGED=1
|
||||||
|
GARAGE_STATEFULSET_CHANGED=1
|
||||||
|
continue
|
||||||
fi
|
fi
|
||||||
echo "$output" >&2
|
echo "$output" >&2
|
||||||
exit 1
|
exit 1
|
||||||
@ -283,7 +318,7 @@ dump_debug() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycle_released_prole_iscsi_pv_for_pvc() {
|
recycle_released_prole_iscsi_pv_for_pvc() {
|
||||||
# StorageClass `prole-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
# StorageClass `synology-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
||||||
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
||||||
local ns="$1"
|
local ns="$1"
|
||||||
local pvc="$2"
|
local pvc="$2"
|
||||||
@ -301,7 +336,7 @@ recycle_released_prole_iscsi_pv_for_pvc() {
|
|||||||
|
|
||||||
local pv sc rp phase claim_ns claim_name claim_uid
|
local pv sc rp phase claim_ns claim_name claim_uid
|
||||||
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
||||||
[[ "$sc" == "prole-iscsi" ]] || continue
|
[[ "$sc" == "synology-iscsi" ]] || continue
|
||||||
[[ "$rp" == "Retain" ]] || continue
|
[[ "$rp" == "Retain" ]] || continue
|
||||||
[[ "$phase" == "Released" ]] || continue
|
[[ "$phase" == "Released" ]] || continue
|
||||||
[[ "$claim_ns" == "$ns" ]] || continue
|
[[ "$claim_ns" == "$ns" ]] || continue
|
||||||
@ -322,7 +357,7 @@ wait_ready() {
|
|||||||
|
|
||||||
local initial_timeout="${PVC_REPAIR_WAIT_TIMEOUT:-30s}"
|
local initial_timeout="${PVC_REPAIR_WAIT_TIMEOUT:-30s}"
|
||||||
if ! kubectl rollout status statefulset/$GARAGE_NAME -n "$NAMESPACE" --timeout="$initial_timeout"; then
|
if ! kubectl rollout status statefulset/$GARAGE_NAME -n "$NAMESPACE" --timeout="$initial_timeout"; then
|
||||||
echo "WARN: Garage not ready after $initial_timeout; checking for Released prole-iscsi PVs with stale claimRefs ..." >&2
|
echo "WARN: Garage not ready after $initial_timeout; checking for Released synology-iscsi PVs with stale claimRefs ..." >&2
|
||||||
recycle_released_prole_iscsi_pv_for_pvc "$NAMESPACE" "data-garage-0" || true
|
recycle_released_prole_iscsi_pv_for_pvc "$NAMESPACE" "data-garage-0" || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@ -313,8 +313,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: merlin-local-iscsi-${volume_id}-prometheus
|
name: merlin-local-iscsi-${volume_id}-prometheus
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: prometheus
|
synology.storage/role: prometheus
|
||||||
prole.storage/volume: ${volume_id}
|
synology.storage/volume: ${volume_id}
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 30Gi
|
storage: 30Gi
|
||||||
@ -339,8 +339,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: merlin-local-iscsi-${volume_id}-alertmanager
|
name: merlin-local-iscsi-${volume_id}-alertmanager
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: alertmanager
|
synology.storage/role: alertmanager
|
||||||
prole.storage/volume: ${volume_id}
|
synology.storage/volume: ${volume_id}
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
@ -365,8 +365,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: merlin-local-iscsi-${volume_id}-grafana
|
name: merlin-local-iscsi-${volume_id}-grafana
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: grafana
|
synology.storage/role: grafana
|
||||||
prole.storage/volume: ${volume_id}
|
synology.storage/volume: ${volume_id}
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
|
|||||||
@ -423,7 +423,7 @@ iscsi_pv_names_from_manifest() {
|
|||||||
awk '
|
awk '
|
||||||
$1=="kind:" && $2=="PersistentVolume" {in_pv=1; next}
|
$1=="kind:" && $2=="PersistentVolume" {in_pv=1; next}
|
||||||
in_pv && $1=="name:" {print $2; in_pv=0}
|
in_pv && $1=="name:" {print $2; in_pv=0}
|
||||||
' "$manifest" | sed 's/["\r]//g' | grep -v '^$' || true
|
' "$manifest" | tr -d $'"\r' | grep -v '^$' || true
|
||||||
}
|
}
|
||||||
|
|
||||||
desired_pv_path_from_manifest() {
|
desired_pv_path_from_manifest() {
|
||||||
@ -435,7 +435,7 @@ desired_pv_path_from_manifest() {
|
|||||||
$1=="kind:" && $2=="PersistentVolume" {is_pv=1}
|
$1=="kind:" && $2=="PersistentVolume" {is_pv=1}
|
||||||
is_pv && $1=="name:" && $2==pv {hit=1}
|
is_pv && $1=="name:" && $2==pv {hit=1}
|
||||||
hit && $1=="path:" {print $2; exit}
|
hit && $1=="path:" {print $2; exit}
|
||||||
' "$manifest" | sed 's/["\r]//g' | head -1 || true
|
' "$manifest" | tr -d $'"\r' | head -1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
desired_pv_node_from_manifest() {
|
desired_pv_node_from_manifest() {
|
||||||
@ -448,7 +448,7 @@ desired_pv_node_from_manifest() {
|
|||||||
is_pv && $1=="name:" && $2==pv {hit=1}
|
is_pv && $1=="name:" && $2==pv {hit=1}
|
||||||
hit && $1=="values:" {in_values=1; next}
|
hit && $1=="values:" {in_values=1; next}
|
||||||
in_values && $1=="-" {print $2; exit}
|
in_values && $1=="-" {print $2; exit}
|
||||||
' "$manifest" | sed 's/["\r]//g' | head -1 || true
|
' "$manifest" | tr -d $'"\r' | head -1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_iscsi_pvs() {
|
ensure_iscsi_pvs() {
|
||||||
@ -503,9 +503,9 @@ apply_k8s() {
|
|||||||
fi
|
fi
|
||||||
if [[ "$use_statefulset" == "1" ]]; then
|
if [[ "$use_statefulset" == "1" ]]; then
|
||||||
# Ensure storage class and PVs exist for k3s
|
# Ensure storage class and PVs exist for k3s
|
||||||
if [[ -f "$SCRIPT_DIR/../k8s/prole/storageclass-prole-iscsi.yaml" ]]; then
|
if [[ -f "$SCRIPT_DIR/../k8s/prole/storageclass-synology-iscsi.yaml" ]]; then
|
||||||
echo "Applying StorageClass 'prole-iscsi' ..."
|
echo "Applying StorageClass 'synology-iscsi' ..."
|
||||||
kubectl apply -f "$SCRIPT_DIR/../k8s/prole/storageclass-prole-iscsi.yaml"
|
kubectl apply -f "$SCRIPT_DIR/../k8s/prole/storageclass-synology-iscsi.yaml"
|
||||||
fi
|
fi
|
||||||
if [[ -f "$SCRIPT_DIR/../k8s/prole/iscsi-pvs.yaml" ]]; then
|
if [[ -f "$SCRIPT_DIR/../k8s/prole/iscsi-pvs.yaml" ]]; then
|
||||||
ensure_iscsi_pvs "$SCRIPT_DIR/../k8s/prole/iscsi-pvs.yaml"
|
ensure_iscsi_pvs "$SCRIPT_DIR/../k8s/prole/iscsi-pvs.yaml"
|
||||||
@ -518,6 +518,20 @@ apply_k8s() {
|
|||||||
else
|
else
|
||||||
if [[ "${PROLE_MODE:-}" == "k3d" && "$output" == *"updates to statefulset spec"* ]]; then
|
if [[ "${PROLE_MODE:-}" == "k3d" && "$output" == *"updates to statefulset spec"* ]]; then
|
||||||
echo "WARN: OpenBao StatefulSet immutable in k3d; skipping apply."
|
echo "WARN: OpenBao StatefulSet immutable in k3d; skipping apply."
|
||||||
|
elif [[ "$output" == *"updates to statefulset spec"* ]]; then
|
||||||
|
# VolumeClaimTemplates are immutable; delete the StatefulSet (PVCs are orphaned/preserved)
|
||||||
|
# and recreate so the new storageClass name takes effect.
|
||||||
|
echo "WARN: OpenBao StatefulSet VolumeClaimTemplates changed; deleting and recreating ..."
|
||||||
|
kubectl delete statefulset "$OPENBAO_NAME" -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
|
local _pvc_sc
|
||||||
|
_pvc_sc=$(kubectl get pvc "data-openbao-0" -n "$OPENBAO_RESOURCE_NAMESPACE" \
|
||||||
|
-o jsonpath='{.spec.storageClassName}' 2>/dev/null || true)
|
||||||
|
if [[ -n "$_pvc_sc" && "$_pvc_sc" != "synology-iscsi" ]]; then
|
||||||
|
echo " Removing stale PVC 'data-openbao-0' (storageClass: $_pvc_sc) ..."
|
||||||
|
kubectl delete pvc "data-openbao-0" -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
prole_render_manifest "$SCRIPT_DIR/../k8s/prole/openbao-statefulset.yaml" \
|
||||||
|
| kubectl apply --validate=false -n "$OPENBAO_RESOURCE_NAMESPACE" -f -
|
||||||
else
|
else
|
||||||
echo "$output" >&2
|
echo "$output" >&2
|
||||||
return 1
|
return 1
|
||||||
@ -554,7 +568,7 @@ k3d_cleanup_pending_openbao_pvc() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
selector=$(kubectl get pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
selector=$(kubectl get pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
||||||
if printf '%s' "$selector" | grep -q "prole.storage/"; then
|
if printf '%s' "$selector" | grep -q "synology.storage/"; then
|
||||||
echo "Removing pending OpenBao PVC with selector for k3d local-path ..."
|
echo "Removing pending OpenBao PVC with selector for k3d local-path ..."
|
||||||
kubectl delete statefulset "$OPENBAO_NAME" -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete statefulset "$OPENBAO_NAME" -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
kubectl delete pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
@ -562,7 +576,7 @@ k3d_cleanup_pending_openbao_pvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycle_released_prole_iscsi_pv_for_pvc() {
|
recycle_released_prole_iscsi_pv_for_pvc() {
|
||||||
# StorageClass `prole-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
# StorageClass `synology-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
||||||
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
||||||
local ns="$1"
|
local ns="$1"
|
||||||
local pvc="$2"
|
local pvc="$2"
|
||||||
@ -580,7 +594,7 @@ recycle_released_prole_iscsi_pv_for_pvc() {
|
|||||||
|
|
||||||
local pv sc rp phase claim_ns claim_name claim_uid
|
local pv sc rp phase claim_ns claim_name claim_uid
|
||||||
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
||||||
[[ "$sc" == "prole-iscsi" ]] || continue
|
[[ "$sc" == "synology-iscsi" ]] || continue
|
||||||
[[ "$rp" == "Retain" ]] || continue
|
[[ "$rp" == "Retain" ]] || continue
|
||||||
[[ "$phase" == "Released" ]] || continue
|
[[ "$phase" == "Released" ]] || continue
|
||||||
[[ "$claim_ns" == "$ns" ]] || continue
|
[[ "$claim_ns" == "$ns" ]] || continue
|
||||||
@ -621,13 +635,13 @@ wait_for_openbao() {
|
|||||||
echo "Waiting for OpenBao to become ready in namespace '$wait_ns' ..."
|
echo "Waiting for OpenBao to become ready in namespace '$wait_ns' ..."
|
||||||
if kubectl get statefulset/$OPENBAO_NAME -n "$wait_ns" >/dev/null 2>&1; then
|
if kubectl get statefulset/$OPENBAO_NAME -n "$wait_ns" >/dev/null 2>&1; then
|
||||||
if ! kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
if ! kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
||||||
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released prole-iscsi PVs with stale claimRefs ..." >&2
|
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released synology-iscsi PVs with stale claimRefs ..." >&2
|
||||||
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
||||||
fi
|
fi
|
||||||
kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
||||||
else
|
else
|
||||||
if ! kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
if ! kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
||||||
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released prole-iscsi PVs with stale claimRefs ..." >&2
|
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released synology-iscsi PVs with stale claimRefs ..." >&2
|
||||||
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
||||||
fi
|
fi
|
||||||
kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
||||||
|
|||||||
@ -246,7 +246,7 @@ deploy_service_layer() {
|
|||||||
SERVICE_NAMESPACE="$ns" PROLE_KDC_NAMESPACE="$ns" \
|
SERVICE_NAMESPACE="$ns" PROLE_KDC_NAMESPACE="$ns" \
|
||||||
"$SCRIPT_DIR/init_kdc.sh" "$kdc_action" || rc=$?
|
"$SCRIPT_DIR/init_kdc.sh" "$kdc_action" || rc=$?
|
||||||
else
|
else
|
||||||
log "[INFO] Kerberos enabled: skipping standalone KDC deploy (KDC runs as `kdc` sidecar in `prole-auth`)."
|
log "[INFO] Kerberos enabled: skipping standalone KDC deploy (KDC runs as 'kdc' sidecar in 'prole-auth')."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@ -42,9 +42,18 @@ common_core_preparse_config() {
|
|||||||
fi
|
fi
|
||||||
local cfg_dir
|
local cfg_dir
|
||||||
cfg_dir=$(cd "$(dirname "$COMMON_CORE_CONFIG_PATH")" && pwd)
|
cfg_dir=$(cd "$(dirname "$COMMON_CORE_CONFIG_PATH")" && pwd)
|
||||||
|
# Preserve an already-set PROLE_CONF when it is a more-specific env subdir of
|
||||||
|
# cfg_dir (e.g. conf/service/ vs the injected-default conf/). This allows the
|
||||||
|
# parent shell / Python milestone to pass the correct env-specific conf dir and
|
||||||
|
# have it survive even when init scripts inject a generic fallback -c path.
|
||||||
|
local _current_conf="${PROLE_CONF:-}"
|
||||||
|
if [[ -n "$_current_conf" && "$_current_conf" == "${cfg_dir}/"* && -f "$_current_conf/prole.cfg" ]]; then
|
||||||
|
: # keep inherited PROLE_CONF — it is already more specific than cfg_dir
|
||||||
|
else
|
||||||
PROLE_CONF="$cfg_dir"
|
PROLE_CONF="$cfg_dir"
|
||||||
export PROLE_CONF
|
export PROLE_CONF
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse standard options and action.
|
# Parse standard options and action.
|
||||||
|
|||||||
@ -518,7 +518,7 @@ fi
|
|||||||
|
|
||||||
# Safety: prole.cfg must override any pre-set PROLE_MODE from the environment.
|
# Safety: prole.cfg must override any pre-set PROLE_MODE from the environment.
|
||||||
# Otherwise a leaked PROLE_MODE=k3d can trigger k3d-only manifest stripping (e.g., removing
|
# Otherwise a leaked PROLE_MODE=k3d can trigger k3d-only manifest stripping (e.g., removing
|
||||||
# `storageClassName: prole-iscsi`) while targeting a k3s cluster.
|
# `storageClassName: synology-iscsi`) while targeting a k3s cluster.
|
||||||
_prole_cfg_mode_hint=""
|
_prole_cfg_mode_hint=""
|
||||||
if [[ -n "${prole_mode:-}" ]]; then
|
if [[ -n "${prole_mode:-}" ]]; then
|
||||||
_prole_cfg_mode_hint=$(prole_normalize_mode "$prole_mode")
|
_prole_cfg_mode_hint=$(prole_normalize_mode "$prole_mode")
|
||||||
|
|||||||
@ -65,7 +65,7 @@ def _strip_blocks(text: str) -> str:
|
|||||||
break
|
break
|
||||||
block_lines.append(next_line)
|
block_lines.append(next_line)
|
||||||
j += 1
|
j += 1
|
||||||
if any("prole.storage/" in bl for bl in block_lines):
|
if any("synology.storage/" in bl for bl in block_lines):
|
||||||
i = j
|
i = j
|
||||||
continue
|
continue
|
||||||
out.extend(block_lines)
|
out.extend(block_lines)
|
||||||
@ -78,7 +78,7 @@ def _strip_blocks(text: str) -> str:
|
|||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if stripped.startswith("storageClassName:") and "prole-iscsi" in stripped:
|
if stripped.startswith("storageClassName:") and "synology-iscsi" in stripped:
|
||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@ -71,8 +71,8 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: garage
|
synology.storage/role: garage
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-data
|
name: synology-iscsi-d001-data
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/data
|
path: /synology/d001/data
|
||||||
@ -27,17 +27,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-wal
|
name: synology-iscsi-d001-wal
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/wal
|
path: /synology/d001/wal
|
||||||
@ -53,17 +53,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-garage
|
name: synology-iscsi-d001-garage
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: garage
|
synology.storage/role: garage
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/garage
|
path: /synology/d001/garage
|
||||||
@ -79,17 +79,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d002-data
|
name: synology-iscsi-d002-data
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
prole.storage/volume: d002
|
synology.storage/volume: d002
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d002/data
|
path: /synology/d002/data
|
||||||
@ -105,17 +105,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d002-wal
|
name: synology-iscsi-d002-wal
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
prole.storage/volume: d002
|
synology.storage/volume: d002
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d002/wal
|
path: /synology/d002/wal
|
||||||
@ -131,17 +131,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d003-data
|
name: synology-iscsi-d003-data
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
prole.storage/volume: d003
|
synology.storage/volume: d003
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d003/data
|
path: /synology/d003/data
|
||||||
@ -157,17 +157,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d003-wal
|
name: synology-iscsi-d003-wal
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
prole.storage/volume: d003
|
synology.storage/volume: d003
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d003/wal
|
path: /synology/d003/wal
|
||||||
@ -183,17 +183,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d003-grafana
|
name: synology-iscsi-d003-grafana
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: grafana
|
synology.storage/role: grafana
|
||||||
prole.storage/volume: d003
|
synology.storage/volume: d003
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d003/grafana
|
path: /synology/d003/grafana
|
||||||
@ -209,17 +209,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d002-prometheus
|
name: synology-iscsi-d002-prometheus
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: prometheus
|
synology.storage/role: prometheus
|
||||||
prole.storage/volume: d002
|
synology.storage/volume: d002
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 20Gi
|
storage: 20Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d002/prometheus
|
path: /synology/d002/prometheus
|
||||||
@ -235,17 +235,17 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi-d001-openbao
|
name: synology-iscsi-d001-openbao
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: openbao
|
synology.storage/role: openbao
|
||||||
prole.storage/volume: d001
|
synology.storage/volume: d001
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
volumeMode: Filesystem
|
volumeMode: Filesystem
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteOnce
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
persistentVolumeReclaimPolicy: Retain
|
persistentVolumeReclaimPolicy: Retain
|
||||||
local:
|
local:
|
||||||
path: /synology/d001/openbao
|
path: /synology/d001/openbao
|
||||||
|
|||||||
@ -3,8 +3,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: prole-monitoring-d004-prometheus
|
name: prole-monitoring-d004-prometheus
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: prometheus
|
synology.storage/role: prometheus
|
||||||
prole.storage/volume: d004
|
synology.storage/volume: d004
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 30Gi
|
storage: 30Gi
|
||||||
@ -29,8 +29,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: prole-monitoring-d004-alertmanager
|
name: prole-monitoring-d004-alertmanager
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: alertmanager
|
synology.storage/role: alertmanager
|
||||||
prole.storage/volume: d004
|
synology.storage/volume: d004
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
@ -55,8 +55,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: prole-monitoring-d004-grafana
|
name: prole-monitoring-d004-grafana
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: grafana
|
synology.storage/role: grafana
|
||||||
prole.storage/volume: d004
|
synology.storage/volume: d004
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
|
|||||||
@ -51,7 +51,7 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: openbao
|
synology.storage/role: openbao
|
||||||
|
|||||||
@ -5,7 +5,7 @@ metadata:
|
|||||||
name: prole-db
|
name: prole-db
|
||||||
spec:
|
spec:
|
||||||
instances: 3
|
instances: 3
|
||||||
imageName: k3d-prole-registry:5000/knoe-db:18-138
|
imageName: example.invalid:5000/knoe-db:0.0.0
|
||||||
postgresUID: 100
|
postgresUID: 100
|
||||||
postgresGID: 101
|
postgresGID: 101
|
||||||
maxSyncReplicas: 1
|
maxSyncReplicas: 1
|
||||||
@ -61,10 +61,10 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
walStorage:
|
walStorage:
|
||||||
size: 1Gi
|
size: 1Gi
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
@ -73,10 +73,10 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
|
|
||||||
monitoring:
|
monitoring:
|
||||||
enablePodMonitor: false
|
enablePodMonitor: false
|
||||||
|
|||||||
@ -4,23 +4,23 @@ metadata:
|
|||||||
name: prole-db
|
name: prole-db
|
||||||
spec:
|
spec:
|
||||||
instances: 3
|
instances: 3
|
||||||
imageName: myrddin.prole.org:5000/knoe-db:18-125
|
imageName: myrddin.prole.org:5000/knoe-db:18-140
|
||||||
postgresUID: 100
|
postgresUID: 100
|
||||||
postgresGID: 101
|
postgresGID: 101
|
||||||
maxSyncReplicas: 1
|
maxSyncReplicas: 1
|
||||||
affinity:
|
affinity:
|
||||||
# CloudNativePG uses its own affinity schema (not corev1.Affinity). See: `kubectl explain cluster.spec.affinity`
|
# CloudNativePG uses its own affinity schema (not corev1.Affinity). See: `kubectl explain cluster.spec.affinity`
|
||||||
enablePodAntiAffinity: true
|
enablePodAntiAffinity: true
|
||||||
podAntiAffinityType: required
|
podAntiAffinityType: preferred
|
||||||
topologyKey: kubernetes.io/hostname
|
topologyKey: kubernetes.io/hostname
|
||||||
nodeAffinity:
|
nodeAffinity:
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
nodeSelectorTerms:
|
nodeSelectorTerms:
|
||||||
- matchExpressions:
|
- matchExpressions:
|
||||||
- key: prole.org/node-role
|
- key: node.kubernetes.io/instance-type
|
||||||
operator: In
|
operator: In
|
||||||
values:
|
values:
|
||||||
- db
|
- k3s
|
||||||
|
|
||||||
postgresql:
|
postgresql:
|
||||||
parameters:
|
parameters:
|
||||||
@ -88,10 +88,10 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
walStorage:
|
walStorage:
|
||||||
size: 1Gi
|
size: 1Gi
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
@ -100,9 +100,9 @@ spec:
|
|||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
monitoring:
|
monitoring:
|
||||||
enablePodMonitor: false
|
enablePodMonitor: false
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
apiVersion: storage.k8s.io/v1
|
apiVersion: storage.k8s.io/v1
|
||||||
kind: StorageClass
|
kind: StorageClass
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-iscsi
|
name: synology-iscsi
|
||||||
provisioner: kubernetes.io/no-provisioner
|
provisioner: kubernetes.io/no-provisioner
|
||||||
reclaimPolicy: Retain
|
reclaimPolicy: Retain
|
||||||
volumeBindingMode: WaitForFirstConsumer
|
volumeBindingMode: WaitForFirstConsumer
|
||||||
@ -856,6 +856,64 @@ class ProleInstaller:
|
|||||||
return self._ensure_namespace_prefix(ns)
|
return self._ensure_namespace_prefix(ns)
|
||||||
return self._ensure_namespace_prefix(self._generate_namespace_name())
|
return self._ensure_namespace_prefix(self._generate_namespace_name())
|
||||||
|
|
||||||
|
def _initial_db_namespace(self) -> str:
|
||||||
|
"""Initial namespace suggestion for CNPG/Postgres.
|
||||||
|
|
||||||
|
Unlike `_initial_namespace()`, this default is version-aware to encourage
|
||||||
|
parallel installs (e.g. `knoe-db-18-142`).
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Explicit overrides must win.
|
||||||
|
base = (
|
||||||
|
os.environ.get("PROLE_DB_NAMESPACE")
|
||||||
|
or os.environ.get("DB_NAMESPACE")
|
||||||
|
or os.environ.get("PROLE_NAMESPACE")
|
||||||
|
or os.environ.get("NAMESPACE")
|
||||||
|
or ""
|
||||||
|
).strip()
|
||||||
|
|
||||||
|
if not base:
|
||||||
|
try:
|
||||||
|
existing = self._read_existing_env()
|
||||||
|
base = (
|
||||||
|
(existing.get("NAMESPACE") or "")
|
||||||
|
or (existing.get("PROLE_NAMESPACE") or "")
|
||||||
|
).strip()
|
||||||
|
except Exception:
|
||||||
|
base = ""
|
||||||
|
|
||||||
|
if not base:
|
||||||
|
base = (self._read_existing_cfg_namespace() or "").strip() or "knoe-db"
|
||||||
|
|
||||||
|
base = self._sanitize_namespace(self._ensure_namespace_prefix(base))
|
||||||
|
|
||||||
|
version = ""
|
||||||
|
try:
|
||||||
|
controller = getattr(self, "controller", None)
|
||||||
|
if controller is not None:
|
||||||
|
version = (controller.get_prole_db_version() or "").strip()
|
||||||
|
except Exception:
|
||||||
|
version = ""
|
||||||
|
|
||||||
|
if not version:
|
||||||
|
return base
|
||||||
|
|
||||||
|
version_ns = self._sanitize_namespace(version.replace(".", "-"))
|
||||||
|
|
||||||
|
if base.endswith(f"-{version_ns}"):
|
||||||
|
return base
|
||||||
|
|
||||||
|
combined = f"{base}-{version_ns}"
|
||||||
|
if len(combined) > 63:
|
||||||
|
# Keep the version suffix intact and trim the base to fit.
|
||||||
|
max_base_len = 63 - len(version_ns) - 1
|
||||||
|
if max_base_len < 1:
|
||||||
|
return self._sanitize_namespace(f"knoe-db-{version_ns}")
|
||||||
|
base_trim = base[:max_base_len].rstrip("-")
|
||||||
|
combined = f"{base_trim}-{version_ns}"
|
||||||
|
|
||||||
|
return self._sanitize_namespace(combined)
|
||||||
|
|
||||||
def _is_valid_namespace(self, name: str) -> bool:
|
def _is_valid_namespace(self, name: str) -> bool:
|
||||||
if not name or len(name) > 63:
|
if not name or len(name) > 63:
|
||||||
return False
|
return False
|
||||||
@ -5613,8 +5671,8 @@ class ProleConsoleInstaller(ProleInstaller):
|
|||||||
NetworkScanMilestone(),
|
NetworkScanMilestone(),
|
||||||
EnvSetupMilestone(),
|
EnvSetupMilestone(),
|
||||||
SecretManagementMilestone(),
|
SecretManagementMilestone(),
|
||||||
DatabaseCreationMilestone(),
|
|
||||||
DockerBuildMilestone(),
|
DockerBuildMilestone(),
|
||||||
|
DatabaseCreationMilestone(),
|
||||||
ClusterLifecycleMilestone(),
|
ClusterLifecycleMilestone(),
|
||||||
InitializationScriptsMilestone(),
|
InitializationScriptsMilestone(),
|
||||||
KerberosMilestone(),
|
KerberosMilestone(),
|
||||||
@ -5768,8 +5826,8 @@ def _prepare_k3s_pipeline(
|
|||||||
_log(f" k3s_token: {'detected' if k3s_token else '(not detected)'}\n\n")
|
_log(f" k3s_token: {'detected' if k3s_token else '(not detected)'}\n\n")
|
||||||
|
|
||||||
# Load config to resolve namespace and secrets for pipeline tfvars
|
# Load config to resolve namespace and secrets for pipeline tfvars
|
||||||
_log("==> Loading installer config...\n")
|
_log("==> Loading knoe config...\n")
|
||||||
installer = ProleConsoleInstaller(controller, str(cfg_path))
|
knoe = ProleConsoleInstaller(controller, str(cfg_path))
|
||||||
try:
|
try:
|
||||||
existing_inputs = knoe._load_inputs_from_cfg()
|
existing_inputs = knoe._load_inputs_from_cfg()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@ -85,7 +85,23 @@ class Milestone(ABC):
|
|||||||
namespace = (state.inputs.get("init_password.db_namespace", "") or "").strip()
|
namespace = (state.inputs.get("init_password.db_namespace", "") or "").strip()
|
||||||
env["NAMESPACE"] = namespace or "default"
|
env["NAMESPACE"] = namespace or "default"
|
||||||
|
|
||||||
# Paths
|
# Paths — prefer the env-specific conf subdir (e.g. conf/service/) so that
|
||||||
|
# init scripts source the correct prole.cfg and don't fall back to the
|
||||||
|
# conf/prole.cfg symlink which may point to a different cluster env.
|
||||||
|
# Priority: (1) inherited PROLE_CONF from parent shell when it points to a
|
||||||
|
# valid env-specific subdir, (2) cluster_env-derived subdir, (3) stored value.
|
||||||
|
_inherited_conf = os.environ.get("PROLE_CONF", "")
|
||||||
|
_cluster_env_for_conf = state.inputs.get("init_cluster.cluster_env", "")
|
||||||
|
_env_conf_dir = (
|
||||||
|
Path(project_root) / "conf" / _cluster_env_for_conf
|
||||||
|
if _cluster_env_for_conf
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
if _inherited_conf and (Path(_inherited_conf) / "prole.cfg").exists():
|
||||||
|
env["PROLE_CONF"] = _inherited_conf
|
||||||
|
elif _env_conf_dir and _env_conf_dir.is_dir():
|
||||||
|
env["PROLE_CONF"] = str(_env_conf_dir)
|
||||||
|
else:
|
||||||
env["PROLE_CONF"] = state.inputs.get(
|
env["PROLE_CONF"] = state.inputs.get(
|
||||||
"env_setup.PROLE_CONF", str(project_root / "conf")
|
"env_setup.PROLE_CONF", str(project_root / "conf")
|
||||||
)
|
)
|
||||||
|
|||||||
@ -348,10 +348,10 @@ class ProleInstaller(
|
|||||||
("Dependencies", "deps_summary"),
|
("Dependencies", "deps_summary"),
|
||||||
("Network", "network_scan"),
|
("Network", "network_scan"),
|
||||||
("System Environment", "env_setup"),
|
("System Environment", "env_setup"),
|
||||||
("Cluster Environment", "init_cluster"),
|
|
||||||
("Cluster Nodes", "cluster_nodes"),
|
|
||||||
("Database Options", "database_options"),
|
("Database Options", "database_options"),
|
||||||
("Docker Build", "init_db_build"),
|
("Docker Build", "init_db_build"),
|
||||||
|
("Cluster Environment", "init_cluster"),
|
||||||
|
("Cluster Nodes", "cluster_nodes"),
|
||||||
("Database Creation", "init_password"),
|
("Database Creation", "init_password"),
|
||||||
("Initialization Scripts", "init_scripts"),
|
("Initialization Scripts", "init_scripts"),
|
||||||
("Kerberos Authentication", "kerberos_config"),
|
("Kerberos Authentication", "kerberos_config"),
|
||||||
@ -655,7 +655,7 @@ class ProleInstaller(
|
|||||||
self.db_password = tk.StringVar()
|
self.db_password = tk.StringVar()
|
||||||
self.db_password_confirm = tk.StringVar()
|
self.db_password_confirm = tk.StringVar()
|
||||||
self.namespace_owner = self._get_local_owner()
|
self.namespace_owner = self._get_local_owner()
|
||||||
self.db_namespace = tk.StringVar(value=self._initial_namespace())
|
self.db_namespace = tk.StringVar(value=self._initial_db_namespace())
|
||||||
try:
|
try:
|
||||||
_ns_from_cfg = (
|
_ns_from_cfg = (
|
||||||
(self.prole_cfg_data.get("Global", {}) or {})
|
(self.prole_cfg_data.get("Global", {}) or {})
|
||||||
@ -663,7 +663,21 @@ class ProleInstaller(
|
|||||||
.strip()
|
.strip()
|
||||||
)
|
)
|
||||||
if _ns_from_cfg:
|
if _ns_from_cfg:
|
||||||
self.db_namespace.set(self._ensure_namespace_prefix(_ns_from_cfg))
|
base = self._ensure_namespace_prefix(_ns_from_cfg)
|
||||||
|
ver = ""
|
||||||
|
try:
|
||||||
|
ver = (self.controller.get_prole_db_version() or "").strip()
|
||||||
|
except Exception:
|
||||||
|
ver = ""
|
||||||
|
if ver:
|
||||||
|
ver_ns = self._sanitize_namespace(ver.replace(".", "-"))
|
||||||
|
base_ns = self._sanitize_namespace(base)
|
||||||
|
if base_ns.endswith(f"-{ver_ns}"):
|
||||||
|
self.db_namespace.set(base_ns)
|
||||||
|
else:
|
||||||
|
self.db_namespace.set(self._sanitize_namespace(f"{base_ns}-{ver_ns}"))
|
||||||
|
else:
|
||||||
|
self.db_namespace.set(self._sanitize_namespace(base))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
self.db_host_port = tk.StringVar(value="5432")
|
self.db_host_port = tk.StringVar(value="5432")
|
||||||
|
|||||||
@ -1420,6 +1420,7 @@ class DatabaseScreenMixin:
|
|||||||
# Use $PROLE_HOME/build for Docker build context
|
# Use $PROLE_HOME/build for Docker build context
|
||||||
# This avoids issues with PyInstaller's temporary _MEIPASS directory
|
# This avoids issues with PyInstaller's temporary _MEIPASS directory
|
||||||
prole_home = resolve_prole_home()
|
prole_home = resolve_prole_home()
|
||||||
|
env_key = self._cluster_env_key()
|
||||||
mode_key = _deployment_mode_from_env(env_key) or "default"
|
mode_key = _deployment_mode_from_env(env_key) or "default"
|
||||||
build_dir = prole_home / "build" / mode_key / "knoe-db"
|
build_dir = prole_home / "build" / mode_key / "knoe-db"
|
||||||
build_dir.mkdir(parents=True, exist_ok=True)
|
build_dir.mkdir(parents=True, exist_ok=True)
|
||||||
@ -1442,7 +1443,6 @@ class DatabaseScreenMixin:
|
|||||||
pub_key = pub_key_path.read_text().strip()
|
pub_key = pub_key_path.read_text().strip()
|
||||||
|
|
||||||
username = self.db_username.get()
|
username = self.db_username.get()
|
||||||
env_key = self._cluster_env_key()
|
|
||||||
cmd = ["docker", "build", "--progress=plain"]
|
cmd = ["docker", "build", "--progress=plain"]
|
||||||
cmd.extend(get_docker_build_platform_args(env_key))
|
cmd.extend(get_docker_build_platform_args(env_key))
|
||||||
cmd += [
|
cmd += [
|
||||||
|
|||||||
@ -615,22 +615,48 @@ class DockerScreenMixin:
|
|||||||
raise Exception(f"Unknown environment: {env}")
|
raise Exception(f"Unknown environment: {env}")
|
||||||
|
|
||||||
def create_or_recreate_k3d_dev_cluster(self, cluster_name="knoe-dev-cluster"):
|
def create_or_recreate_k3d_dev_cluster(self, cluster_name="knoe-dev-cluster"):
|
||||||
"""Create or restart local k3d cluster and wire it to the chosen registry."""
|
"""Create or restart local k3d cluster and wire it to the local k3d registry."""
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["k3d", "cluster", "list"], capture_output=True, text=True
|
["k3d", "cluster", "list"], capture_output=True, text=True
|
||||||
)
|
)
|
||||||
if cluster_name in (result.stdout or ""):
|
if cluster_name in (result.stdout or ""):
|
||||||
subprocess.run(["k3d", "cluster", "delete", cluster_name], check=True)
|
subprocess.run(["k3d", "cluster", "delete", cluster_name], check=True)
|
||||||
|
|
||||||
# Determine registry integration args
|
# Always ensure the local k3d registry exists before creating the cluster so
|
||||||
reg_args = []
|
# that we can wire it via --registry-use. Using --registry-use (rather than
|
||||||
if getattr(self, "registry_url", None):
|
# --registry-create) is required when the registry container already exists,
|
||||||
# If using the local k3d registry, we want to create or use it
|
# which is the common case after the first install run.
|
||||||
if self.registry_url.startswith("localhost:5000"):
|
reg_name = "prole-registry"
|
||||||
# Creating with --registry-create ensures it's available and integrated
|
registry_container = f"k3d-{reg_name}"
|
||||||
reg_args = ["--registry-create", f"prole-registry:0.0.0.0:5000"]
|
lst = subprocess.run(
|
||||||
else:
|
["k3d", "registry", "list"], capture_output=True, text=True
|
||||||
reg_args = ["--registry-use", self.registry_url]
|
)
|
||||||
|
if registry_container not in (lst.stdout or "") and reg_name not in (
|
||||||
|
lst.stdout or ""
|
||||||
|
):
|
||||||
|
subprocess.run(
|
||||||
|
["k3d", "registry", "create", reg_name, "--port", "0.0.0.0:5000"],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
# Ensure the registry container is actually running
|
||||||
|
running = subprocess.run(
|
||||||
|
[
|
||||||
|
"docker",
|
||||||
|
"ps",
|
||||||
|
"--filter",
|
||||||
|
f"name={registry_container}",
|
||||||
|
"--format",
|
||||||
|
"{{.Names}}",
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if not (running.stdout or "").strip():
|
||||||
|
subprocess.run(["docker", "start", registry_container], check=True)
|
||||||
|
|
||||||
|
# Wire the cluster to the registry so containerd inside each node resolves
|
||||||
|
# k3d-prole-registry.localhost:5000 correctly.
|
||||||
|
reg_args = ["--registry-use", f"{registry_container}:5000"]
|
||||||
|
|
||||||
prole_data = str(self._resolve_env_dir("PROLE_DATA", "data"))
|
prole_data = str(self._resolve_env_dir("PROLE_DATA", "data"))
|
||||||
volume_args = _k3d_prole_data_volume_args(prole_data)
|
volume_args = _k3d_prole_data_volume_args(prole_data)
|
||||||
|
|||||||
@ -61,9 +61,9 @@ CERT_MANAGER_MANIFEST_URL=${CERT_MANAGER_MANIFEST_URL:-}
|
|||||||
CERT_MANAGER_FALLBACK_VERSION=${CERT_MANAGER_FALLBACK_VERSION:-1.19.3}
|
CERT_MANAGER_FALLBACK_VERSION=${CERT_MANAGER_FALLBACK_VERSION:-1.19.3}
|
||||||
|
|
||||||
# Protected storage requirements (k3s only)
|
# Protected storage requirements (k3s only)
|
||||||
PROLE_CNPG_STORAGE_CLASS=${PROLE_CNPG_STORAGE_CLASS:-prole-iscsi}
|
PROLE_CNPG_STORAGE_CLASS=${PROLE_CNPG_STORAGE_CLASS:-synology-iscsi}
|
||||||
PROLE_PROTECTED_DATA_PATH=${PROLE_PROTECTED_DATA_PATH:-/prole/d001/data}
|
PROLE_PROTECTED_DATA_PATH=${PROLE_PROTECTED_DATA_PATH:-/synology/d001/data}
|
||||||
PROLE_PROTECTED_WAL_PATH=${PROLE_PROTECTED_WAL_PATH:-/prole/d001/wal}
|
PROLE_PROTECTED_WAL_PATH=${PROLE_PROTECTED_WAL_PATH:-/synology/d001/wal}
|
||||||
|
|
||||||
if [[ "$ACTION" != "deploy" && "$ACTION" != "rollout" && "$ACTION" != "force-rollout" ]]; then
|
if [[ "$ACTION" != "deploy" && "$ACTION" != "rollout" && "$ACTION" != "force-rollout" ]]; then
|
||||||
if [[ -n "${2:-}" ]]; then
|
if [[ -n "${2:-}" ]]; then
|
||||||
@ -225,9 +225,9 @@ validate_cnpg_manifest_storage() {
|
|||||||
wal_sc="$v"
|
wal_sc="$v"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [[ -n "$block" && "$line" =~ prole\.storage/role: ]]; then
|
if [[ -n "$block" && "$line" =~ synology\.storage/role: ]]; then
|
||||||
local r
|
local r
|
||||||
r=$(printf '%s' "$line" | sed -E 's/^.*prole\.storage\/role:[[:space:]]*//; s/[[:space:]]+$//')
|
r=$(printf '%s' "$line" | sed -E 's/^.*synology\.storage\/role:[[:space:]]*//; s/[[:space:]]+$//')
|
||||||
if [[ "$block" == "storage" && -z "$data_role" ]]; then
|
if [[ "$block" == "storage" && -z "$data_role" ]]; then
|
||||||
data_role="$r"
|
data_role="$r"
|
||||||
elif [[ "$block" == "wal" && -z "$wal_role" ]]; then
|
elif [[ "$block" == "wal" && -z "$wal_role" ]]; then
|
||||||
@ -243,7 +243,7 @@ validate_cnpg_manifest_storage() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$data_role" != "data" || "$wal_role" != "wal" ]]; then
|
if [[ "$data_role" != "data" || "$wal_role" != "wal" ]]; then
|
||||||
echo "ERROR: CNPG Cluster manifest must include explicit PV selectors for Prole storage (prole.storage/role=data and prole.storage/role=wal)." >&2
|
echo "ERROR: CNPG Cluster manifest must include explicit PV selectors for Prole storage (synology.storage/role=data and synology.storage/role=wal)." >&2
|
||||||
echo "Got selector roles: data='${data_role:-<missing>}', wal='${wal_role:-<missing>}'" >&2
|
echo "Got selector roles: data='${data_role:-<missing>}', wal='${wal_role:-<missing>}'" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -267,8 +267,8 @@ validate_cnpg_runtime_storage() {
|
|||||||
local data_sc wal_sc data_role wal_role
|
local data_sc wal_sc data_role wal_role
|
||||||
data_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.storageClassName // empty')
|
data_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.storageClassName // empty')
|
||||||
wal_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.storageClassName // empty')
|
wal_sc=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.storageClassName // empty')
|
||||||
data_role=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.selector.matchLabels["prole.storage/role"] // empty')
|
data_role=$(printf '%s' "$cluster_json" | jq -r '.spec.storage.pvcTemplate.selector.matchLabels["synology.storage/role"] // empty')
|
||||||
wal_role=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.selector.matchLabels["prole.storage/role"] // empty')
|
wal_role=$(printf '%s' "$cluster_json" | jq -r '.spec.walStorage.pvcTemplate.selector.matchLabels["synology.storage/role"] // empty')
|
||||||
|
|
||||||
if [[ "$data_sc" != "$sc" || "$wal_sc" != "$sc" ]]; then
|
if [[ "$data_sc" != "$sc" || "$wal_sc" != "$sc" ]]; then
|
||||||
echo "ERROR: Live CNPG Cluster storageClassName must be '${sc}' for both data and walStorage (got data='${data_sc:-<missing>}', wal='${wal_sc:-<missing>}')." >&2
|
echo "ERROR: Live CNPG Cluster storageClassName must be '${sc}' for both data and walStorage (got data='${data_sc:-<missing>}', wal='${wal_sc:-<missing>}')." >&2
|
||||||
@ -326,9 +326,9 @@ validate_cnpg_runtime_storage() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
case "$pv_path" in
|
case "$pv_path" in
|
||||||
/prole/*) ;;
|
/synology/*) ;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: Bound PV '${pv}' path '${pv_path}' is not under /prole/. Refusing deployment." >&2
|
echo "ERROR: Bound PV '${pv}' path '${pv_path}' is not under /synology/. Refusing deployment." >&2
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -1168,6 +1168,81 @@ apply_prole_manifest_file() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_prole_k3s_registry_host_for_cache() {
|
||||||
|
# Best-effort host:port for the k3s registry, used as an optional cache source in k3d mode.
|
||||||
|
# Intentionally avoids k3d registry names and localhost-ish endpoints.
|
||||||
|
local r="${PROLE_K3S_REGISTRY:-${K3S_REGISTRY_HOST:-${LOCAL_REGISTRY_INTERNAL:-${LOCAL_REGISTRY:-}}}}"
|
||||||
|
|
||||||
|
r="${r#http://}"
|
||||||
|
r="${r#https://}"
|
||||||
|
|
||||||
|
case "${r}" in
|
||||||
|
"")
|
||||||
|
r="myrddin.prole.org:5000"
|
||||||
|
;;
|
||||||
|
localhost:5000|127.0.0.1:5000|*.localhost|*.localhost:5000)
|
||||||
|
r="myrddin.prole.org:5000"
|
||||||
|
;;
|
||||||
|
k3d-*|*/k3d-*)
|
||||||
|
r="myrddin.prole.org:5000"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf '%s' "$r"
|
||||||
|
}
|
||||||
|
|
||||||
|
_docker_build_knoe_db_image() {
|
||||||
|
# Build the knoe-db image with BuildKit and optional cache source.
|
||||||
|
# Args: <tag> <context_dir> [cache_ref]
|
||||||
|
local tag="$1"
|
||||||
|
local context_dir="$2"
|
||||||
|
local cache_ref="${3:-}"
|
||||||
|
|
||||||
|
local ssh_args=()
|
||||||
|
if [[ -n "${SSH_AUTH_SOCK:-}" ]]; then
|
||||||
|
ssh_args+=(--ssh default)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker buildx version >/dev/null 2>&1; then
|
||||||
|
# Prefer an isolated docker-container builder to avoid host snapshot/cache corruption.
|
||||||
|
local builder_name="${PROLE_BUILDX_BUILDER:-prole-buildkit}"
|
||||||
|
if ! docker buildx inspect "$builder_name" >/dev/null 2>&1; then
|
||||||
|
docker buildx create --name "$builder_name" --driver docker-container --use >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
docker buildx use "$builder_name" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
local cache_args=()
|
||||||
|
if [[ -n "$cache_ref" ]]; then
|
||||||
|
cache_args+=(--cache-from "type=registry,ref=${cache_ref}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker buildx build \
|
||||||
|
--pull \
|
||||||
|
--tag "$tag" \
|
||||||
|
--load \
|
||||||
|
"${ssh_args[@]}" \
|
||||||
|
"${cache_args[@]}" \
|
||||||
|
"$context_dir"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback to docker build (still BuildKit-enabled); cache-from here only works if the cache image is present locally.
|
||||||
|
local cache_from_args=()
|
||||||
|
if [[ -n "$cache_ref" ]]; then
|
||||||
|
docker pull "$cache_ref" >/dev/null 2>&1 || true
|
||||||
|
cache_from_args+=(--cache-from "$cache_ref")
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOCKER_BUILDKIT=1 docker build \
|
||||||
|
--pull \
|
||||||
|
"${ssh_args[@]}" \
|
||||||
|
"${cache_from_args[@]}" \
|
||||||
|
-t "$tag" \
|
||||||
|
"$context_dir"
|
||||||
|
}
|
||||||
|
|
||||||
_push_to_k3s_registry() {
|
_push_to_k3s_registry() {
|
||||||
local image="$1"
|
local image="$1"
|
||||||
local push_host="${LOCAL_REGISTRY:-${LOCAL_REGISTRY_INTERNAL:-myrddin.prole.org:5000}}"
|
local push_host="${LOCAL_REGISTRY:-${LOCAL_REGISTRY_INTERNAL:-myrddin.prole.org:5000}}"
|
||||||
@ -1310,6 +1385,7 @@ _ensure_prole_db_image() {
|
|||||||
image=$(resolve_cnpg_image "$image")
|
image=$(resolve_cnpg_image "$image")
|
||||||
local prole_db_dir="${PROLE_HOME:-$SCRIPT_DIR/..}/prole-db"
|
local prole_db_dir="${PROLE_HOME:-$SCRIPT_DIR/..}/prole-db"
|
||||||
local plain_image="${image##*/}" # e.g. knoe-db:18-088
|
local plain_image="${image##*/}" # e.g. knoe-db:18-088
|
||||||
|
local k3s_cache_ref=""
|
||||||
|
|
||||||
if [[ "${PROLE_MODE:-}" == "k3s" ]]; then
|
if [[ "${PROLE_MODE:-}" == "k3s" ]]; then
|
||||||
echo "Pre-flight: ensuring image '$image' is available in k3s registry/import path ..."
|
echo "Pre-flight: ensuring image '$image' is available in k3s registry/import path ..."
|
||||||
@ -1321,6 +1397,13 @@ _ensure_prole_db_image() {
|
|||||||
fi
|
fi
|
||||||
cluster_name="${cluster_name:-knoe-dev-cluster}"
|
cluster_name="${cluster_name:-knoe-dev-cluster}"
|
||||||
|
|
||||||
|
# In k3d mode, optionally consult the k3s registry as a cache/source of truth before building.
|
||||||
|
local k3s_host
|
||||||
|
k3s_host=$(_prole_k3s_registry_host_for_cache)
|
||||||
|
if [[ -n "${k3s_host:-}" ]]; then
|
||||||
|
k3s_cache_ref="${k3s_host}/${plain_image}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Pre-flight: verifying image '$image' is available in k3d cluster '$cluster_name' ..."
|
echo "Pre-flight: verifying image '$image' is available in k3d cluster '$cluster_name' ..."
|
||||||
|
|
||||||
# Step 1: check if already present in k3d containerd with matching digest
|
# Step 1: check if already present in k3d containerd with matching digest
|
||||||
@ -1393,6 +1476,17 @@ _ensure_prole_db_image() {
|
|||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Step 3b (k3d only): try to reuse a previously-built image from the k3s registry.
|
||||||
|
if [[ "${PROLE_MODE:-}" == "k3d" && -n "${k3s_cache_ref:-}" && "${k3s_cache_ref}" != "${image}" ]]; then
|
||||||
|
if docker image inspect "$k3s_cache_ref" >/dev/null 2>&1 || docker pull "$k3s_cache_ref" >/dev/null 2>&1; then
|
||||||
|
echo " ✓ Found '$plain_image' in k3s registry (${k3s_cache_ref}); re-tagging for k3d as '$image' ..."
|
||||||
|
docker tag "$k3s_cache_ref" "$image" 2>/dev/null || true
|
||||||
|
_push_to_k3d_registry "$image" "$cluster_name"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
echo " (cache) '$plain_image' not present in k3s registry (${k3s_cache_ref}); building locally ..."
|
||||||
|
fi
|
||||||
|
|
||||||
# Step 4: image not found anywhere — build from source then push + import
|
# Step 4: image not found anywhere — build from source then push + import
|
||||||
if [[ ! -f "$prole_db_dir/Dockerfile" ]]; then
|
if [[ ! -f "$prole_db_dir/Dockerfile" ]]; then
|
||||||
echo "ERROR: Dockerfile not found in '$prole_db_dir'; cannot build knoe-db image." >&2
|
echo "ERROR: Dockerfile not found in '$prole_db_dir'; cannot build knoe-db image." >&2
|
||||||
@ -1404,7 +1498,7 @@ _ensure_prole_db_image() {
|
|||||||
echo " Image '$image' not found in k3d, Docker daemon, or docker-import dir."
|
echo " Image '$image' not found in k3d, Docker daemon, or docker-import dir."
|
||||||
fi
|
fi
|
||||||
echo " Building knoe-db image from '$prole_db_dir' ..."
|
echo " Building knoe-db image from '$prole_db_dir' ..."
|
||||||
if ! docker build -t "$plain_image" "$prole_db_dir"; then
|
if ! _docker_build_knoe_db_image "$plain_image" "$prole_db_dir" "${k3s_cache_ref:-}"; then
|
||||||
echo "ERROR: docker build failed for image '$plain_image'." >&2
|
echo "ERROR: docker build failed for image '$plain_image'." >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -2148,14 +2242,14 @@ reset_and_reinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycle_released_prole_iscsi_pvs() {
|
recycle_released_prole_iscsi_pvs() {
|
||||||
# StorageClass `prole-iscsi` uses `Retain` PV reclaim policy. After a CNPG reset, PVs can remain
|
# StorageClass `synology-iscsi` uses `Retain` PV reclaim policy. After a CNPG reset, PVs can remain
|
||||||
# in `Released` with a stale `claimRef`, which prevents new PVCs (same names) from binding.
|
# in `Released` with a stale `claimRef`, which prevents new PVCs (same names) from binding.
|
||||||
# In that case, CNPG init jobs remain `Pending` with "didn't find available persistent volumes".
|
# In that case, CNPG init jobs remain `Pending` with "didn't find available persistent volumes".
|
||||||
echo "Recycling Released prole-iscsi PVs (clearing stale claimRefs) for namespace '$NAMESPACE' ..."
|
echo "Recycling Released synology-iscsi PVs (clearing stale claimRefs) for namespace '$NAMESPACE' ..."
|
||||||
local pvs
|
local pvs
|
||||||
pvs=$(kubectl get pv -o json \
|
pvs=$(kubectl get pv -o json \
|
||||||
| jq -r --arg ns "$NAMESPACE" '.items[]
|
| jq -r --arg ns "$NAMESPACE" '.items[]
|
||||||
| select(.spec.storageClassName == "prole-iscsi")
|
| select(.spec.storageClassName == "synology-iscsi")
|
||||||
| select(.status.phase == "Released")
|
| select(.status.phase == "Released")
|
||||||
| select((.spec.claimRef.namespace // "") == $ns)
|
| select((.spec.claimRef.namespace // "") == $ns)
|
||||||
| .metadata.name' 2>/dev/null || true)
|
| .metadata.name' 2>/dev/null || true)
|
||||||
|
|||||||
@ -60,7 +60,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
GARAGE_FILES=(
|
GARAGE_FILES=(
|
||||||
"$GARAGE_MANIFEST_DIR/storageclass-prole-iscsi.yaml"
|
"$GARAGE_MANIFEST_DIR/storageclass-synology-iscsi.yaml"
|
||||||
"$GARAGE_MANIFEST_DIR/iscsi-pvs.yaml"
|
"$GARAGE_MANIFEST_DIR/iscsi-pvs.yaml"
|
||||||
"$GARAGE_MANIFEST_DIR/garage-configmap.yaml"
|
"$GARAGE_MANIFEST_DIR/garage-configmap.yaml"
|
||||||
"$GARAGE_MANIFEST_DIR/garage-statefulset.yaml"
|
"$GARAGE_MANIFEST_DIR/garage-statefulset.yaml"
|
||||||
@ -133,7 +133,7 @@ k3d_cleanup_pending_pvc() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
selector=$(kubectl get pvc data-garage-0 -n "$NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
selector=$(kubectl get pvc data-garage-0 -n "$NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
||||||
if printf '%s' "$selector" | grep -q "prole.storage/"; then
|
if printf '%s' "$selector" | grep -q "synology.storage/"; then
|
||||||
echo "Removing pending Garage PVC with selector for k3d local-path ..."
|
echo "Removing pending Garage PVC with selector for k3d local-path ..."
|
||||||
kubectl delete statefulset "$GARAGE_NAME" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete statefulset "$GARAGE_NAME" -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
kubectl delete pvc data-garage-0 -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete pvc data-garage-0 -n "$NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
@ -283,7 +283,7 @@ dump_debug() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycle_released_prole_iscsi_pv_for_pvc() {
|
recycle_released_prole_iscsi_pv_for_pvc() {
|
||||||
# StorageClass `prole-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
# StorageClass `synology-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
||||||
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
||||||
local ns="$1"
|
local ns="$1"
|
||||||
local pvc="$2"
|
local pvc="$2"
|
||||||
@ -301,7 +301,7 @@ recycle_released_prole_iscsi_pv_for_pvc() {
|
|||||||
|
|
||||||
local pv sc rp phase claim_ns claim_name claim_uid
|
local pv sc rp phase claim_ns claim_name claim_uid
|
||||||
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
||||||
[[ "$sc" == "prole-iscsi" ]] || continue
|
[[ "$sc" == "synology-iscsi" ]] || continue
|
||||||
[[ "$rp" == "Retain" ]] || continue
|
[[ "$rp" == "Retain" ]] || continue
|
||||||
[[ "$phase" == "Released" ]] || continue
|
[[ "$phase" == "Released" ]] || continue
|
||||||
[[ "$claim_ns" == "$ns" ]] || continue
|
[[ "$claim_ns" == "$ns" ]] || continue
|
||||||
@ -322,7 +322,7 @@ wait_ready() {
|
|||||||
|
|
||||||
local initial_timeout="${PVC_REPAIR_WAIT_TIMEOUT:-30s}"
|
local initial_timeout="${PVC_REPAIR_WAIT_TIMEOUT:-30s}"
|
||||||
if ! kubectl rollout status statefulset/$GARAGE_NAME -n "$NAMESPACE" --timeout="$initial_timeout"; then
|
if ! kubectl rollout status statefulset/$GARAGE_NAME -n "$NAMESPACE" --timeout="$initial_timeout"; then
|
||||||
echo "WARN: Garage not ready after $initial_timeout; checking for Released prole-iscsi PVs with stale claimRefs ..." >&2
|
echo "WARN: Garage not ready after $initial_timeout; checking for Released synology-iscsi PVs with stale claimRefs ..." >&2
|
||||||
recycle_released_prole_iscsi_pv_for_pvc "$NAMESPACE" "data-garage-0" || true
|
recycle_released_prole_iscsi_pv_for_pvc "$NAMESPACE" "data-garage-0" || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@ -313,8 +313,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: merlin-local-iscsi-${volume_id}-prometheus
|
name: merlin-local-iscsi-${volume_id}-prometheus
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: prometheus
|
synology.storage/role: prometheus
|
||||||
prole.storage/volume: ${volume_id}
|
synology.storage/volume: ${volume_id}
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 30Gi
|
storage: 30Gi
|
||||||
@ -339,8 +339,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: merlin-local-iscsi-${volume_id}-alertmanager
|
name: merlin-local-iscsi-${volume_id}-alertmanager
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: alertmanager
|
synology.storage/role: alertmanager
|
||||||
prole.storage/volume: ${volume_id}
|
synology.storage/volume: ${volume_id}
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
@ -365,8 +365,8 @@ kind: PersistentVolume
|
|||||||
metadata:
|
metadata:
|
||||||
name: merlin-local-iscsi-${volume_id}-grafana
|
name: merlin-local-iscsi-${volume_id}-grafana
|
||||||
labels:
|
labels:
|
||||||
prole.storage/role: grafana
|
synology.storage/role: grafana
|
||||||
prole.storage/volume: ${volume_id}
|
synology.storage/volume: ${volume_id}
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
|
|||||||
@ -424,9 +424,9 @@ apply_k8s() {
|
|||||||
fi
|
fi
|
||||||
if [[ "$use_statefulset" == "1" ]]; then
|
if [[ "$use_statefulset" == "1" ]]; then
|
||||||
# Ensure storage class and PVs exist for k3s
|
# Ensure storage class and PVs exist for k3s
|
||||||
if [[ -f "$SCRIPT_DIR/../k8s/prole/storageclass-prole-iscsi.yaml" ]]; then
|
if [[ -f "$SCRIPT_DIR/../k8s/prole/storageclass-synology-iscsi.yaml" ]]; then
|
||||||
echo "Applying StorageClass 'prole-iscsi' ..."
|
echo "Applying StorageClass 'synology-iscsi' ..."
|
||||||
kubectl apply -f "$SCRIPT_DIR/../k8s/prole/storageclass-prole-iscsi.yaml"
|
kubectl apply -f "$SCRIPT_DIR/../k8s/prole/storageclass-synology-iscsi.yaml"
|
||||||
fi
|
fi
|
||||||
if [[ -f "$SCRIPT_DIR/../k8s/prole/iscsi-pvs.yaml" ]]; then
|
if [[ -f "$SCRIPT_DIR/../k8s/prole/iscsi-pvs.yaml" ]]; then
|
||||||
echo "Applying iSCSI PersistentVolumes ..."
|
echo "Applying iSCSI PersistentVolumes ..."
|
||||||
@ -476,7 +476,7 @@ k3d_cleanup_pending_openbao_pvc() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
selector=$(kubectl get pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
selector=$(kubectl get pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" -o jsonpath='{.spec.selector}' 2>/dev/null || true)
|
||||||
if printf '%s' "$selector" | grep -q "prole.storage/"; then
|
if printf '%s' "$selector" | grep -q "synology.storage/"; then
|
||||||
echo "Removing pending OpenBao PVC with selector for k3d local-path ..."
|
echo "Removing pending OpenBao PVC with selector for k3d local-path ..."
|
||||||
kubectl delete statefulset "$OPENBAO_NAME" -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete statefulset "$OPENBAO_NAME" -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
kubectl delete pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
kubectl delete pvc data-openbao-0 -n "$OPENBAO_RESOURCE_NAMESPACE" --ignore-not-found >/dev/null 2>&1 || true
|
||||||
@ -484,7 +484,7 @@ k3d_cleanup_pending_openbao_pvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recycle_released_prole_iscsi_pv_for_pvc() {
|
recycle_released_prole_iscsi_pv_for_pvc() {
|
||||||
# StorageClass `prole-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
# StorageClass `synology-iscsi` uses `Retain` PV reclaim policy. On restart, PVs can remain
|
||||||
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
# in `Released` with a stale `claimRef`, which prevents a same-named PVC from binding.
|
||||||
local ns="$1"
|
local ns="$1"
|
||||||
local pvc="$2"
|
local pvc="$2"
|
||||||
@ -502,7 +502,7 @@ recycle_released_prole_iscsi_pv_for_pvc() {
|
|||||||
|
|
||||||
local pv sc rp phase claim_ns claim_name claim_uid
|
local pv sc rp phase claim_ns claim_name claim_uid
|
||||||
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
while IFS=$'\t' read -r pv sc rp phase claim_ns claim_name claim_uid; do
|
||||||
[[ "$sc" == "prole-iscsi" ]] || continue
|
[[ "$sc" == "synology-iscsi" ]] || continue
|
||||||
[[ "$rp" == "Retain" ]] || continue
|
[[ "$rp" == "Retain" ]] || continue
|
||||||
[[ "$phase" == "Released" ]] || continue
|
[[ "$phase" == "Released" ]] || continue
|
||||||
[[ "$claim_ns" == "$ns" ]] || continue
|
[[ "$claim_ns" == "$ns" ]] || continue
|
||||||
@ -543,13 +543,13 @@ wait_for_openbao() {
|
|||||||
echo "Waiting for OpenBao to become ready in namespace '$wait_ns' ..."
|
echo "Waiting for OpenBao to become ready in namespace '$wait_ns' ..."
|
||||||
if kubectl get statefulset/$OPENBAO_NAME -n "$wait_ns" >/dev/null 2>&1; then
|
if kubectl get statefulset/$OPENBAO_NAME -n "$wait_ns" >/dev/null 2>&1; then
|
||||||
if ! kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
if ! kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
||||||
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released prole-iscsi PVs with stale claimRefs ..." >&2
|
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released synology-iscsi PVs with stale claimRefs ..." >&2
|
||||||
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
||||||
fi
|
fi
|
||||||
kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
kubectl rollout status statefulset/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
||||||
else
|
else
|
||||||
if ! kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
if ! kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout="$initial_timeout"; then
|
||||||
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released prole-iscsi PVs with stale claimRefs ..." >&2
|
echo "WARN: OpenBao not ready after $initial_timeout; checking for Released synology-iscsi PVs with stale claimRefs ..." >&2
|
||||||
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
recycle_released_prole_iscsi_pv_for_pvc "$wait_ns" "data-openbao-0" || true
|
||||||
fi
|
fi
|
||||||
kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
kubectl rollout status deploy/$OPENBAO_NAME -n "$wait_ns" --timeout=${ROLLOUT_TIMEOUT:-300s}
|
||||||
|
|||||||
@ -488,7 +488,7 @@ fi
|
|||||||
|
|
||||||
# Safety: prole.cfg must override any pre-set PROLE_MODE from the environment.
|
# Safety: prole.cfg must override any pre-set PROLE_MODE from the environment.
|
||||||
# Otherwise a leaked PROLE_MODE=k3d can trigger k3d-only manifest stripping (e.g., removing
|
# Otherwise a leaked PROLE_MODE=k3d can trigger k3d-only manifest stripping (e.g., removing
|
||||||
# `storageClassName: prole-iscsi`) while targeting a k3s cluster.
|
# `storageClassName: synology-iscsi`) while targeting a k3s cluster.
|
||||||
_prole_cfg_mode_hint=""
|
_prole_cfg_mode_hint=""
|
||||||
if [[ -n "${prole_mode:-}" ]]; then
|
if [[ -n "${prole_mode:-}" ]]; then
|
||||||
_prole_cfg_mode_hint=$(prole_normalize_mode "$prole_mode")
|
_prole_cfg_mode_hint=$(prole_normalize_mode "$prole_mode")
|
||||||
|
|||||||
@ -65,7 +65,7 @@ def _strip_blocks(text: str) -> str:
|
|||||||
break
|
break
|
||||||
block_lines.append(next_line)
|
block_lines.append(next_line)
|
||||||
j += 1
|
j += 1
|
||||||
if any("prole.storage/" in bl for bl in block_lines):
|
if any("synology.storage/" in bl for bl in block_lines):
|
||||||
i = j
|
i = j
|
||||||
continue
|
continue
|
||||||
out.extend(block_lines)
|
out.extend(block_lines)
|
||||||
@ -78,7 +78,7 @@ def _strip_blocks(text: str) -> str:
|
|||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if stripped.startswith("storageClassName:") and "prole-iscsi" in stripped:
|
if stripped.startswith("storageClassName:") and "synology-iscsi" in stripped:
|
||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
1
modes/k3d/conf/postgresql/.version
Normal file
1
modes/k3d/conf/postgresql/.version
Normal file
@ -0,0 +1 @@
|
|||||||
|
18
|
||||||
1
modes/k3d/prole-db/.version
Normal file
1
modes/k3d/prole-db/.version
Normal file
@ -0,0 +1 @@
|
|||||||
|
3
|
||||||
@ -1 +1 @@
|
|||||||
138
|
140
|
||||||
17
prole.sh
17
prole.sh
@ -145,15 +145,19 @@ err_msg() {
|
|||||||
|
|
||||||
load_prole_cfg() {
|
load_prole_cfg() {
|
||||||
local cfg="${1:-$PROLE_CFG_DEFAULT}"
|
local cfg="${1:-$PROLE_CFG_DEFAULT}"
|
||||||
|
# Set PROLE_CONF before sourcing prole_cfg.sh so it is preserved (prole_cfg.sh
|
||||||
|
# honours a pre-set PROLE_CONF) and the correct config file is auto-detected.
|
||||||
|
if [[ -f "$cfg" ]]; then
|
||||||
|
PROLE_CONF="$(cd "$(dirname "$cfg")" && pwd)"
|
||||||
|
export PROLE_CONF
|
||||||
|
PROLE_CFG_FILE="$cfg"
|
||||||
|
export PROLE_CFG_FILE
|
||||||
|
fi
|
||||||
if [[ -f "${ROOT_DIR}/etc/prole_cfg.sh" ]]; then
|
if [[ -f "${ROOT_DIR}/etc/prole_cfg.sh" ]]; then
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${ROOT_DIR}/etc/prole_cfg.sh"
|
source "${ROOT_DIR}/etc/prole_cfg.sh"
|
||||||
fi
|
fi
|
||||||
if [[ -f "$cfg" ]]; then
|
export PROLE_CFG_FILE="${cfg}"
|
||||||
export PROLE_CONF
|
|
||||||
PROLE_CONF="$(cd "$(dirname "$cfg")" && pwd)"
|
|
||||||
fi
|
|
||||||
export PROLE_CFG_FILE="$cfg"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_prole_mode() {
|
resolve_prole_mode() {
|
||||||
@ -594,7 +598,8 @@ case "${CMD}" in
|
|||||||
CMD_ARGS=("${_INSTALL_PASSTHRU[@]}")
|
CMD_ARGS=("${_INSTALL_PASSTHRU[@]}")
|
||||||
|
|
||||||
# Ensure OpenBao URL is set appropriately for the active mode before running install.py.
|
# Ensure OpenBao URL is set appropriately for the active mode before running install.py.
|
||||||
_cfg_for_env="${PROLE_CFG_DEFAULT}"
|
# Honour top-level -c / --config if provided (CONFIG_PATH), falling back to default.
|
||||||
|
_cfg_for_env="${CONFIG_PATH:-${PROLE_CFG_DEFAULT}}"
|
||||||
for ((i=0; i<${#CMD_ARGS[@]}; i++)); do
|
for ((i=0; i<${#CMD_ARGS[@]}; i++)); do
|
||||||
if [[ "${CMD_ARGS[$i]}" == "-c" || "${CMD_ARGS[$i]}" == "--config" ]]; then
|
if [[ "${CMD_ARGS[$i]}" == "-c" || "${CMD_ARGS[$i]}" == "--config" ]]; then
|
||||||
if [[ $((i+1)) -lt ${#CMD_ARGS[@]} ]]; then
|
if [[ $((i+1)) -lt ${#CMD_ARGS[@]} ]]; then
|
||||||
|
|||||||
7
scan/ansible_inventory_flat.txt
Normal file
7
scan/ansible_inventory_flat.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
host,ip,roles
|
||||||
|
merlin,10.0.0.36,merlin_bootstrap
|
||||||
|
merlin.prole.org,,iscsi,k3s_agents,k3s_hosts,linux_hosts,mariadb,mariadb_primary
|
||||||
|
myrddin.prole.org,,ad_dc,iscsi,k3s_hosts,k3s_servers,linux_hosts,ssl_hosts
|
||||||
|
pi.prole.org,,iscsi,k3s_agents,k3s_hosts,linux_hosts,pihole
|
||||||
|
raspberry.prole.org,,iscsi,linux_hosts,mariadb,mariadb_replica,pihole
|
||||||
|
retropie.prole.org,,iscsi,linux_hosts
|
||||||
65
scan/network_description.txt
Normal file
65
scan/network_description.txt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
Network Discovery Summary:
|
||||||
|
Primary Router: 10.0.0.1 (eero_5d:50:f2)
|
||||||
|
DNS Servers: 10.0.0.4, 100.100.100.100, 10.0.0.5
|
||||||
|
Detected Devices:
|
||||||
|
- 10.0.0.38 [7e:19:9a:fe:9f:ed] (7e:19:9a:fe:9f:ed): Ports [22, 445, 5900, 11434, 88], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'Ollama', 'Active Directory Related']
|
||||||
|
- 10.0.0.22 [2c:cf:67:45:8d:97] (RaspberryPi_45:8d:97): Ports [22, 80, 443], Services: ['SSH', 'Web Server']
|
||||||
|
- 10.0.0.4 [b8:27:eb:b3:6f:2b] (RaspberryPiF_b3:6f:2b): Ports [22, 53, 443, 2049], Services: ['DNS', 'SSH', 'NFS', 'Web Server']
|
||||||
|
- 10.0.0.1 [9c:57:bc:5d:50:f2] (eero_5d:50:f2): Ports [53], Services: ['DNS']
|
||||||
|
- 10.0.0.3 [2c:cf:67:8c:2b:47] (RaspberryPi_8c:2b:47): Ports [22, 53, 80, 443, 2049, 445, 5900, 88, 389, 636], Services: ['DNS', 'SSH', 'NFS', 'VNC', 'Web Server', 'SMB/CIFS (Possible Windows/AD)', 'Active Directory Related']
|
||||||
|
- 10.0.0.2 [dc:a4:ca:ea:1a:2f] (Apple_ea:1a:2f): Ports [], Services: []
|
||||||
|
- 10.0.0.6 [2c:cf:67:45:8d:97] (RaspberryPi_45:8d:97): Ports [22, 80, 443], Services: ['SSH', 'Web Server']
|
||||||
|
- 10.0.0.5 [b8:27:eb:88:3a:41] (RaspberryPiF_88:3a:41): Ports [22, 53, 443, 2049, 5900], Services: ['DNS', 'SSH', 'NFS', 'VNC', 'Web Server']
|
||||||
|
- 10.0.0.26 [c8:db:26:08:52:f8] (Logitech_08:52:f8): Ports [], Services: []
|
||||||
|
- 10.0.0.33 [ec:b5:fa:b0:76:e4] (PhilipsLight_b0:76:e4): Ports [80, 443], Services: ['Web Server']
|
||||||
|
- 10.0.0.73 [4c:a9:19:b3:12:f8] (TuyaSmart_b3:12:f8): Ports [], Services: []
|
||||||
|
- 10.0.0.37 [54:07:7d:22:c0:b2] (Netgear_22:c0:b2): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.45 [f8:b4:6a:30:a4:1f] (HewlettPacka_30:a4:1f): Ports [80, 443], Services: ['Web Server']
|
||||||
|
- 10.0.0.46 [d4:f7:d5:40:ab:17] (SonyInteract_40:ab:17): Ports [], Services: []
|
||||||
|
- 10.0.0.48 [0c:fe:45:53:f4:3c] (SonyInteract_53:f4:3c): Ports [], Services: []
|
||||||
|
- 10.0.0.55 [48:a6:b8:a7:50:60] (Sonos_a7:50:60): Ports [], Services: []
|
||||||
|
- 10.0.0.58 [7e:46:74:2a:b0:b2] (7e:46:74:2a:b0:b2): Ports [], Services: []
|
||||||
|
- 10.0.0.41 [b8:27:eb:57:10:d9] (RaspberryPiF_57:10:d9): Ports [22], Services: ['SSH']
|
||||||
|
- 10.0.0.203 [00:11:32:3b:2f:08] (Synology_3b:2f:08): Ports [22, 80, 443, 2049, 445], Services: ['SSH', 'NFS', 'Web Server', 'SMB/CIFS (Possible Windows/AD)']
|
||||||
|
- 10.0.0.100 [24:fc:e5:51:cf:74] (SamsungElect_51:cf:74): Ports [], Services: []
|
||||||
|
- 10.0.0.99 [20:28:bc:f1:dc:ba] (Visionscape_f1:dc:ba): Ports [], Services: []
|
||||||
|
- 10.0.0.95 [b8:27:eb:88:3a:41] (RaspberryPiF_88:3a:41): Ports [22, 53, 443, 2049, 5900], Services: ['DNS', 'SSH', 'NFS', 'VNC', 'Web Server']
|
||||||
|
- 10.0.0.204 [50:eb:f6:56:f3:26] (ASUSTekCOMPU_56:f3:26): Ports [22, 3389, 445, 5900, 11434], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'RDP (Windows)', 'Ollama']
|
||||||
|
- 10.0.0.1\ [9c:57:bc:5d:50:f2] (eero_5d:50:f2): Ports [], Services: []
|
||||||
|
- 10.0.0.123 [3c:ef:8c:96:e3:3c] (ZhejiangDahu_96:e3:3c): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.124 [9c:8e:cd:02:73:c4] (AmcrestTechn_02:73:c4): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.111 [ca:0b:6c:5d:0a:e5] (ca:0b:6c:5d:0a:e5): Ports [], Services: []
|
||||||
|
- 10.0.0.127 [58:55:ca:4a:60:6e] (Apple_4a:60:6e): Ports [22], Services: ['SSH']
|
||||||
|
- 10.0.0.117 [40:f5:20:1e:5e:91] (Espressif_1e:5e:91): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.113 [60:81:10:92:02:4e] (Apple_92:02:4e): Ports [], Services: []
|
||||||
|
- 10.0.0.107 [b8:06:0d:b7:7c:56] (TuyaSmart_b7:7c:56): Ports [], Services: []
|
||||||
|
- 10.0.0.112 [f8:33:31:40:58:c0] (TexasInstrum_40:58:c0): Ports [80, 443], Services: ['Web Server']
|
||||||
|
- 10.0.0.130 [f8:bb:bf:a3:84:eb] (eero_a3:84:eb): Ports [53], Services: ['DNS']
|
||||||
|
- 10.0.0.125 [a0:60:32:04:73:ba] (AmcrestTechn_04:73:ba): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.205 [a8:20:66:28:12:e7] (Apple_28:12:e7): Ports [22, 445, 5900, 88], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'Active Directory Related']
|
||||||
|
- 10.0.0.143 [60:5f:8d:7a:aa:32] (eero_7a:aa:32): Ports [53], Services: ['DNS']
|
||||||
|
- 10.0.0.145 [7c:a6:b0:04:db:1c] (7c:a6:b0:04:db:1c): Ports [], Services: []
|
||||||
|
- 10.0.0.128 [20:c9:d0:94:30:dd] (Apple_94:30:dd): Ports [], Services: []
|
||||||
|
- 10.0.0.155 [62:17:97:b3:06:a1] (62:17:97:b3:06:a1): Ports [], Services: []
|
||||||
|
- 10.0.0.170 [b0:ee:7b:ca:73:99] (Roku_ca:73:99): Ports [], Services: []
|
||||||
|
- 10.0.0.179 [48:a6:b8:a4:8e:cc] (Sonos_a4:8e:cc): Ports [], Services: []
|
||||||
|
- 10.0.0.180 [4c:e1:73:42:1a:be] (HuizhouDehon_2:1a:be): Ports [445], Services: ['SMB/CIFS (Possible Windows/AD)']
|
||||||
|
- 10.0.0.189 [00:17:88:a3:2f:cc] (PhilipsLight_a3:2f:cc): Ports [80, 443], Services: ['Web Server']
|
||||||
|
- 10.0.0.188 [00:16:6c:c5:1f:54] (SamsungElect_c5:1f:54): Ports [80, 443], Services: ['Web Server']
|
||||||
|
- 10.0.0.196 [60:5f:8d:88:08:f2] (eero_88:08:f2): Ports [53], Services: ['DNS']
|
||||||
|
- 10.0.0.175 [28:80:88:e4:10:1a] (Netgear_e4:10:1a): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.199 [7c:a6:b0:01:a7:33] (7c:a6:b0:01:a7:33): Ports [], Services: []
|
||||||
|
- 10.0.0.206 [00:a0:de:a2:0b:ef] (Yamaha_a2:0b:ef): Ports [80], Services: ['Web Server']
|
||||||
|
- 10.0.0.208 [a0:ad:9f:30:84:5f] (ASUSTekCOMPU_30:84:5f): Ports [], Services: []
|
||||||
|
Ollama Instances found at: 10.0.0.38, 10.0.0.204
|
||||||
|
|
||||||
|
Ansible Inventory Summary:
|
||||||
|
Inventory directory: /Users/chrisfu/dev/prole/infrastructure
|
||||||
|
Hosts detected: 6
|
||||||
|
- merlin (10.0.0.36): roles [merlin_bootstrap]
|
||||||
|
- merlin.prole.org (unknown): roles [iscsi, k3s_agents, k3s_hosts, linux_hosts, mariadb, mariadb_primary]
|
||||||
|
- myrddin.prole.org (unknown): roles [ad_dc, iscsi, k3s_hosts, k3s_servers, linux_hosts, ssl_hosts]
|
||||||
|
- pi.prole.org (unknown): roles [iscsi, k3s_agents, k3s_hosts, linux_hosts, pihole]
|
||||||
|
- raspberry.prole.org (unknown): roles [iscsi, linux_hosts, mariadb, mariadb_replica, pihole]
|
||||||
|
- retropie.prole.org (unknown): roles [iscsi, linux_hosts]
|
||||||
|
Flat inventory file: /Users/chrisfu/dev/prole/scan/ansible_inventory_flat.txt
|
||||||
@ -1219,7 +1219,7 @@ ensure_k8s_supabase_static_pvs() {
|
|||||||
if [[ "${MODE:-}" != "k8s" ]]; then
|
if [[ "${MODE:-}" != "k8s" ]]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [[ -z "${storage_class:-}" || "$storage_class" != "prole-iscsi" ]]; then
|
if [[ -z "${storage_class:-}" || "$storage_class" != "synology-iscsi" ]]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1227,7 +1227,7 @@ ensure_k8s_supabase_static_pvs() {
|
|||||||
|
|
||||||
local node base parent base_name
|
local node base parent base_name
|
||||||
node="${SUPABASE_PV_NODE:-myrddin.prole.org}"
|
node="${SUPABASE_PV_NODE:-myrddin.prole.org}"
|
||||||
base="${SUPABASE_PV_BASE_DIR:-/prole/d002/supabase}"
|
base="${SUPABASE_PV_BASE_DIR:-/synology/d002/supabase}"
|
||||||
base="${base%/}"
|
base="${base%/}"
|
||||||
parent="$(dirname "$base")"
|
parent="$(dirname "$base")"
|
||||||
base_name="$(basename "$base")"
|
base_name="$(basename "$base")"
|
||||||
@ -1298,12 +1298,12 @@ EOF
|
|||||||
# Static local PVs with Retain reclaimPolicy can get stuck in Released after a namespace reset.
|
# Static local PVs with Retain reclaimPolicy can get stuck in Released after a namespace reset.
|
||||||
# Delete Released PV objects so they can be recreated and rebound to the new PVCs.
|
# Delete Released PV objects so they can be recreated and rebound to the new PVCs.
|
||||||
local pvs=(
|
local pvs=(
|
||||||
prole-supabase-db
|
synology-supabase-db
|
||||||
prole-supabase-deno
|
synology-supabase-deno
|
||||||
prole-supabase-functions
|
synology-supabase-functions
|
||||||
prole-supabase-imgproxy
|
synology-supabase-imgproxy
|
||||||
prole-supabase-snippets
|
synology-supabase-snippets
|
||||||
prole-supabase-storage
|
synology-supabase-storage
|
||||||
)
|
)
|
||||||
local pv
|
local pv
|
||||||
for pv in "${pvs[@]}"; do
|
for pv in "${pvs[@]}"; do
|
||||||
@ -1320,9 +1320,9 @@ EOF
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-supabase-db
|
name: synology-supabase-db
|
||||||
labels:
|
labels:
|
||||||
prole.storage/pvc: supabase-db
|
synology.storage/pvc: supabase-db
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 5Gi
|
storage: 5Gi
|
||||||
@ -1345,9 +1345,9 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-supabase-deno
|
name: synology-supabase-deno
|
||||||
labels:
|
labels:
|
||||||
prole.storage/pvc: supabase-deno
|
synology.storage/pvc: supabase-deno
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
@ -1370,9 +1370,9 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-supabase-functions
|
name: synology-supabase-functions
|
||||||
labels:
|
labels:
|
||||||
prole.storage/pvc: supabase-functions
|
synology.storage/pvc: supabase-functions
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
@ -1395,9 +1395,9 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-supabase-imgproxy
|
name: synology-supabase-imgproxy
|
||||||
labels:
|
labels:
|
||||||
prole.storage/pvc: supabase-imgproxy
|
synology.storage/pvc: supabase-imgproxy
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
@ -1420,9 +1420,9 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-supabase-snippets
|
name: synology-supabase-snippets
|
||||||
labels:
|
labels:
|
||||||
prole.storage/pvc: supabase-snippets
|
synology.storage/pvc: supabase-snippets
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
@ -1445,9 +1445,9 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: prole-supabase-storage
|
name: synology-supabase-storage
|
||||||
labels:
|
labels:
|
||||||
prole.storage/pvc: supabase-storage
|
synology.storage/pvc: supabase-storage
|
||||||
spec:
|
spec:
|
||||||
capacity:
|
capacity:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
@ -1513,7 +1513,7 @@ PY
|
|||||||
local storage_class
|
local storage_class
|
||||||
storage_class="${SUPABASE_STORAGE_CLASS:-}"
|
storage_class="${SUPABASE_STORAGE_CLASS:-}"
|
||||||
if [[ -z "$storage_class" && "$MODE" == "k8s" ]]; then
|
if [[ -z "$storage_class" && "$MODE" == "k8s" ]]; then
|
||||||
storage_class="prole-iscsi"
|
storage_class="synology-iscsi"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ensure_k8s_supabase_static_pvs "$storage_class"
|
ensure_k8s_supabase_static_pvs "$storage_class"
|
||||||
|
|||||||
@ -34,7 +34,7 @@ metadata:
|
|||||||
name: {{ $pvcName }}
|
name: {{ $pvcName }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "supabase.labels" $root | nindent 4 }}
|
{{- include "supabase.labels" $root | nindent 4 }}
|
||||||
prole.storage/pvc: {{ $pvcName | quote }}
|
synology.storage/pvc: {{ $pvcName | quote }}
|
||||||
{{- with $persistence.annotations }}
|
{{- with $persistence.annotations }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
@ -43,10 +43,10 @@ spec:
|
|||||||
{{- if $persistence.storageClassName }}
|
{{- if $persistence.storageClassName }}
|
||||||
storageClassName: {{ $persistence.storageClassName }}
|
storageClassName: {{ $persistence.storageClassName }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq ($persistence.storageClassName | default "") "prole-iscsi" }}
|
{{- if eq ($persistence.storageClassName | default "") "synology-iscsi" }}
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/pvc: {{ $pvcName | quote }}
|
synology.storage/pvc: {{ $pvcName | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
accessModes:
|
accessModes:
|
||||||
{{- range $persistence.accessModes }}
|
{{- range $persistence.accessModes }}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
# Regression tests for k3s CNPG storage guardrails in etc/init_cloudnative_pg.sh
|
# Regression tests for k3s CNPG storage guardrails in etc/init_cloudnative_pg.sh
|
||||||
# - must fail if protected mounts are root-backed
|
# - must fail if protected mounts are root-backed
|
||||||
# - must fail if manifest lacks explicit prole-iscsi + selector labels (prevents local-path fallback)
|
# - must fail if manifest lacks explicit synology-iscsi + selector labels (prevents local-path fallback)
|
||||||
# - must succeed (with mocks) when mounts + manifest + runtime objects are correct
|
# - must succeed (with mocks) when mounts + manifest + runtime objects are correct
|
||||||
|
|
||||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||||
@ -139,9 +139,13 @@ if [[ "$args" == *"get nodes"*"--no-headers"* ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Runtime validation calls
|
# Runtime validation calls
|
||||||
|
if [[ "$args" == *" get cluster prole-db -o jsonpath="* ]]; then
|
||||||
|
# Return empty imageName so _cnpg_current_image_name sees no prior image.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
if [[ "$args" == *" get cluster prole-db -o json"* ]]; then
|
if [[ "$args" == *" get cluster prole-db -o json"* ]]; then
|
||||||
cat <<JSON
|
cat <<JSON
|
||||||
{"apiVersion":"postgresql.cnpg.io/v1","kind":"Cluster","metadata":{"name":"prole-db"},"spec":{"storage":{"pvcTemplate":{"storageClassName":"prole-iscsi","selector":{"matchLabels":{"prole.storage/role":"data"}}}},"walStorage":{"pvcTemplate":{"storageClassName":"prole-iscsi","selector":{"matchLabels":{"prole.storage/role":"wal"}}}}}}
|
{"apiVersion":"postgresql.cnpg.io/v1","kind":"Cluster","metadata":{"name":"prole-db"},"spec":{"storage":{"pvcTemplate":{"storageClassName":"synology-iscsi","selector":{"matchLabels":{"synology.storage/role":"data"}}}},"walStorage":{"pvcTemplate":{"storageClassName":"synology-iscsi","selector":{"matchLabels":{"synology.storage/role":"wal"}}}}}}
|
||||||
JSON
|
JSON
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@ -149,19 +153,19 @@ fi
|
|||||||
if [[ "$args" == *" get pvc"*"cnpg.io/cluster=prole-db"*"-o json"* ]]; then
|
if [[ "$args" == *" get pvc"*"cnpg.io/cluster=prole-db"*"-o json"* ]]; then
|
||||||
cat <<JSON
|
cat <<JSON
|
||||||
{"items":[
|
{"items":[
|
||||||
{"metadata":{"name":"prole-db-1"},"spec":{"storageClassName":"prole-iscsi","volumeName":"pv-data"}},
|
{"metadata":{"name":"prole-db-1"},"spec":{"storageClassName":"synology-iscsi","volumeName":"pv-data"}},
|
||||||
{"metadata":{"name":"prole-db-wal"},"spec":{"storageClassName":"prole-iscsi","volumeName":"pv-wal"}}
|
{"metadata":{"name":"prole-db-wal"},"spec":{"storageClassName":"synology-iscsi","volumeName":"pv-wal"}}
|
||||||
]}
|
]}
|
||||||
JSON
|
JSON
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$args" == "get pv pv-data -o json"* ]]; then
|
if [[ "$args" == "get pv pv-data -o json"* ]]; then
|
||||||
echo '{"spec":{"storageClassName":"prole-iscsi","local":{"path":"/prole/d001/data"}}}'
|
echo '{"spec":{"storageClassName":"synology-iscsi","local":{"path":"/synology/d001/data"}}}'
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ "$args" == "get pv pv-wal -o json"* ]]; then
|
if [[ "$args" == "get pv pv-wal -o json"* ]]; then
|
||||||
echo '{"spec":{"storageClassName":"prole-iscsi","local":{"path":"/prole/d001/wal"}}}'
|
echo '{"spec":{"storageClassName":"synology-iscsi","local":{"path":"/synology/d001/wal"}}}'
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -248,16 +252,16 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
storage:
|
storage:
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
walStorage:
|
walStorage:
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
export PROLE_TEST_FINDMNT_DATA_SRC="/dev/root"
|
export PROLE_TEST_FINDMNT_DATA_SRC="/dev/root"
|
||||||
@ -300,19 +304,19 @@ spec:
|
|||||||
instances: 1
|
instances: 1
|
||||||
storage:
|
storage:
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: data
|
synology.storage/role: data
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
walStorage:
|
walStorage:
|
||||||
pvcTemplate:
|
pvcTemplate:
|
||||||
storageClassName: prole-iscsi
|
storageClassName: synology-iscsi
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
prole.storage/role: wal
|
synology.storage/role: wal
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 29Gi
|
storage: 29Gi
|
||||||
|
|||||||
266
tests/etc/test_init_cloudnative_pg_image_policy.sh
Normal file
266
tests/etc/test_init_cloudnative_pg_image_policy.sh
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Unit tests for etc/init_cloudnative_pg.sh image policy behavior:
|
||||||
|
# - no-op when desired image already deployed
|
||||||
|
# - fail early on version mismatch without --upgrade (before namespace creation)
|
||||||
|
# - on --upgrade + mismatch, trigger a rollout/restart hook
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||||
|
REPO_ROOT=$(cd "$SCRIPT_DIR/../.." && pwd)
|
||||||
|
SCRIPT_UNDER_TEST="$REPO_ROOT/etc/init_cloudnative_pg.sh"
|
||||||
|
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|
||||||
|
BIN_DIR="$TMP_DIR/bin"
|
||||||
|
mkdir -p "$BIN_DIR"
|
||||||
|
|
||||||
|
MOCK_LOG="$TMP_DIR/mock_calls.log"
|
||||||
|
|
||||||
|
cat <<'K_EOF' > "$BIN_DIR/kubectl"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "Mocked kubectl called with $@" >> "${MOCK_LOG:-/tmp/mock_calls.log}"
|
||||||
|
|
||||||
|
args="$*"
|
||||||
|
|
||||||
|
if [[ "$args" == *"get --raw=/readyz"* || "$args" == *"get --raw='/readyz'"* || "$args" == *"get --raw=\"/readyz\""* ]]; then
|
||||||
|
echo "ok"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"version --short"* ]]; then
|
||||||
|
echo "Client Version: v0.0.0"
|
||||||
|
echo "Server Version: v0.0.0"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CNPG webhook wait: return an endpoint IP so the wait loop passes.
|
||||||
|
if [[ "$args" == *"get endpoints"*"cnpg-webhook-service"* ]]; then
|
||||||
|
echo "10.42.0.10"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"get endpoints barman-cloud"* ]]; then
|
||||||
|
echo "10.42.0.11"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Barman plugin service registration: return a service name for label-based lookups.
|
||||||
|
if [[ "$args" == *"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="* ]]; then
|
||||||
|
echo "barman-cloud"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "$args" == *"get svc barman-cloud"*"-o jsonpath="*".metadata.name"* ]]; then
|
||||||
|
echo "barman-cloud"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"get svc barman-cloud"*"-o jsonpath="*"pluginClientSecret"* ]]; then
|
||||||
|
echo "barman-cloud-client-tls"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "$args" == *"get svc barman-cloud"*"-o jsonpath="*"pluginServerSecret"* ]]; then
|
||||||
|
echo "barman-cloud-server-tls"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "$args" == *"get svc barman-cloud"*"-o jsonpath="*"pluginPort"* ]]; then
|
||||||
|
echo "443"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"get namespace"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"create namespace"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"get cluster"*"-o jsonpath="*".spec.imageName"* ]]; then
|
||||||
|
echo "${MOCK_CLUSTER_IMAGE:-}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"get cluster"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"patch cluster"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"cnpg version"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"cnpg restart"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"apply"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$args" == *"get secret"* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
K_EOF
|
||||||
|
chmod +x "$BIN_DIR/kubectl"
|
||||||
|
|
||||||
|
mock_ok_tool() {
|
||||||
|
cat <<M_EOF > "$BIN_DIR/$1"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Mocked $1 called with \$@" >> "${MOCK_LOG:-/tmp/mock_calls.log}"
|
||||||
|
exit 0
|
||||||
|
M_EOF
|
||||||
|
chmod +x "$BIN_DIR/$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prevent accidental real calls during tests.
|
||||||
|
mock_ok_tool docker
|
||||||
|
mock_ok_tool k3d
|
||||||
|
mock_ok_tool curl
|
||||||
|
mock_ok_tool jq
|
||||||
|
mock_ok_tool skopeo
|
||||||
|
|
||||||
|
export PATH="$BIN_DIR:$PATH"
|
||||||
|
export MOCK_LOG
|
||||||
|
|
||||||
|
CONF_DIR="$TMP_DIR/conf"
|
||||||
|
mkdir -p "$CONF_DIR"
|
||||||
|
|
||||||
|
SERVICE_DIR="$TMP_DIR/service"
|
||||||
|
mkdir -p "$SERVICE_DIR/secrets"
|
||||||
|
printf '%s' "dummy-private-key" > "$SERVICE_DIR/secrets/admin.key"
|
||||||
|
printf '%s' "dummy-public-key" > "$SERVICE_DIR/secrets/admin.pub"
|
||||||
|
|
||||||
|
write_cfg() {
|
||||||
|
local prole_home_val="$1"
|
||||||
|
cat <<C_EOF > "$CONF_DIR/prole.cfg"
|
||||||
|
[User]
|
||||||
|
NAMESPACE = test-ns
|
||||||
|
SERVICE_NAMESPACE = test-system
|
||||||
|
PROLE_HOME = ${prole_home_val}
|
||||||
|
PROLE_SERVICE = ${SERVICE_DIR}
|
||||||
|
|
||||||
|
[Global]
|
||||||
|
DEPLOYMENT_MODE = k3d
|
||||||
|
|
||||||
|
[Docker Build]
|
||||||
|
LOCAL_REGISTRY = localhost:5000
|
||||||
|
LOCAL_REGISTRY_INTERNAL = k3d-prole-registry:5000
|
||||||
|
C_EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_log() {
|
||||||
|
: > "$MOCK_LOG"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_not_called() {
|
||||||
|
local needle="$1"
|
||||||
|
if grep -q "$needle" "$MOCK_LOG"; then
|
||||||
|
echo "FAILURE: expected not to see '$needle' in mock log"
|
||||||
|
sed -n '1,200p' "$MOCK_LOG" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_called() {
|
||||||
|
local needle="$1"
|
||||||
|
if ! grep -q "$needle" "$MOCK_LOG"; then
|
||||||
|
echo "FAILURE: expected to see '$needle' in mock log"
|
||||||
|
sed -n '1,200p' "$MOCK_LOG" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_case() {
|
||||||
|
local name="$1"; shift
|
||||||
|
local expected_rc="$1"; shift
|
||||||
|
|
||||||
|
reset_log
|
||||||
|
local out="$TMP_DIR/${name}.out"
|
||||||
|
local err="$TMP_DIR/${name}.err"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
"$@" >"$out" 2>"$err"
|
||||||
|
local rc=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ "$rc" != "$expected_rc" ]]; then
|
||||||
|
echo "FAILURE: $name expected RC=$expected_rc got RC=$rc"
|
||||||
|
echo "--- stdout ---"
|
||||||
|
sed -n '1,200p' "$out" || true
|
||||||
|
echo "--- stderr ---"
|
||||||
|
sed -n '1,200p' "$err" || true
|
||||||
|
echo "--- mock log ---"
|
||||||
|
sed -n '1,200p' "$MOCK_LOG" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Case 1: no-op on same image (initialize)
|
||||||
|
###############################################
|
||||||
|
|
||||||
|
export PROLE_CONF="$CONF_DIR"
|
||||||
|
export PROLE_SERVICE="$SERVICE_DIR"
|
||||||
|
|
||||||
|
write_cfg "$REPO_ROOT"
|
||||||
|
|
||||||
|
export MOCK_CLUSTER_IMAGE="k3d-prole-registry:5000/knoe-db:18-140"
|
||||||
|
|
||||||
|
run_case "noop_initialize" 0 \
|
||||||
|
bash "$SCRIPT_UNDER_TEST" --mode k3d --namespace test-ns initialize prole-db 18-140
|
||||||
|
|
||||||
|
assert_not_called "create namespace"
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Case 2: mismatch without --upgrade fails early
|
||||||
|
###############################################
|
||||||
|
|
||||||
|
export MOCK_CLUSTER_IMAGE="k3d-prole-registry:5000/knoe-db:18-138"
|
||||||
|
|
||||||
|
run_case "mismatch_initialize" 1 \
|
||||||
|
bash "$SCRIPT_UNDER_TEST" --mode k3d --namespace test-ns initialize prole-db 18-140
|
||||||
|
|
||||||
|
assert_not_called "create namespace"
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# Case 3: mismatch with --upgrade triggers restart hook (deploy)
|
||||||
|
###############################################
|
||||||
|
|
||||||
|
PROLE_HOME_UPGRADE="$TMP_DIR/prole_home"
|
||||||
|
mkdir -p "$PROLE_HOME_UPGRADE/deploy/opentofu/k3s/manifests/prole"
|
||||||
|
cat <<'Y_EOF' > "$PROLE_HOME_UPGRADE/deploy/opentofu/k3s/manifests/prole/prole-db.yaml"
|
||||||
|
apiVersion: postgresql.cnpg.io/v1
|
||||||
|
kind: Cluster
|
||||||
|
metadata:
|
||||||
|
name: prole-db
|
||||||
|
spec:
|
||||||
|
instances: 1
|
||||||
|
imageName: knoe-db:dummy
|
||||||
|
Y_EOF
|
||||||
|
cat <<'Y_EOF' > "$PROLE_HOME_UPGRADE/deploy/opentofu/k3s/manifests/prole/prole-db-barman-objectstore.yaml"
|
||||||
|
apiVersion: postgresql.cnpg.io/v1
|
||||||
|
kind: ObjectStore
|
||||||
|
metadata:
|
||||||
|
name: prole-db
|
||||||
|
spec: {}
|
||||||
|
Y_EOF
|
||||||
|
|
||||||
|
write_cfg "$PROLE_HOME_UPGRADE"
|
||||||
|
|
||||||
|
export MOCK_CLUSTER_IMAGE="k3d-prole-registry:5000/knoe-db:18-138"
|
||||||
|
|
||||||
|
run_case "upgrade_deploy" 0 \
|
||||||
|
bash "$SCRIPT_UNDER_TEST" --mode k3d --namespace test-ns --upgrade deploy 18-140
|
||||||
|
|
||||||
|
assert_called "cnpg restart"
|
||||||
|
|
||||||
|
echo "SUCCESS"
|
||||||
@ -136,25 +136,25 @@ fi
|
|||||||
# Runtime storage validation (k3s) expects live Cluster + PVC/PV objects.
|
# Runtime storage validation (k3s) expects live Cluster + PVC/PV objects.
|
||||||
if [[ "${args}" == *"-n test-ns"*"get cluster"*"prole-db"*"-o json"* ]]; then
|
if [[ "${args}" == *"-n test-ns"*"get cluster"*"prole-db"*"-o json"* ]]; then
|
||||||
cat <<'JSON'
|
cat <<'JSON'
|
||||||
{"apiVersion":"postgresql.cnpg.io/v1","kind":"Cluster","metadata":{"name":"prole-db"},"spec":{"storage":{"pvcTemplate":{"storageClassName":"prole-iscsi","selector":{"matchLabels":{"prole.storage/role":"data"}}}},"walStorage":{"pvcTemplate":{"storageClassName":"prole-iscsi","selector":{"matchLabels":{"prole.storage/role":"wal"}}}}}}
|
{"apiVersion":"postgresql.cnpg.io/v1","kind":"Cluster","metadata":{"name":"prole-db"},"spec":{"storage":{"pvcTemplate":{"storageClassName":"synology-iscsi","selector":{"matchLabels":{"synology.storage/role":"data"}}}},"walStorage":{"pvcTemplate":{"storageClassName":"synology-iscsi","selector":{"matchLabels":{"synology.storage/role":"wal"}}}}}}
|
||||||
JSON
|
JSON
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ "${args}" == *"-n test-ns"*"get pvc"*"cnpg.io/cluster=prole-db"*"-o json"* ]]; then
|
if [[ "${args}" == *"-n test-ns"*"get pvc"*"cnpg.io/cluster=prole-db"*"-o json"* ]]; then
|
||||||
cat <<'JSON'
|
cat <<'JSON'
|
||||||
{"items":[
|
{"items":[
|
||||||
{"metadata":{"name":"prole-db-1"},"spec":{"storageClassName":"prole-iscsi","volumeName":"pv-data"}},
|
{"metadata":{"name":"prole-db-1"},"spec":{"storageClassName":"synology-iscsi","volumeName":"pv-data"}},
|
||||||
{"metadata":{"name":"prole-db-1-wal"},"spec":{"storageClassName":"prole-iscsi","volumeName":"pv-wal"}}
|
{"metadata":{"name":"prole-db-1-wal"},"spec":{"storageClassName":"synology-iscsi","volumeName":"pv-wal"}}
|
||||||
]}
|
]}
|
||||||
JSON
|
JSON
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ "${args}" == "get pv pv-data -o json"* ]]; then
|
if [[ "${args}" == "get pv pv-data -o json"* ]]; then
|
||||||
echo '{"spec":{"storageClassName":"prole-iscsi","local":{"path":"/prole/d001/data"}}}'
|
echo '{"spec":{"storageClassName":"synology-iscsi","local":{"path":"/synology/d001/data"}}}'
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ "${args}" == "get pv pv-wal -o json"* ]]; then
|
if [[ "${args}" == "get pv pv-wal -o json"* ]]; then
|
||||||
echo '{"spec":{"storageClassName":"prole-iscsi","local":{"path":"/prole/d001/wal"}}}'
|
echo '{"spec":{"storageClassName":"synology-iscsi","local":{"path":"/synology/d001/wal"}}}'
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -279,13 +279,18 @@ if grep -qE '^\s*- key:\s*kubernetes\\.io/hostname\s*$|myrddin\\.prole\\.org' "$
|
|||||||
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if ! grep -qE '^\s*- key:\s*prole\.org/node-role\s*$' "$TMP_DIR/applied.yaml"; then
|
if ! grep -qE '^\s*- key:\s*node\.kubernetes\.io/instance-type\s*$' "$TMP_DIR/applied.yaml"; then
|
||||||
echo "FAILURE: expected node-role label affinity in applied manifest (default)"
|
echo "FAILURE: expected k3s instance-type node affinity in applied manifest (default)"
|
||||||
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if ! grep -qE '^\s*podAntiAffinityType:\s*required\s*$' "$TMP_DIR/applied.yaml"; then
|
if ! grep -qE '^\s*- k3s\s*$' "$TMP_DIR/applied.yaml"; then
|
||||||
echo "FAILURE: expected podAntiAffinityType=required in applied manifest (default)"
|
echo "FAILURE: expected node affinity value k3s in applied manifest (default)"
|
||||||
|
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! grep -qE '^\s*podAntiAffinityType:\s*preferred\s*$' "$TMP_DIR/applied.yaml"; then
|
||||||
|
echo "FAILURE: expected podAntiAffinityType=preferred in applied manifest (default)"
|
||||||
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
sed -n '1,160p' "$TMP_DIR/applied.yaml" || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
155
tests/etc/test_init_cloudnative_pg_k3d_k3s_registry_cache.sh
Normal file
155
tests/etc/test_init_cloudnative_pg_k3d_k3s_registry_cache.sh
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Regression test: in k3d mode, init_cloudnative_pg.sh should consult the k3s registry
|
||||||
|
# as an optional cache/source before falling back to a local build.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||||
|
REPO_ROOT=$(cd "$SCRIPT_DIR/../.." && pwd)
|
||||||
|
ETC_DIR="$REPO_ROOT/etc"
|
||||||
|
SCRIPT_UNDER_TEST="$ETC_DIR/init_cloudnative_pg.sh"
|
||||||
|
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|
||||||
|
BIN_DIR="$TMP_DIR/bin"
|
||||||
|
mkdir -p "$BIN_DIR"
|
||||||
|
|
||||||
|
_log_file="$TMP_DIR/mock_calls.log"
|
||||||
|
export MOCK_LOG_FILE="$_log_file"
|
||||||
|
|
||||||
|
# Minimal kubectl mock so preflight-image path doesn't hang.
|
||||||
|
cat <<'K_EOF' > "$BIN_DIR/kubectl"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Mocked kubectl called with $*" >> "${MOCK_LOG_FILE}"
|
||||||
|
args="$*"
|
||||||
|
if [[ "${args}" == *"get --raw=/readyz"* || "${args}" == *"get --raw='/readyz'"* || "${args}" == *"get --raw=\"/readyz\""* ]]; then
|
||||||
|
echo "ok"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "${args}" == *"version --short"* ]]; then
|
||||||
|
echo "Client Version: v0.0.0"
|
||||||
|
echo "Server Version: v0.0.0"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
K_EOF
|
||||||
|
chmod +x "$BIN_DIR/kubectl"
|
||||||
|
|
||||||
|
# docker mock: pretend local images are missing, but the k3s registry has the image.
|
||||||
|
cat <<'D_EOF' > "$BIN_DIR/docker"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Mocked docker called with $*" >> "${MOCK_LOG_FILE}"
|
||||||
|
|
||||||
|
cmd1="${1:-}"
|
||||||
|
cmd2="${2:-}"
|
||||||
|
cmd3="${3:-}"
|
||||||
|
|
||||||
|
if [[ "$cmd1" == "image" && "$cmd2" == "inspect" ]]; then
|
||||||
|
# Force local inspect misses so the script tries the k3s registry.
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$cmd1" == "pull" ]]; then
|
||||||
|
# Succeed only for the expected k3s registry ref.
|
||||||
|
if [[ "$cmd2" == myrddin.prole.org:5000/knoe-db:* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$cmd1" == "build" || ( "$cmd1" == "buildx" && "$cmd2" == "build" ) ]]; then
|
||||||
|
echo "FAILURE: docker build should not be invoked when k3s registry contains the image" >&2
|
||||||
|
exit 99
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
D_EOF
|
||||||
|
chmod +x "$BIN_DIR/docker"
|
||||||
|
|
||||||
|
# k3d mock: allow cluster list without failing; we assert we don't need image import when push succeeds.
|
||||||
|
cat <<'K3D_EOF' > "$BIN_DIR/k3d"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Mocked k3d called with $*" >> "${MOCK_LOG_FILE}"
|
||||||
|
if [[ "${1:-}" == "cluster" && "${2:-}" == "list" ]]; then
|
||||||
|
echo "knoe-dev-cluster"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
K3D_EOF
|
||||||
|
chmod +x "$BIN_DIR/k3d"
|
||||||
|
|
||||||
|
# Other mocks used by the script in various branches.
|
||||||
|
for t in curl skopeo ansible-playbook tofu terraform ollama jq; do
|
||||||
|
cat <<M_EOF > "$BIN_DIR/$t"
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "Mocked $t called with \$@" >> "${_log_file}"
|
||||||
|
exit 0
|
||||||
|
M_EOF
|
||||||
|
chmod +x "$BIN_DIR/$t"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Mock prole.cfg for k3d mode.
|
||||||
|
mkdir -p "$TMP_DIR/conf"
|
||||||
|
cat <<C_EOF > "$TMP_DIR/conf/prole.cfg"
|
||||||
|
[User]
|
||||||
|
NAMESPACE = test-ns
|
||||||
|
SERVICE_NAMESPACE = test-system
|
||||||
|
PROLE_HOME = $REPO_ROOT
|
||||||
|
PROLE_SERVICE = $TMP_DIR/service
|
||||||
|
|
||||||
|
[Global]
|
||||||
|
DEPLOYMENT_MODE = k3d
|
||||||
|
|
||||||
|
[Docker Build]
|
||||||
|
LOCAL_REGISTRY = localhost:5000
|
||||||
|
LOCAL_REGISTRY_INTERNAL = k3d-prole-registry.localhost:5000
|
||||||
|
C_EOF
|
||||||
|
|
||||||
|
mkdir -p "$TMP_DIR/service/secrets"
|
||||||
|
printf '%s' "dummy-private-key" > "$TMP_DIR/service/secrets/admin.key"
|
||||||
|
printf '%s' "dummy-public-key" > "$TMP_DIR/service/secrets/admin.pub"
|
||||||
|
|
||||||
|
export PATH="$BIN_DIR:$PATH"
|
||||||
|
export PROLE_HOME="$REPO_ROOT"
|
||||||
|
export PROLE_CONF="$TMP_DIR/conf"
|
||||||
|
export PROLE_PASSWD="test-password"
|
||||||
|
export PROLE_SERVICE="$TMP_DIR/service"
|
||||||
|
|
||||||
|
# Run a path that triggers image preflight.
|
||||||
|
bash "$SCRIPT_UNDER_TEST" --mode k3d preflight-image > "$TMP_DIR/stdout" 2> "$TMP_DIR/stderr"
|
||||||
|
RC=$?
|
||||||
|
|
||||||
|
# Assertions
|
||||||
|
if ! grep -q "Mocked docker called with pull myrddin.prole.org:5000/knoe-db:" "${_log_file}"; then
|
||||||
|
echo "FAILURE: expected a k3s-registry pull attempt in k3d mode" >&2
|
||||||
|
echo "--- mock calls ---" >&2
|
||||||
|
sed -n '1,200p' "${_log_file}" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q "Mocked docker called with build" "${_log_file}"; then
|
||||||
|
echo "FAILURE: did not expect docker build to run when cache image is present" >&2
|
||||||
|
echo "--- mock calls ---" >&2
|
||||||
|
sed -n '1,200p' "${_log_file}" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q "Mocked k3d called with image import" "${_log_file}"; then
|
||||||
|
echo "FAILURE: expected registry push path, not k3d image import fallback" >&2
|
||||||
|
echo "--- mock calls ---" >&2
|
||||||
|
sed -n '1,200p' "${_log_file}" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $RC -eq 0 || $RC -eq 1 || $RC -eq 2 ]]; then
|
||||||
|
echo "SUCCESS (RC=$RC)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "FAILURE with RC $RC" >&2
|
||||||
|
echo "--- stdout ---" >&2
|
||||||
|
sed -n '1,200p' "$TMP_DIR/stdout" >&2 || true
|
||||||
|
echo "--- stderr ---" >&2
|
||||||
|
sed -n '1,200p' "$TMP_DIR/stderr" >&2 || true
|
||||||
|
exit 1
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Regression test: Garage startup should auto-recycle a Released prole-iscsi PV with a stale
|
# Regression test: Garage startup should auto-recycle a Released synology-iscsi PV with a stale
|
||||||
# claimRef when the PVC is Pending and rollout is stuck beyond the initial timeout.
|
# claimRef when the PVC is Pending and rollout is stuck beyond the initial timeout.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@ -23,7 +23,7 @@ cp "$SOURCE_ETC_DIR/prole_cfg.sh" "$WORK_DIR/etc/prole_cfg.sh"
|
|||||||
chmod +x "$WORK_DIR/etc/init_garage_store.sh"
|
chmod +x "$WORK_DIR/etc/init_garage_store.sh"
|
||||||
|
|
||||||
# Dummy manifests required by init_garage_store.sh
|
# Dummy manifests required by init_garage_store.sh
|
||||||
for f in storageclass-prole-iscsi.yaml iscsi-pvs.yaml garage-configmap.yaml garage-statefulset.yaml garage-service.yaml; do
|
for f in storageclass-synology-iscsi.yaml iscsi-pvs.yaml garage-configmap.yaml garage-statefulset.yaml garage-service.yaml; do
|
||||||
printf '%s\n' "apiVersion: v1" > "$WORK_DIR/k8s/prole/$f"
|
printf '%s\n' "apiVersion: v1" > "$WORK_DIR/k8s/prole/$f"
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ case "$sub" in
|
|||||||
# PV list for recycle helper
|
# PV list for recycle helper
|
||||||
if [[ "$*" == *"get pv"*"-o jsonpath="* ]]; then
|
if [[ "$*" == *"get pv"*"-o jsonpath="* ]]; then
|
||||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||||
"prole-iscsi-d001-garage" "prole-iscsi" "Retain" "Released" "test-ns" "data-garage-0" "olduid"
|
"synology-iscsi-d001-garage" "synology-iscsi" "Retain" "Released" "test-ns" "data-garage-0" "olduid"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
# Pod lookup for init_layout
|
# Pod lookup for init_layout
|
||||||
@ -148,7 +148,7 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -q "patch pv prole-iscsi-d001-garage" "$KUBECTL_LOG"; then
|
if ! grep -q "patch pv synology-iscsi-d001-garage" "$KUBECTL_LOG"; then
|
||||||
echo "FAILURE: expected PV claimRef recycle (kubectl patch pv) was not invoked" >&2
|
echo "FAILURE: expected PV claimRef recycle (kubectl patch pv) was not invoked" >&2
|
||||||
echo "--- kubectl log ---" >&2
|
echo "--- kubectl log ---" >&2
|
||||||
sed -n '1,200p' "$KUBECTL_LOG" >&2 || true
|
sed -n '1,200p' "$KUBECTL_LOG" >&2 || true
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Regression test: OpenBao restart should auto-recycle a Released prole-iscsi PV with a stale
|
# Regression test: OpenBao restart should auto-recycle a Released synology-iscsi PV with a stale
|
||||||
# claimRef when the PVC is Pending and rollout is stuck beyond the initial timeout.
|
# claimRef when the PVC is Pending and rollout is stuck beyond the initial timeout.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@ -77,7 +77,7 @@ case "$sub" in
|
|||||||
# PV list for recycle helper
|
# PV list for recycle helper
|
||||||
if [[ "$*" == *"get pv"*"-o jsonpath="* ]]; then
|
if [[ "$*" == *"get pv"*"-o jsonpath="* ]]; then
|
||||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||||
"prole-iscsi-d001-openbao" "prole-iscsi" "Retain" "Released" "knoe-system" "data-openbao-0" "olduid"
|
"synology-iscsi-d001-openbao" "synology-iscsi" "Retain" "Released" "knoe-system" "data-openbao-0" "olduid"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
@ -116,7 +116,7 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -q "patch pv prole-iscsi-d001-openbao" "$KUBECTL_LOG"; then
|
if ! grep -q "patch pv synology-iscsi-d001-openbao" "$KUBECTL_LOG"; then
|
||||||
echo "FAILURE: expected PV claimRef recycle (kubectl patch pv) was not invoked" >&2
|
echo "FAILURE: expected PV claimRef recycle (kubectl patch pv) was not invoked" >&2
|
||||||
echo "--- kubectl log ---" >&2
|
echo "--- kubectl log ---" >&2
|
||||||
sed -n '1,200p' "$KUBECTL_LOG" >&2 || true
|
sed -n '1,200p' "$KUBECTL_LOG" >&2 || true
|
||||||
|
|||||||
@ -53,7 +53,7 @@ def test_repair_flow_classifies_blockers_attempts_reclaim_and_avoids_blind_healt
|
|||||||
"uid": "new-garage-uid",
|
"uid": "new-garage-uid",
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"resources": {"requests": {"storage": "20Gi"}},
|
"resources": {"requests": {"storage": "20Gi"}},
|
||||||
},
|
},
|
||||||
@ -66,7 +66,7 @@ def test_repair_flow_classifies_blockers_attempts_reclaim_and_avoids_blind_healt
|
|||||||
"uid": "new-bao-uid",
|
"uid": "new-bao-uid",
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"resources": {"requests": {"storage": "20Gi"}},
|
"resources": {"requests": {"storage": "20Gi"}},
|
||||||
},
|
},
|
||||||
@ -78,9 +78,9 @@ def test_repair_flow_classifies_blockers_attempts_reclaim_and_avoids_blind_healt
|
|||||||
return {
|
return {
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"metadata": {"name": "prole-iscsi-d001-garage"},
|
"metadata": {"name": "synology-iscsi-d001-garage"},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"capacity": {"storage": "20Gi"},
|
"capacity": {"storage": "20Gi"},
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"claimRef": {
|
"claimRef": {
|
||||||
@ -92,9 +92,9 @@ def test_repair_flow_classifies_blockers_attempts_reclaim_and_avoids_blind_healt
|
|||||||
"status": {"phase": "Released"},
|
"status": {"phase": "Released"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"metadata": {"name": "prole-iscsi-d001-openbao"},
|
"metadata": {"name": "synology-iscsi-d001-openbao"},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"capacity": {"storage": "20Gi"},
|
"capacity": {"storage": "20Gi"},
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"claimRef": {
|
"claimRef": {
|
||||||
@ -184,8 +184,8 @@ def test_repair_flow_classifies_blockers_attempts_reclaim_and_avoids_blind_healt
|
|||||||
|
|
||||||
# Reclaim was attempted for matching stale Released PVs.
|
# Reclaim was attempted for matching stale Released PVs.
|
||||||
patched = [c for c in calls if c[:3] == ["kubectl", "patch", "pv"]]
|
patched = [c for c in calls if c[:3] == ["kubectl", "patch", "pv"]]
|
||||||
assert any("prole-iscsi-d001-garage" in c for c in patched)
|
assert any("synology-iscsi-d001-garage" in c for c in patched)
|
||||||
assert any("prole-iscsi-d001-openbao" in c for c in patched)
|
assert any("synology-iscsi-d001-openbao" in c for c in patched)
|
||||||
|
|
||||||
# Explicit scheduling/storage classification is surfaced.
|
# Explicit scheduling/storage classification is surfaced.
|
||||||
assert "Storage blockers" in msg
|
assert "Storage blockers" in msg
|
||||||
|
|||||||
@ -155,7 +155,7 @@ def test_reset_reclaim_stale_released_pvs_patches_concrete_garage_and_openbao(
|
|||||||
"uid": "new-garage-uid",
|
"uid": "new-garage-uid",
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"resources": {"requests": {"storage": "10Gi"}},
|
"resources": {"requests": {"storage": "10Gi"}},
|
||||||
},
|
},
|
||||||
@ -168,7 +168,7 @@ def test_reset_reclaim_stale_released_pvs_patches_concrete_garage_and_openbao(
|
|||||||
"uid": "new-bao-uid",
|
"uid": "new-bao-uid",
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"resources": {"requests": {"storage": "10Gi"}},
|
"resources": {"requests": {"storage": "10Gi"}},
|
||||||
},
|
},
|
||||||
@ -178,9 +178,9 @@ def test_reset_reclaim_stale_released_pvs_patches_concrete_garage_and_openbao(
|
|||||||
|
|
||||||
released_pvs = [
|
released_pvs = [
|
||||||
{
|
{
|
||||||
"metadata": {"name": "prole-iscsi-d001-garage"},
|
"metadata": {"name": "synology-iscsi-d001-garage"},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"capacity": {"storage": "20Gi"},
|
"capacity": {"storage": "20Gi"},
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"claimRef": {
|
"claimRef": {
|
||||||
@ -192,9 +192,9 @@ def test_reset_reclaim_stale_released_pvs_patches_concrete_garage_and_openbao(
|
|||||||
"status": {"phase": "Released"},
|
"status": {"phase": "Released"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"metadata": {"name": "prole-iscsi-d001-openbao"},
|
"metadata": {"name": "synology-iscsi-d001-openbao"},
|
||||||
"spec": {
|
"spec": {
|
||||||
"storageClassName": "prole-iscsi",
|
"storageClassName": "synology-iscsi",
|
||||||
"capacity": {"storage": "20Gi"},
|
"capacity": {"storage": "20Gi"},
|
||||||
"accessModes": ["ReadWriteOnce"],
|
"accessModes": ["ReadWriteOnce"],
|
||||||
"claimRef": {
|
"claimRef": {
|
||||||
@ -237,8 +237,8 @@ def test_reset_reclaim_stale_released_pvs_patches_concrete_garage_and_openbao(
|
|||||||
assert changed is True
|
assert changed is True
|
||||||
|
|
||||||
patched = [c for c in calls if c[:3] == ["kubectl", "patch", "pv"]]
|
patched = [c for c in calls if c[:3] == ["kubectl", "patch", "pv"]]
|
||||||
assert any("prole-iscsi-d001-garage" in c for c in patched)
|
assert any("synology-iscsi-d001-garage" in c for c in patched)
|
||||||
assert any("prole-iscsi-d001-openbao" in c for c in patched)
|
assert any("synology-iscsi-d001-openbao" in c for c in patched)
|
||||||
assert all('{"spec":{"claimRef":null}}' in c for c in patched)
|
assert all('{"spec":{"claimRef":null}}' in c for c in patched)
|
||||||
|
|
||||||
# Reset policy: never delete PVs.
|
# Reset policy: never delete PVs.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user