Skip to content

Commit 7359429

Browse files
fixed upgrade to kube 1.24 (#42)
* fixed upgrade to kube 1.24 Signed-off-by: raffaelespazzoli <raffaele.spazzoli@gmail.com> * added more docs Signed-off-by: raffaelespazzoli <raffaele.spazzoli@gmail.com> Signed-off-by: raffaelespazzoli <raffaele.spazzoli@gmail.com>
1 parent bea6e7a commit 7359429

File tree

2 files changed

+65
-19
lines changed

2 files changed

+65
-19
lines changed

controllers/patch_controller.go

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"k8s.io/apimachinery/pkg/types"
3232
"k8s.io/client-go/rest"
3333
ctrl "sigs.k8s.io/controller-runtime"
34+
"sigs.k8s.io/controller-runtime/pkg/client"
3435
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3536
"sigs.k8s.io/controller-runtime/pkg/handler"
3637
"sigs.k8s.io/controller-runtime/pkg/log"
@@ -132,34 +133,67 @@ func (r *PatchReconciler) SetupWithManager(mgr ctrl.Manager) error {
132133
func (r *PatchReconciler) getRestConfigFromInstance(ctx context.Context, instance *redhatcopv1alpha1.Patch) (*rest.Config, error) {
133134
rlog := log.FromContext(ctx)
134135
sa := corev1.ServiceAccount{}
135-
err := r.GetClient().Get(ctx, types.NamespacedName{Name: instance.Spec.ServiceAccountRef.Name, Namespace: instance.GetNamespace()}, &sa)
136+
137+
secretList := &corev1.SecretList{}
138+
err := r.GetClient().List(ctx, secretList, &client.ListOptions{
139+
Namespace: instance.GetNamespace(),
140+
})
141+
142+
var saSecret corev1.Secret
143+
136144
if err != nil {
137-
rlog.Error(err, "unable to get the specified", "service account", types.NamespacedName{Name: instance.Spec.ServiceAccountRef.Name, Namespace: instance.GetNamespace()})
138-
return &rest.Config{}, err
145+
rlog.Error(err, "unable to retrieve secrets", "in namespace", instance.GetNamespace())
146+
return nil, err
147+
}
148+
for _, secret := range secretList.Items {
149+
if saname, ok := secret.Annotations["kubernetes.io/service-account.name"]; ok {
150+
if secret.Type == corev1.SecretTypeServiceAccountToken && saname == instance.Spec.ServiceAccountRef.Name {
151+
if _, ok := secret.Data["token"]; ok {
152+
saSecret = secret
153+
break
154+
} else {
155+
return nil, errs.New("unable to find \"token\" key in secret" + instance.GetNamespace() + "/" + secret.Name)
156+
}
157+
}
158+
}
139159
}
140-
var tokenSecret corev1.Secret
141-
for _, secretRef := range sa.Secrets {
142-
secret := corev1.Secret{}
143-
err := r.GetClient().Get(ctx, types.NamespacedName{Name: secretRef.Name, Namespace: instance.GetNamespace()}, &secret)
160+
// if the map is still empty we test the old approach, pre kube 1.21
161+
if _, ok := saSecret.Data["token"]; !ok {
162+
err := r.GetClient().Get(ctx, types.NamespacedName{Name: instance.Spec.ServiceAccountRef.Name, Namespace: instance.GetNamespace()}, &sa)
144163
if err != nil {
145-
rlog.Error(err, "(ignoring) unable to get ", "ref secret", types.NamespacedName{Name: secretRef.Name, Namespace: instance.GetNamespace()})
146-
continue
164+
rlog.Error(err, "unable to get the specified", "service account", types.NamespacedName{Name: instance.Spec.ServiceAccountRef.Name, Namespace: instance.GetNamespace()})
165+
return &rest.Config{}, err
147166
}
148-
if secret.Type == "kubernetes.io/service-account-token" {
149-
tokenSecret = secret
150-
break
167+
var tokenSecret corev1.Secret
168+
for _, secretRef := range sa.Secrets {
169+
secret := corev1.Secret{}
170+
err := r.GetClient().Get(ctx, types.NamespacedName{Name: secretRef.Name, Namespace: instance.GetNamespace()}, &secret)
171+
if err != nil {
172+
rlog.Error(err, "(ignoring) unable to get ", "ref secret", types.NamespacedName{Name: secretRef.Name, Namespace: instance.GetNamespace()})
173+
continue
174+
}
175+
if secret.Type == "kubernetes.io/service-account-token" {
176+
tokenSecret = secret
177+
break
178+
}
179+
}
180+
if tokenSecret.Data == nil {
181+
err = errs.New("unable to find secret of type kubernetes.io/service-account-token")
182+
rlog.Error(err, "unable to find secret of type kubernetes.io/service-account-token for", "service account", sa)
183+
return &rest.Config{}, err
184+
}
185+
if _, ok := tokenSecret.Data["token"]; ok {
186+
saSecret = tokenSecret
187+
} else {
188+
return nil, errs.New("unable to find \"token\" key in secret" + instance.GetNamespace() + "/" + tokenSecret.Name)
151189
}
152190
}
153-
if tokenSecret.Data == nil {
154-
err = errs.New("unable to find secret of type kubernetes.io/service-account-token")
155-
rlog.Error(err, "unable to find secret of type kubernetes.io/service-account-token for", "service account", sa)
156-
return &rest.Config{}, err
157-
}
191+
// if we got here the map should be filled up
158192
config := rest.Config{
159193
Host: r.GetRestConfig().Host,
160-
BearerToken: string(tokenSecret.Data["token"]),
194+
BearerToken: string(saSecret.Data["token"]),
161195
TLSClientConfig: rest.TLSClientConfig{
162-
CAData: tokenSecret.Data["ca.crt"],
196+
CAData: saSecret.Data["ca.crt"],
163197
},
164198
}
165199
return &config, nil

readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,18 @@ The `deployer` service accounts from all namespaces are selected as target of th
385385

386386
The patch enforcement enacted by the patch controller is executed with a client which uses the service account referenced by the `serviceAccountRef` field. So before a patch object can actually work an administrator must have granted the needed permissions to a service account in the same namespace. The `serviceAccountRef` will default to the `default` service account if not specified.
387387

388+
_Note:_ with kubernetes 1.24, service account token secrets are not created automatically anymore (see also [here](https://kubernetes.io/docs/concepts/configuration/secret/#service-account-token-secrets)). The path-operator relies on these secrets. So you have to create the secret for the service account referenced in the `serviceAccountRef`. Here is an example of how to create a service account token secret for the `default` service account:
389+
390+
```yaml
391+
apiVersion: v1
392+
kind: Secret
393+
metadata:
394+
name: default-service-account-secret
395+
annotations:
396+
kubernetes.io/service-account.name: "default"
397+
type: kubernetes.io/service-account-token
398+
```
399+
388400
### Patch Controller Performance Considerations
389401

390402
The patch controller will create a controller-manager and per `Patch` object and a reconciler for each of the `PatchSpec` defined in the array on patches in the `Patch` object.

0 commit comments

Comments
 (0)