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
11 changes: 9 additions & 2 deletions internal/operator-controller/applier/boxcutter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ 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"
testutils "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/bundlefs"
)

func Test_RegistryV1BundleRenderer_Render_Success(t *testing.T) {
Expand All @@ -52,7 +55,9 @@ func Test_RegistryV1BundleRenderer_Render_Success(t *testing.T) {
},
},
}
bundleFS := testutils.NewBundleFS()
bundleFS := bundlefs.Builder().
WithPackageName("some-package").
WithCSV(testutils.MakeCSV(testutils.WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces))).Build()

objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Expand All @@ -74,7 +79,9 @@ func Test_RegistryV1BundleRenderer_Render_Failure(t *testing.T) {
},
},
}
bundleFS := testutils.NewBundleFS()
bundleFS := bundlefs.Builder().
WithPackageName("some-package").
WithCSV(testutils.MakeCSV(testutils.WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces))).Build()

objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
Spec: ocv1.ClusterExtensionSpec{
Expand Down
10 changes: 5 additions & 5 deletions internal/operator-controller/rukpak/bundle/source/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ type BundleSource interface {
GetBundle() (bundle.RegistryV1, error)
}

type RegistryV1Properties struct {
Properties []property.Property `json:"properties"`
}

// identitySource is a bundle source that returns itself
type identitySource bundle.RegistryV1

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

// Otherwise, we need to parse the properties.yaml file and
// append its properties into the CSV annotation.
type registryV1Properties struct {
Properties []property.Property `json:"properties"`
}

var metadataProperties registryV1Properties
var metadataProperties RegistryV1Properties
if err := yaml.Unmarshal(metadataPropertiesJSON, &metadataProperties); err != nil {
return fmt.Errorf("failed to unmarshal metadata/properties.yaml: %w", err)
}
Expand Down
60 changes: 39 additions & 21 deletions internal/operator-controller/rukpak/bundle/source/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ package source_test

import (
"io/fs"
"strings"
"testing"
"testing/fstest"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"

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

"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
. "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
testutils "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing/bundlefs"
)

const (
Expand All @@ -27,7 +31,18 @@ func Test_FromBundle_Success(t *testing.T) {
}

func Test_FromFS_Success(t *testing.T) {
rv1, err := source.FromFS(NewBundleFS()).GetBundle()
bundleFS := bundlefs.Builder().
WithPackageName("test").
WithBundleProperty("from-file-key", "from-file-value").
WithBundleResource("csv.yaml", ptr.To(testutils.MakeCSV(
testutils.WithName("test.v1.0.0"),
testutils.WithAnnotations(map[string]string{
"olm.properties": `[{"type":"from-csv-annotations-key", "value":"from-csv-annotations-value"}]`,
}),
testutils.WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces)),
)).Build()

rv1, err := source.FromFS(bundleFS).GetBundle()
require.NoError(t, err)

t.Log("Check package name is correctly taken from metadata/annotations.yaml")
Expand All @@ -44,16 +59,30 @@ func Test_FromFS_Fails(t *testing.T) {
}{
{
name: "bundle missing ClusterServiceVersion manifest",
FS: removePaths(NewBundleFS(), BundlePathCSV),
FS: bundlefs.Builder().
WithPackageName("test").
WithBundleProperty("foo", "bar").
WithBundleResource("service.yaml", &corev1.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
APIVersion: corev1.SchemeGroupVersion.String(),
},
}).Build(),
}, {
name: "bundle missing metadata/annotations.yaml",
FS: removePaths(NewBundleFS(), BundlePathAnnotations),
FS: bundlefs.Builder().
WithBundleProperty("foo", "bar").
WithBundleResource("csv.yaml", ptr.To(testutils.MakeCSV())).Build(),
}, {
name: "bundle missing metadata/ directory",
FS: removePaths(NewBundleFS(), "metadata/"),
name: "metadata/annotations.yaml missing package name annotation",
FS: bundlefs.Builder().
WithBundleProperty("foo", "bar").
WithBundleResource("csv.yaml", ptr.To(testutils.MakeCSV())).Build(),
}, {
name: "bundle missing manifests/ directory",
FS: removePaths(NewBundleFS(), "manifests/"),
name: "bundle missing manifests directory",
FS: bundlefs.Builder().
WithPackageName("test").
WithBundleProperty("foo", "bar").Build(),
},
} {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -62,14 +91,3 @@ func Test_FromFS_Fails(t *testing.T) {
})
}
}

func removePaths(mapFs fstest.MapFS, paths ...string) fstest.MapFS {
for k := range mapFs {
for _, path := range paths {
if strings.HasPrefix(k, path) {
delete(mapFs, k)
}
}
}
return mapFs
}
64 changes: 0 additions & 64 deletions internal/operator-controller/rukpak/util/testing/bundlefs.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package bundlefs

