Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions internal/deployer/crds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package deployer

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
)

// requiredCRDs lists the CRDs required for ACS operator.
var requiredCRDs = []string{
"centrals.platform.stackrox.io",
"securedclusters.platform.stackrox.io",
"securitypolicies.config.stackrox.io",
}

// ensureCRDsInstalled ensures required CRDs exist, installing them from the provided bundle directory.
func (d *Deployer) ensureCRDsInstalled(ctx context.Context, bundleDir string) error {
var missing []string
for _, crd := range requiredCRDs {
_, err := d.runKubectl(ctx, KubectlOptions{
Args: []string{"get", "crd", crd},
})
if err != nil {
missing = append(missing, crd)
}
}

if len(missing) > 0 {
d.logger.Warningf("Missing CRDs detected (%s)", strings.Join(missing, ", "))

crdFiles, err := d.identifyCRDFileNames(bundleDir)
if err != nil {
return err
}

return d.applyCRDsToCluster(ctx, crdFiles)
}

return nil
}

// 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 {
if err != nil {
return err
}

if info.IsDir() {
return nil
}

if !strings.HasSuffix(info.Name(), ".yaml") && !strings.HasSuffix(info.Name(), ".yml") {
return nil
}

// TODO(#91): The following detection logic does not seem particularly robust. We should
// probably parse the YAML and check api group and kind fields.
name := strings.ToLower(info.Name())
if strings.Contains(name, "customresourcedefinition") ||
strings.Contains(name, "platform.stackrox.io") ||
strings.Contains(name, "config.stackrox.io") {
if strings.Contains(name, "clusterserviceversion") {
return nil
}

content, err := os.ReadFile(path)
if err != nil {
return nil
}

if strings.Contains(string(content), "kind: CustomResourceDefinition") {
crdFiles = append(crdFiles, path)
}
}

return nil
})

if err != nil {
return nil, fmt.Errorf("failed to walk bundle directory: %w", err)
}

return crdFiles, nil
}

// applyCRDsToCluster applies CRD files to the cluster
func (d *Deployer) applyCRDsToCluster(ctx context.Context, crdFiles []string) error {
d.logger.Infof("Applying %d CRD(s) to cluster", len(crdFiles))

for _, crdFile := range crdFiles {
result, err := d.runKubectl(ctx, KubectlOptions{
Args: []string{"apply", "-f", crdFile},
})
if err != nil {
d.logger.Errorf("kubectl stderr: %s", result.Stderr)
return fmt.Errorf("failed to apply CRD %s: %w\nStderr: %s", crdFile, err, result.Stderr)
}

basename := filepath.Base(crdFile)
d.logger.Successf("✓ Successfully applied CRD %s", basename)
}

return nil
}

// deleteCRDs deletes RHACS CRDs from the cluster
func (d *Deployer) deleteCRDs(ctx context.Context) {
d.logger.Info("Deleting CRDs...")

args := append([]string{"delete", "crd", "--ignore-not-found=true"}, requiredCRDs...)
d.runKubectl(ctx, KubectlOptions{
Args: args,
IgnoreErrors: true,
})
}
17 changes: 0 additions & 17 deletions internal/deployer/deploy_via_helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,20 +518,3 @@ func (d *Deployer) installSecuredClusterHelmChart(ctx context.Context, chartDir,
d.logger.Success("✓ Helm chart installed")
return nil
}

// deleteCRDs deletes ACS CRDs (used before Helm deployment)
func (d *Deployer) deleteCRDs(ctx context.Context) {
crds := []string{
"centrals.platform.stackrox.io",
"securedclusters.platform.stackrox.io",
"securitypolicies.config.stackrox.io",
}

d.logger.Info("Deleting CRDs...")

args := append([]string{"delete", "crd", "--ignore-not-found=true"}, crds...)
d.runKubectl(ctx, KubectlOptions{
Args: args,
IgnoreErrors: true,
})
}
48 changes: 32 additions & 16 deletions internal/deployer/deploy_via_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"time"

