diff --git a/cmd/logs.go b/cmd/logs.go index f67795f..c23d285 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -60,7 +60,6 @@ func runLogsOperator(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - // Create kubectl command with context kubectlCmd := exec.CommandContext(ctx, "kubectl", kubectlArgs...) // Get stdout pipe for streaming @@ -69,20 +68,15 @@ func runLogsOperator(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to create stdout pipe: %w", err) } - // Pass through stderr directly kubectlCmd.Stderr = os.Stderr - // Start the command if err := kubectlCmd.Start(); err != nil { return fmt.Errorf("failed to start kubectl: %w", err) } - // Process stdout with color coding processLogStream(stdout) - // Wait for command to complete if err := kubectlCmd.Wait(); err != nil { - // Check if it was a timeout if ctx.Err() == context.DeadlineExceeded { return fmt.Errorf("timeout connecting to cluster - ensure your kubeconfig is correct and the cluster is reachable") } @@ -99,7 +93,6 @@ func runLogsOperator(cmd *cobra.Command, args []string) error { func processLogStream(reader io.Reader) { scanner := bufio.NewScanner(reader) - // Define colors for different log levels infoColor := color.New(color.FgWhite) debugColor := color.New(color.Faint) errorColor := color.New(color.FgRed, color.Bold) @@ -108,7 +101,6 @@ func processLogStream(reader io.Reader) { for scanner.Scan() { line := scanner.Text() - // Determine log level and apply appropriate color switch { case strings.Contains(line, "ERROR"): errorColor.Println(line) diff --git a/internal/deployer/deploy_via_helm.go b/internal/deployer/deploy_via_helm.go index a7c429d..bc96c11 100644 --- a/internal/deployer/deploy_via_helm.go +++ b/internal/deployer/deploy_via_helm.go @@ -268,7 +268,7 @@ func (d *Deployer) createCentralValues(resourcesName, exposure string) (map[stri func (d *Deployer) createSecuredClusterValues(clusterName, resources string) (map[string]interface{}, error) { base := map[string]interface{}{ "clusterName": clusterName, - "centralEndpoint": "https://central.acs-central.svc:443", + "centralEndpoint": "https://central." + centralNamespace + ".svc:443", "allowNonstandardNamespace": true, } @@ -318,102 +318,90 @@ func (d *Deployer) getCentralExposureConfigHelm(exposure string) map[string]inte // getCentralResourcesHelm returns resource overlays for Central Helm deployment func (d *Deployer) getCentralResourcesHelm(resourcesName string) map[string]interface{} { - resourcesSmall := map[string]interface{}{ - "central": map[string]interface{}{ - "resources": centralResourcesSmall, - "db": map[string]interface{}{ - "resources": centralDbResourcesSmall, - }, - }, - "scanner": map[string]interface{}{ - "resources": centralScannerResourcesSmall, - "dbResources": centralScannerDbResourcesSmall, - }, - "scannerV4": map[string]interface{}{ - "indexer": map[string]interface{}{ - "resources": centralScannerV4IndexerResourcesSmall, - }, - "matcher": map[string]interface{}{ - "resources": centralScannerV4MatcherResourcesSmall, + switch resourcesName { + case "small": + return map[string]interface{}{ + "central": map[string]interface{}{ + "resources": centralResourcesSmall, + "db": map[string]interface{}{ + "resources": centralDbResourcesSmall, + }, }, - "db": map[string]interface{}{ - "resources": centralScannerV4DbResourcesSmall, + "scanner": map[string]interface{}{ + "resources": centralScannerResourcesSmall, + "dbResources": centralScannerDbResourcesSmall, }, - }, - } - - resourcesMedium := map[string]interface{}{ - "central": map[string]interface{}{ - "resources": centralResourcesMedium, - "db": map[string]interface{}{ - "resources": centralDbResourcesMedium, + "scannerV4": map[string]interface{}{ + "indexer": map[string]interface{}{ + "resources": centralScannerV4IndexerResourcesSmall, + }, + "matcher": map[string]interface{}{ + "resources": centralScannerV4MatcherResourcesSmall, + }, + "db": map[string]interface{}{ + "resources": centralScannerV4DbResourcesSmall, + }, }, - }, - "scanner": map[string]interface{}{ - "resources": centralScannerResourcesMedium, - "dbResources": centralScannerDbResourcesMedium, - }, - "scannerV4": map[string]interface{}{ - "indexer": map[string]interface{}{ - "resources": centralScannerV4IndexerResourcesMedium, + } + case "medium": + return map[string]interface{}{ + "central": map[string]interface{}{ + "resources": centralResourcesMedium, + "db": map[string]interface{}{ + "resources": centralDbResourcesMedium, + }, }, - "matcher": map[string]interface{}{ - "resources": centralScannerV4MatcherResourcesMedium, + "scanner": map[string]interface{}{ + "resources": centralScannerResourcesMedium, + "dbResources": centralScannerDbResourcesMedium, }, - "db": map[string]interface{}{ - "resources": centralScannerV4DbResourcesMedium, + "scannerV4": map[string]interface{}{ + "indexer": map[string]interface{}{ + "resources": centralScannerV4IndexerResourcesMedium, + }, + "matcher": map[string]interface{}{ + "resources": centralScannerV4MatcherResourcesMedium, + }, + "db": map[string]interface{}{ + "resources": centralScannerV4DbResourcesMedium, + }, }, - }, - } - - var resources map[string]interface{} - - switch resourcesName { - case "small": - resources = resourcesSmall - case "medium": - resources = resourcesMedium + } + default: + return nil } - - return resources } // getSecuredClusterResourcesHelm returns resource overlays for SecuredCluster Helm deployment func (d *Deployer) getSecuredClusterResourcesHelm(resourcesName string) map[string]interface{} { - resourcesSmall := map[string]interface{}{ - "sensor": map[string]interface{}{ - "resources": securedClusterSensorResourcesSmall, - }, - "scanner": map[string]interface{}{ - "disable": true, - }, - "scannerV4": map[string]interface{}{ - "disable": true, - }, - } - - resourcesMedium := map[string]interface{}{ - "sensor": map[string]interface{}{ - "resources": securedClusterSensorResourcesMedium, - }, - "scanner": map[string]interface{}{ - "disable": true, - }, - "scannerV4": map[string]interface{}{ - "disable": true, - }, - } - - var resources map[string]interface{} - switch resourcesName { case "small": - resources = resourcesSmall + return map[string]interface{}{ + "sensor": map[string]interface{}{ + "resources": securedClusterSensorResourcesSmall, + }, + "scanner": map[string]interface{}{ + "disable": true, + }, + "scannerV4": map[string]interface{}{ + "disable": true, + }, + } case "medium": - resources = resourcesMedium + return map[string]interface{}{ + "sensor": map[string]interface{}{ + "resources": securedClusterSensorResourcesMedium, + }, + "scanner": map[string]interface{}{ + "disable": true, + }, + "scannerV4": map[string]interface{}{ + "disable": true, + }, + } + default: + return nil } - - return resources } // verifyHelmChartImages renders the Helm template and verifies that images are pullable @@ -431,7 +419,7 @@ func (d *Deployer) verifyHelmChartImages(ctx context.Context, chartDir, valuesFi return fmt.Errorf("failed to render helm template: %w", err) } - imageRefs := extractImageReferences(string(output)) + imageRefs := extractMainImageReferences(string(output)) if len(imageRefs) == 0 { d.logger.Warning("No images found in rendered template") @@ -451,8 +439,8 @@ func (d *Deployer) verifyHelmChartImages(ctx context.Context, chartDir, valuesFi return nil } -// extractImageReferences extracts unique image references from rendered YAML -func extractImageReferences(renderedYAML string) []string { +// extractMainImageReferences extracts unique image references from rendered YAML +func extractMainImageReferences(renderedYAML string) []string { seen := make(map[string]bool) var images []string diff --git a/internal/deployer/deploy_via_operator.go b/internal/deployer/deploy_via_operator.go index fbe511f..d6b6e5a 100644 --- a/internal/deployer/deploy_via_operator.go +++ b/internal/deployer/deploy_via_operator.go @@ -14,6 +14,17 @@ import ( "gopkg.in/yaml.v3" ) +var ( + smallScale = map[string]interface{}{ + "autoScaling": "Enabled", + "replicas": 1, + } + noScaling = map[string]interface{}{ + "autoScaling": "Disabled", + "replicas": 1, + } +) + // deployOperatorOnly deploys only the operator without any Central or SecuredCluster resources func (d *Deployer) deployOperatorOnly(ctx context.Context) error { d.logger.Info("🚀 Deploying Operator only...") @@ -270,96 +281,70 @@ func (d *Deployer) createCentralCR(resources, exposure string) (map[string]inter } func (d *Deployer) getCentralResourcesOperator(resourcesName string) map[string]interface{} { - resourcesSmall := map[string]interface{}{ - "spec": map[string]interface{}{ - "central": map[string]interface{}{ - "resources": centralResourcesSmall, - "db": map[string]interface{}{ - "resources": centralDbResourcesSmall, - }, - }, - "scanner": map[string]interface{}{ - "scannerComponent": "Disabled", - "analyzer": map[string]interface{}{ - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + switch resourcesName { + case "small": + return map[string]interface{}{ + "spec": map[string]interface{}{ + "central": map[string]interface{}{ + "resources": centralResourcesSmall, + "db": map[string]interface{}{ + "resources": centralDbResourcesSmall, }, }, - }, - "scannerV4": map[string]interface{}{ - "db": map[string]interface{}{ - "resources": centralScannerV4DbResourcesSmall, - }, - "indexer": map[string]interface{}{ - "resources": centralScannerV4IndexerResourcesSmall, - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "scanner": map[string]interface{}{ + "scannerComponent": "Disabled", + "analyzer": map[string]interface{}{ + "scaling": noScaling, }, }, - "matcher": map[string]interface{}{ - "resources": centralScannerV4MatcherResourcesSmall, - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "scannerV4": map[string]interface{}{ + "db": map[string]interface{}{ + "resources": centralScannerV4DbResourcesSmall, }, - }, - }, - }, - } - - resourcesMedium := map[string]interface{}{ - "spec": map[string]interface{}{ - "central": map[string]interface{}{ - "resources": centralResourcesMedium, - "db": map[string]interface{}{ - "resources": centralDbResourcesMedium, - }, - }, - "scanner": map[string]interface{}{ - "scannerComponent": "Disabled", - "analyzer": map[string]interface{}{ - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "indexer": map[string]interface{}{ + "resources": centralScannerV4IndexerResourcesSmall, + "scaling": noScaling, + }, + "matcher": map[string]interface{}{ + "resources": centralScannerV4MatcherResourcesSmall, + "scaling": noScaling, }, }, }, - "scannerV4": map[string]interface{}{ - "db": map[string]interface{}{ - "resources": centralScannerV4DbResourcesMedium, + } + case "medium": + return map[string]interface{}{ + "spec": map[string]interface{}{ + "central": map[string]interface{}{ + "resources": centralResourcesMedium, + "db": map[string]interface{}{ + "resources": centralDbResourcesMedium, + }, }, - "indexer": map[string]interface{}{ - "resources": centralScannerV4IndexerResourcesMedium, - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "scanner": map[string]interface{}{ + "scannerComponent": "Disabled", + "analyzer": map[string]interface{}{ + "scaling": noScaling, }, }, - "matcher": map[string]interface{}{ - "resources": centralScannerV4MatcherResourcesMedium, - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "scannerV4": map[string]interface{}{ + "db": map[string]interface{}{ + "resources": centralScannerV4DbResourcesMedium, + }, + "indexer": map[string]interface{}{ + "resources": centralScannerV4IndexerResourcesMedium, + "scaling": noScaling, + }, + "matcher": map[string]interface{}{ + "resources": centralScannerV4MatcherResourcesMedium, + "scaling": noScaling, }, }, }, - }, - } - - var resources map[string]interface{} - - switch resourcesName { - case "acs-defaults": - // Nothing to do here, don't set any custom resources. - case "small": - resources = resourcesSmall - case "medium": - resources = resourcesMedium + } + default: + return nil } - - return resources } // getCentralExposureConfig returns the exposure configuration @@ -581,7 +566,7 @@ func (d *Deployer) configureCentralEndpoint(ctx context.Context, exposure string d.centralEndpoint = strings.TrimSuffix(d.centralEndpoint, ":443") d.centralEndpoint = d.centralEndpoint + ":443" } else { - d.centralEndpoint = "central.acs-central.svc:443" + d.centralEndpoint = "central." + centralNamespace + ".svc:443" } if err := d.fetchCentralCACert(ctx); err != nil { @@ -670,73 +655,53 @@ func (d *Deployer) createSecuredClusterCR(clusterName, resources string) (map[st } func (d *Deployer) getSecuredClusterResourcesOperator(resourcesName string) map[string]interface{} { - resourcesSmall := map[string]interface{}{ - "spec": map[string]interface{}{ - "sensor": map[string]interface{}{ - "resources": securedClusterSensorResourcesSmall, - }, - "scanner": map[string]interface{}{ - "scannerComponent": "Disabled", - "analyzer": map[string]interface{}{ - "scaling": map[string]interface{}{ - "autoScaling": "Enabled", - "replicas": 1, + switch resourcesName { + case "small": + return map[string]interface{}{ + "spec": map[string]interface{}{ + "sensor": map[string]interface{}{ + "resources": securedClusterSensorResourcesSmall, + }, + "scanner": map[string]interface{}{ + "scannerComponent": "Disabled", + "analyzer": map[string]interface{}{ + "scaling": smallScale, }, }, - }, - "scannerV4": map[string]interface{}{ - "scannerComponent": "Disabled", - "indexer": map[string]interface{}{ - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "scannerV4": map[string]interface{}{ + "scannerComponent": "Disabled", + "indexer": map[string]interface{}{ + "scaling": noScaling, }, }, }, - }, - } - - resourcesMedium := map[string]interface{}{ - "spec": map[string]interface{}{ - "admissionControl": map[string]interface{}{ - "replicas": 1, - }, - "scanner": map[string]interface{}{ - "scannerComponent": "Disabled", - "analyzer": map[string]interface{}{ - "scaling": map[string]interface{}{ - "autoScaling": "Enabled", - "replicas": 1, + } + case "medium": + return map[string]interface{}{ + "spec": map[string]interface{}{ + "admissionControl": map[string]interface{}{ + "replicas": 1, + }, + "scanner": map[string]interface{}{ + "scannerComponent": "Disabled", + "analyzer": map[string]interface{}{ + "scaling": smallScale, }, }, - }, - "sensor": map[string]interface{}{ - "resources": securedClusterSensorResourcesMedium, - }, - "scannerV4": map[string]interface{}{ - "scannerComponent": "Disabled", - "indexer": map[string]interface{}{ - "scaling": map[string]interface{}{ - "autoScaling": "Disabled", - "replicas": 1, + "sensor": map[string]interface{}{ + "resources": securedClusterSensorResourcesMedium, + }, + "scannerV4": map[string]interface{}{ + "scannerComponent": "Disabled", + "indexer": map[string]interface{}{ + "scaling": noScaling, }, }, }, - }, - } - - var resources map[string]interface{} - - switch resourcesName { - case "acs-defaults": - // Nothing to do here, don't set any custom resources. - case "small": - resources = resourcesSmall - case "medium": - resources = resourcesMedium + } + default: + return nil } - - return resources } // applySecuredClusterCR applies the SecuredCluster CR to the cluster @@ -782,10 +747,8 @@ func (d *Deployer) waitForSecuredClusterReady(ctx context.Context, timeout int) checkInterval := 3 * time.Second for time.Since(start) < time.Duration(timeout)*time.Second { - // Check for new deployments d.checkDeploymentProgressInNamespace(ctx, d.sensorNamespace, seenDeployments) - // Check for pod events if in early readiness mode or verbose if d.earlyReadiness || d.verbose { d.checkPodProgressInNamespace(ctx, d.sensorNamespace, seenPods) } diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index 82860dc..c694742 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -141,18 +141,7 @@ func (d *Deployer) filterResourceKinds(resourceKinds []string) []string { } func (d *Deployer) deleteResource(ctx context.Context, namespace, resourceType, resourceName string, args ...string) error { - finalArgs := []string{ - "-n", namespace, - "delete", - resourceType, - resourceName, - "--ignore-not-found", - "--force", - "--grace-period=0", - } - finalArgs = append(finalArgs, args...) - _, err := d.runKubectl(ctx, KubectlOptions{Args: finalArgs}) - return err + return d.deleteResources(ctx, namespace, []string{resourceType}, append([]string{resourceName}, args...)...) } func (d *Deployer) deleteResources(ctx context.Context, namespace string, resourceTypes []string, args ...string) error { @@ -174,7 +163,7 @@ func (d *Deployer) deleteFinalizers(ctx context.Context, namespace, resourceType _, err := d.runKubectl(ctx, KubectlOptions{ Args: []string{ "-n", namespace, "patch", resourceType, resourceName, - "-p", "{\"metadata\":{\"finalizers\":null}}", + "-p", `{"metadata":{"finalizers":null}}`, "--type=merge", }, }) @@ -468,7 +457,6 @@ func (d *Deployer) SetFeatureFlags(featureFlags []string) error { } func New(log *logger.Logger) (*Deployer, error) { - // Check required tools first if err := checkRequiredTools(); err != nil { return nil, err } @@ -609,7 +597,6 @@ func (d *Deployer) prepareCredentials() error { return err } - // Store the verified credentials d.dockerCreds = creds d.logger.Dimf("Docker credentials verified successfully") diff --git a/internal/deployer/operator.go b/internal/deployer/operator.go index dd49bd0..919209d 100644 --- a/internal/deployer/operator.go +++ b/internal/deployer/operator.go @@ -19,11 +19,19 @@ import ( ) const ( - adminPasswordSecretName = "admin-password" - operatorNamespace = "rhacs-operator-system" - operatorDeploymentName = "rhacs-operator-controller-manager" + adminPasswordSecretName = "admin-password" + operatorNamespace = "rhacs-operator-system" + operatorDeploymentName = "rhacs-operator-controller-manager" + operatorBundleImageRepo = "quay.io/rhacs-eng/stackrox-operator-bundle" + operatorBundleImageReleaseRepo = "quay.io/rhacs-eng/release-operator-bundle" ) +var requiredCRDs = []string{ + "centrals.platform.stackrox.io", + "securedclusters.platform.stackrox.io", + "securitypolicies.config.stackrox.io", +} + // deployOperatorNonOLM deploys the RHACS operator without OLM func (d *Deployer) deployOperatorNonOLM(ctx context.Context) error { d.logger.Infof("Operator tag: %s", d.operatorTag) @@ -46,7 +54,7 @@ func (d *Deployer) deployOperatorNonOLM(ctx context.Context) error { d.logger.Infof("Bundle image: %s", bundleImage) - crdFiles, err := d.identifyCRDFiles(bundleDir) + crdFiles, err := d.identifyCRDFileNames(bundleDir) if err != nil { return err } @@ -82,8 +90,8 @@ func (d *Deployer) downloadAndExtractOperatorBundle(ctx context.Context, bundleI return bundleDir, nil } -// identifyCRDFiles identifies CRD files in the bundle directory -func (d *Deployer) identifyCRDFiles(bundleDir string) ([]string, error) { +// identifyCRDFileNames identifies CRD files in the bundle directory +func (d *Deployer) identifyCRDFileNames(bundleDir string) ([]string, error) { var crdFiles []string err := filepath.Walk(bundleDir, func(path string, info os.FileInfo, err error) error { @@ -149,12 +157,6 @@ func (d *Deployer) applyCRDsToCluster(ctx context.Context, crdFiles []string) er // ensureCRDsInstalled ensures required CRDs exist func (d *Deployer) ensureCRDsInstalled(ctx context.Context) error { - requiredCRDs := []string{ - "centrals.platform.stackrox.io", - "securedclusters.platform.stackrox.io", - "securitypolicies.config.stackrox.io", - } - var missing []string for _, crd := range requiredCRDs { _, err := d.runKubectl(ctx, KubectlOptions{ @@ -176,7 +178,7 @@ func (d *Deployer) ensureCRDsInstalled(ctx context.Context) error { } defer d.cleanupTempDir(bundleDir, "CRD bundle directory") - crdFiles, err := d.identifyCRDFiles(bundleDir) + crdFiles, err := d.identifyCRDFileNames(bundleDir) if err != nil { return err } @@ -190,9 +192,9 @@ func (d *Deployer) ensureCRDsInstalled(ctx context.Context) error { func (d *Deployer) getOperatorBundleImage() string { if d.useKonflux { d.logger.Infof("Using Konflux-built operator bundle image") - return fmt.Sprintf("quay.io/rhacs-eng/release-operator-bundle:v%s", d.operatorTag) + return fmt.Sprintf(operatorBundleImageReleaseRepo+":v%s", d.operatorTag) } - return fmt.Sprintf("quay.io/rhacs-eng/stackrox-operator-bundle:v%s", d.operatorTag) + return fmt.Sprintf(operatorBundleImageRepo+":v%s", d.operatorTag) } // ensureKonfluxImageRewriting configures image rewriting for Konflux images diff --git a/internal/deployer/operator_olm.go b/internal/deployer/operator_olm.go index ceea967..62eda9c 100644 --- a/internal/deployer/operator_olm.go +++ b/internal/deployer/operator_olm.go @@ -12,10 +12,11 @@ import ( ) const ( - catalogSourceName = "stackrox-operator-index" - subscriptionName = "stackrox-operator-subscription" - operatorGroupName = "all-namespaces-operator-group" - operatorChannel = "latest" + catalogSourceName = "stackrox-operator-index" + subscriptionName = "stackrox-operator-subscription" + operatorGroupName = "all-namespaces-operator-group" + operatorChannel = "latest" + operatorIndexImage = "quay.io/rhacs-eng/stackrox-operator-index" ) // OperatorDeploymentMode represents how the operator is deployed @@ -31,7 +32,6 @@ func (d *Deployer) deployOperatorViaOLM(ctx context.Context) error { d.logger.Info("🚀 Deploying operator via OLM...") d.logger.Infof("Operator tag: %s", d.operatorTag) - // Sanity check:Check if OLM is installed. if err := d.checkOLMInstalled(ctx); err != nil { return err } @@ -39,37 +39,30 @@ func (d *Deployer) deployOperatorViaOLM(ctx context.Context) error { indexImage := d.getOperatorIndexImage() d.logger.Infof("Index image: %s", indexImage) - // Create operator namespace. if err := d.createOperatorNamespace(ctx); err != nil { return err } - // Create CatalogSource. if err := d.createCatalogSource(ctx, indexImage); err != nil { return fmt.Errorf("failed to create CatalogSource: %w", err) } - // Create OperatorGroup. if err := d.createOperatorGroup(ctx); err != nil { return fmt.Errorf("failed to create OperatorGroup: %w", err) } - // Create Subscription. if err := d.createSubscription(ctx); err != nil { return fmt.Errorf("failed to create Subscription: %w", err) } - // Wait for and approve InstallPlan. if err := d.waitForAndApproveInstallPlan(ctx); err != nil { return fmt.Errorf("failed to approve InstallPlan: %w", err) } - // Wait for CSV to succeed. if err := d.waitForCSVSuccess(ctx); err != nil { return fmt.Errorf("failed waiting for CSV: %w", err) } - // Wait for operator deployment. if err := d.waitForOperatorReady(ctx, operatorNamespace, operatorDeploymentName, 300); err != nil { return fmt.Errorf("failed waiting for operator: %w", err) } @@ -103,14 +96,14 @@ func (d *Deployer) checkOLMInstalled(ctx context.Context) error { // getOperatorIndexImage returns the operator index image reference. func (d *Deployer) getOperatorIndexImage() string { - return fmt.Sprintf("quay.io/rhacs-eng/stackrox-operator-index:v%s", d.operatorTag) + return fmt.Sprintf(operatorIndexImage+":v%s", d.operatorTag) } // createCatalogSource creates the CatalogSource for the operator. func (d *Deployer) createCatalogSource(ctx context.Context, indexImage string) error { d.logger.Info("Creating CatalogSource...") - // Check if CatalogSource CRD supports securityContextConfig. + // Check if CatalogSource CRD supports securityContextConfig (OCP 4.14+). hasSecurityContextConfig, err := d.catalogSourceSupportsSecurityContextConfig(ctx) if err != nil { d.logger.Warning("Could not check CatalogSource CRD capabilities, proceeding without securityContextConfig") diff --git a/internal/dockerauth/dockerauth.go b/internal/dockerauth/dockerauth.go index 3f0dde6..7678245 100644 --- a/internal/dockerauth/dockerauth.go +++ b/internal/dockerauth/dockerauth.go @@ -14,7 +14,8 @@ import ( ) const ( - acsImageRegistry = "quay.io" + acsImageRegistry = "quay.io" + mainImageRepository = "rhacs-eng/main" ) // DockerAuth handles Docker authentication and pull secret management. @@ -186,9 +187,8 @@ func (d *DockerAuth) VerifyCredentials(username, password string) error { // Try to get a token from quay.io's OAuth2 endpoint for a specific repository // This mimics what kubelet does when pulling images - it requests a token with pull scope // for the specific repository. - repository := "rhacs-eng/main" authURL := fmt.Sprintf("https://%s/v2/auth?service=%s&scope=repository:%s:pull", - acsImageRegistry, acsImageRegistry, repository) + acsImageRegistry, acsImageRegistry, mainImageRepository) cmd := exec.Command("curl", "-s", "-f", "-H", fmt.Sprintf("Authorization: Basic %s", encodedAuth), @@ -211,7 +211,7 @@ func (d *DockerAuth) VerifyCredentials(username, password string) error { return fmt.Errorf("credential verification failed: no token received from %s", acsImageRegistry) } - d.logger.Dimf("Successfully verified credentials for %s (repository: %s)", acsImageRegistry, repository) + d.logger.Dimf("Successfully verified credentials for %s (repository: %s)", acsImageRegistry, mainImageRepository) return nil } diff --git a/internal/dockerauth/dockerauth_test.go b/internal/dockerauth/dockerauth_test.go index 939dc29..492400b 100644 --- a/internal/dockerauth/dockerauth_test.go +++ b/internal/dockerauth/dockerauth_test.go @@ -3,7 +3,6 @@ package dockerauth import ( "encoding/base64" "encoding/json" - "os" "strings" "testing" @@ -80,8 +79,8 @@ func TestGetAndVerifyCredentialsFromEnv(t *testing.T) { func TestGetAndVerifyCredentialsNoCredentials(t *testing.T) { // Ensure no credentials are set - os.Unsetenv("REGISTRY_USERNAME") - os.Unsetenv("REGISTRY_PASSWORD") + t.Setenv("REGISTRY_USERNAME", "") + t.Setenv("REGISTRY_PASSWORD", "") // Use a temporary home directory to simulate missing credentials. t.Setenv("HOME", t.TempDir()) diff --git a/tests/e2e/basic_test.go b/tests/e2e/basic_test.go index 3129b84..75b1e68 100644 --- a/tests/e2e/basic_test.go +++ b/tests/e2e/basic_test.go @@ -16,13 +16,12 @@ func TestDeployBothSimple(t *testing.T) { } // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) t.Log("=== Deploying both components together ===") args := append([]string{roxieBinary, "deploy", "--early-readiness", "both", "--envrc", envrcPath}, commonDeployArgsNoPortForward...) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 27e7729..82f1760 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -264,13 +264,12 @@ func TestDeployCentralAndSecuredCluster(t *testing.T) { } // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) // Deploy central t.Log("=== Deploying central ===") @@ -296,9 +295,6 @@ func TestDeployCentralAndSecuredCluster(t *testing.T) { t.Log("Verifying namespace: acs-sensor") verifyNamespaceExists(t, "acs-sensor") verifyNamespaceHasLabel(t, "acs-sensor", "app.kubernetes.io/managed-by", "roxie") - - // Brief pause before next test - time.Sleep(5 * time.Second) } func TestTeardownCentralAndSecuredCluster(t *testing.T) { @@ -353,13 +349,12 @@ func TestDeployBothComponentsTogether(t *testing.T) { } // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) t.Log("=== Deploying both components ===") // We also test --pause-reconciliation flag here. @@ -390,13 +385,12 @@ func TestDeployBothComponentsTogetherInSingleNamespace(t *testing.T) { } // Create temporary envrc file. - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) t.Log("=== Deploying both components in single namespace ===") args := append([]string{roxieBinary, "deploy", "both", "--single-namespace", "--early-readiness", "--envrc", envrcPath}, commonDeployArgsNoPortForward...) @@ -415,13 +409,12 @@ func TestDeployBothComponentsTogetherInSingleNamespace(t *testing.T) { func TestDeployCentralAndSecuredClusterViaHelm(t *testing.T) { // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) t.Log("=== Deploying central via Helm ===") args := append([]string{roxieBinary, "deploy", "--early-readiness", "central", "--helm", "--envrc", envrcPath}, commonDeployArgsNoPortForward...) diff --git a/tests/e2e/olm_switch_test.go b/tests/e2e/olm_switch_test.go index 90fae0f..09b4507 100644 --- a/tests/e2e/olm_switch_test.go +++ b/tests/e2e/olm_switch_test.go @@ -8,7 +8,6 @@ import ( "os/exec" "strings" "testing" - "time" ) // Note: All e2e tests run sequentially via the -parallel=1 flag in the Makefile. @@ -71,13 +70,12 @@ func TestOLMToNonOLMSwitch(t *testing.T) { } // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) // Step 1: Deploy central with OLM operator t.Log("=== Step 1: Deploy central with OLM operator ===") @@ -92,9 +90,6 @@ func TestOLMToNonOLMSwitch(t *testing.T) { // Verify central namespace exists verifyNamespaceExists(t, "acs-central") - // Brief pause - time.Sleep(10 * time.Second) - // Step 2: Deploy central again without OLM (should switch modes) t.Log("=== Step 2: Redeploy central without OLM (triggering mode switch) ===") args = append([]string{roxieBinary, "deploy", "central", "--envrc", envrcPath}, commonDeployArgsNoPortForward...) @@ -123,13 +118,12 @@ func TestNonOLMToOLMSwitch(t *testing.T) { } // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) // Step 1: Deploy central without OLM (non-OLM operator) t.Log("=== Step 1: Deploy central with non-OLM operator ===") @@ -144,9 +138,6 @@ func TestNonOLMToOLMSwitch(t *testing.T) { // Verify central namespace exists verifyNamespaceExists(t, "acs-central") - // Brief pause - time.Sleep(10 * time.Second) - // Step 2: Deploy central again with OLM (should switch modes) t.Log("=== Step 2: Redeploy central with OLM (triggering mode switch) ===") args = append([]string{roxieBinary, "deploy", "central", "--olm", "--envrc", envrcPath}, commonDeployArgsNoPortForward...) @@ -179,13 +170,12 @@ func TestOLMOperatorVersionUpgrade(t *testing.T) { // but the logic should handle version changes by tearing down and redeploying // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) // Step 1: Deploy central with OLM operator t.Log("=== Step 1: Deploy central with OLM operator ===") @@ -209,9 +199,6 @@ func TestOLMOperatorVersionUpgrade(t *testing.T) { initialImage := strings.TrimSpace(string(output)) t.Logf("Initial operator image: %s", initialImage) - // Brief pause - time.Sleep(10 * time.Second) - // Step 2: Redeploy with same version (should skip if version matches) t.Log("=== Step 2: Redeploy with same version (should detect correct version) ===") args = append([]string{roxieBinary, "deploy", "central", "--olm", "--envrc", envrcPath}, commonDeployArgsNoPortForward...) @@ -241,13 +228,12 @@ func TestSecuredClusterWithOLMSwitch(t *testing.T) { } // Create temporary envrc file - envrcFile, err := os.CreateTemp("", ".envrc.roxie-test-*") + envrcFile, err := os.CreateTemp(t.TempDir(), ".envrc.roxie-test-*") if err != nil { t.Fatalf("Failed to create temp envrc: %v", err) } envrcPath := envrcFile.Name() envrcFile.Close() - defer os.Remove(envrcPath) // Step 1: Deploy central with OLM t.Log("=== Step 1: Deploy central with OLM ===") diff --git a/tests/testhelpers/testhelpers.go b/tests/testhelpers/testhelpers.go deleted file mode 100644 index 24c4555..0000000 --- a/tests/testhelpers/testhelpers.go +++ /dev/null @@ -1,3 +0,0 @@ -package testhelpers - -// This package is currently unused but kept for future test helpers