Skip to content

Commit 9ff2816

Browse files
Merge pull request #497 from tmshort/synchronize
NO-ISSUE: Synchronize From Upstream Repositories
2 parents d6b8f7f + 23cd611 commit 9ff2816

File tree

22 files changed

+989
-744
lines changed

22 files changed

+989
-744
lines changed

cmd/operator-controller/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,10 @@ func setupHelm(
655655
ActionClientGetter: acg,
656656
Preflights: preflights,
657657
HelmChartProvider: &applier.RegistryV1HelmChartProvider{
658-
BundleRenderer: registryv1.Renderer,
659-
CertificateProvider: certProvider,
660-
IsWebhookSupportEnabled: certProvider != nil,
658+
BundleRenderer: registryv1.Renderer,
659+
CertificateProvider: certProvider,
660+
IsWebhookSupportEnabled: certProvider != nil,
661+
IsSingleOwnNamespaceEnabled: features.OperatorControllerFeatureGate.Enabled(features.SingleOwnNamespaceInstallSupport),
661662
},
662663
HelmReleaseToObjectsConverter: &applier.HelmReleaseToObjectsConverter{},
663664
PreAuthorizer: preAuth,

commitchecker.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
expectedMergeBase: 588ad5dff70f193ceb19820996d347430a631faa
1+
expectedMergeBase: 35da385077935545a4eaadc338015e249a6df211
22
upstreamBranch: main
33
upstreamOrg: operator-framework
44
upstreamRepo: operator-controller

go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ require (
1818
github.com/klauspost/compress v1.18.0
1919
github.com/opencontainers/go-digest v1.0.0
2020
github.com/opencontainers/image-spec v1.1.1
21-
github.com/operator-framework/api v0.34.0
21+
github.com/operator-framework/api v0.35.0
2222
github.com/operator-framework/helm-operator-plugins v0.8.0
2323
github.com/operator-framework/operator-registry v1.59.0
2424
github.com/prometheus/client_golang v1.23.2
@@ -31,13 +31,13 @@ require (
3131
golang.org/x/sync v0.17.0
3232
golang.org/x/tools v0.37.0
3333
helm.sh/helm/v3 v3.19.0
34-
k8s.io/api v0.34.0
35-
k8s.io/apiextensions-apiserver v0.34.0
36-
k8s.io/apimachinery v0.34.0
37-
k8s.io/apiserver v0.34.0
34+
k8s.io/api v0.34.1
35+
k8s.io/apiextensions-apiserver v0.34.1
36+
k8s.io/apimachinery v0.34.1
37+
k8s.io/apiserver v0.34.1
3838
k8s.io/cli-runtime v0.34.0
39-
k8s.io/client-go v0.34.0
40-
k8s.io/component-base v0.34.0
39+
k8s.io/client-go v0.34.1
40+
k8s.io/component-base v0.34.1
4141
k8s.io/klog/v2 v2.130.1
4242
k8s.io/kubernetes v1.34.0
4343
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
388388
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
389389
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
390390
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
391-
github.com/operator-framework/api v0.34.0 h1:REiEaYhG1CWmDoajdcAdZqtgoljWG+ixMY59vUX5pFI=
392-
github.com/operator-framework/api v0.34.0/go.mod h1:eGncUNIYvWtfGCCKmLzGXvoi3P0TDf3Yd/Z0Sn9E6SQ=
391+
github.com/operator-framework/api v0.35.0 h1:xKrffuGEagk3CWy6zqdK5YmIErlBtWUblNNK+q7ld7c=
392+
github.com/operator-framework/api v0.35.0/go.mod h1:A9UNu/pdcO1RauMHvV54unp4DNm/Y5fMVbGDpnIIF+M=
393393
github.com/operator-framework/helm-operator-plugins v0.8.0 h1:0f6HOQC5likkf0b/OvGvw7nhDb6h8Cj5twdCNjwNzMc=
394394
github.com/operator-framework/helm-operator-plugins v0.8.0/go.mod h1:Sc+8bE38xTCgCChBUvtq/PxatEg9fAypr7S5iAw8nlA=
395395
github.com/operator-framework/operator-lib v0.17.0 h1:cbz51wZ9+GpWR1ZYP4CSKSSBxDlWxmmnseaHVZZjZt4=

internal/operator-controller/applier/boxcutter_test.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ import (
2424
"sigs.k8s.io/controller-runtime/pkg/client"
2525
"sigs.k8s.io/controller-runtime/pkg/client/fake"
2626

27+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
28+
2729
ocv1 "github.com/operator-framework/operator-controller/api/v1"
2830
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
2931
"github.com/operator-framework/operator-controller/internal/operator-controller/controllers"
3032
"github.com/operator-framework/operator-controller/internal/operator-controller/labels"
3133
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle"
3234
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
33-
testutils "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
35+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/bundlefs"
36+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/clusterserviceversion"
3437
)
3538

3639
func Test_RegistryV1BundleRenderer_Render_Success(t *testing.T) {
@@ -52,8 +55,10 @@ func Test_RegistryV1BundleRenderer_Render_Success(t *testing.T) {
5255
},
5356
},
5457
}
55-
bundleFS := testutils.NewBundleFS()
56-
58+
bundleFS := bundlefs.Builder().
59+
WithPackageName("some-package").
60+
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).Build()).
61+
Build()
5762
objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
5863
Spec: ocv1.ClusterExtensionSpec{
5964
Namespace: "some-namespace",
@@ -74,8 +79,10 @@ func Test_RegistryV1BundleRenderer_Render_Failure(t *testing.T) {
7479
},
7580
},
7681
}
77-
bundleFS := testutils.NewBundleFS()
78-
82+
bundleFS := bundlefs.Builder().
83+
WithPackageName("some-package").
84+
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).Build()).
85+
Build()
7986
objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
8087
Spec: ocv1.ClusterExtensionSpec{
8188
Namespace: "some-namespace",

internal/operator-controller/applier/provider.go

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,20 @@ import (
66
"fmt"
77

88
"helm.sh/helm/v3/pkg/chart"
9+
"k8s.io/apimachinery/pkg/util/sets"
10+
11+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
912

1013
ocv1 "github.com/operator-framework/operator-controller/api/v1"
1114
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
1215
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
1316
)
1417

1518
type RegistryV1HelmChartProvider struct {
16-
BundleRenderer render.BundleRenderer
17-
CertificateProvider render.CertificateProvider
18-
IsWebhookSupportEnabled bool
19+
BundleRenderer render.BundleRenderer
20+
CertificateProvider render.CertificateProvider
21+
IsWebhookSupportEnabled bool
22+
IsSingleOwnNamespaceEnabled bool
1923
}
2024

2125
func (r *RegistryV1HelmChartProvider) Get(bundle source.BundleSource, ext *ocv1.ClusterExtension) (*chart.Chart, error) {
@@ -24,18 +28,6 @@ func (r *RegistryV1HelmChartProvider) Get(bundle source.BundleSource, ext *ocv1.
2428
return nil, err
2529
}
2630

27-
watchNamespace, err := GetWatchNamespace(ext)
28-
if err != nil {
29-
return nil, err
30-
}
31-
32-
opts := []render.Option{
33-
render.WithCertificateProvider(r.CertificateProvider),
34-
}
35-
if watchNamespace != "" {
36-
opts = append(opts, render.WithTargetNamespaces(watchNamespace))
37-
}
38-
3931
if len(rv1.CSV.Spec.APIServiceDefinitions.Owned) > 0 {
4032
return nil, fmt.Errorf("unsupported bundle: apiServiceDefintions are not supported")
4133
}
@@ -48,8 +40,35 @@ func (r *RegistryV1HelmChartProvider) Get(bundle source.BundleSource, ext *ocv1.
4840
}
4941
}
5042

51-
if r.CertificateProvider == nil && len(rv1.CSV.Spec.WebhookDefinitions) > 0 {
52-
return nil, fmt.Errorf("unsupported bundle: webhookDefinitions are not supported")
43+
installModes := sets.New(rv1.CSV.Spec.InstallModes...)
44+
if !r.IsSingleOwnNamespaceEnabled && !installModes.Has(v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true}) {
45+
return nil, fmt.Errorf("unsupported bundle: bundle does not support AllNamespaces install mode")
46+
}
47+
48+
if !installModes.HasAny(
49+
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true},
50+
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true},
51+
v1alpha1.InstallMode{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true},
52+
) {
53+
return nil, fmt.Errorf("unsupported bundle: bundle must support at least one of [AllNamespaces SingleNamespace OwnNamespace] install modes")
54+
}
55+
56+
opts := []render.Option{
57+
render.WithCertificateProvider(r.CertificateProvider),
58+
}
59+
60+
// TODO: in a follow up PR we'll split this into two components:
61+
// 1. takes a bundle + cluster extension => manifests
62+
// 2. takes a bundle + cluster extension => chart (which will use the component in 1. under the hood)
63+
// GetWatchNamespace will move under the component in 1. and also be reused by the component that
64+
// takes bundle + cluster extension => revision
65+
watchNamespace, err := GetWatchNamespace(ext)
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
if watchNamespace != "" {
71+
opts = append(opts, render.WithTargetNamespaces(watchNamespace))
5372
}
5473