"github.com/stackrox/roxie/internal/component"
"github.com/stackrox/roxie/internal/env"
"github.com/stackrox/roxie/internal/helpers"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -47,10 +48,6 @@ func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error {
return nil
}

if err := d.ensureCRDsInstalled(ctx); err != nil {
return fmt.Errorf("failed to ensure CRDs installed: %w", err)
}

// Detect current operator deployment mode
operatorExists, currentMode := d.detectOperatorDeploymentMode(ctx)
needsDeployment := false
Expand Down Expand Up @@ -80,26 +77,45 @@ func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error {
}

if needsTeardown {
// Perform teardown for the current mode
if currentMode == OperatorModeOLM {
if err := d.teardownOperatorOLM(ctx); err != nil {
return fmt.Errorf("failed to teardown OLM operator: %w", err)
}
} else {
if err := d.teardownOperatorNonOLM(ctx); err != nil {
return fmt.Errorf("failed to teardown non-OLM operator: %w", err)
}
}
// It is a prerequisite that all CRs are removed before the operator is removed to avoid blocking during teardown.
d.Teardown(ctx, component.All)
}

if needsDeployment {
d.logger.Info("🚀 Deploying operator...")
d.logger.Infof("Operator tag: %s", d.operatorTag)

if d.useOLM {
// OLM takes care of CRD installation.
if err := d.deployOperatorViaOLM(ctx); err != nil {
return fmt.Errorf("failed to deploy operator via OLM: %w", err)
}
} else {
if err := d.deployOperatorNonOLM(ctx); err != nil {
return fmt.Errorf("failed to deploy operator: %w", err)
if d.useKonflux {
if err := d.ensureKonfluxImageRewriting(ctx); err != nil {
return fmt.Errorf("failed to configure Konflux image rewriting: %w", err)
}
} else {
if err := d.removeKonfluxImageRewriting(ctx); err != nil {
return fmt.Errorf("failed to remove Konflux ImageContentSourcePolicy: %v", err)
}
}

bundleImage := d.getOperatorBundleImage()
d.logger.Infof("Bundle image: %s", bundleImage)

bundleDir, err := d.downloadAndExtractOperatorBundle(ctx, bundleImage)
if err != nil {
return fmt.Errorf("failed to download operator bundle: %w", err)
}
defer d.cleanupTempDir(bundleDir, "operator bundle directory")

if err := d.ensureCRDsInstalled(ctx, bundleDir); err != nil {
return fmt.Errorf("failed to ensure CRDs installed: %w", err)
}

if err := d.deployOperatorFromCSV(ctx, bundleDir); err != nil {
return fmt.Errorf("failed to deploy operator from CSV: %w", err)
}
}
}
Expand Down
14 changes: 4 additions & 10 deletions internal/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,11 +612,8 @@ func (d *Deployer) prepareCredentials() error {

func (d *Deployer) deployCentral(ctx context.Context, resources, exposure string) error {
d.logger.Infof("Deploying Central to namespace %s", d.centralNamespace)
if d.namespaceExists(d.centralNamespace) {
d.logger.Info("Existing Central deployment found, tearing down...")
if err := d.teardownCentral(ctx); err != nil {
d.logger.Warningf("Error during teardown: %v", err)
}
if err := d.Teardown(ctx, component.Both); err != nil {
d.logger.Warningf("Error during teardown: %v", err)
}

portForwardWanted := d.portForwardEnabled
Expand Down Expand Up @@ -645,11 +642,8 @@ func (d *Deployer) deployCentral(ctx context.Context, resources, exposure string

func (d *Deployer) deploySecuredCluster(ctx context.Context, resources string) error {
d.logger.Infof("Deploying SecuredCluster to namespace %s", d.sensorNamespace)
if d.namespaceExists(d.sensorNamespace) {
d.logger.Info("Existing SecuredCluster deployment found, tearing down...")
if err := d.teardownSecuredCluster(ctx); err != nil {
d.logger.Warningf("Error during teardown: %v", err)
}
if err := d.Teardown(ctx, component.SecuredCluster); err != nil {
d.logger.Warningf("Error during teardown: %v", err)
}

if d.useHelm {
Expand Down
Loading
Loading