From 4528b08347109da955208d2585b517bbedf5b26a Mon Sep 17 00:00:00 2001 From: Alex Vulaj Date: Tue, 7 Apr 2026 15:02:03 -0400 Subject: [PATCH 1/3] Fix teardown to clean up operator namespace --- internal/deployer/deployer.go | 8 +++++++- internal/deployer/operator.go | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index dd076e9..fb31d69 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -664,7 +664,13 @@ func (d *Deployer) Teardown(ctx context.Context, components component.Component) if err := d.teardownSecuredCluster(ctx); err != nil { d.logger.Warningf("Error tearing down secured cluster: %v", err) } - return d.teardownCentral(ctx) + if err := d.teardownCentral(ctx); err != nil { + d.logger.Warningf("Error tearing down central: %v", err) + } + if err := d.teardownOperator(ctx); err != nil { + d.logger.Warningf("Error tearing down operator: %v", err) + } + return nil default: return fmt.Errorf("unknown component: %s", components) } diff --git a/internal/deployer/operator.go b/internal/deployer/operator.go index 96dd4ed..d08ff44 100644 --- a/internal/deployer/operator.go +++ b/internal/deployer/operator.go @@ -396,6 +396,7 @@ metadata: name: %s labels: name: %s + app.kubernetes.io/managed-by: roxie `, operatorNamespace, operatorNamespace) _, err := d.runKubectl(ctx, KubectlOptions{ @@ -634,3 +635,17 @@ func (d *Deployer) teardownOperatorNonOLM(ctx context.Context) error { d.logger.Success("✓ Non-OLM operator resources removed") return nil } + +// teardownOperator removes the operator if it exists, detecting the deployment mode automatically. +func (d *Deployer) teardownOperator(ctx context.Context) error { + operatorExists, operatorMode := d.detectOperatorDeploymentMode(ctx) + if !operatorExists { + d.logger.Dim("No operator deployment found, skipping operator teardown") + return nil + } + + if operatorMode == OperatorModeOLM { + return d.teardownOperatorOLM(ctx) + } + return d.teardownOperatorNonOLM(ctx) +} From db3a7ac9a5b37d13be6d88d9ac492374114d6545 Mon Sep 17 00:00:00 2001 From: Alex Vulaj Date: Wed, 8 Apr 2026 12:39:03 -0400 Subject: [PATCH 2/3] Implement both vs all teardown distinction and parallel teardown --- internal/component/component.go | 25 ++++++----- internal/deployer/deploy_via_operator.go | 16 ++----- internal/deployer/deployer.go | 54 +++++++++++++++++++----- internal/deployer/operator.go | 4 +- 4 files changed, 62 insertions(+), 37 deletions(-) diff --git a/internal/component/component.go b/internal/component/component.go index 3fe6ebd..be15e0b 100644 --- a/internal/component/component.go +++ b/internal/component/component.go @@ -5,7 +5,8 @@ import "fmt" type Component int const ( - All Component = iota + Both Component = iota + All Central SecuredCluster Operator @@ -14,7 +15,9 @@ const ( func FromArgs(args []string) (Component, error) { if len(args) > 0 { switch args[0] { - case "both", "all": + case "both": + return Both, nil + case "all": return All, nil case "central": return Central, nil @@ -31,8 +34,10 @@ func FromArgs(args []string) (Component, error) { func (c Component) String() string { switch c { - case All: + case Both: return "Central and Secured Cluster" + case All: + return "Central, Secured Cluster, and Operator" case Central: return "Central" case SecuredCluster: @@ -45,21 +50,15 @@ func (c Component) String() string { } func (c Component) IncludesCentral() bool { - if c == SecuredCluster || c == Operator { - return false - } - return true + return c == Both || c == All || c == Central } func (c Component) IncludesSensor() bool { - if c == Central || c == Operator { - return false - } - return true + return c == Both || c == All || c == SecuredCluster } func (c Component) IncludesOperator() bool { - return c == Operator || c == All + return c == All || c == Operator } func (c Component) IncludesOperatorExplicitly() bool { @@ -67,5 +66,5 @@ func (c Component) IncludesOperatorExplicitly() bool { } func (c Component) IncludesBothCentralAndSensor() bool { - return c == Central || c == SecuredCluster || c == All + return c == Both || c == All } diff --git a/internal/deployer/deploy_via_operator.go b/internal/deployer/deploy_via_operator.go index 44b7598..c91d40e 100644 --- a/internal/deployer/deploy_via_operator.go +++ b/internal/deployer/deploy_via_operator.go @@ -18,7 +18,7 @@ import ( func (d *Deployer) deployOperatorOnly(ctx context.Context) error { d.logger.Info("🚀 Deploying Operator only...") - if err := d.ensureOperatorDeployed(ctx); err != nil { + if err := d.deployOperator(ctx); err != nil { return err } @@ -27,8 +27,8 @@ func (d *Deployer) deployOperatorOnly(ctx context.Context) error { return nil } -// ensureOperatorDeployed ensures the operator is deployed with the correct version and mode -func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error { +// deployOperator deploys the operator with the correct version and mode +func (d *Deployer) deployOperator(ctx context.Context) error { // Skip operator deployment/checks if flag is set to false if !d.shouldDeployOperator { d.logger.Info("â„šī¸ Skipping operator deployment checks (--deploy-operator=false)") @@ -87,7 +87,7 @@ func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error { return fmt.Errorf("failed to deploy operator via OLM: %w", err) } } else { - if err := d.deployOperator(ctx); err != nil { + if err := d.deployOperatorNonOLM(ctx); err != nil { return fmt.Errorf("failed to deploy operator: %w", err) } } @@ -100,10 +100,6 @@ func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error { func (d *Deployer) deployCentralOperator(ctx context.Context, resources, exposure string) error { d.logger.Info("🚀 Deploying Central via Operator...") - if err := d.ensureOperatorDeployed(ctx); err != nil { - return err - } - if err := d.prepareNamespace(ctx, d.centralNamespace); err != nil { return fmt.Errorf("failed to prepare namespace: %w", err) } @@ -604,10 +600,6 @@ func (d *Deployer) configureCentralEndpoint(ctx context.Context, exposure string func (d *Deployer) deploySecuredClusterOperator(ctx context.Context, resources string) error { d.logger.Info("🚀 Deploying SecuredCluster via Operator...") - if err := d.ensureOperatorDeployed(ctx); err != nil { - return err - } - if err := d.prepareNamespace(ctx, d.sensorNamespace); err != nil { return fmt.Errorf("failed to prepare namespace: %w", err) } diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index fb31d69..e11589a 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -8,6 +8,7 @@ import ( "os" "os/exec" "strings" + "sync" "time" "github.com/fatih/color" @@ -571,9 +572,19 @@ func (d *Deployer) Deploy(ctx context.Context, components component.Component, r d.logger.Infof("Initiating deployment of %s", components) - if components.IncludesOperator() { + // If only deploying operator, use the operator-only flow + if components.IncludesOperatorExplicitly() { return d.deployOperatorOnly(ctx) } + + // Deploy operator first if needed (unless using Helm) + // Operator is required for central/sensor deployments when not using Helm + if !d.useHelm { + if err := d.deployOperator(ctx); err != nil { + return fmt.Errorf("failed to deploy operator: %w", err) + } + } + if components.IncludesCentral() { if err := d.deployCentral(ctx, resources, exposure); err != nil { return fmt.Errorf("failed to deploy central: %w", err) @@ -660,16 +671,39 @@ func (d *Deployer) Teardown(ctx context.Context, components component.Component) return d.teardownCentral(ctx) case component.SecuredCluster: return d.teardownSecuredCluster(ctx) - case component.All: - if err := d.teardownSecuredCluster(ctx); err != nil { - d.logger.Warningf("Error tearing down secured cluster: %v", err) - } - if err := d.teardownCentral(ctx); err != nil { - d.logger.Warningf("Error tearing down central: %v", err) - } - if err := d.teardownOperator(ctx); err != nil { - d.logger.Warningf("Error tearing down operator: %v", err) + case component.Both, component.All: + // Tear down components in parallel for better performance + var wg sync.WaitGroup + + // Always tear down central and sensor + wg.Add(2) + + go func() { + defer wg.Done() + if err := d.teardownSecuredCluster(ctx); err != nil { + d.logger.Warningf("Error tearing down secured cluster: %v", err) + } + }() + + go func() { + defer wg.Done() + if err := d.teardownCentral(ctx); err != nil { + d.logger.Warningf("Error tearing down central: %v", err) + } + }() + + // For 'all', also tear down the operator in parallel + if components == component.All { + wg.Add(1) + go func() { + defer wg.Done() + if err := d.teardownOperator(ctx); err != nil { + d.logger.Warningf("Error tearing down operator: %v", err) + } + }() } + + wg.Wait() return nil default: return fmt.Errorf("unknown component: %s", components) diff --git a/internal/deployer/operator.go b/internal/deployer/operator.go index d08ff44..dd49bd0 100644 --- a/internal/deployer/operator.go +++ b/internal/deployer/operator.go @@ -24,8 +24,8 @@ const ( operatorDeploymentName = "rhacs-operator-controller-manager" ) -// deployOperator deploys the RHACS operator -func (d *Deployer) deployOperator(ctx context.Context) error { +// deployOperatorNonOLM deploys the RHACS operator without OLM +func (d *Deployer) deployOperatorNonOLM(ctx context.Context) error { d.logger.Infof("Operator tag: %s", d.operatorTag) if d.useKonflux { if err := d.ensureKonfluxImageRewriting(ctx); err != nil { From f5e60952a76f8e4e731ce4626460d9dbd8b7171a Mon Sep 17 00:00:00 2001 From: Alex Vulaj Date: Thu, 9 Apr 2026 08:52:50 -0400 Subject: [PATCH 3/3] Address review feedback - Revert deployOperator rename back to ensureOperatorDeployed - Remove unused IncludesOperator() function --- internal/component/component.go | 4 ---- internal/deployer/deploy_via_operator.go | 6 +++--- internal/deployer/deployer.go | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/internal/component/component.go b/internal/component/component.go index be15e0b..a4181a6 100644 --- a/internal/component/component.go +++ b/internal/component/component.go @@ -57,10 +57,6 @@ func (c Component) IncludesSensor() bool { return c == Both || c == All || c == SecuredCluster } -func (c Component) IncludesOperator() bool { - return c == All || c == Operator -} - func (c Component) IncludesOperatorExplicitly() bool { return c == Operator } diff --git a/internal/deployer/deploy_via_operator.go b/internal/deployer/deploy_via_operator.go index c91d40e..fbe511f 100644 --- a/internal/deployer/deploy_via_operator.go +++ b/internal/deployer/deploy_via_operator.go @@ -18,7 +18,7 @@ import ( func (d *Deployer) deployOperatorOnly(ctx context.Context) error { d.logger.Info("🚀 Deploying Operator only...") - if err := d.deployOperator(ctx); err != nil { + if err := d.ensureOperatorDeployed(ctx); err != nil { return err } @@ -27,8 +27,8 @@ func (d *Deployer) deployOperatorOnly(ctx context.Context) error { return nil } -// deployOperator deploys the operator with the correct version and mode -func (d *Deployer) deployOperator(ctx context.Context) error { +// ensureOperatorDeployed ensures the operator is deployed with the correct version and mode +func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error { // Skip operator deployment/checks if flag is set to false if !d.shouldDeployOperator { d.logger.Info("â„šī¸ Skipping operator deployment checks (--deploy-operator=false)") diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index e11589a..489d5dc 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -580,7 +580,7 @@ func (d *Deployer) Deploy(ctx context.Context, components component.Component, r // Deploy operator first if needed (unless using Helm) // Operator is required for central/sensor deployments when not using Helm if !d.useHelm { - if err := d.deployOperator(ctx); err != nil { + if err := d.ensureOperatorDeployed(ctx); err != nil { return fmt.Errorf("failed to deploy operator: %w", err) } }