5574
objs, err := r.BundleRenderer.Render(rv1, ext.Spec.Namespace, opts...)

internal/operator-controller/applier/provider_test.go

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
2222
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
2323
. "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
24+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/clusterserviceversion"
2425
)
2526

2627
func Test_RegistryV1HelmChartProvider_Get_ReturnsBundleSourceFailures(t *testing.T) {
@@ -51,7 +52,7 @@ func Test_RegistryV1HelmChartProvider_Get_ReturnsBundleRendererFailures(t *testi
5152

5253
b := source.FromBundle(
5354
bundle.RegistryV1{
54-
CSV: MakeCSV(WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces)),
55+
CSV: clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).Build(),
5556
},
5657
)
5758

@@ -70,7 +71,7 @@ func Test_RegistryV1HelmChartProvider_Get_NoAPIServiceDefinitions(t *testing.T)
7071

7172
b := source.FromBundle(
7273
bundle.RegistryV1{
73-
CSV: MakeCSV(WithOwnedAPIServiceDescriptions(v1alpha1.APIServiceDescription{})),
74+
CSV: clusterserviceversion.Builder().WithOwnedAPIServiceDescriptions(v1alpha1.APIServiceDescription{}).Build(),
7475
},
7576
)
7677

@@ -85,14 +86,86 @@ func Test_RegistryV1HelmChartProvider_Get_NoAPIServiceDefinitions(t *testing.T)
8586
require.Contains(t, err.Error(), "unsupported bundle: apiServiceDefintions are not supported")
8687
}
8788

89+
func Test_RegistryV1HelmChartProvider_Get_SingleOwnNamespace(t *testing.T) {
90+
t.Run("rejects bundles without AllNamespaces install mode support if SingleOwnNamespace is not enabled", func(t *testing.T) {
91+
provider := applier.RegistryV1HelmChartProvider{}
92+
93+
b := source.FromBundle(
94+
bundle.RegistryV1{
95+
CSV: clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeOwnNamespace).Build(),
96+
},
97+
)
98+
99+
ext := &ocv1.ClusterExtension{
100+
Spec: ocv1.ClusterExtensionSpec{
101+
Namespace: "install-namespace",
102+
},
103+
}
104+
105+
_, err := provider.Get(b, ext)
106+
require.Error(t, err)
107+
require.Contains(t, err.Error(), "unsupported bundle: bundle does not support AllNamespaces install mode")
108+
})
109+
t.Run("accepts bundles with SingleNamespace install mode support if SingleOwnNamespace is enabled", func(t *testing.T) {
110+
// TODO: this will be removed in a follow-up PR that will refactor GetWatchNamespace's location
111+
featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.SingleOwnNamespaceInstallSupport, true)
112+
provider := applier.RegistryV1HelmChartProvider{
113+
IsSingleOwnNamespaceEnabled: true,
114+
}
115+
116+
b := source.FromBundle(
117+
bundle.RegistryV1{
118+
CSV: clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeSingleNamespace).Build(),
119+
},
120+
)
121+
122+
ext := &ocv1.ClusterExtension{
123+
Spec: ocv1.ClusterExtensionSpec{
124+
Namespace: "install-namespace",
125+
Config: &ocv1.ClusterExtensionConfig{
126+
ConfigType: ocv1.ClusterExtensionConfigTypeInline,
127+
Inline: &apiextensionsv1.JSON{
128+
Raw: []byte(`{"watchNamespace": "some-namespace"}`),
129+
},
130+
},
131+
},
132+
}
133+
134+
_, err := provider.Get(b, ext)
135+
require.NoError(t, err)
136+
})
137+
t.Run("accepts bundles with OwnNamespace install mode support if SingleOwnNamespace is enabled", func(t *testing.T) {
138+
// TODO: this will be removed in a follow-up PR that will refactor GetWatchNamespace's location
139+
featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.SingleOwnNamespaceInstallSupport, true)
140+
provider := applier.RegistryV1HelmChartProvider{
141+
IsSingleOwnNamespaceEnabled: true,
142+
}
143+
144+
b := source.FromBundle(
145+
bundle.RegistryV1{
146+
CSV: clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeOwnNamespace).Build(),
147+
},
148+
)
149+
150+
ext := &ocv1.ClusterExtension{
151+
Spec: ocv1.ClusterExtensionSpec{
152+
Namespace: "install-namespace",
153+
},
154+
}
155+
156+
_, err := provider.Get(b, ext)
157+
require.NoError(t, err)
158+
})
159+
}
160+
88161
func Test_RegistryV1HelmChartProvider_Get_NoWebhooksWithoutCertProvider(t *testing.T) {
89162
provider := applier.RegistryV1HelmChartProvider{
90163
IsWebhookSupportEnabled: true,
91164
}
92165

93166
b := source.FromBundle(
94167
bundle.RegistryV1{
95-
CSV: MakeCSV(WithWebhookDefinitions(v1alpha1.WebhookDescription{})),
168+
CSV: clusterserviceversion.Builder().WithWebhookDefinitions(v1alpha1.WebhookDescription{}).Build(),
96169
},
97170
)
98171

@@ -114,7 +187,7 @@ func Test_RegistryV1HelmChartProvider_Get_WebhooksSupportDisabled(t *testing.T)
114187

115188
b := source.FromBundle(
116189
bundle.RegistryV1{
117-
CSV: MakeCSV(WithWebhookDefinitions(v1alpha1.WebhookDescription{})),
190+
CSV: clusterserviceversion.Builder().WithWebhookDefinitions(v1alpha1.WebhookDescription{}).Build(),
118191
},
119192
)
120193

@@ -137,10 +210,9 @@ func Test_RegistryV1HelmChartProvider_Get_WebhooksWithCertProvider(t *testing.T)
137210

138211
b := source.FromBundle(
139212
bundle.RegistryV1{
140-
CSV: MakeCSV(
141-
WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces),
142-
WithWebhookDefinitions(v1alpha1.WebhookDescription{}),
143-
),
213+
CSV: clusterserviceversion.Builder().
214+
WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).
215+
WithWebhookDefinitions(v1alpha1.WebhookDescription{}).Build(),
144216
},
145217
)
146218

