@@ -56,11 +56,26 @@ func (r ResourceGenerators) ResourceGenerator() ResourceGenerator {
5656
5757type UniqueNameGenerator func (string , interface {}) (string , error )
5858
59+ // BundleConfig represents configuration options for bundle rendering
60+ type BundleConfig struct {
61+ // Install contains runtime configuration
62+ Install * InstallConfig `json:"install,omitempty"`
63+ // DeploymentConfig contains Deployment specific configuration
64+ DeploymentConfig map [string ]interface {} `json:"deploymentConfig,omitempty"`
65+ }
66+
67+ // InstallConfig contains runtime configuration options
68+ type InstallConfig struct {
69+ // WatchNamespace specifies the namespace to watch for Single/OwnNamespace install modes
70+ WatchNamespace string `json:"watchNamespace,omitempty"`
71+ }
72+
5973type Options struct {
6074 InstallNamespace string
6175 TargetNamespaces []string
6276 UniqueNameGenerator UniqueNameGenerator
6377 CertificateProvider CertificateProvider
78+ BundleConfig * BundleConfig
6479}
6580
6681func (o * Options ) apply (opts ... Option ) * Options {
@@ -83,6 +98,14 @@ func (o *Options) validate(rv1 *bundle.RegistryV1) (*Options, []error) {
8398 if err := validateTargetNamespaces (rv1 , o .InstallNamespace , o .TargetNamespaces ); err != nil {
8499 errs = append (errs , fmt .Errorf ("invalid target namespaces %v: %w" , o .TargetNamespaces , err ))
85100 }
101+
102+ // Validate bundle configuration
103+ if o .BundleConfig != nil {
104+ if configErrs := validateBundleConfig (rv1 , o .InstallNamespace , o .BundleConfig ); len (configErrs ) > 0 {
105+ errs = append (errs , configErrs ... )
106+ }
107+ }
108+
86109 return o , errs
87110}
88111
@@ -106,6 +129,12 @@ func WithCertificateProvider(provider CertificateProvider) Option {
106129 }
107130}
108131
132+ func WithBundleConfig (config * BundleConfig ) Option {
133+ return func (o * Options ) {
134+ o .BundleConfig = config
135+ }
136+ }
137+
109138type BundleRenderer struct {
110139 BundleValidator BundleValidator
111140 ResourceGenerators []ResourceGenerator
@@ -118,13 +147,19 @@ func (r BundleRenderer) Render(rv1 bundle.RegistryV1, installNamespace string, o
118147 }
119148
120149 // generate bundle objects
121- genOpts , errs := (& Options {
150+ genOpts := (& Options {
122151 // default options
123152 InstallNamespace : installNamespace ,
124153 TargetNamespaces : []string {metav1 .NamespaceAll },
125154 UniqueNameGenerator : DefaultUniqueNameGenerator ,
126155 CertificateProvider : nil ,
127- }).apply (opts ... ).validate (& rv1 )
156+ }).apply (opts ... )
157+
158+ // If bundle config is provided and contains watchNamespace, derive target namespaces from it
159+ if genOpts .BundleConfig != nil && genOpts .BundleConfig .Install != nil && genOpts .BundleConfig .Install .WatchNamespace != "" {
160+ genOpts .TargetNamespaces = []string {genOpts .BundleConfig .Install .WatchNamespace }
161+ }
162+ genOpts , errs := genOpts .validate (& rv1 )
128163
129164 if len (errs ) > 0 {
130165 return nil , fmt .Errorf ("invalid option(s): %w" , errors .Join (errs ... ))
@@ -175,3 +210,59 @@ func validateTargetNamespaces(rv1 *bundle.RegistryV1, installNamespace string, t
175210 }
176211 return fmt .Errorf ("supported install modes %v do not support target namespaces %v" , sets.List [string ](supportedInstallModes ), targetNamespaces )
177212}
213+
214+ // validateBundleConfig validates the bundle configuration against the bundle's supported install modes
215+ func validateBundleConfig (rv1 * bundle.RegistryV1 , installNamespace string , config * BundleConfig ) []error {
216+ var errs []error
217+
218+ supportedInstallModes := sets .New [string ]()
219+ for _ , im := range rv1 .CSV .Spec .InstallModes {
220+ if im .Supported {
221+ supportedInstallModes .Insert (string (im .Type ))
222+ }
223+ }
224+
225+ if config .Install != nil {
226+ watchNamespace := config .Install .WatchNamespace
227+
228+ allSupported := supportedInstallModes .Has (string (v1alpha1 .InstallModeTypeAllNamespaces ))
229+ singleSupported := supportedInstallModes .Has (string (v1alpha1 .InstallModeTypeSingleNamespace ))
230+ ownSupported := supportedInstallModes .Has (string (v1alpha1 .InstallModeTypeOwnNamespace ))
231+
232+ switch {
233+ case allSupported && ! singleSupported && ! ownSupported :
234+ // All, no Single, no Own: watchNamespace should be unknown/non-existent
235+ if watchNamespace != "" {
236+ errs = append (errs , fmt .Errorf ("watchNamespace configuration parameter is not supported for bundles that only support AllNamespaces install mode" ))
237+ }
238+ case allSupported && singleSupported && ! ownSupported :
239+ // All, Single, no Own: watchNamespace is optional
240+ // No validation needed - any value is acceptable
241+ case allSupported && ! singleSupported && ownSupported :
242+ // All, no Single, Own: watchNamespace is optional (must == install namespace when set)
243+ if watchNamespace != "" && watchNamespace != installNamespace {
244+ errs = append (errs , fmt .Errorf ("watchNamespace must equal install namespace (%s) when set for bundles supporting AllNamespaces and OwnNamespace install modes" , installNamespace ))
245+ }
246+ case ! allSupported && singleSupported && ! ownSupported :
247+ // no All, Single, no Own: watchNamespace is required
248+ if watchNamespace == "" {
249+ errs = append (errs , fmt .Errorf ("watchNamespace configuration parameter is required for bundles that only support SingleNamespace install mode" ))
250+ }
251+ case ! allSupported && singleSupported && ownSupported :
252+ // no All, Single, Own: watchNamespace is required
253+ if watchNamespace == "" {
254+ errs = append (errs , fmt .Errorf ("watchNamespace configuration parameter is required for bundles supporting SingleNamespace and OwnNamespace install modes" ))
255+ }
256+ case ! allSupported && ! singleSupported && ownSupported :
257+ // no All, no Single, Own: watchNamespace should be unknown/non-existent
258+ if watchNamespace != "" {
259+ errs = append (errs , fmt .Errorf ("watchNamespace configuration parameter is not supported for bundles that only support OwnNamespace install mode" ))
260+ }
261+ case ! allSupported && ! singleSupported && ! ownSupported :
262+ // no All, no Single, no Own: invalid bundle
263+ errs = append (errs , fmt .Errorf ("invalid bundle: no supported install modes" ))
264+ }
265+ }
266+
267+ return errs
268+ }
0 commit comments