Skip to content

Commit 0589b6c

Browse files
author
Per Goncalves da Silva
committed
Add render resource mutator unit tests
Signed-off-by: Per Goncalves da Silva <[email protected]>
1 parent 8a785e1 commit 0589b6c

File tree

4 files changed

+213
-11
lines changed

4 files changed

+213
-11
lines changed

internal/operator-controller/rukpak/convert/render/mutate.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55

66
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
77
"sigs.k8s.io/controller-runtime/pkg/client"
8+
9+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/convert"
810
)
911

1012
type ResourceMutator func(client.Object) error
@@ -46,18 +48,18 @@ func (g *ResourceMutators) MutateObjects(objs iter.Seq[client.Object]) error {
4648
return nil
4749
}
4850

49-
type ResourceMutatorFactory func() (ResourceMutators, error)
51+
type ResourceMutatorFactory func(rv1 *convert.RegistryV1, opts Options) (ResourceMutators, error)
5052

51-
func (m ResourceMutatorFactory) MakeResourceMutators() (ResourceMutators, error) {
52-
return m()
53+
func (m ResourceMutatorFactory) MakeResourceMutators(rv1 *convert.RegistryV1, opts Options) (ResourceMutators, error) {
54+
return m(rv1, opts)
5355
}
5456

5557
type ChainedResourceMutatorFactory []ResourceMutatorFactory
5658

57-
func (c ChainedResourceMutatorFactory) MakeResourceMutators() (ResourceMutators, error) {
59+
func (c ChainedResourceMutatorFactory) MakeResourceMutators(rv1 *convert.RegistryV1, opts Options) (ResourceMutators, error) {
5860
var resourceMutators []ResourceMutator
5961
for _, mutatorFactory := range c {
60-
mutators, err := mutatorFactory.MakeResourceMutators()
62+
mutators, err := mutatorFactory.MakeResourceMutators(rv1, opts)
6163
if err != nil {
6264
return nil, err
6365
}
@@ -69,7 +71,7 @@ func (c ChainedResourceMutatorFactory) MakeResourceMutators() (ResourceMutators,
6971
func CustomResourceDefinitionMutator(name string, mutator func(crd *apiextensionsv1.CustomResourceDefinition) error) ResourceMutator {
7072
return func(obj client.Object) error {
7173
crd, ok := obj.(*apiextensionsv1.CustomResourceDefinition)
72-
if obj.GetName() != name || !ok {
74+
if !ok || obj.GetName() != name {
7375
return nil
7476
}
7577
return mutator(crd)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package render_test
2+
3+
import (
4+
"fmt"
5+
"slices"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
corev1 "k8s.io/api/core/v1"
10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
12+
13+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/convert"
14+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/convert/render"
15+
)
16+
17+
func Test_ResourceMutator_Mutate(t *testing.T) {
18+
var m render.ResourceMutator = func(obj client.Object) error {
19+
obj.SetName("some-name")
20+
return nil
21+
}
22+
svc := corev1.Service{}
23+
err := m.Mutate(&svc)
24+
require.NoError(t, err)
25+
require.Equal(t, "some-name", svc.Name)
26+
}
27+
28+
func Test_ResourceMutator_MutateObjects(t *testing.T) {
29+
var m render.ResourceMutator = func(obj client.Object) error {
30+
obj.SetName("some-name")
31+
return nil
32+
}
33+
34+
objs := []client.Object{&corev1.Service{}, &corev1.ConfigMap{}}
35+
err := m.MutateObjects(slices.Values(objs))
36+
require.NoError(t, err)
37+
for _, obj := range objs {
38+
require.Equal(t, "some-name", obj.GetName())
39+
}
40+
}
41+
42+
func Test_ResourceMutator_MutateObjects_Errors(t *testing.T) {
43+
var m render.ResourceMutator = func(obj client.Object) error {
44+
return fmt.Errorf("some error")
45+
}
46+
47+
objs := []client.Object{&corev1.Service{}, &corev1.ConfigMap{}}
48+
err := m.MutateObjects(slices.Values(objs))
49+
require.Error(t, err)
50+
require.Contains(t, err.Error(), "some error")
51+
}
52+
53+
func Test_ResourceMutators_Mutate(t *testing.T) {
54+
ms := render.ResourceMutators{
55+
func(obj client.Object) error {
56+
obj.SetName("some-name")
57+
return nil
58+
},
59+
func(obj client.Object) error {
60+
obj.SetNamespace("some-namespace")
61+
return nil
62+
},
63+
}
64+
svc := corev1.Service{}
65+
err := ms.Mutate(&svc)
66+
require.NoError(t, err)
67+
require.Equal(t, "some-name", svc.Name)
68+
require.Equal(t, "some-namespace", svc.Namespace)
69+
}
70+
71+
func Test_ResourceMutators_MutateObjects(t *testing.T) {
72+
ms := render.ResourceMutators{
73+
func(obj client.Object) error {
74+
obj.SetName("some-name")
75+
return nil
76+
},
77+
func(obj client.Object) error {
78+
obj.SetNamespace("some-namespace")
79+
return nil
80+
},
81+
}
82+
objs := []client.Object{&corev1.Service{}, &corev1.ConfigMap{}}
83+
err := ms.MutateObjects(slices.Values(objs))
84+
require.NoError(t, err)
85+
for _, obj := range objs {
86+
require.Equal(t, "some-name", obj.GetName())
87+
require.Equal(t, "some-namespace", obj.GetNamespace())
88+
}
89+
}
90+
91+
func Test_ResourceMutators_MutateObjects_Errors(t *testing.T) {
92+
ms := render.ResourceMutators{
93+
func(obj client.Object) error {
94+
obj.SetName("some-name")
95+
return nil
96+
},
97+
func(obj client.Object) error {
98+
return fmt.Errorf("some error")
99+
},
100+
}
101+
objs := []client.Object{&corev1.Service{}, &corev1.ConfigMap{}}
102+
err := ms.MutateObjects(slices.Values(objs))
103+
require.Error(t, err)
104+
require.Contains(t, err.Error(), "some error")
105+
}
106+
107+
func Test_ResourceMutatorFactory_MakeResourceMutators(t *testing.T) {
108+
var f render.ResourceMutatorFactory = func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
109+
return render.ResourceMutators{
110+
func(obj client.Object) error {
111+
obj.SetName("some-name")
112+
return nil
113+
},
114+
}, nil
115+
}
116+
117+
ms, err := f.MakeResourceMutators(&convert.RegistryV1{}, render.Options{})
118+
require.NoError(t, err)
119+
require.NotNil(t, ms)
120+
require.Len(t, ms, 1)
121+
122+
svc := &corev1.Service{}
123+
require.NoError(t, ms.Mutate(svc))
124+
require.Equal(t, "some-name", svc.Name)
125+
}
126+
127+
func Test_ChainedResourceMutatorFactory(t *testing.T) {
128+
cf := render.ChainedResourceMutatorFactory{
129+
func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
130+
return render.ResourceMutators{
131+
func(object client.Object) error {
132+
object.SetName("some-name")
133+
return nil
134+
},
135+
}, nil
136+
},
137+
func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
138+
return render.ResourceMutators{
139+
func(object client.Object) error {
140+
object.SetNamespace("some-namespace")
141+
return nil
142+
},
143+
}, nil
144+
},
145+
}
146+
147+
ms, err := cf.MakeResourceMutators(&convert.RegistryV1{}, render.Options{})
148+
require.NoError(t, err)
149+
require.NotNil(t, ms)
150+
require.Len(t, ms, 2)
151+
152+
svc := &corev1.Service{}
153+
require.NoError(t, ms.Mutate(svc))
154+
require.Equal(t, "some-name", svc.Name)
155+
require.Equal(t, "some-namespace", svc.Namespace)
156+
}
157+
158+
func Test_CustomResourceDefinitionMutator(t *testing.T) {
159+
m := render.CustomResourceDefinitionMutator("my-crd", func(crd *apiextensionsv1.CustomResourceDefinition) error {
160+
crd.SetAnnotations(map[string]string{
161+
"foo": "bar",
162+
})
163+
return nil
164+
})
165+
166+
t.Log("Check matching crd is mutated")
167+
crd := &apiextensionsv1.CustomResourceDefinition{}
168+
crd.SetName("my-crd")
169+
require.NoError(t, m.Mutate(crd))
170+
require.Equal(t, map[string]string{"foo": "bar"}, crd.GetAnnotations())
171+
172+
t.Log("Check non-matching crd is NOT mutated")
173+
crd = &apiextensionsv1.CustomResourceDefinition{}
174+
crd.SetName("not-my-crd")
175+
require.NoError(t, m.Mutate(crd))
176+
require.NotEqual(t, map[string]string{"foo": "bar"}, crd.GetAnnotations())
177+
178+
t.Log("Check mutator handles nil")
179+
require.NoError(t, m.Mutate(nil))
180+
}

internal/operator-controller/rukpak/convert/render/render.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,17 @@ func (o *options) apply(opts ...Option) *options {
2626
}
2727

2828
type BundleRenderer struct {
29+
BundleValidator convert.BundleValidator
2930
ResourceGenerators []ResourceGenerator
3031
ResourceMutatorFactories []ResourceMutatorFactory
3132
}
3233

3334
func (r BundleRenderer) Render(rv1 convert.RegistryV1, installNamespace string, watchNamespaces []string, opts ...Option) ([]client.Object, error) {
35+
// validate bundle
36+
if err := r.BundleValidator.Validate(&rv1); err != nil {
37+
return nil, err
38+
}
39+
3440
renderOptions := (&options{
3541
UniqueNameGenerator: DefaultUniqueNameGenerator,
3642
}).apply(opts...)
@@ -43,7 +49,7 @@ func (r BundleRenderer) Render(rv1 convert.RegistryV1, installNamespace string,
4349
}
4450

4551
// generate object mutators
46-
objMutators, err := ChainedResourceMutatorFactory(r.ResourceMutatorFactories).MakeResourceMutators()
52+
objMutators, err := ChainedResourceMutatorFactory(r.ResourceMutatorFactories).MakeResourceMutators(&rv1, genOpts)
4753
if err != nil {
4854
return nil, err
4955
}

internal/operator-controller/rukpak/convert/render/render_test.go

+18-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ func Test_BundleRenderer_NoConfig(t *testing.T) {
2222
require.Empty(t, objs)
2323
}
2424

25+
func Test_BundleRenderer_ValidatesBundle(t *testing.T) {
26+
renderer := render.BundleRenderer{
27+
BundleValidator: convert.BundleValidator{
28+
func(v1 *convert.RegistryV1) []error {
29+
return []error{errors.New("this bundle is invalid")}
30+
},
31+
},
32+
}
33+
objs, err := renderer.Render(convert.RegistryV1{}, "", nil)
34+
require.Nil(t, objs)
35+
require.Error(t, err)
36+
require.Contains(t, err.Error(), "this bundle is invalid")
37+
}
38+
2539
func Test_BundleRenderer_CallsResourceGenerators(t *testing.T) {
2640
renderer := render.BundleRenderer{
2741
ResourceGenerators: []render.ResourceGenerator{
@@ -46,7 +60,7 @@ func Test_BundleRenderer_CallsResourceMutators(t *testing.T) {
4660
},
4761
},
4862
ResourceMutatorFactories: []render.ResourceMutatorFactory{
49-
func() (render.ResourceMutators, error) {
63+
func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
5064
return []render.ResourceMutator{
5165
func(object client.Object) error {
5266
switch object.(type) {
@@ -65,7 +79,7 @@ func Test_BundleRenderer_CallsResourceMutators(t *testing.T) {
6579
},
6680
}, nil
6781
},
68-
func() (render.ResourceMutators, error) {
82+
func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
6983
return []render.ResourceMutator{
7084
func(object client.Object) error {
7185
object.SetAnnotations(map[string]string{
@@ -130,7 +144,7 @@ func Test_BundleRenderer_ReturnsResourceMutatorFactoryErrors(t *testing.T) {
130144
},
131145
},
132146
ResourceMutatorFactories: []render.ResourceMutatorFactory{
133-
func() (render.ResourceMutators, error) {
147+
func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
134148
return nil, errors.New("mutator factory error")
135149
},
136150
},
@@ -149,7 +163,7 @@ func Test_BundleRenderer_ReturnsResourceMutatorErrors(t *testing.T) {
149163
},
150164
},
151165
ResourceMutatorFactories: []render.ResourceMutatorFactory{
152-
func() (render.ResourceMutators, error) {
166+
func(rv1 *convert.RegistryV1, opts render.Options) (render.ResourceMutators, error) {
153167
return []render.ResourceMutator{
154168
func(object client.Object) error {
155169
return errors.New("mutator error")

0 commit comments

Comments
 (0)