fixup externalIP

This commit is contained in:
Stavros kois
2023-02-06 17:56:12 +02:00
parent baefb37289
commit a412277293
7 changed files with 257 additions and 32 deletions
@@ -1,6 +1,8 @@
suite: service externalIP test
templates:
- common.yaml
chart:
appVersion: &appVer v9.9.9
tests:
- it: should pass with type externalIP
set:
@@ -9,7 +11,7 @@ tests:
enabled: true
primary: true
type: ExternalIP
externalName: my-external-name
externalIP: 1.1.1.1
ports:
port-name:
enabled: true
@@ -46,6 +48,8 @@ tests:
some_port: 12344
some_target_port: 12346
some_protocol: HTTP
some_external_ip: 1.1.1.1
some_address_type: IPv6
service:
my-service:
enabled: true
@@ -53,6 +57,7 @@ tests:
type: ExternalIP
publishNotReadyAddresses: true
externalTrafficPolicy: "{{ .Values.some_policy }}"
externalIP: "{{ .Values.some_external_ip }}"
externalIPs:
- "{{ .Values.some_ip }}"
- 10.200.34.54
@@ -60,6 +65,7 @@ tests:
sessionAffinityConfig:
clientIP:
timeoutSeconds: "{{ .Values.some_timeout }}"
addressType: "{{ .Values.some_address_type }}"
ports:
port-name:
enabled: true
@@ -93,3 +99,46 @@ tests:
port: 12344
protocol: TCP
targetPort: 12346
- documentIndex: &endpointSliceDoc 1
isKind:
of: EndpointSlice
- documentIndex: *endpointSliceDoc
isAPIVersion:
of: discovery.k8s.io/v1
- documentIndex: *endpointSliceDoc
equal:
path: metadata.name
value: release-name-common-test
- documentIndex: *endpointSliceDoc
equal:
path: metadata.labels
value:
kubernetes.io/service-name: release-name-common-test
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
helm.sh/chart: common-test-1.0.0
helm-revision: 0
app: common-test-1.0.0
release: RELEASE-NAME
- documentIndex: *endpointSliceDoc
equal:
path: addressType
value: IPv6
- documentIndex: *endpointSliceDoc
equal:
path: ports
value:
- name: port-name
port: 12345
protocol: TCP
appProtocol: tcp
- name: port-name2
port: 12346
protocol: TCP
appProtocol: http
- documentIndex: *endpointSliceDoc
equal:
path: endpoints
value:
- addresses:
- 1.1.1.1
@@ -246,6 +246,41 @@ tests:
- failedTemplate:
errorMessage: Service - Expected <ipFamilyPolicy> to be one of [SingleStack, PreferDualStack, RequireDualStack], but got [not-a-policy]
- it: should fail with empty externalIP
set:
service:
service-name1:
enabled: true
primary: true
type: ExternalIP
externalIP: ""
ports:
port-name1:
enabled: true
primary: true
port: 12345
asserts:
- failedTemplate:
errorMessage: EndpointSlice - Expected non-empty <externalIP>
- it: should fail with externalIP not a string
set:
service:
service-name1:
enabled: true
primary: true
type: ExternalIP
externalIP:
- not-a-string
ports:
port-name1:
enabled: true
primary: true
port: 12345
asserts:
- failedTemplate:
errorMessage: EndpointSlice - Expected <externalIP> to be a [string], but got [slice]
- it: should fail with ipFamilies not a list
set:
service:
+66 -30
View File
@@ -1,35 +1,37 @@
# Service
| Key | Type | Required | Helm Template | Default | Description |
| :------------------------------------------------------------------- | :-------: | :---------------------: | :----------------: | :----------------: | :------------------------------------------------------------------------------------------------------------------------------------ |
| service | `dict` | | ❌ | `{}` | Define the service as dicts |
| service.[service-name] | `dict` | | ❌ | `{}` | Holds service definition |
| service.[service-name].enabled | `boolean` | | ❌ | `false` | Enables or Disables the service |
| service.[service-name].labels | `dict` | | ✅ (On value only) | `{}` | Additional labels for service |
| service.[service-name].annotations | `dict` | | ✅ (On value only) | `{}` | Additional annotations for service |
| service.[service-name].type | `string` | | ✅ | `ClusterIP` | Define the service type (ClusterIP, LoadBalancer, NodePort, ExternalIP, ExternalName) |
| service.[service-name].publishNotReadyAddresses | `boolean` | | ❌ | `false` | Define whether to publishNotReadyAddresses or not |
| service.[service-name].externalIPs | `list` | | | | Define externalIPs |
| service.[service-name].externalIPs.[externalIP] | `string` | | ✅ | | The external IP |
| service.[service-name].sharedKey | `string` | ❌ | | `$FullName` | Custom Shared Key for MetalLB Annotation |
| service.[service-name].clusterIP | `string` | | ✅ | | Custom Cluster IP |
| service.[service-name].ipFamilyPolicy | `string` | | ✅ | | Define the ipFamilyPolicy (SingleStack, PreferDualStack, RequireDualStack) |
| service.[service-name].ipFamilies | `list` | ❌ | | | Define the ipFamilies |
| service.[service-name].ipFamilies.[ipFamily] | `string` | | ✅ | | Define the ipFamily (IPv4, IPv6) |
| service.[service-name].loadBalancerIP | `string` | ❌ | | | Define the load balancer IP |
| service.[service-name].loadBalancerSourceRanges | `list` | | | | Define the load balancer source ranges |
| service.[service-name].loadBalancerSourceRanges.[source-range] | `string` | | ✅ | | Define the load balancer source range |
| service.[service-name].externalTrafficPolicy | `string` | ❌ | | | Define the external traffic policy (Cluster, Local) |
| service.[service-name].sessionAffinity | `string` | | ✅ | | Define the session affinity (ClientIP, None) |
| service.[service-name].sessionAffinityConfig.clientIP.timeoutSeconds | `int` | | ✅ | | Define the timeout for ClientIP session affinity (0-86400) |
| service.[service-name].targetSelector | `string` | | | `""` | Define the pod to link the service, by default will use the primary pod |
| service.[service-name].ports | `list` | | | `{}` | Define the ports of the service |
| service.[service-name].ports.[port-name] | `dict` | | ❌ | `{}` | Define the port dict |
| service.[service-name].ports.[port-name].port | `int` | ✅ | | | Define the port that will be exposed by the service |
| service.[service-name].ports.[port-name].nodePort | `int` | ✅ (Only NodePort type) | ✅ | | Define the node port that will be exposed on the node |
| service.[service-name].ports.[port-name].targetPort | `int` | | ✅ | `[port-name].port` | Define the target port (No named ports, as this will be used to assign the containerPort to containers) |
| service.[service-name].ports.[port-name].protocol | `string` | ❌ | ✅ | `TCP` | Define the port protocol (HTTP, HTTPS, TCP, UDP). (Also used by the container probes, HTTP and HTTPS are converted to TCP on service) |
| service.[service-name].ports.[port-name].targetSelector | `string` | ❌ | | `TCP` | Define the container to link this port (Must be on under the pod linked above) |
| Key | Type | Required | Helm Template | Default | Description |
| :------------------------------------------------------------------- | :-------: | :-----------------------: | :----------------: | :----------------: | :------------------------------------------------------------------------------------------------------------------------------------ |
| service | `dict` | | ❌ | `{}` | Define the service as dicts |
| service.[service-name] | `dict` | | ❌ | `{}` | Holds service definition |
| service.[service-name].enabled | `boolean` | | ❌ | `false` | Enables or Disables the service |
| service.[service-name].labels | `dict` | | ✅ (On value only) | `{}` | Additional labels for service |
| service.[service-name].annotations | `dict` | | ✅ (On value only) | `{}` | Additional annotations for service |
| service.[service-name].type | `string` | | ✅ | `ClusterIP` | Define the service type (ClusterIP, LoadBalancer, NodePort, ExternalIP, ExternalName) |
| service.[service-name].publishNotReadyAddresses | `boolean` | | ❌ | `false` | Define whether to publishNotReadyAddresses or not |
| service.[service-name].externalIP | `string` | ✅ (Only ExternalIP type) | | | Define External IP for headless service |
| service.[service-name].addressType | `string` | ✅ (Only ExternalIP type) | ✅ | `IPv4` | Define the addressType for External IP |
| service.[service-name].externalIPs | `list` | | | | Define externalIPs |
| service.[service-name].externalIPs.[externalIP] | `string` | | ✅ | | The external IP |
| service.[service-name].sharedKey | `string` | | ✅ | `$FullName` | Custom Shared Key for MetalLB Annotation |
| service.[service-name].clusterIP | `string` | | | | Custom Cluster IP |
| service.[service-name].ipFamilyPolicy | `string` | | ✅ | | Define the ipFamilyPolicy (SingleStack, PreferDualStack, RequireDualStack) |
| service.[service-name].ipFamilies | `list` | | | | Define the ipFamilies |
| service.[service-name].ipFamilies.[ipFamily] | `string` | | | | Define the ipFamily (IPv4, IPv6) |
| service.[service-name].loadBalancerIP | `string` | | ✅ | | Define the load balancer IP |
| service.[service-name].loadBalancerSourceRanges | `list` | | | | Define the load balancer source ranges |
| service.[service-name].loadBalancerSourceRanges.[source-range] | `string` | | ✅ | | Define the load balancer source range |
| service.[service-name].externalTrafficPolicy | `string` | | ✅ | | Define the external traffic policy (Cluster, Local) |
| service.[service-name].sessionAffinity | `string` | | | | Define the session affinity (ClientIP, None) |
| service.[service-name].sessionAffinityConfig.clientIP.timeoutSeconds | `int` | | | | Define the timeout for ClientIP session affinity (0-86400) |
| service.[service-name].targetSelector | `string` | | ❌ | `""` | Define the pod to link the service, by default will use the primary pod |
| service.[service-name].ports | `list` | | | `{}` | Define the ports of the service |
| service.[service-name].ports.[port-name] | `dict` | | | `{}` | Define the port dict |
| service.[service-name].ports.[port-name].port | `int` | | ✅ | | Define the port that will be exposed by the service |
| service.[service-name].ports.[port-name].nodePort | `int` | ✅ (Only NodePort type) | ✅ | | Define the node port that will be exposed on the node |
| service.[service-name].ports.[port-name].targetPort | `int` | | | `[port-name].port` | Define the target port (No named ports, as this will be used to assign the containerPort to containers) |
| service.[service-name].ports.[port-name].protocol | `string` | ❌ | ✅ | `TCP` | Define the port protocol (HTTP, HTTPS, TCP, UDP). (Also used by the container probes, HTTP and HTTPS are converted to TCP on service) |
| service.[service-name].ports.[port-name].targetSelector | `string` | ❌ | ❌ | `TCP` | Define the container to link this port (Must be on under the pod linked above) |
---
@@ -62,6 +64,9 @@ service:
externalIPs:
- 10.200.230.34
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 86400
targetSelector: pod-name
ports:
port-name:
@@ -88,6 +93,9 @@ service:
externalIPs:
- 10.200.230.34
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 86400
externalTrafficPolicy: Cluster
targetSelector: pod-name
ports:
@@ -108,6 +116,9 @@ service:
externalIPs:
- 10.200.230.34
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 86400
externalTrafficPolicy: Cluster
targetSelector: pod-name
ports:
@@ -120,6 +131,7 @@ service:
targetPort: 8080
nodePort: 30080
# Special type
service-externalname:
enabled: true
primary: true
@@ -130,6 +142,29 @@ service:
externalIPs:
- 10.200.230.34
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 86400
externalTrafficPolicy: Cluster
ports:
port-name:
enabled: true
primary: true
targetSelector: container-name
port: 80
protocol: HTTP
# Special type
service-externalip:
enabled: true
primary: true
type: ExternalIP
externalIP: 1.1.1.1
addressType: IPv4
publishNotReadyAddresses: true
externalIPs:
- 10.200.230.34
sessionAffinity: ClientIP
externalTrafficPolicy: Cluster
ports:
port-name:
@@ -137,6 +172,7 @@ service:
primary: true
targetSelector: container-name
port: 80
targetPort: 8080
protocol: HTTP
other-service-name:
@@ -0,0 +1,40 @@
{{/* EndpointSlice Class */}}
{{/* Call this template:
{{ include "ix.v1.common.class.endpointSlice" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the template. It is used to access the global context.
objectData: The service data, that will be used to render the Service object.
*/}}
{{- define "ix.v1.common.class.endpointSlice" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $addressType := $objectData.addressType | default "IPv4" -}}
{{- if $objectData.addressType -}}
{{- $addressType = tpl $addressType $rootCtx -}}
{{- end }}
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: {{ $objectData.name }}
{{- $labels := (mustMerge ($objectData.labels | default dict) (include "ix.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml)) -}}
{{- $_ := set $labels "kubernetes.io/service-name" $objectData.name -}}
{{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }}
labels:
{{- . | nindent 4 }}
{{- end -}}
{{- $annotations := (mustMerge ($objectData.annotations | default dict) (include "ix.v1.common.lib.metadata.allAnnotations" $rootCtx | fromYaml)) -}}
{{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
addressType: {{ $addressType }}
ports:
{{- include "ix.v1.common.lib.endpointslice.ports" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 }}
endpoints:
{{- include "ix.v1.common.lib.endpointslice.endpoints" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 }}
{{- end -}}
@@ -93,6 +93,6 @@ spec:
{{- include "ix.v1.common.lib.metadata.selectorLabels" (dict "rootCtx" $rootCtx "podName" $podValues.shortName) | trim | nindent 4 -}}
{{- end -}}
{{- if eq $svcType "ExternalIP" -}}
{{/* TODO: endpointsslice for externalIP */}}
{{- include "ix.v1.common.class.endpointSlice" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 0 }}
{{- end -}}
{{- end -}}
@@ -0,0 +1,21 @@
{{/* EndpointSlice - endpoints */}}
{{/* Call this template:
{{ include "ix.v1.common.lib.endpointslice.endpoints" (dict "rootCtx" $rootCtx "objectData" $objectData) -}}
rootCtx: The root context of the service
objectData: The object data of the service
*/}}
{{- define "ix.v1.common.lib.endpointslice.endpoints" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- if not $objectData.externalIP -}}
{{- fail "EndpointSlice - Expected non-empty <externalIP>" -}}
{{- end -}}
{{- if not (kindIs "string" $objectData.externalIP) -}} {{/* Only single IP is supported currently on this lib */}}
{{- fail (printf "EndpointSlice - Expected <externalIP> to be a [string], but got [%s]" (kindOf $objectData.externalIP)) -}}
{{- end }}
- addresses:
- {{ tpl $objectData.externalIP $rootCtx }}
{{- end -}}
@@ -0,0 +1,44 @@
{{/* EndpointSlice - Ports */}}
{{/* Call this template:
{{ include "ix.v1.common.lib.endpointslice.ports" (dict "rootCtx" $rootCtx "objectData" $objectData) -}}
rootCtx: The root context
objectData: The object data of the service
*/}}
{{- define "ix.v1.common.lib.endpointslice.ports" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $tcpProtocols := (list "TCP" "HTTP" "HTTPS") -}}
{{- range $name, $portValues := $objectData.ports -}}
{{- if $portValues.enabled -}}
{{- $protocol := $rootCtx.Values.fallbackDefaults.serviceProtocol -}} {{/* Default to fallback protocol, if no protocol is defined */}}
{{- $appProtocol := $rootCtx.Values.fallbackDefaults.serviceProtocol -}}
{{- $targetPort := $portValues.targetPort -}}
{{- if not $targetPort -}}
{{- $targetPort = $portValues.port -}}
{{- end -}}
{{/* Expand targetPort */}}
{{- if (kindIs "string" $targetPort) -}}
{{- $targetPort = (tpl $targetPort $rootCtx) -}}
{{- end -}}
{{- $targetPort = int $targetPort -}}
{{- with $portValues.protocol -}}
{{- $protocol = tpl . $rootCtx -}}
{{- $appProtocol = tpl . $rootCtx -}}
{{- if mustHas $protocol $tcpProtocols -}}
{{- $protocol = "TCP" -}}
{{- end -}}
{{- end }}
- name: {{ $name }}
port: {{ $targetPort }}
protocol: {{ $protocol }}
appProtocol: {{ $appProtocol | lower }}
{{- end -}}
{{- end -}}
{{- end -}}