Skip to content

Commit 3ac6014

Browse files
author
Per Goncalves da Silva
committed
add more unit testing
Signed-off-by: Per Goncalves da Silva <[email protected]>
1 parent 0893dd4 commit 3ac6014

File tree

4 files changed

+311
-238
lines changed

4 files changed

+311
-238
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,184 +1,203 @@
11
package convert
22

33
import (
4-
"cmp"
5-
"fmt"
6-
"strings"
4+
"cmp"
5+
"fmt"
6+
"strings"
77

8-
corev1 "k8s.io/api/core/v1"
9-
rbacv1 "k8s.io/api/rbac/v1"
10-
"k8s.io/apimachinery/pkg/util/sets"
11-
"k8s.io/utils/ptr"
12-
"sigs.k8s.io/controller-runtime/pkg/client"
8+
corev1 "k8s.io/api/core/v1"
9+
rbacv1 "k8s.io/api/rbac/v1"
10+
"k8s.io/apimachinery/pkg/util/sets"
11+
"k8s.io/utils/ptr"
12+
"sigs.k8s.io/controller-runtime/pkg/client"
1313

14-
registrybundle "github.com/operator-framework/operator-registry/pkg/lib/bundle"
14+
registrybundle "github.com/operator-framework/operator-registry/pkg/lib/bundle"
1515

16-
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util"
16+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util"
1717
)
1818

1919
type UniqueNameGenerator func(string, interface{}) (string, error)
2020

2121
type Options struct {
22-
InstallNamespace string
23-
TargetNamespaces []string
24-
UniqueNameGenerator UniqueNameGenerator
22+
InstallNamespace string
23+
TargetNamespaces []string
24+
UniqueNameGenerator UniqueNameGenerator
2525
}
2626

2727
type ResourceGenerator func(rv1 *RegistryV1, opts Options) ([]client.Object, error)
2828

2929
func (g ResourceGenerator) GenerateResources(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
30-
return g(rv1, opts)
30+
return g(rv1, opts)
3131
}
3232

3333
func ChainedResourceGenerator(resourceGenerators ...ResourceGenerator) ResourceGenerator {
34-
return func(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
35-
//nolint:prealloc
36-
var renderedObjects []client.Object
37-
for _, generator := range resourceGenerators {
38-
objs, err := generator(rv1, opts)
39-
if err != nil {
40-
return nil, err
41-
}
42-
renderedObjects = append(renderedObjects, objs...)
43-
}
44-
return renderedObjects, nil
45-
}
34+
return func(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
35+
//nolint:prealloc
36+
var renderedObjects []client.Object
37+
for _, generator := range resourceGenerators {
38+
objs, err := generator(rv1, opts)
39+
if err != nil {
40+
return nil, err
41+
}
42+
renderedObjects = append(renderedObjects, objs...)
43+
}
44+
return renderedObjects, nil
45+
}
4646
}
4747

4848
func BundleDeploymentGenerator(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
49-
objs := make([]client.Object, 0, len(rv1.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs))
50-
for _, depSpec := range rv1.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
51-
annotations := util.MergeMaps(rv1.CSV.Annotations, depSpec.Spec.Template.Annotations)
52-
annotations["olm.targetNamespaces"] = strings.Join(opts.TargetNamespaces, ",")
53-
depSpec.Spec.Template.Annotations = annotations
54-
55-
// Hardcode the deployment with RevisionHistoryLimit=1 (something OLMv0 does, not sure why)
56-
depSpec.Spec.RevisionHistoryLimit = ptr.To(int32(1))
57-
58-
objs = append(objs,
59-
GenerateDeploymentResource(
60-
depSpec.Name,
61-
opts.InstallNamespace,
62-
WithDeploymentSpec(depSpec.Spec),
63-
WithLabels(depSpec.Label),
64-
),
65-
)
66-
}
67-
return objs, nil
49+
if rv1 == nil {
50+
return nil, fmt.Errorf("bundle cannot be nil")
51+
}
52+
objs := make([]client.Object, 0, len(rv1.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs))
53+
for _, depSpec := range rv1.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
54+
annotations := util.MergeMaps(rv1.CSV.Annotations, depSpec.Spec.Template.Annotations)
55+
annotations["olm.targetNamespaces"] = strings.Join(opts.TargetNamespaces, ",")
56+
depSpec.Spec.Template.Annotations = annotations
57+
58+
// Hardcode the deployment with RevisionHistoryLimit=1 (something OLMv0 does, not sure why)
59+
depSpec.Spec.RevisionHistoryLimit = ptr.To(int32(1))
60+
61+
objs = append(objs,
62+
GenerateDeploymentResource(
63+
depSpec.Name,
64+
opts.InstallNamespace,
65+
WithDeploymentSpec(depSpec.Spec),
66+
WithLabels(depSpec.Label),
67+
),
68+
)
69+
}
70+
return objs, nil
6871
}
6972

