@@ -56,11 +56,26 @@ func (r ResourceGenerators) ResourceGenerator() ResourceGenerator {
56
56
57
57
type UniqueNameGenerator func (string , interface {}) (string , error )
58
58
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
+
59
73
type Options struct {
60
74
InstallNamespace string
61
75
TargetNamespaces []string
62
76
UniqueNameGenerator UniqueNameGenerator
63
77
CertificateProvider CertificateProvider
78
+ BundleConfig * BundleConfig
64
79
}
65
80
66
81
func (o * Options ) apply (opts ... Option ) * Options {
@@ -83,6 +98,14 @@ func (o *Options) validate(rv1 *bundle.RegistryV1) (*Options, []error) {
83
98
if err := validateTargetNamespaces (rv1 , o .InstallNamespace , o .TargetNamespaces ); err != nil {
84
99
errs = append (errs , fmt .Errorf ("invalid target namespaces %v: %w" , o .TargetNamespaces , err ))
85
100
}
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
+
86
109
return o , errs
87
110
}
88
111
@@ -106,6 +129,12 @@ func WithCertificateProvider(provider CertificateProvider) Option {
106
129
}
107
130
}
108
131
132
+ func WithBundleConfig (config * BundleConfig ) Option {
133
+ return func (o * Options ) {
134
+ o .BundleConfig = config
135
+ }
136
+ }
137
+
109
138
type BundleRenderer struct {
110
139
BundleValidator BundleValidator
111
140
ResourceGenerators []ResourceGenerator
@@ -118,13 +147,19 @@ func (r BundleRenderer) Render(rv1 bundle.RegistryV1, installNamespace string, o
118
147
}
119
148
120
149
// generate bundle objects
121
- genOpts , errs := (& Options {
150
+ genOpts := (& Options {
122
151
// default options
123
152
InstallNamespace : installNamespace ,
124
153
TargetNamespaces : []string {metav1 .NamespaceAll },
125
154
UniqueNameGenerator : DefaultUniqueNameGenerator ,
126
155
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 )
128
163
129
164
if len (errs ) > 0 {
130
165
return nil , fmt .Errorf ("invalid option(s): %w" , errors .Join (errs ... ))
@@ -175,3 +210,59 @@ func validateTargetNamespaces(rv1 *bundle.RegistryV1, installNamespace string, t
175
210
}
176
211
return fmt .Errorf ("supported install modes %v do not support target namespaces %v" , sets.List [string ](supportedInstallModes ), targetNamespaces )
177
212
}
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