Skip to content

Commit bece111

Browse files
mclasmeierMoritz Clasmeierporridge
authored
Refactor CRD installation/deletion, skipping second CRD installation. (#93)
Co-authored-by: Moritz Clasmeier <mclasmeier@redhat.com> Co-authored-by: Marcin Owsiany <porridge@redhat.com>
1 parent 3c2d3a3 commit bece111

5 files changed

Lines changed: 152 additions & 171 deletions

File tree

internal/deployer/crds.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package deployer
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
)
10+
11+
// requiredCRDs lists the CRDs required for ACS operator.
12+
var requiredCRDs = []string{
13+
"centrals.platform.stackrox.io",
14+
"securedclusters.platform.stackrox.io",
15+
"securitypolicies.config.stackrox.io",
16+
}
17+
18+
// ensureCRDsInstalled ensures required CRDs exist, installing them from the provided bundle directory.
19+
func (d *Deployer) ensureCRDsInstalled(ctx context.Context, bundleDir string) error {
20+
var missing []string
21+
for _, crd := range requiredCRDs {
22+
_, err := d.runKubectl(ctx, KubectlOptions{
23+
Args: []string{"get", "crd", crd},
24+
})
25+
if err != nil {
26+
missing = append(missing, crd)
27+
}
28+
}
29+
30+
if len(missing) > 0 {
31+
d.logger.Warningf("Missing CRDs detected (%s)", strings.Join(missing, ", "))
32+
33+
crdFiles, err := d.identifyCRDFileNames(bundleDir)
34+
if err != nil {
35+
return err
36+
}
37+
38+
return d.applyCRDsToCluster(ctx, crdFiles)
39+
}
40+
41+
return nil
42+
}
43+
44+
// identifyCRDFileNames identifies CRD files in the bundle directory.
45+
func (d *Deployer) identifyCRDFileNames(bundleDir string) ([]string, error) {
46+
var crdFiles []string
47+
48+
err := filepath.Walk(bundleDir, func(path string, info os.FileInfo, err error) error {
49+
if err != nil {
50+
return err
51+
}
52+
53+
if info.IsDir() {
54+
return nil
55+
}
56+
57+
if !strings.HasSuffix(info.Name(), ".yaml") && !strings.HasSuffix(info.Name(), ".yml") {
58+
return nil
59+
}
60+
61+
// TODO(#91): The following detection logic does not seem particularly robust. We should
62+
// probably parse the YAML and check api group and kind fields.
63+
name := strings.ToLower(info.Name())
64+
if strings.Contains(name, "customresourcedefinition") ||
65+
strings.Contains(name, "platform.stackrox.io") ||
66+
strings.Contains(name, "config.stackrox.io") {
67+
if strings.Contains(name, "clusterserviceversion") {
68+
return nil
69+
}
70+
71+
content, err := os.ReadFile(path)
72+
if err != nil {
73+
return nil
74+
}
75+
76+
if strings.Contains(string(content), "kind: CustomResourceDefinition") {
77+
crdFiles = append(crdFiles, path)
78+
}
79+
}
80+
81+
return nil
82+
})
83+
84+
if err != nil {
85+
return nil, fmt.Errorf("failed to walk bundle directory: %w", err)
86+
}
87+
88+
return crdFiles, nil
89+
}
90+
91+
// applyCRDsToCluster applies CRD files to the cluster
92+
func (d *Deployer) applyCRDsToCluster(ctx context.Context, crdFiles []string) error {
93+
d.logger.Infof("Applying %d CRD(s) to cluster", len(crdFiles))
94+
95+
for _, crdFile := range crdFiles {
96+
result, err := d.runKubectl(ctx, KubectlOptions{
97+
Args: []string{"apply", "-f", crdFile},
98+
})
99+
if err != nil {
100+
d.logger.Errorf("kubectl stderr: %s", result.Stderr)
101+
return fmt.Errorf("failed to apply CRD %s: %w\nStderr: %s", crdFile, err, result.Stderr)
102+
}
103+
104+
basename := filepath.Base(crdFile)
105+
d.logger.Successf("✓ Successfully applied CRD %s", basename)
106+
}
107+
108+
return nil
109+
}
110+
111+
// deleteCRDs deletes RHACS CRDs from the cluster
112+
func (d *Deployer) deleteCRDs(ctx context.Context) {
113+
d.logger.Info("Deleting CRDs...")
114+
115+
args := append([]string{"delete", "crd", "--ignore-not-found=true"}, requiredCRDs...)
116+
d.runKubectl(ctx, KubectlOptions{
117+
Args: args,
118+
IgnoreErrors: true,
119+
})
120+
}

internal/deployer/deploy_via_helm.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -518,20 +518,3 @@ func (d *Deployer) installSecuredClusterHelmChart(ctx context.Context, chartDir,
518518
d.logger.Success("✓ Helm chart installed")
519519
return nil
520520
}
521-
522-
// deleteCRDs deletes ACS CRDs (used before Helm deployment)
523-
func (d *Deployer) deleteCRDs(ctx context.Context) {
524-
crds := []string{
525-
"centrals.platform.stackrox.io",
526-
"securedclusters.platform.stackrox.io",
527-
"securitypolicies.config.stackrox.io",
528-
}
529-
530-
d.logger.Info("Deleting CRDs...")
531-
532-
args := append([]string{"delete", "crd", "--ignore-not-found=true"}, crds...)
533-
d.runKubectl(ctx, KubectlOptions{
534-
Args: args,
535-
IgnoreErrors: true,
536-
})
537-
}

