Skip to content

Commit bf02ec0

Browse files
committed
helm: use chunking release driver in systemNamespace
Signed-off-by: Joe Lanford <[email protected]>
1 parent 245436c commit bf02ec0

File tree

9 files changed

+287
-43
lines changed

9 files changed

+287
-43
lines changed

cmd/manager/main.go

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
3030
k8slabels "k8s.io/apimachinery/pkg/labels"
3131
"k8s.io/apimachinery/pkg/selection"
32-
"k8s.io/apimachinery/pkg/types"
3332
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
3433
_ "k8s.io/client-go/plugin/pkg/client/auth"
3534
"k8s.io/client-go/rest"
@@ -159,38 +158,23 @@ func main() {
159158
os.Exit(1)
160159
}
161160

162-
installNamespaceMapper := helmclient.ObjectToStringMapper(func(obj client.Object) (string, error) {
163-
ext := obj.(*ocv1alpha1.ClusterExtension)
164-
return ext.Spec.InstallNamespace, nil
165-
})
166161
coreClient, err := corev1client.NewForConfig(mgr.GetConfig())
167162
if err != nil {
168163
setupLog.Error(err, "unable to create core client")
169164
os.Exit(1)
170165
}
171166
tokenGetter := authentication.NewTokenGetter(coreClient, authentication.WithExpirationDuration(1*time.Hour))
172167

