Skip to content

Commit 2e871d3

Browse files
Per Goncalves da Silvaperdasilva
Per Goncalves da Silva
authored andcommitted
Move Map and GroupBy to slice package
Signed-off-by: Per Goncalves da Silva <[email protected]>
1 parent 20d391a commit 2e871d3

File tree

4 files changed

+84
-54
lines changed

4 files changed

+84
-54
lines changed

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

+31-33
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import (
77

88
rbacv1 "k8s.io/api/rbac/v1"
99
"k8s.io/apimachinery/pkg/runtime/schema"
10-
"k8s.io/utils/ptr"
1110
"sigs.k8s.io/controller-runtime/pkg/client"
1211

13-
slicesutil "github.com/operator-framework/operator-controller/internal/shared/util/filter"
12+
"github.com/operator-framework/operator-controller/internal/shared/util/filter"
13+
slicesutil "github.com/operator-framework/operator-controller/internal/shared/util/slices"
1414
)
1515

1616
var (
@@ -45,21 +45,16 @@ var (
4545
}
4646
)
4747

48-
// GenerateResourceManagerClusterRole generates a ClusterRole with permissions to manage objs resources. The
48+
// GenerateResourceManagerClusterRolePerms generates a ClusterRole permissions to manage objs resources. The
4949
// permissions also aggregate any permissions from any ClusterRoles in objs allowing the holder to also assign
5050
// the RBAC therein to another service account. Note: assumes objs have been created by convert.Convert.
51-
// The returned ClusterRole will not have set .metadata.name
52-
func GenerateResourceManagerClusterRole(objs []client.Object) *rbacv1.ClusterRole {
53-
rules := slices.Concat(
51+
func GenerateResourceManagerClusterRolePerms(objs []client.Object) []rbacv1.PolicyRule {
52+
return slices.Concat(
5453
// cluster scoped resource creation and management rules
55-
generatePolicyRules(slicesutil.Filter(objs, isClusterScopedResource)),
54+
generatePolicyRules(filter.Filter(objs, isClusterScopedResource)),
5655
// controller rbac scope
57-
collectRBACResourcePolicyRules(slicesutil.Filter(objs, slicesutil.And(isGeneratedResource, isOfKind("ClusterRole")))),
56+
collectRBACResourcePolicyRules(filter.Filter(objs, filter.And(isGeneratedResource, isOfKind("ClusterRole")))),
5857
)
59-
if len(rules) == 0 {
60-
return nil
61-
}
62-
return ptr.To(newClusterRole("", rules))
6358
}
6459

6560
// GenerateClusterExtensionFinalizerPolicyRule generates a policy rule that allows the holder to update
@@ -73,26 +68,27 @@ func GenerateClusterExtensionFinalizerPolicyRule(clusterExtensionName string) rb
7368
}
7469
}
7570

