Skip to content

Commit 9d2c04b

Browse files
author
Per Goncalves da Silva
committed
Update NewBundleFS test utility to builder pattern
Signed-off-by: Per Goncalves da Silva <[email protected]>
1 parent 55d9dfb commit 9d2c04b

File tree

5 files changed

+271
-68
lines changed

5 files changed

+271
-68
lines changed

internal/operator-controller/applier/boxcutter_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ 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"
@@ -52,7 +54,10 @@ func Test_RegistryV1BundleRenderer_Render_Success(t *testing.T) {
5254
},
5355
},
5456
}
55-
bundleFS := testutils.NewBundleFS()
57+
58+
bundleFS := testutils.NewBundleFSBuilder().
59+
WithPackageName("some-package").
60+
WithCSV(testutils.MakeCSV(testutils.WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces))).Build()
5661

5762
objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
5863
Spec: ocv1.ClusterExtensionSpec{
@@ -74,7 +79,9 @@ func Test_RegistryV1BundleRenderer_Render_Failure(t *testing.T) {
7479
},
7580
},
7681
}
77-
bundleFS := testutils.NewBundleFS()
82+
bundleFS := testutils.NewBundleFSBuilder().
83+
WithPackageName("some-package").
84+
WithCSV(testutils.MakeCSV(testutils.WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces))).Build()
7885

