From a0d02373349b3f0cc7e8c254278c59f14c5aa64f Mon Sep 17 00:00:00 2001 From: Paramtamtam <7326800+tarampampam@users.noreply.github.com> Date: Sat, 1 Feb 2025 16:24:57 +0400 Subject: [PATCH] feat(helm): Add app helm chart --- .github/workflows/release.yml | 47 ++++ .github/workflows/tests.yml | 70 +++--- README.md | 16 +- chart/Chart.yaml | 11 + chart/README.md | 28 +++ chart/templates/_helpers.tpl | 52 +++++ chart/templates/deployment.yaml | 155 +++++++++++++ chart/templates/ingress.yaml | 48 ++++ chart/templates/service.yaml | 25 ++ chart/values.schema.json | 392 ++++++++++++++++++++++++++++++++ chart/values.yaml | 160 +++++++++++++ 11 files changed, 969 insertions(+), 35 deletions(-) create mode 100644 chart/Chart.yaml create mode 100644 chart/README.md create mode 100644 chart/templates/_helpers.tpl create mode 100644 chart/templates/deployment.yaml create mode 100644 chart/templates/ingress.yaml create mode 100644 chart/templates/service.yaml create mode 100644 chart/values.schema.json create mode 100644 chart/values.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f6035c5..f1aadba3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -121,6 +121,53 @@ jobs: docker.io/tarampampam/webhook-tester:${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }} docker.io/tarampampam/webhook-tester:${{ steps.slug.outputs.version-major }} + helm-pack: + name: Pack the Helm chart + runs-on: ubuntu-latest + defaults: {run: {working-directory: ./chart}} + steps: + - uses: actions/checkout@v4 + - uses: azure/setup-helm@v4 + - {uses: gacts/github-slug@v1, id: slug} + - run: | + helm package \ + --app-version "${{ steps.slug.outputs.version }}" \ + --version "${{ steps.slug.outputs.version }}" . + - uses: actions/upload-artifact@v4 + with: + name: helm-chart + path: ./chart/*.tgz + if-no-files-found: error + retention-days: 1 + + helm-publish: + name: Put the Helm chart to the GitHub pages branch + runs-on: ubuntu-latest + needs: [helm-pack] + steps: + - {uses: actions/checkout@v4, with: {ref: gh-pages}} + - uses: azure/setup-helm@v4 + - name: Configure git + run: | + git config user.name "${{ github.actor }}" + git config user.email "${{ github.actor }}@users.noreply.github.com" + - uses: actions/download-artifact@v4 + with: {name: helm-chart, path: ./helm-charts} + - name: Update the index.yaml + run: | + helm repo index \ + --url https://${{ github.actor }}.github.io/${{ github.event.repository.name }}/helm-charts/ \ + --merge \ + ./helm-charts/index.yaml \ + ./helm-charts + - name: Update the index.html + run: tree -H '.' --noreport --dirsfirst -T 'Index' --charset utf-8 -P "*.tgz" -o ./index.html + - name: Commit and push the changes + run: | + git add 'helm-charts/*' index.html + git commit -m "Helm chart release" + git push origin gh-pages + deploy-on-render: name: Deploy on Render runs-on: ubuntu-latest diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e0acd3dc..3bec3123 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -24,9 +24,43 @@ jobs: - {uses: actions/checkout@v4, with: {fetch-depth: 0}} - uses: gacts/gitleaks@v1 + filter: + name: Filter files + runs-on: ubuntu-latest + permissions: {pull-requests: read} + outputs: + backend: ${{ steps.filter.outputs.backend }} + frontend: ${{ steps.filter.outputs.frontend }} + docker: ${{ steps.filter.outputs.docker }} + helm: ${{ steps.filter.outputs.helm }} + steps: + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + backend: ['api/**', 'cmd/**', 'internal/**', '*go*', 'web/**/*.go'] + frontend: ['api/**', 'web/**'] + docker: [Dockerfile, '*docker*'] + helm: ['chart/**', '*kube*'] + + lint-charts: + name: Lint the chart + runs-on: ubuntu-latest + needs: [filter] + if: needs.filter.outputs.helm == 'true' + defaults: {run: {working-directory: ./chart}} + steps: + - uses: actions/checkout@v4 + - uses: azure/setup-helm@v4 + - run: helm dependency update . + - run: helm template . > /dev/null + - run: helm lint --strict . + lint-and-test-backend: name: Test and lint the backend runs-on: ubuntu-latest + needs: [filter] + if: needs.filter.outputs.backend == 'true' steps: - uses: actions/checkout@v4 - {uses: actions/setup-go@v5, with: {go-version-file: go.mod}} @@ -38,6 +72,8 @@ jobs: lint-and-test-frontend: name: Test and lint the frontend runs-on: ubuntu-latest + needs: [filter] + if: needs.filter.outputs.frontend == 'true' env: {FORCE_COLOR: 'true', NPM_PREFIX: './web'} steps: - uses: actions/checkout@v4 @@ -51,6 +87,8 @@ jobs: build-web: name: Build the frontend runs-on: ubuntu-latest + needs: [filter] # since this is the initial step, we can filter out the rest of the jobs right here to skip them + if: ${{ needs.filter.outputs.backend == 'true' || needs.filter.outputs.frontend == 'true' }} env: {FORCE_COLOR: 'true', NPM_PREFIX: './web'} steps: - uses: actions/checkout@v4 @@ -70,7 +108,7 @@ jobs: matrix: # https://pkg.go.dev/internal/platform os: [linux, darwin, windows] arch: [amd64, arm64] - needs: [lint-and-test-backend, lint-and-test-frontend, build-web] + needs: [build-web] steps: - uses: actions/checkout@v4 - {uses: gacts/github-slug@v1, id: slug} @@ -95,33 +133,6 @@ jobs: if-no-files-found: error retention-days: 7 - build-deb-package: - name: Build the Debian package - runs-on: ubuntu-latest - strategy: {matrix: {arch: [amd64, arm64]}} - needs: [build-app] - steps: - - {uses: gacts/github-slug@v1, id: slug} - - {uses: actions/download-artifact@v4, with: {name: "webhook-tester-linux-${{ matrix.arch }}"}} - - id: values - run: | - majorMinorPatch="${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}.${{ steps.slug.outputs.version-patch }}" - echo "version=${majorMinorPatch}" >> $GITHUB_OUTPUT - echo "pkg-name=webhook-tester_${majorMinorPatch}-1_${{ matrix.arch }}" >> $GITHUB_OUTPUT - - run: | - mkdir -p ./${{ steps.values.outputs.pkg-name }}/usr/local/bin ./${{ steps.values.outputs.pkg-name }}/DEBIAN - mv ./webhook-tester-linux-${{ matrix.arch }} ./${{ steps.values.outputs.pkg-name }}/usr/local/bin/webhook-tester - echo -e "Package: webhook-tester\nVersion: ${{ steps.values.outputs.version }}" > ./${{ steps.values.outputs.pkg-name }}/DEBIAN/control - echo -e "Architecture: ${{ matrix.arch }}\nMaintainer: ${{ github.actor }}" >> ./${{ steps.values.outputs.pkg-name }}/DEBIAN/control - echo -e "Description: Powerful tool for testing WebHooks and more" >> ./${{ steps.values.outputs.pkg-name }}/DEBIAN/control - dpkg-deb --build --root-owner-group ${{ steps.values.outputs.pkg-name }} - - uses: actions/upload-artifact@v4 - with: - name: ${{ steps.values.outputs.pkg-name }}.deb - path: ./${{ steps.values.outputs.pkg-name }}.deb - if-no-files-found: error - retention-days: 7 - e2e-test: name: End-to-end tests runs-on: ubuntu-latest @@ -155,7 +166,8 @@ jobs: build-docker-image: name: Build the docker image runs-on: ubuntu-latest - needs: [lint-and-test-backend, lint-and-test-frontend] + needs: [filter] + if: needs.filter.outputs.docker == 'true' steps: - uses: actions/checkout@v4 - uses: docker/build-push-action@v6 diff --git a/README.md b/README.md index e77e0f6e..fce8fc95 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,14 @@ You'll never miss a request! ## ⁉ FAQ -**Can I have pre-defined (static) webhook URLs (sessions) to ensure that the sent request will be captured even +**Can I have pre-defined (static) webhook URLs (sessions) to ensure that the sent request will be captured even without data persistence?** -Yes, simply use the `--auto-create-sessions` flag or set the `AUTO_CREATE_SESSIONS=true` environment variable. In -`v1`, you needed to define sessions during app startup to enable this functionality. However, since `v2`, all you -need to do is enable this feature. It works quite simply - if the incoming request contains a UUID-formatted prefix -(e.g., `http://app/11111111-2222-3333-4444-555555555555/...`), a session for this request will be created -automatically. All that's left for you to do is open the session in the UI +Yes, simply use the `--auto-create-sessions` flag or set the `AUTO_CREATE_SESSIONS=true` environment variable. In +`v1`, you needed to define sessions during app startup to enable this functionality. However, since `v2`, all you +need to do is enable this feature. It works quite simply - if the incoming request contains a UUID-formatted prefix +(e.g., `http://app/11111111-2222-3333-4444-555555555555/...`), a session for this request will be created +automatically. All that's left for you to do is open the session in the UI (`http://app/s/11111111-2222-3333-4444-555555555555`). ## 🧩 Installation @@ -112,6 +112,10 @@ Alternatively, you can use the Docker image: > It’s recommended to avoid using the `latest` tag, as **major** upgrades may include breaking changes. > Instead, use specific tags in `X.Y.Z` format for version consistency. +To install it on Kubernetes (K8s), please use the Helm chart from [ArtifactHUB][artifact-hub]. + +[artifact-hub]:https://artifacthub.io/packages/helm/webhook-tester/webhook-tester + ## ⚙ Usage The easiest way to run the app is by using the Docker image: diff --git a/chart/Chart.yaml b/chart/Chart.yaml new file mode 100644 index 00000000..b506e5f9 --- /dev/null +++ b/chart/Chart.yaml @@ -0,0 +1,11 @@ +# yaml-language-server: $schema=https://json.schemastore.org/chart.json + +apiVersion: v2 +name: webhook-tester +description: Powerful tool for testing WebHooks and more + +type: application +version: 0.1.0 +appVersion: 2.0.1 +icon: https://github.com/user-attachments/assets/e2e659dc-7fb1-4ac2-ad3c-883899f5fc38 +sources: [https://github.com/tarampampam/webhook-tester] diff --git a/chart/README.md b/chart/README.md new file mode 100644 index 00000000..60b42bd0 --- /dev/null +++ b/chart/README.md @@ -0,0 +1,28 @@ +# WebHook Tester + +## Usage + +```shell +helm repo add tarampampam https://tarampampam.github.io/webhook-tester/helm-charts +helm repo update + +helm install webhook-tester tarampampam/webhook-tester +``` + +Alternatively, add the following lines to your `Chart.yaml`: + +```yaml +dependencies: + - name: webhook-tester + version: + repository: https://tarampampam.github.io/webhook-tester/helm-charts +``` + +And override the default values in your `values.yaml`: + +```yaml +webhook-tester: + # ... + service: {port: 8800} + # ... +``` diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 00000000..e0d3609d --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,52 @@ +{{/* Define namespace of chart, useful for multi-namespace deployments */}} +{{- define "webhook-tester.namespace" -}} + {{- if .Values.namespaceOverride }} + {{- .Values.namespaceOverride }} + {{- else }} + {{- .Release.Namespace }} + {{- end }} +{{- end }} + +{{/* Expand the name of the chart */}} +{{- define "webhook-tester.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "webhook-tester.fullname" -}} + {{- if .Values.fullnameOverride }} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} + {{- else }} + {{- $name := default .Chart.Name .Values.nameOverride }} + {{- if contains $name .Release.Name }} + {{- .Release.Name | trunc 63 | trimSuffix "-" }} + {{- else }} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} + {{- end }} + {{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label */}} +{{- define "webhook-tester.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "webhook-tester.commonLabels" -}} +helm.sh/chart: {{ include "webhook-tester.chart" . }} +{{ include "webhook-tester.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "webhook-tester.selectorLabels" -}} +app.kubernetes.io/name: {{ include "webhook-tester.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml new file mode 100644 index 00000000..11af8aac --- /dev/null +++ b/chart/templates/deployment.yaml @@ -0,0 +1,155 @@ +{{- if .Values.deployment.enabled }} +apiVersion: apps/v1 +kind: Deployment + +metadata: + name: {{ include "webhook-tester.fullname" . }} + namespace: {{ template "webhook-tester.namespace" . }} + labels: + {{- include "webhook-tester.commonLabels" . | nindent 4 }} + +spec: + {{- with .Values.deployment }} + replicas: {{ .replicas | default 1 }} + selector: + matchLabels: + {{- include "webhook-tester.selectorLabels" $ | nindent 6 }} + template: + metadata: + {{- with .podAnnotations }} + annotations: + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + labels: + {{- include "webhook-tester.commonLabels" $ | nindent 8 }} + {{- with .labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + automountServiceAccountToken: false + {{- with .imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ include "webhook-tester.fullname" $ }} + + {{- with .securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- with $.Values.image }} + image: "{{ .repository }}:{{ .tag | default $.Chart.AppVersion }}" + imagePullPolicy: {{ .pullPolicy | default "IfNotPresent" }} + {{- end }} + ports: + - name: http + containerPort: {{ $.Values.config.listen.port }} + protocol: TCP + env: + {{- with $.Values.config }} + - {name: HTTP_PORT, value: "{{ .listen.port }}"} + {{- if .log.level }} + - {name: LOG_LEVEL, value: "{{ .log.level }}"} + {{- end }} + {{- if .log.format }} + - {name: LOG_FORMAT, value: "{{ .log.format }}"} + {{- end }} + {{- if .listen.address }} + - {name: SERVER_ADDR, value: "{{ .listen.address }}"} + {{- end }} + {{- if ne .timeouts.read nil }} + - {name: HTTP_READ_TIMEOUT, value: "{{ .timeouts.read }}"} + {{- end }} + {{- if ne .timeouts.write nil }} + - {name: HTTP_WRITE_TIMEOUT, value: "{{ .timeouts.write }}"} + {{- end }} + {{- if ne .timeouts.idle nil }} + - {name: HTTP_IDLE_TIMEOUT, value: "{{ .timeouts.idle }}"} + {{- end }} + {{- if ne .timeouts.shutdown nil }} + - {name: SHUTDOWN_TIMEOUT, value: "{{ .timeouts.shutdown }}"} + {{- end }} + {{- if .storage.driver }} + - {name: STORAGE_DRIVER, value: "{{ .storage.driver }}"} + {{- end }} + {{- if .storage.dirPath }} + - {name: FS_STORAGE_DIR, value: "{{ .storage.dirPath }}"} + {{- end }} + {{- if .pubsub.driver }} + - {name: PUBSUB_DRIVER, value: "{{ .pubsub.driver }}"} + {{- end }} + {{- if .tunnel.driver }} + - {name: TUNNEL_DRIVER, value: "{{ .tunnel.driver }}"} + {{- end }} + {{- if .tunnel.ngrokAuthToken }} + - {name: NGROK_AUTHTOKEN, value: "{{ .tunnel.ngrokAuthToken }}"} + {{- end }} + {{- if .redis.dsn }} + - {name: REDIS_DSN, value: "{{ .redis.dsn }}"} + {{- end }} + {{- if ne .limits.sessionTTL nil }} + - {name: SESSION_TTL, value: "{{ .limits.sessionTTL }}"} + {{- end }} + {{- if ne .limits.maxRequests nil }} + - {name: MAX_REQUESTS, value: "{{ .limits.maxRequests }}"} + {{- end }} + {{- if ne .limits.maxRequestBodySize nil }} + - {name: MAX_REQUEST_BODY_SIZE, value: "{{ .limits.maxRequestBodySize }}"} + {{- end }} + {{- if .autoCreateSessions }} + - {name: AUTO_CREATE_SESSIONS, value: "true"} + {{- end }} + {{- with $.Values.deployment.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + + {{- with .args }} + args: + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- with .probe }} + livenessProbe: + httpGet: {port: http, path: /healthz} + periodSeconds: {{ .interval }} + initialDelaySeconds: {{ .initialDelay }} + readinessProbe: + httpGet: {port: http, path: /ready} + periodSeconds: {{ .interval }} + initialDelaySeconds: {{ .initialDelay }} + {{- end }} + + {{- with .resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- with .volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- with .volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + + {{- with .nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + + {{- with .affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + + {{- with .tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 00000000..40b7b6d4 --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,48 @@ +{{- if .Values.ingress.enabled -}} +{{- if .Values.ingress.hosts -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress + +metadata: + name: {{ include "webhook-tester.fullname" . }} + namespace: {{ template "webhook-tester.namespace" . }} + labels: + {{- include "webhook-tester.commonLabels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "webhook-tester.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/chart/templates/service.yaml b/chart/templates/service.yaml new file mode 100644 index 00000000..cbcbf063 --- /dev/null +++ b/chart/templates/service.yaml @@ -0,0 +1,25 @@ +{{- if .Values.service.enabled }} +apiVersion: v1 +kind: Service + +metadata: + name: {{ include "webhook-tester.fullname" . }} + namespace: {{ template "webhook-tester.namespace" . }} + labels: + {{- include "webhook-tester.commonLabels" . | nindent 4 }} + +spec: + {{- with .Values.service }} + type: {{ .type }} + {{- with .externalName }} + externalName: {{ . }} + {{- end }} + ports: + - name: http + port: {{ .port }} + targetPort: http + protocol: TCP + selector: + {{- include "webhook-tester.selectorLabels" $ | nindent 4 }} + {{- end }} +{{- end }} diff --git a/chart/values.schema.json b/chart/values.schema.json new file mode 100644 index 00000000..99527e2d --- /dev/null +++ b/chart/values.schema.json @@ -0,0 +1,392 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "nameOverride": { + "oneOf": [ + {"type": "string", "minLength": 1}, + {"type": "null"} + ] + }, + "fullnameOverride": { + "oneOf": [ + {"type": "string", "minLength": 1}, + {"type": "null"} + ] + }, + "namespaceOverride": { + "oneOf": [ + {"type": "string", "minLength": 1}, + {"type": "null"} + ] + }, + "image": { + "type": "object", + "properties": { + "repository": {"type": "string", "minLength": 1}, + "tag": { + "oneOf": [ + {"type": "string", "minLength": 1}, + {"type": "null"} + ] + }, + "pullPolicy": { + "oneOf": [ + {"type": "string", "enum": ["Always", "IfNotPresent", "Never"]}, + {"type": "null"} + ] + } + } + }, + "deployment": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "replicas": {"type": "integer"}, + "podAnnotations": { + "type": "object", + "additionalProperties": {"type": "string", "minLength": 1} + }, + "labels": { + "type": "object", + "additionalProperties": {"type": "string", "minLength": 1} + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": {"type": "string"} + }, + "minProperties": 1 + } + }, + "securityContext": { + "type": "object", + "properties": { + "runAsNonRoot": {"type": "boolean"}, + "runAsUser": {"type": "integer"}, + "runAsGroup": {"type": "integer"} + } + }, + "probe": { + "type": "object", + "properties": { + "interval": {"type": "integer"}, + "initialDelay": {"type": "integer"} + } + }, + "resources": { + "type": "object", + "properties": { + "requests": { + "type": "object", + "properties": { + "cpu": {"type": "string"}, + "memory": {"type": "string"} + } + }, + "limits": { + "type": "object", + "properties": { + "cpu": {"type": "string"}, + "memory": {"type": "string"} + } + } + } + }, + "volumes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "configMap": { + "type": "object", + "properties": { + "name": {"type": "string"} + } + }, + "secret": { + "type": "object", + "properties": { + "secretName": {"type": "string"} + } + }, + "persistentVolumeClaim": { + "type": "object", + "properties": { + "claimName": {"type": "string"} + } + } + } + } + }, + "volumeMounts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "mountPath": {"type": "string"}, + "subPath": {"type": "string"}, + "readOnly": {"type": "boolean"} + } + } + }, + "nodeSelector": { + "type": "object", + "additionalProperties": {"type": "string", "minLength": 1} + }, + "affinity": { + "type": "object", + "properties": { + "nodeAffinity": {"type": "object"}, + "podAffinity": {"type": "object"}, + "podAntiAffinity": {"type": "object"} + } + }, + "tolerations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": {"type": "string"}, + "operator": {"type": "string"}, + "value": {"type": "string"}, + "effect": {"type": "string"} + } + } + }, + "env": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "value": {"type": "string"}, + "valueFrom": {"type": "object"} + } + } + }, + "args": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + } + } + }, + "service": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "type": { + "type": "string", + "enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"] + }, + "externalName": { + "oneOf": [ + {"type": "string", "minLength": 1}, + {"type": "null"} + ] + }, + "port": {"type": "integer", "minimum": 1, "maximum": 65535} + } + }, + "ingress": { + "type": "object", + "properties": { + "enabled": {"type": "boolean"}, + "className": { + "oneOf": [ + {"type": "string", "minLength": 1}, + {"type": "null"} + ] + }, + "annotations": { + "type": "object", + "additionalProperties": {"type": "string", "minLength": 1} + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "host": {"type": "string", "minLength": 1}, + "paths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": {"type": "string", "minLength": 1}, + "pathType": {"type": "string", "minLength": 1} + } + } + } + } + } + }, + "tls": { + "type": "array", + "items": { + "type": "object", + "properties": { + "hosts": {"type": "array"}, + "secretName": {"type": "string"} + } + } + } + } + }, + "config": { + "properties": { + "log": { + "properties": { + "level": { + "oneOf": [ + {"type": "string", "enum": ["debug", "info", "warn", "error", "fatal"]}, + {"type": "null"} + ] + }, + "format": { + "oneOf": [ + {"type": "string", "enum": ["console", "json"]}, + {"type": "null"} + ] + } + } + }, + "listen": { + "properties": { + "address": { + "oneOf": [ + {"type": "string", "examples": ["0.0.0.0"]}, + {"type": "null"} + ] + }, + "port": {"type": "integer", "minimum": 1, "maximum": 65535} + } + }, + "timeouts": { + "type": "object", + "properties": { + "read": { + "oneOf": [ + {"type": "number", "enum": [0]}, + {"type": "string", "minLength": 2, "examples": ["15s", "1m30s"]}, + {"type": "null"} + ] + }, + "write": { + "oneOf": [ + {"type": "number", "enum": [0]}, + {"type": "string", "minLength": 2, "examples": ["15s", "1m30s"]}, + {"type": "null"} + ] + }, + "idle": { + "oneOf": [ + {"type": "number", "enum": [0]}, + {"type": "string", "minLength": 2, "examples": ["15s", "1m30s"]}, + {"type": "null"} + ] + }, + "shutdown": { + "oneOf": [ + {"type": "string", "examples": ["15s", "1m30s"]}, + {"type": "null"} + ] + } + } + }, + "storage": { + "type": "object", + "properties": { + "driver": { + "oneOf": [ + {"type": "string", "enum": ["memory", "redis", "fs"]}, + {"type": "null"} + ] + }, + "dirPath": { + "oneOf": [ + {"type": "string"}, + {"type": "null"} + ] + } + } + }, + "pubsub": { + "type": "object", + "properties": { + "driver": { + "oneOf": [ + {"type": "string", "enum": ["memory", "redis"]}, + {"type": "null"} + ] + } + } + }, + "tunnel": { + "type": "object", + "properties": { + "driver": { + "oneOf": [ + {"type": "string", "enum": ["ngrok"]}, + {"type": "null"} + ] + }, + "ngrokAuthToken": { + "oneOf": [ + {"type": "string", "minLength": 32}, + {"type": "null"} + ] + } + } + }, + "redis": { + "type": "object", + "properties": { + "dsn": { + "oneOf": [ + {"type": "string", "examples": ["redis://user:pwd@127.0.0.1:6379/0"]}, + {"type": "null"} + ] + } + } + }, + "limits": { + "type": "object", + "properties": { + "sessionTTL": { + "oneOf": [ + {"type": "string", "minLength": 2, "examples": ["15s", "1m30s"]}, + {"type": "null"} + ] + }, + "maxRequests": { + "oneOf": [ + {"type": "integer", "minimum": 0}, + {"type": "null"} + ] + }, + "maxRequestBodySize": { + "oneOf": [ + {"type": "integer", "minimum": 0}, + {"type": "null"} + ] + } + } + }, + "autoCreateSessions": { + "oneOf": [ + {"type": "boolean"}, + {"type": "null"} + ] + } + } + } + } +} diff --git a/chart/values.yaml b/chart/values.yaml new file mode 100644 index 00000000..361b589c --- /dev/null +++ b/chart/values.yaml @@ -0,0 +1,160 @@ +# -- The name of the Helm release +fullnameOverride: null +# -- This is to override the chart name +nameOverride: null +# -- Override the default Release Namespace for Helm +namespaceOverride: null + +image: + # -- The image repository to pull from + repository: ghcr.io/tarampampam/webhook-tester + # -- Defines the image pull policy + pullPolicy: IfNotPresent + # -- Overrides the image tag whose default is the chart appVersion + tag: null + +deployment: + # -- Enable deployment + enabled: true + # -- How many replicas to run + replicas: 1 + # -- Additional pod annotations (e.g. for mesh injection or prometheus scraping) + # It supports templating. One can set it with values like some/name: '{{ template "some.name" . }}' + # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + podAnnotations: {} + # -- Additional deployment labels (e.g. for filtering deployment by custom labels) + labels: {} + # -- This is for the secretes for pulling an image from a private repository more information can be found + # here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # -- Security context for the pod, more information can be found here: + # https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1 + securityContext: + runAsNonRoot: true + runAsUser: 10001 # as defined in the Dockerfile + runAsGroup: 10001 # as defined in the Dockerfile + probe: + # -- How often (in seconds) to perform the probe + interval: 10 + # -- Number of seconds after the container has started before liveness probes are initiated + initialDelay: 2 + # -- Resource limits and requests, more information can be found here: + # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + requests: {memory: 16Mi} + limits: {memory: 256Mi} + # -- Additional volumes to add to the pod, more information can be found here: + # https://kubernetes.io/docs/concepts/storage/volumes/ + volumes: [] + # -- Additional volumeMounts to add to the container (for instance when using fs storage driver) + volumeMounts: [] + # -- Node selector for pod assignment, more information can be found here: + # https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + nodeSelector: {} + # -- Affinity for pod assignment, more information can be found here: + # https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ + affinity: {} + # -- Tolerations for pod assignment, more information can be found here: + # https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: [] + # -- The list of additional environment variables to set in the container + env: [] + # -- The list of additional arguments to pass to the container + args: [] + +service: + # -- Enable service + enabled: true + # -- Sets the service type more information can be found here: + # https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ExternalName + # -- External name for the service (for type=ExternalName) + externalName: null + # -- Sets the port, more information can be found here: + # https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 8081 + +ingress: + # -- Enable ingress + enabled: false + # -- Ingress class to use, for more information checkout: + # https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class + className: null + # -- Additional ingress annotations + annotations: {} + # -- The list of hosts for the ingress + hosts: [] + # -- TLS configuration for the ingress, more information can be found here: + # https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + tls: [] + +config: + log: + # -- Logging level (debug|info|warn|error|fatal) + # @default info (defined in the Dockerfile) + level: null + # -- Logging format (console|json) + # @default json (defined in the Dockerfile) + format: null + + listen: + # -- IP (v4 or v6) address to listen on (0.0.0.0 to bind to all interfaces) + # @default 0.0.0.0 + address: null + # -- HTTP server port + port: 8080 + + timeouts: + # -- Maximum duration for reading the entire request, including the body (zero = no timeout) + # @default 1m0s + read: null + # -- Maximum duration before timing out writes of the response (zero = no timeout) + # @default 1m0s + write: null + # -- Maximum amount of time to wait for the next request (keep-alive, zero = no timeout) + # @default 1m0s + idle: null + # -- Maximum duration for graceful shutdown + # @default 15s + shutdown: null + + storage: + # -- Storage driver (memory|redis|fs) + # @default memory + driver: null + # -- Path to the directory for local fs storage (directory must exist) + # @default /data (defined in the Dockerfile) + dirPath: null + + pubsub: + # -- Pub/Sub driver (memory|redis) + # @default memory + driver: null + + tunnel: + # -- Tunnel driver to expose your locally running app to the internet (ngrok, empty to disable) + # @default "" (empty) + driver: null + + # -- Ngrok authentication token (required for ngrok tunnel driver) + ngrokAuthToken: null + + redis: + # -- Redis-like (redis, keydb) server DSN (e.g. redis://user:pwd@127.0.0.1:6379/0) + # @default redis://127.0.0.1:6379/0 + dsn: null + + limits: + # -- Session (single webhook) TTL (time-to-live, lifetime) + # @default 168h0m0s (7 days) + sessionTTL: null + # -- Maximal number of requests to store in the storage for the session (zero means unlimited) + # @default 128 + maxRequests: null + # -- Maximal webhook request body size (in bytes), zero means unlimited + # @default 0 + maxRequestBodySize: null + + # -- Automatically create sessions (webhooks) for incoming requests + # @default false + autoCreateSessions: null