7073
func BundlePermissionsGenerator(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
71-
permissions := rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions
72-
73-
// If we're in AllNamespaces mode permissions will be treated as clusterPermissions
74-
if len(opts.TargetNamespaces) == 1 && opts.TargetNamespaces[0] == "" {
75-
return nil, nil
76-
}
77-
78-
objs := make([]client.Object, 0, 2*len(opts.TargetNamespaces)*len(permissions))
79-
for _, ns := range opts.TargetNamespaces {
80-
for _, permission := range permissions {
81-
saName := saNameOrDefault(permission.ServiceAccountName)
82-
name, err := opts.UniqueNameGenerator(fmt.Sprintf("%s-%s", rv1.CSV.Name, saName), permission)
83-
if err != nil {
84-
return nil, err
85-
}
86-
87-
objs = append(objs,
88-
GenerateRoleResource(name, ns, WithRules(permission.Rules...)),
89-
GenerateRoleBindingResource(
90-
name,
91-
ns,
92-
WithSubjects(rbacv1.Subject{Kind: "ServiceAccount", Namespace: opts.InstallNamespace, Name: saName}),
93-
WithRoleRef(rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: name}),
94-
),
95-
)
96-
}
97-
}
98-
return objs, nil
74+
if rv1 == nil {
75+
return nil, fmt.Errorf("bundle cannot be nil")
76+
}
77+
78+
// If we're in AllNamespaces mode permissions will be treated as clusterPermissions
79+
if len(opts.TargetNamespaces) == 1 && opts.TargetNamespaces[0] == "" {
80+
return nil, nil
81+
}
82+
83+
permissions := rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions
84+
85+
objs := make([]client.Object, 0, 2*len(opts.TargetNamespaces)*len(permissions))
86+
for _, ns := range opts.TargetNamespaces {
87+
for _, permission := range permissions {
88+
saName := saNameOrDefault(permission.ServiceAccountName)
89+
name, err := opts.UniqueNameGenerator(fmt.Sprintf("%s-%s", rv1.CSV.Name, saName), permission)
90+
if err != nil {
91+
return nil, err
92+
}
93+
94+
objs = append(objs,
95+
GenerateRoleResource(name, ns, WithRules(permission.Rules...)),
96+
GenerateRoleBindingResource(
97+
name,
98+
ns,
99+
WithSubjects(rbacv1.Subject{Kind: "ServiceAccount", Namespace: opts.InstallNamespace, Name: saName}),
100+
WithRoleRef(rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: name}),
101+
),
102+
)
103+
}
104+
}
105+
return objs, nil
99106
}
100107

101108
func BundleClusterPermissionsGenerator(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
102-
clusterPermissions := rv1.CSV.Spec.InstallStrategy.StrategySpec.ClusterPermissions
103-
104-
// If we're in AllNamespaces mode, promote the permissions to clusterPermissions
105-
if len(opts.TargetNamespaces) == 1 && opts.TargetNamespaces[0] == "" {
106-
for _, p := range rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions {
107-
p.Rules = append(p.Rules, rbacv1.PolicyRule{
108-
Verbs: []string{"get", "list", "watch"},
109-
APIGroups: []string{corev1.GroupName},
110-
Resources: []string{"namespaces"},
111-
})
112-
clusterPermissions = append(clusterPermissions, p)
113-
}
114-
}
115-
116-
objs := make([]client.Object, 0, 2*len(clusterPermissions))
117-
for _, permission := range clusterPermissions {
118-
saName := saNameOrDefault(permission.ServiceAccountName)
119-
name, err := opts.UniqueNameGenerator(fmt.Sprintf("%s-%s", rv1.CSV.Name, saName), permission)
120-
if err != nil {
121-
return nil, err
122-
}
123-
objs = append(objs,
124-
GenerateClusterRoleResource(name, WithRules(permission.Rules...)),
125-
GenerateClusterRoleBindingResource(
126-
name,
127-
WithSubjects(rbacv1.Subject{Kind: "ServiceAccount", Namespace: opts.InstallNamespace, Name: saName}),
128-
WithRoleRef(rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: name}),
129-
),
130-
)
131-
}
132-
return objs, nil
109+
if rv1 == nil {
110+
return nil, fmt.Errorf("bundle cannot be nil")
111+
}
112+
clusterPermissions := rv1.CSV.Spec.InstallStrategy.StrategySpec.ClusterPermissions
113+
114+
// If we're in AllNamespaces mode, promote the permissions to clusterPermissions
115+
if len(opts.TargetNamespaces) == 1 && opts.TargetNamespaces[0] == "" {
116+
for _, p := range rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions {
117+
p.Rules = append(p.Rules, rbacv1.PolicyRule{
118+
Verbs: []string{"get", "list", "watch"},
119+
APIGroups: []string{corev1.GroupName},
120+
Resources: []string{"namespaces"},
121+
})
122+
clusterPermissions = append(clusterPermissions, p)
123+
}
124+
}
125+
126+
objs := make([]client.Object, 0, 2*len(clusterPermissions))
127+
for _, permission := range clusterPermissions {
128+
saName := saNameOrDefault(permission.ServiceAccountName)
129+
name, err := opts.UniqueNameGenerator(fmt.Sprintf("%s-%s", rv1.CSV.Name, saName), permission)
130+
if err != nil {
131+
return nil, err
132+
}
133+
objs = append(objs,
134+
GenerateClusterRoleResource(name, WithRules(permission.Rules...)),
135+
GenerateClusterRoleBindingResource(
136+
name,
137+
WithSubjects(rbacv1.Subject{Kind: "ServiceAccount", Namespace: opts.InstallNamespace, Name: saName}),
138+
WithRoleRef(rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: name}),
139+
),
140+
)
141+
}
142+
return objs, nil
133143
}
134144

