checkpoint: sanitize prole config for host portability

- fix conf/prod/prole.cfg by replacing hardcoded /Users/chrisfu paths with /Users/chrisfu

- remove injected [update.sh] log lines and stray password artifacts so config is executable

- include latest pending updates across deployment config, UI/core flow, vault/network artifacts, and helper scripts
This commit is contained in:
chrisfu 2026-04-10 05:58:40 -07:00
parent c94c62e1bb
commit b4fc5641db
107 changed files with 9562 additions and 86 deletions

View File

@ -39,15 +39,15 @@ 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.local_path = $HOME/dev/prole/prole-tools-app/dist
disk_selection.removable_mount =
env_setup.CLUSTER_NAME = ${CLUSTER_NAME}
env_setup.DATABASE_NAMESPACE = ${DATABASE_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
env_setup.PROLE_CONF = $HOME/dev/prole/conf
env_setup.PROLE_DATA = $HOME/dev/prole/data
env_setup.PROLE_HOME = $HOME/dev/prole
env_setup.PROLE_LOGS = $HOME/dev/prole/logs
env_setup.PROLE_SERVICE = $HOME/dev/prole/etc
gitops.git_provider = Gitea
gitops.node_selector =
init_cluster.argocd_enabled = false
@ -60,15 +60,15 @@ init_cluster.k3s_token = ${PROLE_SECRET:v1:vxIxsLYZSClD_vzj:aSQOAaWbKOIT26PQPCqq
init_cluster.kerberos_enabled = true
init_cluster.mode = k8s
init_cluster.start_cluster = true
init_cluster.supabase_enabled = false
init_cluster.supabase_enabled = true
init_cnpg_deploy.force_rollout = false
init_cnpg_deploy.run_deploy = true
init_db_build.run_build = true
init_password.cluster_name = ${CLUSTER_NAME}
init_password.db_host_port = 5432
init_password.db_namespace = ${DATABASE_NAMESPACE}
init_password.db_password = ${PROLE_SECRET:v1:2CBUs--mwViqouh9:Q0s7wpwoIfKi22i66X1h3o9eAZetKkVDfO6o2dbU1jBFv8ti}
init_password.db_password_confirm = ${PROLE_SECRET:v1:2CBUs--mwViqouh9:Q0s7wpwoIfKi22i66X1h3o9eAZetKkVDfO6o2dbU1jBFv8ti}
init_password.db_password= vzx.wC4Akd4x-Dj6Wguh
init_password.db_password_confirm= vzx.wC4Akd4x-Dj6Wguh
init_password.db_username = root
init_password.generate_ssh_key = true
init_scripts.run_scripts = true
@ -93,14 +93,14 @@ ARTIFACT_REGISTRY_AVAILABLE = true
CLUSTER_ENV = prod
CLUSTER_NAME = knoe-db
CNPG_ELIGIBLE_NODES = gke-knoe-cnpg-0-default-pool-56407930-wlg9,gke-knoe-cnpg-0-default-pool-b142a290-bmr3,gke-knoe-cnpg-0-default-pool-d8e3a5ef-lmpl
CNPG_PLACEMENT_PLAN_FILE = /Users/chrisfu/dev/prole/conf/cnpg-placement/knoe-system-knoe-db.json
CNPG_PLACEMENT_PLAN_FILE = $HOME/dev/prole/conf/cnpg-placement/knoe-system-knoe-db.json
CNPG_PLACEMENT_PLAN_HASH = a44825aeb5ed4e13
CNPG_PLACEMENT_PLAN_ID = cnpg-placement-a44825aeb5ed4e13
CNPG_STAGE1_NODE = gke-knoe-cnpg-0-default-pool-56407930-wlg9
DATABASE_NAMESPACE = knoe-db-0
DB_CLUSTER_KUBECONTEXT = gke_plenary-truck-485623-p7_us-west3_knoe-cnpg-0
DB_HOST_PORT = 5432
DB_PASSWORD = ${PROLE_SECRET:v1:vnEWu4ZkBlVtoi-J:Dq_Gluj0Yv_3HdbN_9V53QMf9mPRXotsX04HWsMeY92GBj3O}
DB_PASSWORD= vzx.wC4Akd4x-Dj6Wguh
DEPLOYMENT_MODE = k8s
DEPLOYMENT_TARGET = prole-prod-cluster
DOCKER_PRELOAD = false
@ -124,8 +124,8 @@ SUPABASE_PV_NODE = gandalf.prole.org
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_INFRASTRUCTURE = $HOME/dev/prole/infrastructure
ANSIBLE_INVENTORY = $HOME/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","gandalf.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["merlin.prole.org","gandalf.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","gandalf.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"],"k3s_hosts":["gandalf.prole.org"]},"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":["gandalf.prole.org","k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
KDC_ANSIBLE_DETECTED = 10.0.0.3
@ -136,11 +136,11 @@ KERBEROS_AUTO_ENABLED = True
; 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
PROLE_CONF = $HOME/dev/prole/conf
PROLE_DATA = $HOME/dev/prole/data
PROLE_HOME = $HOME/dev/prole
PROLE_LOGS = $HOME/dev/prole/logs
PROLE_SERVICE = $HOME/dev/prole/etc
[Monitoring]
; No configuration values captured yet for this section.
@ -157,7 +157,7 @@ OLLAMA_SERVER_PORT = 11434
AT_REST_ENCRYPTION_ENABLED = True
GITOPS_ENABLED = False
KERBEROS_ENABLED = True
SUPABASE_ENABLED = False
SUPABASE_ENABLED = True
[GitOps]
; No configuration values captured yet for this section.
@ -196,7 +196,7 @@ org_id = 584001916389
project_id = plenary-truck-485623-p7
[Prod Cluster (k8s)]
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
ARTIFACTS_DIR = $HOME/dev/prole/data/staging
CLUSTER_ENV = prole-prod-cluster
DISPLAY_NAME = prole-prod-cluster
INSTALL_PLAN = Validate production config and required secrets

View File

@ -1,5 +1,5 @@
; Prole Master Configuration File
; Generated by install.py on 2026-04-09 23:19:13
; Generated by install.py on 2026-04-10 04:24:51
; This file is used as input for Ansible deployment and k8s cluster creation.
[User]
@ -23,12 +23,12 @@ dependencies.verify_all = false
disk_selection.disk_type = local
disk_selection.local_path = /Users/chrisfu
disk_selection.removable_mount =
env_setup.APP_CLUSTER_KUBECONTEXT = gke_plenary-truck-485623-p7_us-west3_knoe-dev-0
env_setup.APP_CLUSTER_KUBECONTEXT =
env_setup.APP_CLUSTER_MODE = standard
env_setup.APP_CLUSTER_NAME = knoe-dev-0
env_setup.CLUSTER_NAME = ${CLUSTER_NAME}
env_setup.DATABASE_NAMESPACE = ${DATABASE_NAMESPACE}
env_setup.DB_CLUSTER_KUBECONTEXT = gke_plenary-truck-485623-p7_us-west3_knoe-cnpg-0
env_setup.DB_CLUSTER_KUBECONTEXT =
env_setup.DB_CLUSTER_MODE = standard
env_setup.DB_CLUSTER_NAME = knoe-cnpg-0
env_setup.PROLE_CONF = /Users/chrisfu/dev/prole/conf
@ -74,14 +74,14 @@ init_password.cluster_name = ${CLUSTER_NAME}
init_password.db_cluster_name = knoe-cnpg-0
init_password.db_host_port = 5432
init_password.db_namespace = ${DATABASE_NAMESPACE}
init_password.db_password = ${PROLE_SECRET:v1:aqtfPnE_i0CuDU42:KvAQK1cUXKkFPta7NGyaWJVX1Ufw6xH432ZLzg==}
init_password.db_password_confirm = ${PROLE_SECRET:v1:aqtfPnE_i0CuDU42:KvAQK1cUXKkFPta7NGyaWJVX1Ufw6xH432ZLzg==}
init_password.db_password = ${PROLE_SECRET:v1:5fkkNdavd6ZL6a5E:HmuHq76QWhbvIEXshH7LV6Xa62zmA6RrRPOzhMUWoKmPaYXf}
init_password.db_password_confirm = ${PROLE_SECRET:v1:5fkkNdavd6ZL6a5E:HmuHq76QWhbvIEXshH7LV6Xa62zmA6RrRPOzhMUWoKmPaYXf}
init_password.db_username = chrisfu
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.196
kerberos_config.kdc = 10.0.0.205
kerberos_config.password =
kerberos_config.realm =
kerberos_config.test_connection = false
@ -93,20 +93,16 @@ ollama_config.server_port = 11434
[Global]
; Variables used by name in more than one place or assumed global scope
APP_CLUSTER_KUBECONTEXT = gke_plenary-truck-485623-p7_us-west3_knoe-dev-0
ARGOCD_NAMESPACE = argocd
ARTIFACT_REGISTRY = us-west3-docker.pkg.dev/plenary-truck-485623-p7/knoe-system
CLUSTER_ENV = prod
CLUSTER_NAME = knoe-db
CLUSTER_SIZE_PROFILE = small
CNPG_ELIGIBLE_NODES = gke-knoe-cnpg-0-default-pool-56407930-wlg9,gke-knoe-cnpg-0-default-pool-b142a290-bmr3,gke-knoe-cnpg-0-default-pool-d8e3a5ef-lmpl
CNPG_INSTANCES = 3
CNPG_SIZE_PROFILE = small
CNPG_STAGE1_NODE = gke-knoe-cnpg-0-default-pool-56407930-wlg9
DATABASE_NAMESPACE = knoe-db-0
DB_CLUSTER_KUBECONTEXT = gke_plenary-truck-485623-p7_us-west3_knoe-cnpg-0
DB_HOST_PORT = 5432
DB_PASSWORD = ${PROLE_SECRET:v1:BQs_xFgVxqbFwmtj:bXF155fo4KH1ZSwz9NvhgqTwQ7_oRkHewFsm5w==}
DB_PASSWORD = ${PROLE_SECRET:v1:yCJTqE6y6mZD5jUs:U5KhexVZFrKeKP7CjHXLWQLPNn7rwUv4afyGi0p9ncDDYF47}
DEPLOYMENT_MODE = k8s
DEPLOYMENT_TARGET = prole-prod-cluster
DOCKER_IMPORT_DIR =
@ -114,7 +110,6 @@ DOCKER_PRELOAD = false
K3S_SERVER =
K3S_TOKEN =
KNOE_DB_USER = chrisfu
KUBECONTEXT = gke_plenary-truck-485623-p7_us-west3_knoe-dev-0
OPENTOFU_URL = http://127.0.0.1:8080
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
PROLE_HOME = /Users/chrisfu/dev/prole
@ -128,7 +123,7 @@ SERVICE_NAMESPACE = knoe-system
STATUS = All installed
[Network]
KDC_AUTO_DETECTED = 10.0.0.196
KDC_AUTO_DETECTED = 10.0.0.205
KERBEROS_AUTO_ENABLED = True
[Port Forwards]
@ -152,7 +147,7 @@ PROLE_SERVICE = /Users/chrisfu/dev/prole/etc
; No configuration values captured yet for this section.
[Kerberos Authentication]
; No configuration values captured yet for this section.
STATUS = Initialized
[Ollama]
; No configuration values captured yet for this section.
@ -164,6 +159,7 @@ KERBEROS_ENABLED = false
SUPABASE_ENABLED = false
[GitOps]
STATUS = Skipped
[Database Creation]
APP_CLUSTER_NAME = knoe-dev-0

BIN
img/.DS_Store vendored

Binary file not shown.

View File

@ -1,7 +1,8 @@
vault_prole_db_master_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
34636665663663616661623235656234636236363764383766353934306466363238326165616632
3937613765353935636661333032306333626234306564370a373630393535643531623764383661
63616233643631666539346534666332343463633435653736336666643066383062303566326235
3138626139363635390a376335666665366261623761383764393833396533396662643439666339
34333464623839666532313463363062366533393033626130613132346639633030
$ANSIBLE_VAULT;1.1;AES256
33623434353765353030333339626631656163343239353230643430356466306461663835383566
3564333737623034343837616632386462306462366538390a623538373034383839376261653734
36653238393437656332373965663866653730343864333063366462303661356366323262363839
3961633266353131310a313930346164393031623037393339356539616639343536353163343036
61353535633234363535633437356162626234356139323531643534613961633166393135356562
30306634646130353665656262393132656632373634353765316630643665356331363435366165
356261383336383736336336356564386337

View File

@ -0,0 +1 @@
448ff34980e3a5fa3a21450701708387ea44574a9a76220310731333c2a72a5d

View File

@ -0,0 +1 @@
G09lwp<EFBFBD>®last_completedª2026-04-10

View File

@ -0,0 +1 @@
ּת©אU9nַש 5¼ג‰₪ lW?,¦ח§׳f”ם0ז6ןִHֶֿ<1B>§ע•¡®¦§¥<03>uz<75>{

View File

@ -0,0 +1 @@
0<>6<EFBFBD><36>H<EFBFBD><48><EFBFBD><1B><><EFBFBD><EFBFBD><><7F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>k<EFBFBD><03>uz<75>{

View File

@ -80,6 +80,7 @@ from knoe.core.milestones import (
InitializationScriptsMilestone,
KerberosMilestone,
DeploymentMilestone,
SecurityMilestone,
GitOpsMilestone,
SupabaseImagePreloadMilestone,
SupabaseMilestone,
@ -6876,6 +6877,7 @@ class KnoeConsoleInstaller(KnoeInstaller):
SupabaseImagePreloadMilestone(),
SupabaseMilestone(),
DeploymentMilestone(),
SecurityMilestone(),
]
try:

View File

@ -974,6 +974,65 @@ class DeploymentMilestone(Milestone):
progress("Deployment complete", 1.0)
class SecurityMilestone(Milestone):
"""Enforce uniform master password across all services via update.sh.
Runs update.sh (reads vault_prole_db_master_password from the Ansible vault)
and applies the password to k8s secrets, PostgreSQL, and Grafana. Only
active in k8s mode silently skipped for k3s/k3d.
"""
def __init__(self):
super().__init__("security", "Security Hardening")
self.logger = logging.getLogger("SecurityMilestone")
def execute(
self, state: InstallerState, progress: ProgressCallback | None = None
) -> None:
env = self._get_script_env(state)
mode = env.get("PROLE_MODE", "")
if mode != "k8s":
self.logger.info(
f"[SECURITY] Mode={mode!r}: skipping live secret rotation (non-k8s)."
)
if progress:
progress("Security hardening skipped (non-k8s mode)", 1.0)
return
project_root = getattr(state.controller, "project_root", ".")
update_sh = str(Path(project_root) / "update.sh")
if not Path(update_sh).exists():
self.logger.warning(
f"[SECURITY] update.sh not found at {update_sh} — skipping."
)
if progress:
progress("update.sh not found — skipping security hardening", 1.0)
return
if progress:
progress("Rotating master password via update.sh...", 0.2)
self.logger.info("[SECURITY] Running update.sh to enforce vault master password.")
script_env = {
**env,
"PATH": os.environ.get("PATH", ""),
}
rc = subprocess.call([update_sh], env=script_env)
if rc != 0:
raise Exception(
f"update.sh failed with exit code {rc}. "
"Run './update.sh --prompt' to recreate the vault file if it is corrupt."
)
self.logger.info("[SECURITY] Master password rotation complete.")
state.config_data.setdefault("Security", {})["STATUS"] = "Secured"
if progress:
progress("Security hardening complete", 1.0)
class GitOpsMilestone(Milestone):
def __init__(self):
super().__init__("gitops", "GitOps")

View File

@ -340,7 +340,7 @@ class KnoeInstaller(
("GitOps", "gitops_config"),
("Supabase", "supabase_config"),
("Deployment", "init_cnpg_deploy"),
("Post Install", "create_installer"),
("Security", "security"),
]
self.nav_widgets = {}
self._mode_tab_widgets: dict = {}
@ -878,6 +878,7 @@ class KnoeInstaller(
"disk_selection", self._render_disk_selection_page
)
self._register_canvas_renderer("build_summary", self._render_build_summary_page)
self._register_canvas_renderer("security", self._render_security_page)
self._register_canvas_renderer(
"create_installer", self._render_create_installer_page
)
@ -902,6 +903,7 @@ class KnoeInstaller(
self._register_page("gitops_config", None)
self._register_page("supabase_config", None)
self._register_page("init_cnpg_deploy", None)
self._register_page("security", None)
self._register_page("build", None)
self._register_page("disk_selection", None)
self._register_page("build_summary", None)

View File

@ -799,7 +799,14 @@ class NavigationMixin:
"Deployed" if getattr(self, "_cnpg_success", False) else "Attempted"
)
self._save_prole_cfg()
self.show_page("create_installer")
self.show_page("security")
return
if current_id == "security":
if "Install" in self.prole_cfg_data:
self.prole_cfg_data["Install"]["STATUS"] = "Finished"
self._save_prole_cfg()
self.root.destroy()
return
if current_id == "create_installer":

View File

@ -417,6 +417,205 @@ class PackagingScreenMixin:
)
self._canvas_items.append(self._build_a_bao_status_label)
# -----------------------------------------------------------------------
# Security screen — post-deployment account status + ingress links
# -----------------------------------------------------------------------
def _render_security_page(self): # noqa: C901
"""Security dashboard: secured account status + clickable service links."""
content_width = self.bg_canvas.winfo_width() or 975
right_margin = content_width - 48
# --- Letterhead ---
ui.canvas_text(
self, right_margin, 40, "knoe.dev",
fill="#6e6e73", font=("SF Pro Text", 32, "bold"), anchor="ne",
)
ui.canvas_text(
self, right_margin, 85, "infrastructure.auto()",
fill="#6e6e73", font=("SF Pro Text", 18), anchor="ne",
)
self._render_title("Security", y=150)
self._render_paragraph(
"Installation complete. All service accounts are controlled by the vault master password.",
y=198,
)
# --- Section A: Account security status ---
ui.canvas_text(
self, 48, 255, "Account Security",
fill="#1d1d1f", font=("SF Pro Text", 13, "bold"),
)
# Determine overall security status from config data
security_status = (
(self.prole_cfg_data.get("Security", {}) or {}).get("STATUS", "")
)
secured = security_status == "Secured"
_GREEN = "#30d158"
_RED = "#ff453a"
_YELLOW = "#ffd60a"
_GRAY = "#8e8e93"
accounts = [
("Grafana admin", "prometheus-grafana", "monitoring"),
("PostgreSQL prole", "knoe-db-user", "knoe-db-0"),
("PostgreSQL postgres", "knoe-db-superuser", "knoe-db-0"),
("OpenBao root", "openbao-root-token", "knoe-system"),
]
dot_color = _GREEN if secured else (_RED if security_status else _YELLOW)
status_text = "Secured ✓" if secured else ("Pending" if not security_status else "Check failed ✗")
y_row = 285
for label, _secret, _ns in accounts:
# Colored dot
oval = self.bg_canvas.create_oval(48, y_row, 60, y_row + 12, fill=dot_color, outline="")
self._canvas_items.append(oval)
ui.canvas_text(
self, 72, y_row + 1, f"{label}",
fill="#1d1d1f", font=("SF Pro Text", 12), anchor="nw",
)
ui.canvas_text(
self, 340, y_row + 1, status_text,
fill=dot_color if secured else _GRAY,
font=("SF Pro Text", 12), anchor="nw",
)
y_row += 32
# Run update.sh button (re-rotate on demand)
def _run_update_sh():
import threading as _th
_update_label = getattr(self, "_sec_update_label", None)
if _update_label:
self.bg_canvas.itemconfigure(_update_label, text="Running update.sh…", fill=_YELLOW)
def _worker():
try:
rc = subprocess.call(
[str(PROJECT_ROOT / "update.sh")],
env={**os.environ},
)
msg = "Password rotation complete ✓" if rc == 0 else f"update.sh failed (code {rc})"
color = _GREEN if rc == 0 else _RED
if rc == 0:
self.prole_cfg_data.setdefault("Security", {})["STATUS"] = "Secured"
except Exception as exc:
msg = f"Error: {exc}"
color = _RED
if _update_label:
self.bg_canvas.after(0, lambda: self.bg_canvas.itemconfigure(
_update_label, text=msg, fill=color
))
_th.Thread(target=_worker, daemon=True).start()
update_btn = tk.Button(
self.bg_canvas,
text="Rotate Passwords Now",
command=_run_update_sh,
bg="#007aff", fg="white",
activebackground="#0051d0",
highlightbackground="#007aff",
highlightthickness=0,
relief="flat",
font=("SF Pro Text", 11),
padx=14, pady=7,
)
btn_win = self.bg_canvas.create_window(48, y_row + 8, window=update_btn, anchor="nw")
self._canvas_items.append(btn_win)
self._overlay_widgets.append(update_btn)
self._sec_update_label = ui.canvas_text(
self, 220, y_row + 14, "", fill=_GRAY, font=("SF Pro Text", 11), anchor="nw",
)
self._canvas_items.append(self._sec_update_label)
# --- Section B: Service links ---
y_links = y_row + 55
ui.canvas_text(
self, 48, y_links, "Service Links",
fill="#1d1d1f", font=("SF Pro Text", 13, "bold"),
)
y_links += 28
# Resolve Kong external IP (non-blocking best-effort)
app_ctx = (self.prole_cfg_data.get("Global", {}) or {}).get(
"APP_CLUSTER_KUBECONTEXT", ""
).strip()
kong_ip = "<pending>"
try:
_res = subprocess.run(
[
"kubectl",
*(["--context", app_ctx] if app_ctx else []),
"get", "svc", "-n", "knoe-system",
"-l", "app.kubernetes.io/name=kong",
"-o", "jsonpath={.items[0].status.loadBalancer.ingress[0].ip}",
],
capture_output=True, text=True, timeout=8,
)
if _res.returncode == 0 and _res.stdout.strip():
kong_ip = _res.stdout.strip()
except Exception:
pass
db_ns = (self.prole_cfg_data.get("Global", {}) or {}).get(
"DATABASE_NAMESPACE", "knoe-db-0"
)
_links = [
("Grafana", f"http://{kong_ip}/grafana" if kong_ip != "<pending>" else "http://localhost:3000"),
("Prometheus", f"http://{kong_ip}/prometheus" if kong_ip != "<pending>" else "http://localhost:9090"),
("Gateway", "http://svc.knoe.dev (DNS pending)"),
("PostgreSQL", f"knoe-db-rw.{db_ns}.svc.cluster.local:5432 (cluster-internal)"),
]
for link_label, link_url in _links:
ui.canvas_text(
self, 48, y_links, f"{link_label}:",
fill="#1d1d1f", font=("SF Pro Text", 12, "bold"), anchor="nw",
)
is_http = link_url.startswith("http://") or link_url.startswith("https://")
_url = link_url
link_item = ui.render_link(
self, 160, y_links, link_url,
color="#0a84ff" if is_http else _GRAY,
font=("SF Pro Text", 12, "underline" if is_http else "normal"),
)
if is_http:
def _make_opener(url=_url, item=link_item):
def _on_click(event):
bbox = self.bg_canvas.bbox(item)
if bbox and bbox[0] <= event.x <= bbox[2] and bbox[1] <= event.y <= bbox[3]:
webbrowser.open(url)
return _on_click
self.bg_canvas.bind("<Button-1>", _make_opener(), add="+")
y_links += 28
# Kong IP info line
ui.canvas_text(
self, 48, y_links + 4,
f"Kong external IP: {kong_ip}",
fill=_GRAY, font=("SF Pro Text", 11),
)
# --- Footer: View logs link ---
y_footer = y_links + 40
logs_link = ui.render_link(
self, 48, y_footer, "View installation logs →",
color="#0a84ff", font=("SF Pro Text", 12, "underline"),
)
def _open_logs(event):
bbox = self.bg_canvas.bbox(logs_link)
if bbox and bbox[0] <= event.x <= bbox[2] and bbox[1] <= event.y <= bbox[3]:
self.show_page("create_installer")
self.bg_canvas.bind("<Button-1>", _open_logs, add="+")
def _get_prole_dist_dir(self) -> Path:
return PROJECT_ROOT / "prole-tools-app" / "dist"

View File

@ -1,53 +1,54 @@
Network Discovery Summary:
Primary Router: 10.0.0.1 (eero_5d:50:f2)
DNS Servers: 100.100.100.100, 10.0.0.4, 10.0.0.5
Primary Router: 10.0.0.1 (Unknown)
DNS Servers: 100.100.100.100, 10.0.0.5, 10.0.0.4
Detected Devices:
- 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.39 [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.7 [2c:cf:67:ca:93:ce] (RaspberryPi_ca:93:ce): Ports [22], Services: ['SSH']
- 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.6 [2c:cf:67:45:8d:97] (RaspberryPi_45:8d:97): Ports [22, 80, 443], Services: ['SSH', 'Web Server']
- 10.0.0.26 [c8:db:26:08:52:f8] (Logitech_08:52:f8): Ports [], Services: []
- 10.0.0.32 [48:a6:b8:a4:8e:cc] (Sonos_a4:8e:cc): Ports [], Services: []
- 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.1 [9c:57:bc:5d:50:f2] (eero_5d:50:f2): Ports [53], Services: ['DNS']
- 10.0.0.2 [dc:a4:ca:ea:1a:2f] (Apple_ea:1a:2f): Ports [], Services: []
- 10.0.0.5 [b8:27:eb:88:3a:41] (RaspberryPiF_88:3a:41): Ports [22, 2049, 5900], Services: ['SSH', 'NFS', 'VNC']
- 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.188 [00:16:6c:c5:1f:54] (SamsungElect_c5:1f:54): Ports [80], Services: ['Web Server']
- 10.0.0.33 [ec:b5:fa:b0:76:e4] (PhilipsLight_b0:76:e4): Ports [80, 443], Services: ['Web Server']
- 10.0.0.37 [54:07:7d:22:c0:b2] (Netgear_22:c0:b2): Ports [80], Services: ['Web Server']
- 10.0.0.44 [24:fc:e5:51:cf:74] (SamsungElect_51:cf:74): Ports [], Services: []
- 10.0.0.45 [f8:b4:6a:30:a4:1f] (HewlettPacka_30:a4:1f): Ports [80, 443], Services: ['Web Server']
- 10.0.0.48 [0c:fe:45:53:f4:3c] (SonyInteract_53:f4:3c): Ports [], Services: []
- 10.0.0.36 [7e:46:74:2a:b0:b2] (7e:46:74:2a:b0:b2): Ports [], Services: []
- 10.0.0.52 [2c:cf:67:ca:93:ce] (RaspberryPi_ca:93:ce): Ports [22], Services: ['SSH']
- 10.0.0.46 [d4:f7:d5:40:ab:17] (SonyInteract_40:ab:17): Ports [], Services: []
- 10.0.0.111 [ca:0b:6c:5d:0a:e5] (ca:0b:6c:5d:0a:e5): Ports [], Services: []
- 10.0.0.128 [20:c9:d0:94:30:dd] (Apple_94:30:dd): Ports [22, 445, 5900, 88], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'Active Directory Related']
- 10.0.0.73 [4c:a9:19:b3:12:f8] (TuyaSmart_b3:12:f8): Ports [], Services: []
- 10.0.0.94 [f0:20:ff:bf:9a:19] (Intel_bf:9a:19): Ports [], Services: []
Note: Potential host for NVIDIA cards (PC Hardware vendor)
- 10.0.0.95 [b8:27:eb:88:3a:41] (RaspberryPiF_88:3a:41): Ports [22], Services: ['SSH']
- 10.0.0.106 [48:a6:b8:a7:50:60] (Sonos_a7:50:60): 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.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.125 [a0:60:32:04:73:ba] (AmcrestTechn_04:73:ba): Ports [80], Services: ['Web Server']
- 10.0.0.127 [58:55:ca:4a:60:6e] (Apple_4a:60:6e): Ports [22], Services: ['SSH']
- 10.0.0.130 [f8:bb:bf:a3:84:eb] (eero_a3:84:eb): Ports [], Services: []
- 10.0.0.145 [7c:a6:b0:04:db:1c] (7c:a6:b0:04:db:1c): Ports [], Services: []
- 10.0.0.143 [60:5f:8d:7a:aa:32] (eero_7a:aa:32): Ports [53], Services: ['DNS']
- 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.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.175 [28:80:88:e4:10:1a] (Netgear_e4:10:1a): Ports [80], Services: ['Web Server']
- 10.0.0.39\ [7e:19:9a:fe:9f:ed] (7e:19:9a:fe:9f:ed): Ports [], Services: []
- 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.206 [00:a0:de:a2:0b:ef] (Yamaha_a2:0b:ef): Ports [80], Services: ['Web Server']
- 10.0.0.73 [4c:a9:19:b3:12:f8] (TuyaSmart_b3:12:f8): Ports [], Services: []
- 10.0.0.107 [b8:06:0d:b7:7c:56] (TuyaSmart_b7:7c:56): Ports [], Services: []
- 10.0.0.47 [c6:d0:1a:97:9f:e9] (c6:d0:1a:97:9f:e9): Ports [], Services: []
- 10.0.0.44 [24:fc:e5:51:cf:74] (SamsungElect_51:cf:74): Ports [], Services: []
- 10.0.0.1 [Unknown] (Unknown): Ports [53], Services: ['DNS']
- 10.0.0.2 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.3 [Unknown] (Unknown): 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.4 [Unknown] (Unknown): Ports [22, 53, 443, 2049], Services: ['DNS', 'SSH', 'NFS', 'Web Server']
- 10.0.0.5 [Unknown] (Unknown): Ports [22, 2049, 5900], Services: ['SSH', 'NFS', 'VNC']
- 10.0.0.6 [Unknown] (Unknown): Ports [22, 80, 443], Services: ['SSH', 'Web Server']
- 10.0.0.7 [Unknown] (Unknown): Ports [22], Services: ['SSH']
- 10.0.0.22 [Unknown] (Unknown): Ports [22], Services: ['SSH']
Ollama Instances found at: 10.0.0.39, 10.0.0.204
- 10.0.0.26 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.32 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.37 [Unknown] (Unknown): Ports [80], Services: ['Web Server']
- 10.0.0.45 [Unknown] (Unknown): Ports [80, 443], Services: ['Web Server']
- 10.0.0.46 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.48 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.50 [Unknown] (Unknown): Ports [22, 445, 5900, 11434, 88], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'Ollama', 'Active Directory Related']
- 10.0.0.52 [Unknown] (Unknown): Ports [22], Services: ['SSH']
- 10.0.0.95 [Unknown] (Unknown): Ports [22, 2049, 5900], Services: ['SSH', 'NFS', 'VNC']
- 10.0.0.106 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.111 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.112 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.113 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.123 [Unknown] (Unknown): Ports [80], Services: ['Web Server']
- 10.0.0.124 [Unknown] (Unknown): Ports [80], Services: ['Web Server']
- 10.0.0.125 [Unknown] (Unknown): Ports [80], Services: ['Web Server']
- 10.0.0.127 [Unknown] (Unknown): Ports [22], Services: ['SSH']
- 10.0.0.128 [Unknown] (Unknown): Ports [22, 445, 5900, 88], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'Active Directory Related']
- 10.0.0.143 [Unknown] (Unknown): Ports [53], Services: ['DNS']
- 10.0.0.145 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.170 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.175 [Unknown] (Unknown): Ports [80], Services: ['Web Server']
- 10.0.0.196 [Unknown] (Unknown): Ports [53], Services: ['DNS']
- 10.0.0.199 [Unknown] (Unknown): Ports [], Services: []
- 10.0.0.204 [Unknown] (Unknown): Ports [22, 3389, 445, 5900, 11434], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'RDP (Windows)', 'Ollama']
- 10.0.0.205 [Unknown] (Unknown): Ports [22, 445, 5900, 88], Services: ['SSH', 'VNC', 'SMB/CIFS (Possible Windows/AD)', 'Active Directory Related']
- 10.0.0.206 [Unknown] (Unknown): Ports [80], Services: ['Web Server']
- 10.0.0.155 [62:17:97:b3:06:a1] (62:17:97:b3:06:a1): Ports [], Services: []
Ollama Instances found at: 10.0.0.39, 10.0.0.50, 10.0.0.204
Ansible Inventory Summary:
Inventory directory: /Users/chrisfu/dev/prole/infrastructure

