diff --git a/cmd/hyperconverged-cluster-operator/main.go b/cmd/hyperconverged-cluster-operator/main.go index 3b2a18580c..efd8ac3906 100644 --- a/cmd/hyperconverged-cluster-operator/main.go +++ b/cmd/hyperconverged-cluster-operator/main.go @@ -120,7 +120,7 @@ func main() { needLeaderElection := !ci.IsRunningLocally() // Create a new Cmd to provide shared dependencies and start components - mgr, err := manager.New(cfg, getManagerOptions(operatorNamespace, needLeaderElection, ci.IsMonitoringAvailable(), ci.IsOpenshift(), scheme)) + mgr, err := manager.New(cfg, getManagerOptions(operatorNamespace, needLeaderElection, ci.IsMonitoringAvailable(), ci.IsNativeOpenshift(), ci.HasOpenshiftConsole(), scheme)) cmdHelper.ExitOnError(err, "can't initiate manager") // register pprof instrumentation if HCO_PPROF_ADDR is set @@ -192,7 +192,7 @@ func main() { // Restricts the cache's ListWatch to specific fields/labels per GVK at the specified object to control the memory impact // this is used to completely overwrite the NewCache function so all the interesting objects should be explicitly listed here -func getCacheOption(operatorNamespace string, isMonitoringAvailable, isOpenshift bool) cache.Options { +func getCacheOption(operatorNamespace string, isMonitoringAvailable, isNativeOpenshift bool, hasOpenshiftConsole bool) cache.Options { namespaceSelector := fields.Set{"metadata.namespace": operatorNamespace}.AsSelector() labelSelector := labels.Set{hcoutil.AppLabel: hcoutil.HyperConvergedName}.AsSelector() labelSelectorForNamespace := labels.Set{hcoutil.KubernetesMetadataName: operatorNamespace}.AsSelector() @@ -247,14 +247,7 @@ func getCacheOption(operatorNamespace string, isMonitoringAvailable, isOpenshift }, } - cacheOptionsByOjectForOpenshift := map[client.Object]cache.ByObject{ - &openshiftroutev1.Route{}: { - Field: namespaceSelector, - }, - &imagev1.ImageStream{}: { - Label: labelSelector, - }, - &openshiftconfigv1.APIServer{}: {}, + cacheOptionsByOjectForOpenshiftConsole := map[client.Object]cache.ByObject{ &consolev1.ConsoleCLIDownload{}: { Label: labelSelector, }, @@ -266,18 +259,31 @@ func getCacheOption(operatorNamespace string, isMonitoringAvailable, isOpenshift }, } + cacheOptionsByOjectForNativeOpenshift := map[client.Object]cache.ByObject{ + &openshiftroutev1.Route{}: { + Field: namespaceSelector, + }, + &imagev1.ImageStream{}: { + Label: labelSelector, + }, + &openshiftconfigv1.APIServer{}: {}, + } + if isMonitoringAvailable { maps.Copy(cacheOptions.ByObject, cacheOptionsByOjectForMonitoring) } - if isOpenshift { - maps.Copy(cacheOptions.ByObject, cacheOptionsByOjectForOpenshift) + if isNativeOpenshift { + maps.Copy(cacheOptions.ByObject, cacheOptionsByOjectForNativeOpenshift) + } + if hasOpenshiftConsole { + maps.Copy(cacheOptions.ByObject, cacheOptionsByOjectForOpenshiftConsole) } return cacheOptions } -func getManagerOptions(operatorNamespace string, needLeaderElection, isMonitoringAvailable, isOpenshift bool, scheme *apiruntime.Scheme) manager.Options { +func getManagerOptions(operatorNamespace string, needLeaderElection, isMonitoringAvailable, isNativeOpenshift bool, hasOpenshiftConsole bool, scheme *apiruntime.Scheme) manager.Options { return manager.Options{ Metrics: server.Options{ BindAddress: fmt.Sprintf("%s:%d", hcoutil.MetricsHost, hcoutil.MetricsPort), @@ -292,7 +298,7 @@ func getManagerOptions(operatorNamespace string, needLeaderElection, isMonitorin // "configmapsleases". Therefore, having only "leases" should be safe now. LeaderElectionResourceLock: resourcelock.LeasesResourceLock, LeaderElectionID: "hyperconverged-cluster-operator-lock", - Cache: getCacheOption(operatorNamespace, isMonitoringAvailable, isOpenshift), + Cache: getCacheOption(operatorNamespace, isMonitoringAvailable, isNativeOpenshift, hasOpenshiftConsole), Scheme: scheme, } } diff --git a/cmd/hyperconverged-cluster-webhook/main.go b/cmd/hyperconverged-cluster-webhook/main.go index 5c0e3663a0..c2ac72c668 100644 --- a/cmd/hyperconverged-cluster-webhook/main.go +++ b/cmd/hyperconverged-cluster-webhook/main.go @@ -165,7 +165,7 @@ func main() { err = webhookscontrollers.RegisterReconciler(mgr, ci) cmdHelper.ExitOnError(err, "Cannot register APIServer reconciler") - if err = webhooks.SetupWebhookWithManager(ctx, mgr, ci.IsOpenshift(), hcoTLSSecurityProfile); err != nil { + if err = webhooks.SetupWebhookWithManager(ctx, mgr, ci.HasOpenshiftConsole(), hcoTLSSecurityProfile); err != nil { logger.Error(err, "unable to create webhook", "webhook", "HyperConverged") eventEmitter.EmitEvent(nil, corev1.EventTypeWarning, "InitError", "Unable to create webhook") os.Exit(1) diff --git a/controllers/alerts/rbac.go b/controllers/alerts/rbac.go index f7c2c9c596..679e01e98a 100644 --- a/controllers/alerts/rbac.go +++ b/controllers/alerts/rbac.go @@ -191,7 +191,7 @@ func newRoleBinding(owner metav1.OwnerReference, namespace string, ci hcoutil.Cl } func getMonitoringNamespace(ci hcoutil.ClusterInfo) string { - if ci.IsOpenshift() { + if ci.IsNativeOpenshift() { return openshiftMonitoringNamespace } diff --git a/controllers/commontestutils/testUtils.go b/controllers/commontestutils/testUtils.go index 4b554f292e..530126c91f 100644 --- a/controllers/commontestutils/testUtils.go +++ b/controllers/commontestutils/testUtils.go @@ -282,7 +282,10 @@ type ClusterInfoMock struct{} func (ClusterInfoMock) Init(_ context.Context, _ client.Client, _ logr.Logger) error { return nil } -func (ClusterInfoMock) IsOpenshift() bool { +func (ClusterInfoMock) IsNativeOpenshift() bool { + return true +} +func (ClusterInfoMock) HasOpenshiftConsole() bool { return true } func (ClusterInfoMock) IsRunningLocally() bool { @@ -339,7 +342,10 @@ type ClusterInfoSNOMock struct{} func (ClusterInfoSNOMock) Init(_ context.Context, _ client.Client, _ logr.Logger) error { return nil } -func (ClusterInfoSNOMock) IsOpenshift() bool { +func (ClusterInfoSNOMock) IsNativeOpenshift() bool { + return true +} +func (ClusterInfoSNOMock) HasOpenshiftConsole() bool { return true } func (ClusterInfoSNOMock) IsRunningLocally() bool { @@ -396,7 +402,10 @@ type ClusterInfoSRCPHAIMock struct{} func (ClusterInfoSRCPHAIMock) Init(_ context.Context, _ client.Client, _ logr.Logger) error { return nil } -func (ClusterInfoSRCPHAIMock) IsOpenshift() bool { +func (ClusterInfoSRCPHAIMock) IsNativeOpenshift() bool { + return true +} +func (ClusterInfoSRCPHAIMock) HasOpenshiftConsole() bool { return true } func (ClusterInfoSRCPHAIMock) IsRunningLocally() bool { diff --git a/controllers/hyperconverged/hyperconverged_controller.go b/controllers/hyperconverged/hyperconverged_controller.go index 82a71fca8d..13141f8a97 100644 --- a/controllers/hyperconverged/hyperconverged_controller.go +++ b/controllers/hyperconverged/hyperconverged_controller.go @@ -195,19 +195,24 @@ func add(mgr manager.Manager, r reconcile.Reconciler, ci hcoutil.ClusterInfo) er &monitoringv1.PrometheusRule{}, }...) } - if ci.IsOpenshift() { + if ci.HasOpenshiftConsole() { + // TODO: Ensure we need all of these secondaryResources = append(secondaryResources, []client.Object{ &sspv1beta2.SSP{}, &corev1.Service{}, - &routev1.Route{}, &consolev1.ConsoleCLIDownload{}, &consolev1.ConsoleQuickStart{}, &consolev1.ConsolePlugin{}, - &imagev1.ImageStream{}, &corev1.Namespace{}, &appsv1.Deployment{}, }...) } + if ci.IsNativeOpenshift() { + secondaryResources = append(secondaryResources, []client.Object{ + &routev1.Route{}, + &imagev1.ImageStream{}, + }...) + } // Watch secondary resources for _, resource := range secondaryResources { @@ -234,7 +239,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler, ci hcoutil.ClusterInfo) er return err } - if ci.IsOpenshift() { + if ci.IsNativeOpenshift() { // Watch openshiftconfigv1.APIServer separately msg := "Reconciling for openshiftconfigv1.APIServer" diff --git a/controllers/operands/operandHandler.go b/controllers/operands/operandHandler.go index eb9f1abe42..024742f5f1 100644 --- a/controllers/operands/operandHandler.go +++ b/controllers/operands/operandHandler.go @@ -59,16 +59,19 @@ func NewOperandHandler(client client.Client, scheme *runtime.Scheme, ci hcoutil. newAAQHandler(client, scheme), } - if ci.IsOpenshift() { + if ci.HasOpenshiftConsole() { operands = append(operands, []Operand{ (*genericOperand)(newSspHandler(client, scheme)), (*genericOperand)(newCliDownloadHandler(client, scheme)), - (*genericOperand)(newCliDownloadsRouteHandler(client, scheme)), (*genericOperand)(newServiceHandler(client, scheme, NewCliDownloadsService)), }...) } - if ci.IsOpenshift() && ci.IsConsolePluginImageProvided() { + if ci.IsNativeOpenshift() { + operands = append(operands, (*genericOperand)(newCliDownloadsRouteHandler(client, scheme))) + } + + if ci.HasOpenshiftConsole() && ci.IsConsolePluginImageProvided() { operands = append(operands, newConsoleHandler(client)) operands = append(operands, (*genericOperand)(newServiceHandler(client, scheme, NewKvUIPluginSvc))) operands = append(operands, (*genericOperand)(newServiceHandler(client, scheme, NewKvUIProxySvc))) @@ -90,16 +93,19 @@ func NewOperandHandler(client client.Client, scheme *runtime.Scheme, ci hcoutil. // Initial operations that need to read/write from the cluster can only be done when the client is already working. func (h *OperandHandler) FirstUseInitiation(scheme *runtime.Scheme, ci hcoutil.ClusterInfo, hc *hcov1beta1.HyperConverged) { h.objects = make([]client.Object, 0) - if ci.IsOpenshift() { + if ci.HasOpenshiftConsole() { h.addOperands(scheme, hc, getQuickStartHandlers) h.addOperands(scheme, hc, getDashboardHandlers) - h.addOperands(scheme, hc, getImageStreamHandlers) h.addOperands(scheme, hc, newVirtioWinCmHandler) h.addOperands(scheme, hc, newVirtioWinCmReaderRoleHandler) h.addOperands(scheme, hc, newVirtioWinCmReaderRoleBindingHandler) } + + if ci.IsNativeOpenshift() { + h.addOperands(scheme, hc, getImageStreamHandlers) + } - if ci.IsOpenshift() && ci.IsConsolePluginImageProvided() { + if ci.HasOpenshiftConsole() && ci.IsConsolePluginImageProvided() { h.addOperands(scheme, hc, newKvUIPluginDeploymentHandler) h.addOperands(scheme, hc, newKvUIProxyDeploymentHandler) h.addOperands(scheme, hc, newKvUINginxCMHandler) diff --git a/controllers/webhooks/controller.go b/controllers/webhooks/controller.go index 876bd6a5cc..b08dace630 100644 --- a/controllers/webhooks/controller.go +++ b/controllers/webhooks/controller.go @@ -42,7 +42,7 @@ func (r *ReconcileAPIServer) Reconcile(ctx context.Context, _ reconcile.Request) // RegisterReconciler creates a new HyperConverged Reconciler and registers it into manager. func RegisterReconciler(mgr manager.Manager, ci hcoutil.ClusterInfo) error { - if ci.IsOpenshift() { + if ci.IsNativeOpenshift() { return add(mgr, newReconciler(mgr, ci)) } return nil diff --git a/pkg/util/cluster.go b/pkg/util/cluster.go index d74c2ccddb..2bd3a2c9c2 100644 --- a/pkg/util/cluster.go +++ b/pkg/util/cluster.go @@ -25,7 +25,8 @@ import ( type ClusterInfo interface { Init(ctx context.Context, cl client.Client, logger logr.Logger) error - IsOpenshift() bool + IsNativeOpenshift() bool + HasOpenshiftConsole() bool IsRunningLocally() bool GetDomain() string GetBaseDomain() string @@ -43,7 +44,8 @@ type ClusterInfo interface { } type ClusterInfoImp struct { - runningInOpenshift bool + runningInNativeOpenshift bool + runningWithOpenshiftConsole bool managedByOLM bool runningLocally bool controlPlaneHighlyAvailable bool @@ -78,7 +80,7 @@ func (c *ClusterInfoImp) Init(ctx context.Context, cl client.Client, logger logr // We assume that this Operator is managed by OLM when this variable is present. _, c.managedByOLM = os.LookupEnv(OperatorConditionNameEnvVar) - if c.runningInOpenshift { + if c.runningInNativeOpenshift { err = c.initOpenshift(ctx, cl) } else { err = c.initKubernetes(cl) @@ -86,7 +88,7 @@ func (c *ClusterInfoImp) Init(ctx context.Context, cl client.Client, logger logr if err != nil { return err } - if c.runningInOpenshift && c.singlestackipv6 { + if c.runningInNativeOpenshift && c.singlestackipv6 { metrics.SetHCOMetricSingleStackIPv6True() } @@ -179,8 +181,12 @@ func (c *ClusterInfoImp) IsManagedByOLM() bool { return c.managedByOLM } -func (c *ClusterInfoImp) IsOpenshift() bool { - return c.runningInOpenshift +func (c *ClusterInfoImp) IsNativeOpenshift() bool { + return c.runningInNativeOpenshift +} + +func (c *ClusterInfoImp) HasOpenshiftConsole() bool { + return c.runningInNativeOpenshift || c.runningWithOpenshiftConsole } func (c *ClusterInfoImp) IsConsolePluginImageProvided() bool { @@ -268,8 +274,9 @@ func isCRDExists(ctx context.Context, cl client.Client, crdName string) bool { func init() { clusterInfo = &ClusterInfoImp{ - runningLocally: IsRunModeLocal(), - runningInOpenshift: false, + runningLocally: IsRunModeLocal(), + runningInNativeOpenshift: false, + runningWithOpenshiftConsole: false, } } @@ -284,14 +291,16 @@ func (c *ClusterInfoImp) queryCluster(ctx context.Context, cl client.Client) err var gdferr *discovery.ErrGroupDiscoveryFailed if meta.IsNoMatchError(err) || apierrors.IsNotFound(err) || errors.As(err, &gdferr) { // Not on OpenShift - c.runningInOpenshift = false + c.runningInNativeOpenshift = false c.logger.Info("Cluster type = kubernetes") + c.runningWithOpenshiftConsole = isCRDExists(ctx, cl, OpenShiftConsolePluginCRDName) } else { c.logger.Error(err, "Failed to get ClusterVersion") return err } } else { - c.runningInOpenshift = true + c.runningInNativeOpenshift = true + c.runningWithOpenshiftConsole = true c.logger.Info("Cluster type = openshift", "version", clusterVersion.Status.Desired.Version) c.domain, err = getClusterDomain(ctx, cl) if err != nil { @@ -318,7 +327,7 @@ func (c *ClusterInfoImp) GetTLSSecurityProfile(hcoTLSSecurityProfile *openshiftc } func (c *ClusterInfoImp) RefreshAPIServerCR(ctx context.Context, cl client.Client) error { - if c.IsOpenshift() { + if c.IsNativeOpenshift() { instance := &openshiftconfigv1.APIServer{} key := client.ObjectKey{Namespace: UndefinedNamespace, Name: APIServerCRName} diff --git a/pkg/util/consts.go b/pkg/util/consts.go index 406cca85f1..8ba3617285 100644 --- a/pkg/util/consts.go +++ b/pkg/util/consts.go @@ -21,6 +21,7 @@ const ( HcoMutatingWebhookNS = "mutate-ns-hco.kubevirt.io" PrometheusRuleCRDName = "prometheusrules.monitoring.coreos.com" ServiceMonitorCRDName = "servicemonitors.monitoring.coreos.com" + OpenShiftConsolePluginCRDName = "consoleplugins.console.openshift.io" HcoMutatingWebhookHyperConverged = "mutate-hyperconverged-hco.kubevirt.io" AppLabel = "app" UndefinedNamespace = "" diff --git a/pkg/webhooks/setup.go b/pkg/webhooks/setup.go index 51c1ea4e55..f668abc996 100644 --- a/pkg/webhooks/setup.go +++ b/pkg/webhooks/setup.go @@ -28,7 +28,7 @@ var ( logger = logf.Log.WithName("webhook-setup") ) -func SetupWebhookWithManager(ctx context.Context, mgr ctrl.Manager, isOpenshift bool, hcoTLSSecurityProfile *openshiftconfigv1.TLSSecurityProfile) error { +func SetupWebhookWithManager(ctx context.Context, mgr ctrl.Manager, isOpenshiftConsole bool, hcoTLSSecurityProfile *openshiftconfigv1.TLSSecurityProfile) error { operatorNsEnv, nserr := hcoutil.GetOperatorNamespaceFromEnv() if nserr != nil { logger.Error(nserr, "failed to get operator namespace from the environment") @@ -37,7 +37,7 @@ func SetupWebhookWithManager(ctx context.Context, mgr ctrl.Manager, isOpenshift decoder := admission.NewDecoder(mgr.GetScheme()) - whHandler := validator.NewWebhookHandler(logger, mgr.GetClient(), decoder, operatorNsEnv, isOpenshift, hcoTLSSecurityProfile) + whHandler := validator.NewWebhookHandler(logger, mgr.GetClient(), decoder, operatorNsEnv, isOpenshiftConsole, hcoTLSSecurityProfile) nsMutator := mutator.NewNsMutator(mgr.GetClient(), decoder, operatorNsEnv) hyperConvergedMutator := mutator.NewHyperConvergedMutator(mgr.GetClient(), decoder) diff --git a/pkg/webhooks/validator/validator.go b/pkg/webhooks/validator/validator.go index 59e15a039f..23550c3a52 100644 --- a/pkg/webhooks/validator/validator.go +++ b/pkg/webhooks/validator/validator.go @@ -35,22 +35,22 @@ const ( ) type WebhookHandler struct { - logger logr.Logger - cli client.Client - namespace string - isOpenshift bool - decoder admission.Decoder + logger logr.Logger + cli client.Client + namespace string + isOpenshiftConsole bool + decoder admission.Decoder } var hcoTLSConfigCache *openshiftconfigv1.TLSSecurityProfile -func NewWebhookHandler(logger logr.Logger, cli client.Client, decoder admission.Decoder, namespace string, isOpenshift bool, hcoTLSSecurityProfile *openshiftconfigv1.TLSSecurityProfile) *WebhookHandler { +func NewWebhookHandler(logger logr.Logger, cli client.Client, decoder admission.Decoder, namespace string, isOpenshiftConsole bool, hcoTLSSecurityProfile *openshiftconfigv1.TLSSecurityProfile) *WebhookHandler { hcoTLSConfigCache = hcoTLSSecurityProfile return &WebhookHandler{ logger: logger, cli: cli, namespace: namespace, - isOpenshift: isOpenshift, + isOpenshiftConsole: isOpenshiftConsole, decoder: decoder, } } @@ -216,7 +216,7 @@ func (wh *WebhookHandler) ValidateUpdate(ctx context.Context, dryrun bool, reque cna, } - if wh.isOpenshift { + if wh.isOpenshiftConsole { ssp, _, err := operands.NewSSP(requested) if err != nil { return err