Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 20 additions & 16 deletions cmd/operator-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,10 +448,18 @@ func run() error {
return err
}

certProvider := getCertificateProvider()
regv1ManifestProvider := &applier.RegistryV1ManifestProvider{
BundleRenderer: registryv1.Renderer,
CertificateProvider: certProvider,
IsWebhookSupportEnabled: certProvider != nil,
IsSingleOwnNamespaceEnabled: features.OperatorControllerFeatureGate.Enabled(features.SingleOwnNamespaceInstallSupport),
}

if features.OperatorControllerFeatureGate.Enabled(features.BoxcutterRuntime) {
err = setupBoxcutter(mgr, ceReconciler, preflights)
err = setupBoxcutter(mgr, ceReconciler, preflights, regv1ManifestProvider)
} else {
err = setupHelm(mgr, ceReconciler, preflights, ceController, clusterExtensionFinalizers)
err = setupHelm(mgr, ceReconciler, preflights, ceController, clusterExtensionFinalizers, regv1ManifestProvider)
}
if err != nil {
setupLog.Error(err, "unable to setup lifecycler")
Expand Down Expand Up @@ -512,9 +520,12 @@ func getCertificateProvider() render.CertificateProvider {
return nil
}

func setupBoxcutter(mgr manager.Manager, ceReconciler *controllers.ClusterExtensionReconciler, preflights []applier.Preflight) error {
certProvider := getCertificateProvider()

func setupBoxcutter(
mgr manager.Manager,
ceReconciler *controllers.ClusterExtensionReconciler,
preflights []applier.Preflight,
regv1ManifestProvider applier.ManifestProvider,
) error {
coreClient, err := corev1client.NewForConfig(mgr.GetConfig())
if err != nil {
return fmt.Errorf("unable to create core client: %w", err)
Expand All @@ -541,11 +552,8 @@ func setupBoxcutter(mgr manager.Manager, ceReconciler *controllers.ClusterExtens
// TODO: better scheme handling - which types do we want to support?
_ = apiextensionsv1.AddToScheme(mgr.GetScheme())
rg := &applier.SimpleRevisionGenerator{
Scheme: mgr.GetScheme(),
BundleRenderer: &applier.RegistryV1BundleRenderer{
BundleRenderer: registryv1.Renderer,
CertificateProvider: certProvider,
},
Scheme: mgr.GetScheme(),
ManifestProvider: regv1ManifestProvider,
}
ceReconciler.Applier = &applier.Boxcutter{
Client: mgr.GetClient(),
Expand Down Expand Up @@ -611,6 +619,7 @@ func setupHelm(
preflights []applier.Preflight,
ceController crcontroller.Controller,
clusterExtensionFinalizers crfinalizer.Registerer,
regv1ManifestProvider applier.ManifestProvider,
) error {
coreClient, err := corev1client.NewForConfig(mgr.GetConfig())
if err != nil {
Expand Down Expand Up @@ -658,17 +667,12 @@ func setupHelm(
return err
}

certProvider := getCertificateProvider()

// now initialize the helmApplier, assigning the potentially nil preAuth
ceReconciler.Applier = &applier.Helm{
ActionClientGetter: acg,
Preflights: preflights,
HelmChartProvider: &applier.RegistryV1HelmChartProvider{
BundleRenderer: registryv1.Renderer,
CertificateProvider: certProvider,
IsWebhookSupportEnabled: certProvider != nil,
IsSingleOwnNamespaceEnabled: features.OperatorControllerFeatureGate.Enabled(features.SingleOwnNamespaceInstallSupport),
ManifestProvider: regv1ManifestProvider,
},
HelmReleaseToObjectsConverter: &applier.HelmReleaseToObjectsConverter{},
PreAuthorizer: preAuth,
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: 6604f2a4e24ca0c4abce99389b1e5dbbe8d8dbfa
expectedMergeBase: 56213a4044e0acadc639a8c2eff38d2a4271cc12
upstreamBranch: main
upstreamOrg: operator-framework
upstreamRepo: operator-controller
36 changes: 3 additions & 33 deletions internal/operator-controller/applier/boxcutter.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
ocv1 "github.com/operator-framework/operator-controller/api/v1"
"github.com/operator-framework/operator-controller/internal/operator-controller/controllers"
"github.com/operator-framework/operator-controller/internal/operator-controller/labels"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
hashutil "github.com/operator-framework/operator-controller/internal/shared/util/hash"
)

Expand All @@ -46,8 +44,8 @@ type ClusterExtensionRevisionGenerator interface {
}

type SimpleRevisionGenerator struct {
Scheme *runtime.Scheme
BundleRenderer BundleRenderer
Scheme *runtime.Scheme
ManifestProvider ManifestProvider
}

func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
Expand Down Expand Up @@ -92,7 +90,7 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
objectLabels, revisionAnnotations map[string]string,
) (*ocv1.ClusterExtensionRevision, error) {
// extract plain manifests
plain, err := r.BundleRenderer.Render(bundleFS, ext)
plain, err := r.ManifestProvider.Get(bundleFS, ext)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -359,34 +357,6 @@ func latestRevisionNumber(prevRevisions []ocv1.ClusterExtensionRevision) int64 {
return prevRevisions[len(prevRevisions)-1].Spec.Revision
}

// TODO: in the next refactor iteration BundleRenderer and RegistryV1BundleRenderer into the RegistryV1ChartProvider

type BundleRenderer interface {
Render(bundleFS fs.FS, ext *ocv1.ClusterExtension) ([]client.Object, error)
}

type RegistryV1BundleRenderer struct {
BundleRenderer render.BundleRenderer
CertificateProvider render.CertificateProvider
}

func (r *RegistryV1BundleRenderer) Render(bundleFS fs.FS, ext *ocv1.ClusterExtension) ([]client.Object, error) {
reg, err := source.FromFS(bundleFS).GetBundle()
if err != nil {
return nil, err
}

if len(reg.CSV.Spec.WebhookDefinitions) > 0 && r.CertificateProvider == nil {
return nil, fmt.Errorf("unsupported bundle: webhookDefinitions are not supported")
}

watchNamespace, err := GetWatchNamespace(ext)
if err != nil {
return nil, err
}
return r.BundleRenderer.Render(reg, ext.Spec.Namespace, render.WithTargetNamespaces(watchNamespace), render.WithCertificateProvider(r.CertificateProvider))
}

func splitManifestDocuments(file string) []string {
//nolint:prealloc
var docs []string
Expand Down
134 changes: 37 additions & 97 deletions internal/operator-controller/applier/boxcutter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,75 +24,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

"github.com/operator-framework/api/pkg/operators/v1alpha1"

ocv1 "github.com/operator-framework/operator-controller/api/v1"
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
"github.com/operator-framework/operator-controller/internal/operator-controller/controllers"
"github.com/operator-framework/operator-controller/internal/operator-controller/labels"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/bundlefs"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/clusterserviceversion"
)

func Test_RegistryV1BundleRenderer_Render_Success(t *testing.T) {
expectedObjs := []client.Object{
&corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service",
},
},
}
r := applier.RegistryV1BundleRenderer{
BundleRenderer: render.BundleRenderer{
ResourceGenerators: []render.ResourceGenerator{
func(rv1 *bundle.RegistryV1, opts render.Options) ([]client.Object, error) {
require.Equal(t, []string{""}, opts.TargetNamespaces)
require.Equal(t, "some-namespace", opts.InstallNamespace)
return expectedObjs, nil
},
},
},
}
bundleFS := bundlefs.Builder().
WithPackageName("some-package").
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).Build()).
Build()
objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Namespace: "some-namespace",
},
})
require.NoError(t, err)
require.Equal(t, expectedObjs, objs)
}

func Test_RegistryV1BundleRenderer_Render_Failure(t *testing.T) {
var expectedObjs []client.Object
r := applier.RegistryV1BundleRenderer{
BundleRenderer: render.BundleRenderer{
ResourceGenerators: []render.ResourceGenerator{
func(rv1 *bundle.RegistryV1, opts render.Options) ([]client.Object, error) {
return expectedObjs, fmt.Errorf("some-error")
},
},
},
}
bundleFS := bundlefs.Builder().
WithPackageName("some-package").
WithCSV(clusterserviceversion.Builder().WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces).Build()).
Build()
objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Namespace: "some-namespace",
},
})
require.Nil(t, objs)
require.Error(t, err)
require.Contains(t, err.Error(), "some-error")
}