import (
"fmt"
"path/filepath"
"strings"
"testing/fstest"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"

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

"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
registry "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/operator-registry"
)

const (
BundlePathAnnotations = "metadata/annotations.yaml"
BundlePathProperties = "metadata/properties.yaml"
BundlePathManifests = "manifests"
)

// BundleFSBuilder builds a registry+v1 bundle filesystem
type BundleFSBuilder interface {
WithPackageName(packageName string) BundleFSBuilder
WithChannels(channels ...string) BundleFSBuilder
WithDefaultChannel(channel string) BundleFSBuilder
WithBundleProperty(propertyType string, value string) BundleFSBuilder
WithBundleResource(resourceName string, resource client.Object) BundleFSBuilder
WithCSV(csv v1alpha1.ClusterServiceVersion) BundleFSBuilder
Build() fstest.MapFS
}

// bundleFSBuilder builds a registry+v1 bundle filesystem
type bundleFSBuilder struct {
annotations *registry.Annotations
properties []property.Property
resources map[string]client.Object
}

func Builder() BundleFSBuilder {
return &bundleFSBuilder{}
}

// WithPackageName is an option for NewBundleFS used to set the package name annotation in the
// bundle filesystem metadata/annotations.yaml file
func (b *bundleFSBuilder) WithPackageName(packageName string) BundleFSBuilder {
if b.annotations == nil {
b.annotations = &registry.Annotations{}
}
b.annotations.PackageName = packageName
return b
}

// WithChannels is an option for NewBundleFS used to set the channels annotation in the
// bundle filesystem metadata/annotations.yaml file
func (b *bundleFSBuilder) WithChannels(channels ...string) BundleFSBuilder {
if b.annotations == nil {
b.annotations = &registry.Annotations{}
}
b.annotations.Channels = strings.Join(channels, ",")
return b
}

// WithDefaultChannel is an option for NewBundleFS used to set the channel annotation in the
// bundle filesystem metadata/annotations.yaml file
func (b *bundleFSBuilder) WithDefaultChannel(channel string) BundleFSBuilder {
if b.annotations == nil {
b.annotations = &registry.Annotations{}
}
b.annotations.DefaultChannelName = channel
return b
}

// WithBundleProperty is an options for NewBundleFS used to add a property to the list of properties
// in the bundle filesystem metadata/properties.yaml file
func (b *bundleFSBuilder) WithBundleProperty(propertyType string, value string) BundleFSBuilder {
b.properties = append(b.properties, property.Property{
Type: propertyType,
Value: []byte(`"` + value + `"`),
})
return b
}

// WithBundleResource is an option for NewBundleFS use to add the yaml representation of resource to the
// path manifests/<resourceName>.yaml on the bundles filesystem
func (b *bundleFSBuilder) WithBundleResource(resourceName string, resource client.Object) BundleFSBuilder {
if b.resources == nil {
b.resources = make(map[string]client.Object)
}
b.resources[resourceName] = resource
return b
}

// WithCSV is an optiona for NewBundleFS used to add the yaml representation of csv to the
// path manifests/csv.yaml on the bundle filesystem
func (b *bundleFSBuilder) WithCSV(csv v1alpha1.ClusterServiceVersion) BundleFSBuilder {
if b.resources == nil {
b.resources = make(map[string]client.Object)
}
b.resources["csv.yaml"] = &csv
return b
}

// Build creates a registry+v1 bundle filesystem with the applied options
// By default, an empty registry+v1 bundle filesystem will be returned
func (b *bundleFSBuilder) Build() fstest.MapFS {
bundleFS := fstest.MapFS{}

// Add annotations metadata
if b.annotations != nil {
annotationsYml, err := yaml.Marshal(registry.AnnotationsFile{
Annotations: *b.annotations,
})
if err != nil {
panic(fmt.Errorf("error building bundle fs: %w", err))
}
bundleFS[BundlePathAnnotations] = &fstest.MapFile{Data: annotationsYml}
}

// Add property metadata
if len(b.properties) > 0 {
propertiesYml, err := yaml.Marshal(source.RegistryV1Properties{
Properties: b.properties,
})
if err != nil {
panic(fmt.Errorf("error building bundle fs: %w", err))
}
bundleFS[BundlePathProperties] = &fstest.MapFile{Data: propertiesYml}
}

// Add resources
for name, obj := range b.resources {
resourcePath := filepath.Join(BundlePathManifests, name)
resourceYml, err := yaml.Marshal(obj)
if err != nil {
panic(fmt.Errorf("error building bundle fs: %w", err))
}
bundleFS[resourcePath] = &fstest.MapFile{Data: resourceYml}
}

return bundleFS
}
Loading
Loading