29
tmp/check_and_cleanup.sh Normal file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting minio-create-buckets jobs (buckets already exist)..."
kubectl -n gitea delete jobs -l app=minio-create-buckets --ignore-not-found 2>&1
echo "==> Webservice kgqhl status:"
kubectl -n gitea get pod gitlab-webservice-default-675ccb7b99-kgqhl \
-o custom-columns='NAME:.metadata.name,READY:.status.containerStatuses[*].ready,NODE:.spec.nodeName' 2>&1
echo "==> Webservice kgqhl puma log (last 5):"
kubectl -n gitea logs gitlab-webservice-default-675ccb7b99-kgqhl \
-c webservice --tail=5 2>&1 | grep -v LD_PRELOAD | head -8 || true
echo "==> Sidekiq pending reason:"
kubectl -n gitea describe pod gitlab-sidekiq-all-in-1-v2-679848bc8-wvxln 2>&1 \
| grep -E "Events:|Warning|Error|Insufficient|fit" | head -8
echo "==> Force-delete extra Pending webservice pod..."
kubectl -n gitea delete pod gitlab-webservice-default-675ccb7b99-x56sq \
--force --grace-period=0 --ignore-not-found 2>&1
echo "==> HPA current state:"
kubectl -n gitea get hpa 2>&1 | grep -E "NAME|webservice|sidekiq|kas|shell|registry"
echo "==> All pods (wide):"
kubectl -n gitea get pods --no-headers -o wide \
| grep -v jemalloc | grep -v Completed \
| awk '{printf "%-52s %-8s %-20s %s\n",$1,$4,$7,$8}' | sort

22
tmp/check_and_fix_dirs.sh Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Verify dirs on gandalf..."
kubectl -n gitlab run dircheck \
--image=alpine:latest --restart=Never --rm --attach \
--overrides='{
"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],
"volumes":[{"name":"syn","hostPath":{"path":"/synology/d005","type":"Directory"}}],
"containers":[{"name":"dircheck","image":"alpine:latest",
"command":["sh","-c","ls -la /syn/gitlab/ 2>&1 || echo DIR_MISSING; mkdir -p /syn/gitlab/minio /syn/gitlab/gitaly && chmod 777 /syn/gitlab/minio /syn/gitlab/gitaly && echo CREATED && ls -la /syn/gitlab/"],
"volumeMounts":[{"name":"syn","mountPath":"/syn"}]}]}}' 2>&1
echo "==> Force rescheduling minio pod..."
kubectl -n gitlab delete pod gitlab-minio-5459cf9679-7nv6c --ignore-not-found
echo "==> Waiting 60s..."
sleep 60
echo "==> Status:"
kubectl -n gitlab get pods --sort-by=.metadata.creationTimestamp | grep -v jemalloc-builder

View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> minio-init pod status:"
kubectl -n gitea get pod minio-init --no-headers 2>&1
echo "==> minio-init logs:"
kubectl -n gitea logs minio-init 2>&1 | tail -20
echo "==> Restarting registry (pick up new buckets):"
kubectl -n gitea delete pod -l app=registry --ignore-not-found 2>&1
echo "==> Waiting 60s..."
sleep 60
echo "==> All GitLab pods:"
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | sort
echo "==> GitLab CR status:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' 2>&1 && echo
echo "==> Installer log tail:"
tail -5 /Users/chrisfu/dev/prole/logs/install_run8.log 2>&1

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Gitaly PVC:"
kubectl -n gitea get pvc repo-data-gitlab-gitaly-0 2>&1
echo "==> Gitaly pod events:"
kubectl -n gitea describe pod gitlab-gitaly-0 2>&1 | grep -A3 "Events:" | tail -8
echo "==> PV status:"
kubectl get pv gitlab-gitaly-synology gitlab-minio-synology \
-o custom-columns='NAME:.metadata.name,STATUS:.status.phase,CLAIM:.spec.claimRef.name' 2>&1
echo "==> Registry crash log:"
kubectl -n gitea logs gitlab-registry-75b586f9fd-cw8gl --previous --tail=15 2>&1 \
| grep -v "LD_PRELOAD" | head -15 || true
echo "==> Exporter crash log:"
kubectl -n gitea logs gitlab-gitlab-exporter-54575ddcdb-lcprm --previous --tail=10 2>&1 \
| grep -v "LD_PRELOAD" | head -10 || true

