@@ -56,11 +56,33 @@ 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+ // InstallMode contains install mode specific configuration
62+ InstallMode * InstallModeConfig
63+ }
64+
65+ // InstallModeConfig is a union type for install mode specific configuration
66+ type InstallModeConfig struct {
67+ // InstallMode must be one of "AllNamespaces", "SingleNamespace", or "OwnNamespace"
68+ InstallMode string
69+
70+ // SingleNamespaceInstallMode is required when InstallMode == "SingleNamespace"
71+ SingleNamespaceInstallMode * SingleNamespaceInstallModeConfig
72+ }
73+
74+ // SingleNamespaceInstallModeConfig contains configuration for SingleNamespace install mode
75+ type SingleNamespaceInstallModeConfig struct {
76+ // WatchNamespace is the namespace to watch (required)
77+ WatchNamespace string
78+ }
79+
5980type Options struct {
6081 InstallNamespace string
6182 TargetNamespaces []string
6283 UniqueNameGenerator UniqueNameGenerator
6384 CertificateProvider CertificateProvider
85+ BundleConfig * BundleConfig
6486}
6587
6688func (o * Options ) apply (opts ... Option ) * Options {
@@ -83,6 +105,14 @@ func (o *Options) validate(rv1 *bundle.RegistryV1) (*Options, []error) {
83105 if err := validateTargetNamespaces (rv1 , o .InstallNamespace , o .TargetNamespaces ); err != nil {
84106 errs = append (errs , fmt .Errorf ("invalid target namespaces %v: %w" , o .TargetNamespaces , err ))
85107 }
108+
109+ // Validate bundle configuration
110+ if o .BundleConfig != nil {
111+ if configErrs := validateBundleConfig (o .BundleConfig ); len (configErrs ) > 0 {
112+ errs = append (errs , configErrs ... )
113+ }
114+ }
115+
86116 return o , errs
87117}
88118
@@ -106,6 +136,12 @@ func WithCertificateProvider(provider CertificateProvider) Option {
106136 }
107137}
108138
139+ func WithBundleConfig (config * BundleConfig ) Option {
140+ return func (o * Options ) {
141+ o .BundleConfig = config
142+ }
143+ }
144+
109145type BundleRenderer struct {
110146 BundleValidator BundleValidator
111147 ResourceGenerators []ResourceGenerator
@@ -118,13 +154,27 @@ func (r BundleRenderer) Render(rv1 bundle.RegistryV1, installNamespace string, o
118154 }
119155
120156 // generate bundle objects
121- genOpts , errs := (& Options {
157+ genOpts := (& Options {
122158 // default options
123159 InstallNamespace : installNamespace ,
124160 TargetNamespaces : []string {metav1 .NamespaceAll },
125161 UniqueNameGenerator : DefaultUniqueNameGenerator ,
126162 CertificateProvider : nil ,
127- }).apply (opts ... ).validate (& rv1 )
163+ }).apply (opts ... )
164+
165+ if genOpts .BundleConfig != nil && genOpts .BundleConfig .InstallMode != nil {
166+ switch genOpts .BundleConfig .InstallMode .InstallMode {
167+ case bundle .InstallModeSingleNamespace :
168+ if genOpts .BundleConfig .InstallMode .SingleNamespaceInstallMode != nil {
169+ genOpts .TargetNamespaces = []string {genOpts .BundleConfig .InstallMode .SingleNamespaceInstallMode .WatchNamespace }
170+ }
171+ case bundle .InstallModeOwnNamespace :
172+ genOpts .TargetNamespaces = []string {installNamespace }
173+ case bundle .InstallModeAllNamespaces :
174+ genOpts .TargetNamespaces = []string {metav1 .NamespaceAll }
175+ }
176+ }
177+ genOpts , errs := genOpts .validate (& rv1 )
128178
129179 if len (errs ) > 0 {
130180 return nil , fmt .Errorf ("invalid option(s): %w" , errors .Join (errs ... ))
@@ -175,3 +225,38 @@ func validateTargetNamespaces(rv1 *bundle.RegistryV1, installNamespace string, t
175225 }
176226 return fmt .Errorf ("supported install modes %v do not support target namespaces %v" , sets.List [string ](supportedInstallModes ), targetNamespaces )
177227}
228+
229+ // validateBundleConfig validates that the bundle configuration is internally consistent and complete
230+ func validateBundleConfig (config * BundleConfig ) []error {
231+ var errs []error
232+
233+ if config .InstallMode == nil {
234+ return errs
235+ }
236+
237+ switch config .InstallMode .InstallMode {
238+ case bundle .InstallModeAllNamespaces :
239+ // AllNamespaces mode should not have SingleNamespace configuration
240+ if config .InstallMode .SingleNamespaceInstallMode != nil {
241+ errs = append (errs , fmt .Errorf ("invalid parameter singleNamespaceInstallMode: must not be set when installMode is %q" , bundle .InstallModeAllNamespaces ))
242+ }
243+ case bundle .InstallModeSingleNamespace :
244+ // SingleNamespace mode requires SingleNamespace configuration
245+ if config .InstallMode .SingleNamespaceInstallMode == nil {
246+ errs = append (errs , fmt .Errorf ("missing required parameter singleNamespaceInstallMode when installMode is %q" , bundle .InstallModeSingleNamespace ))
247+ } else if config .InstallMode .SingleNamespaceInstallMode .WatchNamespace == "" {
248+ errs = append (errs , fmt .Errorf ("missing required parameter watchNamespace in singleNamespaceInstallMode" ))
249+ }
250+ case bundle .InstallModeOwnNamespace :
251+ // OwnNamespace mode should not have SingleNamespace configuration
252+ if config .InstallMode .SingleNamespaceInstallMode != nil {
253+ errs = append (errs , fmt .Errorf ("invalid parameter singleNamespaceInstallMode: must not be set when installMode is %q" , bundle .InstallModeOwnNamespace ))
254+ }
255+ default :
256+ // Invalid install mode string
257+ errs = append (errs , fmt .Errorf ("invalid value for parameter installMode: %q, must be one of [%s, %s, %s]" ,
258+ config .InstallMode .InstallMode , bundle .InstallModeAllNamespaces , bundle .InstallModeSingleNamespace , bundle .InstallModeOwnNamespace ))
259+ }
260+
261+ return errs
262+ }
0 commit comments