From 6d0ed0cea9942b74ea1bbb62e206f054af62d36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20B=C4=9Bh=C3=A1vka?= Date: Tue, 25 Aug 2026 18:06:44 +0200 Subject: [PATCH 1/4] feat: Issue #222: allow custom annotations on deployment and apiservice --- deploy/stackit/README.md | 8 +++++++- deploy/stackit/templates/apiservice.yaml | 5 ++++- deploy/stackit/templates/deployment.yaml | 8 ++++++++ deploy/stackit/values.yaml | 17 ++++++++++++++--- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/deploy/stackit/README.md b/deploy/stackit/README.md index 27b3815e..20c72cc2 100644 --- a/deploy/stackit/README.md +++ b/deploy/stackit/README.md @@ -1,6 +1,6 @@ # stackit-cert-manager-webhook -![Version: 0.4.1](https://img.shields.io/badge/Version-0.4.1-informational?style=flat-square) ![AppVersion: v0.4.1](https://img.shields.io/badge/AppVersion-v0.4.1-informational?style=flat-square) +![Version: 0.4.11](https://img.shields.io/badge/Version-0.4.11-informational?style=flat-square) ![AppVersion: v0.4.11](https://img.shields.io/badge/AppVersion-v0.4.11-informational?style=flat-square) A Helm chart for stackitcloud/stackit-cert-manager-webhook @@ -11,6 +11,9 @@ A Helm chart for stackitcloud/stackit-cert-manager-webhook | additionalVolumeMounts | list | `[]` | | | additionalVolumes | list | `[]` | | | affinity | object | `{}` | | +| annotations | object | `{}` | Deployment-level annotations. | +| apiService | object | `{"annotations":{}}` | Configuration for the APIService. | +| apiService.annotations | object | `{}` | APIService annotations. | | certManager | object | `{"namespace":"cert-manager","serviceAccountName":"cert-manager"}` | Meta information of the cert-manager itself. | | certManager.namespace | string | `"cert-manager"` | namespace where the webhook should be installed. Cert-Manager and the webhook should be in the same namespace. | | certManager.serviceAccountName | string | `"cert-manager"` | service account name for the cert-manager. | @@ -23,6 +26,7 @@ A Helm chart for stackitcloud/stackit-cert-manager-webhook | imagePullSecrets | list | `[]` | | | nameOverride | string | `""` | Webhook configuration. | | nodeSelector | object | `{}` | Node selector for the webhook. | +| podAnnotations | object | `{}` | Pod-level annotations. | | podSecurityContext.runAsGroup | int | `1000` | | | podSecurityContext.runAsNonRoot | bool | `true` | | | podSecurityContext.runAsUser | int | `1000` | | @@ -35,6 +39,8 @@ A Helm chart for stackitcloud/stackit-cert-manager-webhook | service | object | `{"port":443,"type":"ClusterIP"}` | Configuration for the webhook service. | | service.port | int | `443` | port of the service. | | service.type | string | `"ClusterIP"` | type of the service. | +| serviceAccount | object | `{"annotations":{}}` | Service Account | +| serviceAccount.annotations | object | `{}` | service account annotations. | | stackitSaAuthentication | object | `{"enabled":false,"fileName":"sa.json","mountPath":"/var/run/secrets/stackit","secretName":"stackit-sa-authentication"}` | Configuration for the stackit service account keys. | | stackitSaAuthentication.enabled | bool | `false` | enabled flag for the stackit service account keys. | | stackitSaAuthentication.fileName | string | `"sa.json"` | key of the service account key in the secret. Which will be later be used to load in keys in the pod as well. | diff --git a/deploy/stackit/templates/apiservice.yaml b/deploy/stackit/templates/apiservice.yaml index 52fd63ce..643ba1a3 100644 --- a/deploy/stackit/templates/apiservice.yaml +++ b/deploy/stackit/templates/apiservice.yaml @@ -9,6 +9,9 @@ metadata: heritage: {{ .Release.Service }} annotations: cert-manager.io/inject-ca-from: "{{ .Release.Namespace }}/{{ include "stackit-cert-manager-webhook.servingCertificate" . }}" + {{- with .Values.apiService.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: group: {{ .Values.groupName }} groupPriorityMinimum: 1000 @@ -16,4 +19,4 @@ spec: service: name: {{ include "stackit-cert-manager-webhook.fullname" . }} namespace: {{ .Release.Namespace }} - version: v1alpha1 + version: v1alpha1 \ No newline at end of file diff --git a/deploy/stackit/templates/deployment.yaml b/deploy/stackit/templates/deployment.yaml index 925e216e..eefdfee2 100644 --- a/deploy/stackit/templates/deployment.yaml +++ b/deploy/stackit/templates/deployment.yaml @@ -8,6 +8,10 @@ metadata: chart: {{ include "stackit-cert-manager-webhook.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- with .Values.annotations }} + annotations: +{{ toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.replicaCount }} selector: @@ -19,6 +23,10 @@ spec: labels: app: {{ include "stackit-cert-manager-webhook.name" . }} release: {{ .Release.Name }} + {{- with .Values.podAnnotations }} + annotations: +{{ toYaml . | nindent 8 }} + {{- end }} spec: serviceAccountName: {{ include "stackit-cert-manager-webhook.fullname" . }} containers: diff --git a/deploy/stackit/values.yaml b/deploy/stackit/values.yaml index 15b2312b..f022613e 100644 --- a/deploy/stackit/values.yaml +++ b/deploy/stackit/values.yaml @@ -12,6 +12,12 @@ groupName: acme.stackit.de # -- Replicas for the webhook. Since it is a stateless application server that sends requests you can increase the number as you want. Most of the time however, 1 replica is enough. replicaCount: 1 +# -- Deployment-level annotations. +annotations: {} + +# -- Pod-level annotations. +podAnnotations: {} + # -- Meta information of the cert-manager itself. certManager: # -- namespace where the webhook should be installed. Cert-Manager and the webhook should be in the same namespace. @@ -19,11 +25,11 @@ certManager: # -- service account name for the cert-manager. serviceAccountName: cert-manager -# -- Service Account +# -- Service Account serviceAccount: # -- service account annotations. annotations: {} - + # -- Image information for the webhook. image: # -- repository of the image. @@ -58,6 +64,11 @@ service: # -- port of the service. port: 443 +# -- Configuration for the APIService. +apiService: + # -- APIService annotations. + annotations: {} + # -- Kubernetes resources for the webhook. Usually limits.cpu=100m, limits.memory=128Mi, requests.cpu=100m, requests.memory=128Mi is enough for the webhook. resources: {} @@ -104,7 +115,7 @@ additionalVolumeMounts: [] # mountPath: /etc/extra-config # readOnly: true -# -- Placeholder for additional env-variables. Apply via "--set"-command or +# -- Placeholder for additional env-variables. Apply via "--set"-command or # -- delete the next line and add your variables as in the commented example below. extraEnv: [] # extraEnv: From 8a250d19c496d4c19084204e0aa5823268d6f0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20B=C4=9Bh=C3=A1vka?= Date: Tue, 25 Aug 2026 18:10:19 +0200 Subject: [PATCH 2/4] feat: Issue #223: Lower default acme TTL --- README.md | 2 +- internal/resolver/config.go | 2 +- internal/resolver/config_test.go | 2 +- internal/resolver/resolver_test.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d10a1ffe..55992165 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ spec: - apiBasePath: The base path for the STACKIT DNS API. (Default: https://dns.api.stackit.cloud) - serviceAccountKeyPath: The path to the service account key file. The file must be mounted into the container. - serviceAccountBaseUrl: The base URL for the STACKIT service account API. (Default: https://service-account.api.stackit.cloud/token) -- acmeTxtRecordTTL: The TTL for the ACME TXT record. (Default: 600) +- acmeTxtRecordTTL: The TTL for the ACME TXT record. (Default: 60) ## Test Procedures diff --git a/internal/resolver/config.go b/internal/resolver/config.go index 9965fbf6..cf6e1c49 100644 --- a/internal/resolver/config.go +++ b/internal/resolver/config.go @@ -82,7 +82,7 @@ func setDefaultValues(cfg *StackitDnsProviderConfig) { cfg.AuthTokenSecretKey = "auth-token" } if cfg.AcmeTxtRecordTTL == 0 { - cfg.AcmeTxtRecordTTL = 600 + cfg.AcmeTxtRecordTTL = 60 } } diff --git a/internal/resolver/config_test.go b/internal/resolver/config_test.go index a940b9b2..28831d44 100644 --- a/internal/resolver/config_test.go +++ b/internal/resolver/config_test.go @@ -77,7 +77,7 @@ func TestLoadConfig(t *testing.T) { require.Equal(t, "https://dns.api.stackit.cloud", cfg.ApiBasePath) require.Equal(t, "stackit-cert-manager-webhook", cfg.AuthTokenSecretRef) require.Equal(t, "auth-token", cfg.AuthTokenSecretKey) - require.Equal(t, int32(600), cfg.AcmeTxtRecordTTL) + require.Equal(t, int32(60), cfg.AcmeTxtRecordTTL) }) t.Run("custom service account base url", func(t *testing.T) { diff --git a/internal/resolver/resolver_test.go b/internal/resolver/resolver_test.go index a9667632..0f9de107 100644 --- a/internal/resolver/resolver_test.go +++ b/internal/resolver/resolver_test.go @@ -429,7 +429,7 @@ func (s *presentSuite) TestFailUpdateRRSet() { } func (s *presentSuite) TestTTLPropagation() { - ttl := int32(600) + ttl := int32(60) // Test Create s.mockConfigProvider.EXPECT(). LoadConfig(gomock.Any()). From 28e6028a6c3883d875ee4b365fe9e60bb6d34d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20B=C4=9Bh=C3=A1vka?= Date: Tue, 25 Aug 2026 18:16:21 +0000 Subject: [PATCH 3/4] fix: remove ActiveEq filter to allow clean up of pending DNS records --- internal/repository/rrset_repository.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/repository/rrset_repository.go b/internal/repository/rrset_repository.go index b0f89440..a2aacb36 100644 --- a/internal/repository/rrset_repository.go +++ b/internal/repository/rrset_repository.go @@ -64,18 +64,21 @@ func (r *rrSetRepository) FetchRRSetForZone( var pager int32 = 1 listRequest := r.apiClient.DefaultAPI.ListRecordSets(ctx, r.projectId, r.zoneId). Page(pager).PageSize(10000). - ActiveEq(true).NameEq(rrSetName).TypeEq(stackitdnsclient.ListRecordSetsTypeEqParameter(rrSetType)) + NameEq(rrSetName).TypeEq(stackitdnsclient.ListRecordSetsTypeEqParameter(rrSetType)) rrSetResponse, err := listRequest.Execute() if err != nil { return nil, err } - if len(rrSetResponse.RrSets) == 0 { - return nil, ErrRRSetNotFound + for i := range rrSetResponse.RrSets { + state := rrSetResponse.RrSets[i].State + if state != stackitdnsclient.RECORDSETSTATE_DELETE_SUCCEEDED && state != stackitdnsclient.RECORDSETSTATE_DELETING { + return &rrSetResponse.RrSets[i], nil + } } - return &rrSetResponse.RrSets[0], nil + return nil, ErrRRSetNotFound } func (r *rrSetRepository) CreateRRSet( From 5d391820112f4d3e21d310b055fcf51cc3fcebb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20B=C4=9Bh=C3=A1vka?= Date: Tue, 25 Aug 2026 19:16:22 +0000 Subject: [PATCH 4/4] fix: add filtering out of deleted rrsets on API side --- internal/repository/rrset_repository.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/repository/rrset_repository.go b/internal/repository/rrset_repository.go index a2aacb36..007a262e 100644 --- a/internal/repository/rrset_repository.go +++ b/internal/repository/rrset_repository.go @@ -64,7 +64,9 @@ func (r *rrSetRepository) FetchRRSetForZone( var pager int32 = 1 listRequest := r.apiClient.DefaultAPI.ListRecordSets(ctx, r.projectId, r.zoneId). Page(pager).PageSize(10000). - NameEq(rrSetName).TypeEq(stackitdnsclient.ListRecordSetsTypeEqParameter(rrSetType)) + NameEq(rrSetName). + TypeEq(stackitdnsclient.ListRecordSetsTypeEqParameter(rrSetType)). + StateNeq(stackitdnsclient.LISTRECORDSETSSTATENEQPARAMETER_DELETE_SUCCEEDED) rrSetResponse, err := listRequest.Execute() if err != nil {