7986
objs, err := r.Render(bundleFS, &ocv1.ClusterExtension{
8087
Spec: ocv1.ClusterExtensionSpec{

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
}

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

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ package source_test
22

33
import (
44
"io/fs"
5-
"strings"
65
"testing"
7-
"testing/fstest"
86

97
"github.com/stretchr/testify/require"
8+
corev1 "k8s.io/api/core/v1"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/utils/ptr"
11+
12+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1013

1114
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle"
1215
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
13-
. "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
16+
testutils "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing"
1417
)
1518

1619
const (
@@ -27,7 +30,18 @@ func Test_FromBundle_Success(t *testing.T) {
2730
}
2831

2932
func Test_FromFS_Success(t *testing.T) {
30-
rv1, err := source.FromFS(NewBundleFS()).GetBundle()
33+
bundleFS := testutils.NewBundleFSBuilder().
34+
WithPackageName("test").
35+
WithBundleProperty("from-file-key", "from-file-value").
36+
WithBundleResource("csv.yaml", ptr.To(testutils.MakeCSV(
37+
testutils.WithName("test.v1.0.0"),
38+
testutils.WithAnnotations(map[string]string{
39+
"olm.properties": `[{"type":"from-csv-annotations-key", "value":"from-csv-annotations-value"}]`,
40+
}),
41+
testutils.WithInstallModeSupportFor(v1alpha1.InstallModeTypeAllNamespaces)),
42+
)).Build()
43+
44+
rv1, err := source.FromFS(bundleFS).GetBundle()
3145
require.NoError(t, err)
3246

3347
t.Log("Check package name is correctly taken from metadata/annotations.yaml")
@@ -44,16 +58,30 @@ func Test_FromFS_Fails(t *testing.T) {
4458
}{
4559
{
4660
name: "bundle missing ClusterServiceVersion manifest",
47-
FS: removePaths(NewBundleFS(), BundlePathCSV),
61+
FS: testutils.NewBundleFSBuilder().
62+
WithPackageName("test").
63+
WithBundleProperty("foo", "bar").
64+
WithBundleResource("service.yaml", &corev1.Service{
65+
TypeMeta: metav1.TypeMeta{
66+
Kind: "Service",
67+
APIVersion: corev1.SchemeGroupVersion.String(),
68+
},
69+
}).Build(),
4870
}, {
4971
name: "bundle missing metadata/annotations.yaml",
50-
FS: removePaths(NewBundleFS(), BundlePathAnnotations),
72+
FS: testutils.NewBundleFSBuilder().
73+
WithBundleProperty("foo", "bar").
74+
WithBundleResource("csv.yaml", ptr.To(testutils.MakeCSV())).Build(),
5175
}, {
52-
name: "bundle missing metadata/ directory",
53-
FS: removePaths(NewBundleFS(), "metadata/"),
76+
name: "metadata/annotations.yaml missing package name annotation",
77+
FS: testutils.NewBundleFSBuilder().
78+
WithBundleProperty("foo", "bar").
79+
WithBundleResource("csv.yaml", ptr.To(testutils.MakeCSV())).Build(),
5480
}, {
55-
name: "bundle missing manifests/ directory",
56-
FS: removePaths(NewBundleFS(), "manifests/"),
81+
name: "bundle missing manifests directory",
82+
FS: testutils.NewBundleFSBuilder().
83+
WithPackageName("test").
84+
WithBundleProperty("foo", "bar").Build(),
5785
},
5886
} {
5987
t.Run(tt.name, func(t *testing.T) {
@@ -62,14 +90,3 @@ func Test_FromFS_Fails(t *testing.T) {
6290
})
6391
}
6492
}
65-
66-
func removePaths(mapFs fstest.MapFS, paths ...string) fstest.MapFS {
67-
for k := range mapFs {
68-
for _, path := range paths {
69-
if strings.HasPrefix(k, path) {
70-
delete(mapFs, k)
71-
}
72-
}
73-
}
74-
return mapFs
75-
}

internal/operator-controller/rukpak/util/testing/bundlefs.go

Lines changed: 110 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,127 @@ import (
88

99
"sigs.k8s.io/controller-runtime/pkg/client"
1010
"sigs.k8s.io/yaml"
11+
12+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
13+
"github.com/operator-framework/operator-registry/alpha/property"
14+
15+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/bundle/source"
16+
registry "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/operator-registry"
1117
)
1218

1319
const (
1420
BundlePathAnnotations = "metadata/annotations.yaml"
1521
BundlePathProperties = "metadata/properties.yaml"
1622
BundlePathManifests = "manifests"
17-
BundlePathCSV = BundlePathManifests + "/csv.yaml"
1823
)
1924

20-
func NewBundleFS() fstest.MapFS {
21-
annotationsYml := `
22-
annotations:
23-
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
24-
operators.operatorframework.io.bundle.package.v1: test
25-
`
26-
27-
propertiesYml := `
28-
properties:
29-
- type: "from-file-key"
30-
value: "from-file-value"
31-
`
32-
33-
csvYml := `
34-
apiVersion: operators.operatorframework.io/v1alpha1
35-
kind: ClusterServiceVersion
36-
metadata:
37-
name: test.v1.0.0
38-
annotations:
39-
olm.properties: '[{"type":"from-csv-annotations-key", "value":"from-csv-annotations-value"}]'
40-
spec:
41-
installModes:
42-
- type: AllNamespaces
43-
supported: true
44-
`
45-
46-
return fstest.MapFS{
47-
BundlePathAnnotations: &fstest.MapFile{Data: []byte(strings.Trim(annotationsYml, "\n"))},
48-
BundlePathProperties: &fstest.MapFile{Data: []byte(strings.Trim(propertiesYml, "\n"))},
49-
BundlePathCSV: &fstest.MapFile{Data: []byte(strings.Trim(csvYml, "\n"))},
25+
// BundleFSBuilder builds a registry+v1 bundle filesystem
26+
type BundleFSBuilder struct {
27+
annotations *registry.Annotations
28+
properties []property.Property
29+
resources map[string]client.Object
30+
}
31+
32+
func NewBundleFSBuilder() *BundleFSBuilder {
33+
return &BundleFSBuilder{}
34+
}
35+
36+
// WithPackageName is an option for NewBundleFS used to set the package name annotation in the
37+
// bundle filesystem metadata/annotations.yaml file
38+
func (b *BundleFSBuilder) WithPackageName(packageName string) *BundleFSBuilder {
39+
if b.annotations == nil {
40+
b.annotations = &registry.Annotations{}
5041
}
42+
b.annotations.PackageName = packageName
43+
return b
5144
}
5245

53-
func AddManifest(bundleFS fstest.MapFS, obj client.Object) error {
54-
gvk := obj.GetObjectKind().GroupVersionKind()
55-
manifestName := fmt.Sprintf("%s%s_%s_%s%s.yaml", gvk.Group, gvk.Version, gvk.Kind, obj.GetNamespace(), obj.GetName())
56-
bytes, err := yaml.Marshal(obj)
57-
if err != nil {
58-
return err
46+
// WithChannels is an option for NewBundleFS used to set the channels annotation in the
47+
// bundle filesystem metadata/annotations.yaml file
48+
func (b *BundleFSBuilder) WithChannels(channels ...string) *BundleFSBuilder {
49+
if b.annotations == nil {
50+
b.annotations = &registry.Annotations{}
5951
}
60-
bundleFS[filepath.Join(BundlePathManifests, manifestName)] = &fstest.MapFile{
61-
Data: bytes,
52+
b.annotations.Channels = strings.Join(channels, ",")
53+
return b
54+
}
55+
56+
// WithDefaultChannel is an option for NewBundleFS used to set the channel annotation in the
57+
// bundle filesystem metadata/annotations.yaml file
58+
func (b *BundleFSBuilder) WithDefaultChannel(channel string) *BundleFSBuilder {
59+
if b.annotations == nil {
60+
b.annotations = &registry.Annotations{}
61+
}
62+
b.annotations.DefaultChannelName = channel
63+
return b
64+
}
65+
66+
// WithBundleProperty is an options for NewBundleFS used to add a property to the list of properties
67+
// in the bundle filesystem metadata/properties.yaml file
68+
func (b *BundleFSBuilder) WithBundleProperty(propertyType string, value string) *BundleFSBuilder {
69+
b.properties = append(b.properties, property.Property{
70+
Type: propertyType,
71+
Value: []byte(`"` + value + `"`),
72+
})
73+
return b
74+
}
75+
76+
// WithBundleResource is an option for NewBundleFS use to add the yaml representation of resource to the
77+
// path manifests/<resourceName>.yaml on the bundles filesystem
78+
func (b *BundleFSBuilder) WithBundleResource(resourceName string, resource client.Object) *BundleFSBuilder {
79+
if b.resources == nil {
80+
b.resources = make(map[string]client.Object)
6281
}
63-
return nil
82+
b.resources[resourceName] = resource
83+
return b
84+
}
85+
86+
// WithCSV is an optiona for NewBundleFS used to add the yaml representation of csv to the
87+
// path manifests/csv.yaml on the bundle filesystem
88+
func (b *BundleFSBuilder) WithCSV(csv v1alpha1.ClusterServiceVersion) *BundleFSBuilder {
89+
if b.resources == nil {
90+
b.resources = make(map[string]client.Object)
91+
}
92+
b.resources["csv.yaml"] = &csv
93+
return b
94+
}
95+
96+
// Build creates a registry+v1 bundle filesystem with the applied options
97+
// By default, an empty registry+v1 bundle filesystem will be returned
98+
func (b *BundleFSBuilder) Build() fstest.MapFS {
99+
bundleFS := fstest.MapFS{}
100+
101+
// Add annotations metadata
102+
if b.annotations != nil {
103+
annotationsYml, err := yaml.Marshal(registry.AnnotationsFile{
104+
Annotations: *b.annotations,
105+
})
106+
if err != nil {
107+
panic(fmt.Errorf("error building bundle fs: %w", err))
108+
}
109+
bundleFS[BundlePathAnnotations] = &fstest.MapFile{Data: annotationsYml}
110+
}
111+
112+
// Add property metadata
113+
if len(b.properties) > 0 {
114+
propertiesYml, err := yaml.Marshal(source.RegistryV1Properties{
115+
Properties: b.properties,
116+
})
117+
if err != nil {
118+
panic(fmt.Errorf("error building bundle fs: %w", err))
119+
}
120+
bundleFS[BundlePathProperties] = &fstest.MapFile{Data: propertiesYml}
121+
}
122+
123+
// Add resources
124+
for name, obj := range b.resources {
125+
resourcePath := filepath.Join(BundlePathManifests, name)
126+
resourceYml, err := yaml.Marshal(obj)
127+
if err != nil {
128+
panic(fmt.Errorf("error building bundle fs: %w", err))
129+
}
130+
bundleFS[resourcePath] = &fstest.MapFile{Data: resourceYml}
131+
}
132+
133+
return bundleFS
64134
}

0 commit comments

Comments
 (0)