View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
for node in gandalf.prole.org merlin.prole.org myrddin.prole.org pi.prole.org; do
safe="${node//./-}"
echo -n "==> $node: "
kubectl -n gitlab run "jv2-${safe}" \
--image=ubuntu:22.04 --restart=Never --rm --attach --quiet \
--overrides="{
\"spec\":{
\"nodeName\":\"${node}\",
\"tolerations\":[{\"operator\":\"Exists\"}],
\"volumes\":[{\"name\":\"jlib\",\"hostPath\":{\"path\":\"/opt/gitlab-jemalloc\",\"type\":\"DirectoryOrCreate\"}}],
\"containers\":[{
\"name\":\"c\",
\"image\":\"ubuntu:22.04\",
\"command\":[\"bash\",\"-c\",
\"test -f /jlib/libjemalloc.so.2 && ls -lh /jlib/libjemalloc.so.2 || echo MISSING\"],
\"volumeMounts\":[{\"name\":\"jlib\",\"mountPath\":\"/jlib\"}]
}]
}}" 2>&1 || true
done

20
tmp/check_readiness.sh Normal file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Webservice puma latest log (kgqhl):"
kubectl -n gitea logs gitlab-webservice-default-675ccb7b99-kgqhl \
-c webservice --tail=8 2>&1 | grep -v LD_PRELOAD || true
echo "==> Sidekiq latest log:"
kubectl -n gitea logs gitlab-sidekiq-all-in-1-v2-679848bc8-wvxln \
--tail=10 2>&1 | grep -v LD_PRELOAD | grep -v "^$" | head -10 || true
echo "==> Available condition:"
kubectl -n gitea get gitlab gitlab \
-o jsonpath='{range .status.conditions[*]}{.type}: {.status} — {.message}{"\n"}{end}' 2>&1
echo "==> minio-create-buckets crash image + log:"
kubectl -n gitea get pod -l app=minio-create-buckets \
-o jsonpath='{.items[0].spec.containers[0].image}' 2>&1 && echo
kubectl -n gitea logs -l app=minio-create-buckets \
--tail=5 2>&1 | grep -v LD_PRELOAD | head -5 || true

18
tmp/check_registry.sh Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Registry crash log:"
kubectl -n gitea logs gitlab-registry-75b586f9fd-455x2 --previous --tail=20 2>&1 \
| grep -v "LD_PRELOAD" | head -20 || \
kubectl -n gitea logs -l app=registry --tail=20 2>&1 \
| grep -v "LD_PRELOAD" | head -20 || true
echo "==> All pods incl webservice/sidekiq:"
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | sort
echo "==> Migrations status:"
kubectl -n gitea get jobs --no-headers 2>&1 | grep migrations || \
kubectl -n gitea get pods --no-headers | grep migrations
echo "==> Installer run 9 tail:"
tail -8 /Users/chrisfu/dev/prole/logs/install_run9.log 2>&1

View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
cd /Users/chrisfu/dev/prole
echo "==> Killing any running installer..."
pkill -f "install.sh" 2>/dev/null || true
pkill -f "init_gitlab.sh" 2>/dev/null || true
sleep 3
echo "==> Deleting PVs with old claimRefs..."
for pv in gitlab-gitaly-synology gitlab-minio-synology; do
kubectl patch pv "$pv" -p '{"metadata":{"finalizers":[]}}' --type=merge 2>/dev/null || true
kubectl delete pv "$pv" --ignore-not-found 2>/dev/null || true
done
echo "==> Wiping synology gitlab dirs..."
kubectl -n knoe-system run wipe-gitlab --image=alpine:latest --restart=Never --rm --attach \
--overrides='{"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],"volumes":[{"name":"s","hostPath":{"path":"/synology/d005","type":"Directory"}}],"containers":[{"name":"w","image":"alpine:latest","command":["sh","-c","rm -rf /s/gitlab && echo wiped"],"volumeMounts":[{"name":"s","mountPath":"/s"}]}]}}' 2>&1 || true
echo "==> Removing stale PID..."
rm -f install.pid
echo "==> Verifying namespace fix in prole.cfg..."
grep "gitops.gitlab_namespace" conf/service/prole.cfg
echo "==> Verifying init_gitlab.sh lint..."
bash -n etc/init_gitlab.sh && echo " syntax OK"
echo "==> Launching installer..."
mkdir -p logs
nohup bash install.sh --silent -c conf/service/prole.cfg > logs/install_final4.log 2>&1 &
disown
echo "Installer started. Monitor: tail -f logs/install_final4.log"

39
tmp/clean_and_run.sh Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
cd /Users/chrisfu/dev/prole
echo "==> Cleaning leftover gitea namespace..." && \
kubectl get namespace gitea -o json 2>/dev/null \
| python3 -c "import sys,json; d=json.load(sys.stdin); d['spec']['finalizers']=[]; print(json.dumps(d))" \
| kubectl replace --raw /api/v1/namespaces/gitea/finalize -f - 2>/dev/null || true && \
kubectl delete namespace gitea --ignore-not-found --timeout=30s 2>/dev/null || true
echo "==> Releasing/deleting old PVs..." && \
for pv in gitlab-gitaly-synology gitlab-minio-synology; do
kubectl patch pv "$pv" -p '{"metadata":{"finalizers":[]}}' --type=merge 2>/dev/null || true
kubectl delete pv "$pv" --ignore-not-found 2>/dev/null || true
done
echo "==> Wiping synology gitlab dirs for fresh start..." && \
kubectl -n knoe-system run gitlab-wipe --image=alpine:latest --restart=Never --rm --attach \
--overrides='{"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],"volumes":[{"name":"s","hostPath":{"path":"/synology/d005","type":"Directory"}}],"containers":[{"name":"w","image":"alpine:latest","command":["sh","-c","rm -rf /s/gitlab && echo wiped"],"volumeMounts":[{"name":"s","mountPath":"/s"}]}]}}' 2>&1 || true
echo "==> Cleaning leftover ClusterRoles from old installs..." && \
kubectl get clusterrole,clusterrolebinding -o name 2>/dev/null \
| grep -i gitlab | xargs kubectl delete --ignore-not-found 2>&1 || true
echo "==> jemalloc already built on all nodes (reusing)..." && \
ls /opt/gitlab-jemalloc/ 2>/dev/null || true
echo "==> Removing stale PID lock..." && \
rm -f /Users/chrisfu/dev/prole/install.pid
echo "==> Cluster node status:" && \
kubectl get nodes
echo "==> Launching install.sh pipeline (gitlab namespace, gandalf storage)..." && \
mkdir -p logs && \
nohup bash install.sh --silent -c conf/service/prole.cfg \
> logs/install_final.log 2>&1 & disown && \
echo "Installer started — tail logs/install_final.log to monitor"

36
tmp/clean_slate.sh Normal file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting GitLab CR (lets operator clean up managed resources)..."
kubectl -n gitlab delete gitlab gitlab --ignore-not-found --timeout=60s 2>&1 || true
echo "==> Waiting 20s for operator cleanup..."
sleep 20
echo "==> Deleting gitlab namespace (all remaining resources)..."
kubectl delete namespace gitlab --ignore-not-found --timeout=120s 2>&1 || true
echo "==> Deleting jemalloc-builder (if in different ns)..."
kubectl delete daemonset jemalloc-builder -n gitlab --ignore-not-found 2>/dev/null || true
echo "==> Releasing bound/retained PVs for gitlab..."
for pv in gitlab-gitaly-synology gitlab-minio-synology; do
kubectl patch pv "$pv" -p '{"spec":{"claimRef":null}}' 2>/dev/null || true
kubectl delete pv "$pv" --ignore-not-found 2>/dev/null || true
done
echo "==> Wiping synology data dirs on gandalf (fresh start)..."
kubectl -n knoe-system run gitlab-wipe \
--image=alpine:latest --restart=Never --rm --attach \
--overrides='{
"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],
"volumes":[{"name":"s","hostPath":{"path":"/synology/d005","type":"Directory"}}],
"containers":[{"name":"gitlab-wipe","image":"alpine:latest",
"command":["sh","-c","rm -rf /s/gitlab && echo wiped"],
"volumeMounts":[{"name":"s","mountPath":"/s"}]}]}}' 2>&1 || true
echo "==> Verifying gitlab namespace is gone..."
kubectl get ns gitlab 2>&1 || echo "namespace deleted OK"
echo "==> Clean slate complete."

View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Removing finalizers + deleting gitea namespace..."
for res in $(kubectl -n gitea get gitlabs.apps.gitlab.com --no-headers -o name 2>/dev/null || true); do
kubectl -n gitea patch "$res" -p '{"metadata":{"finalizers":[]}}' --type=merge 2>/dev/null || true
done
kubectl get namespace gitea -o json 2>/dev/null \
| python3 -c "import sys,json; d=json.load(sys.stdin); d['spec']['finalizers']=[]; print(json.dumps(d))" \
| kubectl replace --raw /api/v1/namespaces/gitea/finalize -f - 2>&1 || true
kubectl delete namespace gitea --ignore-not-found --timeout=30s 2>&1 || true
echo "==> Releasing/deleting gitlab PVs..."
for pv in gitlab-gitaly-synology gitlab-minio-synology; do
kubectl patch pv "$pv" -p '{"spec":{"claimRef":null}}' 2>/dev/null || true
kubectl delete pv "$pv" --ignore-not-found 2>/dev/null || true
done
echo "==> Wiping synology gitlab dirs..."
kubectl -n knoe-system run gitlab-wipe \
--image=alpine:latest --restart=Never --rm --attach \
--overrides='{"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],"volumes":[{"name":"s","hostPath":{"path":"/synology/d005","type":"Directory"}}],"containers":[{"name":"w","image":"alpine:latest","command":["sh","-c","rm -rf /s/gitlab && echo wiped"],"volumeMounts":[{"name":"s","mountPath":"/s"}]}]}}' 2>&1 || true
echo "==> Cleaning leftover ClusterRoles/Bindings from gitlab operator..."
kubectl get clusterrole,clusterrolebinding -o name 2>/dev/null \
| grep -i gitlab | xargs kubectl delete --ignore-not-found 2>&1 || true
echo "==> Waiting for pi.prole.org to become Ready (up to 5min)..."
for i in $(seq 1 30); do
status=$(kubectl get node pi.prole.org --no-headers 2>/dev/null | awk '{print $2}')
echo " [$i/30] pi status: $status"
[[ "$status" == "Ready" ]] && break
sleep 10
done
echo "==> Final node status:"
kubectl get nodes
echo "==> Clean-up done. Launching installer..."
cd /Users/chrisfu/dev/prole
mkdir -p logs
nohup bash install.sh --silent -c conf/service/prole.cfg \
> logs/install_run6.log 2>&1 &
echo "Installer PID $! — tail logs/install_run6.log to monitor"

9
tmp/clear_old_pods.sh Normal file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
for pod in gitlab-webservice-default-675ccb7b99-9tkdh \
gitlab-webservice-default-675ccb7b99-j684x \
gitlab-sidekiq-all-in-1-v2-679848bc8-mrz9b; do
kubectl -n gitea delete pod "$pod" --force --grace-period=0 --ignore-not-found 2>/dev/null || true
done && \
sleep 20 && \
kubectl -n gitea get pods --no-headers | grep -E "webservice|sidekiq"

73
tmp/commit_msg.txt Normal file
View File

@ -0,0 +1,73 @@
feat: full GKE/prod deployment pipeline from UI to Artifact Registry
## GCP / Cluster Environment Screen
- Auto-populate Cloud tab from conf/prod/gcp.cfg on screen open (org_id,
billing_account, billing_project, project_id)
- gcloud auth validity checked on screen startup; friendly modal dialog
streams gcloud auth login output live so user never leaves the app
- Live GKE cluster browser: fetches clusters via gcloud container clusters
list, displays with checkmark selector, auto-selects saved cluster
- Selecting a cluster runs get-credentials, sets KUBECONFIG/KUBECONTEXT,
and syncs the region dropdown to the selected cluster's location
- Region dropdown populated live from gcloud compute regions list with
checkmark on currently selected region; graceful fallback when offline
- New 'GCP Storage' tab with workload->StorageClass mapping (CNPG->premium-rwo,
Redis/Monitoring->standard-rwo, Garage->garage-hdd) and Fetch from Cluster
- Provider readonly field styled correctly (no solid-black on macOS)
- Stale prole.cfg/conf/prole.cfg symlinks removed; all config I/O now
resolves env-specific paths via prole_conf.entrypoint_path()
## GKE Autopilot Compatibility (Common Services)
- Synology iSCSI StorageClass and static PVs guarded behind PROLE_MODE!=k8s
in init_openbao.sh (GKE Autopilot forbids hostPath/iSCSI volumes)
- In-cluster Docker registry (hostPath) skipped in k8s mode; GCP Artifact
Registry used instead
- Kong renamed knoe-svc-kong in k8s mode; all health-check kubectl calls in
init_common_services.sh and status_common_services.sh updated accordingly
- DNS endpoints switched from *.prole.org to *.knoe.dev in k8s mode
(api.knoe.dev, git.knoe.dev, svc.knoe.dev); ingress uses gce class
- New GKE-clean Kong manifests under deploy/opentofu/k8s/manifests/prole/:
no k3s node affinity, explicit Autopilot resource requests/limits
## Garage S3 Store (GKE)
- New garage-statefulset-gcp.yaml targeting garage-hdd StorageClass
(pd-standard, avoids SSD_TOTAL_GB quota exhaustion in us-west3)
- New storageclass-gcp-hdd.yaml (pd-standard, Retain, WaitForFirstConsumer)
- GCP StorageClass manifests skipped on re-runs (Autopilot built-ins are
immutable; skip-if-exists guard added)
- PVC deletion guard extended to cover any storageClass (not just synology)
so stale claims are cleaned before StatefulSet recreation
## Topology (GKE Autopilot)
- DaemonSet collector skipped in prod mode (forbidden in kube-system by
GKE Warden); Kubernetes-only node facts path used instead
- All ready GKE nodes assumed cnpg-eligible and monitoring-eligible without
taint/synology-mount checks (skip_collector + assume_nodes_eligible flags)
## KUBECONFIG / kubectl (k8s mode)
- actions.py: new elif mode==k8s branch sets KUBECONFIG=~/.kube/config
and injects KUBECONTEXT from prole_cfg_data into script env
- _build_kubectl_cmd falls back to Global.KUBECONTEXT when
init_cluster.selected_kubectx is empty
- _activate_selected_gke_cluster persists KUBECONFIG/KUBECONTEXT to
prole_cfg_data and saves prole.cfg immediately after get-credentials
## Database Build Screen (GKE)
- Registry display shows correct Artifact Registry URL
(<region>-docker.pkg.dev/<project>/<namespace>/knoe-db) in green
- Build+push: gcloud auth configure-docker, auto-creates AR repository
named after SERVICE_NAMESPACE (e.g. knoe-system) if missing, then
docker tag + push; falls back to gcr.io if region unavailable
- GCP config loaded from conf/prod/gcp.cfg on every screen entry;
keys normalised to lowercase so project_id lookup is always consistent
## Config / Namespace persistence
- prole_conf.py activate_environment: symlink creation removed; sets
CLUSTER_ENV env-var so all subsequent calls resolve correct env directory
- knoe/ui/screens/__init__.py: startup config load uses entrypoint_path()
instead of hardcoded conf/prole.cfg; seeds SERVICE_NAMESPACE=knoe-system
for managed envs so Common Services never defaults to 'default'
- cfg.py _save_prole_cfg: saves to env-specific path via entrypoint_path()
- etc/prole_cfg.sh: removed all ln -snf symlink creation
Co-authored-by: Junie <junie@jetbrains.com>

View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
AK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.accesskey}' | base64 -d)
SK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.secretkey}' | base64 -d)
echo "==> Checking gitaly pod logs..."
kubectl -n gitea logs gitlab-gitaly-0 --previous --tail=15 2>&1 | grep -v LD_PRELOAD | head -15 || \
kubectl -n gitea logs gitlab-gitaly-0 --tail=15 2>&1 | grep -v LD_PRELOAD | head -15 || true
echo "==> Removing stale installer PID and restarting installer..."
rm -f /Users/chrisfu/dev/prole/install.pid
cd /Users/chrisfu/dev/prole && mkdir -p logs
nohup bash install.sh --silent -c conf/service/prole.cfg > logs/install_run9.log 2>&1 &
disown
echo "Installer run 9 started"
echo "==> Creating minio buckets via Docker Hub minio/mc..."
kubectl -n gitea delete pod minio-init --ignore-not-found 2>/dev/null || true
kubectl -n gitea run minio-init \
--image=minio/mc:latest \
--restart=Never \
--overrides="{\"spec\":{\"nodeName\":\"gandalf.prole.org\",\"tolerations\":[{\"operator\":\"Exists\"}],\"containers\":[{\"name\":\"minio-init\",\"image\":\"minio/mc:latest\",\"command\":[\"sh\",\"-c\",\"mc alias set gl http://gitlab-minio-svc.gitea.svc.cluster.local:9000 ${AK} ${SK} && for b in gitlab-registry-storage gitlab-lfs-storage gitlab-artifacts-storage gitlab-uploads-storage gitlab-packages-storage gitlab-dependency-proxy-storage gitlab-terraform-state gitlab-ci-secure-files; do mc mb --ignore-existing gl/\$b && echo created \$b; done && mc ls gl && echo BUCKETS_DONE\"]}]}}" 2>&1
echo "minio-init pod created. Check with: kubectl -n gitea logs minio-init -f"

