Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(chart): Simplify config ports, probes, lifecycle hooks for Nodes #2077

Merged
merged 1 commit into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/helm-chart-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ jobs:
with:
name: ${{ matrix.test-strategy }}_${{ env.CHART_FILE_NAME }}
path: ${{ env.CHART_PACKAGE_PATH }}
- name: Upload Helm chart template rendered
- name: Upload chart test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.test-strategy }}_chart_template_rendered.yaml
path: ./tests/tests/output_deployment.yaml
name: ${{ matrix.test-strategy }}-artifacts
path: ./tests/tests/
if-no-files-found: ignore
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ chart_test_edge:
VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh NodeEdge

chart_test_parallel_autoscaling:
VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh ParallelAutoscaling
VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh JobAutoscaling

.PHONY: \
all \
Expand Down
233 changes: 191 additions & 42 deletions charts/selenium-grid/README.md

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion charts/selenium-grid/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ All related testing to this helm chart will be documented in this file.
| | Basic Auth is enabled | ✗ | |
| Auto scaling | Auto scaling with `enableWithExistingKEDA` is `true` | ✓ | Cluster |
| | Auto scaling with `scalingType` is `job` | ✓ | Cluster |
| | Auto scaling with `scalingType` is `deployment` | ✗ | |
| | Auto scaling with `scalingType` is `deployment` | ✓ | Cluster |
| | Auto scaling with `autoscaling.scaledOptions.minReplicaCount` is `0` | ✓ | Cluster |
| | Parallel tests execution against node autoscaling | ✓ | Cluster |
| Ingress | Ingress is enabled without `hostname` | ✓ | Cluster |
Expand All @@ -27,6 +27,10 @@ All related testing to this helm chart will be documented in this file.
| | Components are able to set `.affinity` | ✓ | Template |
| Tracing | Enable tracing via `SE_ENABLE_TRACING` | ✓ | Cluster |
| | Disable tracing via `SE_ENABLE_TRACING` | ✓ | Cluster |
| `Node` component | `SE_NODE_PORT` can set a port different via `.port` | ✓ | Cluster |
| | Extra ports can be exposed on container via `.ports` | ✓ | Cluster |
| | Extra ports can be exposed on Service via `.service.ports` | ✓ | Cluster |
| | Service type change to `NodePort`, specific NodePort can be set | ✓ | Cluster |

## Test Chart Template
- By using `helm template` command, the chart template is tested without installing it to Kubernetes cluster.
Expand Down
175 changes: 160 additions & 15 deletions charts/selenium-grid/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,56 @@ Ingress fullname
{{- default "selenium-ingress" .Values.ingress.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Probe httpGet schema
*/}}
{{- define "seleniumGrid.probe.httpGet.schema" -}}
{{- "HTTP" -}}
{{- end -}}

{{/*
Check user define custom probe method
*/}}
{{- define "seleniumGrid.probe.fromUserDefine" -}}
{{- $overrideProbe := dict -}}
{{- with .exec -}}
{{- $overrideProbe = dict "exec" . -}}
{{- end }}
{{- with .httpGet -}}
{{- $overrideProbe = dict "httpGet" . -}}
{{- end }}
{{- with .tcpSocket -}}
{{- $overrideProbe = dict "tcpSocket" . -}}
{{- end }}
{{- with .grpc -}}
{{- $overrideProbe = dict "grpc" . -}}
{{- end -}}
{{- $overrideProbe | toYaml -}}
{{- end -}}

{{/*
Get probe settings
*/}}
{{- define "seleniumGrid.probe.settings" -}}
{{- $settings := dict -}}
{{- with .initialDelaySeconds -}}
{{- $settings = set $settings "initialDelaySeconds" . -}}
{{- end }}
{{- with .periodSeconds -}}
{{- $settings = set $settings "periodSeconds" . -}}
{{- end }}
{{- with .timeoutSeconds -}}
{{- $settings = set $settings "timeoutSeconds" . -}}
{{- end }}
{{- with .successThreshold -}}
{{- $settings = set $settings "successThreshold" . -}}
{{- end }}
{{- with .failureThreshold -}}
{{- $settings = set $settings "failureThreshold" . -}}
{{- end -}}
{{- $settings | toYaml -}}
{{- end -}}

