hub v0.15.0: Phase 2 managed updates — per-customer controller-version floor
Operator sets a minimum controller version (FLOOR), per-customer defaulting to a
global floor; the report ACK returns the effective floor + latest_version so the
controller auto-updates to the floor when below it (latest stays the opt-in button).
- store: min_controller_version column + hub_settings global floor + Effective/
Get/SetGlobal/SetMin resolution + config/env DEFAULT_MIN_CONTROLLER_VERSION
- handler: report ACK {min_controller_version, latest_version}; LatestVersionProvider
- web: global floor editor + per-customer override form + Floor column (English)
- tests: floor resolution + ACK + render; override-precedence red-proof verified
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSZmmSFVzGwEzhYmxbkgBK
This commit is contained in:
@@ -58,6 +58,13 @@ type Config struct {
|
||||
Listen string `yaml:"listen"`
|
||||
DataDir string `yaml:"data_dir"`
|
||||
} `yaml:"server"`
|
||||
ControllerUpdates struct {
|
||||
// DefaultMinVersion is the global controller-version FLOOR fallback (Phase 2 managed updates):
|
||||
// the minimum controller version any customer's box auto-updates to, unless overridden
|
||||
// per-customer or via the operator UI (hub_settings). Empty = no global floor. Env-overridable
|
||||
// with DEFAULT_MIN_CONTROLLER_VERSION.
|
||||
DefaultMinVersion string `yaml:"default_min_version"`
|
||||
} `yaml:"controller_updates"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -83,6 +90,9 @@ func main() {
|
||||
if v := os.Getenv("REGISTRY_TOKEN"); v != "" {
|
||||
cfg.Registry.Token = v
|
||||
}
|
||||
if v := os.Getenv("DEFAULT_MIN_CONTROLLER_VERSION"); v != "" {
|
||||
cfg.ControllerUpdates.DefaultMinVersion = v
|
||||
}
|
||||
|
||||
// Ensure data dir exists
|
||||
os.MkdirAll(cfg.Server.DataDir, 0755)
|
||||
@@ -96,6 +106,13 @@ func main() {
|
||||
defer dataStore.Close()
|
||||
logger.Printf("[INFO] Database opened at %s", dbPath)
|
||||
|
||||
// Phase 2 managed updates: seed the global controller-version floor fallback (config/env). A
|
||||
// hub_settings row set via the operator UI overrides this at runtime.
|
||||
dataStore.SetDefaultMinControllerVersion(cfg.ControllerUpdates.DefaultMinVersion)
|
||||
if cfg.ControllerUpdates.DefaultMinVersion != "" {
|
||||
logger.Printf("[INFO] Default controller-version floor: %s", cfg.ControllerUpdates.DefaultMinVersion)
|
||||
}
|
||||
|
||||
// Parse stale threshold
|
||||
staleThreshold, err := time.ParseDuration(cfg.Alerting.StaleThreshold)
|
||||
if err != nil {
|
||||
@@ -192,6 +209,11 @@ func main() {
|
||||
logger.Printf("[INFO] Registry version checker disabled (no credentials configured)")
|
||||
}
|
||||
webServer.SetVersionChecker(versionChecker)
|
||||
// Advertise latest on the controller report ACK (Phase 2). Guard the nil case so we don't store a
|
||||
// non-nil interface wrapping a nil *VersionChecker.
|
||||
if versionChecker != nil {
|
||||
apiHandler.SetLatestVersionProvider(versionChecker)
|
||||
}
|
||||
|
||||
// Session cleanup — removes expired sessions every hour
|
||||
go webServer.CleanupSessions(ctx)
|
||||
|
||||
Reference in New Issue
Block a user