76-
// GenerateResourceManagerRoles generates one or more Roles with permissions to manage objs resources in their
71+
// GenerateResourceManagerRolePerms generates role permissions to manage objs resources in their
7772
// namespaces. The permissions also include any permissions defined in any Roles in objs within the namespace, allowing
7873
// the holder to also assign the RBAC therein to another service account.
7974
// Note: currently assumes objs have been created by convert.Convert.
8075
// The returned Roles will not have set .metadata.name
81-
func GenerateResourceManagerRoles(objs []client.Object) []*rbacv1.Role {
82-
return mapToSlice(slicesutil.GroupBy(slicesutil.Filter(objs, isNamespaceScopedResource), namespaceName), generateRole)
83-
}
84-
85-
func generateRole(namespace string, namespaceObjs []client.Object) *rbacv1.Role {
86-
return ptr.To(newRole(
87-
namespace,
88-
"",
89-
slices.Concat(
90-
// namespace scoped resource creation and management rules
91-
generatePolicyRules(namespaceObjs),
92-
// controller rbac scope
93-
collectRBACResourcePolicyRules(slicesutil.Filter(namespaceObjs, slicesutil.And(isOfKind("Role"), isGeneratedResource))),
94-
),
95-
))
76+
func GenerateResourceManagerRolePerms(objs []client.Object) map[string][]rbacv1.PolicyRule {
77+
out := map[string][]rbacv1.PolicyRule{}
78+
namespaceScopedObjs := filter.Filter(objs, isNamespaceScopedResource)
79+
for _, obj := range namespaceScopedObjs {
80+
namespace := obj.GetNamespace()
81+
if _, ok := out[namespace]; !ok {
82+
objsInNamespace := filter.Filter(namespaceScopedObjs, isInNamespace(namespace))
83+
out[namespace] = slices.Concat(
84+
// namespace scoped resource creation and management rules
85+
generatePolicyRules(objsInNamespace),
86+
// controller rbac scope
87+
collectRBACResourcePolicyRules(filter.Filter(objsInNamespace, filter.And(isOfKind("Role"), isGeneratedResource))),
88+
)
89+
}
90+
}
91+
return out
9692
}
9793

9894
func generatePolicyRules(objs []client.Object) []rbacv1.PolicyRule {
@@ -143,7 +139,7 @@ func isNamespaceScopedResource(o client.Object) bool {
143139
return slices.Contains(namespaceScopedResources, o.GetObjectKind().GroupVersionKind().Kind)
144140
}
145141

146-
func isOfKind(kind string) slicesutil.Predicate[client.Object] {
142+
func isOfKind(kind string) filter.Predicate[client.Object] {
147143
return func(o client.Object) bool {
148144
return o.GetObjectKind().GroupVersionKind().Kind == kind
149145
}
@@ -155,12 +151,14 @@ func isGeneratedResource(o client.Object) bool {
155151
return ok
156152
}
157153

158-
func groupKind(obj client.Object) schema.GroupKind {
159-
return obj.GetObjectKind().GroupVersionKind().GroupKind()
154+
func isInNamespace(namespace string) filter.Predicate[client.Object] {
155+
return func(o client.Object) bool {
156+
return o.GetNamespace() == namespace
157+
}
160158
}
161159

162-
func namespaceName(obj client.Object) string {
163-
return obj.GetNamespace()
160+
func groupKind(obj client.Object) schema.GroupKind {
161+
return obj.GetObjectKind().GroupVersionKind().GroupKind()
164162
}
165163

166164
func toResourceName(o client.Object) string {

internal/shared/util/filter/filter.go

-21
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ import "slices"
55
// Predicate returns true if the object should be kept when filtering
66
type Predicate[T any] func(entity T) bool
77

8-
type Key[T any, K comparable] func(entity T) K
9-
10-
type MapFn[S any, V any] func(S) V
11-
128
func And[T any](predicates ...Predicate[T]) Predicate[T] {
139
return func(obj T) bool {
1410
for _, predicate := range predicates {
@@ -54,20 +50,3 @@ func Filter[T any](s []T, test Predicate[T]) []T {
5450
func InPlace[T any](s []T, test Predicate[T]) []T {
5551
return slices.DeleteFunc(s, Not(test))
5652
}
57-
58-
func GroupBy[T any, K comparable](s []T, key Key[T, K]) map[K][]T {
59-
out := map[K][]T{}
60-
for _, value := range s {
61-
k := key(value)
62-
out[k] = append(out[k], value)
63-
}
64-
return out
65-
}
66-
67-
func Map[S, V any](s []S, mapper MapFn[S, V]) []V {
68-
out := make([]V, len(s))
69-
for i := 0; i < len(s); i++ {
70-
out[i] = mapper(s[i])
71-
}
72-
return out
73-
}

internal/shared/util/slices/slices.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package slices
2+
3+
type Key[T any, K comparable] func(entity T) K
4+
5+
type MapFn[S any, V any] func(S) V
6+
7+
func GroupBy[T any, K comparable](s []T, key Key[T, K]) map[K][]T {
8+
out := map[K][]T{}
9+
for _, value := range s {
10+
k := key(value)
11+
out[k] = append(out[k], value)
12+
}
13+
return out
14+
}
15+
16+
func Map[S, V any](s []S, mapper MapFn[S, V]) []V {
17+
out := make([]V, len(s))
18+
for i := 0; i < len(s); i++ {
19+
out[i] = mapper(s[i])
20+
}
21+
return out
22+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package slices_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
8+
slicesutil "github.com/operator-framework/operator-controller/internal/shared/util/slices"
9+
)
10+
11+
func Test_Map(t *testing.T) {
12+
in := []int{1, 2, 3, 4, 5}
13+
doubleIt := func(val int) int {
14+
return 2 * val
15+
}
16+
require.Equal(t, []int{2, 4, 6, 8, 10}, slicesutil.Map(in, doubleIt))
17+
}
18+
19+
func Test_GroupBy(t *testing.T) {
20+
in := []int{1, 2, 3, 4, 5}
21+
oddOrEven := func(val int) string {
22+
if val%2 == 0 {
23+
return "even"
24+
}
25+
return "odd"
26+
}
27+
require.Equal(t, map[string][]int{
28+
"even": {2, 4},
29+
"odd": {1, 3, 5},
30+
}, slicesutil.GroupBy(in, oddOrEven))
31+
}

0 commit comments

Comments
 (0)