From 1d63c1a94bbf3d8af6f1ee553f285ca535ec2806 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Tue, 8 Apr 2025 05:14:33 +0700 Subject: [PATCH] K8s: Add template for file browser video records service Signed-off-by: Viet Nguyen Duc --- charts/selenium-grid/CONFIGURATION.md | 40 ++++++ .../selenium-grid/templates/_nameHelpers.tpl | 7 + .../file-browser-deployment.yaml | 121 ++++++++++++++++++ .../video-manager/file-browser-ingress.yaml | 59 +++++++++ .../video-manager/file-browser-service.yaml | 44 +++++++ charts/selenium-grid/values.yaml | 94 ++++++++++++++ .../refValues/simplex-docker-desktop.yaml | 3 + 7 files changed, 368 insertions(+) create mode 100644 charts/selenium-grid/templates/video-manager/file-browser-deployment.yaml create mode 100644 charts/selenium-grid/templates/video-manager/file-browser-ingress.yaml create mode 100644 charts/selenium-grid/templates/video-manager/file-browser-service.yaml diff --git a/charts/selenium-grid/CONFIGURATION.md b/charts/selenium-grid/CONFIGURATION.md index 03cf5d3e39..71f80ce8fc 100644 --- a/charts/selenium-grid/CONFIGURATION.md +++ b/charts/selenium-grid/CONFIGURATION.md @@ -678,6 +678,46 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes | videoRecorder.extraVolumes | list | `[]` | Extra volumes for video recorder pod | | videoRecorder.s3 | object | `{"args":[],"command":[],"extraEnvironmentVariables":[],"imageName":"aws-cli","imagePullPolicy":"IfNotPresent","imageRegistry":"bitnami","imageTag":"latest","securityContext":{"runAsUser":0}}` | Container spec for the uploader if above it is defined as "uploader.name: s3" | | customLabels | object | `{}` | Custom labels for k8s resources | +| videoManager.enabled | bool | `false` | Enable video manager | +| videoManager.nameOverride | string | `""` | Override deployment name of video manager | +| videoManager.ingress.enabled | bool | `true` | Enable ingress resource to access the file browser | +| videoManager.ingress.annotations | string | `nil` | Annotations for file browser ingress resource | +| videoManager.ingress.paths | list | `[]` | Configure paths for file browser ingress resource | +| videoManager.imageRegistry | string | `"filebrowser"` | Registry to pull the image (this overwrites global.seleniumGrid.imageRegistry parameter) | +| videoManager.imageName | string | `"filebrowser"` | File browser image name | +| videoManager.imageTag | string | `"latest"` | File browser image tag (this overwrites global.seleniumGrid.imageTag parameter) | +| videoManager.imagePullPolicy | string | `"IfNotPresent"` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| videoManager.imagePullSecret | string | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) | +| videoManager.config.baseurl | string | `"recordings"` | Base URL use to access the file browser (e.g. http://public.ip/recordings) | +| videoManager.config.username | string | `""` | Username for the first user when using quick config (default "admin") | +| videoManager.config.password | string | `""` | Hashed password (bcrypt) for the first user when using quick config (default "admin") | +| videoManager.config.noauth | bool | `true` | Use the noauth auther when using quick setup | +| videoManager.extraEnvironmentVariables | list | `[]` | Specify extra environment variables for Router | +| videoManager.extraEnvFrom | list | `[]` | Specify extra environment variables from ConfigMap and Secret for Router | +| videoManager.affinity | object | `{}` | Specify affinity for router pods, this overwrites global.seleniumGrid.affinity parameter | +| videoManager.topologySpreadConstraints | list | `[]` | Specify topologySpreadConstraints for router pods, this overwrites global.seleniumGrid.topologySpreadConstraints parameter | +| videoManager.annotations | object | `{}` | Custom annotations for router pods | +| videoManager.port | int | `80` | Router container port | +| videoManager.nodePort | int | `30080` | Router expose NodePort | +| videoManager.startupProbe | object | `{}` | Startup probe settings | +| videoManager.readinessProbe | object | `{}` | Readiness probe settings | +| videoManager.livenessProbe | object | `{}` | Liveness probe settings | +| videoManager.lifecycle | object | `{}` | | +| videoManager.resources | object | `{"limits":{"cpu":"1","memory":"1Gi"},"requests":{"cpu":"0.1","memory":"128Mi"}}` | Resources for router container | +| videoManager.replicas | int | `1` | Number of replicas | +| videoManager.securityContext | object | `{}` | SecurityContext for router container | +| videoManager.serviceType | string | `"ClusterIP"` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | +| videoManager.clusterIP | string | `""` | Set specific clusterIP when serviceType is ClusterIP (see https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) | +| videoManager.externalName | string | `""` | Set specific externalName when serviceType is ExternalName (see https://kubernetes.io/docs/concepts/services-networking/service/#type-externalname) | +| videoManager.loadBalancerIP | string | `""` | Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) | +| videoManager.serviceAnnotations | object | `{}` | Custom annotations for router service | +| videoManager.serviceExternalTrafficPolicy | string | `""` | Set externalTrafficPolicy to Local or Cluster (see https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) | +| videoManager.serviceSessionAffinity | string | `""` | Set session affinity to None, ClientIP or ClientIPString | +| videoManager.tolerations | list | `[]` | Tolerations for router pods | +| videoManager.nodeSelector | object | `{}` | Node selector for router pods | +| videoManager.priorityClassName | string | `""` | Priority class name for router pods | +| videoManager.extraVolumeMounts | list | `[]` | | +| videoManager.extraVolumes | list | `[]` | Extra volumes for video recorder pod | | keda.additionalAnnotations | string | `nil` | Annotations for KEDA resources | | keda.http.timeout | int | `60000` | | | keda.webhooks | object | `{"enabled":false}` | Enable KEDA admission webhooks component | diff --git a/charts/selenium-grid/templates/_nameHelpers.tpl b/charts/selenium-grid/templates/_nameHelpers.tpl index cef0a0159c..bb81100898 100644 --- a/charts/selenium-grid/templates/_nameHelpers.tpl +++ b/charts/selenium-grid/templates/_nameHelpers.tpl @@ -232,6 +232,13 @@ Recorder ConfigMap fullname {{- tpl (default (include "seleniumGrid.component.name" (list "selenium-recorder-config" $)) .Values.recorderConfigMap.nameOverride) $ | trunc 63 | trimSuffix "-" -}} {{- end -}} +{{/* +Video manager fullname +*/}} +{{- define "seleniumGrid.videoManager.fullname" -}} +{{- tpl (default (include "seleniumGrid.component.name" (list "selenium-video-manager" $)) .Values.videoManager.nameOverride) $ | trunc 63 | trimSuffix "-" -}} +{{- end -}} + {{/* Uploader ConfigMap fullname */}} diff --git a/charts/selenium-grid/templates/video-manager/file-browser-deployment.yaml b/charts/selenium-grid/templates/video-manager/file-browser-deployment.yaml new file mode 100644 index 0000000000..dc67873fe1 --- /dev/null +++ b/charts/selenium-grid/templates/video-manager/file-browser-deployment.yaml @@ -0,0 +1,121 @@ +{{- if .Values.videoManager.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "seleniumGrid.videoManager.fullname" $ }} + namespace: {{ .Release.Namespace }} + labels: &app_labels + app: {{ template "seleniumGrid.videoManager.fullname" $ }} + app.kubernetes.io/name: {{ template "seleniumGrid.videoManager.fullname" $ }} + {{- include "seleniumGrid.commonLabels" . | nindent 4 }} + {{- with .Values.customLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + strategy: + {{- template "seleniumGrid.updateStrategy" (list $.Values.videoManager $.Values.global.seleniumGrid) }} + replicas: {{ max 1 ($.Values.videoManager.replicas | int) }} + revisionHistoryLimit: {{ .Values.global.seleniumGrid.revisionHistoryLimit }} + selector: + matchLabels: + app: {{ template "seleniumGrid.videoManager.fullname" $ }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: *app_labels + {{- with .Values.videoManager.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} + serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} + containers: + - name: file-browser + image: {{ printf "%s/%s:%s" .Values.videoManager.imageRegistry .Values.videoManager.imageName .Values.videoManager.imageTag }} + imagePullPolicy: {{ .Values.videoManager.imagePullPolicy }} + env: + {{- with .Values.videoManager.config.baseurl }} + - name: FB_BASEURL + value: {{ . | quote }} + {{- end }} + {{- with .Values.videoManager.config.username }} + - name: FB_USERNAME + value: {{ . | quote }} + {{- end }} + {{- with .Values.videoManager.config.password }} + - name: FB_PASSWORD + value: {{ . | quote }} + {{- end }} + {{- if .Values.videoManager.config.noauth }} + - name: FB_NOAUTH + value: "true" + {{- end }} + {{- with .Values.videoManager.extraEnvironmentVariables }} + {{- tpl (toYaml .) $ | nindent 12 }} + {{- end }} + {{- with .Values.videoManager.extraEnvFrom }} + envFrom: {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.videoManager.extraVolumeMounts }} + {{- tpl (toYaml .) $ | nindent 12 }} + {{- else }} + - name: srv + mountPath: /srv + subPath: srv + {{- end }} + ports: + - containerPort: {{ .Values.videoManager.port }} + protocol: TCP + {{- with .Values.videoManager.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.videoManager.securityContext }} + securityContext: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.videoManager.startupProbe }} + startupProbe: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.videoManager.livenessProbe }} + livenessProbe: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.videoManager.lifecycle }} + lifecycle: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.videoManager.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.global.seleniumGrid.affinity .Values.videoManager.affinity }} + {{- $affinityYaml := default .Values.global.seleniumGrid.affinity .Values.videoManager.affinity }} + affinity: {{- toYaml $affinityYaml | nindent 8 }} + {{- end }} + {{- if or .Values.global.seleniumGrid.topologySpreadConstraints .Values.videoManager.topologySpreadConstraints }} + {{- $topologySpreadConstraints := default .Values.global.seleniumGrid.topologySpreadConstraints .Values.videoManager.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $constraint := $topologySpreadConstraints }} + - {{ toYaml $constraint | nindent 10 | trim }} + {{- if not $constraint.labelSelector }} + labelSelector: + matchLabels: + app: {{ template "seleniumGrid.videoManager.fullname" $ }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.videoManager.tolerations }} + tolerations: {{ toYaml . | nindent 6 }} + {{- end }} + {{- if or .Values.global.seleniumGrid.imagePullSecret .Values.videoManager.imagePullSecret }} + imagePullSecrets: + - name: {{ default .Values.global.seleniumGrid.imagePullSecret .Values.videoManager.imagePullSecret }} + {{- end }} + {{- with .Values.videoManager.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + volumes: + {{- if .Values.videoManager.extraVolumes }} + {{ tpl (toYaml .) $ | nindent 8 }} + {{- else }} + - name: srv + emptyDir: {} + {{- end }} +{{- end }} diff --git a/charts/selenium-grid/templates/video-manager/file-browser-ingress.yaml b/charts/selenium-grid/templates/video-manager/file-browser-ingress.yaml new file mode 100644 index 0000000000..98d41713d1 --- /dev/null +++ b/charts/selenium-grid/templates/video-manager/file-browser-ingress.yaml @@ -0,0 +1,59 @@ +{{- if and .Values.videoManager.enabled .Values.videoManager.ingress.enabled .Values.ingress.enabled }} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ template "seleniumGrid.videoManager.fullname" $ }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "seleniumGrid.commonLabels" . | nindent 4 }} + {{- with .Values.customLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.videoManager.ingress.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if and (or .Values.tls.enabled .Values.tls.ingress.generateTLS) (tpl .Values.ingress.hostname $) (not .Values.ingress.tls) }} + tls: + - hosts: + - {{ tpl .Values.ingress.hostname $ }} + secretName: {{ include "seleniumGrid.tls.fullname" $ | quote }} + {{- else if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ tpl . $ }} + {{- end }} + secretName: {{ tpl (default (include "seleniumGrid.tls.fullname" $) .secretName) $ | quote }} + {{- end }} + {{- end }} + rules: + {{- if $.Values.ingress.hostname }} + - host: {{ tpl $.Values.ingress.hostname $ }} + http: + {{- else }} + - http: + {{- end }} + paths: + {{- if .Values.videoManager.ingress.paths }} + {{- tpl (toYaml . | nindent 10) $ }} + {{- else }} + - backend: + service: + name: {{ include "seleniumGrid.videoManager.fullname" $ | quote }} + port: + number: 80 + path: {{ printf "/%s" $.Values.videoManager.config.baseurl | quote }} + pathType: Prefix + {{- end }} +{{- end }} diff --git a/charts/selenium-grid/templates/video-manager/file-browser-service.yaml b/charts/selenium-grid/templates/video-manager/file-browser-service.yaml new file mode 100644 index 0000000000..8a705ef0e8 --- /dev/null +++ b/charts/selenium-grid/templates/video-manager/file-browser-service.yaml @@ -0,0 +1,44 @@ +{{- if .Values.videoManager.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "seleniumGrid.videoManager.fullname" $ }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "seleniumGrid.videoManager.fullname" $ }} + {{- include "seleniumGrid.commonLabels" . | nindent 4 }} + {{- with .Values.customLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.videoManager.serviceAnnotations }} + annotations: {{- toYaml . | nindent 4 }} +{{- end }} +spec: + selector: + app: {{ template "seleniumGrid.videoManager.fullname" $ }} + app.kubernetes.io/instance: {{ .Release.Name }} + type: {{ .Values.videoManager.serviceType }} + {{- if and (eq .Values.videoManager.serviceType "ClusterIP") ( .Values.videoManager.clusterIP ) }} + clusterIP: {{ .Values.videoManager.clusterIP }} + {{- end }} + {{- if and (eq .Values.videoManager.serviceType "ExternalName") ( .Values.videoManager.externalName ) }} + externalName: {{ .Values.videoManager.externalName }} + {{- end }} + {{- if and (eq .Values.videoManager.serviceType "LoadBalancer") (.Values.videoManager.loadBalancerIP) }} + loadBalancerIP: {{ .Values.videoManager.loadBalancerIP }} + {{- end }} + ports: + - name: web + protocol: TCP + port: {{ .Values.videoManager.port }} + targetPort: {{ .Values.videoManager.port }} + {{- if and (eq $.Values.videoManager.serviceType "NodePort") $.Values.videoManager.nodePort }} + nodePort: {{ $.Values.videoManager.nodePort }} + {{- end }} + {{- with .Values.videoManager.serviceExternalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + {{- with .Values.videoManager.serviceSessionAffinity }} + sessionAffinity: {{ . }} + {{- end }} +{{- end }} diff --git a/charts/selenium-grid/values.yaml b/charts/selenium-grid/values.yaml index bbb31ec12c..02156a0eca 100644 --- a/charts/selenium-grid/values.yaml +++ b/charts/selenium-grid/values.yaml @@ -2030,6 +2030,100 @@ videoRecorder: # -- Custom labels for k8s resources customLabels: {} +videoManager: + # -- Enable video manager + enabled: false + # -- Override deployment name of video manager + nameOverride: "" + ingress: + # -- Enable ingress resource to access the file browser + enabled: true + # -- Annotations for file browser ingress resource + annotations: + # -- Configure paths for file browser ingress resource + paths: [] + # -- Registry to pull the image (this overwrites global.seleniumGrid.imageRegistry parameter) + imageRegistry: "filebrowser" + # -- File browser image name + imageName: "filebrowser" + # -- File browser image tag (this overwrites global.seleniumGrid.imageTag parameter) + imageTag: "latest" + # -- Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) + imagePullPolicy: IfNotPresent + # -- Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) + imagePullSecret: "" + config: + # -- Base URL use to access the file browser (e.g. http://public.ip/recordings) + baseurl: "recordings" + # -- Username for the first user when using quick config (default "admin") + username: "" + # -- Hashed password (bcrypt) for the first user when using quick config (default "admin") + password: "" + # -- Use the noauth auther when using quick setup + noauth: true + # -- Specify extra environment variables for Router + extraEnvironmentVariables: [] + # -- Specify extra environment variables from ConfigMap and Secret for Router + extraEnvFrom: [] + # -- Specify affinity for router pods, this overwrites global.seleniumGrid.affinity parameter + affinity: {} + # -- Specify topologySpreadConstraints for router pods, this overwrites global.seleniumGrid.topologySpreadConstraints parameter + topologySpreadConstraints: [] + # -- Custom annotations for router pods + annotations: {} + # -- Router container port + port: 80 + # -- Router expose NodePort + nodePort: 30080 + # -- Startup probe settings + startupProbe: {} + # -- Readiness probe settings + readinessProbe: {} + # -- Liveness probe settings + livenessProbe: {} + lifecycle: {} + # -- Resources for router container + resources: + requests: + cpu: "0.1" + memory: "128Mi" + limits: + cpu: "1" + memory: "1Gi" + # -- Number of replicas + replicas: 1 + # -- SecurityContext for router container + securityContext: { } + # -- Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) + serviceType: ClusterIP + # -- Set specific clusterIP when serviceType is ClusterIP (see https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) + clusterIP: "" + # -- Set specific externalName when serviceType is ExternalName (see https://kubernetes.io/docs/concepts/services-networking/service/#type-externalname) + externalName: "" + # -- Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) + loadBalancerIP: "" + # -- Custom annotations for router service + serviceAnnotations: { } + # -- Set externalTrafficPolicy to Local or Cluster (see https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) + serviceExternalTrafficPolicy: "" + # -- Set session affinity to None, ClientIP or ClientIPString + serviceSessionAffinity: "" + # -- Tolerations for router pods + tolerations: [ ] + # -- Node selector for router pods + nodeSelector: { } + # -- Priority class name for router pods + priorityClassName: "" + extraVolumeMounts: [ ] + # - name: srv + # mountPath: /srv + # subPath: srv + # -- Extra volumes for video recorder pod + extraVolumes: [ ] + # - name: srv + # persistentVolumeClaim: + # claimName: video-pv-claim + # Configuration for dependency chart keda keda: # enabled: false diff --git a/tests/charts/refValues/simplex-docker-desktop.yaml b/tests/charts/refValues/simplex-docker-desktop.yaml index 783346e3f4..9ac3ecc791 100644 --- a/tests/charts/refValues/simplex-docker-desktop.yaml +++ b/tests/charts/refValues/simplex-docker-desktop.yaml @@ -68,6 +68,9 @@ edgeNode: videoRecorder: enabled: true +videoManager: + enabled: true + ingress-nginx: controller: hostPort: