@@ -26,6 +26,50 @@ 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+
2973// downloadAndExtractOperatorBundle downloads and extracts the operator bundle
3074func (d * Deployer ) downloadAndExtractOperatorBundle (ctx context.Context , bundleImage string ) (string , error ) {
3175 bundleDir , err := os .MkdirTemp ("" , "stackrox-operator-bundle-" )
@@ -46,6 +90,107 @@ func (d *Deployer) downloadAndExtractOperatorBundle(ctx context.Context, bundleI
4690 return bundleDir , nil
4791}
4892
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\n Stderr: %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+
49194func (d * Deployer ) getOperatorBundleImage () string {
50195 if d .useKonflux {
51196 d .logger .Infof ("Using Konflux-built operator bundle image" )
@@ -487,9 +632,6 @@ func (d *Deployer) teardownOperatorNonOLM(ctx context.Context) error {
487632 })
488633 }
489634
490- // Delete CRDs to ensure clean redeployment with updated CRD versions.
491- d .deleteCRDs (ctx )
492-
493635 if err := d .waitForNamespaceDeletion (operatorNamespace ); err != nil {
494636 d .logger .Warningf ("Namespace %s deletion incomplete: %v" , operatorNamespace , err )
495637 }
0 commit comments