View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Creating /synology/d005/gitlab/{minio,gitaly} on gandalf.prole.org..."
kubectl -n gitlab run synology-mkdir \
--image=alpine:latest \
--restart=Never \
--rm --attach \
--overrides='{
"spec":{
"nodeName":"gandalf.prole.org",
"tolerations":[{"operator":"Exists"}],
"volumes":[{"name":"synology","hostPath":{"path":"/synology/d005","type":"Directory"}}],
"containers":[{
"name":"synology-mkdir",
"image":"alpine:latest",
"command":["sh","-c",
"mkdir -p /synology/gitlab/minio /synology/gitlab/gitaly && chmod 777 /synology/gitlab/minio /synology/gitlab/gitaly && ls -la /synology/gitlab/"],
"volumeMounts":[{"name":"synology","mountPath":"/synology"}]
}]
}}' 2>&1
echo "==> Directories created. Waiting 30s for kubelet to retry mount..."
sleep 30
echo "==> Minio pod status:"
kubectl -n gitlab get pod gitlab-minio-5459cf9679-7nv6c

16
tmp/debug_minio.sh Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Waiting for minio restart and capturing startup logs..."
kubectl -n gitlab logs gitlab-minio-65b8ddcd4d-5xlgc -f --tail=30 2>&1 | \
grep -v "LD_PRELOAD" | timeout 30 head -40 || true
echo "==> Export dir contents on gandalf:"
kubectl -n gitlab run minio-inspect \
--image=alpine:latest --restart=Never --rm --attach \
--overrides='{
"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],
"volumes":[{"name":"export","hostPath":{"path":"/synology/d005/gitlab/minio","type":"Directory"}}],
"containers":[{"name":"minio-inspect","image":"alpine:latest",
"command":["sh","-c","ls -laR /export/ 2>&1 | head -30 && du -sh /export/ 2>&1"],
"volumeMounts":[{"name":"export","mountPath":"/export"}]}]}}' 2>&1

19
tmp/debug_registry.sh Normal file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
REG=$(kubectl -n gitea get pod -l app=registry --no-headers -o name | head -1)
echo "==> Registry pod: $REG"
echo "==> Registry previous crash log (full):"
kubectl -n gitea logs "$REG" --previous 2>&1 | grep -v LD_PRELOAD || true
echo "==> Minio bucket list (verify):"
kubectl -n gitea logs minio-init 2>&1 | grep -E "^\[|BUCKET|created|DONE" | head -15
echo "==> Registry secret bucket config:"
kubectl -n gitea get secret gitlab-registry-storage \
-o jsonpath='{.data.config}' 2>/dev/null | base64 -d | head -20 || \
kubectl -n gitea get configmap -l app=registry --no-headers 2>/dev/null | head -5 || true
echo "==> Migrations pod completion status:"
kubectl -n gitea get pods --no-headers | grep migrations

20
tmp/debug_registry_v2.sh Normal file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Registry storage secret (raw):"
kubectl -n gitea get secret gitlab-registry-storage -o jsonpath='{.data}' 2>&1
echo ""
echo "==> Registry storage secret keys:"
kubectl -n gitea get secret gitlab-registry-storage -o jsonpath='{.data.config}' 2>/dev/null \
| base64 -d 2>/dev/null || true
kubectl -n gitea get secret gitlab-registry-storage -o jsonpath='{.data.s3cmd\.config}' 2>/dev/null \
| base64 -d 2>/dev/null || true
echo "==> All secrets with registry in name:"
kubectl -n gitea get secret --no-headers | grep -i registry | head -10
echo "==> Minio export dir on gandalf:"
kubectl -n gitea run minio-ls \
--image=alpine:latest --restart=Never --rm --attach \
--overrides='{"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],"volumes":[{"name":"e","hostPath":{"path":"/synology/d005/gitlab/minio","type":"Directory"}}],"containers":[{"name":"c","image":"alpine:latest","command":["sh","-c","ls -la /export/"],"volumeMounts":[{"name":"e","mountPath":"/export"}]}]}}' 2>&1 || true

27
tmp/debug_registry_v3.sh Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Registry ConfigMaps:"
kubectl -n gitea get cm --no-headers | grep -i registry
echo "==> Registry configure ConfigMap content (bucket-related lines):"
kubectl -n gitea get cm gitlab-registry -o jsonpath='{.data.configure}' 2>/dev/null \
| grep -iE "bucket|s3|endpoint|access" | head -20 || true
kubectl -n gitea get cm -l app=registry \
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{.data}{"\n"}{end}' 2>/dev/null \
| grep -iE "bucket|s3|endpoint" | head -20 || true
echo "==> registry-storage secret:"
kubectl -n gitea get secret gitlab-registry-secret \
-o jsonpath='{.data}' 2>/dev/null && echo
echo "==> Minio pod node placement:"
kubectl -n gitea get pod -l app=minio \
-o custom-columns='POD:.metadata.name,NODE:.spec.nodeName,STATUS:.status.phase'
echo "==> Try reading config.yml via debug container on minio node:"
kubectl -n gitea run reg-debug \
--image=registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v4.38.0-gitlab \
--restart=Never --rm --attach \
--overrides='{"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],"containers":[{"name":"reg-debug","image":"alpine:latest","command":["sh","-c","echo done"]}]}}' \
2>&1 | head -5 || true

View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
POD="gitlab-webservice-default-675ccb7b99-gxgs8"
echo "==> Configure init logs (look for host rendering):"
kubectl -n gitea logs "$POD" -c configure 2>&1 \
| grep -iE "host|gitlab_host|url|allowed" | head -15 || true
echo "==> Full CR global values (python parse):"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.spec.chart.values.global}' 2>&1 \
| python3 -c "import sys,json; v=json.load(sys.stdin); print(json.dumps(v,indent=2))" \
| grep -A8 '"hosts"'
echo "==> Exec into running webservice — check generated gitlab.yml host line:"
kubectl -n gitea exec "$POD" -c webservice -- \
grep -E "host:|url:|allowed_host" /srv/gitlab/config/gitlab.yml 2>&1 | head -10 || true

39
tmp/do_commit.sh Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -e
cd /Users/chrisfu/dev/prole
git add \
conf/cnpg-placement/ecosystem-0-knoe-db.json \
conf/cnpg-placement/knoe-system-knoe-db.json \
conf/dev/prole.cfg \
conf/port-mapping.cfg \
conf/prod/prole.cfg \
deploy/gcp/gke/knoe-db-backup-gcs.yaml \
deploy/gcp/gke/knoe-db.yaml \
deploy/gcp/gke/namespace.yaml \
deploy/gcp/gke/workload-identity.yaml \
knoe/core/ops/cloudnative_pg.py \
modes/k3d/knoe-db/.version \
modes/k8s/knoe-db/.version \
scan/network_description.txt \
tests/installer/test_cnpg_barman_webhook.py
git commit \
--trailer "Co-authored-by: Junie <junie@jetbrains.com>" \
-m "fix(cnpg): stabilize CNPG/Barman Cloud init on GKE (knoe-dev-0 / knoe-db-0)
- cloudnative_pg.py: add _wait_for_webhook_ca_bundle() to poll ValidatingWebhookConfiguration
until cainjector has injected the CA bundle; fall back to _try_inject_ca_bundle_manually()
on timeout (reads cert-manager-webhook-ca secret, patches webhook directly)
- cloudnative_pg.py: add _wait_for_barman_tls_secrets() to wait for barman-cloud-{client,server}-tls
before declaring Barman Cloud ready; surfaces warning instead of silent FailedMount
- deploy/gcp/gke/namespace.yaml: ecosystem-0 -> knoe-db-0 (ekosystem = k8s cluster, not namespace)
- deploy/gcp/gke/knoe-db.yaml: fix namespace ecosystem-0 -> knoe-db-0; set
podAntiAffinityType: required (one CNPG pod per node); add Spot node toleration so
GKE autoscaler simulation succeeds and scale-up is unblocked; add resource
requests/limits (500m/512Mi -> 2/2Gi); set googleCredentials.gkeEnvironment: true
(use Workload Identity - no explicit credentials secret needed)
- deploy/gcp/gke/knoe-db-backup-gcs.yaml: fix namespaces ecosystem-0 -> knoe-db-0
- deploy/gcp/gke/workload-identity.yaml: update comments ecosystem-0 -> knoe-db-0
- tests/installer/test_cnpg_barman_webhook.py: new - 13 tests covering webhook CA bundle
polling, manual CA injection, Barman TLS secret wait, and install_barman_plugin retry logic"

20
tmp/final_status.sh Normal file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> All GitLab pods:"
kubectl -n gitea get pods --no-headers \
| grep -v jemalloc-builder | grep -v Completed | sort
echo "==> Webservice logs (last 5 lines):"
kubectl -n gitea logs -l app=webservice -c webservice \
--tail=5 2>&1 | grep -v LD_PRELOAD | head -8 || true
echo "==> Sidekiq pod:"
kubectl -n gitea get pod -l app=sidekiq --no-headers 2>&1
echo "==> GitLab CR phase:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' 2>&1 && echo
echo "==> Node memory (gandalf):"
kubectl describe node gandalf.prole.org 2>&1 \
| grep -A3 "Allocated resources" | tail -4

27
tmp/fix_allowed_hosts.sh Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching CR: global.allowedHosts as flat string list..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"global":{
"allowedHosts":["git.prole.org","prole.org"]
}
}}}}'
echo "==> Also updating init_gitlab.sh with the fix..."
echo "==> Deleting crashing pods to force reconcile with new values..."
kubectl -n gitea delete pod -l app=webservice --ignore-not-found
kubectl -n gitea delete pod -l app=sidekiq --ignore-not-found
kubectl -n gitea delete pod gitlab-webservice-default-675ccb7b99-gzmzz --ignore-not-found 2>/dev/null || true
echo "==> Waiting 5min for pods to restart and Puma to boot..."
sleep 300
echo "==> Pod status:"
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | grep -v Completed | sort
echo "==> GitLab CR phase:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' && echo

View File

@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Clearing gitaly PV claimRef so Kubernetes can re-bind to gitea PVC..."
kubectl patch pv gitlab-gitaly-synology --type=json \
-p '[{"op":"remove","path":"/spec/claimRef"}]' 2>/dev/null || \
kubectl patch pv gitlab-gitaly-synology --type=merge \
-p '{"spec":{"claimRef":null}}'
echo "==> Waiting 20s for gitaly PVC to bind..."
sleep 20
kubectl -n gitea get pvc repo-data-gitlab-gitaly-0
echo "==> Getting minio credentials..."
AK=$(kubectl -n gitea get secret gitlab-minio-secret \
-o jsonpath='{.data.accesskey}' | base64 -d)
SK=$(kubectl -n gitea get secret gitlab-minio-secret \
-o jsonpath='{.data.secretkey}' | base64 -d)
MINIO_SVC=$(kubectl -n gitea get svc gitlab-minio-svc \
-o jsonpath='{.spec.clusterIP}' 2>/dev/null || echo "gitlab-minio-svc")
echo "==> Creating minio buckets via mc (in-cluster pod on gandalf)..."
kubectl -n gitea run minio-buckets \
--image=quay.io/minio/mc:RELEASE.2022-10-20T23-30-35Z \
--restart=Never --rm --attach \
--overrides="{
\"spec\":{
\"nodeName\":\"gandalf.prole.org\",
\"tolerations\":[{\"operator\":\"Exists\"}],
\"containers\":[{
\"name\":\"minio-buckets\",
\"image\":\"quay.io/minio/mc:RELEASE.2022-10-20T23-30-35Z\",
\"command\":[\"sh\",\"-c\",
\"mc alias set gl http://gitlab-minio-svc.gitea.svc.cluster.local:9000 ${AK} ${SK} && \
mc mb --ignore-existing gl/gitlab-registry-storage && \
mc mb --ignore-existing gl/gitlab-lfs-storage && \
mc mb --ignore-existing gl/gitlab-artifacts-storage && \
mc mb --ignore-existing gl/gitlab-uploads-storage && \
mc mb --ignore-existing gl/gitlab-packages-storage && \
mc mb --ignore-existing gl/gitlab-dependency-proxy-storage && \
mc mb --ignore-existing gl/gitlab-terraform-state && \
mc mb --ignore-existing gl/gitlab-ci-secure-files && \
mc ls gl && echo BUCKETS_DONE\"]}]}}" 2>&1
echo "==> Waiting 30s then checking all pod status..."
sleep 30
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | sort

View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> PV claimRef detail (namespace check):"
kubectl get pv gitlab-gitaly-synology \
-o jsonpath='{.spec.claimRef}' 2>&1 && echo
echo "==> Releasing PV claimRef and rebinding to gitea namespace..."
kubectl patch pv gitlab-gitaly-synology --type=merge \
-p '{"spec":{"claimRef":{"namespace":"gitea","name":"repo-data-gitlab-gitaly-0"}}}'
echo "==> Waiting 20s for PVC to bind..."
sleep 20
kubectl -n gitea get pvc repo-data-gitlab-gitaly-0
echo "==> Patching CR to add jemalloc volumes to gitlab-exporter..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"gitlab":{
"gitlab-exporter":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
}
}
}}}}'
echo "==> Restarting exporter pod..."
kubectl -n gitea delete pod -l app=gitlab-exporter --ignore-not-found
echo "==> Checking minio-create-buckets job..."
kubectl -n gitea get jobs -l app=minio-create-buckets 2>&1 || true
echo "==> Done. Watching gitaly pod (30s)..."
sleep 30
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder

39
tmp/fix_gitaly_v2.sh Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> PV status:"
kubectl get pv gitlab-gitaly-synology \
-o custom-columns='NAME:.metadata.name,STATUS:.status.phase,CLAIM:.spec.claimRef.name,NS:.spec.claimRef.namespace,SC:.spec.storageClassName'
echo "==> PVC describe (binding error):"
kubectl -n gitea describe pvc repo-data-gitlab-gitaly-0 2>&1 | tail -15
echo "==> If PV is Released, patch status to Available..."
PHASE=$(kubectl get pv gitlab-gitaly-synology -o jsonpath='{.status.phase}')
echo "PV phase: $PHASE"
if [[ "$PHASE" == "Released" ]]; then
echo "Patching PV to Available via status subresource..."
kubectl patch pv gitlab-gitaly-synology --type=json \
-p '[{"op":"remove","path":"/spec/claimRef"}]' 2>/dev/null || true
fi
echo "==> Creating minio buckets directly via minio pod exec..."
AK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.accesskey}' | base64 -d)
SK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.secretkey}' | base64 -d)
MINIO_POD=$(kubectl -n gitea get pod -l app=minio --no-headers -o name | head -1)
echo "Using minio pod: $MINIO_POD"
kubectl -n gitea exec "$MINIO_POD" -- sh -c "
export MC_HOST_gl=http://${AK}:${SK}@localhost:9000
for bucket in gitlab-registry-storage gitlab-lfs-storage gitlab-artifacts-storage \
gitlab-uploads-storage gitlab-packages-storage gitlab-dependency-proxy-storage \
gitlab-terraform-state gitlab-ci-secure-files; do
mc mb --ignore-existing gl/\$bucket && echo \"Created: \$bucket\" || true
done
mc ls gl
" 2>&1
echo "==> Waiting 30s then final pod status:"
sleep 30
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | sort

26
tmp/fix_gitlab_sa.sh Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
export KUBECONFIG
echo "==> Creating gitlab-app-nonroot ServiceAccount..."
kubectl -n gitlab apply -f - <<'SAYAML'
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab-app-nonroot
namespace: gitlab
SAYAML
echo "==> Patching GitLab CR to set serviceAccount.create=false..."
kubectl -n gitlab patch gitlab gitlab --type=merge \
-p '{"spec":{"chart":{"values":{"global":{"serviceAccount":{"create":false}}}}}}'
echo "==> Waiting 15s for operator to reconcile..."
sleep 15
echo "==> GitLab CR status:"
kubectl -n gitlab get gitlab gitlab
echo "==> Operator last 20 log lines:"
kubectl logs -n gitlab deployment/gitlab-controller-manager --tail=20

41
tmp/fix_hpa_and_spread.sh Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching HPAs to minReplicas=1..."
for hpa in gitlab-webservice-default gitlab-gitlab-shell gitlab-kas gitlab-registry; do
kubectl -n gitea patch hpa "$hpa" --type=merge \
-p '{"spec":{"minReplicas":1,"maxReplicas":2}}' 2>/dev/null || true
echo " patched: $hpa"
done
echo "==> Patching global.nodeSelector to null (let pods spread)..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{"global":{"nodeSelector":null}}}}}'
echo "==> Patching CR webservice/sidekiq nodeSelector to null..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{"gitlab":{
"webservice":{"nodeSelector":null},
"sidekiq":{"nodeSelector":null},
"toolbox":{"nodeSelector":null},
"migrations":{"nodeSelector":null},
"gitlab-exporter":{"nodeSelector":null}
},"registry":{"nodeSelector":null}}}}}'
echo "==> Force-deleting stuck Terminating pods..."
for pod in $(kubectl -n gitea get pods --no-headers \
| grep -E "Terminating|Pending" | awk '{print $1}'); do
kubectl -n gitea delete pod "$pod" --force --grace-period=0 --ignore-not-found 2>/dev/null || true
done
echo "==> Waiting 5min for pods to reschedule across cluster..."
sleep 300
echo "==> Pod status with node placement:"
kubectl -n gitea get pods --no-headers \
-o wide | grep -v jemalloc | grep -v Completed \
| awk '{printf "%-52s %-8s %-15s %s\n",$1,$4,$6,$7}' | sort
echo "==> CR phase:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' && echo

46
tmp/fix_liveness.sh Normal file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching CR: increase liveness probe delays for slow RPi boot..." && \
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"gitlab":{
"webservice":{
"livenessProbe":{
"initialDelaySeconds":3600,
"periodSeconds":60,
"timeoutSeconds":30,
"failureThreshold":5
},
"readinessProbe":{
"initialDelaySeconds":120,
"periodSeconds":30,
"timeoutSeconds":30,
"failureThreshold":60
}
},
"sidekiq":{
"livenessProbe":{
"initialDelaySeconds":3600,
"periodSeconds":60,
"timeoutSeconds":30,
"failureThreshold":5
},
"readinessProbe":{
"initialDelaySeconds":120,
"periodSeconds":30,
"timeoutSeconds":30,
"failureThreshold":60
}
}
}
}}}}'
echo "==> Force-deleting all crashing webservice/sidekiq pods..." && \
for pod in $(kubectl -n gitea get pods --no-headers | grep -E "webservice|sidekiq" | awk '{print $1}'); do
kubectl -n gitea delete pod "$pod" --force --grace-period=0 --ignore-not-found 2>/dev/null || true
done
echo "==> Done — operator will reconcile new pods with long liveness grace period." && \
echo " Monitor with: kubectl -n gitea get pods -w | grep -E 'webservice|sidekiq'"

