mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 10:13:58 +00:00
Refactor iSCSI Synology mounts to /synology/d00x
- Rename host mount namespace from /prole/d00x to /synology/d00x - Make LUN ownership explicit per host in inventory (myrddin=d001; merlin=d002,d004; pi=d003) - Add safe migration cleanup for legacy /prole/d00x mounts and stale /etc/fstab entries - Update k3s/ArgoCD/OpenTofu manifests and PV node affinities to match new mount paths - Improve iSCSI role check-mode behavior and add quiesce/detach flow in ansible.sh
This commit is contained in:
parent
0943186d08
commit
2244d6acd6
@ -74,6 +74,13 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
# Default to k3s hosts for the main site run (avoid touching non-k3s Linux/Pi hosts unless explicitly requested)
|
||||
if [[ -z "${LIMIT}" ]]; then
|
||||
if [[ "${PLAYBOOK}" =~ (^|/)infrastructure/playbooks/site\.yml$ ]]; then
|
||||
LIMIT="k3s_hosts"
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
ts="$(date +%Y%m%d-%H%M%S)"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
; Prole Master Configuration File
|
||||
; Generated by install.py on 2026-03-20 16:11:36
|
||||
; Generated by install.py on 2026-03-20 16:59:08
|
||||
; This file is used as input for Ansible deployment and k8s cluster creation.
|
||||
|
||||
[User]
|
||||
@ -36,7 +36,7 @@ dependencies.opentofu.install = true
|
||||
dependencies.python.install = true
|
||||
dependencies.verify_all = false
|
||||
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 =
|
||||
env_setup.NAMESPACE = ${NAMESPACE}
|
||||
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||
@ -49,9 +49,9 @@ init_cluster.at_rest_encryption_enabled = true
|
||||
init_cluster.cluster_env = prod
|
||||
init_cluster.deployment_target = prole-prod-cluster
|
||||
init_cluster.gitops_enabled = false
|
||||
init_cluster.k3s_server_url =
|
||||
init_cluster.k3s_token =
|
||||
init_cluster.kerberos_enabled = false
|
||||
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
||||
init_cluster.k3s_token = ${PROLE_SECRET:v1:byngYfgT7BPkndc5:TukgM2QvPylhorfIm0t-tPysEPq-Lvc8lqbv594nzDsJxc6Kj6J9walkiVQS6o18ZJYNU7xpuYsRWV1yyZW8RBxvPi-glfs7C-sdj6Q3mwia2A9jLcxyJMck3_8z4L-mc7utmo8PIxw0MnjeF8P_Ixzoyi4cM3WoKtZiyA==}
|
||||
init_cluster.kerberos_enabled = true
|
||||
init_cluster.mode = k8s
|
||||
init_cluster.start_cluster = true
|
||||
init_cluster.supabase_enabled = false
|
||||
@ -65,15 +65,15 @@ init_password.db_password_confirm =
|
||||
init_password.db_username = root
|
||||
init_password.generate_ssh_key = true
|
||||
init_scripts.run_scripts = true
|
||||
kerberos_config.enabled = false
|
||||
kerberos_config.kdc =
|
||||
kerberos_config.password = ${PROLE_SECRET:v1:3vn_jWdWyDkkLs4m:k5wERNl46EUEa4QReopiBD6daCtPdE8Mkcp2zYyaMu7OMr2d}
|
||||
kerberos_config.realm =
|
||||
kerberos_config.enabled = true
|
||||
kerberos_config.kdc = 10.0.0.3
|
||||
kerberos_config.password = ${PROLE_SECRET:v1:A6qvhIB8BlPEcQjO:0tFeTyOFqqkn13rROLkgcJ9NgYmVYRD1ZjJzCAeFwfrgSxQx}
|
||||
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 =
|
||||
ollama_config.server_host = fairyland.prole.org
|
||||
ollama_config.server_port = 11434
|
||||
|
||||
[Global]
|
||||
@ -87,8 +87,9 @@ DOCKER_PRELOAD = false
|
||||
NAMESPACE = prole-db
|
||||
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
||||
PROLE_DB_USER = root
|
||||
PROLE_K3S_SERVER =
|
||||
PROLE_K3S_TOKEN =
|
||||
PROLE_HOME = $HOME/dev/prole
|
||||
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
||||
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:dQZZFvDfN_I8bFPY:yr9laHz55aM5lL_QTnBim1m0xBpX5SgfOPOVp-2HwLdii-2TNnT0gSAuWqSjgwI9JSoMT3QfD2lavVF2qMoWh9SFN8idZ3-VIYRsiZ7SM2BOiS_sbOG3_QDucvciuIxy5MXNyFEmxOGTtXwyzC1cnQjlsiEnKy0XbFF7dA==}
|
||||
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
||||
SERVICE_NAMESPACE = knoe-system
|
||||
|
||||
@ -107,12 +108,18 @@ 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]
|
||||
; 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]
|
||||
; No configuration values captured yet for this section.
|
||||
@ -121,7 +128,10 @@ KDC_ANSIBLE_DETECTED = 10.0.0.3
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[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]
|
||||
; No configuration values captured yet for this section.
|
||||
@ -144,13 +154,13 @@ MODE = k3d
|
||||
[Service Cluster (k3s)]
|
||||
CLUSTER_ENV = prole-service-cluster
|
||||
DISPLAY_NAME = prole-service-cluster
|
||||
K3S_SERVER_URL =
|
||||
K3S_TOKEN =
|
||||
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||
K3S_TOKEN = ${PROLE_SECRET:v1:_iFv8sZdDHQxTxd4:a3RRUkKtO9ctIm_393LrEg9Lq9tN1Sfl7B3TZLnSwEXEKgpNnp9VAeicvFy8kV4unSX99yXZPhTf3RbTQ7qaTt4Oj8vU9aFK905qa5BVPOzmAZo_10mTcfXYTOeNXALl4sprStWambtJ4CEYol3XsIXFywzGq1jkldPyLw==}
|
||||
MODE = k3s
|
||||
PIPELINE_URL = http://127.0.0.1:8080
|
||||
|
||||
[Prod Cluster (k8s)]
|
||||
ARTIFACTS_DIR = /private/var/folders/rt/pywlnmxj3dn7t5552vwdcpp80000gn/T/pytest-of-chrisfu/pytest-26/test_encryption_toggle0/data/staging
|
||||
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
|
||||
CLUSTER_ENV = prole-prod-cluster
|
||||
DISPLAY_NAME = prole-prod-cluster
|
||||
MODE = k8s
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
; Prole Master Configuration File
|
||||
; Generated by install.py on 2026-03-20 16:10:22
|
||||
; Generated by install.py on 2026-03-20 17:05:22
|
||||
; This file is used as input for Ansible deployment and k8s cluster creation.
|
||||
|
||||
[User]
|
||||
@ -36,7 +36,7 @@ dependencies.opentofu.install = true
|
||||
dependencies.python.install = true
|
||||
dependencies.verify_all = false
|
||||
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 =
|
||||
env_setup.NAMESPACE = ${NAMESPACE}
|
||||
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
|
||||
@ -49,9 +49,9 @@ 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 =
|
||||
init_cluster.k3s_token =
|
||||
init_cluster.kerberos_enabled = false
|
||||
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
||||
init_cluster.k3s_token = ${PROLE_SECRET:v1:s4MdUcnQRJBPdAss:irg5n342LjxLeLV8kGtoAAO_Od3QcmWtTXLQbPw2o2mUJrRnNEBOhN-z4Q6J3UZylEKp6ZhmD_TdRGqdpfpC79j1kFtaTPWCvl_cdHHiG9580AQ87V4XmtAwEh-_ICm4GS35szQHELlXkJH4j7CvfAngW8RW_1nvtLHQyQ==}
|
||||
init_cluster.kerberos_enabled = true
|
||||
init_cluster.mode = k3s
|
||||
init_cluster.start_cluster = true
|
||||
init_cluster.supabase_enabled = false
|
||||
@ -60,37 +60,37 @@ 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 = ${OPENBAO:kv/prole/knoe-db/db#password}
|
||||
init_password.db_password_confirm = ${OPENBAO:kv/prole/knoe-db/db#password}
|
||||
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 = false
|
||||
kerberos_config.kdc =
|
||||
kerberos_config.password = ${OPENBAO:kv/prole/knoe-db/kerberos#password}
|
||||
kerberos_config.realm =
|
||||
kerberos_config.enabled = true
|
||||
kerberos_config.kdc = 10.0.0.3
|
||||
kerberos_config.password = ${PROLE_SECRET:v1:1zuEATgIOtkCPTIi:w2eKBUzce6mq6BJAlefU9cl6K05A9EDT81AQ1uSVzgI1NbUY}
|
||||
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 =
|
||||
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 = ${OPENBAO:kv/prole/knoe-db/db#password}
|
||||
DB_PASSWORD =
|
||||
DEPLOYMENT_MODE = k3s
|
||||
DEPLOYMENT_TARGET = prole-service-cluster
|
||||
DOCKER_IMPORT_DIR =
|
||||
DOCKER_PRELOAD = false
|
||||
NAMESPACE = knoe-db
|
||||
KUBECONTEXT = prole-k3s
|
||||
NAMESPACE = prole-db
|
||||
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
|
||||
PROLE_DB_USER = root
|
||||
PROLE_K3S_SERVER =
|
||||
PROLE_K3S_TOKEN =
|
||||
PROLE_HOME = $HOME/dev/prole
|
||||
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
||||
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:SNcp3N71DMccQw5G:UXmhfoiN8PKqw3jaarQxhhv5rtPjjUQTRSVo4pS6FkmHqLDt1xghL4RfgBdcaR5HA9lnlDc5jFpLruIrC1ivxk5HssTn1prde0lKvhioO7SkIOSl6HsA4XXosf6KveNASpxCdeZ6RkZlg2i7jpHxvxX3zbIrSKNISN5gEQ==}
|
||||
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
||||
SERVICE_NAMESPACE = knoe-system
|
||||
|
||||
@ -109,12 +109,18 @@ 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]
|
||||
; 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]
|
||||
; No configuration values captured yet for this section.
|
||||
@ -123,10 +129,16 @@ KDC_ANSIBLE_DETECTED = 10.0.0.3
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[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]
|
||||
AT_REST_ENCRYPTION_ENABLED = True
|
||||
GITOPS_ENABLED = False
|
||||
KERBEROS_ENABLED = True
|
||||
SUPABASE_ENABLED = False
|
||||
|
||||
[GitOps]
|
||||
; No configuration values captured yet for this section.
|
||||
@ -135,24 +147,26 @@ GITOPS_ENABLED = False
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Initialize Cluster]
|
||||
; No configuration values captured yet for this section.
|
||||
ENVIRONMENT = service
|
||||
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||
K3S_TOKEN = ${PROLE_SECRET:v1:570CIZjbSCH131v_:pDQwbH9nKYsCl5z0f-iAb-cilZlo1KLpI16c6Hgj0Ic81Jk1I7CSjEFo5UJ1ezV_pdat-7kxhaWE_TxCXG6ZnuOA8SBh3xCCi1LsgYFluPwm47b4IaS5ftvMOe5TVWbQfnzsXuU4SdO_3O9mgagKHdDIzu8kufYfpeDyqA==}
|
||||
|
||||
[Dev Cluster (k3d)]
|
||||
CLUSTER_ENV = dev
|
||||
DISPLAY_NAME = knoe-dev-cluster
|
||||
KUBECTL_CONTEXT =
|
||||
KUBECTL_CONTEXT = prole-k3s
|
||||
MODE = k3d
|
||||
|
||||
[Service Cluster (k3s)]
|
||||
CLUSTER_ENV = prole-service-cluster
|
||||
DISPLAY_NAME = prole-service-cluster
|
||||
K3S_SERVER_URL =
|
||||
K3S_TOKEN =
|
||||
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 = /private/var/folders/rt/pywlnmxj3dn7t5552vwdcpp80000gn/T/pytest-of-chrisfu/pytest-25/test_encryption_toggle0/data/staging
|
||||
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
|
||||
CLUSTER_ENV = prole-prod-cluster
|
||||
DISPLAY_NAME = prole-prod-cluster
|
||||
MODE = k8s
|
||||
|
||||
@ -14,7 +14,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/data
|
||||
path: /synology/d001/data
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -40,7 +40,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/wal
|
||||
path: /synology/d001/wal
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -66,7 +66,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/garage
|
||||
path: /synology/d001/garage
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -92,7 +92,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d002/data
|
||||
path: /synology/d002/data
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -100,7 +100,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- merlin.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -118,7 +118,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d002/wal
|
||||
path: /synology/d002/wal
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -126,7 +126,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- merlin.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -144,7 +144,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d003/data
|
||||
path: /synology/d003/data
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -152,7 +152,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- pi.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -170,7 +170,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d003/wal
|
||||
path: /synology/d003/wal
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -178,7 +178,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- pi.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -196,7 +196,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d003/grafana
|
||||
path: /synology/d003/grafana
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -204,7 +204,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- pi.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -222,7 +222,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d002/prometheus
|
||||
path: /synology/d002/prometheus
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -230,7 +230,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- merlin.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -248,7 +248,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/openbao
|
||||
path: /synology/d001/openbao
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
|
||||
@ -4,7 +4,7 @@ metadata:
|
||||
name: prole-db
|
||||
spec:
|
||||
instances: 3
|
||||
imageName: myrddin.prole.org:5000/prole-db:18-129
|
||||
imageName: myrddin.prole.org:5000/prole-db:0.0.0
|
||||
postgresUID: 100
|
||||
postgresGID: 101
|
||||
maxSyncReplicas: 1
|
||||
|
||||
@ -49,6 +49,25 @@ CNPG_MANIFEST_OVERRIDE=${CNPG_MANIFEST_OVERRIDE:-}
|
||||
PROLE_HOME=${PROLE_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)}
|
||||
BACKUP_DIR=${BACKUP_DIR:-$PROLE_HOME/prole/backup}
|
||||
BACKUP_WAIT_TIMEOUT=${BACKUP_WAIT_TIMEOUT:-1800}
|
||||
|
||||
# CNPG staged topology controls
|
||||
# - CNPG_TOPOLOGY=auto (default): use stage-1 pinning if CNPG_STAGE1_NODE exists, otherwise label-based
|
||||
# - CNPG_TOPOLOGY=stage1: pin CNPG pods to CNPG_STAGE1_NODE and relax anti-affinity to preferred
|
||||
# - CNPG_TOPOLOGY=label: keep manifest label-based and keep anti-affinity as-is
|
||||
CNPG_TOPOLOGY=${CNPG_TOPOLOGY:-auto}
|
||||
CNPG_STAGE1_NODE=${CNPG_STAGE1_NODE:-myrddin.prole.org}
|
||||
CNPG_DB_NODE_SELECTOR=${CNPG_DB_NODE_SELECTOR:-}
|
||||
CNPG_ALLOW_COLOCATED_INSTANCES=${CNPG_ALLOW_COLOCATED_INSTANCES:-}
|
||||
CNPG_POD_ANTI_AFFINITY_TYPE=${CNPG_POD_ANTI_AFFINITY_TYPE:-}
|
||||
|
||||
# Barman plugin identity (used for readiness checks)
|
||||
BARMAN_PLUGIN_NAME=${BARMAN_PLUGIN_NAME:-barman-cloud.cloudnative-pg.io}
|
||||
|
||||
# Barman readiness timeouts (seconds). Keep them overridable for testability.
|
||||
BARMAN_CRD_TIMEOUT=${BARMAN_CRD_TIMEOUT:-120}
|
||||
BARMAN_TLS_TIMEOUT=${BARMAN_TLS_TIMEOUT:-180}
|
||||
BARMAN_DEPLOY_TIMEOUT=${BARMAN_DEPLOY_TIMEOUT:-180}
|
||||
BARMAN_SERVICE_TIMEOUT=${BARMAN_SERVICE_TIMEOUT:-180}
|
||||
if [[ "${PROLE_MODE:-}" == "k3s" ]]; then
|
||||
CNPG_WAIT_TIMEOUT=${CNPG_WAIT_TIMEOUT:-900}
|
||||
else
|
||||
@ -919,12 +938,8 @@ wait_for_barman_tls_secrets() {
|
||||
start_time=$(date +%s)
|
||||
echo "Waiting for Barman Cloud TLS secrets (timeout: ${timeout}s)..."
|
||||
while true; do
|
||||
local client_crt client_key server_crt server_key
|
||||
client_crt=$(kubectl -n cnpg-system get secret barman-cloud-client-tls -o jsonpath='{.data.tls\.crt}' 2>/dev/null || true)
|
||||
client_key=$(kubectl -n cnpg-system get secret barman-cloud-client-tls -o jsonpath='{.data.tls\.key}' 2>/dev/null || true)
|
||||
server_crt=$(kubectl -n cnpg-system get secret barman-cloud-server-tls -o jsonpath='{.data.tls\.crt}' 2>/dev/null || true)
|
||||
server_key=$(kubectl -n cnpg-system get secret barman-cloud-server-tls -o jsonpath='{.data.tls\.key}' 2>/dev/null || true)
|
||||
if [[ -n "$client_crt" && -n "$client_key" && -n "$server_crt" && -n "$server_key" ]]; then
|
||||
if kubectl -n cnpg-system get secret barman-cloud-client-tls >/dev/null 2>&1 \
|
||||
&& kubectl -n cnpg-system get secret barman-cloud-server-tls >/dev/null 2>&1; then
|
||||
echo "Barman Cloud TLS secrets are available."
|
||||
return 0
|
||||
fi
|
||||
@ -940,6 +955,46 @@ wait_for_barman_tls_secrets() {
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_barman_plugin_service_registration() {
|
||||
local timeout=${1:-180}
|
||||
local start_time
|
||||
start_time=$(date +%s)
|
||||
|
||||
echo "Waiting for Barman plugin service registration (timeout: ${timeout}s)..."
|
||||
while true; do
|
||||
local svc_name client_secret server_secret plugin_port endpoints
|
||||
svc_name=$(kubectl -n cnpg-system get svc -l "cnpg.io/pluginName=$BARMAN_PLUGIN_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
|
||||
if [[ -z "$svc_name" ]]; then
|
||||
svc_name=$(kubectl -n cnpg-system get svc barman-cloud -o jsonpath='{.metadata.name}' 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [[ -n "$svc_name" ]]; then
|
||||
client_secret=$(kubectl -n cnpg-system get svc "$svc_name" -o jsonpath='{.metadata.annotations.cnpg\.io/pluginClientSecret}' 2>/dev/null || true)
|
||||
server_secret=$(kubectl -n cnpg-system get svc "$svc_name" -o jsonpath='{.metadata.annotations.cnpg\.io/pluginServerSecret}' 2>/dev/null || true)
|
||||
plugin_port=$(kubectl -n cnpg-system get svc "$svc_name" -o jsonpath='{.metadata.annotations.cnpg\.io/pluginPort}' 2>/dev/null || true)
|
||||
endpoints=$(kubectl -n cnpg-system get endpoints "$svc_name" -o jsonpath='{.subsets[*].addresses[*].ip}' 2>/dev/null || true)
|
||||
|
||||
if [[ -n "$client_secret" && -n "$server_secret" && -n "$plugin_port" && -n "$endpoints" ]]; then
|
||||
if kubectl -n cnpg-system get secret "$client_secret" >/dev/null 2>&1 && kubectl -n cnpg-system get secret "$server_secret" >/dev/null 2>&1; then
|
||||
echo "Barman plugin service registration is ready (service=${svc_name}, port=${plugin_port})."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
local elapsed=$(( $(date +%s) - start_time ))
|
||||
if (( elapsed > timeout )); then
|
||||
echo "Barman plugin service registration not ready after ${elapsed}s." >&2
|
||||
kubectl -n cnpg-system get svc,ep 2>/dev/null >&2 || true
|
||||
return 1
|
||||
fi
|
||||
if (( elapsed % 30 < 6 && elapsed > 5 )); then
|
||||
echo " [${elapsed}s/${timeout}s] Still waiting for barman plugin service registration..."
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
|
||||
ensure_barman_plugin() {
|
||||
ensure_cert_manager
|
||||
|
||||
@ -955,25 +1010,28 @@ ensure_barman_plugin() {
|
||||
kubectl -n cert-manager rollout status deploy/cert-manager-webhook --timeout=180s >/dev/null 2>&1 || true
|
||||
kubectl -n cert-manager rollout status deploy/cert-manager --timeout=180s >/dev/null 2>&1 || true
|
||||
kubectl -n cert-manager rollout status deploy/cert-manager-cainjector --timeout=180s >/dev/null 2>&1 || true
|
||||
kubectl apply -f "$plugin_url" || true
|
||||
if ! kubectl apply -f "$plugin_url" >/dev/null 2>&1; then
|
||||
echo "ERROR: Failed to apply Barman Cloud plugin manifest after cert-manager restart." >&2
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "ERROR: Failed to apply Barman Cloud plugin manifest." >&2
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
printf '%s\n' "$apply_out"
|
||||
fi
|
||||
|
||||
if ! wait_for_barman_crd 120; then
|
||||
echo "WARN: Barman Cloud ObjectStore CRD not ready after install." >&2
|
||||
fi
|
||||
|
||||
if ! wait_for_barman_tls_secrets 180; then
|
||||
echo "WARN: Barman Cloud TLS secrets not ready after install." >&2
|
||||
fi
|
||||
wait_for_barman_crd "$BARMAN_CRD_TIMEOUT"
|
||||
wait_for_barman_tls_secrets "$BARMAN_TLS_TIMEOUT"
|
||||
|
||||
pin_barman_cloud
|
||||
|
||||
if kubectl -n cnpg-system get deploy barman-cloud >/dev/null 2>&1; then
|
||||
kubectl -n cnpg-system rollout status deploy/barman-cloud --timeout=180s || true
|
||||
kubectl -n cnpg-system rollout status deploy/barman-cloud --timeout="${BARMAN_DEPLOY_TIMEOUT}s"
|
||||
fi
|
||||
|
||||
wait_for_barman_plugin_service_registration "$BARMAN_SERVICE_TIMEOUT"
|
||||
}
|
||||
|
||||
pin_cnpg_controller() {
|
||||
@ -1415,8 +1473,8 @@ ensure_prole_stack_resources() {
|
||||
done
|
||||
prole_render_manifest "$dir/ingress.yaml" | kubectl_apply_retry "" || true
|
||||
fi
|
||||
apply_barman_objectstore_if_present
|
||||
apply_cnpg_cluster_manifest "$CNPG_MANIFEST_OVERRIDE"
|
||||
ensure_cnpg_cluster_scheduling || true
|
||||
validate_cnpg_runtime_storage
|
||||
reconcile_cnpg_instances
|
||||
else
|
||||
@ -1456,8 +1514,8 @@ ensure_prole_stack_resources() {
|
||||
done
|
||||
prole_render_manifest "$dir/ingress.yaml" | kubectl_apply_retry "" || true
|
||||
fi
|
||||
apply_barman_objectstore_if_present
|
||||
apply_cnpg_cluster_manifest "$CNPG_MANIFEST"
|
||||
ensure_cnpg_cluster_scheduling || true
|
||||
validate_cnpg_runtime_storage
|
||||
reconcile_cnpg_instances
|
||||
fi
|
||||
@ -1492,15 +1550,125 @@ _coerce_uint() {
|
||||
fi
|
||||
}
|
||||
|
||||
_cnpg_node_exists() {
|
||||
local node_name="${1:-}"
|
||||
[[ -n "$node_name" ]] || return 1
|
||||
local out
|
||||
out=$(kubectl get node "$node_name" -o jsonpath='{.metadata.name}' 2>/dev/null || true)
|
||||
[[ "$out" == "$node_name" ]]
|
||||
}
|
||||
|
||||
_cnpg_effective_topology() {
|
||||
local t="${CNPG_TOPOLOGY:-auto}"
|
||||
case "$t" in
|
||||
stage1|stage-1|stage1-single-node|single-node)
|
||||
echo "stage1"
|
||||
return 0
|
||||
;;
|
||||
label|labels|label-db)
|
||||
echo "label"
|
||||
return 0
|
||||
;;
|
||||
auto|'')
|
||||
if _cnpg_node_exists "${CNPG_STAGE1_NODE:-myrddin.prole.org}"; then
|
||||
echo "stage1"
|
||||
else
|
||||
echo "label"
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
echo "label"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_cnpg_effective_node_selector() {
|
||||
if [[ -n "${CNPG_DB_NODE_SELECTOR:-}" ]]; then
|
||||
echo "$CNPG_DB_NODE_SELECTOR"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$(_cnpg_effective_topology)" == "stage1" ]]; then
|
||||
echo "kubernetes.io/hostname=${CNPG_STAGE1_NODE:-myrddin.prole.org}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "${CNPG_NODE_ROLE_LABEL_KEY:-prole.org/node-role}=${CNPG_NODE_ROLE_LABEL_VALUE:-db}"
|
||||
}
|
||||
|
||||
_cnpg_allow_colocated_instances() {
|
||||
local v="${CNPG_ALLOW_COLOCATED_INSTANCES:-}"
|
||||
if [[ -n "$v" ]]; then
|
||||
local v_lc
|
||||
v_lc=$(printf '%s' "$v" | tr '[:upper:]' '[:lower:]')
|
||||
case "$v_lc" in
|
||||
1|true|yes|y) return 0 ;;
|
||||
0|false|no|n) return 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
[[ "$(_cnpg_effective_topology)" == "stage1" ]]
|
||||
}
|
||||
|
||||
patch_cnpg_manifest_for_topology() {
|
||||
# Best-effort patch for stage-1 (single-node) scheduling: pin to CNPG_STAGE1_NODE and
|
||||
# relax anti-affinity so all instances can schedule on one node.
|
||||
local manifest_file="$1"
|
||||
[[ -f "$manifest_file" ]] || return 0
|
||||
|
||||
if [[ "$(_cnpg_effective_topology)" != "stage1" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local host anti
|
||||
host="${CNPG_STAGE1_NODE:-myrddin.prole.org}"
|
||||
anti="${CNPG_POD_ANTI_AFFINITY_TYPE:-preferred}"
|
||||
|
||||
local tmp
|
||||
tmp=$(mktemp -t prole-cnpg-topo.XXXXXX)
|
||||
sed -E \
|
||||
-e "s/^([[:space:]]*podAntiAffinityType:)[[:space:]]*required[[:space:]]*$/\\1 ${anti}/" \
|
||||
-e 's/^([[:space:]]*-[[:space:]]*key:)[[:space:]]*prole\.org\/node-role[[:space:]]*$/\1 kubernetes.io\/hostname/' \
|
||||
-e "s/^([[:space:]]*-[[:space:]]*)db[[:space:]]*$/\\1${host}/" \
|
||||
"$manifest_file" >"$tmp"
|
||||
mv "$tmp" "$manifest_file"
|
||||
}
|
||||
|
||||
ensure_cnpg_cluster_scheduling() {
|
||||
# Enforce the effective topology on the live Cluster object.
|
||||
if ! kubectl -n "$NAMESPACE" get cluster "$CNPG_CLUSTER_NAME" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local selector key val topo anti
|
||||
topo="$(_cnpg_effective_topology)"
|
||||
selector="$(_cnpg_effective_node_selector)"
|
||||
key="${selector%%=*}"
|
||||
val="${selector#*=}"
|
||||
|
||||
anti="${CNPG_POD_ANTI_AFFINITY_TYPE:-}"
|
||||
if [[ -z "$anti" ]]; then
|
||||
if [[ "$topo" == "stage1" || "$(_cnpg_allow_colocated_instances && echo 1 || echo 0)" == "1" ]]; then
|
||||
anti="preferred"
|
||||
else
|
||||
anti="required"
|
||||
fi
|
||||
fi
|
||||
|
||||
kubectl -n "$NAMESPACE" patch cluster "$CNPG_CLUSTER_NAME" --type merge -p "{\"spec\":{\"affinity\":{\"enablePodAntiAffinity\":true,\"podAntiAffinityType\":\"${anti}\",\"topologyKey\":\"kubernetes.io/hostname\",\"nodeAffinity\":{\"requiredDuringSchedulingIgnoredDuringExecution\":{\"nodeSelectorTerms\":[{\"matchExpressions\":[{\"key\":\"${key}\",\"operator\":\"In\",\"values\":[\"${val}\"]}]}]}}}}}}" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
_ready_schedulable_nodes_count() {
|
||||
kubectl get nodes --no-headers 2>/dev/null \
|
||||
| awk '$2 ~ /^Ready/ && $2 !~ /SchedulingDisabled/ {c++} END {print c+0}'
|
||||
}
|
||||
|
||||
_ready_schedulable_db_nodes_count() {
|
||||
local key="${CNPG_NODE_ROLE_LABEL_KEY:-prole.org/node-role}"
|
||||
local val="${CNPG_NODE_ROLE_LABEL_VALUE:-db}"
|
||||
kubectl get nodes -l "${key}=${val}" --no-headers 2>/dev/null \
|
||||
local selector
|
||||
selector=$(_cnpg_effective_node_selector)
|
||||
kubectl get nodes -l "$selector" --no-headers 2>/dev/null \
|
||||
| awk '$2 ~ /^Ready/ && $2 !~ /SchedulingDisabled/ {c++} END {print c+0}'
|
||||
}
|
||||
|
||||
@ -1515,17 +1683,28 @@ reconcile_cnpg_instances() {
|
||||
[[ -z "$current" ]] && return 0
|
||||
current=$(_coerce_uint "$current" 0)
|
||||
|
||||
local allow_colocated=0
|
||||
if _cnpg_allow_colocated_instances; then
|
||||
allow_colocated=1
|
||||
fi
|
||||
|
||||
local min_required
|
||||
min_required=$(_coerce_uint "${OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES:-2}" 2)
|
||||
if (( min_required < 1 )); then
|
||||
min_required=1
|
||||
fi
|
||||
# Stage-1 single-node evaluation is an explicit mode; do not force scale-down
|
||||
# solely due to node-count heuristics.
|
||||
if (( allow_colocated == 1 )); then
|
||||
min_required=1
|
||||
fi
|
||||
|
||||
local ready_nodes eligible_db_nodes
|
||||
local ready_nodes eligible_nodes selector
|
||||
selector=$(_cnpg_effective_node_selector)
|
||||
ready_nodes=$(_coerce_uint "$(_ready_schedulable_nodes_count)" 0)
|
||||
eligible_db_nodes=$(_coerce_uint "$(_ready_schedulable_db_nodes_count)" 0)
|
||||
if (( eligible_db_nodes < 1 )); then
|
||||
echo "ERROR: No Ready, schedulable CNPG DB nodes found (label ${CNPG_NODE_ROLE_LABEL_KEY:-prole.org/node-role}=${CNPG_NODE_ROLE_LABEL_VALUE:-db})." >&2
|
||||
eligible_nodes=$(_coerce_uint "$(_ready_schedulable_db_nodes_count)" 0)
|
||||
if (( eligible_nodes < 1 )); then
|
||||
echo "ERROR: No Ready, schedulable CNPG eligible nodes found (selector ${selector})." >&2
|
||||
echo "Refusing to force CNPG pods onto an arbitrary node during bootstrap." >&2
|
||||
return 1
|
||||
fi
|
||||
@ -1535,13 +1714,17 @@ reconcile_cnpg_instances() {
|
||||
if (( desired < 1 )); then
|
||||
desired=1
|
||||
fi
|
||||
if (( desired > eligible_db_nodes )); then
|
||||
desired=$eligible_db_nodes
|
||||
if (( allow_colocated == 0 )); then
|
||||
if (( desired > eligible_nodes )); then
|
||||
desired=$eligible_nodes
|
||||
fi
|
||||
fi
|
||||
|
||||
# Degraded cluster: keep instances at 1 until enough nodes are Ready+schedulable.
|
||||
if (( ready_nodes < min_required )); then
|
||||
desired=1
|
||||
if (( allow_colocated == 0 )); then
|
||||
if (( ready_nodes < min_required )); then
|
||||
desired=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( desired < 1 )); then
|
||||
@ -1569,7 +1752,7 @@ reconcile_cnpg_instances() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Reconciling CNPG cluster '$CNPG_CLUSTER_NAME' instances=${desired} (was ${current}; ready_nodes=${ready_nodes}; eligible_db_nodes=${eligible_db_nodes}) ..."
|
||||
echo "Reconciling CNPG cluster '$CNPG_CLUSTER_NAME' instances=${desired} (was ${current}; ready_nodes=${ready_nodes}; eligible_nodes=${eligible_nodes}; allow_colocated=${allow_colocated}) ..."
|
||||
|
||||
# CloudNativePG validates `maxSyncReplicas < instances`. When we temporarily
|
||||
# scale down to a single instance during degraded startup, we must also
|
||||
@ -1619,6 +1802,9 @@ apply_cnpg_cluster_manifest() {
|
||||
local tmp
|
||||
tmp=$(mktemp -t prole-cnpg.XXXXXX)
|
||||
prole_render_manifest "$manifest" >"$tmp"
|
||||
|
||||
patch_cnpg_manifest_for_topology "$tmp" || true
|
||||
|
||||
if ! validate_cnpg_manifest_storage "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
@ -2109,6 +2295,100 @@ reset_and_reinit() {
|
||||
wait_for_cnpg_pods "${CNPG_WAIT_TIMEOUT}"
|
||||
}
|
||||
|
||||
destroy_cnpg_cluster() {
|
||||
# Destroy only CNPG + backup resources (not the entire prole stack).
|
||||
# This is intended to support repeatable destroy/recreate/restore storage evaluation.
|
||||
local delete_pvcs
|
||||
delete_pvcs=$(_coerce_uint "${CNPG_DESTROY_DELETE_PVCS:-1}" 1)
|
||||
|
||||
# IMPORTANT: The recovery template uses `bootstrap.recovery.backup.name`, which requires the
|
||||
# Backup CR to exist at restore time. By default we keep Backup/ObjectStore CRs.
|
||||
local delete_backup_crs delete_objectstore_crs
|
||||
delete_backup_crs=$(_coerce_uint "${CNPG_DESTROY_DELETE_BACKUP_CRS:-0}" 0)
|
||||
delete_objectstore_crs=$(_coerce_uint "${CNPG_DESTROY_DELETE_OBJECTSTORE_CRS:-0}" 0)
|
||||
|
||||
echo "Destroying CNPG cluster '$CNPG_CLUSTER_NAME' in namespace '$NAMESPACE' ..."
|
||||
kubectl -n "$NAMESPACE" delete scheduledbackup --all --ignore-not-found 2>/dev/null || true
|
||||
if (( delete_backup_crs == 1 )); then
|
||||
kubectl -n "$NAMESPACE" delete backup --all --ignore-not-found 2>/dev/null || true
|
||||
fi
|
||||
if (( delete_objectstore_crs == 1 )); then
|
||||
kubectl -n "$NAMESPACE" delete objectstore --all --ignore-not-found 2>/dev/null || true
|
||||
fi
|
||||
|
||||
kubectl -n "$NAMESPACE" delete cluster "$CNPG_CLUSTER_NAME" --ignore-not-found
|
||||
kubectl -n "$NAMESPACE" wait --for=delete pod -l "cnpg.io/cluster=$CNPG_CLUSTER_NAME" --timeout=180s >/dev/null 2>&1 || true
|
||||
|
||||
if (( delete_pvcs == 1 )); then
|
||||
echo "Deleting PVCs for CNPG cluster '$CNPG_CLUSTER_NAME' (label cnpg.io/cluster=$CNPG_CLUSTER_NAME) ..."
|
||||
kubectl -n "$NAMESPACE" delete pvc -l "cnpg.io/cluster=$CNPG_CLUSTER_NAME" --ignore-not-found 2>/dev/null || true
|
||||
else
|
||||
echo "Leaving PVCs intact (CNPG_DESTROY_DELETE_PVCS=0)."
|
||||
fi
|
||||
|
||||
recycle_released_prole_iscsi_pvs || true
|
||||
}
|
||||
|
||||
restore_cnpg_cluster() {
|
||||
ensure_tools
|
||||
ensure_namespace
|
||||
ensure_cnpg_operator
|
||||
pin_cnpg_controller
|
||||
ensure_barman_plugin
|
||||
ensure_prole_protected_storage
|
||||
|
||||
if kubectl -n "$NAMESPACE" get cluster "$CNPG_CLUSTER_NAME" >/dev/null 2>&1; then
|
||||
echo "ERROR: CNPG cluster '$CNPG_CLUSTER_NAME' already exists in namespace '$NAMESPACE'." >&2
|
||||
echo "Run '$0 destroy' first (or delete the cluster) before restoring." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local backup_name
|
||||
backup_name="${BACKUP_NAME:-}"
|
||||
if [[ -z "$backup_name" ]]; then
|
||||
backup_name=$(latest_completed_backup_name)
|
||||
fi
|
||||
if [[ -z "$backup_name" ]]; then
|
||||
echo "ERROR: No completed backups found for restore (set BACKUP_NAME explicitly if needed)." >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -f "$RECOVERY_TEMPLATE" ]]; then
|
||||
echo "ERROR: Recovery template not found: $RECOVERY_TEMPLATE" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local image
|
||||
if [[ "$VERSION" == "latest" || -z "$VERSION" ]]; then
|
||||
image=$(get_latest_image)
|
||||
else
|
||||
image="prole-db:$VERSION"
|
||||
fi
|
||||
image=$(resolve_cnpg_image "$image")
|
||||
|
||||
local tmp_manifest
|
||||
tmp_manifest=$(mktemp -t prole-cnpg-restore.XXXXXX)
|
||||
sed \
|
||||
-e "s/{{BACKUP_NAME}}/${backup_name}/g" \
|
||||
-e "s|^ imageName:.*| imageName: ${image}|" \
|
||||
"$RECOVERY_TEMPLATE" >"$tmp_manifest"
|
||||
|
||||
echo "Restoring CNPG cluster '$CNPG_CLUSTER_NAME' from backup '$backup_name' using image '$image' ..."
|
||||
apply_cnpg_cluster_manifest "$tmp_manifest"
|
||||
ensure_cnpg_cluster_scheduling || true
|
||||
validate_cnpg_runtime_storage
|
||||
reconcile_cnpg_instances
|
||||
|
||||
rm -f "$tmp_manifest"
|
||||
|
||||
if ! wait_for_cnpg_pods "${CNPG_WAIT_TIMEOUT}"; then
|
||||
echo "ERROR: CNPG pods did not become ready after restore." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Ensuring CNPG continuous backups after restore (ObjectStore + plugin config + ScheduledBackup + first successful backup) ..."
|
||||
"$SCRIPT_DIR/init_cnpg_backup.sh" start
|
||||
}
|
||||
|
||||
recycle_released_prole_iscsi_pvs() {
|
||||
# StorageClass `prole-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.
|
||||
@ -2522,6 +2802,7 @@ deploy_cluster() {
|
||||
return 1
|
||||
fi
|
||||
apply_cnpg_cluster_manifest "$manifest"
|
||||
ensure_cnpg_cluster_scheduling || true
|
||||
validate_cnpg_runtime_storage
|
||||
reconcile_cnpg_instances
|
||||
|
||||
@ -2548,10 +2829,8 @@ case "$ACTION" in
|
||||
;;
|
||||
recreate)
|
||||
ensure_tools
|
||||
"$0" delete "$CNPG_CLUSTER_NAME"
|
||||
# Clean up PVCs left behind by the CNPG operator (not in static manifests)
|
||||
echo "Cleaning up PVCs in namespace '$NAMESPACE' ..."
|
||||
kubectl -n "$NAMESPACE" delete pvc --all --ignore-not-found 2>/dev/null || true
|
||||
ensure_namespace
|
||||
destroy_cnpg_cluster
|
||||
# Wait briefly for pods to fully terminate before re-creating
|
||||
echo "Waiting for pods to terminate in namespace '$NAMESPACE' ..."
|
||||
_wait_term=0
|
||||
@ -2565,6 +2844,14 @@ case "$ACTION" in
|
||||
done
|
||||
"$0" create "$CNPG_CLUSTER_NAME"
|
||||
;;
|
||||
destroy)
|
||||
ensure_tools
|
||||
ensure_namespace
|
||||
destroy_cnpg_cluster
|
||||
;;
|
||||
restore)
|
||||
restore_cnpg_cluster
|
||||
;;
|
||||
create)
|
||||
ensure_tools
|
||||
ensure_namespace
|
||||
@ -2593,13 +2880,13 @@ case "$ACTION" in
|
||||
ensure_namespace
|
||||
ensure_cnpg_operator
|
||||
pin_cnpg_controller
|
||||
ensure_barman_plugin
|
||||
if [[ ! -f "$CNPG_MANIFEST" ]]; then
|
||||
echo "ERROR: CNPG manifest not found at $CNPG_MANIFEST" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Starting CloudNative-PG cluster from $CNPG_MANIFEST in namespace $NAMESPACE..."
|
||||
prole_render_manifest "$CNPG_MANIFEST" | kubectl apply -n "$NAMESPACE" -f -
|
||||
apply_cnpg_cluster_manifest "$CNPG_MANIFEST"
|
||||
ensure_cnpg_cluster_scheduling || true
|
||||
reconcile_cnpg_instances
|
||||
;;
|
||||
stop)
|
||||
|
||||
@ -48,6 +48,8 @@ BARMAN_OBJECT_NAME=${BARMAN_OBJECT_NAME:-prole-db-barman-objectstore}
|
||||
BACKUP_STATUS_TIMEOUT=${BACKUP_STATUS_TIMEOUT:-600}
|
||||
BACKUP_STATUS_INTERVAL=${BACKUP_STATUS_INTERVAL:-10}
|
||||
PLUGIN_READY_TIMEOUT=${PLUGIN_READY_TIMEOUT:-180}
|
||||
OBJECTSTORE_READY_TIMEOUT=${OBJECTSTORE_READY_TIMEOUT:-180}
|
||||
OBJECTSTORE_READY_INTERVAL=${OBJECTSTORE_READY_INTERVAL:-5}
|
||||
|
||||
SCHEDULED_BACKUP_NAME=${SCHEDULED_BACKUP_NAME:-prole-db-scheduled-backup}
|
||||
SCHEDULED_BACKUP_CRON=${SCHEDULED_BACKUP_CRON:-"0 3 * * *"}
|
||||
@ -470,6 +472,94 @@ wait_for_plugin_ready() {
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_barman_plugin_infra_ready() {
|
||||
# Ensure the plugin controller and its registration artifacts (Service annotations + TLS secrets)
|
||||
# are present *before* patching the CNPG Cluster to depend on the plugin.
|
||||
local start_time now
|
||||
local deployment_rows ns ready replicas
|
||||
local plugin_deploy_ready plugin_ns svc_ns svc_name client_secret server_secret plugin_port
|
||||
start_time=$(date +%s)
|
||||
|
||||
while true; do
|
||||
plugin_deploy_ready=0
|
||||
plugin_ns=""
|
||||
|
||||
deployment_rows=$(kubectl get deployment -A -l app.kubernetes.io/name=barman-cloud -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.status.readyReplicas}{"\t"}{.status.replicas}{"\n"}{end}' 2>/dev/null || true)
|
||||
if [[ -z "$deployment_rows" ]]; then
|
||||
deployment_rows=$(kubectl get deployment -A -o jsonpath='{range .items[?(@.metadata.name=="barman-cloud")]}{.metadata.namespace}{"\t"}{.status.readyReplicas}{"\t"}{.status.replicas}{"\n"}{end}' 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
while IFS=$'\t' read -r ns ready replicas; do
|
||||
[[ -z "$ns" ]] && continue
|
||||
ready=${ready:-0}
|
||||
replicas=${replicas:-0}
|
||||
if (( ready >= 1 && replicas >= 1 )); then
|
||||
plugin_deploy_ready=1
|
||||
plugin_ns="$ns"
|
||||
break
|
||||
fi
|
||||
done <<< "$deployment_rows"
|
||||
|
||||
if (( plugin_deploy_ready == 1 )); then
|
||||
svc_ns="${plugin_ns:-$CNPG_OPERATOR_NAMESPACE}"
|
||||
svc_name=$(kubectl -n "$svc_ns" get svc -l "cnpg.io/pluginName=$BARMAN_PLUGIN_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
|
||||
if [[ -z "$svc_name" ]]; then
|
||||
svc_name=$(kubectl -n "$svc_ns" get svc barman-cloud -o jsonpath='{.metadata.name}' 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [[ -n "$svc_name" ]]; then
|
||||
client_secret=$(kubectl -n "$svc_ns" get svc "$svc_name" -o jsonpath='{.metadata.annotations.cnpg\.io/pluginClientSecret}' 2>/dev/null || true)
|
||||
server_secret=$(kubectl -n "$svc_ns" get svc "$svc_name" -o jsonpath='{.metadata.annotations.cnpg\.io/pluginServerSecret}' 2>/dev/null || true)
|
||||
plugin_port=$(kubectl -n "$svc_ns" get svc "$svc_name" -o jsonpath='{.metadata.annotations.cnpg\.io/pluginPort}' 2>/dev/null || true)
|
||||
|
||||
if [[ -n "$client_secret" && -n "$server_secret" && -n "$plugin_port" ]]; then
|
||||
if kubectl -n "$svc_ns" get secret "$client_secret" >/dev/null 2>&1 && kubectl -n "$svc_ns" get secret "$server_secret" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
now=$(date +%s)
|
||||
if (( now - start_time >= PLUGIN_READY_TIMEOUT )); then
|
||||
echo "ERROR: Timed out waiting for Barman plugin infrastructure to become ready." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Waiting for Barman plugin infrastructure (deployment + service registration) ..."
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_objectstore_ready() {
|
||||
local timeout=${1:-$OBJECTSTORE_READY_TIMEOUT}
|
||||
local start_time now elapsed
|
||||
start_time=$(date +%s)
|
||||
|
||||
echo "Waiting for ObjectStore '$BARMAN_OBJECT_NAME' to be Ready (timeout: ${timeout}s)..."
|
||||
while true; do
|
||||
local ready_cond phase
|
||||
ready_cond=$(kubectl -n "$NAMESPACE" get objectstore "$BARMAN_OBJECT_NAME" \
|
||||
-o jsonpath='{range .status.conditions[?(@.type=="Ready")]}{.status}{end}' 2>/dev/null || true)
|
||||
phase=$(kubectl -n "$NAMESPACE" get objectstore "$BARMAN_OBJECT_NAME" \
|
||||
-o jsonpath='{.status.phase}' 2>/dev/null || true)
|
||||
|
||||
if [[ "$ready_cond" == "True" || "$ready_cond" == "true" || "$phase" == "Ready" || "$phase" == "ready" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
now=$(date +%s)
|
||||
elapsed=$((now - start_time))
|
||||
if (( elapsed >= timeout )); then
|
||||
echo "ERROR: Timed out waiting for ObjectStore '$BARMAN_OBJECT_NAME' to become Ready." >&2
|
||||
kubectl -n "$NAMESPACE" get objectstore "$BARMAN_OBJECT_NAME" -o yaml 2>/dev/null >&2 || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep "$OBJECTSTORE_READY_INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
has_successful_base_backup() {
|
||||
local rows name phase method backup_type phase_lc method_lc backup_type_lc
|
||||
rows=$(kubectl get backup -n "$NAMESPACE" -o jsonpath="{range .items[?(@.spec.cluster.name=='$CNPG_CLUSTER_NAME')]}{.metadata.name}{\"\t\"}{.status.phase}{\"\t\"}{.spec.method}{\"\t\"}{.spec.pluginConfiguration.parameters.backupType}{\"\n\"}{end}" 2>/dev/null || true)
|
||||
@ -619,7 +709,9 @@ case "$ACTION" in
|
||||
wait_for_apiserver_ready 180
|
||||
ensure_cluster
|
||||
ensure_garage_bucket_and_key
|
||||
wait_for_barman_plugin_infra_ready
|
||||
apply_barman_object_store
|
||||
wait_for_objectstore_ready
|
||||
ensure_barman_plugin_config
|
||||
ensure_cluster_backup_config
|
||||
wait_for_plugin_ready
|
||||
@ -642,7 +734,9 @@ case "$ACTION" in
|
||||
ensure_namespace
|
||||
wait_for_apiserver_ready 180
|
||||
ensure_cluster
|
||||
wait_for_barman_plugin_infra_ready
|
||||
apply_barman_object_store
|
||||
wait_for_objectstore_ready
|
||||
ensure_barman_plugin_config
|
||||
ensure_cluster_backup_config
|
||||
wait_for_plugin_ready
|
||||
|
||||
@ -49,11 +49,26 @@ k3s_service_node_labels:
|
||||
- "prole.org/node-role=general"
|
||||
k3s_node_taints: []
|
||||
|
||||
k3s_required_mounts:
|
||||
- /synology/d002
|
||||
- /synology/d004
|
||||
|
||||
# iSCSI
|
||||
# `/var/lib/rancher` is local host storage (do not manage it via iSCSI).
|
||||
iscsi_portal: 10.0.0.203:3260
|
||||
|
||||
iscsi_targets:
|
||||
# PROLE-DATA-2
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-12.292d45194a1"
|
||||
chap_user: "prole"
|
||||
chap_password: "{{ vault_iscsi_prole_password }}"
|
||||
mounts:
|
||||
- name: d002
|
||||
path: /synology/d002
|
||||
fstype: xfs
|
||||
opts: "_netdev,noatime"
|
||||
src: "UUID=fe087fb0-a321-4767-b838-b4385e81693e"
|
||||
|
||||
# PROLE-DATA-4
|
||||
# Repurposed from myrddin's former `/var/lib/rancher` Synology LUN.
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-15.292d45194a1"
|
||||
@ -61,7 +76,7 @@ iscsi_targets:
|
||||
chap_password: "{{ vault_iscsi_prole_password }}"
|
||||
mounts:
|
||||
- name: d004
|
||||
path: /prole/d004
|
||||
path: /synology/d004
|
||||
fstype: xfs
|
||||
opts: "_netdev,noatime"
|
||||
mkfs_if_missing: true
|
||||
|
||||
@ -1,36 +1,16 @@
|
||||
iscsi_portal: 10.0.0.203
|
||||
|
||||
iscsi_targets:
|
||||
# PROLE-DB-1
|
||||
# PROLE-DATA-1
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-11.292d45194a1"
|
||||
chap_user: "prole"
|
||||
chap_password: "{{ vault_iscsi_prole_password }}"
|
||||
mounts:
|
||||
- path: /prole/d001
|
||||
- path: /synology/d001
|
||||
fstype: xfs
|
||||
opts: "_netdev,noatime"
|
||||
src: "UUID=c07dc0f2-cf60-4da5-b68e-ea45e86d473e"
|
||||
|
||||
# PROLE-DB-2
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-12.292d45194a1"
|
||||
chap_user: "prole"
|
||||
chap_password: "{{ vault_iscsi_prole_password }}"
|
||||
mounts:
|
||||
- path: /prole/d002
|
||||
fstype: xfs
|
||||
opts: "_netdev,noatime"
|
||||
src: "UUID=fe087fb0-a321-4767-b838-b4385e81693e"
|
||||
|
||||
# PROLE-DB-3
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-13.292d45194a1"
|
||||
chap_user: "prole"
|
||||
chap_password: "{{ vault_iscsi_prole_password }}"
|
||||
mounts:
|
||||
- path: /prole/d003
|
||||
fstype: xfs
|
||||
opts: "_netdev,noatime"
|
||||
src: "UUID=757f1ee4-dc23-414b-b595-e3058c0744f0"
|
||||
|
||||
# PROLE-HOME
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-17.292d45194a1"
|
||||
chap_user: "prole"
|
||||
@ -53,6 +33,18 @@ iscsi_targets:
|
||||
|
||||
iscsi_absent_mounts:
|
||||
- /opt/prole/logs/chrisfu
|
||||
# Migration cleanup: PROLE-DATA-2/3 are moving off myrddin
|
||||
- /prole/d002
|
||||
- /prole/d003
|
||||
- /synology/d002
|
||||
- /synology/d003
|
||||
|
||||
# Migration cleanup: ensure myrddin fully logs out of LUNs that are moving to other hosts
|
||||
iscsi_absent_targets:
|
||||
# PROLE-DATA-2
|
||||
- "iqn.2000-01.com.synology:synology.Target-12.292d45194a1"
|
||||
# PROLE-DATA-3
|
||||
- "iqn.2000-01.com.synology:synology.Target-13.292d45194a1"
|
||||
|
||||
ad_dc_enabled: true
|
||||
|
||||
@ -122,6 +114,4 @@ k3s_kubeconfig_users:
|
||||
- pi
|
||||
|
||||
k3s_required_mounts:
|
||||
- /prole/d001
|
||||
- /prole/d002
|
||||
- /prole/d003
|
||||
- /synology/d001
|
||||
|
||||
@ -1,8 +1,21 @@
|
||||
iscsi_portal: 10.0.0.203
|
||||
|
||||
k3s_required_mounts:
|
||||
- /synology/d003
|
||||
|
||||
iscsi_targets:
|
||||
# `/var/lib/rancher` is local host storage (do not manage it via iSCSI).
|
||||
|
||||
# PROLE-DATA-3
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-13.292d45194a1"
|
||||
chap_user: "prole"
|
||||
chap_password: "{{ vault_iscsi_prole_password }}"
|
||||
mounts:
|
||||
- path: /synology/d003
|
||||
fstype: xfs
|
||||
opts: "_netdev,noatime"
|
||||
src: "UUID=757f1ee4-dc23-414b-b595-e3058c0744f0"
|
||||
|
||||
# PROLE-PI-2
|
||||
- iqn: "iqn.2000-01.com.synology:synology.Target-19.292d45194a1"
|
||||
chap_user: "prole"
|
||||
|
||||
@ -23,6 +23,37 @@
|
||||
roles:
|
||||
- cgroups
|
||||
|
||||
- name: Tier 1.5 - Quiesce k3s and detach migrated iSCSI LUNs (myrddin)
|
||||
hosts: myrddin.prole.org
|
||||
gather_facts: false
|
||||
become: true
|
||||
pre_tasks:
|
||||
- name: Gather minimal facts
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- min
|
||||
tasks:
|
||||
- name: Check if k3s systemd unit exists
|
||||
ansible.builtin.stat:
|
||||
path: /etc/systemd/system/k3s.service
|
||||
register: _k3s_unit
|
||||
|
||||
- name: Stop k3s (quiesce before iSCSI detach)
|
||||
ansible.builtin.systemd:
|
||||
name: k3s
|
||||
state: stopped
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
- _k3s_unit.stat.exists | default(false)
|
||||
- (iscsi_absent_mounts | default([]) | length) > 0 or (iscsi_absent_targets | default([]) | length) > 0
|
||||
|
||||
- name: Detach migrated iSCSI targets/mounts (best-effort cleanup)
|
||||
ansible.builtin.import_role:
|
||||
name: iscsi
|
||||
tasks_from: detach
|
||||
when:
|
||||
- (iscsi_absent_mounts | default([]) | length) > 0 or (iscsi_absent_targets | default([]) | length) > 0
|
||||
|
||||
- name: Tier 2 - Storage (iSCSI auth/login)
|
||||
hosts: iscsi
|
||||
gather_facts: false
|
||||
|
||||
@ -4,6 +4,6 @@
|
||||
tasks:
|
||||
- name: Ensure OpenBao storage directory exists
|
||||
ansible.builtin.file:
|
||||
path: /prole/d001/openbao
|
||||
path: /synology/d001/openbao
|
||||
state: directory
|
||||
mode: "0777" # OpenBao pod runs as non-root usually, but k3s local-path often needs this or specific UID
|
||||
|
||||
69
infrastructure/roles/iscsi/tasks/detach.yml
Normal file
69
infrastructure/roles/iscsi/tasks/detach.yml
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
- name: Require iscsi_portal when logging out absent targets
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- iscsi_portal is defined
|
||||
- (iscsi_portal | string | length) > 0
|
||||
fail_msg: "iscsi_absent_targets is set but iscsi_portal is missing/empty."
|
||||
when: (iscsi_absent_targets | default([]) | length) > 0
|
||||
|
||||
- name: Unmount absent iSCSI mountpoints
|
||||
ansible.builtin.mount:
|
||||
path: "{{ item.path | default(item) }}"
|
||||
state: unmounted
|
||||
loop: "{{ iscsi_absent_mounts | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.path | default(item) }}"
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Remove absent iSCSI fstab entries
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
state: absent
|
||||
regexp: "^\\s*\\S+\\s+{{ (item.path | default(item)) | regex_escape }}\\s+"
|
||||
loop: "{{ iscsi_absent_mounts | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.path | default(item) }}"
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Check for active sessions for absent targets
|
||||
ansible.builtin.shell: >-
|
||||
iscsiadm -m session 2>/dev/null | grep -Fq -- {{ item | quote }}
|
||||
register: _iscsi_absent_target_session_checks
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
loop: "{{ iscsi_absent_targets | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: (iscsi_absent_targets | default([]) | length) > 0
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Logout absent iSCSI targets (active sessions only)
|
||||
ansible.builtin.command: >-
|
||||
iscsiadm -m node -T {{ item.item }} -p {{ iscsi_portal }} --logout
|
||||
register: _iscsi_absent_target_logout
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
loop: "{{ _iscsi_absent_target_session_checks.results | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
when:
|
||||
- (iscsi_absent_targets | default([]) | length) > 0
|
||||
- item.rc == 0
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Delete node records for absent iSCSI targets (best-effort)
|
||||
ansible.builtin.command: >-
|
||||
iscsiadm -m node -o delete -T {{ item }} -p {{ iscsi_portal }}
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
loop: "{{ iscsi_absent_targets | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: (iscsi_absent_targets | default([]) | length) > 0
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
@ -111,6 +111,7 @@
|
||||
register: _iscsi_blkid_type
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
check_mode: no
|
||||
when:
|
||||
- _iscsi_need_blockdev | default(false) | bool
|
||||
- _iscsi_blockdev is defined
|
||||
@ -287,6 +288,7 @@
|
||||
ansible.builtin.command: "blkid -o value -s UUID {{ _iscsi_blockdev }}"
|
||||
register: _iscsi_blkid_uuid
|
||||
changed_when: false
|
||||
check_mode: no
|
||||
when:
|
||||
- (_iscsi_mount_src | default('') | string | length) == 0
|
||||
- _iscsi_blockdev is defined
|
||||
@ -302,7 +304,9 @@
|
||||
- _iscsi_blkid_uuid is defined
|
||||
- (_iscsi_blkid_uuid.stdout | default('') | trim) != ''
|
||||
fail_msg: "Unable to resolve a filesystem UUID for {{ m.path }} from {{ _iscsi_blockdev }}."
|
||||
when: (_iscsi_mount_src | default('') | string | length) == 0
|
||||
when:
|
||||
- (_iscsi_mount_src | default('') | string | length) == 0
|
||||
- not (ansible_check_mode and ((m.mkfs_once | default(false) | bool) or (m.mkfs_if_missing | default(false) | bool)))
|
||||
tags:
|
||||
- iscsi
|
||||
- iscsi_mount
|
||||
@ -311,7 +315,10 @@
|
||||
- name: Set mount source to UUID
|
||||
ansible.builtin.set_fact:
|
||||
_iscsi_mount_src: "UUID={{ _iscsi_blkid_uuid.stdout | trim }}"
|
||||
when: (_iscsi_mount_src | default('') | string | length) == 0
|
||||
when:
|
||||
- (_iscsi_mount_src | default('') | string | length) == 0
|
||||
- _iscsi_blkid_uuid is defined
|
||||
- (_iscsi_blkid_uuid.stdout | default('') | trim) != ''
|
||||
tags:
|
||||
- iscsi
|
||||
- iscsi_mount
|
||||
@ -324,6 +331,7 @@
|
||||
fstype: "{{ m.fstype | default('ext4') }}"
|
||||
opts: "{{ m.opts | default('_netdev,noatime') }}"
|
||||
state: mounted
|
||||
when: (_iscsi_mount_src | default('') | string | trim | length) > 0
|
||||
tags:
|
||||
- iscsi
|
||||
- iscsi_mount
|
||||
|
||||
@ -31,8 +31,8 @@
|
||||
no_log: true
|
||||
|
||||
- name: Check if target session is already logged in
|
||||
ansible.builtin.command: >
|
||||
iscsiadm -m session -T {{ t.iqn }} -p {{ iscsi_portal }}
|
||||
ansible.builtin.shell: >-
|
||||
iscsiadm -m session 2>/dev/null | grep -Fq -- {{ t.iqn | quote }}
|
||||
register: session_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
@ -46,8 +46,8 @@
|
||||
when: session_check.rc != 0
|
||||
|
||||
- name: Re-check session after login attempt
|
||||
ansible.builtin.command: >
|
||||
iscsiadm -m session -T {{ t.iqn }} -p {{ iscsi_portal }}
|
||||
ansible.builtin.shell: >-
|
||||
iscsiadm -m session 2>/dev/null | grep -Fq -- {{ t.iqn | quote }}
|
||||
register: session_after_login
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
@ -55,7 +55,12 @@
|
||||
|
||||
- name: Fail if login did not establish a session
|
||||
ansible.builtin.fail:
|
||||
msg: "iSCSI login failed for {{ t.iqn }} at {{ iscsi_portal }}"
|
||||
msg: |-
|
||||
iSCSI login failed for {{ t.iqn }} at {{ iscsi_portal }}.
|
||||
|
||||
login.rc={{ login.rc | default('') }}
|
||||
login.stdout={{ (login.stdout | default('')) | trim }}
|
||||
login.stderr={{ (login.stderr | default('')) | trim }}
|
||||
when:
|
||||
- session_check.rc != 0
|
||||
- session_after_login is defined
|
||||
|
||||
@ -1,4 +1,41 @@
|
||||
---
|
||||
- name: Compute legacy mountpoints to clean up (/prole/d00x -> /synology/d00x)
|
||||
ansible.builtin.set_fact:
|
||||
_iscsi_legacy_absent_mounts: >-
|
||||
{{
|
||||
(iscsi_targets | default([])
|
||||
| map(attribute='mounts') | list | flatten
|
||||
| selectattr('path', 'defined')
|
||||
| map(attribute='path') | list
|
||||
| select('match', '^/synology/d[0-9]{3}$')
|
||||
| map('regex_replace', '^/synology/', '/prole/')
|
||||
| list)
|
||||
}}
|
||||
changed_when: false
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Unmount legacy iSCSI mounts (old /prole/d00x layout)
|
||||
ansible.builtin.mount:
|
||||
path: "{{ item }}"
|
||||
state: unmounted
|
||||
loop: "{{ _iscsi_legacy_absent_mounts | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Remove legacy iSCSI fstab entries (old /prole/d00x layout)
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/fstab
|
||||
state: absent
|
||||
regexp: "^\\s*\\S+\\s+{{ item | regex_escape }}\\s+"
|
||||
loop: "{{ _iscsi_legacy_absent_mounts | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
tags:
|
||||
- iscsi_cleanup
|
||||
|
||||
- name: Unmount stale iSCSI mounts
|
||||
ansible.builtin.mount:
|
||||
path: "{{ item.path | default(item) }}"
|
||||
|
||||
@ -99,28 +99,48 @@
|
||||
- k3s_prestage_images | bool
|
||||
tags: [images]
|
||||
|
||||
- name: Create ArgoCD hostPath directories on myrddin.prole.org
|
||||
- name: Create ArgoCD hostPath directories on myrddin.prole.org (/synology/d001)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0777"
|
||||
loop:
|
||||
- /prole/d001/argocd
|
||||
- /prole/d001/argocd/home
|
||||
- /prole/d001/argocd/tmp
|
||||
- /prole/d002/argocd
|
||||
- /prole/d002/argocd/data
|
||||
- /prole/d002/argocd/tmp
|
||||
- /prole/d003/argocd
|
||||
- /prole/d003/argocd/gpg-keyring
|
||||
- /prole/d003/argocd/tmp
|
||||
- /prole/d003/argocd/helm-working-dir
|
||||
- /prole/d003/argocd/var-files
|
||||
- /prole/d003/argocd/plugins
|
||||
- /synology/d001/argocd
|
||||
- /synology/d001/argocd/home
|
||||
- /synology/d001/argocd/tmp
|
||||
when:
|
||||
- k3s_state == "present"
|
||||
- inventory_hostname == 'myrddin.prole.org'
|
||||
|
||||
- name: Create ArgoCD hostPath directories on merlin.prole.org (/synology/d002)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0777"
|
||||
loop:
|
||||
- /synology/d002/argocd
|
||||
- /synology/d002/argocd/data
|
||||
- /synology/d002/argocd/tmp
|
||||
when:
|
||||
- k3s_state == "present"
|
||||
- inventory_hostname == 'merlin.prole.org'
|
||||
|
||||
- name: Create ArgoCD hostPath directories on pi.prole.org (/synology/d003)
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0777"
|
||||
loop:
|
||||
- /synology/d003/argocd
|
||||
- /synology/d003/argocd/gpg-keyring
|
||||
- /synology/d003/argocd/tmp
|
||||
- /synology/d003/argocd/helm-working-dir
|
||||
- /synology/d003/argocd/var-files
|
||||
- /synology/d003/argocd/plugins
|
||||
when:
|
||||
- k3s_state == "present"
|
||||
- inventory_hostname == 'pi.prole.org'
|
||||
|
||||
- name: Wait for k3s Kubernetes API to become ready
|
||||
ansible.builtin.command: k3s kubectl get --raw='/readyz'
|
||||
register: _k3s_readyz
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
RequiresMountsFor={{ k3s_rancher_mountpoint }}
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/bin/sh -ec 'rancher_src="$(findmnt -n -o SOURCE -T {{ k3s_rancher_mountpoint }})"; root_src="$(findmnt -n -o SOURCE -T /)"; if [ "${rancher_src}" = "${root_src}" ]; then echo "Refusing to start k3s: {{ k3s_rancher_mountpoint }} resolves to rootfs (${root_src}). Expected a dedicated mount." >&2; exit 1; fi'
|
||||
ExecStartPre=/bin/sh -ec 'rancher_src="$(findmnt -n -o SOURCE -T {{ k3s_rancher_mountpoint }})"; root_src="$(findmnt -n -o SOURCE -T /)"; if [ "$${rancher_src}" = "$${root_src}" ]; then echo "Refusing to start k3s: {{ k3s_rancher_mountpoint }} resolves to rootfs ($${root_src}). Expected a dedicated mount." >&2; exit 1; fi'
|
||||
register: _k3s_rancher_mount_guard_dropin
|
||||
when: ansible_service_mgr | default('') == 'systemd'
|
||||
|
||||
|
||||
@ -32161,11 +32161,11 @@ spec:
|
||||
serviceAccountName: argocd-redis
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /prole/d002/argocd/data
|
||||
path: /synology/d002/argocd/data
|
||||
type: DirectoryOrCreate
|
||||
name: argocd-redis-data
|
||||
- hostPath:
|
||||
path: /prole/d002/argocd/tmp
|
||||
path: /synology/d002/argocd/tmp
|
||||
type: DirectoryOrCreate
|
||||
name: argocd-redis-tmp
|
||||
|
||||
@ -32582,15 +32582,15 @@ spec:
|
||||
name: argocd-gpg-keys-cm
|
||||
name: gpg-keys
|
||||
- hostPath:
|
||||
path: /prole/d003/argocd/gpg-keyring
|
||||
path: /synology/d003/argocd/gpg-keyring
|
||||
type: DirectoryOrCreate
|
||||
name: gpg-keyring
|
||||
- hostPath:
|
||||
path: /prole/d003/argocd/tmp
|
||||
path: /synology/d003/argocd/tmp
|
||||
type: DirectoryOrCreate
|
||||
name: tmp
|
||||
- hostPath:
|
||||
path: /prole/d003/argocd/helm-working-dir
|
||||
path: /synology/d003/argocd/helm-working-dir
|
||||
type: DirectoryOrCreate
|
||||
name: helm-working-dir
|
||||
- name: argocd-repo-server-tls
|
||||
@ -32605,11 +32605,11 @@ spec:
|
||||
optional: true
|
||||
secretName: argocd-repo-server-tls
|
||||
- hostPath:
|
||||
path: /prole/d003/argocd/var-files
|
||||
path: /synology/d003/argocd/var-files
|
||||
type: DirectoryOrCreate
|
||||
name: var-files
|
||||
- hostPath:
|
||||
path: /prole/d003/argocd/plugins
|
||||
path: /synology/d003/argocd/plugins
|
||||
type: DirectoryOrCreate
|
||||
name: plugins
|
||||
|
||||
@ -33359,11 +33359,11 @@ spec:
|
||||
serviceAccountName: argocd-application-controller
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /prole/d001/argocd/home
|
||||
path: /synology/d001/argocd/home
|
||||
type: DirectoryOrCreate
|
||||
name: argocd-home
|
||||
- hostPath:
|
||||
path: /prole/d001/argocd/tmp
|
||||
path: /synology/d001/argocd/tmp
|
||||
type: DirectoryOrCreate
|
||||
name: argocd-application-controller-tmp
|
||||
- name: argocd-repo-server-tls
|
||||
|
||||
@ -14,7 +14,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/data
|
||||
path: /synology/d001/data
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -40,7 +40,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/wal
|
||||
path: /synology/d001/wal
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -66,7 +66,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/garage
|
||||
path: /synology/d001/garage
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -92,7 +92,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d002/data
|
||||
path: /synology/d002/data
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -100,7 +100,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- merlin.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -118,7 +118,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d002/wal
|
||||
path: /synology/d002/wal
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -126,7 +126,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- merlin.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -144,7 +144,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d003/data
|
||||
path: /synology/d003/data
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -152,7 +152,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- pi.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -170,7 +170,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d003/wal
|
||||
path: /synology/d003/wal
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -178,7 +178,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- pi.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -196,7 +196,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d003/grafana
|
||||
path: /synology/d003/grafana
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -204,7 +204,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- pi.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -222,7 +222,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d002/prometheus
|
||||
path: /synology/d002/prometheus
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -230,7 +230,7 @@ spec:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- myrddin.prole.org
|
||||
- merlin.prole.org
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
@ -248,7 +248,7 @@ spec:
|
||||
storageClassName: prole-iscsi
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d001/openbao
|
||||
path: /synology/d001/openbao
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
|
||||
@ -14,7 +14,7 @@ spec:
|
||||
storageClassName: prole-monitoring-d004
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d004/prometheus
|
||||
path: /synology/d004/prometheus
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -40,7 +40,7 @@ spec:
|
||||
storageClassName: prole-monitoring-d004
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d004/alertmanager
|
||||
path: /synology/d004/alertmanager
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
@ -66,7 +66,7 @@ spec:
|
||||
storageClassName: prole-monitoring-d004
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /prole/d004/grafana
|
||||
path: /synology/d004/grafana
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
|
||||
@ -5,7 +5,7 @@ metadata:
|
||||
name: prole-db
|
||||
spec:
|
||||
instances: 3
|
||||
imageName: myrddin.prole.org:5000/prole-db:18-129
|
||||
imageName: myrddin.prole.org:5000/prole-db:0.0.0
|
||||
postgresUID: 100
|
||||
postgresGID: 101
|
||||
maxSyncReplicas: 1
|
||||
|
||||
@ -1 +1 @@
|
||||
129
|
||||
130
|
||||
@ -105,6 +105,32 @@ if [[ "$args" == *"-n cnpg-system get secret"*"barman-cloud-"*"-o jsonpath="* ]]
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Barman plugin service registration readiness (strict gating)
|
||||
if [[ "$args" == *"-n cnpg-system get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$args" == *"-n cnpg-system get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$args" == *"-n cnpg-system get svc barman-cloud"*"pluginClientSecret"* ]]; then
|
||||
echo "barman-cloud-client-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$args" == *"-n cnpg-system get svc barman-cloud"*"pluginServerSecret"* ]]; then
|
||||
echo "barman-cloud-server-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$args" == *"-n cnpg-system get svc barman-cloud"*"pluginPort"* ]]; then
|
||||
echo "9090"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$args" == *"-n cnpg-system get endpoints barman-cloud"* ]]; then
|
||||
echo "10.42.0.11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# DB node availability checks (bootstrap safety)
|
||||
if [[ "$args" == *"get nodes"*"--no-headers"* ]]; then
|
||||
# Name Status Roles Age Version
|
||||
|
||||
@ -68,6 +68,47 @@ if [[ "${args}" == *"get endpoints"*"cnpg-webhook-service"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Avoid barman plugin waits (strict readiness now includes service registration)
|
||||
if [[ "${args}" == *"get crd"*"objectstores.barmancloud.cnpg.io"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get secret"*"barman-cloud-client-tls"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get secret"*"barman-cloud-server-tls"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get deploy"*"barman-cloud"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"rollout status"*"deploy/barman-cloud"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginClientSecret"* ]]; then
|
||||
echo "barman-cloud-client-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginServerSecret"* ]]; then
|
||||
echo "barman-cloud-server-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginPort"* ]]; then
|
||||
echo "9090"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get endpoints barman-cloud"* ]]; then
|
||||
echo "10.42.0.11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# CNPG pods listing and readiness queries
|
||||
if [[ "${args}" == *"get pods"* && "${args}" == *"cnpg.io/cluster="* ]]; then
|
||||
if [[ "${args}" == *"--no-headers"* ]]; then
|
||||
|
||||
@ -65,7 +65,7 @@ if [[ "${args}" == *"-n cert-manager"*"get deploy"* ]]; then
|
||||
fi
|
||||
|
||||
# Avoid barman plugin waits
|
||||
if [[ "${args}" == *"get crd"*"barmanobjectstores.barmancloud.cnpg.io"* ]]; then
|
||||
if [[ "${args}" == *"get crd"*"objectstores.barmancloud.cnpg.io"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get secret"*"barman-cloud-client-tls"* ]]; then
|
||||
@ -74,19 +74,90 @@ fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get secret"*"barman-cloud-server-tls"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get deploy"*"barman-cloud"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"rollout status"*"deploy/barman-cloud"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginClientSecret"* ]]; then
|
||||
echo "barman-cloud-client-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginServerSecret"* ]]; then
|
||||
echo "barman-cloud-server-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginPort"* ]]; then
|
||||
echo "9090"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get endpoints barman-cloud"* ]]; then
|
||||
echo "10.42.0.11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Namespace check in ensure_namespace()
|
||||
if [[ "${args}" == "get namespace test-ns" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Capture applied CNPG manifest
|
||||
if [[ "${args}" == apply* && "${args}" == *"-n"*"test-ns"* && "${args}" == *"-f"*"-"* ]]; then
|
||||
cat > "${TMP_DIR}/applied.yaml"
|
||||
# Capture applied CNPG manifest (stdin or file)
|
||||
if [[ "${args}" == apply* && "${args}" == *"-n"*"test-ns"* && "${args}" == *" -f "* ]]; then
|
||||
f=""
|
||||
if [[ "$#" -ge 2 ]]; then
|
||||
for ((i=1; i<=$#; i++)); do
|
||||
if [[ "${!i}" == "-f" ]]; then
|
||||
j=$((i+1))
|
||||
f="${!j:-}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ "${f}" == "-" ]]; then
|
||||
cat > "${TMP_DIR}/applied.yaml"
|
||||
elif [[ -n "${f}" && -f "${f}" ]]; then
|
||||
cat "${f}" > "${TMP_DIR}/applied.yaml"
|
||||
else
|
||||
: > "${TMP_DIR}/applied.yaml"
|
||||
fi
|
||||
echo "cluster.postgresql.cnpg.io/prole-db configured"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Runtime storage validation (k3s) expects live Cluster + PVC/PV objects.
|
||||
if [[ "${args}" == *"-n test-ns"*"get cluster"*"prole-db"*"-o json"* ]]; then
|
||||
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"}}}}}}
|
||||
JSON
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n test-ns"*"get pvc"*"cnpg.io/cluster=prole-db"*"-o json"* ]]; then
|
||||
cat <<'JSON'
|
||||
{"items":[
|
||||
{"metadata":{"name":"prole-db-1"},"spec":{"storageClassName":"prole-iscsi","volumeName":"pv-data"}},
|
||||
{"metadata":{"name":"prole-db-1-wal"},"spec":{"storageClassName":"prole-iscsi","volumeName":"pv-wal"}}
|
||||
]}
|
||||
JSON
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == "get pv pv-data -o json"* ]]; then
|
||||
echo '{"spec":{"storageClassName":"prole-iscsi","local":{"path":"/prole/d001/data"}}}'
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == "get pv pv-wal -o json"* ]]; then
|
||||
echo '{"spec":{"storageClassName":"prole-iscsi","local":{"path":"/prole/d001/wal"}}}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Node inventory used by reconcile_cnpg_instances
|
||||
if [[ "${args}" == "get nodes --no-headers" ]]; then
|
||||
n="${MOCK_READY_NODES:-1}"
|
||||
@ -133,7 +204,6 @@ mock_tool ansible-playbook
|
||||
mock_tool tofu
|
||||
mock_tool terraform
|
||||
mock_tool ollama
|
||||
mock_tool jq
|
||||
|
||||
export PATH="$BIN_DIR:$PATH"
|
||||
export TMP_DIR
|
||||
@ -178,7 +248,10 @@ E_EOF
|
||||
rm -f "$TMP_DIR/applied.yaml"
|
||||
rm -f "$TMP_DIR/mock_cluster_instances"
|
||||
set +e
|
||||
MOCK_READY_NODES="$mock_ready_nodes" MOCK_DB_NODES="$mock_db_nodes" PROLE_HOME="$env_home" \
|
||||
MOCK_READY_NODES="$mock_ready_nodes" MOCK_DB_NODES="$mock_db_nodes" \
|
||||
BARMAN_CRD_TIMEOUT=5 BARMAN_TLS_TIMEOUT=5 BARMAN_DEPLOY_TIMEOUT=5 BARMAN_SERVICE_TIMEOUT=5 \
|
||||
CNPG_STORAGE_VALIDATE_TIMEOUT=5 \
|
||||
PROLE_HOME="$env_home" \
|
||||
bash "$SCRIPT_UNDER_TEST" --mode k3s start >/dev/null 2>"$TMP_DIR/stderr-${label}"
|
||||
local rc=$?
|
||||
set -e
|
||||
|
||||
@ -117,6 +117,38 @@ if [[ "${args}" == *"get crd"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Barman plugin strict readiness checks (service registration)
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get deploy"*"barman-cloud"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"rollout status"*"deploy/barman-cloud"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginClientSecret"* ]]; then
|
||||
echo "barman-cloud-client-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginServerSecret"* ]]; then
|
||||
echo "barman-cloud-server-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginPort"* ]]; then
|
||||
echo "9090"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get endpoints barman-cloud"* ]]; then
|
||||
echo "10.42.0.11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# CNPG cluster instances lookup in wait_for_cnpg_pods()
|
||||
if [[ "${args}" == *"-n test-ns"*"get cluster"*"-o jsonpath="*".spec.instances"* ]]; then
|
||||
echo "3"
|
||||
|
||||
@ -64,6 +64,32 @@ if [[ "${args}" == "get deployment -A -l app.kubernetes.io/name=barman-cloud -o
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Barman plugin service registration (used by wait_for_barman_plugin_infra_ready)
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginClientSecret"* ]]; then
|
||||
echo "barman-cloud-client-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginServerSecret"* ]]; then
|
||||
echo "barman-cloud-server-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginPort"* ]]; then
|
||||
echo "9090"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get endpoints barman-cloud"* ]]; then
|
||||
echo "10.42.0.11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# CNPG cluster pod selection for socket check
|
||||
if [[ "${args}" == *"-n test-ns"*"get pods"*"-l cnpg.io/cluster=prole-db,cnpg.io/instanceRole=primary"*"-o jsonpath={.items[0].metadata.name"* ]]; then
|
||||
echo "prole-db-1"
|
||||
@ -102,6 +128,16 @@ if [[ "${args}" == apply*"-n"*"test-ns"*"-f"*"-"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ObjectStore readiness checks
|
||||
if [[ "${args}" == *"-n test-ns"*"get objectstore"*"prole-db-barman-objectstore"*"-o jsonpath="*"conditions"*"Ready"* ]]; then
|
||||
echo "True"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n test-ns"*"get objectstore"*"prole-db-barman-objectstore"*"-o jsonpath={.status.phase"* ]]; then
|
||||
echo "Ready"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exit 0
|
||||
K_EOF
|
||||
chmod +x "$BIN_DIR/kubectl"
|
||||
|
||||
@ -74,6 +74,32 @@ if [[ "${args}" == "get deployment -A -l app.kubernetes.io/name=barman-cloud -o
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Barman plugin service registration (used by wait_for_barman_plugin_infra_ready)
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then
|
||||
echo "barman-cloud"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginClientSecret"* ]]; then
|
||||
echo "barman-cloud-client-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginServerSecret"* ]]; then
|
||||
echo "barman-cloud-server-tls"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginPort"* ]]; then
|
||||
echo "9090"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n cnpg-system"*"get endpoints barman-cloud"* ]]; then
|
||||
echo "10.42.0.11"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# CNPG cluster pod selection for socket check
|
||||
if [[ "${args}" == *"-n test-ns"*"get pods"*"-l cnpg.io/cluster=prole-db,cnpg.io/instanceRole=primary"*"-o jsonpath={.items[0].metadata.name"* ]]; then
|
||||
echo "prole-db-1"
|
||||
@ -157,6 +183,16 @@ if [[ "${args}" == "get backup -n test-ns"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ObjectStore readiness checks
|
||||
if [[ "${args}" == *"-n test-ns"*"get objectstore"*"prole-db-barman-objectstore"*"-o jsonpath="*"conditions"*"Ready"* ]]; then
|
||||
echo "True"
|
||||
exit 0
|
||||
fi
|
||||
if [[ "${args}" == *"-n test-ns"*"get objectstore"*"prole-db-barman-objectstore"*"-o jsonpath={.status.phase"* ]]; then
|
||||
echo "Ready"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exit 0
|
||||
K_EOF
|
||||
chmod +x "$BIN_DIR/kubectl"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user