Repository: kubernetes-sigs/external-dns

Issue:
Port is not allowed to be int anymore
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks!

-->

**What happened**:
Helm chart 1.16.1 broke compatibility with older values as before we could use integers as port values for readiness and liveness probes

**What you expected to happen**:

Port: 8888 is valid in liveness or readiness probe config

**How to reproduce it (as minimally and precisely as possible)**:

Set port as int instead of string (which is valid in kubernetes) 

**Anything else we need to know?**:

**Environment**:

- External-DNS version (use `external-dns --version`): N.A.N.
- DNS provider: Infoblox
- Others:


Discussion:
@stevehipwell: @semnell out of interest why are you using the port number instead of the name?@semnell: We're uing a custom provider using webhook and it uses a non standard port. We used to be able to just define the port but now we're unable to do so after te validation was added.

@stevehipwell: @semnell do you mean the probes on the webhook rather than the controller (default container)? If so could you update the issue and PR to make this clear?

Solution patch:
diff --git a/charts/external-dns/CHANGELOG.md b/charts/external-dns/CHANGELOG.md
index f21a35f7..a08aa175 100644
--- a/charts/external-dns/CHANGELOG.md
+++ b/charts/external-dns/CHANGELOG.md
@@ -18,6 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [UNRELEASED]
 
+### Fixed
+
+- Fixed wrong type definitions for webhook probes. ([#5297](https://github.com/kubernetes-sigs/external-dns/pull/5297)) _@semnell_
+
 ## [v1.16.1] - 2025-04-10
 
 ### Changed
diff --git a/charts/external-dns/values.schema.json b/charts/external-dns/values.schema.json
index d5e64143..bbd36ada 100644
--- a/charts/external-dns/values.schema.json
+++ b/charts/external-dns/values.schema.json
@@ -308,30 +308,51 @@
             "livenessProbe": {
               "properties": {
                 "failureThreshold": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "httpGet": {
                   "properties": {
                     "path": {
-                      "type": "string"
+                      "type": [
+                        "string",
+                        "null"
+                      ]
                     },
                     "port": {
-                      "type": "string"
+                      "type": [
+                        "integer",
+                        "string"
+                      ]
                     }
                   },
                   "type": "object"
                 },
                 "initialDelaySeconds": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "periodSeconds": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "successThreshold": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "timeoutSeconds": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 }
               },
               "type": "object"
@@ -339,30 +360,51 @@
             "readinessProbe": {
               "properties": {
                 "failureThreshold": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "httpGet": {
                   "properties": {
                     "path": {
-                      "type": "string"
+                      "type": [
+                        "string",
+                        "null"
+                      ]
                     },
                     "port": {
-                      "type": "string"
+                      "type": [
+                        "integer",
+                        "string"
+                      ]
                     }
                   },
                   "type": "object"
                 },
                 "initialDelaySeconds": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "periodSeconds": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "successThreshold": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 },
                 "timeoutSeconds": {
-                  "type": "integer"
+                  "type": [
+                    "integer",
+                    "null"
+                  ]
                 }
               },
               "type": "object"
diff --git a/charts/external-dns/values.yaml b/charts/external-dns/values.yaml
index c1acf0c4..c1d9be87 100644
--- a/charts/external-dns/values.yaml
+++ b/charts/external-dns/values.yaml
@@ -263,24 +263,24 @@ provider:  # @schema type: [object, string];
     # @default -- See _values.yaml_
     livenessProbe:
       httpGet:
-        path: /healthz
-        port: http-webhook
-      initialDelaySeconds: 10
-      periodSeconds: 10
-      timeoutSeconds: 5
-      failureThreshold: 2
-      successThreshold: 1
+        path: /healthz  # @schema type:[string, null]; default: null
+        port: http-webhook  # @schema type:[integer,string]; default: string
+      initialDelaySeconds: 10  # @schema type:[integer, null]; default: null
+      periodSeconds: 10  # @schema type:[integer, null]; default: null
+      timeoutSeconds: 5  # @schema type:[integer, null]; default: null
+      failureThreshold: 2  # @schema type:[integer, null]; default: null
+      successThreshold: 1  # @schema type:[integer, null]; default: null
     # -- [Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `webhook` container.
     # @default -- See _values.yaml_
     readinessProbe:
       httpGet:
-        path: /healthz
-        port: http-webhook
-      initialDelaySeconds: 5
-      periodSeconds: 10
-      timeoutSeconds: 5
-      failureThreshold: 6
-      successThreshold: 1
+        path: /healthz  # @schema type:[string, null]; default: null
+        port: http-webhook  # @schema type:[integer,string]; default: string
+      initialDelaySeconds: 5  # @schema type:[integer, null]; default: null
+      periodSeconds: 10  # @schema type:[integer, null]; default: null
+      timeoutSeconds: 5  # @schema type:[integer, null]; default: null
+      failureThreshold: 6  # @schema type:[integer, null]; default: null
+      successThreshold: 1  # @schema type:[integer, null]; default: null
     service:
       # -- Webhook exposed HTTP port for the service.
       port: 8080



Test patch:
diff --git a/charts/external-dns/tests/json-schema_test.yaml b/charts/external-dns/tests/json-schema_test.yaml
index 694e59d5..68b9b6ba 100644
--- a/charts/external-dns/tests/json-schema_test.yaml
+++ b/charts/external-dns/tests/json-schema_test.yaml
@@ -50,3 +50,15 @@ tests:
       labelFilter: "mydomain.io/enable-dns-record in (true)"
     asserts:
       - notFailedTemplate: {}
+
+  - it: should not fail when livenessProbe is null
+    set:
+      livenessProbe: null
+    asserts:
+      - notFailedTemplate: {}
+
+  - it: should not fail when readinessProbe is null
+    set:
+      readinessProbe: null
+    asserts:
+      - notFailedTemplate: {}