diff --git a/controller/deploy/operator/cmd/main.go b/controller/deploy/operator/cmd/main.go index 8f66cbe81..03f827e46 100644 --- a/controller/deploy/operator/cmd/main.go +++ b/controller/deploy/operator/cmd/main.go @@ -228,6 +228,7 @@ func main() { Scheme: mgr.GetScheme(), EndpointReconciler: endpoints.NewReconciler(mgr.GetClient(), mgr.GetScheme(), mgr.GetConfig()), Recorder: mgr.GetEventRecorderFor("jumpstarter-operator"), + Version: version, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Jumpstarter") os.Exit(1) diff --git a/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go b/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go index 2e4c5eaaf..38afde2f6 100644 --- a/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go +++ b/controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go @@ -63,6 +63,21 @@ type JumpstarterReconciler struct { Scheme *runtime.Scheme EndpointReconciler *endpoints.Reconciler Recorder record.EventRecorder + Version string +} + +// resolveImage replaces the :latest tag with the operator's own version tag. +// If the operator version is unknown ("dev") or the image uses a non-latest tag +// (admin override), the image is returned unchanged. +func (r *JumpstarterReconciler) resolveImage(image string) string { + if r.Version == "" || r.Version == "dev" { + return image + } + version := strings.TrimPrefix(r.Version, "v") + if base, ok := strings.CutSuffix(image, ":latest"); ok { + return base + ":" + version + } + return image } // +kubebuilder:rbac:groups=operator.jumpstarter.dev,resources=jumpstarters,verbs=get;list;watch;create;update;patch;delete @@ -816,7 +831,7 @@ func (r *JumpstarterReconciler) createControllerDeployment(jumpstarter *operator Containers: []corev1.Container{ { Name: "manager", - Image: jumpstarter.Spec.Controller.Image, + Image: r.resolveImage(jumpstarter.Spec.Controller.Image), ImagePullPolicy: jumpstarter.Spec.Controller.ImagePullPolicy, Args: []string{ "--leader-elect", @@ -1013,7 +1028,7 @@ func (r *JumpstarterReconciler) createRouterDeployment(jumpstarter *operatorv1al Containers: []corev1.Container{ { Name: "router", - Image: jumpstarter.Spec.Routers.Image, + Image: r.resolveImage(jumpstarter.Spec.Routers.Image), ImagePullPolicy: jumpstarter.Spec.Routers.ImagePullPolicy, Command: []string{"/router"}, Env: envVars,