internal/deployer/deploy_via_operator.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error {
4747
return nil
4848
}
4949

50-
if err := d.ensureCRDsInstalled(ctx); err != nil {
51-
return fmt.Errorf("failed to ensure CRDs installed: %w", err)
52-
}
53-
5450
// Detect current operator deployment mode
5551
operatorExists, currentMode := d.detectOperatorDeploymentMode(ctx)
5652
needsDeployment := false
@@ -93,13 +89,40 @@ func (d *Deployer) ensureOperatorDeployed(ctx context.Context) error {
9389
}
9490

9591
if needsDeployment {
92+
d.logger.Info("🚀 Deploying operator...")
93+
d.logger.Infof("Operator tag: %s", d.operatorTag)
94+
9695
if d.useOLM {
96+
// OLM takes care of CRD installation.
9797
if err := d.deployOperatorViaOLM(ctx); err != nil {
9898
return fmt.Errorf("failed to deploy operator via OLM: %w", err)
9999
}
100100
} else {
101-
if err := d.deployOperatorNonOLM(ctx); err != nil {
102-
return fmt.Errorf("failed to deploy operator: %w", err)
101+
if d.useKonflux {
102+
if err := d.ensureKonfluxImageRewriting(ctx); err != nil {
103+
return fmt.Errorf("failed to configure Konflux image rewriting: %w", err)
104+
}
105+
} else {
106+
if err := d.removeKonfluxImageRewriting(ctx); err != nil {
107+
return fmt.Errorf("failed to remove Konflux ImageContentSourcePolicy: %v", err)
108+
}
109+
}
110+
111+
bundleImage := d.getOperatorBundleImage()
112+
d.logger.Infof("Bundle image: %s", bundleImage)
113+
114+
bundleDir, err := d.downloadAndExtractOperatorBundle(ctx, bundleImage)
115+
if err != nil {
116+
return fmt.Errorf("failed to download operator bundle: %w", err)
117+
}
118+
defer d.cleanupTempDir(bundleDir, "operator bundle directory")
119+
120+
if err := d.ensureCRDsInstalled(ctx, bundleDir); err != nil {
121+
return fmt.Errorf("failed to ensure CRDs installed: %w", err)
122+
}
123+
124+
if err := d.deployOperatorFromCSV(ctx, bundleDir); err != nil {
125+
return fmt.Errorf("failed to deploy operator from CSV: %w", err)
103126
}
104127
}
105128
}

internal/deployer/operator.go

Lines changed: 3 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -26,50 +26,6 @@ const (
2626
operatorBundleImageReleaseRepo = "quay.io/rhacs-eng/release-operator-bundle"
2727
)
2828

29-
var requiredCRDs = []string{
30-
"centrals.platform.stackrox.io",
31-
"securedclusters.platform.stackrox.io",
32-
"securitypolicies.config.stackrox.io",
33-
}
34-
35-
// deployOperatorNonOLM deploys the RHACS operator without OLM
36-
func (d *Deployer) deployOperatorNonOLM(ctx context.Context) error {
37-
d.logger.Infof("Operator tag: %s", d.operatorTag)
38-
if d.useKonflux {
39-
if err := d.ensureKonfluxImageRewriting(ctx); err != nil {
40-
return fmt.Errorf("failed to configure Konflux image rewriting: %w", err)
41-
}
42-
} else {
43-
if err := d.removeKonfluxImageRewriting(ctx); err != nil {
44-
return fmt.Errorf("failed to remove Konflux ImageContentSourcePolicy: %v", err)
45-
}
46-
}
47-
bundleImage := d.getOperatorBundleImage()
48-
49-
bundleDir, err := d.downloadAndExtractOperatorBundle(ctx, bundleImage)
50-
if err != nil {
51-
return fmt.Errorf("failed to download operator bundle: %w", err)
52-
}
53-
defer d.cleanupTempDir(bundleDir, "operator bundle directory")
54-
55-
d.logger.Infof("Bundle image: %s", bundleImage)
56-
57-
crdFiles, err := d.identifyCRDFileNames(bundleDir)
58-
if err != nil {
59-
return err
60-
}
61-
62-
if err := d.applyCRDsToCluster(ctx, crdFiles); err != nil {
63-
return err
64-
}
65-
66-
if err := d.deployOperatorFromCSV(ctx, bundleDir); err != nil {
67-
return err
68-
}
69-
70-
return nil
71-
}
72-
7329
// downloadAndExtractOperatorBundle downloads and extracts the operator bundle
7430
func (d *Deployer) downloadAndExtractOperatorBundle(ctx context.Context, bundleImage string) (string, error) {
7531
bundleDir, err := os.MkdirTemp("", "stackrox-operator-bundle-")
@@ -90,107 +46,6 @@ func (d *Deployer) downloadAndExtractOperatorBundle(ctx context.Context, bundleI
9046
return bundleDir, nil
9147
}
9248

93-
// identifyCRDFileNames identifies CRD files in the bundle directory
94-
func (d *Deployer) identifyCRDFileNames(bundleDir string) ([]string, error) {
95-
var crdFiles []string
96-
97-
err := filepath.Walk(bundleDir, func(path string, info os.FileInfo, err error) error {
98-
if err != nil {
99-
return err
100-
}
101-
102-
if info.IsDir() {
103-
return nil
104-
}
105-
106-
if !strings.HasSuffix(info.Name(), ".yaml") && !strings.HasSuffix(info.Name(), ".yml") {
107-
return nil
108-
}
109-
110-
// TODO(#91): The following detection logic does not seem particularly robust. We should
111-
// probably parse the YAML and check api group and kind fields.
112-
name := strings.ToLower(info.Name())
113-
if strings.Contains(name, "customresourcedefinition") ||
114-
strings.Contains(name, "platform.stackrox.io") ||
115-
strings.Contains(name, "config.stackrox.io") {
116-
if strings.Contains(name, "clusterserviceversion") {
117-
return nil
118-
}
119-
120-
content, err := os.ReadFile(path)
121-
if err != nil {
122-
return nil
123-
}
124-
125-
if strings.Contains(string(content), "kind: CustomResourceDefinition") {
126-
crdFiles = append(crdFiles, path)
127-
}
128-
}
129-
130-
return nil
131-
})
132-
133-
if err != nil {
134-
return nil, fmt.Errorf("failed to walk bundle directory: %w", err)
135-
}
136-
137-
return crdFiles, nil
138-
}
139-
140-
// applyCRDsToCluster applies CRD files to the cluster
141-
func (d *Deployer) applyCRDsToCluster(ctx context.Context, crdFiles []string) error {
142-
d.logger.Infof("Applying %d CRD(s) to cluster", len(crdFiles))
143-
144-
for _, crdFile := range crdFiles {
145-
result, err := d.runKubectl(ctx, KubectlOptions{
146-
Args: []string{"apply", "-f", crdFile},
147-
})
148-
if err != nil {
149-
d.logger.Errorf("kubectl stderr: %s", result.Stderr)
150-
return fmt.Errorf("failed to apply CRD %s: %w\nStderr: %s", crdFile, err, result.Stderr)
151-
}
152-
153-
basename := filepath.Base(crdFile)
154-
d.logger.Successf("✓ Successfully applied CRD %s", basename)
155-
}
156-
157-
return nil
158-
}
159-
160-
// ensureCRDsInstalled ensures required CRDs exist
161-
func (d *Deployer) ensureCRDsInstalled(ctx context.Context) error {
162-
var missing []string
163-
for _, crd := range requiredCRDs {
164-
_, err := d.runKubectl(ctx, KubectlOptions{
165-
Args: []string{"get", "crd", crd},
166-
})
167-
if err != nil {
168-
missing = append(missing, crd)
169-
}
170-
}
171-
172-
if len(missing) > 0 {
173-
bundleImage := d.getOperatorBundleImage()
174-
d.logger.Warningf("Missing CRDs detected (%s)", strings.Join(missing, ", "))
175-
d.logger.Warningf("Fetching bundle %s", bundleImage)
176-
177-
bundleDir, err := d.downloadAndExtractOperatorBundle(ctx, bundleImage)
178-
if err != nil {
179-
return err
180-
}
181-
defer d.cleanupTempDir(bundleDir, "CRD bundle directory")
182-
183-
crdFiles, err := d.identifyCRDFileNames(bundleDir)
184-
if err != nil {
185-
return err
186-
}
187-
188-
return d.applyCRDsToCluster(ctx, crdFiles)
189-
}
190-
191-
return nil
192-
}
193-
19449
func (d *Deployer) getOperatorBundleImage() string {
19550
if d.useKonflux {
19651
d.logger.Infof("Using Konflux-built operator bundle image")
@@ -632,6 +487,9 @@ func (d *Deployer) teardownOperatorNonOLM(ctx context.Context) error {
632487
})
633488
}
634489

490+
// Delete CRDs to ensure clean redeployment with updated CRD versions.
491+
d.deleteCRDs(ctx)
492+
635493
if err := d.waitForNamespaceDeletion(operatorNamespace); err != nil {
636494
d.logger.Warningf("Namespace %s deletion incomplete: %v", operatorNamespace, err)
637495
}

internal/deployer/operator_olm.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ const (
2929

3030
// deployOperatorViaOLM deploys the RHACS operator using OLM.
3131
func (d *Deployer) deployOperatorViaOLM(ctx context.Context) error {
32-
d.logger.Info("🚀 Deploying operator via OLM...")
33-
d.logger.Infof("Operator tag: %s", d.operatorTag)
34-
3532
if err := d.checkOLMInstalled(ctx); err != nil {
3633
return err
3734
}

0 commit comments

Comments
 (0)