Skip to content

Commit 688bd22

Browse files
author
Per Goncalves da Silva
committed
add render package
Signed-off-by: Per Goncalves da Silva <[email protected]>
1 parent e49597a commit 688bd22

16 files changed

+24320
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package render
2+
3+
import (
4+
"fmt"
5+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/convert"
6+
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util"
7+
registrybundle "github.com/operator-framework/operator-registry/pkg/lib/bundle"
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"
13+
"strings"
14+
)
15+
16+
type Options struct {
17+
InstallNamespace string
18+
TargetNamespaces []string
19+
UniqueNameGenerator func(string, interface{}) (string, error)
20+
}
21+
22+
type ResourceGenerator func(rv1 *convert.RegistryV1, opts Options) ([]client.Object, error)
23+
24+
func (g ResourceGenerator) GenerateResources(rv1 *convert.RegistryV1, opts Options) ([]client.Object, error) {
25+
return g(rv1, opts)
26+
}
27+
28+
func ChainedResourceGenerator(resourceGenerators ...ResourceGenerator) ResourceGenerator {
29+
return func(rv1 *convert.RegistryV1, opts Options) ([]client.Object, error) {
30+
var renderedObjects []client.Object
31+
for _, generator := range resourceGenerators {
32+
objs, err := generator(rv1, opts)
33+
if err != nil {
34+
return nil, err
35+
}
36+
renderedObjects = append(renderedObjects, objs...)
37+
}
38+
return renderedObjects, nil
39+
}
40+
}
41+
42+
func BundleDeploymentGenerator(rv1 *convert.RegistryV1, opts Options) ([]client.Object, error) {
43+
var objs []client.Object
44+
for _, depSpec := range rv1.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
45+
annotations := util.MergeMaps(rv1.CSV.Annotations, depSpec.Spec.Template.Annotations)
46+
annotations["olm.targetNamespaces"] = strings.Join(opts.TargetNamespaces, ",")
47+
depSpec.Spec.Template.Annotations = annotations
48+
49+
// Hardcode the deployment with RevisionHistoryLimit=1 (something OLMv0 does, not sure why)
50+
depSpec.Spec.RevisionHistoryLimit = ptr.To(int32(1))
51+
52+
objs = append(objs,
53+
GenerateDeploymentResource(
54+
depSpec.Name,
55+
opts.InstallNamespace,
56+
WithDeploymentSpec(depSpec.Spec),
57+
WithLabels(depSpec.Label),
58+
),
59+
)
60+
}
61+
return objs, nil
62+
}
63+
64+
func BundlePermissionsGenerator(rv1 *convert.RegistryV1, opts Options) ([]client.Object, error) {
65+
permissions := rv1.CSV.Spec.InstallStrategy.StrategySpec.Permissions
66+
clusterPermissions := rv1.CSV.Spec.InstallStrategy.StrategySpec.ClusterPermissions
67+
68+
// If we're in AllNamespaces mode, promote the permissions to clusterPermissions
69+
if len(opts.TargetNamespaces) == 1 && opts.TargetNamespaces[0] == "" {
70+
for _, p := range permissions {
71+
p.Rules = append(p.Rules, rbacv1.PolicyRule{
72+
Verbs: []string{"get", "list", "watch"},
73+
APIGroups: []string{corev1.GroupName},
74+
Resources: []string{"namespaces"},
75+
})
76+
clusterPermissions = append(clusterPermissions, p)
77+
}
78+
permissions = nil
79+
}
80+
81+
var objs []client.Object
82+
serviceAccountNames := sets.Set[string]{}
83+
for _, ns := range opts.TargetNamespaces {
84+
for _, permission := range permissions {
85+
saName := saNameOrDefault(permission.ServiceAccountName)
86+
name, err := opts.UniqueNameGenerator(fmt.Sprintf("%s-%s", rv1.CSV.Name, saName), permission)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
objs = append(objs,
92+
GenerateRoleResource(name, ns, WithRules(permission.Rules...)),
93+
GenerateRoleBindingResource(
94+
name,
95+
ns,
96+
WithSubjects(rbacv1.Subject{Kind: "ServiceAccount", Namespace: ns, Name: saName}),
97+
WithRoleRef(rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: name}),
98+
),
99+
)
100+
101+
serviceAccountNames.Insert(saName)
102+
}
103+
}
104+
105+
for _, permission := range clusterPermissions {
106+
saName := saNameOrDefault(permission.ServiceAccountName)
107+
name, err := opts.UniqueNameGenerator(fmt.Sprintf("%s-%s", rv1.CSV.Name, saName), permission)
108+
if err != nil {
109+
return nil, err
110+
}
111+
objs = append(objs,
112+
GenerateClusterRoleResource(name, WithRules(permission.Rules...)),
113+
GenerateClusterRoleBindingResource(
114+
name,
115+
WithSubjects(rbacv1.Subject{Kind: "ServiceAccount", Namespace: opts.InstallNamespace, Name: saName}),
116+
WithRoleRef(rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: name}),
117+
),
118+
)
119+
120+
serviceAccountNames.Insert(saName)
121+
}
122+
123+
for _, serviceAccountName := range serviceAccountNames.UnsortedList() {
124+
// no need to generate the default service account
125+
if serviceAccountName != "default" {
126+
objs = append(objs, GenerateServiceAccountResource(serviceAccountName, opts.InstallNamespace))
127+
}
128+
}
129+
130+
return objs, nil
131+
}
132+
133+
func BundleCRDGenerator(rv1 *convert.RegistryV1, _ Options) ([]client.Object, error) {
134+
var objs []client.Object
135+
for _, crd := range rv1.CRDs {
136+
objs = append(objs, crd.DeepCopy())
137+
}
138+
return objs, nil
139+
}
140+
141+
func BundleResourceGenerator(rv1 *convert.RegistryV1, _ Options) ([]client.Object, error) {
142+
var objs []client.Object
143+
for _, res := range rv1.Others {
144+
supported, namespaced := registrybundle.IsSupported(res.GetKind())
145+
if !supported {
146+
return nil, fmt.Errorf("bundle contains unsupported resource: Name: %v, Kind: %v", res.GetName(), res.GetKind())
147+
}
148+
149+
obj := res.DeepCopy()
150+
if namespaced {
151+
obj.SetNamespace(res.GetNamespace())
152+
}
153+
154+
objs = append(objs, obj)
155+
156+
}
157+
return objs, nil
158+
}
159+
160+
func saNameOrDefault(saName string) string {
161+
if saName == "" {
162+
return "default"
163+
}
164+
return saName
165+
}

0 commit comments

Comments
 (0)