func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T) {
g := &applier.SimpleRevisionGenerator{}

Expand Down Expand Up @@ -175,24 +112,26 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T)
}

func Test_SimpleRevisionGenerator_GenerateRevision(t *testing.T) {
var r mockBundleRenderer = func(_ fs.FS, _ *ocv1.ClusterExtension) ([]client.Object, error) {
return []client.Object{
&corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service",
r := &FakeManifestProvider{
GetFn: func(_ fs.FS, _ *ocv1.ClusterExtension) ([]client.Object, error) {
return []client.Object{
&corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service",
},
},
},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "test-deployment",
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "test-deployment",
},
},
},
}, nil
}, nil
},
}

b := applier.SimpleRevisionGenerator{
Scheme: k8scheme.Scheme,
BundleRenderer: r,
Scheme: k8scheme.Scheme,
ManifestProvider: r,
}

ext := &ocv1.ClusterExtension{
Expand Down Expand Up @@ -266,15 +205,17 @@ func Test_SimpleRevisionGenerator_Renderer_Integration(t *testing.T) {
Name: "test-extension",
},
}
var r mockBundleRenderer = func(b fs.FS, e *ocv1.ClusterExtension) ([]client.Object, error) {
t.Log("by checking renderer was called with the correct parameters")
require.Equal(t, bundleFS, b)
require.Equal(t, ext, e)
return nil, nil
r := &FakeManifestProvider{
GetFn: func(b fs.FS, e *ocv1.ClusterExtension) ([]client.Object, error) {
t.Log("by checking renderer was called with the correct parameters")
require.Equal(t, bundleFS, b)
require.Equal(t, ext, e)
return nil, nil
},
}
b := applier.SimpleRevisionGenerator{
Scheme: k8scheme.Scheme,
BundleRenderer: r,
Scheme: k8scheme.Scheme,
ManifestProvider: r,
}

_, err := b.GenerateRevision(bundleFS, ext, map[string]string{}, map[string]string{})
Expand All @@ -300,12 +241,15 @@ func Test_SimpleRevisionGenerator_AppliesObjectLabelsAndRevisionAnnotations(t *t
},
},
}
var r mockBundleRenderer = func(b fs.FS, e *ocv1.ClusterExtension) ([]client.Object, error) {
return renderedObjs, nil
r := &FakeManifestProvider{
GetFn: func(b fs.FS, e *ocv1.ClusterExtension) ([]client.Object, error) {
return renderedObjs, nil
},
}

b := applier.SimpleRevisionGenerator{
Scheme: k8scheme.Scheme,
BundleRenderer: r,
Scheme: k8scheme.Scheme,
ManifestProvider: r,
}

revAnnotations := map[string]string{
Expand All @@ -330,12 +274,14 @@ func Test_SimpleRevisionGenerator_AppliesObjectLabelsAndRevisionAnnotations(t *t
}

func Test_SimpleRevisionGenerator_Failure(t *testing.T) {
var r mockBundleRenderer = func(b fs.FS, e *ocv1.ClusterExtension) ([]client.Object, error) {
return nil, fmt.Errorf("some-error")
r := &FakeManifestProvider{
GetFn: func(b fs.FS, e *ocv1.ClusterExtension) ([]client.Object, error) {
return nil, fmt.Errorf("some-error")
},
}
b := applier.SimpleRevisionGenerator{
Scheme: k8scheme.Scheme,
BundleRenderer: r,
Scheme: k8scheme.Scheme,
ManifestProvider: r,
}

rev, err := b.GenerateRevision(fstest.MapFS{}, &ocv1.ClusterExtension{}, map[string]string{}, map[string]string{})
Expand Down Expand Up @@ -928,12 +874,6 @@ func (m *mockBundleRevisionBuilder) GenerateRevisionFromHelmRelease(
return nil, nil
}

type mockBundleRenderer func(bundleFS fs.FS, ext *ocv1.ClusterExtension) ([]client.Object, error)

func (f mockBundleRenderer) Render(bundleFS fs.FS, ext *ocv1.ClusterExtension) ([]client.Object, error) {
return f(bundleFS, ext)
}

type clientMock struct {
mock.Mock
}
Expand Down
5 changes: 2 additions & 3 deletions internal/operator-controller/applier/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/authorization"
"github.com/operator-framework/operator-controller/internal/operator-controller/contentmanager"
"github.com/operator-framework/operator-controller/internal/operator-controller/features"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util"
imageutil "github.com/operator-framework/operator-controller/internal/shared/util/image"
)

// HelmChartProvider provides helm charts from bundle sources and cluster extensions
type HelmChartProvider interface {
Get(bundle source.BundleSource, clusterExtension *ocv1.ClusterExtension) (*chart.Chart, error)
Get(bundle fs.FS, clusterExtension *ocv1.ClusterExtension) (*chart.Chart, error)
}

type HelmReleaseToObjectsConverter struct {
Expand Down Expand Up @@ -212,7 +211,7 @@ func (h *Helm) buildHelmChart(bundleFS fs.FS, ext *ocv1.ClusterExtension) (*char
)
}
}
return h.HelmChartProvider.Get(source.FromFS(bundleFS), ext)
return h.HelmChartProvider.Get(bundleFS, ext)
}

func (h *Helm) renderClientOnlyRelease(ctx context.Context, ext *ocv1.ClusterExtension, chrt *chart.Chart, values chartutil.Values, post postrender.PostRenderer) (*release.Release, error) {
Expand Down
Loading