From 0f36f8923a0b3ef363759a6adb59a2c63015e028 Mon Sep 17 00:00:00 2001 From: Kjeld Schouten Date: Wed, 16 Apr 2025 15:55:11 +0200 Subject: [PATCH] feat(common): move metallb/traefik service annotations to integrations (#33905) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Description** Currently annotations for services are set by global keys. We want to move away from that and streamline setup just like is done with ingress: using "integrations" that can be toggled per service and per integration. Its breaking as its now disabled by default AND the global keys have been removed. ⚒️ Fixes #28997 Fixes #33211 **⚙️ Type of change** - [x] ⚙️ Feature/App addition - [ ] 🪛 Bugfix - [x] ⚠️ Breaking change (fix or feature that would cause existing functionality to not work as expected) - [x] 🔃 Refactor of current code - [ ] 📜 Documentation Changes **🧪 How Has This Been Tested?** **📃 Notes:** Also adds cilium loadbalancer support as an integration in sililair style as metallb, allowing for easy lb switching by users **✔️ Checklist:** - [ ] ⚖️ My code follows the style guidelines of this project - [ ] 👀 I have performed a self-review of my own code - [ ] #️⃣ I have commented my code, particularly in hard-to-understand areas - [ ] 📄 I have made changes to the documentation - [ ] 🧪 I have added tests to this description that prove my fix is effective or that my feature works - [ ] ⬆️ I increased versions for any altered app according to semantic versioning - [ ] I made sure the title starts with `feat(chart-name):`, `fix(chart-name):`, `chore(chart-name):`, `docs(chart-name):` or `fix(docs):` **➕ App addition** If this PR is an app addition please make sure you have done the following. - [ ] 🖼️ I have added an icon in the Chart's root directory called `icon.png` --- _Please don't blindly check all the boxes. Read them and only check those that apply. Those checkboxes are there for the reviewer to see what is this all about and the status of this PR with a quick glance._ --------- Signed-off-by: Kjeld Schouten Signed-off-by: Alfred Göppel <43101280+alfi0812@users.noreply.github.com> Co-authored-by: Stavros Kois Co-authored-by: Stavros Kois <47820033+stavros-k@users.noreply.github.com> Co-authored-by: Alfred Göppel <43101280+alfi0812@users.noreply.github.com> --- .github/workflows/common-tests.yaml | 2 +- charts/library/common-test/Chart.yaml | 1 - .../tests/addons/autoperms_test.yaml | 14 +- .../tests/addons/codeserver_test.yaml | 24 +-- .../tests/addons/gluetun_test.yaml | 16 +- .../tests/addons/netshoot_test.yaml | 16 +- .../tests/addons/tailscale_test.yaml | 32 ++-- .../cnpg/cluster_recovery_spec_test.yaml | 8 +- .../tests/cnpg/cluster_spec_test.yaml | 16 +- .../tests/container/resources_test.yaml | 110 ++++++------- .../tests/container/volumeMounts_test.yaml | 8 +- .../tests/defaults/defaults-test.yaml | 8 +- .../tests/pod/volume_emptyDIr_test.yaml | 2 +- .../service/cilium_integration_test.yaml | 152 ++++++++++++++++++ .../tests/service/external_ip_test.yaml | 13 +- .../tests/service/load_balancer_test.yaml | 9 +- .../tests/service/metadata_test.yaml | 36 ++--- .../service/metallb_integration_test.yaml | 152 ++++++++++++++++++ charts/library/common-test/values.yaml | 1 - .../common/templates/class/_service.tpl | 20 ++- .../lib/service/_additionalAnnotations.tpl | 77 --------- .../lib/service/integrations/_cilium.tpl | 33 ++++ .../lib/service/integrations/_metallb.tpl | 38 +++++ .../lib/service/integrations/_traefik.tpl | 12 ++ .../lib/service/integrations/_validation.tpl | 25 +++ charts/library/common/values.yaml | 19 ++- 26 files changed, 592 insertions(+), 252 deletions(-) create mode 100644 charts/library/common-test/tests/service/cilium_integration_test.yaml create mode 100644 charts/library/common-test/tests/service/metallb_integration_test.yaml delete mode 100644 charts/library/common/templates/lib/service/_additionalAnnotations.tpl create mode 100644 charts/library/common/templates/lib/service/integrations/_cilium.tpl create mode 100644 charts/library/common/templates/lib/service/integrations/_metallb.tpl create mode 100644 charts/library/common/templates/lib/service/integrations/_traefik.tpl create mode 100644 charts/library/common/templates/lib/service/integrations/_validation.tpl diff --git a/.github/workflows/common-tests.yaml b/.github/workflows/common-tests.yaml index ef838f8f669..b4b8c9cb3c3 100644 --- a/.github/workflows/common-tests.yaml +++ b/.github/workflows/common-tests.yaml @@ -81,7 +81,7 @@ jobs: name: Unit Tests runs-on: ubuntu-24.04 env: - helmUnitVersion: 0.7.1 + helmUnitVersion: 0.8.1 strategy: fail-fast: false matrix: diff --git a/charts/library/common-test/Chart.yaml b/charts/library/common-test/Chart.yaml index dc852063acd..0c72d74cb6a 100644 --- a/charts/library/common-test/Chart.yaml +++ b/charts/library/common-test/Chart.yaml @@ -35,4 +35,3 @@ sources: - https://github.com/truecharts/charts/tree/master/charts/library/common-test type: application version: 1.0.0 - diff --git a/charts/library/common-test/tests/addons/autoperms_test.yaml b/charts/library/common-test/tests/addons/autoperms_test.yaml index 620e596ced3..658df96e957 100644 --- a/charts/library/common-test/tests/addons/autoperms_test.yaml +++ b/charts/library/common-test/tests/addons/autoperms_test.yaml @@ -176,7 +176,7 @@ tests: name: tmp emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - documentIndex: *jobDoc contains: path: spec.template.spec.containers[0].volumeMounts @@ -367,19 +367,19 @@ tests: path: spec.template.spec.containers[0].resources value: requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 - documentIndex: *jobDoc equal: path: spec.template.spec.containers[0].resources value: requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi limits: cpu: 2000m memory: 2Gi diff --git a/charts/library/common-test/tests/addons/codeserver_test.yaml b/charts/library/common-test/tests/addons/codeserver_test.yaml index d642542647a..b5aa98c7fe2 100644 --- a/charts/library/common-test/tests/addons/codeserver_test.yaml +++ b/charts/library/common-test/tests/addons/codeserver_test.yaml @@ -99,11 +99,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument equal: path: spec.template.spec.containers[1].name @@ -114,12 +114,12 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *AddonServiceDocument equal: path: metadata.name @@ -358,11 +358,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should fail if more than 1 workload selected set: diff --git a/charts/library/common-test/tests/addons/gluetun_test.yaml b/charts/library/common-test/tests/addons/gluetun_test.yaml index 8a2f68ccd39..6b4dede7cca 100644 --- a/charts/library/common-test/tests/addons/gluetun_test.yaml +++ b/charts/library/common-test/tests/addons/gluetun_test.yaml @@ -89,12 +89,12 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument equal: path: spec.template.spec.containers[1].name @@ -105,11 +105,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *ServiceDocument equal: path: metadata.name diff --git a/charts/library/common-test/tests/addons/netshoot_test.yaml b/charts/library/common-test/tests/addons/netshoot_test.yaml index c2df2c686a7..529731eaa61 100644 --- a/charts/library/common-test/tests/addons/netshoot_test.yaml +++ b/charts/library/common-test/tests/addons/netshoot_test.yaml @@ -55,12 +55,12 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument equal: path: spec.template.spec.containers[1].name @@ -71,11 +71,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *ServiceDocument equal: path: metadata.name diff --git a/charts/library/common-test/tests/addons/tailscale_test.yaml b/charts/library/common-test/tests/addons/tailscale_test.yaml index c1b95335768..14c0d5d9855 100644 --- a/charts/library/common-test/tests/addons/tailscale_test.yaml +++ b/charts/library/common-test/tests/addons/tailscale_test.yaml @@ -67,12 +67,12 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument equal: path: spec.template.spec.containers[1].name @@ -83,11 +83,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument contains: path: spec.template.spec.containers[1].env @@ -174,12 +174,12 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument equal: path: spec.template.spec.containers[1].name @@ -190,11 +190,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *DeploymentDocument contains: path: spec.template.spec.containers[1].env diff --git a/charts/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml b/charts/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml index 4acbce836f5..2d4655d6ffc 100644 --- a/charts/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml +++ b/charts/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml @@ -49,11 +49,11 @@ tests: inProgress: false resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi storage: pvcTemplate: accessModes: diff --git a/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml b/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml index d633c04242c..03be1a7ac8f 100644 --- a/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml +++ b/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml @@ -45,11 +45,11 @@ tests: inProgress: false resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi storage: pvcTemplate: accessModes: @@ -114,11 +114,11 @@ tests: inProgress: false resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi storage: pvcTemplate: accessModes: diff --git a/charts/library/common-test/tests/container/resources_test.yaml b/charts/library/common-test/tests/container/resources_test.yaml index cdf415e70ec..1fb13631492 100644 --- a/charts/library/common-test/tests/container/resources_test.yaml +++ b/charts/library/common-test/tests/container/resources_test.yaml @@ -42,11 +42,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should override the default limits set: @@ -89,8 +89,8 @@ tests: nvidia.com/gpu: 1 some-resource: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should override the default limits from top level set: @@ -134,8 +134,8 @@ tests: memory: 4Gi some-other-resource: 2 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should override the default limits.cpu set: @@ -169,10 +169,10 @@ tests: resources: limits: cpu: 2000m - memory: 8Gi + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should override the default limits.memory set: @@ -205,11 +205,11 @@ tests: content: resources: limits: - cpu: 4000m + cpu: 1000m memory: 4Gi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should not render limits.cpu set: @@ -242,10 +242,10 @@ tests: content: resources: limits: - memory: 8Gi + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should not render limits.memory set: @@ -278,10 +278,10 @@ tests: content: resources: limits: - cpu: 4000m + cpu: 1000m requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - it: should override the default requests set: @@ -315,8 +315,8 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: cpu: 200m memory: 1Gi @@ -352,11 +352,11 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: cpu: 200m - memory: 50Mi + memory: 250Mi - it: should override the default requests.memory set: @@ -389,10 +389,10 @@ tests: content: resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m + cpu: 100m memory: 1Gi - it: should not add extra resources on "wait" containers and on excluded containers @@ -451,11 +451,11 @@ tests: path: spec.resources value: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: &deploymentDoc 8 isKind: of: Deployment @@ -469,12 +469,12 @@ tests: name: test-release-name-common-test resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi nvidia.com/gpu: 1 requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *deploymentDoc isSubset: path: spec.template.spec.containers[1] @@ -482,11 +482,11 @@ tests: name: test-release-name-common-test-my-container resources: limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi - documentIndex: *deploymentDoc isSubset: path: spec.template.spec.initContainers[0] @@ -609,7 +609,7 @@ tests: image: *image resources: requests: - cpu: 10m + cpu: 100m memory: "" workload: workload-name1: @@ -632,8 +632,8 @@ tests: image: *image resources: requests: - cpu: 10MB - memory: 50Mi + cpu: 100MB + memory: 250Mi workload: workload-name1: enabled: true @@ -648,18 +648,18 @@ tests: probes: *probes asserts: - failedTemplate: - errorMessage: Container - Expected [resources.requests.cpu] to have one of the following formats [(Plain Integer - eg. 1), (Float - eg. 0.5), (Milicpu - eg. 500m)], but got [10MB] + errorMessage: Container - Expected [resources.requests.cpu] to have one of the following formats [(Plain Integer - eg. 1), (Float - eg. 0.5), (Milicpu - eg. 500m)], but got [100MB] - it: should fail with invalid format in limits.cpu set: image: *image resources: requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi limits: - cpu: 10MB - memory: 8Gi + cpu: 100MB + memory: 1500Mi workload: workload-name1: enabled: true @@ -674,18 +674,18 @@ tests: probes: *probes asserts: - failedTemplate: - errorMessage: Container - Expected [resources.limits.cpu] to have one of the following formats [(Plain Integer - eg. 1), (Float - eg. 0.5), (Milicpu - eg. 500m)], but got [10MB] + errorMessage: Container - Expected [resources.limits.cpu] to have one of the following formats [(Plain Integer - eg. 1), (Float - eg. 0.5), (Milicpu - eg. 500m)], but got [100MB] - it: should fail with invalid format in requests.memory set: image: *image resources: requests: - cpu: 10m + cpu: 100m memory: 50MB limits: - cpu: 4000m - memory: 8Gi + cpu: 1000m + memory: 1500Mi workload: workload-name1: enabled: true @@ -707,10 +707,10 @@ tests: image: *image resources: requests: - cpu: 10m - memory: 50Mi + cpu: 100m + memory: 250Mi limits: - cpu: 4000m + cpu: 1000m memory: 8GB workload: workload-name1: diff --git a/charts/library/common-test/tests/container/volumeMounts_test.yaml b/charts/library/common-test/tests/container/volumeMounts_test.yaml index 524bdb41537..ef2af5b6c38 100644 --- a/charts/library/common-test/tests/container/volumeMounts_test.yaml +++ b/charts/library/common-test/tests/container/volumeMounts_test.yaml @@ -670,21 +670,21 @@ tests: - name: devshm emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - name: shared emptyDir: {} - name: tmp emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - name: varlogs emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - name: varrun emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - documentIndex: *deploymentDoc equal: diff --git a/charts/library/common-test/tests/defaults/defaults-test.yaml b/charts/library/common-test/tests/defaults/defaults-test.yaml index 28b097fdaf2..f280233404b 100644 --- a/charts/library/common-test/tests/defaults/defaults-test.yaml +++ b/charts/library/common-test/tests/defaults/defaults-test.yaml @@ -90,21 +90,21 @@ tests: - name: devshm emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - name: shared emptyDir: {} - name: tmp emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - name: varlogs emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - name: varrun emptyDir: medium: Memory - sizeLimit: 8Gi + sizeLimit: 1500Mi - documentIndex: *deploymentDoc isSubset: path: spec.template.spec.containers[0] diff --git a/charts/library/common-test/tests/pod/volume_emptyDIr_test.yaml b/charts/library/common-test/tests/pod/volume_emptyDIr_test.yaml index 83d5d66a6b0..3e91bfdcf93 100644 --- a/charts/library/common-test/tests/pod/volume_emptyDIr_test.yaml +++ b/charts/library/common-test/tests/pod/volume_emptyDIr_test.yaml @@ -81,7 +81,7 @@ tests: name: emptyDir-vol emptyDir: medium: Memory - sizeLimit: 2Gi + sizeLimit: 1500Mi - it: should pass with emptyDir volume with size set set: diff --git a/charts/library/common-test/tests/service/cilium_integration_test.yaml b/charts/library/common-test/tests/service/cilium_integration_test.yaml new file mode 100644 index 00000000000..8c20196737b --- /dev/null +++ b/charts/library/common-test/tests/service/cilium_integration_test.yaml @@ -0,0 +1,152 @@ +suite: service loadBalancer (cilium integration) test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with type LoadBalancer and cilium integration enabled + set: + service: + my-service: + enabled: true + primary: true + type: LoadBalancer + loadBalancerIPs: + - 1.2.3.4 + - 5.6.7.8 + integrations: + cilium: + enabled: true + ports: + port-name: + enabled: true + primary: true + port: 12345 + workload: + my-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - documentIndex: &serviceDoc 1 + isKind: + of: Service + - documentIndex: *serviceDoc + isAPIVersion: + of: v1 + - documentIndex: *serviceDoc + equal: + path: metadata.name + value: test-release-name-common-test + - documentIndex: *serviceDoc + equal: + path: spec + value: + type: LoadBalancer + allocateLoadBalancerNodePorts: false + publishNotReadyAddresses: false + ports: + - name: port-name + port: 12345 + protocol: TCP + targetPort: 12345 + selector: + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/name: common-test + pod.name: my-workload + - documentIndex: *serviceDoc + isSubset: + path: metadata.annotations + content: + lbipam.cilium.io/ips: "1.2.3.4,5.6.7.8" + + - it: should pass with type LoadBalancer and cilium integration enabled and sharedKey set + set: + service: + my-service: + enabled: true + primary: true + type: LoadBalancer + loadBalancerIPs: + - 1.2.3.4 + - 5.6.7.8 + integrations: + cilium: + enabled: true + sharedKey: some-key + ports: + port-name: + enabled: true + primary: true + port: 12345 + workload: + my-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - documentIndex: &serviceDoc 1 + isKind: + of: Service + - documentIndex: *serviceDoc + isAPIVersion: + of: v1 + - documentIndex: *serviceDoc + equal: + path: metadata.name + value: test-release-name-common-test + - documentIndex: *serviceDoc + equal: + path: spec + value: + type: LoadBalancer + allocateLoadBalancerNodePorts: false + publishNotReadyAddresses: false + ports: + - name: port-name + port: 12345 + protocol: TCP + targetPort: 12345 + selector: + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/name: common-test + pod.name: my-workload + - documentIndex: *serviceDoc + isSubset: + path: metadata.annotations + content: + lbipam.cilium.io/ips: "1.2.3.4,5.6.7.8" + lbipam.cilium.io/sharing-key: "some-key" + + - it: should fail with both sharedKey set and externalTrafficPolicy set to Local + set: + service: + my-service: + enabled: true + primary: true + type: LoadBalancer + loadBalancerIPs: + - 1.2.3.4 + - 5.6.7.8 + externalTrafficPolicy: Local + integrations: + cilium: + enabled: true + sharedKey: some-key + ports: + port-name: + enabled: true + primary: true + port: 12345 + workload: + my-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Service - [sharedKey], cannot both be used together with [externalTrafficPolicy] set to [Local] diff --git a/charts/library/common-test/tests/service/external_ip_test.yaml b/charts/library/common-test/tests/service/external_ip_test.yaml index 2900fccfbc7..a9e179be610 100644 --- a/charts/library/common-test/tests/service/external_ip_test.yaml +++ b/charts/library/common-test/tests/service/external_ip_test.yaml @@ -162,6 +162,9 @@ tests: type: ExternalIP useSlice: true externalIP: 1.1.1.1 + integrations: + traefik: + enabled: true ports: port-name: enabled: true @@ -201,11 +204,6 @@ tests: - documentIndex: &serviceDoc 0 isKind: of: Service - - documentIndex: *serviceDoc - isSubset: - path: metadata.annotations - content: - traefik.ingress.kubernetes.io/service.serversscheme: https - it: should pass with type ExternalIP and useSlice set to false set: @@ -260,11 +258,6 @@ tests: - documentIndex: &serviceDoc 0 isKind: of: Service - - documentIndex: *serviceDoc - isSubset: - path: metadata.annotations - content: - traefik.ingress.kubernetes.io/service.serversscheme: https - it: should pass with type ExternalIP and useSlice set to false, multiple ports set: diff --git a/charts/library/common-test/tests/service/load_balancer_test.yaml b/charts/library/common-test/tests/service/load_balancer_test.yaml index 14362da9b8c..f6acb8cc8fb 100644 --- a/charts/library/common-test/tests/service/load_balancer_test.yaml +++ b/charts/library/common-test/tests/service/load_balancer_test.yaml @@ -54,10 +54,11 @@ tests: app.kubernetes.io/name: common-test pod.name: my-workload - documentIndex: *serviceDoc - isSubset: - path: metadata.annotations + isNotSubset: + path: metadata content: - metallb.io/loadBalancerIPs: "1.2.3.4,5.6.7.8" + annotations: + metallb.io/loadBalancerIPs: "1.2.3.4,5.6.7.8" - it: should pass with type LoadBalancer and available options set set: @@ -150,7 +151,7 @@ tests: app.kubernetes.io/name: common-test pod.name: my-workload - documentIndex: *serviceDoc - isSubset: + isNotSubset: path: metadata.annotations content: metallb.io/loadBalancerIPs: "10.100.200.45" diff --git a/charts/library/common-test/tests/service/metadata_test.yaml b/charts/library/common-test/tests/service/metadata_test.yaml index 461ad339fdb..24fcfa77247 100644 --- a/charts/library/common-test/tests/service/metadata_test.yaml +++ b/charts/library/common-test/tests/service/metadata_test.yaml @@ -121,19 +121,19 @@ tests: path: metadata.namespace value: test-release-namespace - - it: should pass with service type LoadBalancer, with https port and metallb.addServiceAnnotations/Traefik true + - it: should pass with service type LoadBalancer, with https port and metallb and traefik integrations enabled set: - global: - metallb: - addServiceAnnotations: true - traefik: - addServiceAnnotations: true proto: https service: my-service1: enabled: true primary: true type: LoadBalancer + integrations: + metallb: + enabled: true + traefik: + enabled: true ports: port-name: enabled: true @@ -154,19 +154,19 @@ tests: isSubset: path: metadata.annotations content: - metallb.io/allow-shared-ip: test-release-name-common-test + metallb.io/allow-shared-ip: test-release-namespace traefik.ingress.kubernetes.io/service.serversscheme: https - it: should add metallb shared ip annotation without externalTrafficPolicy set: - global: - metallb: - addServiceAnnotations: true service: my-service1: enabled: true primary: true type: LoadBalancer + integrations: + metallb: + enabled: true ports: port-name: enabled: true @@ -186,19 +186,19 @@ tests: isSubset: path: metadata.annotations content: - metallb.io/allow-shared-ip: test-release-name-common-test + metallb.io/allow-shared-ip: test-release-namespace - it: should add metallb shared ip annotation with externalTrafficPolicy set to Cluster set: - global: - metallb: - addServiceAnnotations: true service: my-service1: enabled: true primary: true type: LoadBalancer externalTrafficPolicy: Cluster + integrations: + metallb: + enabled: true ports: port-name: enabled: true @@ -218,18 +218,18 @@ tests: isSubset: path: metadata.annotations content: - metallb.io/allow-shared-ip: test-release-name-common-test + metallb.io/allow-shared-ip: test-release-namespace - it: should NOT add metallb shared ip annotation with externalTrafficPolicy set to Local set: - global: - metallb: - addServiceAnnotations: true service: my-service1: enabled: true primary: true type: LoadBalancer + integrations: + metallb: + enabled: true externalTrafficPolicy: Local ports: port-name: diff --git a/charts/library/common-test/tests/service/metallb_integration_test.yaml b/charts/library/common-test/tests/service/metallb_integration_test.yaml new file mode 100644 index 00000000000..67fb952951f --- /dev/null +++ b/charts/library/common-test/tests/service/metallb_integration_test.yaml @@ -0,0 +1,152 @@ +suite: service loadBalancer (metallb integration) test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with type LoadBalancer and metallb integration enabled + set: + service: + my-service: + enabled: true + primary: true + type: LoadBalancer + loadBalancerIPs: + - 1.2.3.4 + - 5.6.7.8 + integrations: + metallb: + enabled: true + ports: + port-name: + enabled: true + primary: true + port: 12345 + workload: + my-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - documentIndex: &serviceDoc 1 + isKind: + of: Service + - documentIndex: *serviceDoc + isAPIVersion: + of: v1 + - documentIndex: *serviceDoc + equal: + path: metadata.name + value: test-release-name-common-test + - documentIndex: *serviceDoc + equal: + path: spec + value: + type: LoadBalancer + allocateLoadBalancerNodePorts: false + publishNotReadyAddresses: false + ports: + - name: port-name + port: 12345 + protocol: TCP + targetPort: 12345 + selector: + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/name: common-test + pod.name: my-workload + - documentIndex: *serviceDoc + isSubset: + path: metadata.annotations + content: + metallb.io/loadBalancerIPs: "1.2.3.4,5.6.7.8" + + - it: should pass with type LoadBalancer and metallb integration enabled and sharedKey set + set: + service: + my-service: + enabled: true + primary: true + type: LoadBalancer + loadBalancerIPs: + - 1.2.3.4 + - 5.6.7.8 + integrations: + metallb: + enabled: true + sharedKey: some-key + ports: + port-name: + enabled: true + primary: true + port: 12345 + workload: + my-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - documentIndex: &serviceDoc 1 + isKind: + of: Service + - documentIndex: *serviceDoc + isAPIVersion: + of: v1 + - documentIndex: *serviceDoc + equal: + path: metadata.name + value: test-release-name-common-test + - documentIndex: *serviceDoc + equal: + path: spec + value: + type: LoadBalancer + allocateLoadBalancerNodePorts: false + publishNotReadyAddresses: false + ports: + - name: port-name + port: 12345 + protocol: TCP + targetPort: 12345 + selector: + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/name: common-test + pod.name: my-workload + - documentIndex: *serviceDoc + isSubset: + path: metadata.annotations + content: + metallb.io/loadBalancerIPs: "1.2.3.4,5.6.7.8" + metallb.io/allow-shared-ip: "some-key" + + - it: should fail with both sharedKey set and externalTrafficPolicy set to Local + set: + service: + my-service: + enabled: true + primary: true + type: LoadBalancer + loadBalancerIPs: + - 1.2.3.4 + - 5.6.7.8 + externalTrafficPolicy: Local + integrations: + metallb: + enabled: true + sharedKey: some-key + ports: + port-name: + enabled: true + primary: true + port: 12345 + workload: + my-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + asserts: + - failedTemplate: + errorMessage: Service - [sharedKey], cannot both be used together with [externalTrafficPolicy] set to [Local] diff --git a/charts/library/common-test/values.yaml b/charts/library/common-test/values.yaml index 63ae5ece97d..0a2b76fd24c 100644 --- a/charts/library/common-test/values.yaml +++ b/charts/library/common-test/values.yaml @@ -3,7 +3,6 @@ # by any default values. global: - createTCNamespace: false traefik: commonMiddlewares: [] diff --git a/charts/library/common/templates/class/_service.tpl b/charts/library/common/templates/class/_service.tpl index 91ec6477488..0c08e8de6b4 100644 --- a/charts/library/common/templates/class/_service.tpl +++ b/charts/library/common/templates/class/_service.tpl @@ -12,6 +12,7 @@ objectData: The service data, that will be used to render the Service object. {{- $objectData := .objectData -}} {{- $svcType := $objectData.type | default $rootCtx.Values.global.fallbackDefaults.serviceType -}} + {{- $_ := set $objectData "annotations" ($objectData.annotations | default dict) -}} {{/* Init variables */}} {{- $hasHTTPSPort := false -}} @@ -56,7 +57,16 @@ objectData: The service data, that will be used to render the Service object. {{- if (include "tc.v1.common.lib.util.stopAll" $rootCtx) -}} {{- $svcType = "ClusterIP" -}} {{- end -}} - {{- $_ := set $objectData "type" $svcType }} + {{- $_ := set $objectData "type" $svcType -}} + + {{- if eq $objectData.type "LoadBalancer" -}} + {{- include "tc.v1.common.lib.service.loadbalancer.validate" (dict "objectData" $objectData) -}} + {{- include "tc.v1.common.lib.service.integration.metallb" (dict "rootCtx" $rootCtx "objectData" $objectData) -}} + {{- include "tc.v1.common.lib.service.integration.cilium" (dict "rootCtx" $rootCtx "objectData" $objectData) -}} + {{- end -}} + {{- if $hasHTTPSPort -}} + {{- include "tc.v1.common.lib.service.integration.traefik" (dict "rootCtx" $rootCtx "objectData" $objectData) -}} + {{- end }} --- apiVersion: v1 kind: Service @@ -70,12 +80,6 @@ metadata: {{- . | nindent 4 }} {{- end -}} {{- $annotations := (mustMerge ($objectData.annotations | default dict) (include "tc.v1.common.lib.metadata.allAnnotations" $rootCtx | fromYaml)) -}} - {{- if eq $objectData.type "LoadBalancer" -}} - {{- include "tc.v1.common.lib.service.metalLBAnnotations" (dict "rootCtx" $rootCtx "objectData" $objectData "annotations" $annotations) -}} - {{- end -}} - {{- if $hasHTTPSPort -}} - {{- include "tc.v1.common.lib.service.traefikAnnotations" (dict "rootCtx" $rootCtx "annotations" $annotations) -}} - {{- end -}} {{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }} annotations: {{- . | nindent 4 }} @@ -104,12 +108,12 @@ spec: {{- include "tc.v1.common.lib.metadata.selectorLabels" (dict "rootCtx" $rootCtx "objectType" "pod" "objectName" $podValues.shortName) | trim | nindent 4 -}} {{- end }} {{- end -}} + {{- if eq $objectData.type "ExternalIP" -}} {{- $useSlice := true -}} {{- if kindIs "bool" $objectData.useSlice -}} {{- $useSlice = $objectData.useSlice -}} {{- end -}} - {{- if $useSlice -}} {{- include "tc.v1.common.class.endpointSlice" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 0 }} {{- else -}} diff --git a/charts/library/common/templates/lib/service/_additionalAnnotations.tpl b/charts/library/common/templates/lib/service/_additionalAnnotations.tpl deleted file mode 100644 index 1aa7b8ebb27..00000000000 --- a/charts/library/common/templates/lib/service/_additionalAnnotations.tpl +++ /dev/null @@ -1,77 +0,0 @@ -{{/* Service - MetalLB Annotations */}} -{{/* Call this template: -{{ include "tc.v1.common.lib.service.metalLBAnnotations" (dict "rootCtx" $rootCtx "objectData" $objectData "annotations" $annotations) -}} -rootCtx: The root context of the chart. -objectData: The object data of the service -annotations: The annotations variable reference, to append the MetalLB annotations -*/}} - -{{- define "tc.v1.common.lib.service.metalLBAnnotations" -}} - {{- $rootCtx := .rootCtx -}} - {{- $objectData := .objectData -}} - {{- $annotations := .annotations -}} - - {{- $sharedKey := include "tc.v1.common.lib.chart.names.fullname" $rootCtx -}} - - {{/* A custom shared key can be defined per service even between multiple charts */}} - {{- with $objectData.sharedKey -}} - {{- $sharedKey = tpl . $rootCtx -}} - {{- end -}} - - {{- if (hasKey $rootCtx.Values.global "metallb") -}} - {{- if $rootCtx.Values.global.metallb.addServiceAnnotations -}} - {{/* If externalTrafficPolicy is not set or is not Local, add the shared key as annotation */}} - {{- if ne $objectData.externalTrafficPolicy "Local" -}} - {{- $_ := set $annotations "metallb.io/allow-shared-ip" $sharedKey -}} - {{- end -}} - - {{- if and $objectData.loadBalancerIP $objectData.loadBalancerIPs -}} - {{- fail "Service - Expected one of [loadBalancerIP, loadBalancerIPs] to be defined but got both" -}} - {{- end -}} - - {{- $ips := list -}} - - {{/* Handle loadBalancerIP (single) */}} - {{- if $objectData.loadBalancerIP -}} - {{- if not (kindIs "string" $objectData.loadBalancerIP) -}} - {{- fail (printf "Service - Expected [loadBalancerIP] to be a string, but got [%s]" (kindOf $objectData.loadBalancerIP)) -}} - {{- end -}} - - {{- $ips = mustAppend $ips (tpl $objectData.loadBalancerIP $rootCtx) -}} - {{- end -}} - - {{/* Handle loadBalancerIPs (multiple) */}} - {{- if $objectData.loadBalancerIPs -}} - {{- if not (kindIs "slice" $objectData.loadBalancerIPs) -}} - {{- fail (printf "Service - Expected [loadBalancerIPs] to be a slice, but got [%s]" (kindOf $objectData.loadBalancerIPs)) -}} - {{- end -}} - - {{- range $ip := $objectData.loadBalancerIPs -}} - {{- $ips = mustAppend $ips (tpl $ip $rootCtx) -}} - {{- end -}} - {{- end -}} - - {{- if $ips -}} - {{- $_ := set $annotations "metallb.io/loadBalancerIPs" (join "," $ips) -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- end -}} - -{{/* Service - Traefik Annotations */}} -{{/* Call this template: -{{ include "tc.v1.common.lib.service.traefikAnnotations" (dict "rootCtx" $rootCtx "annotations" $annotations) -}} -rootCtx: The root context of the chart. -annotations: The annotations variable reference, to append the Traefik annotations -*/}} - -{{- define "tc.v1.common.lib.service.traefikAnnotations" -}} - {{- $rootCtx := .rootCtx -}} - {{- $annotations := .annotations -}} - - {{- if (hasKey $rootCtx.Values.global "traefik") -}} - {{- if $rootCtx.Values.global.traefik.addServiceAnnotations -}} - {{- $_ := set $annotations "traefik.ingress.kubernetes.io/service.serversscheme" "https" -}} - {{- end -}} - {{- end -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/service/integrations/_cilium.tpl b/charts/library/common/templates/lib/service/integrations/_cilium.tpl new file mode 100644 index 00000000000..bf373e4acf1 --- /dev/null +++ b/charts/library/common/templates/lib/service/integrations/_cilium.tpl @@ -0,0 +1,33 @@ +{{- define "tc.v1.common.lib.service.integration.cilium" -}} + {{- $objectData := .objectData -}} + {{- $rootCtx := .rootCtx -}} + + {{- $_ := set $objectData "integrations" ($objectData.integrations | default dict) -}} + {{- $cilium := $objectData.integrations.cilium -}} + + {{- if $cilium.enabled -}} + {{- include "tc.v1.common.lib.service.integration.validate" (dict "objectData" $objectData "integration" $cilium) -}} + + {{- if and $cilium.sharedKey (ne $objectData.externalTrafficPolicy "Local") -}} + {{/* If externalTrafficPolicy is not set or is not Local, add the shared key as annotation */}} + {{- $_ := set $objectData.annotations "lbipam.cilium.io/sharing-key" $cilium.sharedKey -}} + {{- end -}} + + {{- $ips := list -}} + + {{/* Handle loadBalancerIP (single) */}} + {{- if $objectData.loadBalancerIP -}} + {{- $ips = mustAppend $ips (tpl $objectData.loadBalancerIP $rootCtx) -}} + {{- end -}} + + {{/* Handle loadBalancerIPs (multiple) */}} + {{- range $ip := $objectData.loadBalancerIPs -}} + {{- $ips = mustAppend $ips (tpl $ip $rootCtx) -}} + {{- end -}} + + {{- if $ips -}} + {{- $_ := set $objectData.annotations "lbipam.cilium.io/ips" (join "," $ips) -}} + {{- end -}} + + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/service/integrations/_metallb.tpl b/charts/library/common/templates/lib/service/integrations/_metallb.tpl new file mode 100644 index 00000000000..8977694af4e --- /dev/null +++ b/charts/library/common/templates/lib/service/integrations/_metallb.tpl @@ -0,0 +1,38 @@ +{{- define "tc.v1.common.lib.service.integration.metallb" -}} + {{- $objectData := .objectData -}} + {{- $rootCtx := .rootCtx -}} + + {{- $_ := set $objectData "integrations" ($objectData.integrations | default dict) -}} + {{- $metallb := $objectData.integrations.metallb -}} + + {{- if $metallb.enabled -}} + {{- include "tc.v1.common.lib.service.integration.validate" (dict "objectData" $objectData "integration" $metallb) -}} + + {{ $sharedKey := (include "tc.v1.common.lib.metadata.namespace" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "Service")) }} + {{- if $metallb.sharedKey -}} + {{- $sharedKey = $metallb.sharedKey -}} + {{- end -}} + + {{/* If externalTrafficPolicy is not set or is not Local, add the shared key as annotation */}} + {{- if ne $objectData.externalTrafficPolicy "Local" -}} + {{- $_ := set $objectData.annotations "metallb.io/allow-shared-ip" $sharedKey -}} + {{- end -}} + + {{- $ips := list -}} + + {{/* Handle loadBalancerIP (single) */}} + {{- if $objectData.loadBalancerIP -}} + {{- $ips = mustAppend $ips (tpl $objectData.loadBalancerIP $rootCtx) -}} + {{- end -}} + + {{/* Handle loadBalancerIPs (multiple) */}} + {{- range $ip := $objectData.loadBalancerIPs -}} + {{- $ips = mustAppend $ips (tpl $ip $rootCtx) -}} + {{- end -}} + + {{- if $ips -}} + {{- $_ := set $objectData.annotations "metallb.io/loadBalancerIPs" (join "," $ips) -}} + {{- end -}} + + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/service/integrations/_traefik.tpl b/charts/library/common/templates/lib/service/integrations/_traefik.tpl new file mode 100644 index 00000000000..e8b64b81ed4 --- /dev/null +++ b/charts/library/common/templates/lib/service/integrations/_traefik.tpl @@ -0,0 +1,12 @@ +{{- define "tc.v1.common.lib.service.integration.traefik" -}} + {{- $objectData := .objectData -}} + {{- $rootCtx := .rootCtx -}} + + {{- $_ := set $objectData "integrations" ($objectData.integrations | default dict) -}} + {{- $traefik := $objectData.integrations.traefik -}} + + {{- if $traefik.enabled -}} + {{- $_ := set $objectData.annotations "traefik.ingress.kubernetes.io/service.serversscheme" "https" -}} + {{- end -}} + +{{- end -}} diff --git a/charts/library/common/templates/lib/service/integrations/_validation.tpl b/charts/library/common/templates/lib/service/integrations/_validation.tpl new file mode 100644 index 00000000000..bf438c0dfbe --- /dev/null +++ b/charts/library/common/templates/lib/service/integrations/_validation.tpl @@ -0,0 +1,25 @@ +{{- define "tc.v1.common.lib.service.integration.validate" -}} + {{- $objectData := .objectData -}} + {{- $integration := .integration -}} + + {{- if and $integration.sharedKey (eq $objectData.externalTrafficPolicy "Local") -}} + {{- fail (printf "Service - [sharedKey], cannot both be used together with [externalTrafficPolicy] set to [Local]" ) -}} + {{- end -}} +{{- end -}} + +{{- define "tc.v1.common.lib.service.loadbalancer.validate" -}} + {{- $objectData := .objectData -}} + + {{- if and $objectData.loadBalancerIPs (not (kindIs "slice" $objectData.loadBalancerIPs)) -}} + {{- fail (printf "Service - Expected [loadBalancerIPs] to be a slice, but got [%s]" (kindOf $objectData.loadBalancerIPs)) -}} + {{- end -}} + + {{- if and $objectData.loadBalancerIP (not (kindIs "string" $objectData.loadBalancerIP)) -}} + {{- fail (printf "Service - Expected [loadBalancerIP] to be a string, but got [%s]" (kindOf $objectData.loadBalancerIP)) -}} + {{- end -}} + + {{- if and $objectData.loadBalancerIP $objectData.loadBalancerIPs -}} + {{- fail "Service - Expected one of [loadBalancerIP, loadBalancerIPs] to be defined but got both" -}} + {{- end -}} + +{{- end -}} diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index 078ccc4f55e..0ae4db48a97 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -63,12 +63,7 @@ global: cnpg: pgVersion: 16 skipEmptyWalArchiveCheck: true - metallb: - # -- Adds metalLB annotations to services - addServiceAnnotations: true traefik: - # -- Adds traefik annotations to services (when needed) - addServiceAnnotations: true commonMiddlewares: - name: tc-basic-secure-headers # -- Minimum nodePort value @@ -203,6 +198,20 @@ diagnosticMode: # -- (docs/service/README.md) service: main: + ## Integration stuff + # integration: + # metallb: + # enabled: false + ## Optional to set shared key manually, otherwise set to namespace + # sharedKey: "" + # + # cilium: + # enabled: false + ## Optional to set shared key manually, otherwise ignored (namespace sharing) + # sharedKey: "" + # + # traefik: + # enabled: false enabled: true primary: true ports: