diff --git a/README.md b/README.md index ead6350..c2512e5 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,114 @@ # Keep Helm Chart The Keep Helm Chart provides a convenient way to deploy and manage Keep on Kubernetes using Helm, a package manager for Kubernetes applications. +# Prerequisites + +## Ingress Controller (Recommended) +The recommended way to deploy Keep is with ingress-nginx that serves as a single ingress for all services (backend, frontend, and websocket server). + +1. Install ingress-nginx: +```bash +helm upgrade --install ingress-nginx ingress-nginx \ + --repo https://kubernetes.github.io/ingress-nginx \ + --namespace ingress-nginx --create-namespace +``` + +2. Enable snippet annotations: +The ingress controller must have snippet annotations enabled. You can enable it during installation: +```bash +helm upgrade --install ingress-nginx ingress-nginx \ + --repo https://kubernetes.github.io/ingress-nginx \ + --namespace ingress-nginx --create-namespace \ + --set controller.config.allow-snippet-annotations=true +``` + +To verify if snippet annotations are enabled: +```bash +# Check the configmap +kubectl get configmap -n ingress-nginx ingress-nginx-controller -o yaml | grep allow-snippet-annotations + +# Or check the controller logs +kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller | grep "allow-snippet-annotations" +``` + # Installation -The easiest way to install Keep with Helm is with the following command: +## Option 1: With ingress-nginx (Recommended) ```bash -# add the Helm repository +# Add the Helm repository helm repo add keephq https://keephq.github.io/helm-charts -# pull the latest version of the chart -helm pull keephq/keep -# install the chart + +# Install Keep with ingress enabled (default nginx) +helm install keep keephq/keep -n keep --create-namespace +``` + +## Option 2: Without ingress-nginx (Not recommended) +Keep can be deployed without ingress-nginx, but this will create three separate ingresses (one for each service): +```bash +# Add the Helm repository +helm repo add keephq https://keephq.github.io/helm-charts + +# Install Keep without ingress helm install keep keephq/keep ``` +# Post-Installation + +## With ingress-nginx +Your Keep installation will be available at the ingress host you configured. Check your ingress status: +```bash +kubectl get ingress +``` + +## Without ingress-nginx +You'll need to set up port forwarding to access the services: +```bash +# Expose the UI locally +kubectl port-forward svc/keep-frontend 3000:3000 & + +# Expose the Backend locally +kubectl port-forward svc/keep-backend 8080:8080 & + +# Export websocket server (optional) +kubectl port-forward svc/keep-websocket 6001:6001 & +``` + # Uninstallation -`helm uninstall keep` +```bash +helm uninstall keep +``` # Configuration To view supported configuration, see [this](charts/keep/README.md). -# Openshift -Keep's Helm Chart also supports installation on Openshift. -Simply set up the keys under frontend(/backend).route: -- route.host: your desired hostname +# Platform-Specific Instructions -# Local Kubernetes -For local kubernetes without external IP (such as NodePort or LoadBalancer), you'll need to run port forwarding: +## Openshift +Keep's Helm Chart supports installation on Openshift. +Configure the route settings under frontend(/backend).route: +```yaml +frontend: + route: + host: your-desired-hostname +``` -## Port forward -```bash +## Local Kubernetes +For local Kubernetes clusters without external IP (such as when using NodePort or LoadBalancer): -# expose the UI locally -kubectl port-forward svc/keep-frontend 3000:3000 & \ -# export websocket server (optional) -kubectl port-forward svc/keep-websocket 6001:6001 & -``` +1. If using ingress-nginx, ensure your ingress controller is properly configured for local development +2. If not using ingress-nginx, use the port forwarding method described in the "Without ingress-nginx" section + +# Troubleshooting + +## Common Issues +1. Ingress not working + - Verify ingress-nginx is properly installed + - Check if snippet annotations are enabled + - Verify ingress configuration with `kubectl describe ingress` + +2. WebSocket connection issues + - Ensure the websocket service is running + - Check ingress configuration for proper WebSocket headers + - Verify connectivity using `curl` or browser developer tools + +For more detailed configuration options and troubleshooting, refer to the [documentation](charts/keep/README.md). \ No newline at end of file diff --git a/charts/keep/Chart.yaml b/charts/keep/Chart.yaml index 4323014..a0ccb01 100644 --- a/charts/keep/Chart.yaml +++ b/charts/keep/Chart.yaml @@ -1,10 +1,10 @@ apiVersion: v2 name: keep -version: 0.1.24 +version: 0.1.25 description: Keep Helm Chart type: application icon: https://platform.keephq.dev/_next/image?url=%2Fkeep.png&w=48&q=75 -appVersion: 0.26.1 +appVersion: 0.27.0 deprecated: false annotations: app: keep diff --git a/charts/keep/README.md b/charts/keep/README.md index 7b603ee..5e1bb17 100644 --- a/charts/keep/README.md +++ b/charts/keep/README.md @@ -1,6 +1,6 @@ # keep -![Version: 0.1.18](https://img.shields.io/badge/Version-0.1.18-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.25.3](https://img.shields.io/badge/AppVersion-0.25.3-informational?style=flat-square) +![Version: 0.1.25](https://img.shields.io/badge/Version-0.1.25-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.27.0](https://img.shields.io/badge/AppVersion-0.27.0-informational?style=flat-square) Keep Helm Chart @@ -27,6 +27,13 @@ Keep Helm Chart | backend.autoscaling.minReplicas | int | `1` | | | backend.autoscaling.targetCPUUtilizationPercentage | int | `80` | | | backend.autoscaling.targetMemoryUtilizationPercentage | int | `80` | | +| backend.backendConfig.healthCheck.checkIntervalSec | int | `30` | | +| backend.backendConfig.healthCheck.healthyThreshold | int | `1` | | +| backend.backendConfig.healthCheck.path | string | `"/docs"` | | +| backend.backendConfig.healthCheck.port | int | `8080` | | +| backend.backendConfig.healthCheck.timeoutSec | int | `10` | | +| backend.backendConfig.healthCheck.type | string | `"HTTP"` | | +| backend.backendConfig.healthCheck.unhealthyThreshold | int | `3` | | | backend.databaseConnectionStringFromSecret.enabled | bool | `false` | | | backend.databaseConnectionStringFromSecret.secretKey | string | `""` | | | backend.databaseConnectionStringFromSecret.secretName | string | `""` | | @@ -37,18 +44,16 @@ Keep Helm Chart | backend.env[1].value | string | `"k8s"` | | | backend.env[2].name | string | `"PORT"` | | | backend.env[2].value | string | `"8080"` | | -| backend.env[3].name | string | `"SECRET_MANAGER_DIRECTORY"` | | -| backend.env[3].value | string | `"/state"` | | -| backend.env[4].name | string | `"PUSHER_APP_ID"` | | -| backend.env[4].value | int | `1` | | -| backend.env[5].name | string | `"PUSHER_APP_KEY"` | | -| backend.env[5].value | string | `"keepappkey"` | | -| backend.env[6].name | string | `"PUSHER_APP_SECRET"` | | -| backend.env[6].value | string | `"keepappsecret"` | | -| backend.env[7].name | string | `"PUSHER_HOST"` | | -| backend.env[7].value | string | `"keep-websocket"` | | -| backend.env[8].name | string | `"PUSHER_PORT"` | | -| backend.env[8].value | int | `6001` | | +| backend.env[3].name | string | `"PUSHER_APP_ID"` | | +| backend.env[3].value | int | `1` | | +| backend.env[4].name | string | `"PUSHER_APP_KEY"` | | +| backend.env[4].value | string | `"keepappkey"` | | +| backend.env[5].name | string | `"PUSHER_APP_SECRET"` | | +| backend.env[5].value | string | `"keepappsecret"` | | +| backend.env[6].name | string | `"PUSHER_HOST"` | | +| backend.env[6].value | string | `"keep-websocket"` | | +| backend.env[7].name | string | `"PUSHER_PORT"` | | +| backend.env[7].value | int | `6001` | | | backend.extraInitContainers | list | `[]` | | | backend.extraVolumeMounts | list | `[]` | | | backend.extraVolumes | list | `[]` | | @@ -59,15 +64,7 @@ Keep Helm Chart | backend.healthCheck.probes.readinessProbe.tcpSocket.port | int | `8080` | | | backend.image.pullPolicy | string | `"Always"` | | | backend.image.repository | string | `"us-central1-docker.pkg.dev/keephq/keep/keep-api"` | | -| backend.image.tag | string | `"{{ .Chart.AppVersion }}"` | | | backend.imagePullSecrets | list | `[]` | | -| backend.ingress.annotations | object | `{}` | | -| backend.ingress.className | string | `""` | | -| backend.ingress.enabled | bool | `true` | | -| backend.ingress.hosts[0].host | string | `"chart-example-backend.local"` | | -| backend.ingress.hosts[0].paths[0].path | string | `"/"` | | -| backend.ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | -| backend.ingress.tls | list | `[]` | | | backend.nodeSelector | object | `{}` | | | backend.openAiApi.enabled | bool | `false` | | | backend.openAiApi.openAiApiKey | string | `""` | | @@ -126,31 +123,26 @@ Keep Helm Chart | frontend.autoscaling.minReplicas | int | `1` | | | frontend.autoscaling.targetCPUUtilizationPercentage | int | `80` | | | frontend.autoscaling.targetMemoryUtilizationPercentage | int | `80` | | +| frontend.backendConfig.healthCheck.checkIntervalSec | int | `30` | | +| frontend.backendConfig.healthCheck.healthyThreshold | int | `1` | | +| frontend.backendConfig.healthCheck.path | string | `"/signin"` | | +| frontend.backendConfig.healthCheck.port | int | `3000` | | +| frontend.backendConfig.healthCheck.timeoutSec | int | `10` | | +| frontend.backendConfig.healthCheck.type | string | `"HTTP"` | | +| frontend.backendConfig.healthCheck.unhealthyThreshold | int | `3` | | | frontend.enabled | bool | `true` | | | frontend.env[0].name | string | `"NEXTAUTH_SECRET"` | | | frontend.env[0].value | string | `"secret"` | | -| frontend.env[10].name | string | `"PUSHER_PORT"` | | -| frontend.env[10].value | int | `6001` | | -| frontend.env[11].name | string | `"PUSHER_APP_KEY"` | | -| frontend.env[11].value | string | `"keepappkey"` | | -| frontend.env[1].name | string | `"NEXTAUTH_URL"` | | -| frontend.env[1].value | string | `"http://localhost:3000"` | | -| frontend.env[2].name | string | `"API_URL"` | | -| frontend.env[2].value | string | `"http://keep-backend:8080"` | | -| frontend.env[3].name | string | `"NEXT_PUBLIC_API_URL"` | | -| frontend.env[3].value | string | `""` | | -| frontend.env[4].name | string | `"NEXT_PUBLIC_POSTHOG_KEY"` | | -| frontend.env[4].value | string | `"phc_muk9qE3TfZsX3SZ9XxX52kCGJBclrjhkP9JxAQcm1PZ"` | | -| frontend.env[5].name | string | `"NEXT_PUBLIC_POSTHOG_HOST"` | | -| frontend.env[5].value | string | `"https://app.posthog.com"` | | -| frontend.env[6].name | string | `"ENV"` | | -| frontend.env[6].value | string | `"development"` | | -| frontend.env[7].name | string | `"NODE_ENV"` | | -| frontend.env[7].value | string | `"development"` | | -| frontend.env[8].name | string | `"HOSTNAME"` | | -| frontend.env[8].value | string | `"0.0.0.0"` | | -| frontend.env[9].name | string | `"PUSHER_HOST"` | | -| frontend.env[9].value | string | `"keep-websocket.default.svc.cluster.local"` | | +| frontend.env[1].name | string | `"VERCEL"` | | +| frontend.env[1].value | int | `1` | | +| frontend.env[2].name | string | `"ENV"` | | +| frontend.env[2].value | string | `"development"` | | +| frontend.env[3].name | string | `"NODE_ENV"` | | +| frontend.env[3].value | string | `"development"` | | +| frontend.env[4].name | string | `"HOSTNAME"` | | +| frontend.env[4].value | string | `"0.0.0.0"` | | +| frontend.env[5].name | string | `"PUSHER_APP_KEY"` | | +| frontend.env[5].value | string | `"keepappkey"` | | | frontend.healthCheck.enabled | bool | `false` | | | frontend.healthCheck.probes.livenessProbe.httpGet.path | string | `"/"` | | | frontend.healthCheck.probes.livenessProbe.httpGet.port | string | `"http"` | | @@ -158,15 +150,7 @@ Keep Helm Chart | frontend.healthCheck.probes.readinessProbe.httpGet.port | string | `"http"` | | | frontend.image.pullPolicy | string | `"Always"` | | | frontend.image.repository | string | `"us-central1-docker.pkg.dev/keephq/keep/keep-ui"` | | -| frontend.image.tag | string | `"{{ .Chart.AppVersion }}"` | | | frontend.imagePullSecrets | list | `[]` | | -| frontend.ingress.annotations | object | `{}` | | -| frontend.ingress.className | string | `""` | | -| frontend.ingress.enabled | bool | `true` | | -| frontend.ingress.hosts[0].host | string | `"chart-example.local"` | | -| frontend.ingress.hosts[0].paths[0].path | string | `"/"` | | -| frontend.ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | -| frontend.ingress.tls | list | `[]` | | | frontend.nodeSelector | object | `{}` | | | frontend.podAnnotations | object | `{}` | | | frontend.podSecurityContext | object | `{}` | | @@ -185,8 +169,28 @@ Keep Helm Chart | frontend.serviceAccount.name | string | `""` | | | frontend.tolerations | list | `[]` | | | fullnameOverride | string | `""` | | +| global.ingress.annotations | object | `{}` | | +| global.ingress.backendPrefix | string | `"/v2"` | | +| global.ingress.className | string | `"nginx"` | | +| global.ingress.enabled | bool | `true` | | +| global.ingress.frontendPrefix | string | `"/"` | | +| global.ingress.hosts | list | `[]` | | +| global.ingress.tls | list | `[]` | | +| global.ingress.websocketPrefix | string | `"/websocket"` | | +| ingress-nginx.controller.admissionWebhooks.certManager.enabled | bool | `false` | | +| ingress-nginx.controller.admissionWebhooks.failurePolicy | string | `"Ignore"` | | +| ingress-nginx.controller.admissionWebhooks.patch.enabled | bool | `true` | | +| ingress-nginx.controller.admissionWebhooks.patch.image.pullPolicy | string | `"IfNotPresent"` | | +| ingress-nginx.controller.allowSnippetAnnotations | bool | `true` | | +| ingress-nginx.controller.service.annotations | object | `{}` | | +| ingress-nginx.controller.service.enabled | bool | `true` | | +| ingress-nginx.controller.service.ports.http | int | `80` | | +| ingress-nginx.controller.service.ports.https | int | `443` | | +| ingress-nginx.controller.service.type | string | `"LoadBalancer"` | | +| ingress-nginx.enabled | bool | `true` | | +| isGKE | bool | `false` | | | nameOverride | string | `""` | | -| namespace | string | `"default"` | | +| namespace | string | `"keep"` | | | serviceAccount.annotations | object | `{}` | | | serviceAccount.create | bool | `true` | | | serviceAccount.name | string | `""` | | @@ -197,14 +201,18 @@ Keep Helm Chart | websocket.autoscaling.targetCPUUtilizationPercentage | int | `80` | | | websocket.autoscaling.targetMemoryUtilizationPercentage | int | `80` | | | websocket.enabled | bool | `true` | | -| websocket.env[0].name | string | `"SOKETI_USER_AUTHENTICATION_TIMEOUT"` | | -| websocket.env[0].value | int | `3000` | | -| websocket.env[1].name | string | `"SOKETI_DEFAULT_APP_ID"` | | -| websocket.env[1].value | int | `1` | | -| websocket.env[2].name | string | `"SOKETI_DEFAULT_APP_KEY"` | | -| websocket.env[2].value | string | `"keepappkey"` | | -| websocket.env[3].name | string | `"SOKETI_DEFAULT_APP_SECRET"` | | -| websocket.env[3].value | string | `"keepappsecret"` | | +| websocket.env[0].name | string | `"SOKETI_HOST"` | | +| websocket.env[0].value | string | `"0.0.0.0"` | | +| websocket.env[1].name | string | `"SOKETI_DEBUG"` | | +| websocket.env[1].value | string | `"1"` | | +| websocket.env[2].name | string | `"SOKETI_USER_AUTHENTICATION_TIMEOUT"` | | +| websocket.env[2].value | int | `3000` | | +| websocket.env[3].name | string | `"SOKETI_DEFAULT_APP_ID"` | | +| websocket.env[3].value | int | `1` | | +| websocket.env[4].name | string | `"SOKETI_DEFAULT_APP_KEY"` | | +| websocket.env[4].value | string | `"keepappkey"` | | +| websocket.env[5].name | string | `"SOKETI_DEFAULT_APP_SECRET"` | | +| websocket.env[5].value | string | `"keepappsecret"` | | | websocket.healthCheck.enabled | bool | `false` | | | websocket.healthCheck.probes.livenessProbe.httpGet.path | string | `"/"` | | | websocket.healthCheck.probes.livenessProbe.httpGet.port | string | `"http"` | | @@ -219,6 +227,10 @@ Keep Helm Chart | websocket.podSecurityContext | object | `{}` | | | websocket.replicaCount | int | `1` | | | websocket.resources | object | `{}` | | +| websocket.route.enabled | bool | `false` | | +| websocket.route.host | string | `"chart-example.local"` | | +| websocket.route.tls | list | `[]` | | +| websocket.route.wildcardPolicy | string | `"None"` | | | websocket.securityContext | object | `{}` | | | websocket.service.port | int | `6001` | | | websocket.service.type | string | `"ClusterIP"` | | diff --git a/charts/keep/templates/_helpers.tpl b/charts/keep/templates/_helpers.tpl index a454d76..b108951 100644 --- a/charts/keep/templates/_helpers.tpl +++ b/charts/keep/templates/_helpers.tpl @@ -60,3 +60,118 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Helper function to find an environment variable in the list +*/}} +{{- define "keep.findEnvVar" -}} +{{- $name := index . 0 -}} +{{- $root := index . 1 -}} +{{- if and $root.Values.frontend $root.Values.frontend.env -}} + {{- range $root.Values.frontend.env -}} + {{- if eq .name $name -}} + {{- .value -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Helper function for websocket host (relative) +*/}} +{{- define "keep.websocketPrefix" -}} +{{- coalesce .Values.global.ingress.websocketPrefix "/websocket" -}} +{{- end -}} + +{{/* +Helper function for backend host (relative) +*/}} +{{- define "keep.backendPrefix" -}} +{{- coalesce .Values.global.ingress.backendPrefix "/api" -}} +{{- end -}} + +{{/* +Helper function for frontend host (relative) +*/}} +{{- define "keep.frontendPrefix" -}} +{{- coalesce .Values.global.ingress.frontendPrefix "/" -}} +{{- end -}} + +{{/* +Helper function for PUSHER_HOST +*/}} +{{- define "keep.pusherHost" -}} +{{- $pusherHost := include "keep.findEnvVar" (list "PUSHER_HOST" .) -}} +{{- if $pusherHost -}} + {{- $pusherHost -}} +{{- else -}} + {{- include "keep.websocketPrefix" . -}} +{{- end -}} +{{- end -}} + +{{/* +Helper function for API_URL for the frontend +*/}} +{{- define "keep.apiUrlClient" -}} +{{- $apiUrlClient := include "keep.findEnvVar" (list "API_URL_CLIENT" .) -}} +{{- if $apiUrlClient -}} + {{- $apiUrlClient -}} +{{- else -}} + {{- include "keep.backendPrefix" . -}} +{{- end -}} +{{- end -}} + +{{/* +Expand the namespace of the release. +*/}} +{{- define "keep.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Helper function for getting the full URL (with protocol and host) +*/}} +{{- define "keep.fullUrl" -}} +{{- if and .Values.global.ingress.enabled .Values.global.ingress.hosts -}} + {{- if .Values.global.ingress.tls -}} + {{- $host := index .Values.global.ingress.hosts 0 -}} + {{- printf "https://%s" $host.host -}} + {{- else -}} + {{- $host := index .Values.global.ingress.hosts 0 -}} + {{- printf "http://%s" $host.host -}} + {{- end -}} +{{- else -}} + {{- print "http://localhost:3000" -}} +{{- end -}} +{{- end -}} + +{{/* +Helper function for NEXTAUTH_URL +*/}} +{{- define "keep.nextAuthUrl" -}} +{{- $nextAuthUrl := include "keep.findEnvVar" (list "NEXTAUTH_URL" .) -}} +{{- if $nextAuthUrl -}} + {{- $nextAuthUrl -}} +{{- else -}} + {{- if .Values.global.ingress.enabled -}} + {{- include "keep.fullUrl" . -}} + {{- else -}} + {{- print "http://localhost:3000" -}} + {{- end -}} +{{- end -}} +{{- end -}} + + +{{/* +Helper function for KEEP_API_URL that handles both relative and absolute URLs +*/}} +{{- define "keep.apiUrl" -}} +{{- $apiUrlClient := include "keep.apiUrlClient" . -}} +{{- /* Check if the URL starts with http:// or https:// */ -}} +{{- if or (hasPrefix "http://" $apiUrlClient) (hasPrefix "https://" $apiUrlClient) -}} + {{- $apiUrlClient -}} +{{- else -}} + {{- include "keep.fullUrl" . -}}{{- $apiUrlClient -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/keep/templates/backend-ingress.yaml b/charts/keep/templates/backend-ingress.yaml deleted file mode 100644 index 9f6d08d..0000000 --- a/charts/keep/templates/backend-ingress.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{{- if and .Values.backend.enabled .Values.backend.ingress.enabled -}} -{{- $fullName := include "keep.fullname" . -}} -{{- $svcPort := .Values.backend.service.port -}} -{{- if and .Values.backend.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.backend.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.backend.ingress.annotations "kubernetes.io/ingress.class" .Values.backend.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }}-backend - labels: - {{- include "keep.labels" . | nindent 4 }} - {{- with .Values.backend.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.backend.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.backend.ingress.className }} - {{- end }} - {{- if .Values.backend.ingress.tls }} - tls: - {{- range .Values.backend.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.backend.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }}-backend - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }}-backend - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/charts/keep/templates/backend.yaml b/charts/keep/templates/backend.yaml index b528f8b..8b03192 100644 --- a/charts/keep/templates/backend.yaml +++ b/charts/keep/templates/backend.yaml @@ -48,6 +48,8 @@ spec: containerPort: {{ .Values.backend.service.port }} protocol: TCP env: + - name: KEEP_API_URL + value: {{ include "keep.apiUrl" . | quote }} {{- range .Values.backend.env }} - name: {{ .name }} {{- if .secretKeyRef }} diff --git a/charts/keep/templates/db-pvc.yaml b/charts/keep/templates/db-pvc.yaml index 6ab6274..0c5b2dd 100644 --- a/charts/keep/templates/db-pvc.yaml +++ b/charts/keep/templates/db-pvc.yaml @@ -1,13 +1,24 @@ -{{- if and .Values.database.enabled .Values.database.pvc.enabled -}} +{{- if and .Values.database.enabled .Values.database.pvc.enabled -}} +{{- $fullName := include "keep.fullname" . -}} +{{- $pvcName := printf "%s-pvc" $fullName -}} +{{- $existingPvc := lookup "v1" "PersistentVolumeClaim" .Release.Namespace $pvcName -}} apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ include "keep.fullname" . }}-pvc + name: {{ $pvcName }} spec: accessModes: - ReadWriteOnce + {{- if $existingPvc }} + # Use existing PVC spec + {{- toYaml $existingPvc.spec | nindent 2 }} + {{- else }} + # Define new PVC spec + {{- if .Values.database.pvc.storageClass }} storageClassName: {{ .Values.database.pvc.storageClass }} + {{- end }} resources: requests: storage: {{ .Values.database.pvc.size }} + {{- end }} {{- end }} \ No newline at end of file diff --git a/charts/keep/templates/delete-secret-job.yaml b/charts/keep/templates/delete-secret-job.yaml index e1fd325..9de20b7 100644 --- a/charts/keep/templates/delete-secret-job.yaml +++ b/charts/keep/templates/delete-secret-job.yaml @@ -16,9 +16,9 @@ spec: - /bin/sh - -c - > - secrets=$(kubectl get secrets -n {{ .Values.Namespace }} -o name | grep '^secret/keep-'); + secrets=$(kubectl get secrets -n {{ include "keep.namespace" . }} -o name | grep '^secret/keep-'); if [ -n "$secrets" ]; then - echo "$secrets" | xargs kubectl delete -n {{ .Values.Namespace }}; + echo "$secrets" | xargs kubectl delete -n {{ include "keep.namespace" . }}; else echo "No matching secrets found to delete."; fi diff --git a/charts/keep/templates/frontend-ingress.yaml b/charts/keep/templates/frontend-ingress.yaml deleted file mode 100644 index c113f3f..0000000 --- a/charts/keep/templates/frontend-ingress.yaml +++ /dev/null @@ -1,64 +0,0 @@ -{{- if and .Values.frontend.enabled .Values.frontend.ingress.enabled -}} -{{- $fullName := include "keep.fullname" . -}} -{{- $svcPort := .Values.frontend.service.port -}} -{{- if and .Values.frontend.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.frontend.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.frontend.ingress.annotations "kubernetes.io/ingress.class" .Values.frontend.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }}-frontend - labels: - {{- include "keep.labels" . | nindent 4 }} - {{- with .Values.frontend.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.frontend.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.frontend.ingress.className }} - {{- end }} - {{- if .Values.frontend.ingress.tls }} - tls: - {{- range .Values.frontend.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.frontend.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }}-frontend - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }}-frontend - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} - {{- if .Values.frontend.extraIngress -}} - {{ toYaml .Values.frontend.extraIngress | nindent 2 }} - {{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/keep/templates/frontend.yaml b/charts/keep/templates/frontend.yaml index cc2f509..00fa9df 100644 --- a/charts/keep/templates/frontend.yaml +++ b/charts/keep/templates/frontend.yaml @@ -42,10 +42,21 @@ spec: containerPort: {{ .Values.frontend.service.port }} protocol: TCP env: + - name: PUSHER_HOST + value: {{ include "keep.pusherHost" . | quote }} + - name: API_URL_CLIENT + value: {{ include "keep.apiUrlClient" . | quote }} + - name: NEXTAUTH_URL + value: {{ include "keep.nextAuthUrl" . | quote }} {{- range .Values.frontend.env }} + {{- if and + (ne .name "PUSHER_HOST") + (ne .name "API_URL_CLIENT") + (ne .name "NEXTAUTH_URL") }} - name: {{ .name }} value: {{ .value | quote }} {{- end }} + {{- end }} volumeMounts: - name: state-volume mountPath: /state @@ -73,4 +84,4 @@ spec: volumes: - name: state-volume emptyDir: {} -{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/keep/templates/nginx-ingress.yaml b/charts/keep/templates/nginx-ingress.yaml new file mode 100644 index 0000000..6d3c18c --- /dev/null +++ b/charts/keep/templates/nginx-ingress.yaml @@ -0,0 +1,118 @@ +{{- if .Values.global.ingress.enabled }} +{{- $fullName := include "keep.fullname" . }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }}-ingress + labels: + {{- include "keep.labels" . | nindent 4 }} + annotations: + {{- if eq .Values.global.ingress.className "nginx" }} + kubernetes.io/ingress.class: "nginx" + nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600" + nginx.ingress.kubernetes.io/proxy-buffering: "off" + nginx.ingress.kubernetes.io/proxy-http-version: "1.1" + nginx.ingress.kubernetes.io/use-http2: "false" + nginx.ingress.kubernetes.io/backend-protocol: "HTTP" + nginx.ingress.kubernetes.io/configuration-snippet: | + if ($request_uri ~* ^({{ .Values.global.ingress.websocketPrefix }}|{{ .Values.global.ingress.backendPrefix }}|{{ .Values.global.ingress.frontendPrefix }})(/|$)(.*)) { + rewrite ^({{ .Values.global.ingress.websocketPrefix }}|{{ .Values.global.ingress.backendPrefix }}|{{ .Values.global.ingress.frontendPrefix }})(/|$)(.*) /$3 break; + } + nginx.ingress.kubernetes.io/server-snippet: | + {{- if $.Values.websocket.enabled }} + location ^~ {{ .Values.global.ingress.websocketPrefix }} { + rewrite ^{{ .Values.global.ingress.websocketPrefix }}(/|$)(.*) /$2 break; + proxy_pass http://{{ $fullName }}-websocket.{{ .Release.Namespace }}.svc.cluster.local:{{ $.Values.websocket.service.port }}; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $http_host; + proxy_cache_bypass $http_upgrade; + } + {{- end }} + nginx.ingress.kubernetes.io/rewrite-target: /$1 + nginx.ingress.kubernetes.io/use-regex: "true" + {{- end }} + {{- with .Values.global.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.global.ingress.className }} + {{- if .Values.global.ingress.tls }} + tls: + {{- range .Values.global.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- if .Values.global.ingress.hosts }} + {{- range .Values.global.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- if $.Values.websocket.enabled }} + - path: {{ $.Values.global.ingress.websocketPrefix }}(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-websocket + port: + number: {{ $.Values.websocket.service.port }} + {{- end }} + {{- if $.Values.backend.enabled }} + - path: {{ $.Values.global.ingress.backendPrefix }}(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-backend + port: + number: {{ $.Values.backend.service.port }} + {{- end }} + - path: {{ $.Values.global.ingress.frontendPrefix }}(.*) + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-frontend + port: + number: {{ $.Values.frontend.service.port }} + {{- end }} + {{- else }} + - http: + paths: + {{- if $.Values.websocket.enabled }} + - path: {{ $.Values.global.ingress.websocketPrefix }}(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-websocket + port: + number: {{ $.Values.websocket.service.port }} + {{- end }} + {{- if $.Values.backend.enabled }} + - path: {{ $.Values.global.ingress.backendPrefix }}(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-backend + port: + number: {{ $.Values.backend.service.port }} + {{- end }} + - path: {{ $.Values.global.ingress.frontendPrefix }}(.*) + pathType: ImplementationSpecific + backend: + service: + name: {{ $fullName }}-frontend + port: + number: {{ $.Values.frontend.service.port }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/keep/templates/role-binding-secret-manager.yaml b/charts/keep/templates/role-binding-secret-manager.yaml index 3c9b8bc..313e975 100644 --- a/charts/keep/templates/role-binding-secret-manager.yaml +++ b/charts/keep/templates/role-binding-secret-manager.yaml @@ -2,11 +2,11 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: secret-manager-rolebinding - namespace: {{ .Values.namespace | default .Release.Namespace | default "default" }} + namespace: {{ include "keep.namespace" . }} subjects: - kind: ServiceAccount name: {{ include "keep.serviceAccountName" . }} - namespace: {{ .Values.namespace | default .Release.Namespace | default "default" }} + namespace: {{ include "keep.namespace" . }} roleRef: kind: Role name: secret-manager-role diff --git a/charts/keep/templates/role-secret-manager.yaml b/charts/keep/templates/role-secret-manager.yaml index 57b842f..917ae57 100644 --- a/charts/keep/templates/role-secret-manager.yaml +++ b/charts/keep/templates/role-secret-manager.yaml @@ -2,7 +2,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: secret-manager-role - namespace: {{ .Values.namespace | default .Release.Namespace | default "default" }} + namespace: {{ include "keep.namespace" . }} rules: - apiGroups: [""] resources: ["secrets"] diff --git a/charts/keep/templates/websocket-ingress.yaml b/charts/keep/templates/websocket-ingress.yaml deleted file mode 100644 index acdba7c..0000000 --- a/charts/keep/templates/websocket-ingress.yaml +++ /dev/null @@ -1,64 +0,0 @@ -{{- if and .Values.websocket.enabled .Values.websocket.ingress.enabled -}} -{{- $fullName := include "keep.fullname" . -}} -{{- $svcPort := .Values.websocket.service.port -}} -{{- if and .Values.websocket.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.websocket.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.websocket.ingress.annotations "kubernetes.io/ingress.class" .Values.websocket.ingress.className }} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }}-websocket - labels: - {{- include "keep.labels" . | nindent 4 }} - {{- with .Values.websocket.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.websocket.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.websocket.ingress.className }} - {{- end }} - {{- if .Values.websocket.ingress.tls }} - tls: - {{- range .Values.websocket.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.websocket.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }}-websocket - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }}-websocket - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} - {{- if .Values.websocket.extraIngress -}} - {{ toYaml .Values.websocket.extraIngress | nindent 2 }} - {{- end }} -{{- end }} diff --git a/charts/keep/values.yaml b/charts/keep/values.yaml index 280b1ce..71874cc 100644 --- a/charts/keep/values.yaml +++ b/charts/keep/values.yaml @@ -1,4 +1,4 @@ -namespace: default +namespace: keep serviceAccount: create: true annotations: {} @@ -7,6 +7,31 @@ nameOverride: "" fullnameOverride: "" isGKE: false +global: + # this section controls the ingress resource and + # not the ingress-nginx controller + # see the ingress-nginx section below for the + # controller configuration + ingress: + enabled: true + className: "nginx" + annotations: {} + websocketPrefix: "/websocket" + # can't use /api since its "catched" by the nextjs frontend e.g + # . /api/auth/signin or /api/config + backendPrefix: "/v2" + frontendPrefix: "/" + hosts: [] + # uncomment when you want to use a custom domain + # hosts: + # - host: keep.example.com + tls: [] + # uncomment when you want to use a custom domain with TLS + # tls: + # - hosts: + # - keep.example.com + # secretName: keep-tls + backend: # if true, the backend will be enabled enabled: true @@ -51,15 +76,7 @@ backend: service: type: ClusterIP port: 8080 - ingress: - enabled: true - className: "" - annotations: {} - hosts: - - paths: - - path: / - pathType: Prefix - tls: [] + # for openshit route: enabled: false host: chart-example-backend.local @@ -105,28 +122,16 @@ frontend: env: - name: NEXTAUTH_SECRET value: secret - - name: NEXTAUTH_URL - value: http://localhost:3000 # Shahar: took me whole day to figure out that I need to set this to 1 # https://github.com/nextauthjs/next-auth/issues/600 - name: VERCEL value: 1 - - name: API_URL - value: http://keep-backend:8080 - - name: NEXT_PUBLIC_POSTHOG_KEY - value: "phc_muk9qE3TfZsX3SZ9XxX52kCGJBclrjhkP9JxAQcm1PZ" - - name: NEXT_PUBLIC_POSTHOG_HOST - value: https://app.posthog.com - name: ENV value: development - name: NODE_ENV value: development - name: HOSTNAME value: 0.0.0.0 - - name: PUSHER_HOST - value: keep-websocket.default.svc.cluster.local - - name: PUSHER_PORT - value: 6001 - name: PUSHER_APP_KEY value: "keepappkey" replicaCount: 1 @@ -144,15 +149,7 @@ frontend: service: type: ClusterIP port: 3000 - ingress: - enabled: true - className: "" - annotations: {} - hosts: - - paths: - - path: / - pathType: Prefix - tls: [] + # for openshit route: enabled: false host: chart-example.local @@ -194,6 +191,10 @@ frontend: websocket: enabled: true env: + - name: SOKETI_HOST + value: "0.0.0.0" + - name: SOKETI_DEBUG + value: "1" - name: SOKETI_USER_AUTHENTICATION_TIMEOUT value: 3000 - name: SOKETI_DEFAULT_APP_ID @@ -239,15 +240,7 @@ websocket: httpGet: path: / port: http - ingress: - enabled: false - className: "nginx" - hosts: - paths: - - path: / - pathType: Prefix - tls: [] - annotations: {} + # for openshit route: enabled: false host: chart-example.local diff --git a/concat.sh b/concat.sh new file mode 100755 index 0000000..5ad3b85 --- /dev/null +++ b/concat.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Usage: ./concat_files_recursive.sh +# Example: ./concat_files_recursive.sh ./my_directory combined_output.txt + +# Check if the correct number of arguments is provided +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Assign arguments to variables for readability +DIRECTORY=$1 +OUTPUT_FILE=$2 + +# Check if the directory exists +if [ ! -d "$DIRECTORY" ]; then + echo "Error: Directory $DIRECTORY does not exist." + exit 1 +fi + +# Create or clear the output file +> "$OUTPUT_FILE" + +# Find and concatenate all files recursively +find "$DIRECTORY" -type f | while read -r file; do + echo "Adding $file to $OUTPUT_FILE" + cat "$file" >> "$OUTPUT_FILE" +done + +echo "All files have been recursively concatenated into $OUTPUT_FILE."