6.1 KiB
IntelliJ AI Assistant — Structural Refactor Prompt
You are performing a focused structural refactor on the knoe installer project. Make ONLY the changes described below. Do NOT add features, rename identifiers not listed, or change observable behaviour. After each task, run the existing test suite and stop + report if any tests fail.
TASK A — Split ops/registry.py into mode-specific modules
A1. Create knoe/core/ops/k3d_registry.py
- Move
_ensure_k3d_registry()fromregistry.py - Implement
initialize,start,update,stop,restart,statusfor k3d mode (extract the k3d branches that currently live inside each function inregistry.py) update()calls_ensure_k3d_registry()stop()deletes the k3d registry and the fallback Docker containerstatus()checksk3d registry list
A2. Create knoe/core/ops/k3s_registry.py
- Move
_manifest()and_deployment_is_available()fromregistry.py - Implement
initialize,start,update,stop,restart,statusfor k3s mode (this is the current default fall-through path inregistry.py) update()appliesk8s/registry/deployment.yaml, reconciles ReplicaSets, waits rollout
A3. Create knoe/core/ops/k8s_registry.py
update()/stop()/restart(): log a no-op message and returnstatus(): returnTrue(GCP Artifact Registry is externally managed)initialize()/start(): delegate toupdate()
A4. Rewrite knoe/core/ops/registry.py as a pure dispatcher
from ._services_common import _detect_mode
from types import ModuleType
def _module(mode, env) -> ModuleType:
m = _detect_mode(mode, env)
if m == "k3d":
from . import k3d_registry; return k3d_registry
if m == "k8s":
from . import k8s_registry; return k8s_registry
from . import k3s_registry; return k3s_registry
# initialize / start / update / stop / restart / status
# — each delegates to _module(mode, env).<fn>(**kwargs)
# Public signatures are UNCHANGED.
TASK B — Split ops/garage_store.py into mode-specific modules
B1. Create knoe/core/ops/_garage_common.py
- Move
_garage_namespace()and_ensure_garage_secret()fromgarage_store.py - These helpers are shared by all three mode variants
B2. Create knoe/core/ops/k3s_garage_store.py
- Move
_repair_released_garage_pvs()here (k3s / Synology iSCSI only) _manifest_files()returns:storageclass-synology-iscsi.yaml,iscsi-pvs.yaml,garage-configmap.yaml,garage-statefulset.yaml,garage-service.yamlupdate()calls_repair_released_garage_pvs()before applying manifests- Cluster-scoped resources (no
-nflag):{"storageclass-synology-iscsi.yaml", "iscsi-pvs.yaml"}
B3. Create knoe/core/ops/k3d_garage_store.py
_manifest_files()returns:garage-configmap.yaml,garage-statefulset.yaml,garage-service.yaml(no Synology storage classes, no static PVs)- No PV repair
B4. Create knoe/core/ops/k8s_garage_store.py
_manifest_files()returns:storageclass-gcp-hdd.yaml,garage-configmap.yaml,garage-statefulset-gcp.yaml,garage-service.yaml- No PV repair
- Cluster-scoped:
{"storageclass-gcp-hdd.yaml"}
B5. Rewrite knoe/core/ops/garage_store.py as dispatcher
Same _module() + delegating-function pattern as Task A.
stop() and restart() in garage variants take only namespace, env, log
(no mode parameter — mode is resolved from env).
TASK C — Rename UI nav labels (display text only)
File: knoe/ui/screens/__init__.py
"Kerberos Authentication" → "Knoe Authority" (nav_items; page_id "kerberos_config" unchanged)
"Knoe User Authority" → "Knoe Users" (nav_items; page_id "knoe_users" unchanged)
File: knoe/ui/screens/security.py
- Change the
_render_title("Kerberos Authentication", ...)call →_render_title("Knoe Authority", ...) - Change
text="Enable Kerberos Authentication"→text="Enable Knoe Authority" - Do NOT change
self.knoe_cfg_data["Kerberos Authentication"]keys — those are config-file section names
File: knoe/ui/screens/knoe_users.py
- Update any user-facing title Label text that still reads "Knoe User Authority"
- Do NOT change log prefixes or cfg/env key names
TASK D — Add k3d | k3s | k8s mode tab strip to sidebar
File: knoe/ui/screens/__init__.py — in __init__, after self.nav_widgets = {}:
self._mode_tab_widgets: dict = {}
self.deployment_mode = tk.StringVar(value=os.environ.get("KNOE_MODE", "k3s"))
File: knoe/ui/screens/navigation.py — in _create_sidebar_nav(),
before the "INSTALLER" Label, insert:
_MODE_COLORS = {"k3d": "#4A90D9", "k3s": "#27AE60", "k8s": "#E67E22"}
mode_frame = tk.Frame(self.sidebar, bg="#F5F5DC")
mode_frame.pack(fill="x", padx=12, pady=(14, 4))
for label, value in [("k3d", "k3d"), ("k3s", "k3s"), ("k8s", "k8s")]:
btn = tk.Label(
mode_frame, text=label,
bg="#D5D5C5", fg="#555",
font=("SF Pro Text", 9, "bold"),
padx=8, pady=3, cursor="hand2",
)
btn.pack(side="left", padx=2)
btn.bind("<Button-1>", lambda e, v=value: self._set_deployment_mode(v))
self._mode_tab_widgets[value] = btn
self._refresh_mode_tabs()
Add to the navigation mixin:
def _set_deployment_mode(self, mode: str) -> None:
self.deployment_mode.set(mode)
os.environ["KNOE_MODE"] = mode
self._refresh_mode_tabs()
def _refresh_mode_tabs(self) -> None:
_MODE_COLORS = {"k3d": "#4A90D9", "k3s": "#27AE60", "k8s": "#E67E22"}
active = self.deployment_mode.get()
for value, widget in self._mode_tab_widgets.items():
if value == active:
widget.configure(bg=_MODE_COLORS[value], fg="white")
else:
widget.configure(bg="#D5D5C5", fg="#555")
CONSTRAINTS
- All existing import paths must remain valid (
from knoe.core.ops import registryetc.) - All public function signatures are unchanged
- Run tests after each task; stop and report failures before continuing
- Do not create README or documentation files (other than this prompt file)
- Do not touch any files not listed above