{{- define "seleniumGrid.ingress.nginx.annotations.default" -}}
{{- with .Values.ingress.nginx }}
{{- with .proxyTimeout }}
Expand Down Expand Up @@ -199,9 +249,12 @@ template:
{{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .node.imageRegistry }}
image: {{ printf "%s/%s:%s" $imageRegistry .node.imageName $imageTag }}
imagePullPolicy: {{ .node.imagePullPolicy }}
{{- with .node.extraEnvironmentVariables }}
env: {{- tpl (toYaml .) $ | nindent 10 }}
{{- end }}
env:
- name: SE_NODE_PORT
value: {{ .node.port | quote }}
{{- with .node.extraEnvironmentVariables }}
{{- tpl (toYaml .) $ | nindent 10 }}
{{- end }}
envFrom:
- configMapRef:
name: {{ .Values.busConfigMap.name }}
Expand All @@ -212,16 +265,26 @@ template:
{{- with .node.extraEnvFrom }}
{{- tpl (toYaml .) $ | nindent 10 }}
{{- end }}
{{- if gt (len .node.ports) 0 }}
ports:
{{- range .node.ports }}
- containerPort: {{ . }}
- containerPort: {{ .node.port }}
protocol: TCP
{{- if gt (len .node.ports) 0 }}
{{- $ports := .node.ports -}}
{{- if (regexMatch "[0-9]+$" (index $ports 0 | toString)) -}}
{{- range .node.ports }}
- containerPort: {{ . | int }}
protocol: TCP
{{- end }}
{{- else -}}
{{- tpl (toYaml .node.ports) $ | nindent 10 }}
{{- end }}
{{- end }}
volumeMounts:
- name: dshm
mountPath: /dev/shm
- name: {{ .Values.nodeConfigMap.scriptVolumeMountName }}
mountPath: /opt/selenium/{{ .Values.nodeConfigMap.preStopScript }}
subPath: {{ .Values.nodeConfigMap.preStopScript }}
{{- if .node.extraVolumeMounts }}
{{- tpl (toYaml .node.extraVolumeMounts) $ | nindent 10 }}
{{- end }}
Expand All @@ -231,12 +294,54 @@ template:
{{- with .node.securityContext }}
securityContext: {{- toYaml . | nindent 10 }}
{{- end }}
{{- include "seleniumGrid.lifecycle" . | nindent 8 -}}
{{- include "seleniumGrid.node.lifecycle" . | nindent 8 -}}
{{- if .node.startupProbe.enabled }}
{{- with .node.startupProbe }}
startupProbe: {{- toYaml . | nindent 10 }}
startupProbe:
{{- if (ne (include "seleniumGrid.probe.fromUserDefine" .) "{}") }}
{{- include "seleniumGrid.probe.fromUserDefine" . | nindent 10 }}
{{- else }}
httpGet:
scheme: {{ default (include "seleniumGrid.probe.httpGet.schema" .) .schema }}
path: {{ .path }}
port: {{ default ($.node.port) .port }}
{{- end }}
{{- if (ne (include "seleniumGrid.probe.settings" .) "{}") }}
{{- include "seleniumGrid.probe.settings" . | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .node.readinessProbe.enabled }}
{{- with .node.readinessProbe }}
readinessProbe:
{{- if (ne (include "seleniumGrid.probe.fromUserDefine" .) "{}") }}
{{- include "seleniumGrid.probe.fromUserDefine" . | nindent 12 }}
{{- else }}
httpGet:
scheme: {{ default (include "seleniumGrid.probe.httpGet.schema" .) .schema }}
path: {{ .path }}
port: {{ default ($.node.port) .port }}
{{- end }}
{{- if (ne (include "seleniumGrid.probe.settings" .) "{}") }}
{{- include "seleniumGrid.probe.settings" . | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .node.livenessProbe.enabled }}
{{- with .node.livenessProbe }}
livenessProbe: {{- toYaml . | nindent 10 }}
livenessProbe:
{{- if (ne (include "seleniumGrid.probe.fromUserDefine" .) "{}") }}
{{- include "seleniumGrid.probe.fromUserDefine" . | nindent 10 }}
{{- else }}
httpGet:
scheme: {{ default (include "seleniumGrid.probe.httpGet.schema" .) .schema }}
path: {{ .path }}
port: {{ default ($.node.port) .port }}
{{- end }}
{{- if (ne (include "seleniumGrid.probe.settings" .) "{}") }}
{{- include "seleniumGrid.probe.settings" . | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .node.sidecars }}
{{- toYaml .node.sidecars | nindent 6 }}
Expand Down Expand Up @@ -325,6 +430,10 @@ template:
{{- end }}
terminationGracePeriodSeconds: {{ .node.terminationGracePeriodSeconds }}
volumes:
- name: {{ .Values.nodeConfigMap.scriptVolumeMountName }}
configMap:
name: {{ .Values.nodeConfigMap.name }}
defaultMode: {{ .Values.nodeConfigMap.defaultMode }}
- name: dshm
emptyDir:
medium: Memory
Expand Down Expand Up @@ -425,19 +534,55 @@ Graphql unsafeSsl of the hub or the router
{{- end -}}

