77
88 "helm.sh/helm/v3/pkg/chart"
99
10+ "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle"
1011 "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
1112 "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
1213)
@@ -18,11 +19,27 @@ type BundleToHelmChartConverter struct {
1819}
1920
2021func (r * BundleToHelmChartConverter ) ToHelmChart (bundle source.BundleSource , installNamespace string , watchNamespace string ) (* chart.Chart , error ) {
22+ config := make (map [string ]interface {})
23+
24+ if watchNamespace != "" {
25+ config ["watchNamespace" ] = watchNamespace
26+ }
27+
2128 rv1 , err := bundle .GetBundle ()
2229 if err != nil {
2330 return nil , err
2431 }
2532
33+ if _ , present := config ["watchNamespace" ]; ! present {
34+ config ["watchNamespace" ] = r .deriveDefaultWatchNamespace (& rv1 , installNamespace )
35+ }
36+
37+ // Derive target namespaces from watchNamespace
38+ targetNamespaces , err := r .deriveTargetNamespaces (config )
39+ if err != nil {
40+ return nil , fmt .Errorf ("error deriving target namespaces: %w" , err )
41+ }
42+
2643 if len (rv1 .CSV .Spec .APIServiceDefinitions .Owned ) > 0 {
2744 return nil , fmt .Errorf ("unsupported bundle: apiServiceDefintions are not supported" )
2845 }
@@ -41,7 +58,7 @@ func (r *BundleToHelmChartConverter) ToHelmChart(bundle source.BundleSource, ins
4158
4259 objs , err := r .BundleRenderer .Render (
4360 rv1 , installNamespace ,
44- render .WithTargetNamespaces (watchNamespace ),
61+ render .WithTargetNamespaces (targetNamespaces ... ),
4562 render .WithCertificateProvider (r .CertificateProvider ),
4663 )
4764
@@ -77,3 +94,55 @@ func (r *BundleToHelmChartConverter) ToHelmChart(bundle source.BundleSource, ins
7794
7895 return chrt , nil
7996}
97+
98+ // deriveDefaultWatchNamespace determines the default watch namespace based on bundle's supported install modes
99+ func (r * BundleToHelmChartConverter ) deriveDefaultWatchNamespace (rv1 * bundle.RegistryV1 , installNamespace string ) string {
100+ // Check what install modes the bundle supports
101+ supportedModes := make (map [string ]bool )
102+ for _ , installMode := range rv1 .CSV .Spec .InstallModes {
103+ if installMode .Supported {
104+ supportedModes [string (installMode .Type )] = true
105+ }
106+ }
107+
108+ // Priority order for defaults:
109+ // 1. If supports AllNamespaces -> "" (AllNamespaces)
110+ // 2. If supports OwnNamespace -> installNamespace (OwnNamespace)
111+ // 3. If supports SingleNamespace -> installNamespace (treat as OwnNamespace since we can't know the target)
112+ // 4. Fallback -> "" (AllNamespaces)
113+
114+ if supportedModes ["AllNamespaces" ] {
115+ return "" // Empty string means AllNamespaces
116+ }
117+ if supportedModes ["OwnNamespace" ] {
118+ return installNamespace // OwnNamespace
119+ }
120+ if supportedModes ["SingleNamespace" ] {
121+ return installNamespace // Treat as OwnNamespace since we don't know the target namespace
122+ }
123+
124+ // Fallback to AllNamespaces
125+ return ""
126+ }
127+
128+ // deriveTargetNamespaces converts config.watchNamespace to the target namespaces for the renderer
129+ func (r * BundleToHelmChartConverter ) deriveTargetNamespaces (cfg map [string ]interface {}) ([]string , error ) {
130+ watchNsRaw , exists := cfg ["watchNamespace" ]
131+ if ! exists {
132+ // No configuration provided, default to AllNamespaces
133+ return []string {"" }, nil
134+ }
135+
136+ watchNs , ok := watchNsRaw .(string )
137+ if ! ok {
138+ return nil , fmt .Errorf ("watchNamespace must be a string, got %T" , watchNsRaw )
139+ }
140+
141+ if watchNs == "" {
142+ // Empty string means AllNamespaces
143+ return []string {"" }, nil
144+ } else {
145+ // Non-empty string means SingleNamespace (or OwnNamespace if it equals installNamespace)
146+ return []string {watchNs }, nil
147+ }
148+ }
0 commit comments