Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3a6afed
:seedling: Add yamlfmt to ensure consistent testdata yaml file format…
perdasilva Oct 23, 2025
8b6debd
🐛 OPRUN-4217: OwnNamespace default handling (#2283)
perdasilva Oct 23, 2025
25d3e43
Clean up deprecated feature enablement mechanism (#2285)
tmshort Oct 23, 2025
5e6db8e
Add option to yamlfmt to ignore vendor directories (#2286)
tmshort Oct 24, 2025
f71870d
Add .claude to .gitignore (#2287)
tmshort Oct 24, 2025
882cb76
Merge branch 'main' into synchronize
Oct 24, 2025
1ca76de
UPSTREAM: <carry>: Add OpenShift specific files
dtfranz Oct 26, 2023
5a9c6af
UPSTREAM: <carry>: Add new tests for single/own namespaces install modes
camilamacedo86 Oct 6, 2025
a46bf89
UPSTREAM: <carry>: Upgrade OCP image from 4.20 to 4.21
camilamacedo86 Oct 13, 2025
86558bc
UPSTREAM: <carry>: [Default Catalog Tests] - Change logic to get ocp …
camilamacedo86 Oct 13, 2025
f34fa1a
UPSTREAM: <carry>: Update OCP catalogs to v4.21
tmshort Oct 13, 2025
2f5aa3a
UPSTREAM: <carry>: support singleown cases in disconnected
kuiwang02 Oct 16, 2025
e7f85dc
UPSTREAM: <carry>: fix cases 81696 and 74618 for product code changes
kuiwang02 Oct 17, 2025
56d6387
UPSTREAM: <carry>: Define Default timeouts and apply their usage accr…
camilamacedo86 Oct 22, 2025
fdf1fe0
UPSTREAM: <carry>: Update to new feature-gate options in helm
tmshort Oct 22, 2025
01ad1d2
UPSTREAM: <carry>: Fix flake for single/own ns tests by ensuring uniq…
camilamacedo86 Oct 22, 2025
d8bb33b
UPSTREAM: <carry>: [OTE]: Enhance single/own ns based on review comme…
camilamacedo86 Oct 24, 2025
f008dc1
UPSTREAM: <drop>: go mod vendor
Oct 24, 2025
96bc2c3
UPSTREAM: <drop>: remove upstream GitHub configuration
Oct 24, 2025
b96f1ca
UPSTREAM: <drop>: configure the commit-checker
Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .bingo/Variables.mk
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,9 @@ $(SETUP_ENVTEST): $(BINGO_DIR)/setup-envtest.mod
@echo "(re)installing $(GOBIN)/setup-envtest-v0.0.0-20250620151452-b9a9ca01fd37"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=setup-envtest.mod -o=$(GOBIN)/setup-envtest-v0.0.0-20250620151452-b9a9ca01fd37 "sigs.k8s.io/controller-runtime/tools/setup-envtest"

YAMLFMT := $(GOBIN)/yamlfmt-v0.20.0
$(YAMLFMT): $(BINGO_DIR)/yamlfmt.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
@echo "(re)installing $(GOBIN)/yamlfmt-v0.20.0"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=yamlfmt.mod -o=$(GOBIN)/yamlfmt-v0.20.0 "github.com/google/yamlfmt/cmd/yamlfmt"

2 changes: 2 additions & 0 deletions .bingo/variables.env
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ OPM="${GOBIN}/opm-v1.51.0"

SETUP_ENVTEST="${GOBIN}/setup-envtest-v0.0.0-20250620151452-b9a9ca01fd37"

YAMLFMT="${GOBIN}/yamlfmt-v0.20.0"

5 changes: 5 additions & 0 deletions .bingo/yamlfmt.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT

go 1.24.4

require github.com/google/yamlfmt v0.20.0 // cmd/yamlfmt
16 changes: 16 additions & 0 deletions .bingo/yamlfmt.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/yamlfmt v0.20.0 h1:EfMuMFEZGnXPn2NY+KgJTH9sNs6P+am/Of6IwE2K6P8=
github.com/google/yamlfmt v0.20.0/go.mod h1:gs0UEklJOYkUJ+OOCG0hg9n+DzucKDPlJElTUasVNK8=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ vendor/
\#*\#
.\#*

# AI temp files files
.claude/

# documentation website asset folder
site

.tiltbuild/
.catalogd-tmp/
.vscode

# Tmporary files and directories
# Temporary files and directories
/test/regression/convert/testdata/tmp/*
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ update-crds:
#
# Override HELM_SETTINGS on the command line to include additional Helm settings
# e.g. make HELM_SETTINGS="options.openshift.enabled=true" manifests
# e.g. make HELM_SETTINGS="operatorControllerFeatures={WebhookProviderCertManager}" manifests
# e.g. make HELM_SETTINGS="options.operatorController.features.enabled={WebhookProviderCertManager}" manifests
#
MANIFESTS ?= $(STANDARD_MANIFEST) $(STANDARD_E2E_MANIFEST) $(EXPERIMENTAL_MANIFEST) $(EXPERIMENTAL_E2E_MANIFEST)
$(STANDARD_MANIFEST) ?= helm/cert-manager.yaml
Expand Down Expand Up @@ -186,8 +186,9 @@ fix-lint: $(GOLANGCI_LINT) #EXHELP Fix lint issues
$(GOLANGCI_LINT) run --fix --build-tags $(GO_BUILD_TAGS) $(GOLANGCI_LINT_ARGS)

.PHONY: fmt
fmt: #EXHELP Formats code
fmt: $(YAMLFMT) #EXHELP Formats code
go fmt ./...
$(YAMLFMT) -gitignore_excludes testdata

.PHONY: update-tls-profiles
update-tls-profiles: $(GOJQ) #EXHELP Update TLS profiles from the Mozilla wiki
Expand Down
2 changes: 1 addition & 1 deletion commitchecker.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
expectedMergeBase: 926d57e1e6559f7ac0ef69a47b3d50d96975ec38
expectedMergeBase: f71870daded48936c5d2012211a885b339d1182f
upstreamBranch: main
upstreamOrg: operator-framework
upstreamRepo: operator-controller
42 changes: 37 additions & 5 deletions docs/draft/howto/single-ownnamespace-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,43 @@ kubectl rollout status -n olmv1-system deployment/operator-controller-controller
## Configuring the `ClusterExtension`

A `ClusterExtension` can be configured to install bundle in `Single-` or `OwnNamespace` mode through the
`.spec.config.inline.watchNamespace` property. The *installMode* is inferred in the following way:

- *AllNamespaces*: `watchNamespace` is empty, or not set
- *OwnNamespace*: `watchNamespace` is the install namespace (i.e. `.spec.namespace`)
- *SingleNamespace*: `watchNamespace` *not* the install namespace
`.spec.config.inline.watchNamespace` property which may or may not be present or required depending on the bundle's
install mode support, if the bundle:

- only supports *AllNamespaces* mode => `watchNamespace` is not a configuration
- supports *AllNamespaces* and *SingleNamespace* and/or *OwnNamespace* => `watchNamespace` is optional
- bundle only supports *SingleNamespace* and/or *OwnNamespace* => `watchNamespace` is required

The `watchNamespace` configuration can only be the install namespace if the bundle supports the *OwnNamespace* install mode, and
it can only be any other namespace if the bundle supports the *SingleNamespace* install mode.

Examples:

Bundle only supports *AllNamespaces*:
- `watchNamespace` is not a configuration
- bundle will be installed in *AllNamespaces* mode

Bundle only supports *OwnNamespace*:
- `watchNamespace` is required
- `watchNamespace` must be the install namespace
- bundle will always be installed in *OwnNamespace* mode

Bundle supports *AllNamespace* and *OwnNamespace*:
- `watchNamespace` is optional
- if `watchNamespace` = install namespace => bundle will be installed in *OwnNamespace* mode
- if `watchNamespace` is null or not set => bundle will be installed in *AllNamespaces* mode
- if `watchNamespace` != install namespace => error

Bundle only supports *SingleNamespace*:
- `watchNamespace` is required
- `watchNamespace` must *NOT* be the install namespace
- bundle will always be installed in *SingleNamespace* mode

Bundle supports *AllNamespaces*, *SingleNamespace*, and *OwnNamespace* install modes:
- `watchNamespace` can be optionally configured
- if `watchNamespace` = install namespace => bundle will be installed in *OwnNamespace* mode
- if `watchNamespace` != install namespace => bundle will be installed in *SingleNamespace* mode
- if `watchNamespace` is null or not set => bundle will be installed in *AllNamespaces* mode

### Examples

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ spec:
{{- end }}
- --metrics-bind-address=:7443
- --external-address=catalogd-service.{{ .Values.namespaces.olmv1.name }}.svc
{{- range .Values.catalogdFeatures }}
- --feature-gates={{- . -}}=true
{{- end }}
{{- range .Values.options.catalogd.features.enabled }}
- --feature-gates={{- . -}}=true
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ spec:
{{- if not .Values.options.tilt.enabled }}
- --leader-elect
{{- end }}
{{- range .Values.operatorControllerFeatures }}
- --feature-gates={{- . -}}=true
{{- end }}
{{- range .Values.options.operatorController.features.enabled }}
- --feature-gates={{- . -}}=true
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ metadata:
labels:
app.kubernetes.io/name: operator-controller
{{- include "olmv1.labels" $ | nindent 4 }}
{{- if or (has "BoxcutterRuntime" .Values.options.operatorController.features.enabled) (has "BoxcutterRuntime" .Values.operatorControllerFeatures) }}
{{- if has "BoxcutterRuntime" .Values.options.operatorController.features.enabled }}
name: operator-controller-manager-admin-rolebinding
{{- else }}
name: operator-controller-manager-rolebinding
{{- end }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
{{- if or (has "BoxcutterRuntime" .Values.options.operatorController.features.enabled) (has "BoxcutterRuntime" .Values.operatorControllerFeatures) }}
{{- if has "BoxcutterRuntime" .Values.options.operatorController.features.enabled }}
name: cluster-admin
{{- else }}
name: operator-controller-manager-role
Expand Down
4 changes: 0 additions & 4 deletions helm/olmv1/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ options:
# This can be one of: standard or experimental
featureSet: standard

# Deprecated: The list of features
operatorControllerFeatures: []
catalogdFeatures: []

# The set of namespaces
namespaces:
olmv1:
Expand Down
24 changes: 22 additions & 2 deletions internal/operator-controller/applier/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,14 @@ func (r *RegistryV1ManifestProvider) Get(bundleFS fs.FS, ext *ocv1.ClusterExtens
render.WithCertificateProvider(r.CertificateProvider),
}

if r.IsSingleOwnNamespaceEnabled && ext.Spec.Config != nil && ext.Spec.Config.ConfigType == ocv1.ClusterExtensionConfigTypeInline {
bundleConfig, err := bundle.UnmarshallConfig(ext.Spec.Config.Inline.Raw, rv1, ext.Spec.Namespace)
if r.IsSingleOwnNamespaceEnabled {
bundleConfigBytes := extensionConfigBytes(ext)
// treat no config as empty to properly validate the configuration
// e.g. ensure that validation catches missing required fields
if bundleConfigBytes == nil {
bundleConfigBytes = []byte(`{}`)
}
bundleConfig, err := bundle.UnmarshalConfig(bundleConfigBytes, rv1, ext.Spec.Namespace)
if err != nil {
return nil, fmt.Errorf("invalid bundle configuration: %w", err)
}
Expand Down Expand Up @@ -128,3 +134,17 @@ func (r *RegistryV1HelmChartProvider) Get(bundleFS fs.FS, ext *ocv1.ClusterExten

return chrt, nil
}

// ExtensionConfigBytes returns the ClusterExtension configuration input by the user
// through .spec.config as a byte slice.
func extensionConfigBytes(ext *ocv1.ClusterExtension) []byte {
if ext.Spec.Config != nil {
switch ext.Spec.Config.ConfigType {
case ocv1.ClusterExtensionConfigTypeInline:
if ext.Spec.Config.Inline != nil {
return ext.Spec.Config.Inline.Raw
}
}
}
return nil
}
84 changes: 72 additions & 12 deletions internal/operator-controller/applier/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,6 @@ func Test_RegistryV1ManifestProvider_SingleOwnNamespaceSupport(t *testing.T) {
t.Run("rejects bundles without AllNamespaces install mode and with SingleNamespace support when Single/OwnNamespace install mode support is enabled", func(t *testing.T) {
expectedWatchNamespace := "some-namespace"
provider := applier.RegistryV1ManifestProvider{
BundleRenderer: render.BundleRenderer{
ResourceGenerators: []render.ResourceGenerator{
func(rv1 *bundle.RegistryV1, opts render.Options) ([]client.Object, error) {
t.Log("ensure watch namespace is appropriately configured")
require.Equal(t, []string{expectedWatchNamespace}, opts.TargetNamespaces)
return nil, nil
},
},
},
IsSingleOwnNamespaceEnabled: false,
}

Expand Down Expand Up @@ -289,7 +280,7 @@ func Test_RegistryV1ManifestProvider_SingleOwnNamespaceSupport(t *testing.T) {
require.Contains(t, err.Error(), "unsupported bundle")
})

t.Run("accepts bundles without AllNamespaces install mode and with SingleNamespace support when Single/OwnNamespace install mode support is enabled", func(t *testing.T) {
t.Run("accepts bundles with install modes {SingleNamespace} when the appropriate configuration is given", func(t *testing.T) {
expectedWatchNamespace := "some-namespace"
provider := applier.RegistryV1ManifestProvider{
BundleRenderer: render.BundleRenderer{
Expand Down Expand Up @@ -321,20 +312,89 @@ func Test_RegistryV1ManifestProvider_SingleOwnNamespaceSupport(t *testing.T) {
require.NoError(t, err)
})

t.Run("accepts bundles without AllNamespaces install mode and with OwnNamespace support when Single/OwnNamespace install mode support is enabled", func(t *testing.T) {
t.Run("rejects bundles with {SingleNamespace} install modes when no configuration is given", func(t *testing.T) {
provider := applier.RegistryV1ManifestProvider{
IsSingleOwnNamespaceEnabled: true,
}

bundleFS := bundlefs.Builder().WithPackageName("test").
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeOwnNamespace).Build()).Build()
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeSingleNamespace).Build()).Build()

_, err := provider.Get(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Namespace: "install-namespace",
},
})
require.Error(t, err)
require.Contains(t, err.Error(), "required field \"watchNamespace\" is missing")
})

t.Run("accepts bundles with {OwnNamespace} install modes when the appropriate configuration is given", func(t *testing.T) {
installNamespace := "some-namespace"
provider := applier.RegistryV1ManifestProvider{
BundleRenderer: render.BundleRenderer{
ResourceGenerators: []render.ResourceGenerator{
func(rv1 *bundle.RegistryV1, opts render.Options) ([]client.Object, error) {
t.Log("ensure watch namespace is appropriately configured")
require.Equal(t, []string{installNamespace}, opts.TargetNamespaces)
return nil, nil
},
},
},
IsSingleOwnNamespaceEnabled: true,
}
bundleFS := bundlefs.Builder().WithPackageName("test").
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeOwnNamespace).Build()).Build()
_, err := provider.Get(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Namespace: installNamespace,
Config: &ocv1.ClusterExtensionConfig{
ConfigType: ocv1.ClusterExtensionConfigTypeInline,
Inline: &apiextensionsv1.JSON{
Raw: []byte(`{"watchNamespace": "` + installNamespace + `"}`),
},
},
},
})
require.NoError(t, err)
})

t.Run("rejects bundles with {OwnNamespace} install modes when no configuration is given", func(t *testing.T) {
provider := applier.RegistryV1ManifestProvider{
IsSingleOwnNamespaceEnabled: true,
}
bundleFS := bundlefs.Builder().WithPackageName("test").
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeOwnNamespace).Build()).Build()
_, err := provider.Get(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Namespace: "install-namespace",
},
})
require.Error(t, err)
require.Contains(t, err.Error(), "required field \"watchNamespace\" is missing")
})

t.Run("rejects bundles with {OwnNamespace} install modes when watchNamespace is not install namespace", func(t *testing.T) {
provider := applier.RegistryV1ManifestProvider{
IsSingleOwnNamespaceEnabled: true,
}
bundleFS := bundlefs.Builder().WithPackageName("test").
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeOwnNamespace).Build()).Build()
_, err := provider.Get(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Namespace: "install-namespace",
Config: &ocv1.ClusterExtensionConfig{
ConfigType: ocv1.ClusterExtensionConfigTypeInline,
Inline: &apiextensionsv1.JSON{
Raw: []byte(`{"watchNamespace": "not-install-namespace"}`),
},
},
},
})
require.Error(t, err)
require.Contains(t, err.Error(), "invalid 'watchNamespace' \"not-install-namespace\": must be install namespace (install-namespace)")
})

t.Run("rejects bundles without AllNamespaces, SingleNamespace, or OwnNamespace install mode support when Single/OwnNamespace install mode support is enabled", func(t *testing.T) {
provider := applier.RegistryV1ManifestProvider{
IsSingleOwnNamespaceEnabled: true,
Expand Down
29 changes: 14 additions & 15 deletions internal/operator-controller/rukpak/bundle/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ type Config struct {
WatchNamespace *string `json:"watchNamespace"`
}

// UnmarshallConfig returns a deserialized and validated *bundle.Config based on bytes and validated
// UnmarshalConfig returns a deserialized *bundle.Config based on bytes and validated
// against rv1 and the desired install namespaces. It will error if:
// - rv is nil
// - bytes is not a valid YAML/JSON object
// - bytes is a valid YAML/JSON object but does not follow the registry+v1 schema
// if bytes is nil a nil bundle.Config is returned
func UnmarshallConfig(bytes []byte, rv1 RegistryV1, installNamespace string) (*Config, error) {
// - if bytes is nil, a nil *bundle.Config is returned with no error
func UnmarshalConfig(bytes []byte, rv1 RegistryV1, installNamespace string) (*Config, error) {
if bytes == nil {
return nil, nil
}

bundleConfig := &Config{}
if err := yaml.UnmarshalStrict(bytes, bundleConfig); err != nil {
return nil, fmt.Errorf("error unmarshalling registry+v1 configuration: %w", formatUnmarshallError(err))
return nil, fmt.Errorf("error unmarshalling registry+v1 configuration: %w", formatUnmarshalError(err))
}

// collect bundle install modes
Expand Down Expand Up @@ -83,24 +83,23 @@ func validateConfig(config *Config, installNamespace string, bundleInstallModeSe
}

// isWatchNamespaceConfigSupported returns true when the bundle exposes a watchNamespace configuration. This happens when:
// - SingleNamespace install more is supported, or
// - OwnNamespace and AllNamespaces install modes are supported
// - SingleNamespace and/or OwnNamespace install modes are supported
func isWatchNamespaceConfigSupported(bundleInstallModeSet sets.Set[v1alpha1.InstallMode]) bool {
return bundleInstallModeSet.Has(v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true}) ||
bundleInstallModeSet.HasAll(
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true},
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true})
return bundleInstallModeSet.HasAny(
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true},
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true},
)
}

// isWatchNamespaceConfigRequired returns true if the watchNamespace configuration is required. This happens when
// AllNamespaces install mode is not supported and SingleNamespace is supported
// AllNamespaces install mode is not supported and SingleNamespace and/or OwnNamespace is supported
func isWatchNamespaceConfigRequired(bundleInstallModeSet sets.Set[v1alpha1.InstallMode]) bool {
return !bundleInstallModeSet.Has(v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true}) &&
bundleInstallModeSet.Has(v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true})
return isWatchNamespaceConfigSupported(bundleInstallModeSet) &&
!bundleInstallModeSet.Has(v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true})
}

// formatUnmarshallError format JSON unmarshal errors to be more readable
func formatUnmarshallError(err error) error {
// formatUnmarshalError format JSON unmarshal errors to be more readable
func formatUnmarshalError(err error) error {
var unmarshalErr *json.UnmarshalTypeError
if errors.As(err, &unmarshalErr) {
if unmarshalErr.Field == "" {
Expand Down
Loading