{{/*
Get the lifecycle of the pod. When KEDA is activated and the lifecycle is used for a pod of a
deployment preStop hook to deregister from the selenium hub.
Define preStop hook for the node pod. Node preStop script is stored in a ConfigMap and mounted as a volume.
*/}}
{{- define "seleniumGrid.lifecycle" }}
{{ $lifecycle := tpl (toYaml (default (dict) .node.lifecycle)) $ }}
{{- if and (eq .Values.autoscaling.scalingType "deployment") (eq (include "seleniumGrid.useKEDA" .) "true") -}}
{{ $lifecycle = merge ($lifecycle | fromYaml ) .Values.autoscaling.deregisterLifecycle | toYaml }}
{{- define "seleniumGrid.node.deregisterLifecycle" -}}
preStop:
exec:
command: ["bash", "-c", "/opt/selenium/{{ .Values.nodeConfigMap.preStopScript }}"]
{{- end -}}

{{/*
Get the lifecycle of the pod is used for a Node to deregister from the Hub/Router.
1. IF KEDA is activated, scalingType is "deployment", and individual node deregisterLifecycle is not set, use autoscaling.deregisterLifecycle
2. ELSE (KEDA is not activated and node deregisterLifecycle is set), use .deregisterLifecycle in individual node
3. IF individual node with .lifecycle is set, it takes highest precedence to override the preStop in above use cases
*/}}
{{- define "seleniumGrid.node.lifecycle" }}
{{- $defaultDeregisterLifecycle := tpl (include "seleniumGrid.node.deregisterLifecycle" .) $ -}}
{{- $lifecycle := toYaml (dict) -}}
{{- if and (and (eq .Values.autoscaling.scalingType "deployment") (eq (include "seleniumGrid.useKEDA" .) "true")) (empty .node.deregisterLifecycle) -}}
{{- $lifecycle = merge ($lifecycle | fromYaml) (tpl (toYaml (default ($defaultDeregisterLifecycle | fromYaml) .Values.autoscaling.deregisterLifecycle)) $ | fromYaml) | toYaml -}}
{{- else -}}
{{- if eq (.node.deregisterLifecycle | toString | lower) "false" -}}
{{- $lifecycle = toYaml (dict) -}}
{{- else -}}
{{- $lifecycle = (tpl (toYaml (default ($defaultDeregisterLifecycle | fromYaml) .node.deregisterLifecycle) ) $ | fromYaml) | toYaml -}}
{{- end -}}
{{- end -}}
{{- if not (empty .node.lifecycle) -}}
{{- $lifecycle = mergeOverwrite ($lifecycle | fromYaml) (tpl (toYaml .node.lifecycle) $ | fromYaml) | toYaml -}}
{{- end -}}
{{ if and $lifecycle (ne $lifecycle "{}") -}}
lifecycle: {{ $lifecycle | nindent 2 }}
{{- end -}}
{{- end -}}