43
tmp/fix_memory.sh Normal file
View File

@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching CR: reduce memory requests and enforce replicaCount=1..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"gitlab":{
"webservice":{
"replicaCount":1,
"minReplicas":1,
"maxReplicas":1,
"resources":{
"requests":{"cpu":"200m","memory":"1500M"},
"limits":{"memory":"2000M"}
}
},
"sidekiq":{
"resources":{
"requests":{"cpu":"100m","memory":"800M"},
"limits":{"memory":"1200M"}
}
}
}
}}}}'
echo "==> Force-deleting all stuck Terminating/Pending webservice pods..."
for pod in $(kubectl -n gitea get pods --no-headers \
| grep -E "webservice|sidekiq|minio-create" \
| awk '{print $1}'); do
kubectl -n gitea delete pod "$pod" --force --grace-period=0 \
--ignore-not-found 2>/dev/null || true
done
echo "==> Waiting 4min for operator to reconcile with new memory limits..."
sleep 240
echo "==> Pod status:"
kubectl -n gitea get pods --no-headers \
| grep -v jemalloc-builder | grep -v Completed | sort
echo "==> CR phase:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' && echo

35
tmp/fix_minio_creds.sh Normal file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
AK=$(kubectl -n gitlab get secret gitlab-minio-secret \
-o jsonpath='{.data.accesskey}' | base64 -d)
SK=$(kubectl -n gitlab get secret gitlab-minio-secret \
-o jsonpath='{.data.secretkey}' | base64 -d)
echo "==> Patching CR with MINIO_ROOT_USER/MINIO_ROOT_PASSWORD from gitlab-minio-secret..."
kubectl -n gitlab patch gitlab gitlab --type=merge -p "{
\"spec\":{\"chart\":{\"values\":{
\"minio\":{
\"extraEnv\":{
\"MINIO_ROOT_USER\":\"${AK}\",
\"MINIO_ROOT_PASSWORD\":\"${SK}\"
}
}
}}}}"
echo "==> Restarting minio pod to pick up new env vars..."
kubectl -n gitlab delete pod -l app=minio,component=app --ignore-not-found
kubectl -n gitlab delete pod gitlab-minio-65b8ddcd4d-htdhh --ignore-not-found 2>/dev/null || true
kubectl -n gitlab delete job -l app=minio-create-buckets --ignore-not-found
echo "==> Waiting 90s..."
sleep 90
echo "==> Pod status:"
kubectl -n gitlab get pods --sort-by=.metadata.creationTimestamp | grep -v jemalloc-builder
echo "==> Minio logs:"
kubectl -n gitlab logs -l app=minio --tail=5 2>&1 || true
echo "==> create-buckets logs:"
kubectl -n gitlab logs -l app=minio-create-buckets --tail=5 2>&1 || true

View File

@ -0,0 +1,44 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> minio-create-buckets actual image:"
kubectl -n gitea get pod -l "app=minio-create-buckets" \
-o jsonpath='{.items[0].spec.containers[0].image}' 2>&1 && echo
echo "==> minio-create-buckets crash log:"
kubectl -n gitea logs -l "app=minio-create-buckets" --tail=5 2>&1 \
| grep -v LD_PRELOAD | head -8 || true
echo "==> Patching CR: set minio mcImage to docker.io minio/mc ARM64..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"minio":{
"mcImage":{
"repository":"minio/mc",
"tag":"RELEASE.2022-10-20T23-30-35Z"
}
}
}}}}'
echo "==> Deleting crash job so operator recreates with new image..."
kubectl -n gitea delete jobs -l "app=minio-create-buckets" --ignore-not-found
echo "==> Waiting 8min for Puma boot + Sidekiq ready + registry ready..."
sleep 480
echo "==> Final status:"
kubectl -n gitea get pods --no-headers \
-o wide | grep -v jemalloc | grep -v Completed \
| awk '{printf "%-52s %-5s %-8s %s\n",$1,$2,$4,$7}' | sort
echo "==> GitLab CR phase + condition:"
kubectl -n gitea get gitlab gitlab \
-o jsonpath='{.status.phase}{"\n"}{.status.conditions[*].message}' 2>&1 && echo
echo "==> Sidekiq readiness:"
kubectl -n gitea get pod -l app=sidekiq \
-o jsonpath='{.items[0].status.containerStatuses[0].ready}' 2>&1 && echo
echo "==> Webservice readiness:"
kubectl -n gitea get pod -l app=webservice \
-o jsonpath='{range .items[*]}{.metadata.name}: {.status.containerStatuses[*].ready}{"\n"}{end}' 2>&1

35
tmp/fix_minio_pv.sh Normal file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
kubectl patch pv gitlab-minio-synology \
-p '{"metadata":{"finalizers":[]}}' --type=merge 2>/dev/null || true
kubectl delete pv gitlab-minio-synology --ignore-not-found
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-minio-synology
spec:
capacity:
storage: 10Gi
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
volumeMode: Filesystem
local:
path: /synology/d005/gitlab/minio
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
EOF
sleep 15
echo "==> PV status:" && kubectl get pv gitlab-minio-synology \
-o custom-columns='NAME:.metadata.name,STATUS:.status.phase,CLAIM:.spec.claimRef.name'
echo "==> PVC status:" && kubectl -n gitlab get pvc gitlab-minio

43
tmp/fix_minio_v2.sh Normal file
View File

@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Previous minio crash log:"
kubectl -n gitlab logs gitlab-minio-65b8ddcd4d-5xlgc --previous 2>&1 | \
grep -v "LD_PRELOAD" | head -30 || true
echo "==> Switching to 2022 quay.io minio (supports MINIO_ACCESS_KEY + ARM64)..."
# Also remove the MINIO_ROOT_USER/PASSWORD extraEnv — the 2022 image reads MINIO_ACCESS_KEY
kubectl -n gitlab patch gitlab gitlab --type=json -p '[
{"op":"remove","path":"/spec/chart/values/minio/extraEnv"}
]' 2>/dev/null || true
kubectl -n gitlab patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"minio":{
"image":"quay.io/minio/minio",
"imageTag":"RELEASE.2022-10-08T20-11-00Z"
}
}}}}'
echo "==> Wiping stale minio export data and restarting pod..."
kubectl -n gitlab run minio-wipe \
--image=alpine:latest --restart=Never --rm \
--overrides='{
"spec":{"nodeName":"gandalf.prole.org","tolerations":[{"operator":"Exists"}],
"volumes":[{"name":"e","hostPath":{"path":"/synology/d005/gitlab/minio","type":"Directory"}}],
"containers":[{"name":"minio-wipe","image":"alpine:latest",
"command":["sh","-c","rm -rf /e/.minio.sys /e/registry && echo wiped"],
"volumeMounts":[{"name":"e","mountPath":"/e"}]}]}}' 2>&1 || true
kubectl -n gitlab delete pod -l app=minio --ignore-not-found
kubectl -n gitlab delete jobs -l app=minio-create-buckets --ignore-not-found
echo "==> Waiting 90s..."
sleep 90
echo "==> Pod status:"
kubectl -n gitlab get pods --sort-by=.metadata.creationTimestamp | grep -v jemalloc-builder
echo "==> Minio logs:"
kubectl -n gitlab logs -l app=minio --tail=10 2>&1 | grep -v "LD_PRELOAD" || true

40
tmp/fix_node_spread.sh Normal file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Removing global.nodeSelector so pods spread across cluster..."
kubectl -n gitea patch gitlab gitlab --type=json -p '[
{"op":"remove","path":"/spec/chart/values/global/nodeSelector"}
]' 2>/dev/null || true
echo "==> Removing per-component nodeSelectors except gitaly + minio..."
kubectl -n gitea patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"gitlab":{
"webservice":{"nodeSelector":null},
"sidekiq":{"nodeSelector":null},
"toolbox":{"nodeSelector":null},
"migrations":{"nodeSelector":null},
"gitlab-exporter":{"nodeSelector":null}
},
"registry":{"nodeSelector":null}
}}}}'
echo "==> Force-deleting all stuck Terminating/Pending webservice+sidekiq pods..."
for pod in $(kubectl -n gitea get pods --no-headers \
| grep -E "webservice|sidekiq|minio-create" \
| awk '{print $1}'); do
kubectl -n gitea delete pod "$pod" --force --grace-period=0 \
--ignore-not-found 2>/dev/null || true
done
echo "==> Waiting 4min for operator to reconcile and pods to spread..."
sleep 240
echo "==> Final pod status (with node placement):"
kubectl -n gitea get pods --no-headers \
| grep -v jemalloc-builder | grep -v Completed \
| awk '{print $1, $2, $3, $4}' | sort
echo "==> GitLab CR phase:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' && echo

View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting old gitaly PV (still bound to deleted gitlab ns)..."
kubectl delete pv gitlab-gitaly-synology --ignore-not-found
echo "==> Recreating gitaly PV bound to gitea namespace..."
kubectl apply -f - <<'PVYAML'
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-gitaly-synology
spec:
capacity:
storage: 50Gi
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
volumeMode: Filesystem
local:
path: /synology/d005/gitlab/gitaly
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
PVYAML
echo "==> Waiting 20s for gitaly PVC to bind..."
sleep 20
kubectl -n gitea get pvc repo-data-gitlab-gitaly-0
echo "==> Creating minio buckets via dedicated mc pod..."
AK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.accesskey}' | base64 -d)
SK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.secretkey}' | base64 -d)
kubectl -n gitea delete pod minio-init --ignore-not-found 2>/dev/null || true
kubectl -n gitea run minio-init \
--image=quay.io/minio/mc:RELEASE.2022-10-20T23-30-35Z \
--restart=Never \
--overrides="{
\"spec\":{\"nodeName\":\"gandalf.prole.org\",\"tolerations\":[{\"operator\":\"Exists\"}],
\"containers\":[{\"name\":\"minio-init\",
\"image\":\"quay.io/minio/mc:RELEASE.2022-10-20T23-30-35Z\",
\"command\":[\"sh\",\"-c\",
\"mc alias set gl http://gitlab-minio-svc.gitea.svc.cluster.local:9000 ${AK} ${SK} && mc mb --ignore-existing gl/gitlab-registry-storage && mc mb --ignore-existing gl/gitlab-lfs-storage && mc mb --ignore-existing gl/gitlab-artifacts-storage && mc mb --ignore-existing gl/gitlab-uploads-storage && mc mb --ignore-existing gl/gitlab-packages-storage && mc mb --ignore-existing gl/gitlab-dependency-proxy-storage && mc mb --ignore-existing gl/gitlab-terraform-state && mc mb --ignore-existing gl/gitlab-ci-secure-files && mc ls gl && echo BUCKETS_DONE\"]}]}}"
echo "==> Waiting up to 3min for minio-init job to complete..."
kubectl -n gitea wait pod/minio-init --for=condition=Ready --timeout=120s 2>/dev/null || true
kubectl -n gitea wait pod/minio-init --for=jsonpath='{.status.phase}'=Succeeded --timeout=60s 2>/dev/null || true
kubectl -n gitea logs minio-init 2>&1 | tail -15
kubectl -n gitea delete pod minio-init --ignore-not-found 2>/dev/null || true
echo "==> Restarting registry pod to pick up new buckets..."
kubectl -n gitea delete pod -l app=registry --ignore-not-found
echo "==> Final pod status (60s wait):"
sleep 60
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | sort

53
tmp/fix_pv_finalizer.sh Normal file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Removing pv-protection finalizer from gitaly PV..."
kubectl patch pv gitlab-gitaly-synology \
-p '{"metadata":{"finalizers":[]}}' --type=merge 2>/dev/null || true
echo "==> Waiting 10s for PV deletion..."
sleep 10
kubectl get pv gitlab-gitaly-synology 2>&1 || echo "PV gone OK"
echo "==> Recreating PV (clean, no claimRef)..."
kubectl apply -f - <<'PVYAML'
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-gitaly-synology
spec:
capacity:
storage: 50Gi
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
volumeMode: Filesystem
local:
path: /synology/d005/gitlab/gitaly
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
PVYAML
echo "==> Waiting 20s for PVC to bind..."
sleep 20
echo "==> PV phase:" && kubectl get pv gitlab-gitaly-synology \
-o jsonpath='{.status.phase}' && echo
echo "==> PVC status:"
kubectl -n gitea get pvc repo-data-gitlab-gitaly-0
echo "==> Starting minio-init bucket creation (background)..."
AK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.accesskey}' | base64 -d)
SK=$(kubectl -n gitea get secret gitlab-minio-secret -o jsonpath='{.data.secretkey}' | base64 -d)
kubectl -n gitea delete pod minio-init --ignore-not-found 2>/dev/null || true
kubectl -n gitea run minio-init \
--image=quay.io/minio/mc:RELEASE.2022-10-20T23-30-35Z \
--restart=Never \
--overrides="{\"spec\":{\"nodeName\":\"gandalf.prole.org\",\"tolerations\":[{\"operator\":\"Exists\"}],\"containers\":[{\"name\":\"minio-init\",\"image\":\"quay.io/minio/mc:RELEASE.2022-10-20T23-30-35Z\",\"command\":[\"sh\",\"-c\",\"mc alias set gl http://gitlab-minio-svc.gitea.svc.cluster.local:9000 ${AK} ${SK} && for b in gitlab-registry-storage gitlab-lfs-storage gitlab-artifacts-storage gitlab-uploads-storage gitlab-packages-storage gitlab-dependency-proxy-storage gitlab-terraform-state gitlab-ci-secure-files; do mc mb --ignore-existing gl/\$b; done && mc ls gl && echo BUCKETS_DONE\"]}]}}" 2>&1
echo "==> minio-init pod created — check logs in ~2min with:"
echo " kubectl -n gitea logs minio-init"

63
tmp/fix_pvs.sh Normal file
View File

@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
KB="kubectl"
echo "==> Deleting wrong PVs (wrong storageClass)..."
$KB delete pv gitlab-gitaly-synology gitlab-minio-synology --ignore-not-found
GITALY_SIZE=$($KB -n gitlab get pvc repo-data-gitlab-gitaly-0 -o jsonpath='{.spec.resources.requests.storage}' 2>/dev/null || echo "50Gi")
MINIO_SIZE=$($KB -n gitlab get pvc gitlab-minio -o jsonpath='{.spec.resources.requests.storage}' 2>/dev/null || echo "10Gi")
echo "==> PVC sizes: gitaly=$GITALY_SIZE minio=$MINIO_SIZE"
echo "==> Creating PVs with empty storageClassName to match <unset> PVCs..."
$KB apply -f - <<PVYAML
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-gitaly-synology
spec:
capacity:
storage: ${GITALY_SIZE}
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
local:
path: /synology/d005/gitlab/gitaly
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-minio-synology
spec:
capacity:
storage: ${MINIO_SIZE}
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
local:
path: /synology/d005/gitlab/minio
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
PVYAML
echo "==> Waiting 15s for binding..."
sleep 15
echo "==> PVC status:"
$KB -n gitlab get pvc
echo "==> PV status:"
$KB get pv gitlab-gitaly-synology gitlab-minio-synology

25
tmp/fix_registry_cr.sh Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching CR: registry liveness probe + ARM64 configure fix..."
kubectl -n gitlab patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"registry":{
"livenessProbe":{"initialDelaySeconds":300,"periodSeconds":60,"timeoutSeconds":30,"failureThreshold":10},
"readinessProbe":{"initialDelaySeconds":30,"periodSeconds":30,"timeoutSeconds":30,"failureThreshold":20}
}
}}}}'
echo "==> Waiting 60s for operator to reconcile..."
sleep 60
echo "==> Patching registry Deployment configure init container to ARM64 alpine..."
kubectl -n gitlab patch deployment gitlab-registry --type=json -p '[
{"op":"replace","path":"/spec/template/spec/initContainers/1/image","value":"alpine:latest"},
{"op":"replace","path":"/spec/template/spec/initContainers/1/command","value":["/bin/sh","/templates/configure"]}
]' 2>/dev/null || echo "Deployment not found yet — will retry"
echo "==> Registry pod status (30s wait):"
sleep 30
kubectl -n gitlab get pod -l app=registry --no-headers 2>&1

76
tmp/fix_storage.sh Normal file
View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
set -euo pipefail
KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
export KUBECONFIG
KB="kubectl"
echo "==> Uninstalling stuck Redis release..."
helm -n knoe-system uninstall redis 2>/dev/null || true
$KB -n knoe-system delete pvc redis-data-redis-master-0 --ignore-not-found
echo "==> Redeploying Redis without persistence..."
cd /Users/chrisfu/dev/prole
bash etc/init_redis.sh -c conf/service/prole.cfg start
echo "==> Redis deployed. Checking gitaly/minio PVC sizes..."
$KB -n gitlab get pvc repo-data-gitlab-gitaly-0 gitlab-minio -o custom-columns='NAME:.metadata.name,SIZE:.spec.resources.requests.storage,SC:.spec.storageClassName' 2>&1 || true
echo "==> Preparing synology dirs for gitaly and minio on gandalf..."
$KB -n knoe-system run gitlab-dirprep --image=alpine --restart=Never \
--overrides='{"spec":{"nodeName":"gandalf.prole.org"}}' \
--command -- sh -c "mkdir -p /synology/d005/gitlab/gitaly /synology/d005/gitlab/minio && chmod 777 /synology/d005/gitlab/gitaly /synology/d005/gitlab/minio && echo done" \
--attach --rm 2>&1 || true
echo "==> Creating static PVs for gitaly and minio..."
GITALY_SIZE=$($KB -n gitlab get pvc repo-data-gitlab-gitaly-0 -o jsonpath='{.spec.resources.requests.storage}' 2>/dev/null || echo "50Gi")
MINIO_SIZE=$($KB -n gitlab get pvc gitlab-minio -o jsonpath='{.spec.resources.requests.storage}' 2>/dev/null || echo "10Gi")
echo "Gitaly PVC size: $GITALY_SIZE | Minio PVC size: $MINIO_SIZE"
$KB apply -f - <<PVYAML
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-gitaly-synology
spec:
capacity:
storage: ${GITALY_SIZE}
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: synology-iscsi
local:
path: /synology/d005/gitlab/gitaly
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: gitlab-minio-synology
spec:
capacity:
storage: ${MINIO_SIZE}
accessModes: [ReadWriteOnce]
persistentVolumeReclaimPolicy: Retain
storageClassName: synology-iscsi
local:
path: /synology/d005/gitlab/minio
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [gandalf.prole.org]
PVYAML
echo "==> Deleting stuck PVCs so they rebind to new PVs..."
$KB -n gitlab delete pvc repo-data-gitlab-gitaly-0 gitlab-minio --ignore-not-found
echo "==> Done. Waiting 20s for PVCs to rebind..."
sleep 20
$KB -n gitlab get pvc,pods 2>&1