@@ -173,7 +245,7 @@ func Test_RegistryV1HelmChartProvider_Get_BundleRendererIntegration(t *testing.T
173245

174246
b := source.FromBundle(
175247
bundle.RegistryV1{
176-
CSV: MakeCSV(WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces, v1alpha1.InstallModeTypeSingleNamespace)),
248+
CSV: clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces, v1alpha1.InstallModeTypeSingleNamespace).Build(),
177249
},
178250
)
179251

@@ -243,10 +315,9 @@ func Test_RegistryV1HelmChartProvider_Get_Success(t *testing.T) {
243315

244316
b := source.FromBundle(
245317
bundle.RegistryV1{
246-
CSV: MakeCSV(
247-
WithAnnotations(map[string]string{"foo": "bar"}),
248-
WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces),
249-
),
318+
CSV: clusterserviceversion.Builder().
319+
WithAnnotations(map[string]string{"foo": "bar"}).
320+
WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).Build(),
250321
Others: []unstructured.Unstructured{
251322
*ToUnstructuredT(t, &corev1.Service{
252323
TypeMeta: metav1.TypeMeta{

internal/operator-controller/rukpak/bundle/source/source.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ type BundleSource interface {
2424
GetBundle() (bundle.RegistryV1, error)
2525
}
2626

27+
type RegistryV1Properties struct {
28+
Properties []property.Property `json:"properties"`
29+
}
30+
2731
// identitySource is a bundle source that returns itself
2832
type identitySource bundle.RegistryV1
2933

@@ -158,11 +162,7 @@ func copyMetadataPropertiesToCSV(csv *v1alpha1.ClusterServiceVersion, fsys fs.FS
158162

159163
// Otherwise, we need to parse the properties.yaml file and
160164
// append its properties into the CSV annotation.
161-
type registryV1Properties struct {
162-
Properties []property.Property `json:"properties"`
163-
}
164-
165-
var metadataProperties registryV1Properties
165+
var metadataProperties RegistryV1Properties
166166
if err := yaml.Unmarshal(metadataPropertiesJSON, &metadataProperties); err != nil {
167167
return fmt.Errorf("failed to unmarshal metadata/properties.yaml: %w", err)
168168
}

0 commit comments

Comments
 (0)