api+ui: kind-scoped save/delete endpoints and links
API: /config/{services,jobs,tools,static}/{name} now pin the twin they
target — _save_deployment/_delete_deployment take an explicit kind so a
patch to a 'backup' service can't bleed into a 'backup' job/tool. Add
/tools and /static endpoints; keep /deployments/{name} kind-agnostic.
New test_kind_twins proves per-kind save/delete isolation on disk.
UI: ConfigPanel and CreateDeploymentForm write to the kind-scoped
resource; GatewayPanel/NodeDetail/DeploymentsSection link via a shared
detailPath(name, kind) helper instead of the ambiguous /deployment/:name.
Includes incidental ruff-format reflow of untouched api files.
This commit is contained in:
@@ -154,7 +154,9 @@ def _summary_from_service(
|
||||
)
|
||||
|
||||
|
||||
def _summary_from_job(name: str, job: SystemdDeployment, config: object) -> DeploymentSummary:
|
||||
def _summary_from_job(
|
||||
name: str, job: SystemdDeployment, config: object
|
||||
) -> DeploymentSummary:
|
||||
"""Build a DeploymentSummary from a systemd deployment (job, non-deployed)."""
|
||||
managed = bool(job.manage and job.manage.systemd and job.manage.systemd.enable)
|
||||
|
||||
@@ -280,7 +282,9 @@ def _service_from_deployed(name: str, deployed: object) -> ServiceSummary:
|
||||
)
|
||||
|
||||
|
||||
def _service_from_spec(name: str, svc: SystemdDeployment, config: object) -> ServiceSummary:
|
||||
def _service_from_spec(
|
||||
name: str, svc: SystemdDeployment, config: object
|
||||
) -> ServiceSummary:
|
||||
"""Build a ServiceSummary from a systemd deployment."""
|
||||
port = None
|
||||
health_path = None
|
||||
@@ -911,7 +915,8 @@ def get_gateway() -> GatewayInfo:
|
||||
# is not a service, so filtering to services dropped its public_url (calculator).
|
||||
public_domain = registry.node.public_domain
|
||||
public_names = {
|
||||
name for _k, name, dep in (config.all_deployments() if config else [])
|
||||
name
|
||||
for _k, name, dep in (config.all_deployments() if config else [])
|
||||
if getattr(dep, "public", False)
|
||||
}
|
||||
|
||||
@@ -937,7 +942,8 @@ def get_gateway() -> GatewayInfo:
|
||||
tunnel_connected = (
|
||||
subprocess.run(
|
||||
["systemctl", "--user", "is-active", "castle-castle-tunnel.service"],
|
||||
capture_output=True, text=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
).stdout.strip()
|
||||
== "active"
|
||||
)
|
||||
@@ -970,7 +976,7 @@ def save_gateway_config(request: GatewayConfigRequest) -> dict[str, str]:
|
||||
from castle_core.config import load_config, save_config
|
||||
|
||||
config = load_config(root)
|
||||
norm = lambda v: (v or None) # noqa: E731 — empty string clears
|
||||
norm = lambda v: v or None # noqa: E731 — empty string clears
|
||||
config.gateway.tls = norm(request.tls)
|
||||
config.gateway.domain = norm(request.domain)
|
||||
config.gateway.public_domain = norm(request.public_domain)
|
||||
|
||||
Reference in New Issue
Block a user