diff --git a/data/olm-catalog/ssp-operator.clusterserviceversion.yaml b/data/olm-catalog/ssp-operator.clusterserviceversion.yaml index 5002ffdfb..75d5ef47d 100644 --- a/data/olm-catalog/ssp-operator.clusterserviceversion.yaml +++ b/data/olm-catalog/ssp-operator.clusterserviceversion.yaml @@ -343,6 +343,7 @@ spec: containers: - args: - --leader-elect + - --olm-deployment command: - /manager env: diff --git a/hack/csv-generator.go b/hack/csv-generator.go index 38ea5d8bb..ba8922174 100644 --- a/hack/csv-generator.go +++ b/hack/csv-generator.go @@ -20,15 +20,16 @@ import ( "bytes" "encoding/json" "fmt" + "io" + "os" + "github.com/blang/semver/v4" "github.com/operator-framework/api/pkg/lib/version" csvv1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/spf13/cobra" - "io" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" - "os" sigsyaml "sigs.k8s.io/yaml" "kubevirt.io/ssp-operator/internal/env" @@ -120,6 +121,8 @@ func runGenerator() error { removeCerts(&csv) } + addOLMArg(&csv) + relatedImages, err := buildRelatedImages(f) if err != nil { return err @@ -144,6 +147,16 @@ func runGenerator() error { return nil } +func addOLMArg(csv *csvv1.ClusterServiceVersion) { + templateSpec := &csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs[0].Spec.Template.Spec + for i, container := range templateSpec.Containers { + if container.Name == "manager" { + templateSpec.Containers[i].Args = append(container.Args, "--olm-deployment") + break + } + } +} + func dumpFiles(path string) error { files, err := os.ReadDir(path) if err != nil { diff --git a/internal/common/constants.go b/internal/common/constants.go new file mode 100644 index 000000000..5478ff430 --- /dev/null +++ b/internal/common/constants.go @@ -0,0 +1,7 @@ +package common + +const ( + SspOperatorMetricsServiceName = "ssp-operator-metrics" + TemplateValidatorMetricsServiceName = "template-validator-metrics" + VirtTemplateValidator = "virt-template-validator" +) diff --git a/internal/common/request.go b/internal/common/request.go index 72e7a9052..f58b019cb 100644 --- a/internal/common/request.go +++ b/internal/common/request.go @@ -23,7 +23,9 @@ type Request struct { VersionCache VersionCache TopologyMode osconfv1.TopologyMode - CrdList crd_watch.CrdList + CrdList crd_watch.CrdList + OLMDeployment bool + SSPServiceHostname string } func (r *Request) IsSingleReplicaTopologyMode() bool { diff --git a/internal/controllers/services_controller.go b/internal/controllers/services_controller.go index a17246a86..459dec4ef 100644 --- a/internal/controllers/services_controller.go +++ b/internal/controllers/services_controller.go @@ -26,7 +26,6 @@ import ( const ( ServiceManagedByLabelValue = "ssp-operator-services" - MetricsServiceName = "ssp-operator-metrics" OperatorName = "ssp-operator" ServiceControllerName = "service-controller" ) @@ -38,13 +37,14 @@ func ServiceObject(namespace string, appKubernetesPartOfValue string) *v1.Servic common.AppKubernetesVersionLabel: env.GetOperatorVersion(), common.AppKubernetesComponentLabel: ServiceControllerName, metrics.PrometheusLabelKey: metrics.PrometheusLabelValue, + metrics.MetricsServiceKey: common.SspOperatorMetricsServiceName, } if appKubernetesPartOfValue != "" { labels[common.AppKubernetesPartOfLabel] = appKubernetesPartOfValue } return &v1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: MetricsServiceName, + Name: common.SspOperatorMetricsServiceName, Namespace: namespace, Labels: labels, }, @@ -136,7 +136,7 @@ func (s *serviceReconciler) setupController(mgr ctrl.Manager) error { Named("service-controller"). For(&v1.Service{}, builder.WithPredicates(predicate.NewPredicateFuncs( func(object client.Object) bool { - return object.GetName() == MetricsServiceName && object.GetNamespace() == s.operatorNamespace + return object.GetName() == common.SspOperatorMetricsServiceName && object.GetNamespace() == s.operatorNamespace }))). Complete(s) } diff --git a/internal/controllers/setup.go b/internal/controllers/setup.go index 18cbca56f..20ea2744e 100644 --- a/internal/controllers/setup.go +++ b/internal/controllers/setup.go @@ -43,7 +43,7 @@ func StartControllers(ctx context.Context, mgr controllerruntime.Manager, contro return nil } -func CreateControllers(ctx context.Context, apiReader client.Reader) ([]Controller, error) { +func CreateControllers(ctx context.Context, apiReader client.Reader, olmDeployment bool, sspServiceHostname string) ([]Controller, error) { runningOnOpenShift, err := env.RunningOnOpenshift(ctx, apiReader) if err != nil { return nil, fmt.Errorf("failed to check if running on openshift: %w", err) @@ -102,7 +102,7 @@ func CreateControllers(ctx context.Context, apiReader client.Reader) ([]Controll serviceController, NewWebhookConfigurationController(), NewVmController(), - NewSspController(infrastructureTopology, sspOperands), + NewSspController(infrastructureTopology, sspOperands, olmDeployment, sspServiceHostname), }, nil } diff --git a/internal/controllers/ssp_controller.go b/internal/controllers/ssp_controller.go index dee070b86..dfcb8b82e 100644 --- a/internal/controllers/ssp_controller.go +++ b/internal/controllers/ssp_controller.go @@ -61,24 +61,28 @@ const ( // sspController reconciles a SSP object type sspController struct { - log logr.Logger - operands []operands.Operand - lastSspSpec ssp.SSPSpec - subresourceCache common.VersionCache - topologyMode osconfv1.TopologyMode - areCrdsMissing bool + log logr.Logger + operands []operands.Operand + lastSspSpec ssp.SSPSpec + subresourceCache common.VersionCache + topologyMode osconfv1.TopologyMode + areCrdsMissing bool + olmDeployment bool + sspServiceHostname string client client.Client uncachedReader client.Reader crdList crd_watch.CrdList } -func NewSspController(infrastructureTopology osconfv1.TopologyMode, operands []operands.Operand) Controller { +func NewSspController(infrastructureTopology osconfv1.TopologyMode, operands []operands.Operand, olmDeployment bool, sspServiceHostname string) Controller { return &sspController{ - log: ctrl.Log.WithName("controllers").WithName("SSP"), - operands: operands, - subresourceCache: common.VersionCache{}, - topologyMode: infrastructureTopology, + log: ctrl.Log.WithName("controllers").WithName("SSP"), + operands: operands, + subresourceCache: common.VersionCache{}, + topologyMode: infrastructureTopology, + olmDeployment: olmDeployment, + sspServiceHostname: sspServiceHostname, } } @@ -175,16 +179,18 @@ func (s *sspController) Reconcile(ctx context.Context, req ctrl.Request) (res ct sspChanged := s.clearCacheIfNeeded(instance) sspRequest := &common.Request{ - Request: req, - Client: s.client, - UncachedReader: s.uncachedReader, - Context: ctx, - Instance: instance, - InstanceChanged: sspChanged, - Logger: reqLogger, - VersionCache: s.subresourceCache, - TopologyMode: s.topologyMode, - CrdList: s.crdList, + Request: req, + Client: s.client, + UncachedReader: s.uncachedReader, + Context: ctx, + Instance: instance, + InstanceChanged: sspChanged, + Logger: reqLogger, + VersionCache: s.subresourceCache, + TopologyMode: s.topologyMode, + CrdList: s.crdList, + OLMDeployment: s.olmDeployment, + SSPServiceHostname: s.sspServiceHostname, } if !isInitialized(sspRequest.Instance) { diff --git a/internal/operands/metrics/reconcile.go b/internal/operands/metrics/reconcile.go index d70b1f49c..c0c0af50b 100644 --- a/internal/operands/metrics/reconcile.go +++ b/internal/operands/metrics/reconcile.go @@ -50,7 +50,8 @@ func (m *metrics) WatchClusterTypes() []operands.WatchType { func (m *metrics) Reconcile(request *common.Request) ([]common.ReconcileResult, error) { return common.CollectResourceStatus(request, - reconcilePrometheusMonitor, + reconcileValidatorMetricsMonitor, + reconcileSspMetricsMonitor, reconcilePrometheusRule, reconcileMonitoringRbacRole, reconcileMonitoringRbacRoleBinding, @@ -75,9 +76,16 @@ const ( operandComponent = common.AppComponentMonitoring ) -func reconcilePrometheusMonitor(request *common.Request) (common.ReconcileResult, error) { +func reconcileSspMetricsMonitor(request *common.Request) (common.ReconcileResult, error) { return common.CreateOrUpdate(request). - NamespacedResource(newServiceMonitorCR(request.Namespace)). + NamespacedResource(newSspServiceMonitor(request)). + WithAppLabels(operandName, operandComponent). + Reconcile() +} + +func reconcileValidatorMetricsMonitor(request *common.Request) (common.ReconcileResult, error) { + return common.CreateOrUpdate(request). + NamespacedResource(newValidatorServiceMonitor(request)). WithAppLabels(operandName, operandComponent). Reconcile() } diff --git a/internal/operands/metrics/reconcile_test.go b/internal/operands/metrics/reconcile_test.go index b50b29e86..69d58c817 100644 --- a/internal/operands/metrics/reconcile_test.go +++ b/internal/operands/metrics/reconcile_test.go @@ -74,7 +74,8 @@ var _ = Describe("Metrics operand", func() { Expect(err).ToNot(HaveOccurred()) ExpectResourceExists(prometheusRule, request) - ExpectResourceExists(newServiceMonitorCR(namespace), request) + ExpectResourceExists(newSspServiceMonitor(&request), request) + ExpectResourceExists(newValidatorServiceMonitor(&request), request) ExpectResourceExists(newMonitoringClusterRole(), request) ExpectResourceExists(newMonitoringClusterRoleBinding(), request) }) diff --git a/internal/operands/metrics/resources.go b/internal/operands/metrics/resources.go index c192d7dfa..9a76351b3 100644 --- a/internal/operands/metrics/resources.go +++ b/internal/operands/metrics/resources.go @@ -1,12 +1,15 @@ package metrics import ( + "fmt" promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + v1 "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" - "kubevirt.io/ssp-operator/pkg/monitoring/rules" + "kubevirt.io/ssp-operator/internal/common" ) const ( @@ -18,6 +21,7 @@ const ( PrometheusClusterRoleName = "prometheus-k8s-ssp" PrometheusServiceAccountName = "prometheus-k8s" MetricsPortName = "http-metrics" + MetricsServiceKey = "metrics.ssp.kubevirt.io" ) func newMonitoringClusterRole() *rbac.ClusterRole { @@ -61,31 +65,87 @@ func ServiceMonitorLabels() map[string]string { } } -func newServiceMonitorCR(namespace string) *promv1.ServiceMonitor { - return &promv1.ServiceMonitor{ +func serviceCABundle() promv1.SecretOrConfigMap { + return promv1.SecretOrConfigMap{ + ConfigMap: &v1.ConfigMapKeySelector{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "openshift-service-ca.crt", + }, + Key: "service-ca.crt", + }, + } +} + +func olmManagedCABundle() promv1.SecretOrConfigMap { + return promv1.SecretOrConfigMap{ + Secret: &v1.SecretKeySelector{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "ssp-operator-service-cert", + }, + Key: "olmCAKey", + }, + } +} + +func getCAConfigForServiceMonitor(olmDeployment bool) promv1.SecretOrConfigMap { + if olmDeployment { + return olmManagedCABundle() + } + return serviceCABundle() +} + +func newValidatorServiceMonitor(request *common.Request) *promv1.ServiceMonitor { + tlsConfig := &promv1.TLSConfig{ + SafeTLSConfig: promv1.SafeTLSConfig{ + CA: serviceCABundle(), + }, + } + + tlsConfig.ServerName = ptr.To(fmt.Sprintf("%s.%s.svc", common.VirtTemplateValidator, request.Namespace)) + serviceMonitor := newServiceMonitor(common.TemplateValidatorMetricsServiceName, request.Namespace, tlsConfig, metav1.LabelSelector{ + MatchLabels: map[string]string{ + MetricsServiceKey: common.TemplateValidatorMetricsServiceName, + }, + }) + return &serviceMonitor +} + +func newSspServiceMonitor(request *common.Request) *promv1.ServiceMonitor { + tlsConfig := &promv1.TLSConfig{ + SafeTLSConfig: promv1.SafeTLSConfig{ + CA: getCAConfigForServiceMonitor(request.OLMDeployment), + }, + } + tlsConfig.ServerName = ptr.To(request.SSPServiceHostname) + + serviceMonitor := newServiceMonitor(common.SspOperatorMetricsServiceName, request.Namespace, tlsConfig, metav1.LabelSelector{ + MatchLabels: map[string]string{ + MetricsServiceKey: common.SspOperatorMetricsServiceName, + }, + }) + return &serviceMonitor +} + +func newServiceMonitor(name, + namespace string, + tlsConfig *promv1.TLSConfig, + selector metav1.LabelSelector) promv1.ServiceMonitor { + return promv1.ServiceMonitor{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, - Name: rules.RuleName, + Name: name, Labels: ServiceMonitorLabels(), }, Spec: promv1.ServiceMonitorSpec{ NamespaceSelector: promv1.NamespaceSelector{ Any: true, }, - Selector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - PrometheusLabelKey: PrometheusLabelValue, - }, - }, + Selector: selector, Endpoints: []promv1.Endpoint{ { - Port: MetricsPortName, - Scheme: ptr.To(promv1.Scheme("https")), - TLSConfig: &promv1.TLSConfig{ - SafeTLSConfig: promv1.SafeTLSConfig{ - InsecureSkipVerify: ptr.To(true), - }, - }, + Port: MetricsPortName, + Scheme: ptr.To(promv1.Scheme("https")), + TLSConfig: tlsConfig, HonorLabels: true, }, }, diff --git a/internal/operands/template-validator/resources.go b/internal/operands/template-validator/resources.go index 670acd73c..1c012bedc 100644 --- a/internal/operands/template-validator/resources.go +++ b/internal/operands/template-validator/resources.go @@ -33,22 +33,20 @@ const ( webhookPortName = "http-webhook" KubevirtIo = "kubevirt.io" SecretName = "virt-template-validator-certs" - VirtTemplateValidator = "virt-template-validator" ClusterRoleName = "template:view" ClusterRoleBindingName = "template-validator" - WebhookName = VirtTemplateValidator + WebhookName = common.VirtTemplateValidator ServiceAccountName = "template-validator" - ServiceName = VirtTemplateValidator - MetricsServiceName = "template-validator-metrics" - DeploymentName = VirtTemplateValidator - ConfigMapName = VirtTemplateValidator + ServiceName = common.VirtTemplateValidator + DeploymentName = common.VirtTemplateValidator + ConfigMapName = common.VirtTemplateValidator PrometheusLabel = "prometheus.ssp.kubevirt.io" kubernetesHostnameTopologyKey = "kubernetes.io/hostname" ) func CommonLabels() map[string]string { return map[string]string{ - KubevirtIo: VirtTemplateValidator, + KubevirtIo: common.VirtTemplateValidator, } } @@ -161,7 +159,7 @@ func newDeployment(namespace string, replicas int32, image string) *apps.Deploym podLabels := CommonLabels() podLabels[PrometheusLabel] = "true" podLabels["name"] = DeploymentName - podAntiAffinity := newPodAntiAffinity(KubevirtIo, kubernetesHostnameTopologyKey, metav1.LabelSelectorOpIn, []string{VirtTemplateValidator}) + podAntiAffinity := newPodAntiAffinity(KubevirtIo, kubernetesHostnameTopologyKey, metav1.LabelSelectorOpIn, []string{common.VirtTemplateValidator}) return &apps.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: DeploymentName, @@ -180,7 +178,7 @@ func newDeployment(namespace string, replicas int32, image string) *apps.Deploym }, Template: core.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Name: VirtTemplateValidator, + Name: common.VirtTemplateValidator, Annotations: map[string]string{ securityv1.RequiredSCCAnnotation: common.RequiredSCCAnnotationValue, }, @@ -372,6 +370,7 @@ func newValidatingWebhook(serviceNamespace string) *admission.ValidatingWebhookC func PrometheusServiceLabels() map[string]string { return map[string]string{ metrics.PrometheusLabelKey: metrics.PrometheusLabelValue, + metrics.MetricsServiceKey: common.TemplateValidatorMetricsServiceName, } } @@ -379,7 +378,7 @@ func newPrometheusService(namespace string) *core.Service { return &core.Service{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, - Name: MetricsServiceName, + Name: common.TemplateValidatorMetricsServiceName, Labels: PrometheusServiceLabels(), }, Spec: core.ServiceSpec{ @@ -400,7 +399,7 @@ func newPrometheusService(namespace string) *core.Service { func newNetworkPolicies(namespace string) []*networkv1.NetworkPolicy { g := networkpolicies.NewOpenShiftGenerator() return []*networkv1.NetworkPolicy{ - g.NewEgressToKubeAPIAndDNS(namespace, KubevirtIo, VirtTemplateValidator), + g.NewEgressToKubeAPIAndDNS(namespace, KubevirtIo, common.VirtTemplateValidator), networkpolicies.NewIngressToVirtTemplateValidatorWebhookAndMetrics(namespace), } } diff --git a/main.go b/main.go index 531d62266..c6d820d7a 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,8 @@ package main import ( "context" "crypto/tls" + "crypto/x509" + "encoding/pem" "errors" "flag" "fmt" @@ -41,7 +43,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" - "sigs.k8s.io/controller-runtime/pkg/metrics" + k8smetrics "sigs.k8s.io/controller-runtime/pkg/metrics" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" @@ -66,11 +68,6 @@ const ( // can be running during upgrade. leaderElectionID = "734f7229.kubevirt.io" - // Certificate directory and file names OLM mounts certificates to - olmTLSDir = "/apiserver.local.config/certificates" - olmTLSCrt = "apiserver.crt" - olmTLSKey = "apiserver.key" - // Default cert file names operator-sdk expects to have sdkTLSCrt = "tls.crt" sdkTLSKey = "tls.key" @@ -162,7 +159,7 @@ func (s *prometheusServer) NeedLeaderElection() bool { func (s *prometheusServer) Start(ctx context.Context) error { setupLog.Info("Starting Prometheus metrics endpoint server with TLS") - handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{}) + handler := promhttp.HandlerFor(k8smetrics.Registry, promhttp.HandlerOpts{}) mux := http.NewServeMux() mux.Handle("/metrics", handler) @@ -210,24 +207,50 @@ func newPrometheusServer(metricsAddr string, cache cache.Cache) (*prometheusServ }, nil } +// due to the difference in how the certificate is issued, hostname extraction from the certificate itself is preferred +func extractHostnameFromCert(certPath string) (string, error) { + certBytes, err := os.ReadFile(certPath) + if err != nil { + return "", fmt.Errorf("failed to read certificate file: %w", err) + } + + block, _ := pem.Decode(certBytes) + if block == nil { + return "", fmt.Errorf("failed to parse certificate PEM") + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return "", fmt.Errorf("failed to parse certificate: %w", err) + } + + if cert.Subject.CommonName != "" && cert.Subject.CommonName == cert.DNSNames[0] { + return cert.Subject.CommonName, nil + } + + return "", errors.New("failed to extract common name from certificate") +} + func main() { var metricsAddr string var enableLeaderElection bool var probeAddr string + var olmDeployment bool flag.StringVar(&metricsAddr, "metrics-bind-address", ":8443", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") + flag.BoolVar(&olmDeployment, "olm-deployment", false, "Signalize deployment via OLM") opts := zap.Options{} opts.BindFlags(flag.CommandLine) flag.Parse() ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - err := createCertificateSymlinks() + sspServiceHostname, err := extractHostnameFromCert(path.Join(sdkTLSDir, sdkTLSCrt)) if err != nil { - setupLog.Error(err, "Error creating certificate symlinks") + setupLog.Error(err, "Error extracting hostname from certificate") os.Exit(1) } @@ -247,7 +270,7 @@ func main() { if err != nil { return nil, err } - return controllers.CreateControllers(ctx, apiClient) + return controllers.CreateControllers(ctx, apiClient, olmDeployment, sspServiceHostname) }() if err != nil { setupLog.Error(err, "error creating controllers") @@ -310,35 +333,3 @@ func main() { os.Exit(1) } } - -func createCertificateSymlinks() error { - olmDir, olmDirErr := os.Stat(olmTLSDir) - _, sdkDirErr := os.Stat(sdkTLSDir) - - // If certificates are generated by OLM, we should use OLM certificates mount path - if olmDirErr == nil && olmDir.IsDir() && os.IsNotExist(sdkDirErr) { - // For some reason, OLM maps the cert/key files to apiserver.crt/apiserver.key - // instead of tls.crt/tls.key like the SDK expects. Creating symlinks to allow - // the operator to find and use them. - setupLog.Info("OLM cert directory found, copying cert files") - - err := os.MkdirAll(sdkTLSDir, 0755) - if err != nil { - return fmt.Errorf("failed to create %s: %w", sdkTLSCrt, err) - } - - err = os.Symlink(path.Join(olmTLSDir, olmTLSCrt), path.Join(sdkTLSDir, sdkTLSCrt)) - if err != nil { - return err - } - - err = os.Symlink(path.Join(olmTLSDir, olmTLSKey), path.Join(sdkTLSDir, sdkTLSKey)) - if err != nil { - return err - } - } else { - setupLog.Info("OLM cert directory not found, using default cert directory") - } - - return nil -} diff --git a/tests/metrics_test.go b/tests/metrics_test.go index 033d2518c..f9ea9192f 100644 --- a/tests/metrics_test.go +++ b/tests/metrics_test.go @@ -34,30 +34,36 @@ func mergeMaps(maps ...map[string]string) map[string]string { return targetMap } +func createServiceMonitorTestResource(name string, expectedLabels map[string]string) testResource { + return testResource{ + Name: name, + Namespace: strategy.GetNamespace(), + Resource: &promv1.ServiceMonitor{}, + ExpectedLabels: mergeMaps(expectedLabels, metrics.ServiceMonitorLabels()), + UpdateFunc: func(ServiceMonitor *promv1.ServiceMonitor) { + ServiceMonitor.Spec.Selector = v1.LabelSelector{} + ServiceMonitor.Spec.NamespaceSelector = promv1.NamespaceSelector{} + }, + EqualsFunc: func(old *promv1.ServiceMonitor, new *promv1.ServiceMonitor) bool { + return reflect.DeepEqual(old.Spec, new.Spec) + }, + } +} + var _ = Describe("Metrics", func() { var ( - prometheusRuleRes testResource - serviceMonitorRes testResource - rbacClusterRoleRes testResource - rbacClusterRoleBindingRes testResource + prometheusRuleRes testResource + sspServiceMonitorRes testResource + templateValidatorServiceMonitorRes testResource + rbacClusterRoleRes testResource + rbacClusterRoleBindingRes testResource ) BeforeEach(func() { expectedLabels := expectedLabelsFor("metrics", common.AppComponentMonitoring) - serviceMonitorRes = testResource{ - Name: rules.RuleName, - Namespace: strategy.GetNamespace(), - Resource: &promv1.ServiceMonitor{}, - ExpectedLabels: mergeMaps(expectedLabels, metrics.ServiceMonitorLabels()), - UpdateFunc: func(ServiceMonitor *promv1.ServiceMonitor) { - ServiceMonitor.Spec.Selector = v1.LabelSelector{} - ServiceMonitor.Spec.NamespaceSelector = promv1.NamespaceSelector{} - }, - EqualsFunc: func(old *promv1.ServiceMonitor, new *promv1.ServiceMonitor) bool { - return reflect.DeepEqual(old.Spec, new.Spec) - }, - } + sspServiceMonitorRes = createServiceMonitorTestResource(common.SspOperatorMetricsServiceName, expectedLabels) + templateValidatorServiceMonitorRes = createServiceMonitorTestResource(common.TemplateValidatorMetricsServiceName, expectedLabels) rbacClusterRoleRes = testResource{ Name: metrics.PrometheusClusterRoleName, Namespace: strategy.GetNamespace(), @@ -109,14 +115,16 @@ var _ = Describe("Metrics", func() { err := apiClient.Get(ctx, res.GetKey(), res.NewResource()) Expect(err).ToNot(HaveOccurred()) }, - Entry("[test_id:8346] service monitor", &serviceMonitorRes), + Entry("[test_id:8346] ssp service monitor", &sspServiceMonitorRes), + Entry("[test_id:TODO] template validator service monitor", &templateValidatorServiceMonitorRes), Entry("[test_id:8347] role", &rbacClusterRoleRes), Entry("[test_id:8345] role binding", &rbacClusterRoleBindingRes), Entry("[test_id:4665] prometheus rules", &prometheusRuleRes), ) DescribeTable("should set app labels", expectAppLabels, - Entry("[test_id:8348] service monitor", &serviceMonitorRes), + Entry("[test_id:8348] ssp service monitor", &sspServiceMonitorRes), + Entry("[test_id:TODO] template validator service monitor", &templateValidatorServiceMonitorRes), Entry("[test_id:8349] role", &rbacClusterRoleRes), Entry("[test_id:8350] role binding", &rbacClusterRoleBindingRes), Entry("[test_id:5790] prometheus rules", &prometheusRuleRes), @@ -125,7 +133,8 @@ var _ = Describe("Metrics", func() { Context("resource deletion", func() { DescribeTable("recreate after delete", decorators.Conformance, expectRecreateAfterDelete, - Entry("[test_id:8351] service monitor", &serviceMonitorRes), + Entry("[test_id:8351] ssp service monitor", &sspServiceMonitorRes), + Entry("[test_id:TODO] template validator service monitor", &templateValidatorServiceMonitorRes), Entry("[test_id:8352] role", &rbacClusterRoleRes), Entry("[test_id:8355] role binding", &rbacClusterRoleBindingRes), Entry("[test_id:6055] prometheus rules", &prometheusRuleRes), @@ -134,7 +143,8 @@ var _ = Describe("Metrics", func() { Context("resource change", func() { DescribeTable("should restore modified resource", decorators.Conformance, expectRestoreAfterUpdate, - Entry("[test_id:8356] service monitor", &serviceMonitorRes), + Entry("[test_id:8356] ssp service monitor", &sspServiceMonitorRes), + Entry("[test_id:TODO] template validator service monitor", &templateValidatorServiceMonitorRes), Entry("[test_id:8353] role", &rbacClusterRoleRes), Entry("[test_id:8354] role binding", &rbacClusterRoleBindingRes), Entry("[test_id:4666] prometheus rules", &prometheusRuleRes), @@ -150,7 +160,8 @@ var _ = Describe("Metrics", func() { }) DescribeTable("should restore modified resource with pause", decorators.Conformance, expectRestoreAfterUpdateWithPause, - Entry("[test_id:8357] service monitor", &serviceMonitorRes), + Entry("[test_id:8357] ssp service monitor", &sspServiceMonitorRes), + Entry("[test_id:TODO] template validator service monitor", &templateValidatorServiceMonitorRes), Entry("[test_id:8358] role", &rbacClusterRoleRes), Entry("[test_id:8361] role binding", &rbacClusterRoleBindingRes), Entry("[test_id:5397] prometheus rules", &prometheusRuleRes), @@ -158,7 +169,8 @@ var _ = Describe("Metrics", func() { }) DescribeTable("should restore modified app labels", expectAppLabelsRestoreAfterUpdate, - Entry("[test_id:8362] service monitor", &serviceMonitorRes), + Entry("[test_id:8362] ssp service monitor", &sspServiceMonitorRes), + Entry("[test_id:TODO] template validator service monitor", &templateValidatorServiceMonitorRes), Entry("[test_id:8359] role", &rbacClusterRoleRes), Entry("[test_id:8360] role binding", &rbacClusterRoleBindingRes), Entry("[test_id:5790] prometheus rules", &prometheusRuleRes), diff --git a/tests/misc_test.go b/tests/misc_test.go index f0aad894d..b0b0bac95 100644 --- a/tests/misc_test.go +++ b/tests/misc_test.go @@ -25,6 +25,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ssp "kubevirt.io/ssp-operator/api/v1beta3" + "kubevirt.io/ssp-operator/internal/common" validator "kubevirt.io/ssp-operator/internal/operands/template-validator" "kubevirt.io/ssp-operator/tests/decorators" "kubevirt.io/ssp-operator/tests/env" @@ -200,7 +201,7 @@ var _ = Describe("SCC annotation", func() { pods := &core.PodList{} err := apiClient.List(ctx, pods, client.InNamespace(strategy.GetNamespace()), - client.MatchingLabels{validator.KubevirtIo: validator.VirtTemplateValidator}) + client.MatchingLabels{validator.KubevirtIo: common.VirtTemplateValidator}) Expect(err).ToNot(HaveOccurred()) Expect(pods.Items).ToNot(BeEmpty()) diff --git a/tests/service_controller_test.go b/tests/service_controller_test.go index 7a52f785a..b379fe773 100644 --- a/tests/service_controller_test.go +++ b/tests/service_controller_test.go @@ -8,7 +8,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -90,7 +89,7 @@ var _ = Describe("Service Controller", func() { return "", err } return foundService.UID, nil - }, env.ShortTimeout(), time.Second).ShouldNot(Equal(oldUID), fmt.Sprintf("Did not recreate the %s service", controllers.MetricsServiceName)) + }, env.ShortTimeout(), time.Second).ShouldNot(Equal(oldUID), fmt.Sprintf("Did not recreate the %s service", common.SspOperatorMetricsServiceName)) }) It("[test_id:8810] Should restore ssp-operator-metrics service after update", decorators.Conformance, func() { diff --git a/tests/validator_test.go b/tests/validator_test.go index bb7cfae3b..2d5e7fbe9 100644 --- a/tests/validator_test.go +++ b/tests/validator_test.go @@ -10,7 +10,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - templatev1 "github.com/openshift/api/template/v1" conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" admission "k8s.io/api/admissionregistration/v1" @@ -155,7 +154,7 @@ var _ = Describe("Template validator operand", func() { }, } serviceMetricsRes = testResource{ - Name: validator.MetricsServiceName, + Name: common.TemplateValidatorMetricsServiceName, Namespace: strategy.GetNamespace(), Resource: &core.Service{}, ExpectedLabels: validator.PrometheusServiceLabels(), @@ -643,7 +642,7 @@ var _ = Describe("Template validator webhooks", func() { } eventuallyCreateVm(vm) - pods, err := GetRunningPodsByLabel(validator.VirtTemplateValidator, validator.KubevirtIo, strategy.GetNamespace()) + pods, err := GetRunningPodsByLabel(common.VirtTemplateValidator, validator.KubevirtIo, strategy.GetNamespace()) Expect(err).ToNot(HaveOccurred(), "Could not find the validator pods") Eventually(func() bool { for _, pod := range pods.Items { @@ -962,7 +961,7 @@ var _ = Describe("Template validator webhooks", func() { }) It("[test_id:4375] Test refreshing of certificates", decorators.Conformance, func() { - pods, err := GetRunningPodsByLabel(validator.VirtTemplateValidator, validator.KubevirtIo, strategy.GetNamespace()) + pods, err := GetRunningPodsByLabel(common.VirtTemplateValidator, validator.KubevirtIo, strategy.GetNamespace()) Expect(err).ToNot(HaveOccurred()) Expect(pods.Items).ToNot(BeEmpty(), "no pods found") @@ -1062,7 +1061,7 @@ func failVmCreationToIncreaseRejectedVmsMetrics(template *templatev1.Template) { } func totalRejectedVmsMetricsValue() (int, error) { - pods, err := GetRunningPodsByLabel(validator.VirtTemplateValidator, validator.KubevirtIo, strategy.GetNamespace()) + pods, err := GetRunningPodsByLabel(common.VirtTemplateValidator, validator.KubevirtIo, strategy.GetNamespace()) Expect(err).ToNot(HaveOccurred(), "Could not find the validator pods") Expect(pods.Items).ToNot(BeEmpty())