mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
feat(multiplayer): report process-ready to the control plane from the supervisor
Add opt-in control-plane registration to server/supervisor: once Agones
Ready succeeds, POST /v1/servers/{id}/register (assignment_ready=false)
using a workload token read fresh from disk each call -- matching how a
Kubernetes projected service account token is rotated in place by
kubelet, unlike a cached/env-var secret. ControlPlaneURL empty (the
default) is a total no-op, so direct/Compose mode and allocated-without-
control-plane mode are both byte-for-byte unaffected; New() rejects a
half-configured registration (URL set without token path/server/match/
digest) rather than silently skipping it.
ServerID/MatchID/ImageDigest are read from env vars named by CLI flags
(--server-id-env, --match-id-env, --image-digest-env), matching the
existing --drain-token-env convention in this same binary, rather than
parsed out of the Agones SDK's own GameServer JSON -- that shape isn't
independently verifiable from here, whereas the Kubernetes Downward API
(fieldRef: metadata.name) populating an env var is a standard, safe
pattern already used elsewhere in this codebase for exactly this class
of secret.
A registration failure now kills the child (matching the existing
waitReady failure path) rather than leaving Agones-Ready-but-
control-plane-unregistered process running -- a real gap the second new
test (TestControlPlaneRegistrationFailureKillsChildRatherThanRunningUnregistered)
had to be corrected to actually exercise: its first draft omitted
ReadyURL and was failing at waitReady, before ever reaching the code
path it claimed to test.
This commit is contained in:
@@ -41,6 +41,12 @@ func main() {
|
||||
drainTokenEnv := options.String("drain-token-env", "COSMIC_CLASH_DRAIN_TOKEN", "environment variable containing the drain bearer token")
|
||||
transport := options.String("transport", "enet", "enet or steam_sdr")
|
||||
grace := options.Duration("drain-grace", supervisor.DefaultDrainGrace, "maximum graceful drain duration")
|
||||
controlPlaneURL := options.String("control-plane-url", "", "matchmaking control-plane base URL; empty skips process-ready registration entirely")
|
||||
workloadTokenPath := options.String("workload-token-path", "", "path to the projected workload service-account token, read fresh on every registration call")
|
||||
serverIDEnv := options.String("server-id-env", "COSMIC_CLASH_SERVER_ID", "environment variable containing this GameServer's control-plane server ID (populate via the Kubernetes Downward API, fieldRef: metadata.name)")
|
||||
matchIDEnv := options.String("match-id-env", "COSMIC_CLASH_MATCH_ID", "environment variable containing the allocated match ID")
|
||||
protocolVersion := options.Int("protocol-version", 0, "protocol version reported at registration")
|
||||
imageDigestEnv := options.String("image-digest-env", "COSMIC_CLASH_IMAGE_DIGEST", "environment variable containing this build's sha256 image digest")
|
||||
if err := options.Parse(args[:separator]); err != nil {
|
||||
os.Exit(2)
|
||||
}
|
||||
@@ -57,6 +63,13 @@ func main() {
|
||||
DrainToken: token,
|
||||
Transport: *transport,
|
||||
ReadyTimeout: 30 * time.Second,
|
||||
|
||||
ControlPlaneURL: *controlPlaneURL,
|
||||
WorkloadTokenPath: *workloadTokenPath,
|
||||
ServerID: os.Getenv(*serverIDEnv),
|
||||
MatchID: os.Getenv(*matchIDEnv),
|
||||
ProtocolVersion: *protocolVersion,
|
||||
ImageDigest: os.Getenv(*imageDigestEnv),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "game-server-supervisor: %v\n", err)
|
||||
|
||||
Reference in New Issue
Block a user