173-
restConfigMapper := func(ctx context.Context, o client.Object, c *rest.Config) (*rest.Config, error) {
174-
cExt, ok := o.(*ocv1alpha1.ClusterExtension)
175-
if !ok {
176-
return c, nil
177-
}
178-
namespacedName := types.NamespacedName{
179-
Name: cExt.Spec.ServiceAccount.Name,
180-
Namespace: cExt.Spec.InstallNamespace,
181-
}
182-
token, err := tokenGetter.Get(ctx, namespacedName)
183-
if err != nil {
184-
return nil, fmt.Errorf("failed to extract SA token, %w", err)
185-
}
186-
tempConfig := rest.AnonymousClientConfig(c)
187-
tempConfig.BearerToken = token
188-
return tempConfig, nil
189-
}
190168
cfgGetter, err := helmclient.NewActionConfigGetter(mgr.GetConfig(), mgr.GetRESTMapper(),
191-
helmclient.StorageNamespaceMapper(installNamespaceMapper),
192-
helmclient.ClientNamespaceMapper(installNamespaceMapper),
193-
helmclient.RestConfigMapper(restConfigMapper),
169+
helmclient.StorageRestConfigMapper(func(ctx context.Context, obj client.Object, config *rest.Config) (*rest.Config, error) {
170+
return rest.CopyConfig(config), nil
171+
}),
172+
helmclient.StorageDriverMapper(action.ChunkedStorageDriverMapper(coreClient, mgr.GetAPIReader(), systemNamespace)),
173+
helmclient.ClientNamespaceMapper(func(obj client.Object) (string, error) {
174+
ext := obj.(*ocv1alpha1.ClusterExtension)
175+
return ext.Spec.InstallNamespace, nil
176+
}),
177+
helmclient.ClientRestConfigMapper(action.ServiceAccountRestConfigMapper(tokenGetter)),
194178
)
195179
if err != nil {
196180
setupLog.Error(err, "unable to config for creating helm client")

config/base/rbac/role.yaml

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,6 @@ rules:
3030
verbs:
3131
- list
3232
- watch
33-
- apiGroups:
34-
- ""
35-
resources:
36-
- secrets
37-
verbs:
38-
- create
39-
- delete
40-
- get
41-
- list
42-
- patch
43-
- update
44-
- watch
4533
- apiGroups:
4634
- ""
4735
resources:
@@ -71,3 +59,23 @@ rules:
7159
verbs:
7260
- patch
7361
- update
62+
---
63+
apiVersion: rbac.authorization.k8s.io/v1
64+
kind: Role
65+
metadata:
66+
name: manager-role
67+
namespace: system
68+
rules:
69+
- apiGroups:
70+
- ""
71+
resources:
72+
- secrets
73+
verbs:
74+
- create
75+
- delete
76+
- deletecollection
77+
- get
78+
- list
79+
- patch
80+
- update
81+
- watch

config/base/rbac/role_binding.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,17 @@ subjects:
1010
- kind: ServiceAccount
1111
name: controller-manager
1212
namespace: system
13+
---
14+
apiVersion: rbac.authorization.k8s.io/v1
15+
kind: RoleBinding
16+
metadata:
17+
name: manager-rolebinding
18+
namespace: system
19+
roleRef:
20+
apiGroup: rbac.authorization.k8s.io
21+
kind: Role
22+
name: manager-role
23+
subjects:
24+
- kind: ServiceAccount
25+
name: controller-manager
26+
namespace: system
Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,104 @@
1+
---
2+
apiVersion: v1
3+
kind: Namespace
4+
metadata:
5+
name: argocd
6+
---
7+
apiVersion: v1
8+
kind: ServiceAccount
9+
metadata:
10+
name: argocd-installer
11+
namespace: argocd
12+
---
13+
apiVersion: rbac.authorization.k8s.io/v1
14+
kind: ClusterRoleBinding
15+
metadata:
16+
name: argocd-installer-binding
17+
roleRef:
18+
apiGroup: rbac.authorization.k8s.io
19+
kind: ClusterRole
20+
name: argocd-installer-clusterrole
21+
subjects:
22+
- kind: ServiceAccount
23+
name: argocd-installer
24+
namespace: argocd
25+
---
26+
apiVersion: rbac.authorization.k8s.io/v1
27+
kind: ClusterRole
28+
metadata:
29+
name: argocd-installer-clusterrole
30+
rules:
31+
- apiGroups: ["*"]
32+
resources: ["*"]
33+
verbs: ["*"]
34+
- apiGroups: [apiextensions.k8s.io]
35+
resources: [customresourcedefinitions]
36+
verbs: [get, list, watch, create, update, patch, delete]
37+
resourceNames:
38+
- appprojects.argoproj.io
39+
- argocds.argoproj.io
40+
- applications.argoproj.io
41+
- argocdexports.argoproj.io
42+
- applicationsets.argoproj.io
43+
- apiGroups: [rbac.authorization.k8s.io]
44+
resources: [clusterroles]
45+
verbs: [get, list, watch, create, update, patch, delete]
46+
resourceNames:
47+
- argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx
48+
- argocd-operator-metrics-reader
49+
- argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3
50+
- apiGroups: [rbac.authorization.k8s.io]
51+
resources: [clusterrolebindings]
52+
verbs: [get, list, watch, create, update, patch, delete]
53+
resourceNames:
54+
- argocd-operator.v0-1dhiybrldl1gyksid1dk2dqjsc72psdybc7iyvse5gpx
55+
- argocd-operator.v0-22gmilmgp91wu25is5i2ec598hni8owq3l71bbkl7iz3
56+
---
57+
apiVersion: rbac.authorization.k8s.io/v1
58+
kind: Role
59+
metadata:
60+
name: argocd-installer-role
61+
namespace: argocd
62+
rules:
63+
- apiGroups: [""]
64+
resources: [serviceaccounts]
65+
verbs: [get, list, watch, create, update, patch, delete]
66+
resourceNames: [argocd-operator-controller-manager]
67+
- apiGroups: [""]
68+
resources: [configmaps]
69+
verbs: [get, list, watch, create, update, patch, delete]
70+
resourceNames: [argocd-operator-manager-config]
71+
- apiGroups: [""]
72+
resources: [services]
73+
verbs: [get, list, watch, create, update, patch, delete]
74+
resourceNames: [argocd-operator-controller-manager-metrics-service]
75+
- apiGroups: [apps]
76+
resources: [deployments]
77+
verbs: [get, list, watch, create, update, patch, delete]
78+
resourceNames: [argocd-operator-controller-manager]
79+
---
80+
apiVersion: rbac.authorization.k8s.io/v1
81+
kind: RoleBinding
82+
metadata:
83+
name: argocd-installer-binding
84+
namespace: argocd
85+
roleRef:
86+
apiGroup: rbac.authorization.k8s.io
87+
kind: Role
88+
name: argocd-installer-role
89+
subjects:
90+
- kind: ServiceAccount
91+
name: argocd-installer
92+
namespace: argocd
93+
---
194
apiVersion: olm.operatorframework.io/v1alpha1
295
kind: ClusterExtension
396
metadata:
4-
name: clusterextension-sample
97+
name: argocd
598
spec:
6-
installNamespace: default
99+
installNamespace: argocd
7100
packageName: argocd-operator
8101
version: 0.6.0
9102
serviceAccount:
10-
name: default
103+
name: argocd-installer
104+
---

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ require (
3535
sigs.k8s.io/yaml v1.4.0
3636
)
3737

38+
replace github.com/operator-framework/helm-operator-plugins => github.com/joelanford/helm-operator v0.0.8-0.20240719203048-14906f8dfcf8
39+
3840
require (
3941
carvel.dev/vendir v0.40.0 // indirect
4042
cloud.google.com/go/compute/metadata v0.3.0 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
443443
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
444444
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
445445
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
446+
github.com/joelanford/helm-operator v0.0.8-0.20240719203048-14906f8dfcf8 h1:+hG2OiAiMz4/zUYLi6+FzjrCRNVJedafECfjaYgTkwc=
447+
github.com/joelanford/helm-operator v0.0.8-0.20240719203048-14906f8dfcf8/go.mod h1:5Kx1PyLnRVPyQmLq+frv+HJgSZzXG+W6LavSCxzm8sI=
446448
github.com/joelanford/ignore v0.1.0 h1:VawbTDeg5EL+PN7W8gxVzGerfGpVo3gFdR5ZAqnkYRk=
447449
github.com/joelanford/ignore v0.1.0/go.mod h1:Vb0PQMAQXK29fmiPjDukpO8I2NTcp1y8LbhFijD1/0o=
448450
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@@ -590,8 +592,6 @@ github.com/operator-framework/api v0.26.0 h1:YVntU2NkVl5zSLLwK5kFcH6P3oSvN9QDgTs
590592
github.com/operator-framework/api v0.26.0/go.mod h1:3IxOwzVUeGxYlzfwKCcfCyS+q3EEhWA/4kv7UehbeyM=
591593
github.com/operator-framework/catalogd v0.18.0 h1:3eFoURYkn+vspoqYL5ijzUjAyVMSSR60BMOiKFvdVmM=
592594
github.com/operator-framework/catalogd v0.18.0/go.mod h1:3i2dDt0yg6L/xHbNt93/Teao6xBC8rhL6UgewjQpvI8=
593-
github.com/operator-framework/helm-operator-plugins v0.3.0 h1:LNhcb5nPT/TAxZSsKH2LTYh79RgiN2twGFptQR96sRM=
594-
github.com/operator-framework/helm-operator-plugins v0.3.0/go.mod h1:ly6Bd9rSzmt37Wy6WtZHmA+IY9zG958MryJFLcVpCXw=
595595
github.com/operator-framework/operator-lib v0.14.0 h1:er+BgZymZD1im2wytLJiPLZpGALAX6N0gXaHx3PKbO4=
596596
github.com/operator-framework/operator-lib v0.14.0/go.mod h1:wUu4Xb9xzXnIpglvaZ3yucTMSlqGXHIoUEH9+5gWiu0=
597597
github.com/operator-framework/operator-registry v1.45.0 h1:9c5NshWjPncdZtWEY0cfMnAjx3pShVnjw5UmZXp/xNE=

internal/action/restconfig.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package action
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"k8s.io/apimachinery/pkg/types"
8+
"k8s.io/client-go/rest"
9+
"sigs.k8s.io/controller-runtime/pkg/client"
10+
11+
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
12+
13+
ocv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
14+
"github.com/operator-framework/operator-controller/internal/authentication"
15+
)
16+
17+
func ServiceAccountRestConfigMapper(tokenGetter *authentication.TokenGetter) helmclient.ObjectToRestConfigMapper {
18+
return func(ctx context.Context, o client.Object, c *rest.Config) (*rest.Config, error) {
19+
cExt := o.(*ocv1alpha1.ClusterExtension)
20+
saKey := types.NamespacedName{
21+
Name: cExt.Spec.ServiceAccount.Name,
22+
Namespace: cExt.Spec.InstallNamespace,
23+
}
24+
token, err := tokenGetter.Get(ctx, saKey)
25+
if err != nil {
26+
return nil, fmt.Errorf("failed to get token for serviceaccount %q: %w", saKey, err)
27+
}
28+
saConfig := rest.AnonymousClientConfig(c)
29+
saConfig.BearerToken = token
30+
return saConfig, nil
31+
}
32+
}

internal/action/storagedriver.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package action
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"helm.sh/helm/v3/pkg/storage/driver"
8+
corev1 "k8s.io/api/core/v1"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/apimachinery/pkg/fields"
11+
k8slabels "k8s.io/apimachinery/pkg/labels"
12+
"k8s.io/apimachinery/pkg/watch"
13+
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
14+
"k8s.io/client-go/rest"
15+
"sigs.k8s.io/controller-runtime/pkg/client"
16+
logf "sigs.k8s.io/controller-runtime/pkg/log"
17+
18+
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
19+
"github.com/operator-framework/helm-operator-plugins/pkg/storage"
20+
)
21+
22+
func ChunkedStorageDriverMapper(secretsGetter clientcorev1.SecretsGetter, reader client.Reader, namespace string) helmclient.ObjectToStorageDriverMapper {
23+
secretsClient := newSecretsDelegatingClient(secretsGetter, reader, namespace)
24+
return func(ctx context.Context, object client.Object, config *rest.Config) (driver.Driver, error) {
25+
log := logf.FromContext(ctx).V(2)
26+
ownerRefs := []metav1.OwnerReference{*metav1.NewControllerRef(object, object.GetObjectKind().GroupVersionKind())}
27+
ownerRefSecretClient := helmclient.NewOwnerRefSecretClient(secretsClient, ownerRefs, func(secret *corev1.Secret) bool {
28+
return secret.Type == storage.SecretTypeChunkedIndex
29+
})
30+
return storage.NewChunkedSecrets(ownerRefSecretClient, "operator-controller", storage.ChunkedSecretsConfig{
31+
ChunkSize: 1024 * 1024,
32+
MaxReadChunks: 10,
33+
MaxWriteChunks: 10,
34+
Log: func(format string, args ...interface{}) { log.Info(fmt.Sprintf(format, args...)) },
35+
}), nil
36+
}
37+
}
38+
39+
var _ clientcorev1.SecretInterface = &secretsDelegatingClient{}
40+
41+
type secretsDelegatingClient struct {
42+
clientcorev1.SecretInterface
43+
reader client.Reader
44+
namespace string
45+
}
46+
47+
func newSecretsDelegatingClient(secretsGetter clientcorev1.SecretsGetter, reader client.Reader, namespace string) clientcorev1.SecretInterface {
48+
return &secretsDelegatingClient{
49+
SecretInterface: secretsGetter.Secrets(namespace),
50+
namespace: namespace,
51+
reader: reader,
52+
}
53+
}
54+
55+
func (s secretsDelegatingClient) Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error) {
56+
var secret corev1.Secret
57+
if err := s.reader.Get(ctx, client.ObjectKey{Namespace: s.namespace, Name: name}, &secret, &client.GetOptions{Raw: &opts}); err != nil {
58+
return nil, err
59+
}
60+
return &secret, nil
61+
}
62+
63+
func (s secretsDelegatingClient) List(ctx context.Context, opts metav1.ListOptions) (*corev1.SecretList, error) {
64+
listOpts, err := metaOptionsToClientOptions(s.namespace, opts)
65+
if err != nil {
66+
return nil, err
67+
}
68+
69+
var secrets corev1.SecretList
70+
if err := s.reader.List(ctx, &secrets, listOpts); err != nil {
71+
return nil, fmt.Errorf("error listing from cache: %w", err)
72+
}
73+
return &secrets, nil
74+
}
75+
76+
func (s secretsDelegatingClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
77+
panic("intentionally not implemented: watch is not intended to be called")
78+
}
79+
80+
func metaOptionsToClientOptions(namespace string, opts metav1.ListOptions) (*client.ListOptions, error) {
81+
clientListOptions := &client.ListOptions{
82+
Namespace: namespace,
83+
Limit: opts.Limit,
84+
Continue: opts.Continue,
85+
}
86+
87+
if opts.LabelSelector != "" {
88+
labelSelector, err := k8slabels.Parse(opts.LabelSelector)
89+
if err != nil {
90+
return nil, err
91+
}
92+
clientListOptions.LabelSelector = labelSelector
93+
}
94+
95+
if opts.FieldSelector != "" {
96+
fieldSelector, err := fields.ParseSelector(opts.FieldSelector)
97+
if err != nil {
98+
return nil, err
99+
}
100+
clientListOptions.FieldSelector = fieldSelector
101+
}
102+
103+
opts.LabelSelector = ""
104+
opts.FieldSelector = ""
105+
opts.Limit = 0
106+
opts.Continue = ""
107+
clientListOptions.Raw = &opts
108+
109+
return clientListOptions, nil
110+
}

0 commit comments

Comments
 (0)