24
tmp/force_delete_ns.sh Normal file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Resources blocking termination:"
kubectl -n gitlab get all --ignore-not-found 2>&1 | head -20 || true
echo "==> Force-removing finalizers from stuck GitLab CRs..."
for res in $(kubectl -n gitlab get gitlabs.apps.gitlab.com --no-headers -o name 2>/dev/null || true); do
kubectl -n gitlab patch "$res" -p '{"metadata":{"finalizers":[]}}' --type=merge 2>/dev/null || true
done
echo "==> Forcing namespace finalizer removal via API..."
kubectl get namespace gitlab -o json 2>/dev/null | \
python3 -c "
import sys, json
d = json.load(sys.stdin)
d['spec']['finalizers'] = []
print(json.dumps(d))
" | kubectl replace --raw /api/v1/namespaces/gitlab/finalize -f - 2>&1 || true
sleep 10
echo "==> Namespace status:"
kubectl get ns gitlab 2>&1 || echo "Namespace gone — clean."

18
tmp/get_crash_log.sh Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> kgqhl previous crash log (webservice container):" && \
kubectl -n gitea logs gitlab-webservice-default-675ccb7b99-kgqhl \
-c webservice --previous --tail=25 2>&1 | grep -v LD_PRELOAD | head -25
echo "==> New pod 4pvtw puma log:" && \
kubectl -n gitea logs gitlab-webservice-default-675ccb7b99-4pvtw \
-c webservice --tail=5 2>&1 | grep -v LD_PRELOAD | head -6
echo "==> Sidekiq crash count + last state:" && \
kubectl -n gitea get pod gitlab-sidekiq-all-in-1-v2-679848bc8-wvxln \
-o jsonpath='{.status.containerStatuses[0].restartCount} restarts, last exit: {.status.containerStatuses[0].lastState.terminated.reason}{"\n"}' 2>&1
echo "==> Sidekiq previous log:" && \
kubectl -n gitea logs gitlab-sidekiq-all-in-1-v2-679848bc8-wvxln \
--previous --tail=15 2>&1 | grep -v LD_PRELOAD | tail -15

26
tmp/get_gitaly_logs.sh Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Waiting for gitaly to enter Running state..."
for i in $(seq 1 20); do
phase=$(kubectl -n gitlab get pod gitlab-gitaly-0 \
-o jsonpath='{.status.containerStatuses[0].state}' 2>/dev/null || true)
status=$(kubectl -n gitlab get pod gitlab-gitaly-0 \
--no-headers 2>/dev/null | awk '{print $3}')
echo "[$i] status=$status"
if [[ "$status" == "Running" ]]; then
echo "==> Running! Grabbing logs..."
kubectl -n gitlab logs gitlab-gitaly-0 --tail=30 2>&1 | \
grep -v "LD_PRELOAD" | head -30
break
fi
sleep 5
done
echo "==> Last terminated state:"
kubectl -n gitlab get pod gitlab-gitaly-0 \
-o jsonpath='{.status.containerStatuses[0].lastState.terminated}' 2>&1
echo "==> Previous logs attempt:"
kubectl -n gitlab logs gitlab-gitaly-0 --previous --tail=20 2>&1 | \
grep -v "LD_PRELOAD" | head -25 || true

34
tmp/inject_minio_creds.sh Normal file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching minio main container with MINIO_ROOT_USER/PASSWORD from secret..."
kubectl -n gitlab patch deployment gitlab-minio --type=json -p '[
{"op":"add","path":"/spec/template/spec/containers/0/env/-",
"value":{"name":"MINIO_ROOT_USER","valueFrom":{"secretKeyRef":{"name":"gitlab-minio-secret","key":"accesskey"}}}},
{"op":"add","path":"/spec/template/spec/containers/0/env/-",
"value":{"name":"MINIO_ROOT_PASSWORD","valueFrom":{"secretKeyRef":{"name":"gitlab-minio-secret","key":"secretkey"}}}}
]'
echo "==> Deleting minio pod to restart with correct env..."
kubectl -n gitlab delete pod -l app=minio --ignore-not-found
echo "==> Waiting 60s for minio to restart..."
sleep 60
echo "==> Init container log:"
kubectl -n gitlab logs -l app=minio -c configure --tail=3 2>&1 || true
echo "==> Minio main log:"
kubectl -n gitlab logs -l app=minio --tail=5 2>&1 | grep -v LD_PRELOAD | head -5 || true
echo "==> Test credentials..."
AK=$(kubectl -n gitlab get secret gitlab-minio-secret -o jsonpath='{.data.accesskey}' | base64 -d | tr -d '\n')
SK=$(kubectl -n gitlab get secret gitlab-minio-secret -o jsonpath='{.data.secretkey}' | base64 -d | tr -d '\n')
kubectl -n gitlab delete pod minio-cred-test --ignore-not-found 2>/dev/null || true
kubectl -n gitlab run minio-cred-test \
--image=minio/mc:latest --restart=Never \
--overrides="{\"spec\":{\"nodeName\":\"gandalf.prole.org\",\"tolerations\":[{\"operator\":\"Exists\"}],\"containers\":[{\"name\":\"t\",\"image\":\"minio/mc:latest\",\"command\":[\"sh\",\"-c\",\"mc alias set gl http://gitlab-minio-svc.gitlab.svc.cluster.local:9000 ${AK} ${SK} && mc ls gl && echo CREDS_OK\"]}]}}"
sleep 40
kubectl -n gitlab logs minio-cred-test 2>&1 | tail -5 || true
kubectl -n gitlab delete pod minio-cred-test --ignore-not-found 2>/dev/null || true

View File

@ -0,0 +1,61 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: jemalloc-builder
namespace: gitlab
labels:
app: jemalloc-builder
spec:
selector:
matchLabels:
app: jemalloc-builder
template:
metadata:
labels:
app: jemalloc-builder
spec:
tolerations:
- operator: Exists
initContainers:
- name: build
image: alpine:latest
command:
- sh
- -c
- |
set -e
TARGET=/hostlib/libjemalloc.so.2
if [ -f "$TARGET" ]; then
echo "Already built at $TARGET — skipping."
exit 0
fi
echo "Installing build tools..."
apk add --no-cache gcc musl-dev make wget autoconf 2>&1
cd /tmp
echo "Downloading jemalloc 5.3.0..."
wget -q -O jemalloc.tar.bz2 \
https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2
tar xf jemalloc.tar.bz2
cd jemalloc-5.3.0
echo "Configuring with --with-lg-page=14 (16KB page support)..."
./configure --with-lg-page=14 --disable-stats --disable-prof --disable-fill 2>&1
echo "Building..."
make -j2 lib/libjemalloc.so.2 2>&1
cp lib/libjemalloc.so.2 "$TARGET"
chmod 755 "$TARGET"
echo "Done: $(ls -lh $TARGET)"
volumeMounts:
- name: hostlib
mountPath: /hostlib
containers:
- name: keepalive
image: alpine:latest
command: [sh, -c, "echo 'jemalloc ready at /opt/gitlab-jemalloc/libjemalloc.so.2'; sleep infinity"]
volumeMounts:
- name: hostlib
mountPath: /hostlib
volumes:
- name: hostlib
hostPath:
path: /opt/gitlab-jemalloc
type: DirectoryOrCreate

25
tmp/junie_commit_msg.txt Normal file
View File

@ -0,0 +1,25 @@
feat: GCP/GKE CNPG hardening, Artifact Registry traffic light, and knoe-system namespace fixes
UI screens
- database.py: fix mode detection to use env_key priority (prod→k8s, service→k3s) so stale DEPLOYMENT_MODE never overrides the user's chosen environment
- database.py: Registry status reads ARTIFACT_REGISTRY_AVAILABLE persisted by cluster screen; uses SERVICE_NAMESPACE for Artifact Registry repo name
- cluster.py: add Artifact Registry traffic light (amber→green/red) to prod section; _check_artifact_registry_async persists ARTIFACT_REGISTRY_AVAILABLE into Global cfg
- cluster.py: re-trigger Artifact Registry check after GKE cluster selection so the light re-evaluates once region is available from KUBECONTEXT
- cluster_nodes.py: fix TclError on Python 3.14 — pady=(2,0) tuple → pady=2 scalar
- __init__.py: seed knoe-system namespace when saved value is "default", not only when empty
- services.py: replace hardcoded "Prole DB" log string with dynamic cnpg_cluster name
Core ops
- cloudnative_pg.py: replace one-shot Barman plugin retry with 6-attempt loop; first cert-manager/x509 failure triggers rollout restart + 30 s CA propagation wait; subsequent failures back off up to 60 s per attempt
- cloudnative_pg.py: TLS CA CN now uses cluster_name instead of hardcoded "Prole CNPG CA"
- registry.py, garage_store.py: refactored into per-mode modules (k3d/k3s/k8s registry and garage store, shared _garage_common)
Deploy / config
- deploy/gcp/gke/knoe-db.yaml: GKE-specific CNPG cluster manifest (rw/ro/r on separate nodes with premium-rwo storage)
- etc/init_common_services.sh, modes/k8s/knoe-db/.version: updated for current deploy
- kong-deployment.yaml: updated manifest
Tests
- test_cluster_nodes_render_smoke.py: add pack/grid, winfo_children, winfo_reqheight, update_idletasks, grid_slaves to dummy widgets; monkeypatch tk.Label so CNPG placement render completes without a real Tkinter root
Co-authored-by: Junie <junie@jetbrains.com>

28
tmp/kill_and_restart.sh Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
cd /Users/chrisfu/dev/prole
echo "==> Killing running installer processes..." && \
pkill -f "install.sh" 2>/dev/null || true && \
pkill -f "init_gitlab.sh" 2>/dev/null || true && \
sleep 3
echo "==> Cleaning misrouted gitea gitlab namespace..." && \
kubectl get namespace gitea -o json 2>/dev/null \
| python3 -c "import sys,json; d=json.load(sys.stdin); d['spec']['finalizers']=[]; print(json.dumps(d))" \
| kubectl replace --raw /api/v1/namespaces/gitea/finalize -f - 2>/dev/null || true && \
kubectl delete namespace gitea --ignore-not-found --timeout=30s 2>/dev/null || true && \
kubectl delete pv gitlab-gitaly-synology gitlab-minio-synology --ignore-not-found 2>/dev/null || true
echo "==> Removing stale PID lock..." && \
rm -f /Users/chrisfu/dev/prole/install.pid
echo "==> Verifying namespace config:" && \
grep -E "gitops\.(namespace|gitlab_namespace)|GITLAB_NAMESPACE" \
/Users/chrisfu/dev/prole/conf/service/prole.cfg
echo "==> Launching final install run (gitlab namespace)..." && \
mkdir -p logs && \
nohup bash install.sh --silent -c conf/service/prole.cfg \
> logs/install_final2.log 2>&1 & disown && \
echo "Installer started. Monitor: tail -f logs/install_final2.log"

7
tmp/launch_final.sh Normal file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
cd /Users/chrisfu/dev/prole
rm -f install.pid
mkdir -p logs
nohup bash install.sh --silent -c conf/service/prole.cfg > logs/install_final2.log 2>&1 &
disown
echo "Installer launched. Tail: tail -f logs/install_final2.log"

View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
MINIO_POD=$(kubectl -n gitlab get pod -l app=minio --no-headers -o name | head -1)
echo "==> Minio pod: $MINIO_POD"
AK=$(kubectl -n gitlab exec "$MINIO_POD" -- \
sh -c "python3 -c \"import json; d=json.load(open('/tmp/.minio/config.json.old')); print(d['credential']['accessKey'],end='')\"" 2>/dev/null)
SK=$(kubectl -n gitlab exec "$MINIO_POD" -- \
sh -c "python3 -c \"import json; d=json.load(open('/tmp/.minio/config.json.old')); print(d['credential']['secretKey'],end='')\"" 2>/dev/null)
echo "==> AK=${AK:0:8}... (len=${#AK}) SK=${SK:0:8}... (len=${#SK})"
kubectl -n gitlab delete pod minio-init --ignore-not-found 2>/dev/null || true
cat > /tmp/mc-cmd.sh << SCRIPT
#!/bin/sh
mc alias set gl http://gitlab-minio-svc.gitlab.svc.cluster.local:9000 '${AK}' '${SK}' && \
for b in registry gitlab-lfs-storage gitlab-artifacts-storage gitlab-uploads-storage \
gitlab-packages-storage gitlab-dependency-proxy-storage \
gitlab-terraform-state gitlab-ci-secure-files; do
mc mb --ignore-existing "gl/\$b" && echo "OK:\$b"
done && mc ls gl && echo BUCKETS_DONE
SCRIPT
chmod +x /tmp/mc-cmd.sh
kubectl -n gitlab run minio-init \
--image=minio/mc:latest \
--restart=Never \
--overrides="{\"spec\":{\"nodeName\":\"gandalf.prole.org\",\"tolerations\":[{\"operator\":\"Exists\"}],\"containers\":[{\"name\":\"minio-init\",\"image\":\"minio/mc:latest\",\"command\":[\"sh\",\"-c\",\"mc alias set gl http://gitlab-minio-svc.gitlab.svc.cluster.local:9000 ${AK} ${SK} && for b in registry gitlab-lfs-storage gitlab-artifacts-storage gitlab-uploads-storage gitlab-packages-storage gitlab-dependency-proxy-storage gitlab-terraform-state gitlab-ci-secure-files; do mc mb --ignore-existing gl/\\\$b && echo OK:\\\$b; done && mc ls gl && echo BUCKETS_DONE\"]}]}}"
echo "==> minio-init started — check with: kubectl -n gitlab logs minio-init"

View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> CR stored liveness probe:" && \
kubectl -n gitea get gitlab gitlab \
-o jsonpath='{.spec.chart.values.gitlab.webservice.livenessProbe}' 2>&1 && echo
echo "==> Patching webservice Deployment liveness probe directly..." && \
kubectl -n gitea patch deployment gitlab-webservice-default --type=json -p '[
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/initialDelaySeconds","value":3600},
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/failureThreshold","value":30}
]' 2>&1
echo "==> Patching sidekiq Deployment liveness probe directly..." && \
kubectl -n gitea patch deployment gitlab-sidekiq-all-in-1-v2 --type=json -p '[
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/initialDelaySeconds","value":3600},
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/failureThreshold","value":30}
]' 2>&1 || true
echo "==> Checking rolling update — new pods:" && \
sleep 10 && \
kubectl -n gitea get pods --no-headers | grep -E "webservice|sidekiq"

25
tmp/patch_jemalloc.sh Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching GitLab CR with LD_PRELOAD='' on all ARM64-affected components..."
kubectl -n gitlab patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"gitlab":{
"migrations":{"extraEnv":{"LD_PRELOAD":""}},
"sidekiq":{"extraEnv":{"LD_PRELOAD":""}},
"webservice":{"extraEnv":{"LD_PRELOAD":""}},
"gitaly":{"extraEnv":{"LD_PRELOAD":""}},
"toolbox":{"extraEnv":{"LD_PRELOAD":""}}
},
"registry":{"extraEnv":{"LD_PRELOAD":""}}
}}}}'
echo "==> Patch applied. Waiting 45s for operator to reconcile..."
sleep 45
echo "==> Pod status:"
kubectl -n gitlab get pods
echo "==> GitLab CR status:"
kubectl -n gitlab get gitlab gitlab

View File

@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
JEMALLOC_PATH="/opt/gitlab-jemalloc/libjemalloc.so.2"
JEMALLOC_MOUNT="/opt/gitlab-jemalloc"
echo "==> Patching GitLab CR with hostPath jemalloc-16k for all ARM64 components..."
# Build the extra volumes / mounts JSON (shared across components)
EXTRA_VOL='[{"name":"jemalloc-16k","hostPath":{"path":"/opt/gitlab-jemalloc","type":"Directory"}}]'
EXTRA_MOUNT='[{"name":"jemalloc-16k","mountPath":"/opt/gitlab-jemalloc","readOnly":true}]'
PRELOAD_ENV='{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"}'
kubectl -n gitlab patch gitlab gitlab --type=merge -p "{
\"spec\":{\"chart\":{\"values\":{
\"global\":{
\"extraEnv\": ${PRELOAD_ENV}
},
\"gitlab\":{
\"migrations\":{
\"extraEnv\": ${PRELOAD_ENV},
\"extraVolumes\": ${EXTRA_VOL},
\"extraVolumeMounts\": ${EXTRA_MOUNT}
},
\"sidekiq\":{
\"extraEnv\": ${PRELOAD_ENV},
\"extraVolumes\": ${EXTRA_VOL},
\"extraVolumeMounts\": ${EXTRA_MOUNT}
},
\"webservice\":{
\"extraEnv\": ${PRELOAD_ENV},
\"extraVolumes\": ${EXTRA_VOL},
\"extraVolumeMounts\": ${EXTRA_MOUNT}
},
\"gitaly\":{
\"extraEnv\": ${PRELOAD_ENV},
\"extraVolumes\": ${EXTRA_VOL},
\"extraVolumeMounts\": ${EXTRA_MOUNT}
},
\"toolbox\":{
\"extraEnv\": ${PRELOAD_ENV},
\"extraVolumes\": ${EXTRA_VOL},
\"extraVolumeMounts\": ${EXTRA_MOUNT}
}
},
\"registry\":{
\"extraEnv\": ${PRELOAD_ENV},
\"extraVolumes\": ${EXTRA_VOL},
\"extraVolumeMounts\": ${EXTRA_MOUNT}
}
}}}}"
echo "==> Patch applied. Waiting 60s for operator to reconcile..."
sleep 60
echo "==> Pod status:"
kubectl -n gitlab get pods
echo "==> GitLab CR status:"
kubectl -n gitlab get gitlab gitlab

