fix(setup): stop the login gate sending players to the old console after a re-domain
Changing root_domain updated felis.toml and the panel, but the login gate kept pointing players at the hostname it was created with. FELIS_ROOT_DOMAIN and FELIS_PANEL_HOSTNAME are baked into the login MinecraftServer at provisioning time, FelisLimboPlugin reads them to build the link an unauthenticated player is told to open, and ensureSystemServers is create-if-absent — so nothing in the install ever rewrote them. On the demo host the CR still carried console.159.223.32.51.nip.io hours after the domain had moved to mc.flyemoji.network: every joining player was handed a link that bypasses the tunnel, hits the node directly and trips a certificate warning, on the one screen someone with no account is guaranteed to see. setup now converges these values on an existing system service instead of skipping it. Create-if-absent stays the rule for everything else, and the comment on it is still true — an operator's edits to a system service must survive a re-run. These three names are the exception because they are not the operator's to own: they are a copy of config that is wrong the moment config changes, and there is no other writer who could notice. The convergence is deliberately narrow. Only a name already present with a different value is rewritten, so env the operator added by hand is untouched and the rest of the spec — image, memory, storage — is not read at all. A derived name that is absent from the live object is left absent rather than added back: a deliberate removal and drift look identical from here, and re-adding it would mean fighting the operator on every run. The outcome string reports the refresh so a setup run does not silently rewrite the front door. This closes one surface of a re-domain, not the whole of it. The write-once panel certificate at deploy/bootstrap.sh keeps its old SANs, and so do the Velocity config and the forwarding material; the warning in bootstrap.sh that says so is still accurate. What changes is that the surface players actually walk through now catches up when setup is re-run. Checks: a login gate built with the old domain converges onto the new one and says so; an env var the operator added and a hand-raised javaMemory both survive that same run; and an install whose config already matches reports no refresh, so a routine setup does not read like a re-domain. The middle one is the one worth having — converging config must not turn into a licence to clobber the edits create-if-absent exists to protect.
This commit is contained in:
2 files changed
+164
-1
No files matched your search
@@ -308,7 +308,16 @@ func ensureSystemServers(ctx context.Context, cl client.Client, namespace, login
|
||||
})
|
||||
continue
|
||||
}
|
||||
outcomes = append(outcomes, systemServerOutcome{name: p.name, available: true, skipped: "already exists"})
|
||||
refreshed, err := refreshDerivedEnv(ctx, cl, &existing, ms)
|
||||
if err != nil {
|
||||
outcomes = append(outcomes, systemServerOutcome{name: p.name, err: err})
|
||||
continue
|
||||
}
|
||||
skipped := "already exists"
|
||||
if refreshed {
|
||||
skipped = "already exists; refreshed the console hostnames it points players at"
|
||||
}
|
||||
outcomes = append(outcomes, systemServerOutcome{name: p.name, available: true, skipped: skipped})
|
||||
continue
|
||||
}
|
||||
if !apierrors.IsNotFound(getErr) {
|
||||
@@ -344,6 +353,55 @@ func ensureSystemServers(ctx context.Context, cl client.Client, namespace, login
|
||||
return outcomes
|
||||
}
|
||||
|
||||
// derivedSystemEnv are the system-server env vars whose values setup computes from
|
||||
// config rather than inventing. They are the exception to create-if-absent, and the
|
||||
// exception is narrow on purpose.
|
||||
//
|
||||
// Everything else on an existing system service is left alone so an operator's edits
|
||||
// survive a re-run — but these are not the operator's to own, they are a copy of
|
||||
// config that goes stale the moment config changes. That is not hypothetical: after
|
||||
// a root-domain change the login gate keeps handing every joining player a console
|
||||
// link built from the OLD domain, which is the one screen an unauthenticated player
|
||||
// is guaranteed to see. Nothing else in the install rewrites them, so a re-run of
|
||||
// setup is the only chance they get to catch up.
|
||||
var derivedSystemEnv = map[string]bool{
|
||||
envAPIBaseURL: true,
|
||||
envRootDomain: true,
|
||||
envPanelHostname: true,
|
||||
}
|
||||
|
||||
// refreshDerivedEnv converges the config-derived env of an existing system server
|
||||
// onto what setup just computed, and reports whether anything actually changed.
|
||||
//
|
||||
// It only ever overwrites a name that is already present with a different value, and
|
||||
// only for the names above: env the operator added by hand is untouched, and a name
|
||||
// missing from the live object is left missing rather than added back, since a
|
||||
// deliberate removal is indistinguishable from drift and re-adding it would fight the
|
||||
// operator every run.
|
||||
func refreshDerivedEnv(ctx context.Context, cl client.Client, existing, desired *v1alpha1.MinecraftServer) (bool, error) {
|
||||
want := make(map[string]string, len(derivedSystemEnv))
|
||||
for _, e := range desired.Spec.Env {
|
||||
if derivedSystemEnv[e.Name] {
|
||||
want[e.Name] = e.Value
|
||||
}
|
||||
}
|
||||
|
||||
changed := false
|
||||
for i, e := range existing.Spec.Env {
|
||||
if v, ok := want[e.Name]; ok && v != e.Value {
|
||||
existing.Spec.Env[i].Value = v
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
return false, nil
|
||||
}
|
||||
if err := cl.Update(ctx, existing); err != nil {
|
||||
return false, fmt.Errorf("refresh %s env: %w", existing.Name, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// The login gate is a hard prerequisite of the Owner bind, so setup waits for it
|
||||
// rather than racing it. The ceiling covers a cold image pull on a fresh node;
|
||||
// the poll is fast enough that a warm start feels immediate.
|
||||
|
||||
Reference in new issue
Block a user