135145
func BundleServiceAccountGenerator(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
136-
allPermissions := append(
137-
rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions,
138-
rv1.CSV.Spec.InstallStrategy.StrategySpec.ClusterPermissions...,
139-
)
140-
141-
serviceAccountNames := sets.Set[string]{}
142-
for _, permission := range allPermissions {
143-
serviceAccountNames.Insert(saNameOrDefault(permission.ServiceAccountName))
144-
}
145-
146-
objs := make([]client.Object, 0, len(serviceAccountNames))
147-
for _, serviceAccountName := range serviceAccountNames.UnsortedList() {
148-
// no need to generate the default service account
149-
if serviceAccountName != "default" {
150-
objs = append(objs, GenerateServiceAccountResource(serviceAccountName, opts.InstallNamespace))
151-
}
152-
}
153-
return objs, nil
146+
if rv1 == nil {
147+
return nil, fmt.Errorf("bundle cannot be nil")
148+
}
149+
allPermissions := append(
150+
rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions,
151+
rv1.CSV.Spec.InstallStrategy.StrategySpec.ClusterPermissions...,
152+
)
153+
154+
serviceAccountNames := sets.Set[string]{}
155+
for _, permission := range allPermissions {
156+
serviceAccountNames.Insert(saNameOrDefault(permission.ServiceAccountName))
157+
}
158+
159+
objs := make([]client.Object, 0, len(serviceAccountNames))
160+
for _, serviceAccountName := range serviceAccountNames.UnsortedList() {
161+
// no need to generate the default service account
162+
if serviceAccountName != "default" {
163+
objs = append(objs, GenerateServiceAccountResource(serviceAccountName, opts.InstallNamespace))
164+
}
165+
}
166+
return objs, nil
154167
}
155168

156169
func BundleCRDGenerator(rv1 *RegistryV1, _ Options) ([]client.Object, error) {
157-
objs := make([]client.Object, 0, len(rv1.CRDs))
158-
for _, crd := range rv1.CRDs {
159-
objs = append(objs, crd.DeepCopy())
160-
}
161-
return objs, nil
170+
if rv1 == nil {
171+
return nil, fmt.Errorf("bundle cannot be nil")
172+
}
173+
objs := make([]client.Object, 0, len(rv1.CRDs))
174+
for _, crd := range rv1.CRDs {
175+
objs = append(objs, crd.DeepCopy())
176+
}
177+
return objs, nil
162178
}
163179

164180
func BundleAdditionalResourcesGenerator(rv1 *RegistryV1, opts Options) ([]client.Object, error) {
165-
objs := make([]client.Object, 0, len(rv1.Others))
166-
for _, res := range rv1.Others {
167-
supported, namespaced := registrybundle.IsSupported(res.GetKind())
168-
if !supported {
169-
return nil, fmt.Errorf("bundle contains unsupported resource: Name: %v, Kind: %v", res.GetName(), res.GetKind())
170-
}
171-
172-
obj := res.DeepCopy()
173-
if namespaced {
174-
obj.SetNamespace(opts.InstallNamespace)
175-
}
176-
177-
objs = append(objs, obj)
178-
}
179-
return objs, nil
181+
if rv1 == nil {
182+
return nil, fmt.Errorf("bundle cannot be nil")
183+
}
184+
objs := make([]client.Object, 0, len(rv1.Others))
185+
for _, res := range rv1.Others {
186+
supported, namespaced := registrybundle.IsSupported(res.GetKind())
187+
if !supported {
188+
return nil, fmt.Errorf("bundle contains unsupported resource: Name: %v, Kind: %v", res.GetName(), res.GetKind())
189+
}
190+
191+
obj := res.DeepCopy()
192+
if namespaced {
193+
obj.SetNamespace(opts.InstallNamespace)
194+
}
195+
196+
objs = append(objs, obj)
197+
}
198+
return objs, nil
180199
}
181200

182201
func saNameOrDefault(saName string) string {
183-
return cmp.Or(saName, "default")
202+
return cmp.Or(saName, "default")
184203
}

0 commit comments

Comments
 (0)