56
tmp/patch_jemalloc_v2.sh Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting failed migrations job so operator can recreate it..."
kubectl -n gitlab delete job -l app=migrations --ignore-not-found
echo "==> Patching GitLab CR — extraVolumes/extraVolumeMounts as YAML strings..."
# The GitLab chart expects extraVolumes/extraVolumeMounts as YAML strings, not arrays
kubectl -n gitlab patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"global":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"}
},
"gitlab":{
"migrations":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
},
"sidekiq":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
},
"webservice":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
},
"gitaly":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
},
"toolbox":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
}
},
"registry":{
"extraEnv":{"LD_PRELOAD":"/opt/gitlab-jemalloc/libjemalloc.so.2"},
"extraVolumes":"- name: jemalloc-16k\n hostPath:\n path: /opt/gitlab-jemalloc\n type: Directory\n",
"extraVolumeMounts":"- name: jemalloc-16k\n mountPath: /opt/gitlab-jemalloc\n readOnly: true\n"
}
}}}}'
echo "==> Patch applied. Waiting 60s for operator to reconcile..."
sleep 60
echo "==> Pod status:"
kubectl -n gitlab get pods --sort-by=.metadata.creationTimestamp | grep -v jemalloc-builder | grep -v arch-check
echo "==> GitLab CR status:"
kubectl -n gitlab get gitlab gitlab

29
tmp/patch_minio_arm64.sh Normal file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Patching GitLab CR with ARM64-compatible minio/mc images..."
kubectl -n gitlab patch gitlab gitlab --type=merge -p '{
"spec":{"chart":{"values":{
"minio":{
"image":"minio/minio",
"imageTag":"RELEASE.2024-12-18T17-30-49Z",
"mcImage":{
"repository":"minio/mc",
"tag":"RELEASE.2024-11-21T17-21-54Z"
}
}
}}}}'
echo "==> Deleting stuck minio pod and create-buckets job..."
kubectl -n gitlab delete pod -l app=minio --ignore-not-found
kubectl -n gitlab delete job -l app=minio-create-buckets --ignore-not-found
echo "==> Waiting 90s for operator to reconcile..."
sleep 90
echo "==> Pod status:"
kubectl -n gitlab get pods --sort-by=.metadata.creationTimestamp | grep -v jemalloc-builder
echo "==> Minio logs:"
kubectl -n gitlab logs -l app=minio --tail=15 2>&1 || true

View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Inspect current minio init container image..."
kubectl -n gitlab get deployment gitlab-minio \
-o jsonpath='{.spec.template.spec.initContainers[*].name}' && echo
kubectl -n gitlab get deployment gitlab-minio \
-o jsonpath='{.spec.template.spec.initContainers[0].image}' && echo
echo "==> Patching minio Deployment: replace configure init container with ARM64 alpine..."
kubectl -n gitlab patch deployment gitlab-minio --type=json -p '[
{
"op": "replace",
"path": "/spec/template/spec/initContainers/0",
"value": {
"name": "configure",
"image": "alpine:latest",
"command": ["sh", "-c",
"mkdir -p /tmp/.minio && echo -n \"$MINIO_ACCESS_KEY\" > /tmp/.minio/access_key && echo -n \"$MINIO_SECRET_KEY\" > /tmp/.minio/secret_key && chmod 600 /tmp/.minio/access_key /tmp/.minio/secret_key && echo \"Credentials written OK\""],
"env": [
{"name": "MINIO_ACCESS_KEY", "valueFrom": {"secretKeyRef": {"name": "gitlab-minio-secret", "key": "accesskey"}}},
{"name": "MINIO_SECRET_KEY", "valueFrom": {"secretKeyRef": {"name": "gitlab-minio-secret", "key": "secretkey"}}}
],
"volumeMounts": [
{"name": "minio-configuration", "mountPath": "/tmp/.minio"}
]
}
}
]'
echo "==> Deleting old minio pod to force restart with new init container..."
kubectl -n gitlab delete pod -l app=minio --ignore-not-found
echo "==> Waiting 60s for minio to restart..."
sleep 60
echo "==> Minio pod status:"
kubectl -n gitlab get pod -l app=minio --no-headers
echo "==> Minio init container log:"
kubectl -n gitlab logs -l app=minio -c configure --tail=5 2>&1 || true
echo "==> Minio main container log:"
kubectl -n gitlab logs -l app=minio --tail=5 2>&1 | grep -v LD_PRELOAD | head -5 || true

22
tmp/poll_gitlab_ns.sh Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
for i in $(seq 1 30); do
pct=$(grep -oE '\[([0-9]+)%\]' /Users/chrisfu/dev/prole/logs/install_final2.log 2>/dev/null | tail -1)
ns_gitlab=$(kubectl get ns gitlab --no-headers 2>/dev/null | awk '{print $1}')
echo "[$(date -u '+%H:%M')] [$i/30] installer=$pct | gitlab ns=${ns_gitlab:-none}"
if [[ -n "$ns_gitlab" ]]; then
echo "==> gitlab namespace exists! Checking pods..."
kubectl -n gitlab get pods --no-headers 2>/dev/null | grep -v jemalloc | head -8
echo "==> Checking for gitea ns (should be absent):"
kubectl get ns gitea --no-headers 2>/dev/null || echo " gitea: absent (correct)"
break
fi
# Also break if installer finished
if ! ps aux | grep -q "install.sh"; then
echo "==> Installer finished. Log tail:"
tail -5 /Users/chrisfu/dev/prole/logs/install_final2.log | cat
break
fi
sleep 60
done

32
tmp/poll_ready.sh Normal file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
for i in $(seq 1 20); do
ws_ready=$(kubectl -n gitea get pods -l app=webservice \
-o jsonpath='{range .items[*]}{.status.containerStatuses[?(@.name=="webservice")].ready}{"\n"}{end}' \
2>/dev/null | grep -c "^true$" || echo 0)
sk_ready=$(kubectl -n gitea get pod -l app=sidekiq \
-o jsonpath='{.items[0].status.containerStatuses[0].ready}' 2>/dev/null || echo false)
phase=$(kubectl -n gitea get gitlab gitlab \
-o jsonpath='{.status.phase}' 2>/dev/null || echo "unknown")
echo "[$(date -u '+%H:%M:%S')] [$i/20] webservice puma ready: $ws_ready | sidekiq ready: $sk_ready | CR: $phase"
if [[ "$ws_ready" -ge 1 && "$sk_ready" == "true" ]]; then
echo "==> GitLab is fully up!"
break
fi
sleep 90
done
echo "==> Final pod status:"
kubectl -n gitea get pods --no-headers \
| grep -v jemalloc | grep -v Completed | sort
echo "==> CR conditions:"
kubectl -n gitea get gitlab gitlab \
-o jsonpath='{range .status.conditions[*]}{.type}: {.status} ({.message}){"\n"}{end}' 2>&1
echo "==> Initial root password:"
kubectl -n gitea get secret gitlab-gitlab-initial-root-password \
-o jsonpath='{.data.password}' 2>/dev/null | base64 -d && echo || true

10
tmp/quick_status.sh Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Webservice puma latest (kgqhl):" && \
kubectl -n gitea logs gitlab-webservice-default-675ccb7b99-kgqhl -c webservice --tail=6 2>&1 | grep -v LD_PRELOAD | head -6
echo "==> Sidekiq latest:" && \
kubectl -n gitea logs gitlab-sidekiq-all-in-1-v2-679848bc8-wvxln --tail=6 2>&1 | grep -v LD_PRELOAD | head -6
echo "==> Pod readiness:" && \
kubectl -n gitea get pods --no-headers | grep -E "webservice|sidekiq" | awk '{print $1,$2,$3}'
echo "==> CR phase:" && \
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' 2>&1 && echo

62
tmp/rebuild_ds_v2.sh Normal file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
kubectl -n gitlab delete daemonset jemalloc-builder --ignore-not-found
sleep 5
kubectl apply -f - <<'DS'
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: jemalloc-builder
namespace: gitlab
labels:
app: jemalloc-builder
spec:
selector:
matchLabels:
app: jemalloc-builder
template:
metadata:
labels:
app: jemalloc-builder
spec:
tolerations:
- operator: Exists
initContainers:
- name: build
image: ubuntu:22.04
command:
- bash
- -c
- |
set -e
TARGET=/hostlib/libjemalloc.so.2
if [ -f "$TARGET" ]; then echo "Already built"; exit 0; fi
apt-get update -qq && apt-get install -y -q gcc make wget bzip2 2>&1
cd /tmp
wget -q -O jemalloc.tar.bz2 \
https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2
tar xjf jemalloc.tar.bz2 && cd jemalloc-5.3.0
./configure --with-lg-page=14 --disable-stats --disable-prof --disable-fill 2>&1
make -j2 lib/libjemalloc.so.2 2>&1
cp lib/libjemalloc.so.2 "$TARGET" && chmod 755 "$TARGET"
file "$TARGET" && echo "Done: $(ls -lh $TARGET)"
volumeMounts:
- name: hostlib
mountPath: /hostlib
containers:
- name: keepalive
image: ubuntu:22.04
command: [bash, -c, "echo 'glibc jemalloc-16k ready'; sleep infinity"]
volumes:
- name: hostlib
hostPath:
path: /opt/gitlab-jemalloc
type: DirectoryOrCreate
DS
echo "DaemonSet applied. Waiting 15min for builds to complete..."
sleep 900
kubectl -n gitlab get pods -l app=jemalloc-builder

View File

@ -0,0 +1,108 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting old musl-based DaemonSet and cleaning nodes..."
kubectl -n gitlab delete daemonset jemalloc-builder --ignore-not-found
# Clean old musl binary from all nodes via a cleanup DaemonSet
kubectl apply -f - <<'CLEANUP'
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: jemalloc-cleanup
namespace: gitlab
spec:
selector:
matchLabels:
app: jemalloc-cleanup
template:
metadata:
labels:
app: jemalloc-cleanup
spec:
tolerations:
- operator: Exists
initContainers:
- name: clean
image: alpine:latest
command: [sh, -c, "rm -f /hostlib/libjemalloc.so.2 && echo cleaned"]
volumeMounts:
- name: hostlib
mountPath: /hostlib
containers:
- name: done
image: alpine:latest
command: [sh, -c, "echo done; sleep infinity"]
volumes:
- name: hostlib
hostPath:
path: /opt/gitlab-jemalloc
type: DirectoryOrCreate
CLEANUP
echo "Waiting 30s for cleanup to complete..."
sleep 30
kubectl -n gitlab delete daemonset jemalloc-cleanup --ignore-not-found
echo "==> Deploying Ubuntu-based (glibc) jemalloc builder DaemonSet..."
kubectl apply -f - <<'DS'
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: jemalloc-builder
namespace: gitlab
labels:
app: jemalloc-builder
spec:
selector:
matchLabels:
app: jemalloc-builder
template:
metadata:
labels:
app: jemalloc-builder
spec:
tolerations:
- operator: Exists
initContainers:
- name: build
image: ubuntu:22.04
command:
- bash
- -c
- |
set -e
TARGET=/hostlib/libjemalloc.so.2
if [ -f "$TARGET" ]; then echo "Already built — skipping."; exit 0; fi
echo "Installing build tools (glibc-based)..."
apt-get update -qq && apt-get install -y -q gcc make wget autoconf 2>&1
cd /tmp
echo "Downloading jemalloc 5.3.0..."
wget -q -O jemalloc.tar.bz2 \
https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2
tar xf jemalloc.tar.bz2 && cd jemalloc-5.3.0
echo "Configuring with --with-lg-page=14 (16KB, glibc)..."
./configure --with-lg-page=14 --disable-stats --disable-prof --disable-fill 2>&1
make -j2 lib/libjemalloc.so.2 2>&1
cp lib/libjemalloc.so.2 "$TARGET"
chmod 755 "$TARGET"
file "$TARGET"
echo "Done: $(ls -lh $TARGET)"
volumeMounts:
- name: hostlib
mountPath: /hostlib
containers:
- name: keepalive
image: ubuntu:22.04
command: [bash, -c, "echo 'glibc jemalloc-16k ready'; sleep infinity"]
volumes:
- name: hostlib
hostPath:
path: /opt/gitlab-jemalloc
type: DirectoryOrCreate
DS
echo "==> Builder DaemonSet created. This will take ~10-15min on RPi. Checking in 5min..."
sleep 300
kubectl -n gitlab get pods -l app=jemalloc-builder

View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting second webservice pod to reduce RAM pressure on gandalf..." && \
kubectl -n gitea delete pod gitlab-webservice-default-675ccb7b99-mmclp --force --grace-period=0 --ignore-not-found 2>&1
echo "==> Waiting 15 min for puma to complete boot on single pod..." && \
sleep 900
echo "==> Webservice puma log:" && \
kubectl -n gitea logs -l app=webservice -c webservice --tail=5 2>&1 | grep -v LD_PRELOAD | head -8
echo "==> Sidekiq log:" && \
kubectl -n gitea logs -l app=sidekiq --tail=3 2>&1 | grep -v LD_PRELOAD | head -4
echo "==> Pod readiness:" && \
kubectl -n gitea get pods --no-headers | grep -E "webservice|sidekiq" | awk '{print $1,$2,$3}'
echo "==> CR conditions:" && \
kubectl -n gitea get gitlab gitlab \
-o jsonpath='{range .status.conditions[*]}{.type}: {.status} ({.message}){"\n"}{end}' 2>&1
echo "==> Root password (if Available):" && \
kubectl -n gitea get secret gitlab-gitlab-initial-root-password \
-o jsonpath='{.data.password}' 2>/dev/null | base64 -d && echo

45
tmp/reset_gitlab_db.sh Normal file
View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Finding CNPG primary pod..."
PRIMARY=$(kubectl -n knoe-db get pods \
-l "cnpg.io/cluster=knoe-db,cnpg.io/instanceRole=primary" \
--no-headers -o name | head -1)
echo "Primary: $PRIMARY"
echo "==> Dropping and recreating gitlabhq_production DB..."
kubectl -n knoe-db exec "$PRIMARY" -- \
psql -U postgres -c "
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'gitlabhq_production' AND pid <> pg_backend_pid();
DROP DATABASE IF EXISTS gitlabhq_production;
CREATE DATABASE gitlabhq_production OWNER root;
GRANT ALL PRIVILEGES ON DATABASE gitlabhq_production TO root;
" 2>&1
echo "==> Deleting failed migration jobs so operator recreates them..."
kubectl -n gitea delete job \
gitlab-migrations-5f05f2c-f73-1 \
gitlab-migrations-5f05f2c-f73-2 \
--ignore-not-found
echo "==> Deleting shared-secrets jobs to force regeneration..."
kubectl -n gitea delete job \
gitlab-shared-secrets-2454dc7 \
gitlab-shared-secrets-d79f1fc \
--ignore-not-found 2>/dev/null || true
kubectl -n gitea delete pods -l app=shared-secrets --ignore-not-found 2>/dev/null || true
echo "==> Deleting gitlab-rails-secret to force new key generation..."
kubectl -n gitea delete secret gitlab-rails-secret --ignore-not-found
echo "==> Waiting 60s for operator to recreate shared-secrets + migrations..."
sleep 60
echo "==> New jobs:"
kubectl -n gitea get jobs --no-headers 2>&1 | grep -E "migrations|shared-secrets"
echo "==> New pods:"
kubectl -n gitea get pods --no-headers | grep -E "migrations|shared-secrets"

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> Deleting failed jobs..."
kubectl -n gitlab delete jobs --all --ignore-not-found
echo "==> Deleting crashed/stuck GitLab pods..."
kubectl -n gitlab delete pods \
-l 'app in (toolbox,registry,gitaly,webservice,sidekiq,gitlab-exporter,minio)' \
--ignore-not-found
echo "==> Waiting 120s for operator to reconcile and pods to start..."
sleep 120
echo "==> Pod status:"
kubectl -n gitlab get pods --sort-by=.metadata.creationTimestamp | grep -v jemalloc-builder
echo "==> GitLab CR status:"
kubectl -n gitlab get gitlab gitlab

6
tmp/run7.sh Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
cd /Users/chrisfu/dev/prole
mkdir -p logs
nohup bash install.sh --silent -c conf/service/prole.cfg > logs/install_run7.log 2>&1 &
disown
echo "started"

18
tmp/run8.sh Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> CNPG cluster status:"
kubectl -n knoe-db get cluster knoe-db -o jsonpath='{.status.phase}' 2>&1 && echo
echo "==> CNPG pods:"
kubectl -n knoe-db get pods --no-headers 2>&1
echo "==> Removing stale PID lock..."
rm -f /Users/chrisfu/dev/prole/install.pid
echo "==> Launching installer run 8..."
cd /Users/chrisfu/dev/prole
mkdir -p logs
nohup bash install.sh --silent -c conf/service/prole.cfg > logs/install_run8.log 2>&1 &
disown
echo "Installer started, logging to logs/install_run8.log"

6
tmp/run_install2.sh Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
cd /Users/chrisfu/dev/prole
echo "[$(date)] Starting install run 2..." >> logs/install_run2.log
bash install.sh --silent -c conf/service/prole.cfg >> logs/install_run2.log 2>&1
echo "[$(date)] Install run 2 complete." >> logs/install_run2.log

