@@ -56,11 +56,39 @@ func (r ResourceGenerators) ResourceGenerator() ResourceGenerator {
5656
5757type UniqueNameGenerator func (string , interface {}) (string , error )
5858
59+ const (
60+ InstallModeAllNamespaces = "AllNamespaces"
61+ InstallModeSingleNamespace = "SingleNamespace"
62+ InstallModeOwnNamespace = "OwnNamespace"
63+ )
64+
65+ // BundleConfig represents configuration options for bundle rendering
66+ type BundleConfig struct {
67+ // InstallMode contains install mode specific configuration
68+ InstallMode * InstallModeConfig
69+ }
70+
71+ // InstallModeConfig is a union type for install mode specific configuration
72+ type InstallModeConfig struct {
73+ // InstallMode must be one of "AllNamespaces", "SingleNamespace", or "OwnNamespace"
74+ InstallMode string
75+
76+ // SingleNamespaceInstallMode is required when InstallMode == "SingleNamespace"
77+ SingleNamespaceInstallMode * SingleNamespaceInstallModeConfig
78+ }
79+
80+ // SingleNamespaceInstallModeConfig contains configuration for SingleNamespace install mode
81+ type SingleNamespaceInstallModeConfig struct {
82+ // WatchNamespace is the namespace to watch (required)
83+ WatchNamespace string
84+ }
85+
5986type Options struct {
6087 InstallNamespace string
6188 TargetNamespaces []string
6289 UniqueNameGenerator UniqueNameGenerator
6390 CertificateProvider CertificateProvider
91+ BundleConfig * BundleConfig
6492}
6593
6694func (o * Options ) apply (opts ... Option ) * Options {
@@ -83,6 +111,14 @@ func (o *Options) validate(rv1 *bundle.RegistryV1) (*Options, []error) {
83111 if err := validateTargetNamespaces (rv1 , o .InstallNamespace , o .TargetNamespaces ); err != nil {
84112 errs = append (errs , fmt .Errorf ("invalid target namespaces %v: %w" , o .TargetNamespaces , err ))
85113 }
114+
115+ // Validate bundle configuration
116+ if o .BundleConfig != nil {
117+ if configErrs := validateBundleConfig (o .BundleConfig ); len (configErrs ) > 0 {
118+ errs = append (errs , configErrs ... )
119+ }
120+ }
121+
86122 return o , errs
87123}
88124
@@ -106,6 +142,12 @@ func WithCertificateProvider(provider CertificateProvider) Option {
106142 }
107143}
108144
145+ func WithBundleConfig (config * BundleConfig ) Option {
146+ return func (o * Options ) {
147+ o .BundleConfig = config
148+ }
149+ }
150+
109151type BundleRenderer struct {
110152 BundleValidator BundleValidator
111153 ResourceGenerators []ResourceGenerator
@@ -118,13 +160,27 @@ func (r BundleRenderer) Render(rv1 bundle.RegistryV1, installNamespace string, o
118160 }
119161
120162 // generate bundle objects
121- genOpts , errs := (& Options {
163+ genOpts := (& Options {
122164 // default options
123165 InstallNamespace : installNamespace ,
124166 TargetNamespaces : []string {metav1 .NamespaceAll },
125167 UniqueNameGenerator : DefaultUniqueNameGenerator ,
126168 CertificateProvider : nil ,
127- }).apply (opts ... ).validate (& rv1 )
169+ }).apply (opts ... )
170+
171+ if genOpts .BundleConfig != nil && genOpts .BundleConfig .InstallMode != nil {
172+ switch genOpts .BundleConfig .InstallMode .InstallMode {
173+ case InstallModeSingleNamespace :
174+ if genOpts .BundleConfig .InstallMode .SingleNamespaceInstallMode != nil {
175+ genOpts .TargetNamespaces = []string {genOpts .BundleConfig .InstallMode .SingleNamespaceInstallMode .WatchNamespace }
176+ }
177+ case InstallModeOwnNamespace :
178+ genOpts .TargetNamespaces = []string {installNamespace }
179+ case InstallModeAllNamespaces :
180+ genOpts .TargetNamespaces = []string {metav1 .NamespaceAll }
181+ }
182+ }
183+ genOpts , errs := genOpts .validate (& rv1 )
128184
129185 if len (errs ) > 0 {
130186 return nil , fmt .Errorf ("invalid option(s): %w" , errors .Join (errs ... ))
@@ -175,3 +231,38 @@ func validateTargetNamespaces(rv1 *bundle.RegistryV1, installNamespace string, t
175231 }
176232 return fmt .Errorf ("supported install modes %v do not support target namespaces %v" , sets.List [string ](supportedInstallModes ), targetNamespaces )
177233}
234+
235+ // validateBundleConfig validates that the bundle configuration is internally consistent and complete
236+ func validateBundleConfig (config * BundleConfig ) []error {
237+ var errs []error
238+
239+ if config .InstallMode == nil {
240+ return errs
241+ }
242+
243+ switch config .InstallMode .InstallMode {
244+ case InstallModeAllNamespaces :
245+ // AllNamespaces mode should not have SingleNamespace configuration
246+ if config .InstallMode .SingleNamespaceInstallMode != nil {
247+ errs = append (errs , fmt .Errorf ("singleNamespaceInstallMode configuration should not be provided when installMode is AllNamespaces" ))
248+ }
249+ case InstallModeSingleNamespace :
250+ // SingleNamespace mode requires SingleNamespace configuration
251+ if config .InstallMode .SingleNamespaceInstallMode == nil {
252+ errs = append (errs , fmt .Errorf ("singleNamespaceInstallMode configuration is required when installMode is SingleNamespace" ))
253+ } else if config .InstallMode .SingleNamespaceInstallMode .WatchNamespace == "" {
254+ errs = append (errs , fmt .Errorf ("watchNamespace is required in singleNamespaceInstallMode configuration" ))
255+ }
256+ case InstallModeOwnNamespace :
257+ // OwnNamespace mode should not have SingleNamespace configuration
258+ if config .InstallMode .SingleNamespaceInstallMode != nil {
259+ errs = append (errs , fmt .Errorf ("singleNamespaceInstallMode configuration should not be provided when installMode is OwnNamespace" ))
260+ }
261+ default :
262+ // Invalid install mode string
263+ errs = append (errs , fmt .Errorf ("invalid installMode %q, must be one of: %s, %s, %s" ,
264+ config .InstallMode , InstallModeAllNamespaces , InstallModeSingleNamespace , InstallModeOwnNamespace ))
265+ }
266+
267+ return errs
268+ }
0 commit comments