{{/*
Define terminationGracePeriodSeconds of the node pod.
1. IF KEDA is activated, scalingType is "deployment", use autoscaling.terminationGracePeriodSeconds
2. IF node.terminationGracePeriodSeconds is greater than autoscaling.terminationGracePeriodSeconds, use node.terminationGracePeriodSeconds
*/}}
{{- define "seleniumGrid.node.terminationGracePeriodSeconds" -}}
{{- $autoscalingPeriod := default 0 .Values.autoscaling.terminationGracePeriodSeconds -}}
{{- $nodePeriod := default 0 .node.terminationGracePeriodSeconds -}}
{{- $period := $nodePeriod -}}
{{- if and (eq .Values.autoscaling.scalingType "deployment") (eq (include "seleniumGrid.useKEDA" .) "true") -}}
{{- $period = ternary $nodePeriod $autoscalingPeriod (gt $nodePeriod $autoscalingPeriod) -}}
{{- end -}}
{{- $period -}}
{{- end -}}

{{/*
Default specs of VolumeMounts and Volumes for video recorder
*/}}
Expand Down
7 changes: 5 additions & 2 deletions charts/selenium-grid/templates/chrome-node-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ spec:
ports:
- name: tcp-chrome
protocol: TCP
port: {{ .Values.chromeNode.seleniumServicePort }}
targetPort: {{ .Values.chromeNode.seleniumPort }}
port: {{ .Values.chromeNode.port }}
targetPort: {{ .Values.chromeNode.port }}
{{- if and (eq $.Values.chromeNode.service.type "NodePort") .Values.chromeNode.nodePort }}
nodePort: {{ .Values.chromeNode.nodePort }}
{{- end }}
{{- with .Values.chromeNode.service.ports }}
{{- range . }}
- name: {{ .name }}
Expand Down
7 changes: 5 additions & 2 deletions charts/selenium-grid/templates/edge-node-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ spec:
ports:
- name: tcp-edge
protocol: TCP
port: {{ .Values.edgeNode.seleniumServicePort }}
targetPort: {{ .Values.edgeNode.seleniumPort }}
port: {{ .Values.edgeNode.port }}
targetPort: {{ .Values.edgeNode.port }}
{{- if and (eq $.Values.edgeNode.service.type "NodePort") .Values.edgeNode.nodePort }}
nodePort: {{ .Values.edgeNode.nodePort }}
{{- end }}
{{- with .Values.edgeNode.service.ports }}
{{- range . }}
- name: {{ .name }}
Expand Down
2 changes: 1 addition & 1 deletion charts/selenium-grid/templates/event-bus-configmap.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- $eventBusHost := ternary (include "seleniumGrid.eventBus.fullname" .) (include "seleniumGrid.hub.fullname" .) .Values.isolateComponents -}}
{{- $eventBusHost := printf "%s.%s" (ternary (include "seleniumGrid.eventBus.fullname" .) (include "seleniumGrid.hub.fullname" .) .Values.isolateComponents) (.Release.Namespace) -}}
{{- $eventBusPublishPort := ternary .Values.components.eventBus.publishPort .Values.hub.publishPort .Values.isolateComponents -}}
{{- $eventBusSubscribePort := ternary .Values.components.eventBus.subscribePort .Values.hub.subscribePort .Values.isolateComponents -}}
apiVersion: v1
Expand Down
7 changes: 5 additions & 2 deletions charts/selenium-grid/templates/firefox-node-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ spec:
ports:
- name: tcp-firefox
protocol: TCP
port: {{ .Values.firefoxNode.seleniumServicePort }}
targetPort: {{ .Values.firefoxNode.seleniumPort }}
port: {{ .Values.firefoxNode.port }}
targetPort: {{ .Values.firefoxNode.port }}
{{- if and (eq $.Values.firefoxNode.service.type "NodePort") .Values.firefoxNode.nodePort }}
nodePort: {{ .Values.firefoxNode.nodePort }}
{{- end }}
{{- with .Values.firefoxNode.service.ports }}
{{- range . }}
- name: {{ .name }}
Expand Down
58 changes: 42 additions & 16 deletions charts/selenium-grid/templates/hub-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,53 @@ spec:
protocol: TCP
- containerPort: {{ .Values.hub.subscribePort }}
protocol: TCP
{{- if .Values.hub.livenessProbe.enabled }}
livenessProbe:
{{- if .Values.hub.startupProbe.enabled }}
{{- with .Values.hub.startupProbe }}
startupProbe:
{{- if (ne (include "seleniumGrid.probe.fromUserDefine" .) "{}") }}
{{- include "seleniumGrid.probe.fromUserDefine" . | nindent 10 }}
{{- else }}
httpGet:
path: {{ .Values.hub.livenessProbe.path }}
port: {{ .Values.hub.port }}
initialDelaySeconds: {{ .Values.hub.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.hub.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.hub.livenessProbe.timeoutSeconds }}
successThreshold: {{ .Values.hub.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.hub.livenessProbe.failureThreshold }}
scheme: {{ default (include "seleniumGrid.probe.httpGet.schema" .) .schema }}
path: {{ .path }}
port: {{ default ($.Values.hub.port) .port }}
{{- end }}
{{- if (ne (include "seleniumGrid.probe.settings" .) "{}") }}
{{- include "seleniumGrid.probe.settings" . | nindent 12 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.hub.readinessProbe.enabled }}
{{- with .Values.hub.readinessProbe }}
readinessProbe:
{{- if (ne (include "seleniumGrid.probe.fromUserDefine" .) "{}") }}
{{- include "seleniumGrid.probe.fromUserDefine" . | nindent 10 }}
{{- else }}
httpGet:
path: {{ .Values.hub.readinessProbe.path }}
port: {{ .Values.hub.port }}
initialDelaySeconds: {{ .Values.hub.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.hub.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.hub.readinessProbe.timeoutSeconds }}
successThreshold: {{ .Values.hub.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.hub.readinessProbe.failureThreshold }}
scheme: {{ default (include "seleniumGrid.probe.httpGet.schema" .) .schema }}
path: {{ .path }}
port: {{ default ($.Values.hub.port) .port }}
{{- end }}
{{- if (ne (include "seleniumGrid.probe.settings" .) "{}") }}
{{- include "seleniumGrid.probe.settings" . | nindent 12 }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.hub.livenessProbe.enabled }}
{{- with .Values.hub.livenessProbe }}
livenessProbe:
{{- if (ne (include "seleniumGrid.probe.fromUserDefine" .) "{}") }}
{{- include "seleniumGrid.probe.fromUserDefine" . | nindent 10 }}
{{- else }}
httpGet:
scheme: {{ default (include "seleniumGrid.probe.httpGet.schema" .) .schema }}
path: {{ .path }}
port: {{ default ($.Values.hub.port) .port }}
{{- end }}
{{- if (ne (include "seleniumGrid.probe.settings" .) "{}") }}
{{- include "seleniumGrid.probe.settings" . | nindent 12 }}
{{- end }}
{{- end }}
{{- end }}
env:
{{- with .Values.hub.subPath }}
Expand Down