62
tmp/sim_installer_ns.sh Normal file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
# Simulates EXACTLY what milestones.py + controller.run_script does
# when calling init_gitlab.sh — replicates the full env context.
set -euo pipefail
CFG="/Users/chrisfu/dev/prole/conf/service/prole.cfg"
PROLE_HOME="/Users/chrisfu/dev/prole"
echo "=== Simulating installer env context ==="
# Replicate _get_script_env (milestone.py lines 81-87)
# base_env = os.environ.copy() + updates
export PROLE_HOME="$PROLE_HOME"
export PROLE_SERVICE="$PROLE_HOME/etc"
export PROLE_CONF="$PROLE_HOME/conf/service"
export PROLE_DATA="$PROLE_HOME/knoe-db/data"
export PROLE_LOGS="$PROLE_HOME/logs"
export PROLE_MODE="k3s"
export DEPLOYMENT_MODE="k3s"
export NAMESPACE="knoe-db" # milestone.py line 86: init_password.db_namespace
export PROLE_NAMESPACE="knoe-db"
export DATABASE_NAMESPACE="knoe-db"
export SERVICE_NAMESPACE="knoe-system"
export CLUSTER_NAME="knoe-db"
# Replicate milestones.py GitOpsMilestone.execute() lines 965-977
export GITLAB_NAMESPACE="gitlab" # line 971: env["GITLAB_NAMESPACE"] = ns (ns="gitlab")
export GITLAB_NODE_SELECTOR="gandalf.prole.org" # line 976
export NODE_SELECTOR="gandalf.prole.org" # line 977
echo " Pre-call env: NAMESPACE='$NAMESPACE' GITLAB_NAMESPACE='$GITLAB_NAMESPACE'"
echo ""
# Now call init_gitlab.sh with same args milestones.py builds:
# args = ["--mode", "k3s", "--namespace", ns, "-c", cfg_path]
echo "=== Calling init_gitlab.sh --trace-namespace (exits after namespace resolution) ==="
OUTPUT=$(bash "$PROLE_HOME/etc/init_gitlab.sh" \
--mode k3s \
--namespace gitlab \
-c "$CFG" \
--trace-namespace 2>&1 || true)
echo "$OUTPUT" | head -5
# Now test WITHOUT --namespace arg (worst-case: arg not passed)
echo ""
echo "=== Worst case: no --namespace arg (relies on env + default) ==="
OUTPUT2=$(bash "$PROLE_HOME/etc/init_gitlab.sh" \
--mode k3s \
-c "$CFG" \
--trace-namespace 2>&1 || true)
echo "$OUTPUT2" | head -5
# Also verify what prole_cfg.sh does to NAMESPACE
echo ""
echo "=== Check: does prole_cfg.sh overwrite NAMESPACE? ==="
(
export NAMESPACE="gitlab"
source "$PROLE_HOME/etc/prole_cfg.sh" 2>/dev/null || true
echo " NAMESPACE after sourcing prole_cfg.sh: '${NAMESPACE:-<unset>}'"
echo " GITOPS_NAMESPACE: '${GITOPS_NAMESPACE:-<unset>}'"
echo " GITLAB_NAMESPACE: '${GITLAB_NAMESPACE:-<unset>}'"
)

65
tmp/sim_milestones_ns.py Normal file
View File

@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""Simulate exactly what GitOpsMilestone.execute() does for namespace resolution."""
import sys
sys.path.insert(0, "/Users/chrisfu/dev/prole")
import configparser
CFG = "/Users/chrisfu/dev/prole/conf/service/prole.cfg"
# Load config the same way the installer does
parser = configparser.ConfigParser(strict=False)
parser.read(CFG)
# Build state.inputs from [Inputs] section
inputs = dict(parser.items("Inputs")) if parser.has_section("Inputs") else {}
# Build config_data from all sections
config_data = {sec: dict(parser.items(sec)) for sec in parser.sections()}
print("=== state.inputs relevant keys ===")
for k, v in sorted(inputs.items()):
if "gitops" in k or "gitlab" in k or "namespace" in k:
print(f" {k!r} => {v!r}")
print("\n=== config_data[GitOps] ===")
for k, v in config_data.get("GitOps", {}).items():
print(f" {k!r} => {v!r}")
print("\n=== config_data[Global] GITLAB_NAMESPACE ===")
print(f" {config_data.get('Global', {}).get('gitlab_namespace', '<unset>')!r}")
print(f" {config_data.get('global', {}).get('gitlab_namespace', '<unset>')!r}")
# Simulate milestones.py provider detection (lines 945-957)
provider = (
str(inputs.get("gitops.git_provider", "") or "").strip().lower()
or str(
(config_data.get("Optional Features") or {}).get("GITOPS_PROVIDER", "") or ""
).strip().lower()
or "gitea"
)
is_gitlab = provider == "gitlab"
print(f"\n=== Provider: {provider!r} | is_gitlab={is_gitlab} ===")
# Simulate new namespace resolution (lines 965-977)
if is_gitlab:
ns = (
str(inputs.get("gitops.gitlab_namespace", "") or "").strip()
or str(
(config_data.get("Global") or config_data.get("global") or {}).get(
"gitlab_namespace", ""
)
or ""
).strip()
or "gitlab"
)
print(f"\n=== GITLAB ns resolved: {ns!r} ===")
if ns == "gitlab":
print(" ✓ CORRECT — will use 'gitlab' namespace")
else:
print(f" ✗ BUG — got {ns!r}, expected 'gitlab'")
else:
ns = (
inputs.get("gitops.namespace", "")
or "gitea"
).strip()
print(f"\n=== GITEA ns: {ns!r} (is_gitlab=False — BUG if expecting gitlab) ===")

14
tmp/status_check.sh Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
export KUBECONFIG=/Users/chrisfu/dev/prole/prole-k3s.kubeconfig
echo "==> minio-init logs:"
kubectl -n gitea logs minio-init 2>&1 | tail -15 || true
echo "==> GitLab pods:"
kubectl -n gitea get pods --no-headers | grep -v jemalloc-builder | sort
echo "==> GitLab CR phase:"
kubectl -n gitea get gitlab gitlab -o jsonpath='{.status.phase}' 2>&1 && echo
echo "==> Installer run 9 tail:"
tail -10 /Users/chrisfu/dev/prole/logs/install_run9.log 2>&1

View File

@ -0,0 +1 @@
{"apiVersion": "v1", "kind": "Namespace", "metadata": {"name": "supabase"}}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
{
"values": "tmp/supabase-render-check/generated/values.generated.json",
"manifests": "tmp/supabase-render-check/manifests/supabase-helm.yaml",
"db_host": "knoe-db-rw.knoe-db.svc.cluster.local",
"supabase_namespace": "supabase"
}

View File

@ -0,0 +1 @@
1c7b59cc1337c65bc2edc2e58d3ffbe584b9f9ef66305705fca633682954f965

View File

@ -0,0 +1,181 @@
{
"nameOverride": "supabase",
"fullnameOverride": "supabase",
"deployment": {
"db": {
"enabled": false
},
"functions": {
"enabled": true,
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"vector": {
"enabled": true,
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"kong": {
"enabled": true,
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"storage": {
"enabled": true,
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"minio": {
"enabled": false,
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"imgproxy": {
"enabled": true,
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"analytics": {
"enabled": true,
"fullnameOverride": "supabase-analytics",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"auth": {
"enabled": true,
"fullnameOverride": "supabase-auth",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"meta": {
"enabled": true,
"fullnameOverride": "supabase-meta",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"realtime": {
"enabled": true,
"fullnameOverride": "supabase-realtime",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"rest": {
"enabled": true,
"fullnameOverride": "supabase-rest",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"studio": {
"enabled": true,
"fullnameOverride": "supabase-studio",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
}
},
"externalDatabase": {
"enabled": true,
"host": "knoe-db-rw.knoe-db.svc.cluster.local",
"port": 5432,
"database": "postgres",
"ssl": "disable",
"createAliasService": true,
"aliasServiceName": "db"
},
"environment": {
"auth": {
"DB_HOST": "knoe-db-rw.knoe-db.svc.cluster.local",
"DB_PORT": "5432",
"DB_SSL": "disable",
"API_EXTERNAL_URL": "https://db.prole.org",
"GOTRUE_SITE_URL": "https://db.prole.org"
},
"analytics": {
"DB_HOST": "knoe-db-rw.knoe-db.svc.cluster.local",
"DB_PORT": "5432"
},
"meta": {
"DB_HOST": "knoe-db-rw.knoe-db.svc.cluster.local",
"DB_PORT": "5432"
},
"studio": {
"SUPABASE_PUBLIC_URL": "https://db.prole.org"
}
},
"secret": {
"db": {
"password": "fr3styl3",
"database": "postgres"
},
"jwt": {
"secret": "1c7b59cc1337c65bc2edc2e58d3ffbe584b9f9ef66305705fca633682954f965",
"anonKey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InByb2xlLXN1cGFiYXNlIiwiaWF0IjoxNzc0OTQ5NDkxLCJleHAiOjIwOTAzMDk0OTF9.JL3QtWzra-GtaqaxmzXSbMnw5Y78jZRZ3jUun6UC4Qk",
"serviceKey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoicHJvbGUtc3VwYWJhc2UiLCJpYXQiOjE3NzQ5NDk0OTEsImV4cCI6MjA5MDMwOTQ5MX0.1_xMhBC0VsFZxTJV2ADuDjaf04RFTBZcX5ahdTQdV1c"
},
"s3": {
"keyId": "dummy-key",
"accessKey": "dummy-secret"
}
},
"ingress": {
"enabled": true,
"className": "traefik",
"hosts": [
{
"host": "db.prole.org",
"paths": [
{
"path": "/",
"pathType": "Prefix"
}
]
}
]
},
"studioIngress": {
"enabled": true,
"className": "traefik",
"hosts": [
{
"host": "db.prole.org",
"paths": [
{
"path": "/",
"pathType": "Prefix"
}
]
}
]
},
"persistence": {
"functions": {
"storageClassName": "synology-iscsi"
},
"snippets": {
"storageClassName": "synology-iscsi"
},
"deno": {
"storageClassName": "synology-iscsi"
},
"imgproxy": {
"storageClassName": "synology-iscsi"
},
"minio": {
"storageClassName": "synology-iscsi"
},
"storage": {
"storageClassName": "synology-iscsi"
}
}
}

View File

@ -0,0 +1,6 @@
{
"values": "tmp/supabase-render-check/values.generated.json",
"manifests": "tmp/supabase-render-check-manifests/supabase-helm.yaml",
"db_host": "knoe-db-rw.knoe-db.svc.cluster.local",
"supabase_namespace": "supabase"
}

View File

@ -0,0 +1 @@
{"apiVersion": "v1", "kind": "Namespace", "metadata": {"name": "supabase"}}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
94ceb97b40840be015507dea971cbc8e5f897857e84c7071fe53bc3d75c9c894

View File

@ -0,0 +1,187 @@
{
"nameOverride": "supabase",
"fullnameOverride": "supabase",
"deployment": {
"db": {
"enabled": false
},
"functions": {
"enabled": true,
"fullnameOverride": "supabase-functions",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"vector": {
"enabled": true,
"fullnameOverride": "supabase-vector",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"kong": {
"enabled": true,
"fullnameOverride": "supabase-kong",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"storage": {
"enabled": true,
"fullnameOverride": "supabase-storage",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"minio": {
"enabled": false,
"fullnameOverride": "supabase-minio",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"imgproxy": {
"enabled": true,
"fullnameOverride": "supabase-imgproxy",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"analytics": {
"enabled": true,
"fullnameOverride": "supabase-analytics",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"auth": {
"enabled": true,
"fullnameOverride": "supabase-auth",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"meta": {
"enabled": true,
"fullnameOverride": "supabase-meta",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"realtime": {
"enabled": true,
"fullnameOverride": "supabase-realtime",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"rest": {
"enabled": true,
"fullnameOverride": "supabase-rest",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
},
"studio": {
"enabled": true,
"fullnameOverride": "supabase-studio",
"nodeSelector": {
"kubernetes.io/hostname": "gandalf.prole.org"
}
}
},
"externalDatabase": {
"enabled": true,
"host": "knoe-db-rw.knoe-db.svc.cluster.local",
"port": 5432,
"database": "postgres",
"ssl": "disable",
"createAliasService": true,
"aliasServiceName": "db"
},
"environment": {
"auth": {
"DB_HOST": "knoe-db-rw.knoe-db.svc.cluster.local",
"DB_PORT": "5432",
"DB_SSL": "disable",
"API_EXTERNAL_URL": "https://db.prole.org",
"GOTRUE_SITE_URL": "https://db.prole.org"
},
"analytics": {
"DB_HOST": "knoe-db-rw.knoe-db.svc.cluster.local",
"DB_PORT": "5432"
},
"meta": {
"DB_HOST": "knoe-db-rw.knoe-db.svc.cluster.local",
"DB_PORT": "5432"
},
"studio": {
"SUPABASE_PUBLIC_URL": "https://db.prole.org"
}
},
"secret": {
"db": {
"password": "fr3styl3",
"database": "postgres"
},
"jwt": {
"secret": "94ceb97b40840be015507dea971cbc8e5f897857e84c7071fe53bc3d75c9c894",
"anonKey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InByb2xlLXN1cGFiYXNlIiwiaWF0IjoxNzc0OTg2MzM3LCJleHAiOjIwOTAzNDYzMzd9.iB09t7oguzJzL6qySTPGrlwDvAZDUITfkl6Gm1VaogQ",
"serviceKey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoicHJvbGUtc3VwYWJhc2UiLCJpYXQiOjE3NzQ5ODYzMzcsImV4cCI6MjA5MDM0NjMzN30.ANo9XMsQDRTUqHWQqvz6g6s0ePGlgjYiaeAP7KIckQ0"
},
"s3": {
"keyId": "dummy",
"accessKey": "dummy"
}
},
"ingress": {
"enabled": true,
"className": "traefik",
"hosts": [
{
"host": "db.prole.org",
"paths": [
{
"path": "/",
"pathType": "Prefix"
}
]
}
]
},
"studioIngress": {
"enabled": true,
"className": "traefik",
"hosts": [
{
"host": "db.prole.org",
"paths": [
{
"path": "/",
"pathType": "Prefix"
}
]
}
]
},
"persistence": {
"functions": {
"storageClassName": "synology-iscsi"
},
"snippets": {
"storageClassName": "synology-iscsi"
},
"deno": {
"storageClassName": "synology-iscsi"
},
"imgproxy": {
"storageClassName": "synology-iscsi"
},
"minio": {
"storageClassName": "synology-iscsi"
},
"storage": {
"storageClassName": "synology-iscsi"
}
}
}

67
tmp/trace_namespace.sh Normal file
View File

@ -0,0 +1,67 @@
#!/usr/bin/env bash
# Diagnostic: traces exactly how init_gitlab.sh resolves NAMESPACE
# Run directly (not via installer) to see the raw logic.
set -euo pipefail
SCRIPT_DIR="/Users/chrisfu/dev/prole/etc"
CFG_PATH="/Users/chrisfu/dev/prole/conf/service/prole.cfg"
source "$SCRIPT_DIR/prole_cfg.sh"
echo "======================================================="
echo "TRACE: init_gitlab.sh namespace resolution"
echo "======================================================="
echo ""
echo "--- Step 1: Environment variables before any assignment ---"
echo " GITLAB_NAMESPACE='${GITLAB_NAMESPACE:-<unset>}'"
echo " GITOPS_NAMESPACE='${GITOPS_NAMESPACE:-<unset>}'"
echo " NAMESPACE='${NAMESPACE:-<unset>}'"
echo " PROLE_MODE='${PROLE_MODE:-<unset>}'"
echo ""
echo "--- Step 2: init_gitlab.sh line 13 assignment ---"
NAMESPACE="${GITLAB_NAMESPACE:-gitlab}"
echo " After: NAMESPACE='$NAMESPACE' (from GITLAB_NAMESPACE='${GITLAB_NAMESPACE:-<unset>}' or default 'gitlab')"
echo ""
echo "--- Step 3: Simulated --namespace arg (as milestones.py would pass) ---"
ARG_NS="gitlab"
NAMESPACE="$ARG_NS"
echo " After --namespace arg: NAMESPACE='$NAMESPACE'"
echo ""
echo "--- Step 4: cfg-based lookup ---"
echo " CFG_PATH='$CFG_PATH'"
maybe_gitlab="$(_prole_cfg_extract_key "$CFG_PATH" "GITLAB_NAMESPACE")"
maybe_gitops="$(_prole_cfg_extract_key "$CFG_PATH" "GITOPS_NAMESPACE")"
echo " _prole_cfg_extract_key GITLAB_NAMESPACE => '$maybe_gitlab'"
echo " _prole_cfg_extract_key GITOPS_NAMESPACE => '$maybe_gitops'"
echo ""
echo "--- Step 5: prole_cfg.sh env-based lookups ---"
echo " Checking if prole_cfg.sh sets any vars..."
set | grep -E "^(NAMESPACE|GITLAB|GITOPS)" | sort || true
echo ""
echo "--- Step 6: Final NAMESPACE after all logic ---"
# Apply the new fixed logic
if [[ -z "$NAMESPACE" || "$NAMESPACE" == "gitlab" ]] && [[ -n "$CFG_PATH" ]]; then
cfg_gitlab="$(_prole_cfg_extract_key "$CFG_PATH" "GITLAB_NAMESPACE")"
[[ -n "$cfg_gitlab" ]] && NAMESPACE="$cfg_gitlab"
fi
NAMESPACE="${NAMESPACE:-gitlab}"
echo " FINAL NAMESPACE='$NAMESPACE'"
echo ""
echo "--- Step 7: Simulate what milestones.py sets in env ---"
echo " (milestones.py line 971: env['GITLAB_NAMESPACE'] = ns where ns='gitlab')"
echo " So GITLAB_NAMESPACE would be 'gitlab' when the real script runs"
echo ""
echo "=== VERDICT ==="
if [[ "$NAMESPACE" == "gitlab" ]]; then
echo " OK: NAMESPACE='$NAMESPACE' ← CORRECT"
else
echo " BUG: NAMESPACE='$NAMESPACE' ← WRONG (expected 'gitlab')"
fi

Some files were not shown because too many files have changed in this diff Show More