From 4242d5ccc58a4ca6f200758932c16b0936382d40 Mon Sep 17 00:00:00 2001 From: igoramf Date: Thu, 7 May 2026 23:35:07 -0300 Subject: [PATCH 1/4] fix(rbac): add list/watch/update verbs for serviceaccounts and create builder SA in operator namespace The controller-runtime cache requires list+watch to set up informers for ServiceAccounts. CreateOrUpdate also needs the update verb. Adds a Helm template to pre-create the builder SA in the operator namespace with the IRSA annotation when build.roleArn is set. --- .../clusterrole-operator-manager-role.yaml | 3 ++ .../serviceaccount-operator-builder.yaml | 11 +++++++ internal/controller/deco_controller.go | 22 ++------------ internal/controller/serviceaccount.go | 30 +++++++++++++++++++ 4 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 chart/templates/serviceaccount-operator-builder.yaml create mode 100644 internal/controller/serviceaccount.go diff --git a/chart/templates/clusterrole-operator-manager-role.yaml b/chart/templates/clusterrole-operator-manager-role.yaml index 4955b35..f72f3fb 100644 --- a/chart/templates/clusterrole-operator-manager-role.yaml +++ b/chart/templates/clusterrole-operator-manager-role.yaml @@ -49,6 +49,9 @@ rules: verbs: - create - get + - list + - update + - watch - apiGroups: - batch resources: diff --git a/chart/templates/serviceaccount-operator-builder.yaml b/chart/templates/serviceaccount-operator-builder.yaml new file mode 100644 index 0000000..7fa2c6b --- /dev/null +++ b/chart/templates/serviceaccount-operator-builder.yaml @@ -0,0 +1,11 @@ +{{- if .Values.build.serviceAccount }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.build.serviceAccount }} + namespace: {{ .Release.Namespace }} + {{- if .Values.build.roleArn }} + annotations: + eks.amazonaws.com/role-arn: {{ .Values.build.roleArn | quote }} + {{- end }} +{{- end }} diff --git a/internal/controller/deco_controller.go b/internal/controller/deco_controller.go index 172d4b5..7498a7d 100644 --- a/internal/controller/deco_controller.go +++ b/internal/controller/deco_controller.go @@ -39,7 +39,7 @@ type DecoReconciler struct { // +kubebuilder:rbac:groups=deco.sites,resources=decos/status,verbs=get;update;patch // +kubebuilder:rbac:groups=deco.sites,resources=decos/finalizers,verbs=update // +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;delete -// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;create +// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update func (r *DecoReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := logf.FromContext(ctx) @@ -252,7 +252,7 @@ func (r *DecoReconciler) createJob(ctx context.Context, deco *decositesv1alpha1. } if sa := job.Spec.Template.Spec.ServiceAccountName; sa != "" { - if err := r.ensureServiceAccount(ctx, deco.Namespace, sa, r.BuilderSAAnnotations); err != nil { + if err := ensureServiceAccount(ctx, r.Client, deco.Namespace, sa, r.BuilderSAAnnotations); err != nil { return fmt.Errorf("ensuring service account %q: %w", sa, err) } } @@ -267,24 +267,6 @@ func (r *DecoReconciler) createJob(ctx context.Context, deco *decositesv1alpha1. return nil } -// ensureServiceAccount creates or updates the ServiceAccount merging the provided annotations. -func (r *DecoReconciler) ensureServiceAccount(ctx context.Context, namespace, name string, annotations map[string]string) error { - sa := &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, - } - _, err := controllerutil.CreateOrUpdate(ctx, r.Client, sa, func() error { - if len(annotations) > 0 { - if sa.Annotations == nil { - sa.Annotations = map[string]string{} - } - for k, v := range annotations { - sa.Annotations[k] = v - } - } - return nil - }) - return err -} func buildPhaseFromJob(job *batchv1.Job) string { for _, c := range job.Status.Conditions { diff --git a/internal/controller/serviceaccount.go b/internal/controller/serviceaccount.go new file mode 100644 index 0000000..99fafeb --- /dev/null +++ b/internal/controller/serviceaccount.go @@ -0,0 +1,30 @@ +package controller + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +// ensureServiceAccount creates or updates the named ServiceAccount in the given +// namespace, merging the provided annotations. It is idempotent. +func ensureServiceAccount(ctx context.Context, c client.Client, namespace, name string, annotations map[string]string) error { + sa := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace}, + } + _, err := controllerutil.CreateOrUpdate(ctx, c, sa, func() error { + if len(annotations) > 0 { + if sa.Annotations == nil { + sa.Annotations = map[string]string{} + } + for k, v := range annotations { + sa.Annotations[k] = v + } + } + return nil + }) + return err +} From 10c2ab0f93527796a5f3d701d5d5f4ddea6fb39a Mon Sep 17 00:00:00 2001 From: igoramf Date: Thu, 7 May 2026 23:40:49 -0300 Subject: [PATCH 2/4] fix(helm): generate builder SA and fix serviceaccount RBAC verbs via make helm The helm-generator was cleaning all templates on each run, so the manually created serviceaccount-operator-builder.yaml was deleted by CI. Added an addBuilderServiceAccount step to the generator so it produces the conditional Helm template. Also updated config/rbac/role.yaml with list/watch/update verbs so make helm generates the correct ClusterRole. --- ...sourcedefinition-decofiles.deco.sites.yaml | 2 +- ...omresourcedefinition-decos.deco.sites.yaml | 2 +- ...ilder.yaml => serviceaccount-builder.yaml} | 0 config/rbac/role.yaml | 3 +++ hack/helm-generator/main.go | 21 +++++++++++++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) rename chart/templates/{serviceaccount-operator-builder.yaml => serviceaccount-builder.yaml} (100%) diff --git a/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml b/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml index 1e6f7d1..7d17a2d 100644 --- a/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml +++ b/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: decofiles.deco.sites spec: group: deco.sites diff --git a/chart/templates/customresourcedefinition-decos.deco.sites.yaml b/chart/templates/customresourcedefinition-decos.deco.sites.yaml index e6e2265..a2c332e 100644 --- a/chart/templates/customresourcedefinition-decos.deco.sites.yaml +++ b/chart/templates/customresourcedefinition-decos.deco.sites.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.21.0 name: decos.deco.sites spec: group: deco.sites diff --git a/chart/templates/serviceaccount-operator-builder.yaml b/chart/templates/serviceaccount-builder.yaml similarity index 100% rename from chart/templates/serviceaccount-operator-builder.yaml rename to chart/templates/serviceaccount-builder.yaml diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 728eecd..879d81d 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -50,6 +50,9 @@ rules: verbs: - create - get + - list + - update + - watch - apiGroups: - batch resources: diff --git a/hack/helm-generator/main.go b/hack/helm-generator/main.go index a30b296..772db23 100644 --- a/hack/helm-generator/main.go +++ b/hack/helm-generator/main.go @@ -88,6 +88,11 @@ func main() { fmt.Fprintf(os.Stderr, "Warning: Could not add env vars to deployment: %v\n", err) } + // Add builder ServiceAccount template (conditional on build.serviceAccount) + if err := addBuilderServiceAccount(templatesDir); err != nil { + fmt.Fprintf(os.Stderr, "Warning: Could not add builder service account: %v\n", err) + } + fmt.Printf("✓ Generated %d Helm templates\n\n", fileCount) fmt.Println("Test with:") fmt.Println(" make helm-lint") @@ -279,3 +284,19 @@ func addEnvVarsToDeployment(templatesDir string) error { return os.WriteFile(deploymentFile, []byte(contentStr), 0644) } + +func addBuilderServiceAccount(templatesDir string) error { + content := `{{- if .Values.build.serviceAccount }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.build.serviceAccount }} + namespace: {{ .Release.Namespace }} + {{- if .Values.build.roleArn }} + annotations: + eks.amazonaws.com/role-arn: {{ .Values.build.roleArn | quote }} + {{- end }} +{{- end }} +` + return os.WriteFile(filepath.Join(templatesDir, "serviceaccount-builder.yaml"), []byte(content), 0644) +} From fad341a0533a63fd6f27e5a16080fe12bcb53318 Mon Sep 17 00:00:00 2001 From: igoramf Date: Thu, 7 May 2026 23:43:38 -0300 Subject: [PATCH 3/4] revert: restore CRDs to CI controller-gen version (v0.18.0) --- .../customresourcedefinition-decofiles.deco.sites.yaml | 2 +- chart/templates/customresourcedefinition-decos.deco.sites.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml b/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml index 7d17a2d..1e6f7d1 100644 --- a/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml +++ b/chart/templates/customresourcedefinition-decofiles.deco.sites.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.21.0 + controller-gen.kubebuilder.io/version: v0.18.0 name: decofiles.deco.sites spec: group: deco.sites diff --git a/chart/templates/customresourcedefinition-decos.deco.sites.yaml b/chart/templates/customresourcedefinition-decos.deco.sites.yaml index a2c332e..e6e2265 100644 --- a/chart/templates/customresourcedefinition-decos.deco.sites.yaml +++ b/chart/templates/customresourcedefinition-decos.deco.sites.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.21.0 + controller-gen.kubebuilder.io/version: v0.18.0 name: decos.deco.sites spec: group: deco.sites From a67717b4aa726ffd9ae4e57a841c247394bb8123 Mon Sep 17 00:00:00 2001 From: igoramf Date: Thu, 7 May 2026 23:48:50 -0300 Subject: [PATCH 4/4] fix(lint): remove trailing blank line left by ensureServiceAccount extraction (gofmt) --- internal/controller/deco_controller.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/controller/deco_controller.go b/internal/controller/deco_controller.go index 7498a7d..7a825fa 100644 --- a/internal/controller/deco_controller.go +++ b/internal/controller/deco_controller.go @@ -267,7 +267,6 @@ func (r *DecoReconciler) createJob(ctx context.Context, deco *decositesv1alpha1. return nil } - func buildPhaseFromJob(job *batchv1.Job) string { for _, c := range job.Status.Conditions { if c.Status != corev1.ConditionTrue {