From f7c102fac82038b23807d16222abc1365ce2723f Mon Sep 17 00:00:00 2001 From: Jordan Simonovski Date: Sat, 27 Jun 2026 11:44:27 +1000 Subject: [PATCH 1/5] chore: Added helmcov for test coverage checking, and implemented helm docs for doc generation on charts --- .githooks/pre-commit | 40 ++++ .github/workflows/helm-test.yaml | 45 ++-- .github/workflows/helmcov.yaml | 41 ++++ .gitignore | 8 + AGENTS.md | 54 ++++- Makefile | 63 ++++++ README.md | 4 +- charts/clickstack-operators/README.md | 37 ++++ charts/clickstack-operators/README.md.gotmpl | 24 +++ charts/clickstack/README.md | 193 ++++++++++++++++++ charts/clickstack/README.md.gotmpl | 30 +++ .../additional-manifests-multi_test.yaml | 13 ++ .../tests/autoscaling-enabled_test.yaml | 13 ++ .../tests/clickhouse-disabled_test.yaml | 10 + .../tests/configmap-extended_test.yaml | 17 ++ .../tests/deployment-features_test.yaml | 24 +++ .../tests/deployment-no-mongodb_test.yaml | 15 ++ .../deployment-probes-disabled_test.yaml | 12 ++ .../tests/deployment-replicas_test.yaml | 11 + .../tests/deployment-tpl-defaults_test.yaml | 12 ++ .../tests/existing-config-secret_test.yaml | 14 ++ .../tests/helpers-fullname_test.yaml | 11 + .../tests/helpers-name-override_test.yaml | 11 + .../tests/helpers-release-name_test.yaml | 9 + .../tests/ingress-additional_test.yaml | 14 ++ .../tests/ingress-default-service_test.yaml | 14 ++ .../tests/ingress-enabled_test.yaml | 16 ++ .../tests/keeper-disabled_test.yaml | 10 + .../tests/mongodb-disabled_test.yaml | 10 + .../tests/networkpolicy-enabled_test.yaml | 13 ++ .../clickstack/tests/notes-ingress_test.yaml | 12 ++ charts/clickstack/tests/notes_test.yaml | 10 + charts/clickstack/tests/pdb-enabled_test.yaml | 13 ++ charts/clickstack/tests/pdb-labels_test.yaml | 13 ++ .../clickstack/tests/secret-custom_test.yaml | 14 ++ .../tests/secret-disabled_test.yaml | 10 + .../tests/service-features_test.yaml | 17 ++ .../tests/serviceaccount-annotated_test.yaml | 13 ++ .../clickstack/tests/tasks-enabled_test.yaml | 13 ++ .../tests/tasks-pre-esbuild_test.yaml | 11 + .../tests/tasks-with-args_test.yaml | 14 ++ .../tasks-with-imagepullsecrets_test.yaml | 11 + .../values/additional-manifests-multi.yaml | 11 + .../tests/values/autoscaling-enabled.yaml | 13 ++ .../tests/values/components-disabled.yaml | 6 + .../tests/values/configmap-extended.yaml | 5 + .../tests/values/deployment-features.yaml | 39 ++++ .../tests/values/deployment-no-mongodb.yaml | 8 + .../values/deployment-probes-disabled.yaml | 7 + .../tests/values/deployment-replicas.yaml | 5 + .../tests/values/deployment-tpl-defaults.yaml | 112 ++++++++++ .../tests/values/existing-config-secret.yaml | 6 + .../tests/values/fullname-override.yaml | 2 + .../tests/values/ingress-additional.yaml | 30 +++ .../tests/values/ingress-default-service.yaml | 24 +++ .../tests/values/ingress-enabled.yaml | 18 ++ .../tests/values/name-override.yaml | 1 + .../tests/values/networkpolicy-enabled.yaml | 10 + .../tests/values/notes-ingress-enabled.yaml | 15 ++ .../clickstack/tests/values/pdb-enabled.yaml | 3 + .../tests/values/pdb-with-labels.yaml | 6 + .../tests/values/secret-custom.yaml | 5 + .../tests/values/secret-disabled.yaml | 8 + .../tests/values/service-features.yaml | 7 + .../values/serviceaccount-annotated.yaml | 5 + .../tests/values/tasks-enabled.yaml | 6 + .../tests/values/tasks-pre-esbuild.yaml | 6 + .../tests/values/tasks-with-args.yaml | 10 + .../values/tasks-with-imagepullsecrets.yaml | 9 + scripts/helmcov.sh | 56 +++++ scripts/helmdocs.sh | 15 ++ scripts/install-helm-docs.sh | 37 ++++ scripts/install-hooks.sh | 27 +++ 73 files changed, 1413 insertions(+), 38 deletions(-) create mode 100755 .githooks/pre-commit create mode 100644 .github/workflows/helmcov.yaml create mode 100644 Makefile create mode 100644 charts/clickstack-operators/README.md create mode 100644 charts/clickstack-operators/README.md.gotmpl create mode 100644 charts/clickstack/README.md create mode 100644 charts/clickstack/README.md.gotmpl create mode 100644 charts/clickstack/tests/additional-manifests-multi_test.yaml create mode 100644 charts/clickstack/tests/autoscaling-enabled_test.yaml create mode 100644 charts/clickstack/tests/clickhouse-disabled_test.yaml create mode 100644 charts/clickstack/tests/configmap-extended_test.yaml create mode 100644 charts/clickstack/tests/deployment-features_test.yaml create mode 100644 charts/clickstack/tests/deployment-no-mongodb_test.yaml create mode 100644 charts/clickstack/tests/deployment-probes-disabled_test.yaml create mode 100644 charts/clickstack/tests/deployment-replicas_test.yaml create mode 100644 charts/clickstack/tests/deployment-tpl-defaults_test.yaml create mode 100644 charts/clickstack/tests/existing-config-secret_test.yaml create mode 100644 charts/clickstack/tests/helpers-fullname_test.yaml create mode 100644 charts/clickstack/tests/helpers-name-override_test.yaml create mode 100644 charts/clickstack/tests/helpers-release-name_test.yaml create mode 100644 charts/clickstack/tests/ingress-additional_test.yaml create mode 100644 charts/clickstack/tests/ingress-default-service_test.yaml create mode 100644 charts/clickstack/tests/ingress-enabled_test.yaml create mode 100644 charts/clickstack/tests/keeper-disabled_test.yaml create mode 100644 charts/clickstack/tests/mongodb-disabled_test.yaml create mode 100644 charts/clickstack/tests/networkpolicy-enabled_test.yaml create mode 100644 charts/clickstack/tests/notes-ingress_test.yaml create mode 100644 charts/clickstack/tests/notes_test.yaml create mode 100644 charts/clickstack/tests/pdb-enabled_test.yaml create mode 100644 charts/clickstack/tests/pdb-labels_test.yaml create mode 100644 charts/clickstack/tests/secret-custom_test.yaml create mode 100644 charts/clickstack/tests/secret-disabled_test.yaml create mode 100644 charts/clickstack/tests/service-features_test.yaml create mode 100644 charts/clickstack/tests/serviceaccount-annotated_test.yaml create mode 100644 charts/clickstack/tests/tasks-enabled_test.yaml create mode 100644 charts/clickstack/tests/tasks-pre-esbuild_test.yaml create mode 100644 charts/clickstack/tests/tasks-with-args_test.yaml create mode 100644 charts/clickstack/tests/tasks-with-imagepullsecrets_test.yaml create mode 100644 charts/clickstack/tests/values/additional-manifests-multi.yaml create mode 100644 charts/clickstack/tests/values/autoscaling-enabled.yaml create mode 100644 charts/clickstack/tests/values/components-disabled.yaml create mode 100644 charts/clickstack/tests/values/configmap-extended.yaml create mode 100644 charts/clickstack/tests/values/deployment-features.yaml create mode 100644 charts/clickstack/tests/values/deployment-no-mongodb.yaml create mode 100644 charts/clickstack/tests/values/deployment-probes-disabled.yaml create mode 100644 charts/clickstack/tests/values/deployment-replicas.yaml create mode 100644 charts/clickstack/tests/values/deployment-tpl-defaults.yaml create mode 100644 charts/clickstack/tests/values/existing-config-secret.yaml create mode 100644 charts/clickstack/tests/values/fullname-override.yaml create mode 100644 charts/clickstack/tests/values/ingress-additional.yaml create mode 100644 charts/clickstack/tests/values/ingress-default-service.yaml create mode 100644 charts/clickstack/tests/values/ingress-enabled.yaml create mode 100644 charts/clickstack/tests/values/name-override.yaml create mode 100644 charts/clickstack/tests/values/networkpolicy-enabled.yaml create mode 100644 charts/clickstack/tests/values/notes-ingress-enabled.yaml create mode 100644 charts/clickstack/tests/values/pdb-enabled.yaml create mode 100644 charts/clickstack/tests/values/pdb-with-labels.yaml create mode 100644 charts/clickstack/tests/values/secret-custom.yaml create mode 100644 charts/clickstack/tests/values/secret-disabled.yaml create mode 100644 charts/clickstack/tests/values/service-features.yaml create mode 100644 charts/clickstack/tests/values/serviceaccount-annotated.yaml create mode 100644 charts/clickstack/tests/values/tasks-enabled.yaml create mode 100644 charts/clickstack/tests/values/tasks-pre-esbuild.yaml create mode 100644 charts/clickstack/tests/values/tasks-with-args.yaml create mode 100644 charts/clickstack/tests/values/tasks-with-imagepullsecrets.yaml create mode 100755 scripts/helmcov.sh create mode 100755 scripts/helmdocs.sh create mode 100755 scripts/install-helm-docs.sh create mode 100755 scripts/install-hooks.sh diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..50294ac --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(git rev-parse --show-toplevel)" +cd "$repo_root" + +staged="$(git diff --cached --name-only --diff-filter=ACMR || true)" + +if [[ -z "${staged}" ]]; then + exit 0 +fi + +chart_changes=false +docs_changes=false + +while IFS= read -r path; do + [[ -z "${path}" ]] && continue + case "${path}" in + charts/*) + chart_changes=true + case "${path}" in + charts/*/Chart.yaml|charts/*/values.yaml|charts/*/README.md.gotmpl|charts/*/templates/*|scripts/helmdocs.sh|scripts/install-helm-docs.sh) + docs_changes=true + ;; + esac + ;; + esac +done <<< "${staged}" + +if [[ "${chart_changes}" == true ]]; then + make test +fi + +if [[ "${docs_changes}" == true ]]; then + make docs + if ! git diff --quiet -- charts/clickstack/README.md charts/clickstack-operators/README.md; then + echo "Chart README(s) are out of date. Run 'make docs' and stage the updated README.md files." >&2 + exit 1 + fi +fi diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml index c848801..a23aab3 100644 --- a/.github/workflows/helm-test.yaml +++ b/.github/workflows/helm-test.yaml @@ -5,45 +5,32 @@ on: branches: [ main ] paths: - 'charts/**' + - 'Makefile' + - 'scripts/**' + - '.githooks/**' + - '.github/workflows/helm-test.yaml' pull_request: branches: [ main ] + paths: + - 'charts/**' + - 'Makefile' + - 'scripts/**' + - '.githooks/**' + - '.github/workflows/helm-test.yaml' jobs: helm-unittest: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y unzip git curl + uses: actions/checkout@v4 - name: Set up Helm - uses: azure/setup-helm@v3 + uses: azure/setup-helm@v4 with: version: v3.12.0 - - name: Install helm-unittest plugin - run: | - helm plugin install https://github.com/helm-unittest/helm-unittest.git --version v1.0.3 ${{ runner.debug && '--debug' || ''}} - - - name: Build chart dependencies - run: | - helm repo add mongodb https://mongodb.github.io/helm-charts - helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts - helm dependency build charts/clickstack - - - name: Validate example values render - run: | - helm template clickstack-example charts/clickstack \ - -f examples/alb-ingress/values.yaml >/dev/null - helm template clickstack-example charts/clickstack \ - -f examples/api-only/values.yaml >/dev/null - - - name: Run helm-unittest - run: | - helm unittest charts/clickstack + - name: Run unit tests and verify docs + run: make setup test docs + - name: Check generated chart READMEs are committed + run: git diff --exit-code -- charts/clickstack/README.md charts/clickstack-operators/README.md diff --git a/.github/workflows/helmcov.yaml b/.github/workflows/helmcov.yaml new file mode 100644 index 0000000..da79c15 --- /dev/null +++ b/.github/workflows/helmcov.yaml @@ -0,0 +1,41 @@ +name: Helm Template Coverage + +on: + push: + branches: [ main ] + paths: + - 'charts/**' + - 'Makefile' + - 'scripts/**' + - '.github/workflows/helmcov.yaml' + pull_request: + branches: [ main ] + paths: + - 'charts/**' + - 'Makefile' + - 'scripts/**' + - '.github/workflows/helmcov.yaml' + +jobs: + helmcov: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.12.0 + + - name: Run template coverage + run: make coverage + + - name: Upload coverage reports + uses: actions/upload-artifact@v4 + if: always() + with: + name: helmcov-reports + path: | + coverage.out + coverage.xml diff --git a/.gitignore b/.gitignore index ca7289d..dd3c6be 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,11 @@ node_modules !.yarn/versions charts/*/charts/*.tgz + +# helmcov +coverage.out +coverage.xml + +# local tooling +.tools/ +.helmcov-work/ diff --git a/AGENTS.md b/AGENTS.md index 707a139..7bcc142 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,21 @@ Helm charts for ClickStack (HyperDX observability platform). Two charts: Package manager: Yarn 4 (via Corepack). Versioning: Changesets. +## Local Development + +Use the Makefile for tool setup, unit tests, and template coverage: + +```bash +make setup # install helm-unittest, chart deps, and git hooks +make test # helm-unittest + example values validation +make coverage # helmcov template coverage via Docker (requires Docker) +make ci # test + coverage +``` + +The pre-commit hook runs `make test` when staged files under `charts/` change, and +`make docs` when chart values, templates, or README templates change. Install hooks +with `make setup` or `make hooks`. + ## Build & Dependency Commands ```bash @@ -35,14 +50,8 @@ helm template clickstack-test charts/clickstack -f examples/api-only/values.yaml ### Unit Tests (helm-unittest) -Requires the `helm-unittest` plugin: ```bash -helm plugin install https://github.com/helm-unittest/helm-unittest.git --version v1.0.3 -``` - -```bash -# Run ALL unit tests -helm unittest charts/clickstack +make test # Run a SINGLE test file helm unittest -f tests/app-deployment_test.yaml charts/clickstack @@ -54,6 +63,35 @@ helm unittest -f 'tests/clickhouse-*_test.yaml' charts/clickstack Test files live in `charts/clickstack/tests/` and follow the naming convention `_test.yaml`. Snapshots are stored in `tests/__snapshot__/`. +### Template Coverage (helmcov) + +```bash +make coverage + +# Verbose per-file output +VERBOSE=1 make coverage + +# Gate on minimum line coverage once baseline is known +COVERAGE_THRESHOLD=25 make coverage + +# Pin a different image +HELMCOV_IMAGE=ghcr.io/jordan-simonovski/helmcov:v0.3.2 make coverage +``` + +Uses `ghcr.io/jordan-simonovski/helmcov:v0.3.2` by default with a **25% line +coverage threshold**. Outputs `coverage.out` (Go coverprofile) and `coverage.xml` +(Cobertura). CI runs `make coverage` via `.github/workflows/helmcov.yaml`. + +### Chart README (helm-docs) + +```bash +make docs +``` + +Regenerates `charts/*/README.md` from `values.yaml` using [helm-docs](https://github.com/norwoodj/helm-docs). +Each chart README includes version and CI build status badges. +The pre-commit hook verifies docs are up to date when values or templates change. + ### Integration Tests (Kind cluster) Suites live under `integration-tests//`. Each has `suite.yaml`, @@ -151,6 +189,7 @@ tests: | Workflow | File | Trigger | Purpose | |----------|------|---------|---------| | Helm Chart Tests | `helm-test.yaml` | push/PR to main | Unit tests + example validation | +| Helm Template Coverage | `helmcov.yaml` | push/PR to main | helmcov template line/branch coverage | | Integration Test | `chart-test.yml` | push/PR/nightly | Kind-based integration suites | | Release | `release.yml` | after tests pass on main | Changeset version + chart release | | Update App Version | `update-app-version.yml` | workflow_dispatch | Bump `appVersion` in Chart.yaml | @@ -165,3 +204,4 @@ tests: - Example values: `examples/*/values.yaml` - Version sync script: `scripts/update-chart-versions.js` - Smoke test: `scripts/smoke-test.sh` +- Makefile: `make setup`, `make test`, `make coverage` diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..75a0da7 --- /dev/null +++ b/Makefile @@ -0,0 +1,63 @@ +SHELL := /bin/bash + +CHART ?= charts/clickstack +HELMCOV_IMAGE ?= ghcr.io/jordan-simonovski/helmcov:v0.3.2 +HELM_UNITTEST_VERSION ?= v1.0.3 +HELM_UNITTEST_PLUGIN := https://github.com/helm-unittest/helm-unittest.git +COVERAGE_THRESHOLD ?= 25 + +.PHONY: help setup hooks chart-deps install-helm-unittest install-helm-docs validate test coverage docs ci + +help: + @echo "Targets:" + @echo " make setup Install helm-unittest, helm-docs, chart deps, and git hooks" + @echo " make test Run helm-unittest and example values validation" + @echo " make coverage Run helmcov template coverage via Docker (min $(COVERAGE_THRESHOLD)%)" + @echo " make docs Regenerate chart README files from values.yaml via helm-docs" + @echo " make ci Run test, coverage, and docs verification" + @echo "" + @echo "Variables:" + @echo " CHART=$(CHART)" + @echo " HELMCOV_IMAGE=$(HELMCOV_IMAGE)" + @echo " HELM_UNITTEST_VERSION=$(HELM_UNITTEST_VERSION)" + @echo " COVERAGE_THRESHOLD=$(COVERAGE_THRESHOLD)" + +setup: hooks install-helm-unittest install-helm-docs chart-deps + @echo "Setup complete." + +hooks: + ./scripts/install-hooks.sh + +install-helm-docs: + ./scripts/install-helm-docs.sh + +chart-deps: + @command -v helm >/dev/null || { echo "helm is required; install Helm 3 first." >&2; exit 1; } + helm repo add mongodb https://mongodb.github.io/helm-charts >/dev/null 2>&1 || true + helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts >/dev/null 2>&1 || true + helm dependency build $(CHART) + +install-helm-unittest: + @command -v helm >/dev/null || { echo "helm is required; install Helm 3 first." >&2; exit 1; } + @if helm plugin list 2>/dev/null | awk '{print $$1}' | grep -qx unittest; then \ + echo "helm-unittest already installed"; \ + else \ + echo "Installing helm-unittest $(HELM_UNITTEST_VERSION)..."; \ + helm plugin install $(HELM_UNITTEST_PLUGIN) --version $(HELM_UNITTEST_VERSION); \ + fi + +validate: chart-deps + helm template clickstack-example $(CHART) -f examples/alb-ingress/values.yaml >/dev/null + helm template clickstack-example $(CHART) -f examples/api-only/values.yaml >/dev/null + +test: chart-deps validate + helm unittest $(CHART) + +coverage: chart-deps + THRESHOLD=$(COVERAGE_THRESHOLD) HELMCOV_IMAGE=$(HELMCOV_IMAGE) ./scripts/helmcov.sh + +docs: install-helm-docs + ./scripts/helmdocs.sh + +ci: test coverage docs + @git diff --exit-code -- charts/clickstack/README.md charts/clickstack-operators/README.md diff --git a/README.md b/README.md index 4a4d397..565ef23 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ For configuration, cloud deployment, ingress setup, and troubleshooting, see the ## Charts -- **`clickstack/clickstack-operators`** - Installs the MongoDB and ClickHouse operator controllers and CRDs. Must be installed first. -- **`clickstack/clickstack`** - Installs HyperDX, OpenTelemetry Collector, and operator custom resources. +- **[`clickstack/clickstack-operators`](charts/clickstack-operators/README.md)** - Installs the MongoDB and ClickHouse operator controllers and CRDs. Must be installed first. +- **[`clickstack/clickstack`](charts/clickstack/README.md)** - Installs HyperDX, OpenTelemetry Collector, and operator custom resources. ## Additional Manifests diff --git a/charts/clickstack-operators/README.md b/charts/clickstack-operators/README.md new file mode 100644 index 0000000..e13fbf0 --- /dev/null +++ b/charts/clickstack-operators/README.md @@ -0,0 +1,37 @@ +# clickstack-operators + +![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat) +![Build Status](https://github.com/ClickHouse/ClickStack-helm-charts/actions/workflows/helm-test.yaml/badge.svg) + +Operator dependencies for ClickStack. Install this chart before installing clickstack/clickstack to ensure CRDs are registered. + +**Homepage:** + +## Quick Start + +```bash +helm repo add clickstack https://clickhouse.github.io/ClickStack-helm-charts +helm repo update +helm install clickstack-operators clickstack/clickstack-operators +``` + +After the operators are ready, install the [clickstack](../clickstack) chart. + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://mongodb.github.io/helm-charts | mongodb-operator(mongodb-kubernetes) | ~1.7.0 | +| oci://ghcr.io/clickhouse | clickhouse-operator(clickhouse-operator-helm) | ~0.0.2 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| clickhouse-operator.certManager.enable | bool | `false` | | +| clickhouse-operator.crd.enable | bool | `true` | | +| clickhouse-operator.webhook.enable | bool | `false` | | +| mongodb-operator.operator.watchedResources[0] | string | `"mongodbcommunity"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/clickstack-operators/README.md.gotmpl b/charts/clickstack-operators/README.md.gotmpl new file mode 100644 index 0000000..c1138a0 --- /dev/null +++ b/charts/clickstack-operators/README.md.gotmpl @@ -0,0 +1,24 @@ +# {{ template "chart.name" . }} + +{{ template "chart.versionBadge" . }} +![Build Status](https://github.com/ClickHouse/ClickStack-helm-charts/actions/workflows/helm-test.yaml/badge.svg) + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +## Quick Start + +```bash +helm repo add clickstack https://clickhouse.github.io/ClickStack-helm-charts +helm repo update +helm install clickstack-operators clickstack/clickstack-operators +``` + +After the operators are ready, install the [clickstack](../clickstack) chart. + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + +{{ template "helm-docs.versionFooter" . }} diff --git a/charts/clickstack/README.md b/charts/clickstack/README.md new file mode 100644 index 0000000..33482be --- /dev/null +++ b/charts/clickstack/README.md @@ -0,0 +1,193 @@ +# clickstack + +![Version: 3.0.0](https://img.shields.io/badge/Version-3.0.0-informational?style=flat) +![Build Status](https://github.com/ClickHouse/ClickStack-helm-charts/actions/workflows/helm-test.yaml/badge.svg) + +A Helm chart for ClickStack - Full-stack observability with ClickHouse, OpenTelemetry, and HyperDX + +**Homepage:** + +## Source Code + +* +* + +## Prerequisites + +Install the [clickstack-operators](../clickstack-operators) chart first so MongoDB and ClickHouse CRDs are available. + +## Quick Start + +```bash +helm repo add clickstack https://clickhouse.github.io/ClickStack-helm-charts +helm repo update +helm install my-clickstack clickstack/clickstack +``` + +See the [ClickStack Helm documentation](https://clickhouse.com/docs/use-cases/observability/clickstack/deployment/helm) for cloud-specific guides, ingress setup, and troubleshooting. + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://open-telemetry.github.io/opentelemetry-helm-charts | otel-collector(opentelemetry-collector) | ~0.146.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalManifests | list | `[]` | | +| clickhouse.cluster.spec.containerTemplate.image.repository | string | `"clickhouse/clickhouse-server"` | | +| clickhouse.cluster.spec.containerTemplate.image.tag | string | `"25.7-alpine"` | | +| clickhouse.cluster.spec.dataVolumeClaimSpec.accessModes[0] | string | `"ReadWriteOnce"` | | +| clickhouse.cluster.spec.dataVolumeClaimSpec.resources.requests.storage | string | `"10Gi"` | | +| clickhouse.cluster.spec.keeperClusterRef.name | string | `"{{ include \"clickstack.clickhouse.keeper\" . }}"` | | +| clickhouse.cluster.spec.replicas | int | `1` | | +| clickhouse.cluster.spec.settings.extraConfig.keep_alive_timeout | int | `64` | | +| clickhouse.cluster.spec.settings.extraConfig.max_concurrent_queries | int | `100` | | +| clickhouse.cluster.spec.settings.extraConfig.max_connections | int | `4096` | | +| clickhouse.cluster.spec.settings.extraUsersConfig.users.app.grants[0].query | string | `"GRANT SHOW ON *.*, SELECT ON system.*, SELECT ON default.*"` | | +| clickhouse.cluster.spec.settings.extraUsersConfig.users.app.password | string | `"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}"` | | +| clickhouse.cluster.spec.settings.extraUsersConfig.users.app.profile | string | `"default"` | | +| clickhouse.cluster.spec.settings.extraUsersConfig.users.otelcollector.grants[0].query | string | `"GRANT SELECT,INSERT,CREATE,SHOW ON default.*"` | | +| clickhouse.cluster.spec.settings.extraUsersConfig.users.otelcollector.password | string | `"{{ .Values.hyperdx.secrets.CLICKHOUSE_PASSWORD }}"` | | +| clickhouse.cluster.spec.settings.extraUsersConfig.users.otelcollector.profile | string | `"default"` | | +| clickhouse.cluster.spec.shards | int | `1` | | +| clickhouse.enabled | bool | `true` | | +| clickhouse.keeper.spec.dataVolumeClaimSpec.accessModes[0] | string | `"ReadWriteOnce"` | | +| clickhouse.keeper.spec.dataVolumeClaimSpec.resources.requests.storage | string | `"5Gi"` | | +| clickhouse.keeper.spec.replicas | int | `1` | | +| clickhouse.nativePort | int | `9000` | | +| clickhouse.port | int | `8123` | | +| clickhouse.prometheus.enabled | bool | `true` | | +| clickhouse.prometheus.port | int | `9363` | | +| global.imagePullSecrets | list | `[]` | | +| global.imageRegistry | string | `""` | | +| hyperdx.autoscaling.enabled | bool | `false` | | +| hyperdx.autoscaling.spec | object | `{}` | | +| hyperdx.config.API_PORT | string | `"8000"` | | +| hyperdx.config.APP_PORT | string | `"3000"` | | +| hyperdx.config.CLICKHOUSE_ENDPOINT | string | `"tcp://{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}?dial_timeout=10s"` | | +| hyperdx.config.CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT | string | `"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.prometheus.port }}"` | | +| hyperdx.config.CLICKHOUSE_SERVER_ENDPOINT | string | `"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}"` | | +| hyperdx.config.CLICKHOUSE_USER | string | `"otelcollector"` | | +| hyperdx.config.FRONTEND_URL | string | `"http://localhost:3000"` | | +| hyperdx.config.HYPERDX_API_PORT | string | `"8000"` | | +| hyperdx.config.HYPERDX_APP_PORT | string | `"3000"` | | +| hyperdx.config.HYPERDX_LOG_LEVEL | string | `"info"` | | +| hyperdx.config.HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE | string | `"default"` | | +| hyperdx.config.MONGO_URI | string | `"mongodb://hyperdx:{{ .Values.hyperdx.secrets.MONGODB_PASSWORD }}@{{ include \"clickstack.mongodb.svc\" . }}:27017/hyperdx?authSource=hyperdx"` | | +| hyperdx.config.OPAMP_PORT | string | `"4320"` | | +| hyperdx.config.OPAMP_SERVER_URL | string | `"http://{{ include \"clickstack.hyperdx.fullname\" . }}:{{ .Values.hyperdx.ports.opamp }}"` | | +| hyperdx.config.OTEL_EXPORTER_OTLP_ENDPOINT | string | `"http://{{ include \"clickstack.otel.fullname\" . }}:4318"` | | +| hyperdx.config.OTEL_SERVICE_NAME | string | `"hdx-oss-api"` | | +| hyperdx.config.RUN_SCHEDULED_TASKS_EXTERNALLY | string | `"false"` | | +| hyperdx.config.USAGE_STATS_ENABLED | string | `"true"` | | +| hyperdx.deployment.annotations | object | `{}` | | +| hyperdx.deployment.defaultConnections | string | `"[\n {\n \"name\": \"Local ClickHouse\",\n \"host\": \"http://{{ include \"clickstack.clickhouse.svc\" . }}:8123\",\n \"port\": 8123,\n \"username\": \"app\",\n \"password\": \"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}\"\n }\n]\n"` | | +| hyperdx.deployment.defaultSources | string | `"[\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_logs\"\n },\n \"kind\": \"log\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Logs\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_traces\"\n },\n \"kind\": \"trace\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Traces\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"SpanName\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"SpanName\",\n \"eventAttributesExpression\": \"SpanAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"durationExpression\": \"Duration\",\n \"durationPrecision\": 9,\n \"parentSpanIdExpression\": \"ParentSpanId\",\n \"spanNameExpression\": \"SpanName\",\n \"spanKindExpression\": \"SpanKind\",\n \"statusCodeExpression\": \"StatusCode\",\n \"statusMessageExpression\": \"StatusMessage\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"\"\n },\n \"kind\": \"metric\",\n \"timestampValueExpression\": \"TimeUnix\",\n \"name\": \"Metrics\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"metricTables\": {\n \"gauge\": \"otel_metrics_gauge\",\n \"histogram\": \"otel_metrics_histogram\",\n \"sum\": \"otel_metrics_sum\",\n \"_id\": \"682586a8b1f81924e628e808\",\n \"id\": \"682586a8b1f81924e628e808\"\n },\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"hyperdx_sessions\"\n },\n \"kind\": \"session\",\n \"timestampValueExpression\": \"TimestampTime\",\n \"name\": \"Sessions\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"metricSourceId\": \"Metrics\"\n }\n]\n"` | | +| hyperdx.deployment.env | list | `[]` | | +| hyperdx.deployment.existingConfigConnectionsKey | string | `"connections.json"` | | +| hyperdx.deployment.existingConfigSecret | string | `""` | | +| hyperdx.deployment.existingConfigSourcesKey | string | `"sources.json"` | | +| hyperdx.deployment.image.pullPolicy | string | `"IfNotPresent"` | | +| hyperdx.deployment.image.repository | string | `"docker.hyperdx.io/hyperdx/hyperdx"` | | +| hyperdx.deployment.image.tag | string | `nil` | | +| hyperdx.deployment.initContainers | list | `[]` | | +| hyperdx.deployment.labels | object | `{}` | | +| hyperdx.deployment.livenessProbe.enabled | bool | `true` | | +| hyperdx.deployment.livenessProbe.failureThreshold | int | `3` | | +| hyperdx.deployment.livenessProbe.initialDelaySeconds | int | `10` | | +| hyperdx.deployment.livenessProbe.periodSeconds | int | `30` | | +| hyperdx.deployment.livenessProbe.timeoutSeconds | int | `5` | | +| hyperdx.deployment.nodeSelector | object | `{}` | | +| hyperdx.deployment.priorityClassName | string | `""` | | +| hyperdx.deployment.readinessProbe.enabled | bool | `true` | | +| hyperdx.deployment.readinessProbe.failureThreshold | int | `3` | | +| hyperdx.deployment.readinessProbe.initialDelaySeconds | int | `1` | | +| hyperdx.deployment.readinessProbe.periodSeconds | int | `10` | | +| hyperdx.deployment.readinessProbe.timeoutSeconds | int | `5` | | +| hyperdx.deployment.replicas | int | `1` | | +| hyperdx.deployment.resources | object | `{}` | | +| hyperdx.deployment.tolerations | list | `[]` | | +| hyperdx.deployment.topologySpreadConstraints | list | `[]` | | +| hyperdx.deployment.useExistingConfigSecret | bool | `false` | | +| hyperdx.deployment.volumeMounts | list | `[]` | | +| hyperdx.deployment.volumes | list | `[]` | | +| hyperdx.deployment.waitForMongodb.image | string | `"busybox@sha256:1fcf5df59121b92d61e066df1788e8df0cc35623f5d62d9679a41e163b6a0cdb"` | | +| hyperdx.deployment.waitForMongodb.pullPolicy | string | `"IfNotPresent"` | | +| hyperdx.ingress.additionalIngresses | list | `[]` | | +| hyperdx.ingress.annotations | object | `{}` | | +| hyperdx.ingress.enabled | bool | `false` | | +| hyperdx.ingress.spec | object | `{}` | | +| hyperdx.networkPolicy.enabled | bool | `false` | | +| hyperdx.networkPolicy.spec | object | `{}` | | +| hyperdx.podDisruptionBudget.enabled | bool | `false` | | +| hyperdx.ports.api | int | `8000` | | +| hyperdx.ports.app | int | `3000` | | +| hyperdx.ports.opamp | int | `4320` | | +| hyperdx.secrets.CLICKHOUSE_APP_PASSWORD | string | `"hyperdx"` | | +| hyperdx.secrets.CLICKHOUSE_PASSWORD | string | `"otelcollectorpass"` | | +| hyperdx.secrets.HYPERDX_API_KEY | string | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` | | +| hyperdx.secrets.MONGODB_PASSWORD | string | `"hyperdx"` | | +| hyperdx.service.annotations | object | `{}` | | +| hyperdx.service.apiPort.enabled | bool | `false` | | +| hyperdx.service.type | string | `"ClusterIP"` | | +| hyperdx.serviceAccount.annotations | object | `{}` | | +| hyperdx.serviceAccount.create | bool | `false` | | +| hyperdx.serviceAccount.name | string | `""` | | +| hyperdx.tasks.checkAlerts.additionalArgs | object | `{}` | | +| hyperdx.tasks.checkAlerts.resources.limits.cpu | string | `"200m"` | | +| hyperdx.tasks.checkAlerts.resources.limits.memory | string | `"256Mi"` | | +| hyperdx.tasks.checkAlerts.resources.requests.cpu | string | `"100m"` | | +| hyperdx.tasks.checkAlerts.resources.requests.memory | string | `"128Mi"` | | +| hyperdx.tasks.checkAlerts.schedule | string | `"*/1 * * * *"` | | +| hyperdx.tasks.enabled | bool | `false` | | +| mongodb.enabled | bool | `true` | | +| mongodb.spec.additionalMongodConfig."storage.wiredTiger.engineConfig.journalCompressor" | string | `"zlib"` | | +| mongodb.spec.members | int | `1` | | +| mongodb.spec.security.authentication.modes[0] | string | `"SCRAM"` | | +| mongodb.spec.type | string | `"ReplicaSet"` | | +| mongodb.spec.users[0].db | string | `"hyperdx"` | | +| mongodb.spec.users[0].name | string | `"hyperdx"` | | +| mongodb.spec.users[0].passwordSecretRef.name | string | `"{{ include \"clickstack.mongodb.fullname\" . }}-password"` | | +| mongodb.spec.users[0].roles[0].db | string | `"hyperdx"` | | +| mongodb.spec.users[0].roles[0].name | string | `"dbOwner"` | | +| mongodb.spec.users[0].roles[1].db | string | `"admin"` | | +| mongodb.spec.users[0].roles[1].name | string | `"clusterMonitor"` | | +| mongodb.spec.users[0].scramCredentialsSecretName | string | `"{{ include \"clickstack.mongodb.fullname\" . }}-scram"` | | +| mongodb.spec.version | string | `"5.0.32"` | | +| otel-collector.enabled | bool | `true` | | +| otel-collector.extraEnvsFrom[0].configMapRef.name | string | `"clickstack-config"` | | +| otel-collector.extraEnvsFrom[1].secretRef.name | string | `"clickstack-secret"` | | +| otel-collector.image.repository | string | `"docker.clickhouse.com/clickhouse/clickstack-otel-collector"` | | +| otel-collector.image.tag | string | `"2.19.0"` | | +| otel-collector.mode | string | `"deployment"` | | +| otel-collector.ports.fluentd.containerPort | int | `24225` | | +| otel-collector.ports.fluentd.enabled | bool | `true` | | +| otel-collector.ports.fluentd.protocol | string | `"TCP"` | | +| otel-collector.ports.fluentd.servicePort | int | `24225` | | +| otel-collector.ports.health-check.containerPort | int | `13133` | | +| otel-collector.ports.health-check.enabled | bool | `true` | | +| otel-collector.ports.health-check.protocol | string | `"TCP"` | | +| otel-collector.ports.health-check.servicePort | int | `13133` | | +| otel-collector.ports.jaeger-compact.enabled | bool | `false` | | +| otel-collector.ports.jaeger-grpc.enabled | bool | `false` | | +| otel-collector.ports.jaeger-thrift.enabled | bool | `false` | | +| otel-collector.ports.metrics.containerPort | int | `8888` | | +| otel-collector.ports.metrics.enabled | bool | `true` | | +| otel-collector.ports.metrics.protocol | string | `"TCP"` | | +| otel-collector.ports.metrics.servicePort | int | `8888` | | +| otel-collector.ports.otlp-http.containerPort | int | `4318` | | +| otel-collector.ports.otlp-http.enabled | bool | `true` | | +| otel-collector.ports.otlp-http.protocol | string | `"TCP"` | | +| otel-collector.ports.otlp-http.servicePort | int | `4318` | | +| otel-collector.ports.otlp.appProtocol | string | `"grpc"` | | +| otel-collector.ports.otlp.containerPort | int | `4317` | | +| otel-collector.ports.otlp.enabled | bool | `true` | | +| otel-collector.ports.otlp.protocol | string | `"TCP"` | | +| otel-collector.ports.otlp.servicePort | int | `4317` | | +| otel-collector.ports.zipkin.enabled | bool | `false` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/clickstack/README.md.gotmpl b/charts/clickstack/README.md.gotmpl new file mode 100644 index 0000000..ef80827 --- /dev/null +++ b/charts/clickstack/README.md.gotmpl @@ -0,0 +1,30 @@ +# {{ template "chart.name" . }} + +{{ template "chart.versionBadge" . }} +![Build Status](https://github.com/ClickHouse/ClickStack-helm-charts/actions/workflows/helm-test.yaml/badge.svg) + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +{{ template "chart.sourcesSection" . }} + +## Prerequisites + +Install the [clickstack-operators](../clickstack-operators) chart first so MongoDB and ClickHouse CRDs are available. + +## Quick Start + +```bash +helm repo add clickstack https://clickhouse.github.io/ClickStack-helm-charts +helm repo update +helm install my-clickstack clickstack/clickstack +``` + +See the [ClickStack Helm documentation](https://clickhouse.com/docs/use-cases/observability/clickstack/deployment/helm) for cloud-specific guides, ingress setup, and troubleshooting. + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + +{{ template "helm-docs.versionFooter" . }} diff --git a/charts/clickstack/tests/additional-manifests-multi_test.yaml b/charts/clickstack/tests/additional-manifests-multi_test.yaml new file mode 100644 index 0000000..80f7ab3 --- /dev/null +++ b/charts/clickstack/tests/additional-manifests-multi_test.yaml @@ -0,0 +1,13 @@ +suite: Test Additional Manifests Multi +templates: + - additional-manifests.yaml +values: + - values/additional-manifests-multi.yaml +tests: + - it: should render multiple additional manifests + asserts: + - hasDocuments: + count: 2 + - isKind: + of: ServiceAccount + documentIndex: 0 diff --git a/charts/clickstack/tests/autoscaling-enabled_test.yaml b/charts/clickstack/tests/autoscaling-enabled_test.yaml new file mode 100644 index 0000000..2bc66bb --- /dev/null +++ b/charts/clickstack/tests/autoscaling-enabled_test.yaml @@ -0,0 +1,13 @@ +suite: Test HorizontalPodAutoscaler Enabled +templates: + - hyperdx/hpa.yaml +values: + - values/autoscaling-enabled.yaml +tests: + - it: should render HPA when autoscaling is enabled + asserts: + - isKind: + of: HorizontalPodAutoscaler + - equal: + path: spec.minReplicas + value: 2 diff --git a/charts/clickstack/tests/clickhouse-disabled_test.yaml b/charts/clickstack/tests/clickhouse-disabled_test.yaml new file mode 100644 index 0000000..7d96615 --- /dev/null +++ b/charts/clickstack/tests/clickhouse-disabled_test.yaml @@ -0,0 +1,10 @@ +suite: Test ClickHouse Cluster Disabled +templates: + - clickhouse/cluster.yaml +values: + - values/components-disabled.yaml +tests: + - it: should not render clickhouse cluster when disabled + asserts: + - hasDocuments: + count: 0 diff --git a/charts/clickstack/tests/configmap-extended_test.yaml b/charts/clickstack/tests/configmap-extended_test.yaml new file mode 100644 index 0000000..b89294e --- /dev/null +++ b/charts/clickstack/tests/configmap-extended_test.yaml @@ -0,0 +1,17 @@ +suite: Test ClickStack ConfigMap Extended +templates: + - hyperdx/configmap.yaml +values: + - values/configmap-extended.yaml +tests: + - it: should render extended config keys with tpl values + asserts: + - equal: + path: data.CUSTOM_STATIC_VALUE + value: static-value + - equal: + path: data.CUSTOM_TPL_VALUE + value: clickstack + - equal: + path: data.NESTED_TPL + value: RELEASE-NAME-3000 diff --git a/charts/clickstack/tests/deployment-features_test.yaml b/charts/clickstack/tests/deployment-features_test.yaml new file mode 100644 index 0000000..c5a11ad --- /dev/null +++ b/charts/clickstack/tests/deployment-features_test.yaml @@ -0,0 +1,24 @@ +suite: Test HyperDX Deployment Features +templates: + - hyperdx/deployment.yaml +values: + - values/deployment-features.yaml +tests: + - it: should render optional deployment features + asserts: + - isKind: + of: Deployment + - equal: + path: metadata.labels.team + value: observability + - equal: + path: spec.template.spec.nodeSelector["kubernetes.io/os"] + value: linux + - matchRegex: + path: spec.template.spec.initContainers[1].name + pattern: custom-init + - contains: + path: spec.template.spec.containers[0].env + content: + name: CUSTOM_ENV + value: test diff --git a/charts/clickstack/tests/deployment-no-mongodb_test.yaml b/charts/clickstack/tests/deployment-no-mongodb_test.yaml new file mode 100644 index 0000000..577960b --- /dev/null +++ b/charts/clickstack/tests/deployment-no-mongodb_test.yaml @@ -0,0 +1,15 @@ +suite: Test Deployment Without MongoDB Init +templates: + - hyperdx/deployment.yaml +values: + - values/deployment-no-mongodb.yaml +tests: + - it: should render custom init container without mongodb wait + asserts: + - equal: + path: spec.template.spec.initContainers[0].name + value: custom-init + - notContains: + path: spec.template.spec.initContainers + content: + name: wait-for-mongodb diff --git a/charts/clickstack/tests/deployment-probes-disabled_test.yaml b/charts/clickstack/tests/deployment-probes-disabled_test.yaml new file mode 100644 index 0000000..b4a49e8 --- /dev/null +++ b/charts/clickstack/tests/deployment-probes-disabled_test.yaml @@ -0,0 +1,12 @@ +suite: Test Deployment Probes Disabled +templates: + - hyperdx/deployment.yaml +values: + - values/deployment-probes-disabled.yaml +tests: + - it: should omit probes when disabled + asserts: + - isNull: + path: spec.template.spec.containers[0].livenessProbe + - isNull: + path: spec.template.spec.containers[0].readinessProbe diff --git a/charts/clickstack/tests/deployment-replicas_test.yaml b/charts/clickstack/tests/deployment-replicas_test.yaml new file mode 100644 index 0000000..bae4713 --- /dev/null +++ b/charts/clickstack/tests/deployment-replicas_test.yaml @@ -0,0 +1,11 @@ +suite: Test Deployment Replicas When Autoscaling Disabled +templates: + - hyperdx/deployment.yaml +values: + - values/deployment-replicas.yaml +tests: + - it: should render replicas when autoscaling is disabled + asserts: + - equal: + path: spec.replicas + value: 3 diff --git a/charts/clickstack/tests/deployment-tpl-defaults_test.yaml b/charts/clickstack/tests/deployment-tpl-defaults_test.yaml new file mode 100644 index 0000000..a19170e --- /dev/null +++ b/charts/clickstack/tests/deployment-tpl-defaults_test.yaml @@ -0,0 +1,12 @@ +suite: Test Deployment Default Sources Tpl +templates: + - hyperdx/deployment.yaml +values: + - values/deployment-tpl-defaults.yaml +tests: + - it: should render inline default sources env var + asserts: + - isNotEmpty: + path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_SOURCES")] + - isNotEmpty: + path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_CONNECTIONS")] diff --git a/charts/clickstack/tests/existing-config-secret_test.yaml b/charts/clickstack/tests/existing-config-secret_test.yaml new file mode 100644 index 0000000..ee65f9a --- /dev/null +++ b/charts/clickstack/tests/existing-config-secret_test.yaml @@ -0,0 +1,14 @@ +suite: Test Deployment Existing Config Secret +templates: + - hyperdx/deployment.yaml +values: + - values/existing-config-secret.yaml +tests: + - it: should load default connections from existing secret + asserts: + - equal: + path: spec.template.spec.containers[0].env[0].valueFrom.secretKeyRef.name + value: external-hyperdx-config + - equal: + path: spec.template.spec.containers[0].env[0].valueFrom.secretKeyRef.key + value: connections.json diff --git a/charts/clickstack/tests/helpers-fullname_test.yaml b/charts/clickstack/tests/helpers-fullname_test.yaml new file mode 100644 index 0000000..b86399c --- /dev/null +++ b/charts/clickstack/tests/helpers-fullname_test.yaml @@ -0,0 +1,11 @@ +suite: Test Helper Fullname Override Coverage +templates: + - hyperdx/deployment.yaml +values: + - values/fullname-override.yaml +tests: + - it: should use fullnameOverride for deployment name + asserts: + - equal: + path: metadata.name + value: hyperdx-api diff --git a/charts/clickstack/tests/helpers-name-override_test.yaml b/charts/clickstack/tests/helpers-name-override_test.yaml new file mode 100644 index 0000000..0425a54 --- /dev/null +++ b/charts/clickstack/tests/helpers-name-override_test.yaml @@ -0,0 +1,11 @@ +suite: Test Helper Name Override Coverage +templates: + - hyperdx/service.yaml +values: + - values/name-override.yaml +tests: + - it: should use nameOverride in service selector labels + asserts: + - equal: + path: spec.selector["app.kubernetes.io/name"] + value: custom-stack diff --git a/charts/clickstack/tests/helpers-release-name_test.yaml b/charts/clickstack/tests/helpers-release-name_test.yaml new file mode 100644 index 0000000..9df58d2 --- /dev/null +++ b/charts/clickstack/tests/helpers-release-name_test.yaml @@ -0,0 +1,9 @@ +suite: Test Helper Fullname Default Coverage +templates: + - hyperdx/deployment.yaml +tests: + - it: should compose release and chart name when release does not contain chart name + asserts: + - equal: + path: metadata.name + value: RELEASE-NAME-clickstack-app diff --git a/charts/clickstack/tests/ingress-additional_test.yaml b/charts/clickstack/tests/ingress-additional_test.yaml new file mode 100644 index 0000000..b5098bc --- /dev/null +++ b/charts/clickstack/tests/ingress-additional_test.yaml @@ -0,0 +1,14 @@ +suite: Test Additional Ingress Coverage +templates: + - hyperdx/ingress.yaml +values: + - values/ingress-additional.yaml +tests: + - it: should render additional ingress resources + asserts: + - hasDocuments: + count: 2 + - equal: + path: spec.tls[0].secretName + value: otel-collector-tls + documentIndex: 1 diff --git a/charts/clickstack/tests/ingress-default-service_test.yaml b/charts/clickstack/tests/ingress-default-service_test.yaml new file mode 100644 index 0000000..951367b --- /dev/null +++ b/charts/clickstack/tests/ingress-default-service_test.yaml @@ -0,0 +1,14 @@ +suite: Test Ingress Default Service Name +templates: + - hyperdx/ingress.yaml +values: + - values/ingress-default-service.yaml +tests: + - it: should use release fullname when path name is omitted + asserts: + - hasDocuments: + count: 2 + - matchRegex: + path: spec.rules[0].http.paths[0].backend.service.name + pattern: RELEASE-NAME-clickstack$ + documentIndex: 1 diff --git a/charts/clickstack/tests/ingress-enabled_test.yaml b/charts/clickstack/tests/ingress-enabled_test.yaml new file mode 100644 index 0000000..8197c2e --- /dev/null +++ b/charts/clickstack/tests/ingress-enabled_test.yaml @@ -0,0 +1,16 @@ +suite: Test Ingress Enabled Coverage +templates: + - hyperdx/ingress.yaml +values: + - values/ingress-enabled.yaml +tests: + - it: should render primary ingress when enabled + asserts: + - isKind: + of: Ingress + - equal: + path: spec.ingressClassName + value: alb + - equal: + path: metadata.annotations["alb.ingress.kubernetes.io/scheme"] + value: internet-facing diff --git a/charts/clickstack/tests/keeper-disabled_test.yaml b/charts/clickstack/tests/keeper-disabled_test.yaml new file mode 100644 index 0000000..83024d8 --- /dev/null +++ b/charts/clickstack/tests/keeper-disabled_test.yaml @@ -0,0 +1,10 @@ +suite: Test ClickHouse Keeper Disabled +templates: + - clickhouse/keeper.yaml +values: + - values/components-disabled.yaml +tests: + - it: should not render clickhouse keeper when disabled + asserts: + - hasDocuments: + count: 0 diff --git a/charts/clickstack/tests/mongodb-disabled_test.yaml b/charts/clickstack/tests/mongodb-disabled_test.yaml new file mode 100644 index 0000000..9b609f7 --- /dev/null +++ b/charts/clickstack/tests/mongodb-disabled_test.yaml @@ -0,0 +1,10 @@ +suite: Test MongoDB Community Disabled +templates: + - mongodb/community.yaml +values: + - values/components-disabled.yaml +tests: + - it: should not render mongodb community when disabled + asserts: + - hasDocuments: + count: 0 diff --git a/charts/clickstack/tests/networkpolicy-enabled_test.yaml b/charts/clickstack/tests/networkpolicy-enabled_test.yaml new file mode 100644 index 0000000..1001191 --- /dev/null +++ b/charts/clickstack/tests/networkpolicy-enabled_test.yaml @@ -0,0 +1,13 @@ +suite: Test NetworkPolicy Enabled +templates: + - hyperdx/networkpolicy.yaml +values: + - values/networkpolicy-enabled.yaml +tests: + - it: should render network policy when enabled + asserts: + - isKind: + of: NetworkPolicy + - contains: + path: spec.policyTypes + content: Ingress diff --git a/charts/clickstack/tests/notes-ingress_test.yaml b/charts/clickstack/tests/notes-ingress_test.yaml new file mode 100644 index 0000000..aa3e67e --- /dev/null +++ b/charts/clickstack/tests/notes-ingress_test.yaml @@ -0,0 +1,12 @@ +suite: Test Chart Notes Ingress Enabled +templates: + - NOTES.txt +values: + - values/notes-ingress-enabled.yaml +tests: + - it: should render ingress guidance when ingress is enabled + asserts: + - matchRegexRaw: + pattern: Ingress is enabled + - matchRegexRaw: + pattern: kubectl get ingress diff --git a/charts/clickstack/tests/notes_test.yaml b/charts/clickstack/tests/notes_test.yaml new file mode 100644 index 0000000..b012e5f --- /dev/null +++ b/charts/clickstack/tests/notes_test.yaml @@ -0,0 +1,10 @@ +suite: Test Chart Notes +templates: + - NOTES.txt +tests: + - it: should render post-install notes with port-forward guidance + asserts: + - matchRegexRaw: + pattern: ClickStack has been installed + - matchRegexRaw: + pattern: kubectl port-forward diff --git a/charts/clickstack/tests/pdb-enabled_test.yaml b/charts/clickstack/tests/pdb-enabled_test.yaml new file mode 100644 index 0000000..3f07bb5 --- /dev/null +++ b/charts/clickstack/tests/pdb-enabled_test.yaml @@ -0,0 +1,13 @@ +suite: Test HyperDX PodDisruptionBudget Enabled +templates: + - hyperdx/pdb.yaml +values: + - values/pdb-enabled.yaml +tests: + - it: should render PDB when enabled + asserts: + - isKind: + of: PodDisruptionBudget + - equal: + path: spec.minAvailable + value: 1 diff --git a/charts/clickstack/tests/pdb-labels_test.yaml b/charts/clickstack/tests/pdb-labels_test.yaml new file mode 100644 index 0000000..9049621 --- /dev/null +++ b/charts/clickstack/tests/pdb-labels_test.yaml @@ -0,0 +1,13 @@ +suite: Test HyperDX PodDisruptionBudget With Labels +templates: + - hyperdx/pdb.yaml +values: + - values/pdb-with-labels.yaml +tests: + - it: should render deployment labels on PDB metadata + asserts: + - isKind: + of: PodDisruptionBudget + - equal: + path: metadata.labels.team + value: platform diff --git a/charts/clickstack/tests/secret-custom_test.yaml b/charts/clickstack/tests/secret-custom_test.yaml new file mode 100644 index 0000000..f1b4be6 --- /dev/null +++ b/charts/clickstack/tests/secret-custom_test.yaml @@ -0,0 +1,14 @@ +suite: Test ClickStack Secret Custom Values +templates: + - hyperdx/secret.yaml +values: + - values/secret-custom.yaml +tests: + - it: should render custom secret values + asserts: + - equal: + path: stringData.HYPERDX_API_KEY + value: custom-api-key + - equal: + path: stringData.CLICKHOUSE_APP_PASSWORD + value: custom-app-password diff --git a/charts/clickstack/tests/secret-disabled_test.yaml b/charts/clickstack/tests/secret-disabled_test.yaml new file mode 100644 index 0000000..5de38c9 --- /dev/null +++ b/charts/clickstack/tests/secret-disabled_test.yaml @@ -0,0 +1,10 @@ +suite: Test ClickStack Secret Disabled +templates: + - hyperdx/secret.yaml +values: + - values/secret-disabled.yaml +tests: + - it: should not render secret when secrets is null and subcharts disabled + asserts: + - hasDocuments: + count: 0 diff --git a/charts/clickstack/tests/service-features_test.yaml b/charts/clickstack/tests/service-features_test.yaml new file mode 100644 index 0000000..2417306 --- /dev/null +++ b/charts/clickstack/tests/service-features_test.yaml @@ -0,0 +1,17 @@ +suite: Test HyperDX Service Features +templates: + - hyperdx/service.yaml +values: + - values/service-features.yaml +tests: + - it: should render load balancer service with api port + asserts: + - equal: + path: spec.type + value: LoadBalancer + - equal: + path: metadata.annotations["service.beta.kubernetes.io/aws-load-balancer-type"] + value: nlb + - equal: + path: spec.ports[1].name + value: api diff --git a/charts/clickstack/tests/serviceaccount-annotated_test.yaml b/charts/clickstack/tests/serviceaccount-annotated_test.yaml new file mode 100644 index 0000000..1953d96 --- /dev/null +++ b/charts/clickstack/tests/serviceaccount-annotated_test.yaml @@ -0,0 +1,13 @@ +suite: Test ServiceAccount Annotations +templates: + - hyperdx/serviceaccount.yaml +values: + - values/serviceaccount-annotated.yaml +tests: + - it: should render service account annotations + asserts: + - isKind: + of: ServiceAccount + - equal: + path: metadata.annotations["eks.amazonaws.com/role-arn"] + value: arn:aws:iam::123456789012:role/hyperdx diff --git a/charts/clickstack/tests/tasks-enabled_test.yaml b/charts/clickstack/tests/tasks-enabled_test.yaml new file mode 100644 index 0000000..7f8039a --- /dev/null +++ b/charts/clickstack/tests/tasks-enabled_test.yaml @@ -0,0 +1,13 @@ +suite: Test Check Alerts CronJob Enabled +templates: + - hyperdx/cronjob-check-alerts.yaml +values: + - values/tasks-enabled.yaml +tests: + - it: should render cronjob when tasks are enabled + asserts: + - isKind: + of: CronJob + - equal: + path: spec.jobTemplate.spec.template.spec.containers[0].command[2] + value: check-alerts diff --git a/charts/clickstack/tests/tasks-pre-esbuild_test.yaml b/charts/clickstack/tests/tasks-pre-esbuild_test.yaml new file mode 100644 index 0000000..400684a --- /dev/null +++ b/charts/clickstack/tests/tasks-pre-esbuild_test.yaml @@ -0,0 +1,11 @@ +suite: Test Check Alerts CronJob Pre Esbuild +templates: + - hyperdx/cronjob-check-alerts.yaml +values: + - values/tasks-pre-esbuild.yaml +tests: + - it: should use pre-esbuild command path + asserts: + - equal: + path: spec.jobTemplate.spec.template.spec.containers[0].command[1] + value: /app/packages/api/tasks/index diff --git a/charts/clickstack/tests/tasks-with-args_test.yaml b/charts/clickstack/tests/tasks-with-args_test.yaml new file mode 100644 index 0000000..f41dd61 --- /dev/null +++ b/charts/clickstack/tests/tasks-with-args_test.yaml @@ -0,0 +1,14 @@ +suite: Test Check Alerts CronJob With Args +templates: + - hyperdx/cronjob-check-alerts.yaml +values: + - values/tasks-with-args.yaml +tests: + - it: should include additional args in command + asserts: + - contains: + path: spec.jobTemplate.spec.template.spec.containers[0].command + content: "--concurrency" + - contains: + path: spec.jobTemplate.spec.template.spec.containers[0].command + content: "4" diff --git a/charts/clickstack/tests/tasks-with-imagepullsecrets_test.yaml b/charts/clickstack/tests/tasks-with-imagepullsecrets_test.yaml new file mode 100644 index 0000000..3204b44 --- /dev/null +++ b/charts/clickstack/tests/tasks-with-imagepullsecrets_test.yaml @@ -0,0 +1,11 @@ +suite: Test Check Alerts CronJob With Image Pull Secrets +templates: + - hyperdx/cronjob-check-alerts.yaml +values: + - values/tasks-with-imagepullsecrets.yaml +tests: + - it: should render imagePullSecrets on cronjob pod spec + asserts: + - equal: + path: spec.jobTemplate.spec.template.spec.imagePullSecrets[0].name + value: regcred diff --git a/charts/clickstack/tests/values/additional-manifests-multi.yaml b/charts/clickstack/tests/values/additional-manifests-multi.yaml new file mode 100644 index 0000000..454078b --- /dev/null +++ b/charts/clickstack/tests/values/additional-manifests-multi.yaml @@ -0,0 +1,11 @@ +additionalManifests: + - apiVersion: v1 + kind: ServiceAccount + metadata: + name: extra-service-account + - apiVersion: v1 + kind: ConfigMap + metadata: + name: extra-config + data: + key: value diff --git a/charts/clickstack/tests/values/autoscaling-enabled.yaml b/charts/clickstack/tests/values/autoscaling-enabled.yaml new file mode 100644 index 0000000..9666735 --- /dev/null +++ b/charts/clickstack/tests/values/autoscaling-enabled.yaml @@ -0,0 +1,13 @@ +hyperdx: + autoscaling: + enabled: true + spec: + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 diff --git a/charts/clickstack/tests/values/components-disabled.yaml b/charts/clickstack/tests/values/components-disabled.yaml new file mode 100644 index 0000000..90359fb --- /dev/null +++ b/charts/clickstack/tests/values/components-disabled.yaml @@ -0,0 +1,6 @@ +clickhouse: + enabled: false +mongodb: + enabled: false +otel-collector: + enabled: false diff --git a/charts/clickstack/tests/values/configmap-extended.yaml b/charts/clickstack/tests/values/configmap-extended.yaml new file mode 100644 index 0000000..6b07e95 --- /dev/null +++ b/charts/clickstack/tests/values/configmap-extended.yaml @@ -0,0 +1,5 @@ +hyperdx: + config: + CUSTOM_TPL_VALUE: '{{ include "clickstack.name" . }}' + CUSTOM_STATIC_VALUE: static-value + NESTED_TPL: '{{ .Release.Name }}-{{ .Values.hyperdx.ports.app }}' diff --git a/charts/clickstack/tests/values/deployment-features.yaml b/charts/clickstack/tests/values/deployment-features.yaml new file mode 100644 index 0000000..3546c39 --- /dev/null +++ b/charts/clickstack/tests/values/deployment-features.yaml @@ -0,0 +1,39 @@ +hyperdx: + deployment: + labels: + team: observability + annotations: + prometheus.io/scrape: "true" + nodeSelector: + kubernetes.io/os: linux + tolerations: + - key: dedicated + operator: Equal + value: observability + effect: NoSchedule + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/name: clickstack + priorityClassName: high-priority + initContainers: + - name: custom-init + image: busybox:1.36 + command: ["sh", "-c", "echo init"] + volumes: + - name: cache + emptyDir: {} + volumeMounts: + - name: cache + mountPath: /cache + env: + - name: CUSTOM_ENV + value: test + serviceAccount: + create: true +global: + imagePullSecrets: + - name: regcred diff --git a/charts/clickstack/tests/values/deployment-no-mongodb.yaml b/charts/clickstack/tests/values/deployment-no-mongodb.yaml new file mode 100644 index 0000000..e3fd64e --- /dev/null +++ b/charts/clickstack/tests/values/deployment-no-mongodb.yaml @@ -0,0 +1,8 @@ +mongodb: + enabled: false +hyperdx: + deployment: + initContainers: + - name: custom-init + image: busybox:1.36 + command: ["sh", "-c", "echo init"] diff --git a/charts/clickstack/tests/values/deployment-probes-disabled.yaml b/charts/clickstack/tests/values/deployment-probes-disabled.yaml new file mode 100644 index 0000000..1edab69 --- /dev/null +++ b/charts/clickstack/tests/values/deployment-probes-disabled.yaml @@ -0,0 +1,7 @@ +hyperdx: + deployment: + livenessProbe: + enabled: false + readinessProbe: + enabled: false + resources: {} diff --git a/charts/clickstack/tests/values/deployment-replicas.yaml b/charts/clickstack/tests/values/deployment-replicas.yaml new file mode 100644 index 0000000..a25dc9f --- /dev/null +++ b/charts/clickstack/tests/values/deployment-replicas.yaml @@ -0,0 +1,5 @@ +hyperdx: + autoscaling: + enabled: false + deployment: + replicas: 3 diff --git a/charts/clickstack/tests/values/deployment-tpl-defaults.yaml b/charts/clickstack/tests/values/deployment-tpl-defaults.yaml new file mode 100644 index 0000000..392f1c6 --- /dev/null +++ b/charts/clickstack/tests/values/deployment-tpl-defaults.yaml @@ -0,0 +1,112 @@ +hyperdx: + deployment: + useExistingConfigSecret: false + defaultConnections: | + [ + { + "name": "Local ClickHouse", + "host": "http://{{ include "clickstack.clickhouse.svc" . }}:8123", + "port": 8123, + "username": "app", + "password": "{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}" + } + ] + defaultSources: | + [ + { + "from": { + "databaseName": "default", + "tableName": "otel_logs" + }, + "kind": "log", + "timestampValueExpression": "Timestamp", + "name": "Logs", + "displayedTimestampValueExpression": "Timestamp", + "implicitColumnExpression": "Body", + "serviceNameExpression": "ServiceName", + "bodyExpression": "Body", + "eventAttributesExpression": "LogAttributes", + "resourceAttributesExpression": "ResourceAttributes", + "defaultTableSelectExpression": "Timestamp,ServiceName,SeverityText,Body", + "severityTextExpression": "SeverityText", + "traceIdExpression": "TraceId", + "spanIdExpression": "SpanId", + "connection": "Local ClickHouse", + "traceSourceId": "Traces", + "sessionSourceId": "Sessions", + "metricSourceId": "Metrics" + }, + { + "from": { + "databaseName": "default", + "tableName": "otel_traces" + }, + "kind": "trace", + "timestampValueExpression": "Timestamp", + "name": "Traces", + "displayedTimestampValueExpression": "Timestamp", + "implicitColumnExpression": "SpanName", + "serviceNameExpression": "ServiceName", + "bodyExpression": "SpanName", + "eventAttributesExpression": "SpanAttributes", + "resourceAttributesExpression": "ResourceAttributes", + "defaultTableSelectExpression": "Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName", + "traceIdExpression": "TraceId", + "spanIdExpression": "SpanId", + "durationExpression": "Duration", + "durationPrecision": 9, + "parentSpanIdExpression": "ParentSpanId", + "spanNameExpression": "SpanName", + "spanKindExpression": "SpanKind", + "statusCodeExpression": "StatusCode", + "statusMessageExpression": "StatusMessage", + "connection": "Local ClickHouse", + "logSourceId": "Logs", + "sessionSourceId": "Sessions", + "metricSourceId": "Metrics" + }, + { + "from": { + "databaseName": "default", + "tableName": "" + }, + "kind": "metric", + "timestampValueExpression": "TimeUnix", + "name": "Metrics", + "resourceAttributesExpression": "ResourceAttributes", + "metricTables": { + "gauge": "otel_metrics_gauge", + "histogram": "otel_metrics_histogram", + "sum": "otel_metrics_sum", + "_id": "682586a8b1f81924e628e808", + "id": "682586a8b1f81924e628e808" + }, + "connection": "Local ClickHouse", + "logSourceId": "Logs", + "traceSourceId": "Traces", + "sessionSourceId": "Sessions" + }, + { + "from": { + "databaseName": "default", + "tableName": "hyperdx_sessions" + }, + "kind": "session", + "timestampValueExpression": "TimestampTime", + "name": "Sessions", + "displayedTimestampValueExpression": "Timestamp", + "implicitColumnExpression": "Body", + "serviceNameExpression": "ServiceName", + "bodyExpression": "Body", + "eventAttributesExpression": "LogAttributes", + "resourceAttributesExpression": "ResourceAttributes", + "defaultTableSelectExpression": "Timestamp,ServiceName,SeverityText,Body", + "severityTextExpression": "SeverityText", + "traceIdExpression": "TraceId", + "spanIdExpression": "SpanId", + "connection": "Local ClickHouse", + "logSourceId": "Logs", + "traceSourceId": "Traces", + "metricSourceId": "Metrics" + } + ] diff --git a/charts/clickstack/tests/values/existing-config-secret.yaml b/charts/clickstack/tests/values/existing-config-secret.yaml new file mode 100644 index 0000000..b572111 --- /dev/null +++ b/charts/clickstack/tests/values/existing-config-secret.yaml @@ -0,0 +1,6 @@ +hyperdx: + deployment: + useExistingConfigSecret: true + existingConfigSecret: external-hyperdx-config + existingConfigConnectionsKey: connections.json + existingConfigSourcesKey: sources.json diff --git a/charts/clickstack/tests/values/fullname-override.yaml b/charts/clickstack/tests/values/fullname-override.yaml new file mode 100644 index 0000000..2ba028e --- /dev/null +++ b/charts/clickstack/tests/values/fullname-override.yaml @@ -0,0 +1,2 @@ +fullnameOverride: hyperdx-api +nameOverride: custom-stack diff --git a/charts/clickstack/tests/values/ingress-additional.yaml b/charts/clickstack/tests/values/ingress-additional.yaml new file mode 100644 index 0000000..d58dccb --- /dev/null +++ b/charts/clickstack/tests/values/ingress-additional.yaml @@ -0,0 +1,30 @@ +hyperdx: + ingress: + enabled: true + spec: + rules: + - host: hyperdx.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: test + port: + number: 3000 + additionalIngresses: + - name: otel-collector + annotations: + testProperty: "true" + ingressClassName: nginx + hosts: + - host: collector.example.com + paths: + - path: / + pathType: Prefix + port: 4318 + tls: + - secretName: otel-collector-tls + hosts: + - collector.example.com diff --git a/charts/clickstack/tests/values/ingress-default-service.yaml b/charts/clickstack/tests/values/ingress-default-service.yaml new file mode 100644 index 0000000..ea82647 --- /dev/null +++ b/charts/clickstack/tests/values/ingress-default-service.yaml @@ -0,0 +1,24 @@ +hyperdx: + ingress: + enabled: true + spec: + rules: + - host: test.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: test + port: + number: 80 + additionalIngresses: + - name: default-service + ingressClassName: nginx + hosts: + - host: default.example.com + paths: + - path: / + pathType: Prefix + port: 8080 diff --git a/charts/clickstack/tests/values/ingress-enabled.yaml b/charts/clickstack/tests/values/ingress-enabled.yaml new file mode 100644 index 0000000..7ae55c1 --- /dev/null +++ b/charts/clickstack/tests/values/ingress-enabled.yaml @@ -0,0 +1,18 @@ +hyperdx: + ingress: + enabled: true + annotations: + alb.ingress.kubernetes.io/scheme: internet-facing + spec: + ingressClassName: alb + rules: + - host: hyperdx.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: my-service + port: + number: 8000 diff --git a/charts/clickstack/tests/values/name-override.yaml b/charts/clickstack/tests/values/name-override.yaml new file mode 100644 index 0000000..a58b18c --- /dev/null +++ b/charts/clickstack/tests/values/name-override.yaml @@ -0,0 +1 @@ +nameOverride: custom-stack diff --git a/charts/clickstack/tests/values/networkpolicy-enabled.yaml b/charts/clickstack/tests/values/networkpolicy-enabled.yaml new file mode 100644 index 0000000..4e4484e --- /dev/null +++ b/charts/clickstack/tests/values/networkpolicy-enabled.yaml @@ -0,0 +1,10 @@ +hyperdx: + networkPolicy: + enabled: true + spec: + podSelector: + matchLabels: + app.kubernetes.io/name: clickstack + policyTypes: + - Ingress + - Egress diff --git a/charts/clickstack/tests/values/notes-ingress-enabled.yaml b/charts/clickstack/tests/values/notes-ingress-enabled.yaml new file mode 100644 index 0000000..d6e9d10 --- /dev/null +++ b/charts/clickstack/tests/values/notes-ingress-enabled.yaml @@ -0,0 +1,15 @@ +hyperdx: + ingress: + enabled: true + spec: + rules: + - host: hyperdx.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: test + port: + number: 3000 diff --git a/charts/clickstack/tests/values/pdb-enabled.yaml b/charts/clickstack/tests/values/pdb-enabled.yaml new file mode 100644 index 0000000..c0ee815 --- /dev/null +++ b/charts/clickstack/tests/values/pdb-enabled.yaml @@ -0,0 +1,3 @@ +hyperdx: + podDisruptionBudget: + enabled: true diff --git a/charts/clickstack/tests/values/pdb-with-labels.yaml b/charts/clickstack/tests/values/pdb-with-labels.yaml new file mode 100644 index 0000000..a1b0a83 --- /dev/null +++ b/charts/clickstack/tests/values/pdb-with-labels.yaml @@ -0,0 +1,6 @@ +hyperdx: + podDisruptionBudget: + enabled: true + deployment: + labels: + team: platform diff --git a/charts/clickstack/tests/values/secret-custom.yaml b/charts/clickstack/tests/values/secret-custom.yaml new file mode 100644 index 0000000..555b9ab --- /dev/null +++ b/charts/clickstack/tests/values/secret-custom.yaml @@ -0,0 +1,5 @@ +hyperdx: + secrets: + HYPERDX_API_KEY: custom-api-key + CLICKHOUSE_PASSWORD: custom-password + CLICKHOUSE_APP_PASSWORD: custom-app-password diff --git a/charts/clickstack/tests/values/secret-disabled.yaml b/charts/clickstack/tests/values/secret-disabled.yaml new file mode 100644 index 0000000..64a04a4 --- /dev/null +++ b/charts/clickstack/tests/values/secret-disabled.yaml @@ -0,0 +1,8 @@ +mongodb: + enabled: false +clickhouse: + enabled: false +otel-collector: + enabled: false +hyperdx: + secrets: null diff --git a/charts/clickstack/tests/values/service-features.yaml b/charts/clickstack/tests/values/service-features.yaml new file mode 100644 index 0000000..21dc5c5 --- /dev/null +++ b/charts/clickstack/tests/values/service-features.yaml @@ -0,0 +1,7 @@ +hyperdx: + service: + type: LoadBalancer + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: nlb + apiPort: + enabled: true diff --git a/charts/clickstack/tests/values/serviceaccount-annotated.yaml b/charts/clickstack/tests/values/serviceaccount-annotated.yaml new file mode 100644 index 0000000..c9021d7 --- /dev/null +++ b/charts/clickstack/tests/values/serviceaccount-annotated.yaml @@ -0,0 +1,5 @@ +hyperdx: + serviceAccount: + create: true + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/hyperdx diff --git a/charts/clickstack/tests/values/tasks-enabled.yaml b/charts/clickstack/tests/values/tasks-enabled.yaml new file mode 100644 index 0000000..0a83e17 --- /dev/null +++ b/charts/clickstack/tests/values/tasks-enabled.yaml @@ -0,0 +1,6 @@ +hyperdx: + tasks: + enabled: true + deployment: + image: + tag: "2.8.0" diff --git a/charts/clickstack/tests/values/tasks-pre-esbuild.yaml b/charts/clickstack/tests/values/tasks-pre-esbuild.yaml new file mode 100644 index 0000000..0a31498 --- /dev/null +++ b/charts/clickstack/tests/values/tasks-pre-esbuild.yaml @@ -0,0 +1,6 @@ +hyperdx: + tasks: + enabled: true + deployment: + image: + tag: "2.6.0" diff --git a/charts/clickstack/tests/values/tasks-with-args.yaml b/charts/clickstack/tests/values/tasks-with-args.yaml new file mode 100644 index 0000000..d57ffa7 --- /dev/null +++ b/charts/clickstack/tests/values/tasks-with-args.yaml @@ -0,0 +1,10 @@ +hyperdx: + tasks: + enabled: true + checkAlerts: + additionalArgs: + concurrency: 4 + sourceTimeoutMs: 90000 + deployment: + image: + tag: "2.8.0" diff --git a/charts/clickstack/tests/values/tasks-with-imagepullsecrets.yaml b/charts/clickstack/tests/values/tasks-with-imagepullsecrets.yaml new file mode 100644 index 0000000..6f70dc0 --- /dev/null +++ b/charts/clickstack/tests/values/tasks-with-imagepullsecrets.yaml @@ -0,0 +1,9 @@ +hyperdx: + tasks: + enabled: true + deployment: + image: + tag: "2.8.0" +global: + imagePullSecrets: + - name: regcred diff --git a/scripts/helmcov.sh b/scripts/helmcov.sh new file mode 100755 index 0000000..6cf8bbf --- /dev/null +++ b/scripts/helmcov.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -e +set -o pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +CHART_PATH="${CHART_PATH:-charts/clickstack}" +TESTS_PATH="${TESTS_PATH:-charts/clickstack/tests}" +HELMCOV_IMAGE="${HELMCOV_IMAGE:-ghcr.io/jordan-simonovski/helmcov:v0.3.2}" +COVERAGE_OUT="${COVERAGE_OUT:-coverage.out}" +COVERAGE_XML="${COVERAGE_XML:-coverage.xml}" +THRESHOLD="${THRESHOLD:-25}" +MAX_SCENARIOS="${MAX_SCENARIOS:-20}" +SEED="${SEED:-42}" +VERBOSE="${VERBOSE:-}" + +if ! command -v docker >/dev/null; then + echo "docker is required for helmcov; install Docker and retry." >&2 + exit 1 +fi + +chart_abs="${ROOT_DIR}/${CHART_PATH}" +tests_abs="${ROOT_DIR}/${TESTS_PATH}" + +if [[ ! -f "${chart_abs}/Chart.yaml" ]]; then + echo "Chart not found: ${chart_abs}/Chart.yaml" >&2 + exit 1 +fi +if ! compgen -G "${tests_abs}/*_test.yaml" >/dev/null; then + echo "No helm-unittest suites found in ${tests_abs}" >&2 + exit 1 +fi + +helmcov_args=( + --chart "/work/${CHART_PATH}" + --tests "/work/${TESTS_PATH}" + --format go + --format cobertura + --go-coverprofile "/work/${COVERAGE_OUT}" + --cobertura-file "/work/${COVERAGE_XML}" + --max-scenarios "${MAX_SCENARIOS}" + --seed "${SEED}" +) + +if [[ "${THRESHOLD}" != "0" ]]; then + helmcov_args+=(--threshold "${THRESHOLD}") +fi +if [[ "${VERBOSE}" == "1" ]]; then + helmcov_args+=(--verbose) +fi + +docker run --rm \ + --platform linux/amd64 \ + -v "${ROOT_DIR}:/work" \ + -w /work \ + "${HELMCOV_IMAGE}" \ + "${helmcov_args[@]}" diff --git a/scripts/helmdocs.sh b/scripts/helmdocs.sh new file mode 100755 index 0000000..9a199d3 --- /dev/null +++ b/scripts/helmdocs.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +HELM_DOCS_BIN="${ROOT_DIR}/.tools/helm-docs" + +if [[ ! -x "${HELM_DOCS_BIN}" ]]; then + "${ROOT_DIR}/scripts/install-helm-docs.sh" +fi + +echo "Generating chart README files..." +"${HELM_DOCS_BIN}" \ + --chart-search-root "${ROOT_DIR}/charts" \ + --template-files README.md.gotmpl \ + --badge-style flat diff --git a/scripts/install-helm-docs.sh b/scripts/install-helm-docs.sh new file mode 100755 index 0000000..d62ecc5 --- /dev/null +++ b/scripts/install-helm-docs.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +TOOLS_DIR="${ROOT_DIR}/.tools" +HELM_DOCS_VERSION="${HELM_DOCS_VERSION:-v1.14.2}" +HELM_DOCS_BIN="${TOOLS_DIR}/helm-docs" + +if [[ -x "${HELM_DOCS_BIN}" ]]; then + echo "helm-docs already installed at ${HELM_DOCS_BIN}" + exit 0 +fi + +os="$(uname | tr '[:upper:]' '[:lower:]')" +arch="$(uname -m)" +case "${arch}" in + x86_64) arch="x86_64" ;; + arm64|aarch64) arch="arm64" ;; + *) + echo "unsupported architecture for helm-docs: ${arch}" >&2 + exit 1 + ;; +esac + +version="${HELM_DOCS_VERSION#v}" +archive="helm-docs_${version}_${os}_${arch}.tar.gz" +url="https://github.com/norwoodj/helm-docs/releases/download/${HELM_DOCS_VERSION}/${archive}" + +mkdir -p "${TOOLS_DIR}" +tmp_dir="$(mktemp -d)" +trap 'rm -rf "${tmp_dir}"' EXIT + +echo "Downloading helm-docs ${HELM_DOCS_VERSION}..." +curl -fsSL "${url}" -o "${tmp_dir}/${archive}" +tar -xzf "${tmp_dir}/${archive}" -C "${tmp_dir}" helm-docs +install -m 0755 "${tmp_dir}/helm-docs" "${HELM_DOCS_BIN}" +echo "Installed helm-docs at ${HELM_DOCS_BIN}" diff --git a/scripts/install-hooks.sh b/scripts/install-hooks.sh new file mode 100755 index 0000000..952f4a1 --- /dev/null +++ b/scripts/install-hooks.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(git rev-parse --show-toplevel)" +hooks_dir="$repo_root/.githooks" +git_hooks_dir="$repo_root/.git/hooks" + +if [ ! -d "$hooks_dir" ]; then + echo "missing hooks directory: $hooks_dir" >&2 + exit 1 +fi + +shopt -s nullglob +hooks=("$hooks_dir"/*) +shopt -u nullglob + +if [ "${#hooks[@]}" -eq 0 ]; then + echo "no hooks found in $hooks_dir" >&2 + exit 1 +fi + +for hook in "${hooks[@]}"; do + name="$(basename "$hook")" + cp "$hook" "$git_hooks_dir/$name" + chmod +x "$git_hooks_dir/$name" + echo "installed $name hook at $git_hooks_dir/$name" +done From 16269c618008bc925917c5794ad1db8580389c6f Mon Sep 17 00:00:00 2001 From: Jordan Simonovski Date: Sat, 27 Jun 2026 11:50:23 +1000 Subject: [PATCH 2/5] chore: fixed up helmdocs values --- AGENTS.md | 3 + charts/clickstack-operators/.helmignore | 2 + charts/clickstack-operators/README.md | 9 +- charts/clickstack-operators/values.yaml | 9 +- charts/clickstack/.helmignore | 5 + charts/clickstack/README.md | 189 +++++------------------- charts/clickstack/README.md.gotmpl | 2 + charts/clickstack/values.yaml | 115 ++++++-------- scripts/helmdocs.sh | 3 +- 9 files changed, 105 insertions(+), 232 deletions(-) create mode 100644 charts/clickstack-operators/.helmignore create mode 100644 charts/clickstack/.helmignore diff --git a/AGENTS.md b/AGENTS.md index 7bcc142..ea18fb6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,6 +89,7 @@ make docs ``` Regenerates `charts/*/README.md` from `values.yaml` using [helm-docs](https://github.com/norwoodj/helm-docs). +Only values with `#` comments in `values.yaml` appear in the README (`--ignore-non-descriptions`). Each chart README includes version and CI build status badges. The pre-commit hook verifies docs are up to date when values or templates change. @@ -141,6 +142,8 @@ Requires: `kind`, `helm`, `kubectl`, `yq`. ### Values Structure (`values.yaml`) - Top-level keys: `global`, `hyperdx`, `clickhouse`, `mongodb`, `otel-collector` +- Document user-facing values with `# --` comments directly above each key (helm-docs format) +- `make docs` omits undocumented keys (`--ignore-non-descriptions`); prefer commenting parent keys for operator/subchart passthrough specs - `hyperdx.config` — non-sensitive env vars (ConfigMap), supports `tpl` expressions - `hyperdx.secrets` — sensitive env vars (Secret); set to `null` to skip creation - `hyperdx.deployment` — Deployment spec (image, replicas, resources, probes, etc.) diff --git a/charts/clickstack-operators/.helmignore b/charts/clickstack-operators/.helmignore new file mode 100644 index 0000000..04e4686 --- /dev/null +++ b/charts/clickstack-operators/.helmignore @@ -0,0 +1,2 @@ +# helm-docs source template (README.md is the published doc) +README.md.gotmpl diff --git a/charts/clickstack-operators/README.md b/charts/clickstack-operators/README.md index e13fbf0..c4c7088 100644 --- a/charts/clickstack-operators/README.md +++ b/charts/clickstack-operators/README.md @@ -28,10 +28,11 @@ After the operators are ready, install the [clickstack](../clickstack) chart. | Key | Type | Default | Description | |-----|------|---------|-------------| -| clickhouse-operator.certManager.enable | bool | `false` | | -| clickhouse-operator.crd.enable | bool | `true` | | -| clickhouse-operator.webhook.enable | bool | `false` | | -| mongodb-operator.operator.watchedResources[0] | string | `"mongodbcommunity"` | | +| clickhouse-operator | object | `{"certManager":{"enable":false},"crd":{"enable":true},"webhook":{"enable":false}}` | ClickHouse Operator subchart. See https://clickhouse.com/docs/clickhouse-operator/overview | +| clickhouse-operator.certManager.enable | bool | `false` | Install cert-manager resources for the operator webhook. | +| clickhouse-operator.crd.enable | bool | `true` | Install ClickHouse operator CRDs with this chart. | +| clickhouse-operator.webhook.enable | bool | `false` | Enable the operator admission webhook (requires cert-manager when true). | +| mongodb-operator | object | `{"operator":{"watchedResources":["mongodbcommunity"]}}` | MongoDB Kubernetes Operator subchart. See https://github.com/mongodb/mongodb-kubernetes | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/clickstack-operators/values.yaml b/charts/clickstack-operators/values.yaml index 85fd44f..f59b32b 100644 --- a/charts/clickstack-operators/values.yaml +++ b/charts/clickstack-operators/values.yaml @@ -1,16 +1,17 @@ -# MongoDB Kubernetes Operator (MCK) subchart configuration -# See https://github.com/mongodb/mongodb-kubernetes for all options +# -- MongoDB Kubernetes Operator subchart. See https://github.com/mongodb/mongodb-kubernetes mongodb-operator: operator: watchedResources: - mongodbcommunity -# ClickHouse Operator subchart configuration -# See https://clickhouse.com/docs/clickhouse-operator/overview for all options +# -- ClickHouse Operator subchart. See https://clickhouse.com/docs/clickhouse-operator/overview clickhouse-operator: webhook: + # -- Enable the operator admission webhook (requires cert-manager when true). enable: false certManager: + # -- Install cert-manager resources for the operator webhook. enable: false crd: + # -- Install ClickHouse operator CRDs with this chart. enable: true diff --git a/charts/clickstack/.helmignore b/charts/clickstack/.helmignore new file mode 100644 index 0000000..fba40f1 --- /dev/null +++ b/charts/clickstack/.helmignore @@ -0,0 +1,5 @@ +# helm-unittest / helmcov — dev-only, not needed at install time +tests/ + +# helm-docs source template (README.md is the published doc) +README.md.gotmpl diff --git a/charts/clickstack/README.md b/charts/clickstack/README.md index 33482be..29dfc46 100644 --- a/charts/clickstack/README.md +++ b/charts/clickstack/README.md @@ -32,162 +32,47 @@ See the [ClickStack Helm documentation](https://clickhouse.com/docs/use-cases/ob |------------|------|---------| | https://open-telemetry.github.io/opentelemetry-helm-charts | otel-collector(opentelemetry-collector) | ~0.146.0 | +Documented values below. Undocumented keys (operator CRD passthrough fields, subchart defaults) are omitted — see the linked operator and subchart docs above. + ## Values | Key | Type | Default | Description | |-----|------|---------|-------------| -| additionalManifests | list | `[]` | | -| clickhouse.cluster.spec.containerTemplate.image.repository | string | `"clickhouse/clickhouse-server"` | | -| clickhouse.cluster.spec.containerTemplate.image.tag | string | `"25.7-alpine"` | | -| clickhouse.cluster.spec.dataVolumeClaimSpec.accessModes[0] | string | `"ReadWriteOnce"` | | -| clickhouse.cluster.spec.dataVolumeClaimSpec.resources.requests.storage | string | `"10Gi"` | | -| clickhouse.cluster.spec.keeperClusterRef.name | string | `"{{ include \"clickstack.clickhouse.keeper\" . }}"` | | -| clickhouse.cluster.spec.replicas | int | `1` | | -| clickhouse.cluster.spec.settings.extraConfig.keep_alive_timeout | int | `64` | | -| clickhouse.cluster.spec.settings.extraConfig.max_concurrent_queries | int | `100` | | -| clickhouse.cluster.spec.settings.extraConfig.max_connections | int | `4096` | | -| clickhouse.cluster.spec.settings.extraUsersConfig.users.app.grants[0].query | string | `"GRANT SHOW ON *.*, SELECT ON system.*, SELECT ON default.*"` | | -| clickhouse.cluster.spec.settings.extraUsersConfig.users.app.password | string | `"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}"` | | -| clickhouse.cluster.spec.settings.extraUsersConfig.users.app.profile | string | `"default"` | | -| clickhouse.cluster.spec.settings.extraUsersConfig.users.otelcollector.grants[0].query | string | `"GRANT SELECT,INSERT,CREATE,SHOW ON default.*"` | | -| clickhouse.cluster.spec.settings.extraUsersConfig.users.otelcollector.password | string | `"{{ .Values.hyperdx.secrets.CLICKHOUSE_PASSWORD }}"` | | -| clickhouse.cluster.spec.settings.extraUsersConfig.users.otelcollector.profile | string | `"default"` | | -| clickhouse.cluster.spec.shards | int | `1` | | -| clickhouse.enabled | bool | `true` | | -| clickhouse.keeper.spec.dataVolumeClaimSpec.accessModes[0] | string | `"ReadWriteOnce"` | | -| clickhouse.keeper.spec.dataVolumeClaimSpec.resources.requests.storage | string | `"5Gi"` | | -| clickhouse.keeper.spec.replicas | int | `1` | | -| clickhouse.nativePort | int | `9000` | | -| clickhouse.port | int | `8123` | | -| clickhouse.prometheus.enabled | bool | `true` | | -| clickhouse.prometheus.port | int | `9363` | | -| global.imagePullSecrets | list | `[]` | | -| global.imageRegistry | string | `""` | | -| hyperdx.autoscaling.enabled | bool | `false` | | -| hyperdx.autoscaling.spec | object | `{}` | | -| hyperdx.config.API_PORT | string | `"8000"` | | -| hyperdx.config.APP_PORT | string | `"3000"` | | -| hyperdx.config.CLICKHOUSE_ENDPOINT | string | `"tcp://{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}?dial_timeout=10s"` | | -| hyperdx.config.CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT | string | `"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.prometheus.port }}"` | | -| hyperdx.config.CLICKHOUSE_SERVER_ENDPOINT | string | `"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}"` | | -| hyperdx.config.CLICKHOUSE_USER | string | `"otelcollector"` | | -| hyperdx.config.FRONTEND_URL | string | `"http://localhost:3000"` | | -| hyperdx.config.HYPERDX_API_PORT | string | `"8000"` | | -| hyperdx.config.HYPERDX_APP_PORT | string | `"3000"` | | -| hyperdx.config.HYPERDX_LOG_LEVEL | string | `"info"` | | -| hyperdx.config.HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE | string | `"default"` | | -| hyperdx.config.MONGO_URI | string | `"mongodb://hyperdx:{{ .Values.hyperdx.secrets.MONGODB_PASSWORD }}@{{ include \"clickstack.mongodb.svc\" . }}:27017/hyperdx?authSource=hyperdx"` | | -| hyperdx.config.OPAMP_PORT | string | `"4320"` | | -| hyperdx.config.OPAMP_SERVER_URL | string | `"http://{{ include \"clickstack.hyperdx.fullname\" . }}:{{ .Values.hyperdx.ports.opamp }}"` | | -| hyperdx.config.OTEL_EXPORTER_OTLP_ENDPOINT | string | `"http://{{ include \"clickstack.otel.fullname\" . }}:4318"` | | -| hyperdx.config.OTEL_SERVICE_NAME | string | `"hdx-oss-api"` | | -| hyperdx.config.RUN_SCHEDULED_TASKS_EXTERNALLY | string | `"false"` | | -| hyperdx.config.USAGE_STATS_ENABLED | string | `"true"` | | -| hyperdx.deployment.annotations | object | `{}` | | -| hyperdx.deployment.defaultConnections | string | `"[\n {\n \"name\": \"Local ClickHouse\",\n \"host\": \"http://{{ include \"clickstack.clickhouse.svc\" . }}:8123\",\n \"port\": 8123,\n \"username\": \"app\",\n \"password\": \"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}\"\n }\n]\n"` | | -| hyperdx.deployment.defaultSources | string | `"[\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_logs\"\n },\n \"kind\": \"log\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Logs\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_traces\"\n },\n \"kind\": \"trace\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Traces\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"SpanName\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"SpanName\",\n \"eventAttributesExpression\": \"SpanAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"durationExpression\": \"Duration\",\n \"durationPrecision\": 9,\n \"parentSpanIdExpression\": \"ParentSpanId\",\n \"spanNameExpression\": \"SpanName\",\n \"spanKindExpression\": \"SpanKind\",\n \"statusCodeExpression\": \"StatusCode\",\n \"statusMessageExpression\": \"StatusMessage\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"\"\n },\n \"kind\": \"metric\",\n \"timestampValueExpression\": \"TimeUnix\",\n \"name\": \"Metrics\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"metricTables\": {\n \"gauge\": \"otel_metrics_gauge\",\n \"histogram\": \"otel_metrics_histogram\",\n \"sum\": \"otel_metrics_sum\",\n \"_id\": \"682586a8b1f81924e628e808\",\n \"id\": \"682586a8b1f81924e628e808\"\n },\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"hyperdx_sessions\"\n },\n \"kind\": \"session\",\n \"timestampValueExpression\": \"TimestampTime\",\n \"name\": \"Sessions\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"metricSourceId\": \"Metrics\"\n }\n]\n"` | | -| hyperdx.deployment.env | list | `[]` | | -| hyperdx.deployment.existingConfigConnectionsKey | string | `"connections.json"` | | -| hyperdx.deployment.existingConfigSecret | string | `""` | | -| hyperdx.deployment.existingConfigSourcesKey | string | `"sources.json"` | | -| hyperdx.deployment.image.pullPolicy | string | `"IfNotPresent"` | | -| hyperdx.deployment.image.repository | string | `"docker.hyperdx.io/hyperdx/hyperdx"` | | -| hyperdx.deployment.image.tag | string | `nil` | | -| hyperdx.deployment.initContainers | list | `[]` | | -| hyperdx.deployment.labels | object | `{}` | | -| hyperdx.deployment.livenessProbe.enabled | bool | `true` | | -| hyperdx.deployment.livenessProbe.failureThreshold | int | `3` | | -| hyperdx.deployment.livenessProbe.initialDelaySeconds | int | `10` | | -| hyperdx.deployment.livenessProbe.periodSeconds | int | `30` | | -| hyperdx.deployment.livenessProbe.timeoutSeconds | int | `5` | | -| hyperdx.deployment.nodeSelector | object | `{}` | | -| hyperdx.deployment.priorityClassName | string | `""` | | -| hyperdx.deployment.readinessProbe.enabled | bool | `true` | | -| hyperdx.deployment.readinessProbe.failureThreshold | int | `3` | | -| hyperdx.deployment.readinessProbe.initialDelaySeconds | int | `1` | | -| hyperdx.deployment.readinessProbe.periodSeconds | int | `10` | | -| hyperdx.deployment.readinessProbe.timeoutSeconds | int | `5` | | -| hyperdx.deployment.replicas | int | `1` | | -| hyperdx.deployment.resources | object | `{}` | | -| hyperdx.deployment.tolerations | list | `[]` | | -| hyperdx.deployment.topologySpreadConstraints | list | `[]` | | -| hyperdx.deployment.useExistingConfigSecret | bool | `false` | | -| hyperdx.deployment.volumeMounts | list | `[]` | | -| hyperdx.deployment.volumes | list | `[]` | | -| hyperdx.deployment.waitForMongodb.image | string | `"busybox@sha256:1fcf5df59121b92d61e066df1788e8df0cc35623f5d62d9679a41e163b6a0cdb"` | | -| hyperdx.deployment.waitForMongodb.pullPolicy | string | `"IfNotPresent"` | | -| hyperdx.ingress.additionalIngresses | list | `[]` | | -| hyperdx.ingress.annotations | object | `{}` | | -| hyperdx.ingress.enabled | bool | `false` | | -| hyperdx.ingress.spec | object | `{}` | | -| hyperdx.networkPolicy.enabled | bool | `false` | | -| hyperdx.networkPolicy.spec | object | `{}` | | -| hyperdx.podDisruptionBudget.enabled | bool | `false` | | -| hyperdx.ports.api | int | `8000` | | -| hyperdx.ports.app | int | `3000` | | -| hyperdx.ports.opamp | int | `4320` | | -| hyperdx.secrets.CLICKHOUSE_APP_PASSWORD | string | `"hyperdx"` | | -| hyperdx.secrets.CLICKHOUSE_PASSWORD | string | `"otelcollectorpass"` | | -| hyperdx.secrets.HYPERDX_API_KEY | string | `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"` | | -| hyperdx.secrets.MONGODB_PASSWORD | string | `"hyperdx"` | | -| hyperdx.service.annotations | object | `{}` | | -| hyperdx.service.apiPort.enabled | bool | `false` | | -| hyperdx.service.type | string | `"ClusterIP"` | | -| hyperdx.serviceAccount.annotations | object | `{}` | | -| hyperdx.serviceAccount.create | bool | `false` | | -| hyperdx.serviceAccount.name | string | `""` | | -| hyperdx.tasks.checkAlerts.additionalArgs | object | `{}` | | -| hyperdx.tasks.checkAlerts.resources.limits.cpu | string | `"200m"` | | -| hyperdx.tasks.checkAlerts.resources.limits.memory | string | `"256Mi"` | | -| hyperdx.tasks.checkAlerts.resources.requests.cpu | string | `"100m"` | | -| hyperdx.tasks.checkAlerts.resources.requests.memory | string | `"128Mi"` | | -| hyperdx.tasks.checkAlerts.schedule | string | `"*/1 * * * *"` | | -| hyperdx.tasks.enabled | bool | `false` | | -| mongodb.enabled | bool | `true` | | -| mongodb.spec.additionalMongodConfig."storage.wiredTiger.engineConfig.journalCompressor" | string | `"zlib"` | | -| mongodb.spec.members | int | `1` | | -| mongodb.spec.security.authentication.modes[0] | string | `"SCRAM"` | | -| mongodb.spec.type | string | `"ReplicaSet"` | | -| mongodb.spec.users[0].db | string | `"hyperdx"` | | -| mongodb.spec.users[0].name | string | `"hyperdx"` | | -| mongodb.spec.users[0].passwordSecretRef.name | string | `"{{ include \"clickstack.mongodb.fullname\" . }}-password"` | | -| mongodb.spec.users[0].roles[0].db | string | `"hyperdx"` | | -| mongodb.spec.users[0].roles[0].name | string | `"dbOwner"` | | -| mongodb.spec.users[0].roles[1].db | string | `"admin"` | | -| mongodb.spec.users[0].roles[1].name | string | `"clusterMonitor"` | | -| mongodb.spec.users[0].scramCredentialsSecretName | string | `"{{ include \"clickstack.mongodb.fullname\" . }}-scram"` | | -| mongodb.spec.version | string | `"5.0.32"` | | -| otel-collector.enabled | bool | `true` | | -| otel-collector.extraEnvsFrom[0].configMapRef.name | string | `"clickstack-config"` | | -| otel-collector.extraEnvsFrom[1].secretRef.name | string | `"clickstack-secret"` | | -| otel-collector.image.repository | string | `"docker.clickhouse.com/clickhouse/clickstack-otel-collector"` | | -| otel-collector.image.tag | string | `"2.19.0"` | | -| otel-collector.mode | string | `"deployment"` | | -| otel-collector.ports.fluentd.containerPort | int | `24225` | | -| otel-collector.ports.fluentd.enabled | bool | `true` | | -| otel-collector.ports.fluentd.protocol | string | `"TCP"` | | -| otel-collector.ports.fluentd.servicePort | int | `24225` | | -| otel-collector.ports.health-check.containerPort | int | `13133` | | -| otel-collector.ports.health-check.enabled | bool | `true` | | -| otel-collector.ports.health-check.protocol | string | `"TCP"` | | -| otel-collector.ports.health-check.servicePort | int | `13133` | | -| otel-collector.ports.jaeger-compact.enabled | bool | `false` | | -| otel-collector.ports.jaeger-grpc.enabled | bool | `false` | | -| otel-collector.ports.jaeger-thrift.enabled | bool | `false` | | -| otel-collector.ports.metrics.containerPort | int | `8888` | | -| otel-collector.ports.metrics.enabled | bool | `true` | | -| otel-collector.ports.metrics.protocol | string | `"TCP"` | | -| otel-collector.ports.metrics.servicePort | int | `8888` | | -| otel-collector.ports.otlp-http.containerPort | int | `4318` | | -| otel-collector.ports.otlp-http.enabled | bool | `true` | | -| otel-collector.ports.otlp-http.protocol | string | `"TCP"` | | -| otel-collector.ports.otlp-http.servicePort | int | `4318` | | -| otel-collector.ports.otlp.appProtocol | string | `"grpc"` | | -| otel-collector.ports.otlp.containerPort | int | `4317` | | -| otel-collector.ports.otlp.enabled | bool | `true` | | -| otel-collector.ports.otlp.protocol | string | `"TCP"` | | -| otel-collector.ports.otlp.servicePort | int | `4317` | | -| otel-collector.ports.zipkin.enabled | bool | `false` | | +| additionalManifests | list | `[]` | Additional Kubernetes manifests deployed alongside the chart (supports tpl). See docs/ADDITIONAL-MANIFESTS.md for examples. | +| clickhouse | object | `{"cluster":{"spec":{"containerTemplate":{"image":{"repository":"clickhouse/clickhouse-server","tag":"25.7-alpine"}},"dataVolumeClaimSpec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"keeperClusterRef":{"name":"{{ include \"clickstack.clickhouse.keeper\" . }}"},"replicas":1,"settings":{"extraConfig":{"keep_alive_timeout":64,"max_concurrent_queries":100,"max_connections":4096},"extraUsersConfig":{"users":{"app":{"grants":[{"query":"GRANT SHOW ON *.*, SELECT ON system.*, SELECT ON default.*"}],"password":"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}","profile":"default"},"otelcollector":{"grants":[{"query":"GRANT SELECT,INSERT,CREATE,SHOW ON default.*"}],"password":"{{ .Values.hyperdx.secrets.CLICKHOUSE_PASSWORD }}","profile":"default"}}}},"shards":1}},"enabled":true,"keeper":{"spec":{"dataVolumeClaimSpec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"5Gi"}}},"replicas":1}},"nativePort":9000,"port":8123,"prometheus":{"enabled":true,"port":9363}}` | In-cluster ClickHouse via ClickHouseCluster CR. Set enabled: false for external ClickHouse. | +| clickhouse.cluster | object | `{"spec":{"containerTemplate":{"image":{"repository":"clickhouse/clickhouse-server","tag":"25.7-alpine"}},"dataVolumeClaimSpec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"10Gi"}}},"keeperClusterRef":{"name":"{{ include \"clickstack.clickhouse.keeper\" . }}"},"replicas":1,"settings":{"extraConfig":{"keep_alive_timeout":64,"max_concurrent_queries":100,"max_connections":4096},"extraUsersConfig":{"users":{"app":{"grants":[{"query":"GRANT SHOW ON *.*, SELECT ON system.*, SELECT ON default.*"}],"password":"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}","profile":"default"},"otelcollector":{"grants":[{"query":"GRANT SELECT,INSERT,CREATE,SHOW ON default.*"}],"password":"{{ .Values.hyperdx.secrets.CLICKHOUSE_PASSWORD }}","profile":"default"}}}},"shards":1}}` | ClickHouseCluster CRD spec (rendered verbatim). See ClickHouse Operator docs. | +| clickhouse.keeper | object | `{"spec":{"dataVolumeClaimSpec":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"5Gi"}}},"replicas":1}}` | KeeperCluster CRD spec (rendered verbatim). See ClickHouse Operator docs. | +| clickhouse.nativePort | int | `9000` | Native TCP port used in connection strings. | +| clickhouse.port | int | `8123` | HTTP interface port for in-cluster connections. | +| clickhouse.prometheus.enabled | bool | `true` | Expose ClickHouse Prometheus metrics endpoint. | +| global | object | `{"imagePullSecrets":[],"imageRegistry":""}` | Global defaults applied across chart workloads. | +| global.imagePullSecrets | list | `[]` | Image pull secrets for private registries. Helps avoid Docker Hub rate limits. | +| global.imageRegistry | string | `""` | Optional prefix for container images (e.g. registry.example.com/). | +| hyperdx.autoscaling | object | `{"enabled":false,"spec":{}}` | HorizontalPodAutoscaler for HyperDX. spec is passed through verbatim (autoscaling/v2). Do not include scaleTargetRef — the chart auto-wires it. Omitting replicas when enabled. | +| hyperdx.config | object | `{"API_PORT":"8000","APP_PORT":"3000","CLICKHOUSE_ENDPOINT":"tcp://{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}?dial_timeout=10s","CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT":"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.prometheus.port }}","CLICKHOUSE_SERVER_ENDPOINT":"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}","CLICKHOUSE_USER":"otelcollector","FRONTEND_URL":"http://localhost:3000","HYPERDX_API_PORT":"8000","HYPERDX_APP_PORT":"3000","HYPERDX_LOG_LEVEL":"info","HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE":"default","MONGO_URI":"mongodb://hyperdx:{{ .Values.hyperdx.secrets.MONGODB_PASSWORD }}@{{ include \"clickstack.mongodb.svc\" . }}:27017/hyperdx?authSource=hyperdx","OPAMP_PORT":"4320","OPAMP_SERVER_URL":"http://{{ include \"clickstack.hyperdx.fullname\" . }}:{{ .Values.hyperdx.ports.opamp }}","OTEL_EXPORTER_OTLP_ENDPOINT":"http://{{ include \"clickstack.otel.fullname\" . }}:4318","OTEL_SERVICE_NAME":"hdx-oss-api","RUN_SCHEDULED_TASKS_EXTERNALLY":"false","USAGE_STATS_ENABLED":"true"}` | Shared non-sensitive environment variables (clickstack-config ConfigMap). Used by HyperDX and OTEL collector via envFrom. Values support tpl expressions. Override entries with plain strings to point at external services. | +| hyperdx.deployment | object | `{"annotations":{},"defaultConnections":"[\n {\n \"name\": \"Local ClickHouse\",\n \"host\": \"http://{{ include \"clickstack.clickhouse.svc\" . }}:8123\",\n \"port\": 8123,\n \"username\": \"app\",\n \"password\": \"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}\"\n }\n]\n","defaultSources":"[\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_logs\"\n },\n \"kind\": \"log\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Logs\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_traces\"\n },\n \"kind\": \"trace\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Traces\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"SpanName\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"SpanName\",\n \"eventAttributesExpression\": \"SpanAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"durationExpression\": \"Duration\",\n \"durationPrecision\": 9,\n \"parentSpanIdExpression\": \"ParentSpanId\",\n \"spanNameExpression\": \"SpanName\",\n \"spanKindExpression\": \"SpanKind\",\n \"statusCodeExpression\": \"StatusCode\",\n \"statusMessageExpression\": \"StatusMessage\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"\"\n },\n \"kind\": \"metric\",\n \"timestampValueExpression\": \"TimeUnix\",\n \"name\": \"Metrics\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"metricTables\": {\n \"gauge\": \"otel_metrics_gauge\",\n \"histogram\": \"otel_metrics_histogram\",\n \"sum\": \"otel_metrics_sum\",\n \"_id\": \"682586a8b1f81924e628e808\",\n \"id\": \"682586a8b1f81924e628e808\"\n },\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"hyperdx_sessions\"\n },\n \"kind\": \"session\",\n \"timestampValueExpression\": \"TimestampTime\",\n \"name\": \"Sessions\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"metricSourceId\": \"Metrics\"\n }\n]\n","env":[],"existingConfigConnectionsKey":"connections.json","existingConfigSecret":"","existingConfigSourcesKey":"sources.json","image":{"pullPolicy":"IfNotPresent","repository":"docker.hyperdx.io/hyperdx/hyperdx","tag":null},"initContainers":[],"labels":{},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":10,"periodSeconds":30,"timeoutSeconds":5},"nodeSelector":{},"priorityClassName":"","readinessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":1,"periodSeconds":10,"timeoutSeconds":5},"replicas":1,"resources":{},"tolerations":[],"topologySpreadConstraints":[],"useExistingConfigSecret":false,"volumeMounts":[],"volumes":[],"waitForMongodb":{"image":"busybox@sha256:1fcf5df59121b92d61e066df1788e8df0cc35623f5d62d9679a41e163b6a0cdb","pullPolicy":"IfNotPresent"}}` | HyperDX Deployment spec (image, probes, scheduling, init containers, volumes). defaultConnections/defaultSources JSON: set to "" to disable; use useExistingConfigSecret for external secrets. | +| hyperdx.deployment.existingConfigSecret | string | `""` | Secret containing connections and sources JSON when useExistingConfigSecret is true. | +| hyperdx.deployment.image.repository | string | `"docker.hyperdx.io/hyperdx/hyperdx"` | HyperDX container image repository. | +| hyperdx.deployment.image.tag | string | `nil` | Image tag. Defaults to Chart appVersion when empty. | +| hyperdx.deployment.initContainers | list | `[]` | Additional init containers to run before the HyperDX container starts. | +| hyperdx.deployment.replicas | int | `1` | Pod replica count. Ignored when hyperdx.autoscaling.enabled is true. | +| hyperdx.deployment.useExistingConfigSecret | bool | `false` | Load HyperDX connections JSON from an existing Secret instead of defaultConnections. | +| hyperdx.deployment.volumeMounts | list | `[]` | Additional volume mounts for the HyperDX container. | +| hyperdx.deployment.volumes | list | `[]` | Additional volumes to attach to the pod. | +| hyperdx.ingress | object | `{"additionalIngresses":[],"annotations":{},"enabled":false,"spec":{}}` | Ingress for HyperDX. annotations and spec are rendered verbatim (nginx, ALB, Traefik, etc.). Use additionalIngresses for multi-ingress setups (e.g. separate OTEL collector ingress). | +| hyperdx.networkPolicy | object | `{"enabled":false,"spec":{}}` | NetworkPolicy for HyperDX. spec is passed through verbatim. | +| hyperdx.podDisruptionBudget | object | `{"enabled":false}` | PodDisruptionBudget for the HyperDX Deployment. | +| hyperdx.ports | object | `{"api":8000,"app":3000,"opamp":4320}` | Ports shared across Deployment, Service, ConfigMap, and Ingress. | +| hyperdx.secrets | object | `{"CLICKHOUSE_APP_PASSWORD":"hyperdx","CLICKHOUSE_PASSWORD":"otelcollectorpass","HYPERDX_API_KEY":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","MONGODB_PASSWORD":"hyperdx"}` | Shared sensitive environment variables (clickstack-secret). Set to null to skip Secret creation (requires mongodb, clickhouse, and otel-collector disabled). | +| hyperdx.service | object | `{"annotations":{},"apiPort":{"enabled":false},"type":"ClusterIP"}` | HyperDX Service (ClusterIP by default). | +| hyperdx.service.apiPort | object | `{"enabled":false}` | Expose the API port (8000) on the Service for API-only or direct API access. | +| hyperdx.serviceAccount | object | `{"annotations":{},"create":false,"name":""}` | ServiceAccount for HyperDX. Set create: true to provision one; use annotations for IRSA/GCP bindings. | +| hyperdx.serviceAccount.name | string | `""` | ServiceAccount name. Defaults to chart fullname when create is true and name is empty. | +| hyperdx.tasks | object | `{"checkAlerts":{"additionalArgs":{},"resources":{"limits":{"cpu":"200m","memory":"256Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"schedule":"*/1 * * * *"},"enabled":false}` | Scheduled HyperDX background tasks (CronJobs). | +| mongodb | object | `{"enabled":true,"spec":{"additionalMongodConfig":{"storage.wiredTiger.engineConfig.journalCompressor":"zlib"},"members":1,"security":{"authentication":{"modes":["SCRAM"]}},"type":"ReplicaSet","users":[{"db":"hyperdx","name":"hyperdx","passwordSecretRef":{"name":"{{ include \"clickstack.mongodb.fullname\" . }}-password"},"roles":[{"db":"hyperdx","name":"dbOwner"},{"db":"admin","name":"clusterMonitor"}],"scramCredentialsSecretName":"{{ include \"clickstack.mongodb.fullname\" . }}-scram"}],"version":"5.0.32"}}` | In-cluster MongoDB via MongoDBCommunity CR. Set enabled: false for external MongoDB. | +| mongodb.spec | object | `{"additionalMongodConfig":{"storage.wiredTiger.engineConfig.journalCompressor":"zlib"},"members":1,"security":{"authentication":{"modes":["SCRAM"]}},"type":"ReplicaSet","users":[{"db":"hyperdx","name":"hyperdx","passwordSecretRef":{"name":"{{ include \"clickstack.mongodb.fullname\" . }}-password"},"roles":[{"db":"hyperdx","name":"dbOwner"},{"db":"admin","name":"clusterMonitor"}],"scramCredentialsSecretName":"{{ include \"clickstack.mongodb.fullname\" . }}-scram"}],"version":"5.0.32"}` | MongoDBCommunity CRD spec (rendered verbatim). See MongoDB Kubernetes Operator docs. | +| otel-collector | object | `{"enabled":true,"extraEnvsFrom":[{"configMapRef":{"name":"clickstack-config"}},{"secretRef":{"name":"clickstack-secret"}}],"image":{"repository":"docker.clickhouse.com/clickhouse/clickstack-otel-collector","tag":"2.19.0"},"mode":"deployment","ports":{"fluentd":{"containerPort":24225,"enabled":true,"protocol":"TCP","servicePort":24225},"health-check":{"containerPort":13133,"enabled":true,"protocol":"TCP","servicePort":13133},"jaeger-compact":{"enabled":false},"jaeger-grpc":{"enabled":false},"jaeger-thrift":{"enabled":false},"metrics":{"containerPort":8888,"enabled":true,"protocol":"TCP","servicePort":8888},"otlp":{"appProtocol":"grpc","containerPort":4317,"enabled":true,"protocol":"TCP","servicePort":4317},"otlp-http":{"containerPort":4318,"enabled":true,"protocol":"TCP","servicePort":4318},"zipkin":{"enabled":false}}}` | OpenTelemetry Collector subchart. Set enabled: false to use an external collector. | +| otel-collector.enabled | bool | `true` | Deploy the bundled OpenTelemetry Collector subchart. | ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/clickstack/README.md.gotmpl b/charts/clickstack/README.md.gotmpl index ef80827..2878dd9 100644 --- a/charts/clickstack/README.md.gotmpl +++ b/charts/clickstack/README.md.gotmpl @@ -25,6 +25,8 @@ See the [ClickStack Helm documentation](https://clickhouse.com/docs/use-cases/ob {{ template "chart.requirementsSection" . }} +Documented values below. Undocumented keys (operator CRD passthrough fields, subchart defaults) are omitted — see the linked operator and subchart docs above. + {{ template "chart.valuesSection" . }} {{ template "helm-docs.versionFooter" . }} diff --git a/charts/clickstack/values.yaml b/charts/clickstack/values.yaml index 4b68915..7dbfa26 100644 --- a/charts/clickstack/values.yaml +++ b/charts/clickstack/values.yaml @@ -1,24 +1,20 @@ +# -- Global defaults applied across chart workloads. global: + # -- Optional prefix for container images (e.g. registry.example.com/). imageRegistry: "" - # List of image pull secrets to use for pulling images from private registries - # This helps avoid rate limiting (429 errors) when pulling from Docker Hub - # Example: - # imagePullSecrets: - # - name: regcred - # - name: docker-hub-secret + # -- Image pull secrets for private registries. Helps avoid Docker Hub rate limits. imagePullSecrets: [] hyperdx: - # Ports shared across Deployment, Service, ConfigMap, and Ingress + # -- Ports shared across Deployment, Service, ConfigMap, and Ingress. ports: api: 8000 app: 3000 opamp: 4320 - # ── K8s ConfigMap (clickstack-config) ──────────────────── - # Shared non-sensitive environment variables. Used by HyperDX and OTEL collector via envFrom. - # All values support Helm template expressions (rendered via tpl). - # Override any entry with a plain string to point at an external service. + # -- Shared non-sensitive environment variables (clickstack-config ConfigMap). + # Used by HyperDX and OTEL collector via envFrom. Values support tpl expressions. + # Override entries with plain strings to point at external services. config: APP_PORT: "3000" API_PORT: "8000" @@ -40,26 +36,25 @@ hyperdx: CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT: '{{ include "clickstack.clickhouse.svc" . }}:{{ .Values.clickhouse.prometheus.port }}' OPAMP_SERVER_URL: 'http://{{ include "clickstack.hyperdx.fullname" . }}:{{ .Values.hyperdx.ports.opamp }}' - # ── K8s Secret (clickstack-secret) ─────────────────────── - # Shared sensitive environment variables. Used by HyperDX and OTEL collector via envFrom. - # - # Advanced: set to null to skip Secret creation entirely. This is useful when - # managing secrets externally via deployment.env valueFrom entries. Requires - # mongodb, clickhouse, and otel-collector to all be disabled. Users must - # provide all required environment variables through their own secret management. + # -- Shared sensitive environment variables (clickstack-secret). + # Set to null to skip Secret creation (requires mongodb, clickhouse, and otel-collector disabled). secrets: HYPERDX_API_KEY: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" CLICKHOUSE_PASSWORD: "otelcollectorpass" CLICKHOUSE_APP_PASSWORD: "hyperdx" MONGODB_PASSWORD: "hyperdx" - # ── K8s Deployment ─────────────────────────────────────── + # -- HyperDX Deployment spec (image, probes, scheduling, init containers, volumes). + # defaultConnections/defaultSources JSON: set to "" to disable; use useExistingConfigSecret for external secrets. deployment: image: + # -- HyperDX container image repository. repository: docker.hyperdx.io/hyperdx/hyperdx + # -- Image tag. Defaults to Chart appVersion when empty. tag: pullPolicy: IfNotPresent - replicas: 1 # ignored when autoscaling.enabled is true (HPA manages replicas) + # -- Pod replica count. Ignored when hyperdx.autoscaling.enabled is true. + replicas: 1 resources: {} livenessProbe: enabled: true @@ -80,20 +75,18 @@ hyperdx: annotations: {} labels: {} env: [] - # Additional init containers to run before the HyperDX container starts. - # Useful for fetching certificates, warming caches, or other startup tasks. + # -- Additional init containers to run before the HyperDX container starts. initContainers: [] - # Additional volumes to attach to the pod. + # -- Additional volumes to attach to the pod. volumes: [] - # Additional volume mounts to apply to the HyperDX container. + # -- Additional volume mounts for the HyperDX container. volumeMounts: [] waitForMongodb: image: "busybox@sha256:1fcf5df59121b92d61e066df1788e8df0cc35623f5d62d9679a41e163b6a0cdb" pullPolicy: IfNotPresent - # Default connections and sources (ENABLED BY DEFAULT) - # Set to empty string to disable: defaultConnections: "" or defaultSources: "" - # To use an existing secret, set useExistingConfigSecret: true + # -- Load HyperDX connections JSON from an existing Secret instead of defaultConnections. useExistingConfigSecret: false + # -- Secret containing connections and sources JSON when useExistingConfigSecret is true. existingConfigSecret: "" existingConfigConnectionsKey: "connections.json" existingConfigSourcesKey: "sources.json" @@ -207,61 +200,45 @@ hyperdx: } ] - # ── K8s Service ────────────────────────────────────────── + # -- HyperDX Service (ClusterIP by default). service: type: ClusterIP annotations: {} - # Expose the API port (8000) on the Service. Useful when deploying the - # API-only image or when external traffic needs to reach port 8000 directly. + # -- Expose the API port (8000) on the Service for API-only or direct API access. apiPort: enabled: false - # ── K8s Ingress ────────────────────────────────────────── - # The primary ingress uses a passthrough pattern: annotations and spec are - # rendered verbatim so any ingress controller (nginx, ALB, Traefik, etc.) - # can be configured via values alone. - # additionalIngresses is kept as a power feature for multi-ingress setups. + # -- Ingress for HyperDX. annotations and spec are rendered verbatim (nginx, ALB, Traefik, etc.). + # Use additionalIngresses for multi-ingress setups (e.g. separate OTEL collector ingress). ingress: enabled: false annotations: {} spec: {} additionalIngresses: [] - # ── K8s PodDisruptionBudget ────────────────────────────── + # -- PodDisruptionBudget for the HyperDX Deployment. podDisruptionBudget: enabled: false - # ── K8s HorizontalPodAutoscaler ───────────────────────── - # When enabled, the Deployment's replicas field is omitted (HPA manages it). - # The spec is passed through verbatim -- provide any valid autoscaling/v2 - # HPA spec fields (minReplicas, maxReplicas, metrics, behavior, etc.). - # NOTE: Do not include scaleTargetRef in spec. The chart auto-wires it to the - # HyperDX Deployment. If scaleTargetRef is present, the template will fail. - # IMPORTANT: If you later disable autoscaling, the Deployment will revert to - # deployment.replicas (default 1). Set deployment.replicas to your desired - # baseline before disabling autoscaling, or use minReplicas in the HPA spec - # as your effective minimum. + # -- HorizontalPodAutoscaler for HyperDX. spec is passed through verbatim (autoscaling/v2). + # Do not include scaleTargetRef — the chart auto-wires it. Omitting replicas when enabled. autoscaling: enabled: false spec: {} - # ── K8s NetworkPolicy ─────────────────────────────────── - # The spec is passed through verbatim -- provide any valid NetworkPolicy spec - # (podSelector, policyTypes, egress, ingress rules, etc.). + # -- NetworkPolicy for HyperDX. spec is passed through verbatim. networkPolicy: enabled: false spec: {} - # ── K8s ServiceAccount ────────────────────────────────── - # When create is true, a ServiceAccount is created and referenced by the Deployment. - # When create is false but name is set, the Deployment references an existing SA. - # Use annotations for provider-specific bindings (e.g., eks.amazonaws.com/role-arn). + # -- ServiceAccount for HyperDX. Set create: true to provision one; use annotations for IRSA/GCP bindings. serviceAccount: create: false - name: "" # if empty and create is true, uses the chart fullname + # -- ServiceAccount name. Defaults to chart fullname when create is true and name is empty. + name: "" annotations: {} - # ── K8s CronJob ────────────────────────────────────────── + # -- Scheduled HyperDX background tasks (CronJobs). tasks: enabled: false checkAlerts: @@ -275,11 +252,10 @@ hyperdx: cpu: 100m memory: 128Mi +# -- In-cluster MongoDB via MongoDBCommunity CR. Set enabled: false for external MongoDB. mongodb: enabled: true - # Full MongoDBCommunity CRD spec -- rendered verbatim into the CR. - # See https://github.com/mongodb/mongodb-kubernetes/tree/master/docs/mongodbcommunity - # for all available fields. Add persistence, nodeSelector, tolerations, etc. here. + # -- MongoDBCommunity CRD spec (rendered verbatim). See MongoDB Kubernetes Operator docs. spec: members: 1 type: ReplicaSet @@ -301,16 +277,18 @@ mongodb: additionalMongodConfig: storage.wiredTiger.engineConfig.journalCompressor: zlib +# -- In-cluster ClickHouse via ClickHouseCluster CR. Set enabled: false for external ClickHouse. clickhouse: enabled: true - # Ports used for cross-service wiring (defaultConnections) + # -- HTTP interface port for in-cluster connections. port: 8123 + # -- Native TCP port used in connection strings. nativePort: 9000 prometheus: + # -- Expose ClickHouse Prometheus metrics endpoint. enabled: true port: 9363 - # Full KeeperCluster CRD spec -- rendered verbatim into the CR. - # See https://clickhouse.com/docs/clickhouse-operator/guides/introduction + # -- KeeperCluster CRD spec (rendered verbatim). See ClickHouse Operator docs. keeper: spec: replicas: 1 @@ -320,8 +298,7 @@ clickhouse: resources: requests: storage: 5Gi - # Full ClickHouseCluster CRD spec -- rendered verbatim into the CR. - # See https://clickhouse.com/docs/clickhouse-operator/guides/configuration + # -- ClickHouseCluster CRD spec (rendered verbatim). See ClickHouse Operator docs. cluster: spec: containerTemplate: @@ -356,17 +333,13 @@ clickhouse: keep_alive_timeout: 64 max_concurrent_queries: 100 -# Additional Kubernetes manifests to deploy alongside the chart. -# Each entry is a complete Kubernetes object. Values are rendered through -# Helm's tpl function so template expressions (Release.Name, include, .Values) -# are available inside string fields. -# See docs/ADDITIONAL-MANIFESTS.md for full examples. +# -- Additional Kubernetes manifests deployed alongside the chart (supports tpl). +# See docs/ADDITIONAL-MANIFESTS.md for examples. additionalManifests: [] -# OpenTelemetry Collector subchart configuration (alias: otel-collector) -# See https://github.com/open-telemetry/opentelemetry-helm-charts for all options -# Set otel-collector.enabled to false to disable the OTEL collector entirely. +# -- OpenTelemetry Collector subchart. Set enabled: false to use an external collector. otel-collector: + # -- Deploy the bundled OpenTelemetry Collector subchart. enabled: true mode: deployment image: diff --git a/scripts/helmdocs.sh b/scripts/helmdocs.sh index 9a199d3..de2c4a0 100755 --- a/scripts/helmdocs.sh +++ b/scripts/helmdocs.sh @@ -12,4 +12,5 @@ echo "Generating chart README files..." "${HELM_DOCS_BIN}" \ --chart-search-root "${ROOT_DIR}/charts" \ --template-files README.md.gotmpl \ - --badge-style flat + --badge-style flat \ + --ignore-non-descriptions From 2953cca2f114b6d2efd0b248cc4e61341218903f Mon Sep 17 00:00:00 2001 From: Jordan Simonovski Date: Sat, 27 Jun 2026 14:13:57 +1000 Subject: [PATCH 3/5] chore: Address feedback and fix up high priority issues --- .github/workflows/helm-test.yaml | 2 ++ AGENTS.md | 29 ++++++++++++++++--- Makefile | 6 ++-- charts/clickstack/README.md | 2 +- .../tests/autoscaling-enabled_test.yaml | 13 --------- .../tests/deployment-tpl-defaults_test.yaml | 12 ++++---- .../tests/helpers-fullname_test.yaml | 11 ------- .../tests/helpers-name-override_test.yaml | 11 ------- .../tests/helpers-release-name_test.yaml | 9 ------ .../tests/hyperdx-service_test.yaml | 8 +++++ .../tests/ingress-enabled_test.yaml | 16 ---------- .../tests/secret-disabled_test.yaml | 10 ------- .../tests/values/autoscaling-enabled.yaml | 13 --------- .../tests/values/fullname-override.yaml | 2 -- .../tests/values/ingress-enabled.yaml | 18 ------------ .../tests/values/name-override.yaml | 1 - .../tests/values/secret-disabled.yaml | 8 ----- charts/clickstack/values.yaml | 3 +- scripts/helmcov.sh | 7 +++-- scripts/install-helm-docs.sh | 15 +++++++--- scripts/load-tool-versions.sh | 16 ++++++++++ scripts/tool-versions.env | 8 +++++ 22 files changed, 88 insertions(+), 132 deletions(-) delete mode 100644 charts/clickstack/tests/autoscaling-enabled_test.yaml delete mode 100644 charts/clickstack/tests/helpers-fullname_test.yaml delete mode 100644 charts/clickstack/tests/helpers-name-override_test.yaml delete mode 100644 charts/clickstack/tests/helpers-release-name_test.yaml delete mode 100644 charts/clickstack/tests/ingress-enabled_test.yaml delete mode 100644 charts/clickstack/tests/secret-disabled_test.yaml delete mode 100644 charts/clickstack/tests/values/autoscaling-enabled.yaml delete mode 100644 charts/clickstack/tests/values/fullname-override.yaml delete mode 100644 charts/clickstack/tests/values/ingress-enabled.yaml delete mode 100644 charts/clickstack/tests/values/name-override.yaml delete mode 100644 charts/clickstack/tests/values/secret-disabled.yaml create mode 100644 scripts/load-tool-versions.sh create mode 100644 scripts/tool-versions.env diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml index a23aab3..205e0db 100644 --- a/.github/workflows/helm-test.yaml +++ b/.github/workflows/helm-test.yaml @@ -5,6 +5,7 @@ on: branches: [ main ] paths: - 'charts/**' + - 'examples/**' - 'Makefile' - 'scripts/**' - '.githooks/**' @@ -13,6 +14,7 @@ on: branches: [ main ] paths: - 'charts/**' + - 'examples/**' - 'Makefile' - 'scripts/**' - '.githooks/**' diff --git a/AGENTS.md b/AGENTS.md index ea18fb6..36465ad 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -63,6 +63,27 @@ helm unittest -f 'tests/clickhouse-*_test.yaml' charts/clickstack Test files live in `charts/clickstack/tests/` and follow the naming convention `_test.yaml`. Snapshots are stored in `tests/__snapshot__/`. +Shared value fixtures live in `charts/clickstack/tests/values/.yaml` and are +loaded with the suite-level `values:` key when a test needs more data than inline +`set:` overrides comfortably provide: + +```yaml +suite: Test Deployment Default Sources Tpl +templates: + - hyperdx/deployment.yaml +values: + - values/deployment-tpl-defaults.yaml +tests: + - it: should render tpl-interpolated default connections + asserts: + - matchRegex: + path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_CONNECTIONS")].value + pattern: clickhouse-headless +``` + +Prefer inline `set:` for small overrides; use `tests/values/` for multi-field +fixtures or tpl-heavy defaults reused across assertions. + ### Template Coverage (helmcov) ```bash @@ -72,13 +93,13 @@ make coverage VERBOSE=1 make coverage # Gate on minimum line coverage once baseline is known -COVERAGE_THRESHOLD=25 make coverage +COVERAGE_THRESHOLD=30 make coverage -# Pin a different image -HELMCOV_IMAGE=ghcr.io/jordan-simonovski/helmcov:v0.3.2 make coverage +# Override the pinned image (see scripts/tool-versions.env) +HELMCOV_IMAGE=ghcr.io/example/helmcov@sha256:... make coverage ``` -Uses `ghcr.io/jordan-simonovski/helmcov:v0.3.2` by default with a **25% line +Uses the digest-pinned image in `scripts/tool-versions.env` with a **30% line coverage threshold**. Outputs `coverage.out` (Go coverprofile) and `coverage.xml` (Cobertura). CI runs `make coverage` via `.github/workflows/helmcov.yaml`. diff --git a/Makefile b/Makefile index 75a0da7..94702ff 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ SHELL := /bin/bash +include scripts/tool-versions.env +export HELM_DOCS_VERSION HELMCOV_IMAGE + CHART ?= charts/clickstack -HELMCOV_IMAGE ?= ghcr.io/jordan-simonovski/helmcov:v0.3.2 HELM_UNITTEST_VERSION ?= v1.0.3 HELM_UNITTEST_PLUGIN := https://github.com/helm-unittest/helm-unittest.git -COVERAGE_THRESHOLD ?= 25 +COVERAGE_THRESHOLD ?= 30 .PHONY: help setup hooks chart-deps install-helm-unittest install-helm-docs validate test coverage docs ci diff --git a/charts/clickstack/README.md b/charts/clickstack/README.md index 29dfc46..ac04da6 100644 --- a/charts/clickstack/README.md +++ b/charts/clickstack/README.md @@ -48,7 +48,7 @@ Documented values below. Undocumented keys (operator CRD passthrough fields, sub | global | object | `{"imagePullSecrets":[],"imageRegistry":""}` | Global defaults applied across chart workloads. | | global.imagePullSecrets | list | `[]` | Image pull secrets for private registries. Helps avoid Docker Hub rate limits. | | global.imageRegistry | string | `""` | Optional prefix for container images (e.g. registry.example.com/). | -| hyperdx.autoscaling | object | `{"enabled":false,"spec":{}}` | HorizontalPodAutoscaler for HyperDX. spec is passed through verbatim (autoscaling/v2). Do not include scaleTargetRef — the chart auto-wires it. Omitting replicas when enabled. | +| hyperdx.autoscaling | object | `{"enabled":false,"spec":{}}` | HorizontalPodAutoscaler for HyperDX. spec is passed through verbatim (autoscaling/v2). Do not include scaleTargetRef — the chart auto-wires it. When enabled, omit deployment.replicas; disabling autoscaling reverts to deployment.replicas (default 1). | | hyperdx.config | object | `{"API_PORT":"8000","APP_PORT":"3000","CLICKHOUSE_ENDPOINT":"tcp://{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}?dial_timeout=10s","CLICKHOUSE_PROMETHEUS_METRICS_ENDPOINT":"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.prometheus.port }}","CLICKHOUSE_SERVER_ENDPOINT":"{{ include \"clickstack.clickhouse.svc\" . }}:{{ .Values.clickhouse.nativePort }}","CLICKHOUSE_USER":"otelcollector","FRONTEND_URL":"http://localhost:3000","HYPERDX_API_PORT":"8000","HYPERDX_APP_PORT":"3000","HYPERDX_LOG_LEVEL":"info","HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE":"default","MONGO_URI":"mongodb://hyperdx:{{ .Values.hyperdx.secrets.MONGODB_PASSWORD }}@{{ include \"clickstack.mongodb.svc\" . }}:27017/hyperdx?authSource=hyperdx","OPAMP_PORT":"4320","OPAMP_SERVER_URL":"http://{{ include \"clickstack.hyperdx.fullname\" . }}:{{ .Values.hyperdx.ports.opamp }}","OTEL_EXPORTER_OTLP_ENDPOINT":"http://{{ include \"clickstack.otel.fullname\" . }}:4318","OTEL_SERVICE_NAME":"hdx-oss-api","RUN_SCHEDULED_TASKS_EXTERNALLY":"false","USAGE_STATS_ENABLED":"true"}` | Shared non-sensitive environment variables (clickstack-config ConfigMap). Used by HyperDX and OTEL collector via envFrom. Values support tpl expressions. Override entries with plain strings to point at external services. | | hyperdx.deployment | object | `{"annotations":{},"defaultConnections":"[\n {\n \"name\": \"Local ClickHouse\",\n \"host\": \"http://{{ include \"clickstack.clickhouse.svc\" . }}:8123\",\n \"port\": 8123,\n \"username\": \"app\",\n \"password\": \"{{ .Values.hyperdx.secrets.CLICKHOUSE_APP_PASSWORD }}\"\n }\n]\n","defaultSources":"[\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_logs\"\n },\n \"kind\": \"log\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Logs\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"otel_traces\"\n },\n \"kind\": \"trace\",\n \"timestampValueExpression\": \"Timestamp\",\n \"name\": \"Traces\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"SpanName\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"SpanName\",\n \"eventAttributesExpression\": \"SpanAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"durationExpression\": \"Duration\",\n \"durationPrecision\": 9,\n \"parentSpanIdExpression\": \"ParentSpanId\",\n \"spanNameExpression\": \"SpanName\",\n \"spanKindExpression\": \"SpanKind\",\n \"statusCodeExpression\": \"StatusCode\",\n \"statusMessageExpression\": \"StatusMessage\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"sessionSourceId\": \"Sessions\",\n \"metricSourceId\": \"Metrics\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"\"\n },\n \"kind\": \"metric\",\n \"timestampValueExpression\": \"TimeUnix\",\n \"name\": \"Metrics\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"metricTables\": {\n \"gauge\": \"otel_metrics_gauge\",\n \"histogram\": \"otel_metrics_histogram\",\n \"sum\": \"otel_metrics_sum\",\n \"_id\": \"682586a8b1f81924e628e808\",\n \"id\": \"682586a8b1f81924e628e808\"\n },\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"sessionSourceId\": \"Sessions\"\n },\n {\n \"from\": {\n \"databaseName\": \"default\",\n \"tableName\": \"hyperdx_sessions\"\n },\n \"kind\": \"session\",\n \"timestampValueExpression\": \"TimestampTime\",\n \"name\": \"Sessions\",\n \"displayedTimestampValueExpression\": \"Timestamp\",\n \"implicitColumnExpression\": \"Body\",\n \"serviceNameExpression\": \"ServiceName\",\n \"bodyExpression\": \"Body\",\n \"eventAttributesExpression\": \"LogAttributes\",\n \"resourceAttributesExpression\": \"ResourceAttributes\",\n \"defaultTableSelectExpression\": \"Timestamp,ServiceName,SeverityText,Body\",\n \"severityTextExpression\": \"SeverityText\",\n \"traceIdExpression\": \"TraceId\",\n \"spanIdExpression\": \"SpanId\",\n \"connection\": \"Local ClickHouse\",\n \"logSourceId\": \"Logs\",\n \"traceSourceId\": \"Traces\",\n \"metricSourceId\": \"Metrics\"\n }\n]\n","env":[],"existingConfigConnectionsKey":"connections.json","existingConfigSecret":"","existingConfigSourcesKey":"sources.json","image":{"pullPolicy":"IfNotPresent","repository":"docker.hyperdx.io/hyperdx/hyperdx","tag":null},"initContainers":[],"labels":{},"livenessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":10,"periodSeconds":30,"timeoutSeconds":5},"nodeSelector":{},"priorityClassName":"","readinessProbe":{"enabled":true,"failureThreshold":3,"initialDelaySeconds":1,"periodSeconds":10,"timeoutSeconds":5},"replicas":1,"resources":{},"tolerations":[],"topologySpreadConstraints":[],"useExistingConfigSecret":false,"volumeMounts":[],"volumes":[],"waitForMongodb":{"image":"busybox@sha256:1fcf5df59121b92d61e066df1788e8df0cc35623f5d62d9679a41e163b6a0cdb","pullPolicy":"IfNotPresent"}}` | HyperDX Deployment spec (image, probes, scheduling, init containers, volumes). defaultConnections/defaultSources JSON: set to "" to disable; use useExistingConfigSecret for external secrets. | | hyperdx.deployment.existingConfigSecret | string | `""` | Secret containing connections and sources JSON when useExistingConfigSecret is true. | diff --git a/charts/clickstack/tests/autoscaling-enabled_test.yaml b/charts/clickstack/tests/autoscaling-enabled_test.yaml deleted file mode 100644 index 2bc66bb..0000000 --- a/charts/clickstack/tests/autoscaling-enabled_test.yaml +++ /dev/null @@ -1,13 +0,0 @@ -suite: Test HorizontalPodAutoscaler Enabled -templates: - - hyperdx/hpa.yaml -values: - - values/autoscaling-enabled.yaml -tests: - - it: should render HPA when autoscaling is enabled - asserts: - - isKind: - of: HorizontalPodAutoscaler - - equal: - path: spec.minReplicas - value: 2 diff --git a/charts/clickstack/tests/deployment-tpl-defaults_test.yaml b/charts/clickstack/tests/deployment-tpl-defaults_test.yaml index a19170e..1c0e201 100644 --- a/charts/clickstack/tests/deployment-tpl-defaults_test.yaml +++ b/charts/clickstack/tests/deployment-tpl-defaults_test.yaml @@ -4,9 +4,11 @@ templates: values: - values/deployment-tpl-defaults.yaml tests: - - it: should render inline default sources env var + - it: should render tpl-interpolated default connections and sources asserts: - - isNotEmpty: - path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_SOURCES")] - - isNotEmpty: - path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_CONNECTIONS")] + - matchRegex: + path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_CONNECTIONS")].value + pattern: '"host": "http://RELEASE-NAME-clickstack-clickhouse-clickhouse-headless:8123"' + - matchRegex: + path: spec.template.spec.containers[0].env[?(@.name=="DEFAULT_SOURCES")].value + pattern: '"tableName": "otel_logs"' diff --git a/charts/clickstack/tests/helpers-fullname_test.yaml b/charts/clickstack/tests/helpers-fullname_test.yaml deleted file mode 100644 index b86399c..0000000 --- a/charts/clickstack/tests/helpers-fullname_test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -suite: Test Helper Fullname Override Coverage -templates: - - hyperdx/deployment.yaml -values: - - values/fullname-override.yaml -tests: - - it: should use fullnameOverride for deployment name - asserts: - - equal: - path: metadata.name - value: hyperdx-api diff --git a/charts/clickstack/tests/helpers-name-override_test.yaml b/charts/clickstack/tests/helpers-name-override_test.yaml deleted file mode 100644 index 0425a54..0000000 --- a/charts/clickstack/tests/helpers-name-override_test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -suite: Test Helper Name Override Coverage -templates: - - hyperdx/service.yaml -values: - - values/name-override.yaml -tests: - - it: should use nameOverride in service selector labels - asserts: - - equal: - path: spec.selector["app.kubernetes.io/name"] - value: custom-stack diff --git a/charts/clickstack/tests/helpers-release-name_test.yaml b/charts/clickstack/tests/helpers-release-name_test.yaml deleted file mode 100644 index 9df58d2..0000000 --- a/charts/clickstack/tests/helpers-release-name_test.yaml +++ /dev/null @@ -1,9 +0,0 @@ -suite: Test Helper Fullname Default Coverage -templates: - - hyperdx/deployment.yaml -tests: - - it: should compose release and chart name when release does not contain chart name - asserts: - - equal: - path: metadata.name - value: RELEASE-NAME-clickstack-app diff --git a/charts/clickstack/tests/hyperdx-service_test.yaml b/charts/clickstack/tests/hyperdx-service_test.yaml index 2fa49b5..6c96b2a 100644 --- a/charts/clickstack/tests/hyperdx-service_test.yaml +++ b/charts/clickstack/tests/hyperdx-service_test.yaml @@ -21,6 +21,14 @@ tests: - isNull: path: metadata.annotations + - it: should use nameOverride in service selector labels + set: + nameOverride: custom-stack + asserts: + - equal: + path: spec.selector["app.kubernetes.io/name"] + value: custom-stack + - it: should use LoadBalancer type when configured set: hyperdx: diff --git a/charts/clickstack/tests/ingress-enabled_test.yaml b/charts/clickstack/tests/ingress-enabled_test.yaml deleted file mode 100644 index 8197c2e..0000000 --- a/charts/clickstack/tests/ingress-enabled_test.yaml +++ /dev/null @@ -1,16 +0,0 @@ -suite: Test Ingress Enabled Coverage -templates: - - hyperdx/ingress.yaml -values: - - values/ingress-enabled.yaml -tests: - - it: should render primary ingress when enabled - asserts: - - isKind: - of: Ingress - - equal: - path: spec.ingressClassName - value: alb - - equal: - path: metadata.annotations["alb.ingress.kubernetes.io/scheme"] - value: internet-facing diff --git a/charts/clickstack/tests/secret-disabled_test.yaml b/charts/clickstack/tests/secret-disabled_test.yaml deleted file mode 100644 index 5de38c9..0000000 --- a/charts/clickstack/tests/secret-disabled_test.yaml +++ /dev/null @@ -1,10 +0,0 @@ -suite: Test ClickStack Secret Disabled -templates: - - hyperdx/secret.yaml -values: - - values/secret-disabled.yaml -tests: - - it: should not render secret when secrets is null and subcharts disabled - asserts: - - hasDocuments: - count: 0 diff --git a/charts/clickstack/tests/values/autoscaling-enabled.yaml b/charts/clickstack/tests/values/autoscaling-enabled.yaml deleted file mode 100644 index 9666735..0000000 --- a/charts/clickstack/tests/values/autoscaling-enabled.yaml +++ /dev/null @@ -1,13 +0,0 @@ -hyperdx: - autoscaling: - enabled: true - spec: - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 diff --git a/charts/clickstack/tests/values/fullname-override.yaml b/charts/clickstack/tests/values/fullname-override.yaml deleted file mode 100644 index 2ba028e..0000000 --- a/charts/clickstack/tests/values/fullname-override.yaml +++ /dev/null @@ -1,2 +0,0 @@ -fullnameOverride: hyperdx-api -nameOverride: custom-stack diff --git a/charts/clickstack/tests/values/ingress-enabled.yaml b/charts/clickstack/tests/values/ingress-enabled.yaml deleted file mode 100644 index 7ae55c1..0000000 --- a/charts/clickstack/tests/values/ingress-enabled.yaml +++ /dev/null @@ -1,18 +0,0 @@ -hyperdx: - ingress: - enabled: true - annotations: - alb.ingress.kubernetes.io/scheme: internet-facing - spec: - ingressClassName: alb - rules: - - host: hyperdx.example.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: my-service - port: - number: 8000 diff --git a/charts/clickstack/tests/values/name-override.yaml b/charts/clickstack/tests/values/name-override.yaml deleted file mode 100644 index a58b18c..0000000 --- a/charts/clickstack/tests/values/name-override.yaml +++ /dev/null @@ -1 +0,0 @@ -nameOverride: custom-stack diff --git a/charts/clickstack/tests/values/secret-disabled.yaml b/charts/clickstack/tests/values/secret-disabled.yaml deleted file mode 100644 index 64a04a4..0000000 --- a/charts/clickstack/tests/values/secret-disabled.yaml +++ /dev/null @@ -1,8 +0,0 @@ -mongodb: - enabled: false -clickhouse: - enabled: false -otel-collector: - enabled: false -hyperdx: - secrets: null diff --git a/charts/clickstack/values.yaml b/charts/clickstack/values.yaml index 7dbfa26..7ee49ff 100644 --- a/charts/clickstack/values.yaml +++ b/charts/clickstack/values.yaml @@ -220,8 +220,7 @@ hyperdx: podDisruptionBudget: enabled: false - # -- HorizontalPodAutoscaler for HyperDX. spec is passed through verbatim (autoscaling/v2). - # Do not include scaleTargetRef — the chart auto-wires it. Omitting replicas when enabled. + # -- HorizontalPodAutoscaler for HyperDX. spec is passed through verbatim (autoscaling/v2). Do not include scaleTargetRef — the chart auto-wires it. When enabled, omit deployment.replicas; disabling autoscaling reverts to deployment.replicas (default 1). autoscaling: enabled: false spec: {} diff --git a/scripts/helmcov.sh b/scripts/helmcov.sh index 6cf8bbf..fc9adf4 100755 --- a/scripts/helmcov.sh +++ b/scripts/helmcov.sh @@ -3,12 +3,14 @@ set -e set -o pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# shellcheck disable=SC1091 +source "${ROOT_DIR}/scripts/load-tool-versions.sh" +load_tool_versions "${ROOT_DIR}" CHART_PATH="${CHART_PATH:-charts/clickstack}" TESTS_PATH="${TESTS_PATH:-charts/clickstack/tests}" -HELMCOV_IMAGE="${HELMCOV_IMAGE:-ghcr.io/jordan-simonovski/helmcov:v0.3.2}" COVERAGE_OUT="${COVERAGE_OUT:-coverage.out}" COVERAGE_XML="${COVERAGE_XML:-coverage.xml}" -THRESHOLD="${THRESHOLD:-25}" +THRESHOLD="${THRESHOLD:-30}" MAX_SCENARIOS="${MAX_SCENARIOS:-20}" SEED="${SEED:-42}" VERBOSE="${VERBOSE:-}" @@ -50,6 +52,7 @@ fi docker run --rm \ --platform linux/amd64 \ + --user "$(id -u):$(id -g)" \ -v "${ROOT_DIR}:/work" \ -w /work \ "${HELMCOV_IMAGE}" \ diff --git a/scripts/install-helm-docs.sh b/scripts/install-helm-docs.sh index d62ecc5..59057ca 100755 --- a/scripts/install-helm-docs.sh +++ b/scripts/install-helm-docs.sh @@ -2,16 +2,23 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# shellcheck disable=SC1091 +source "${ROOT_DIR}/scripts/load-tool-versions.sh" +load_tool_versions "${ROOT_DIR}" TOOLS_DIR="${ROOT_DIR}/.tools" -HELM_DOCS_VERSION="${HELM_DOCS_VERSION:-v1.14.2}" HELM_DOCS_BIN="${TOOLS_DIR}/helm-docs" +expected_version="${HELM_DOCS_VERSION#v}" if [[ -x "${HELM_DOCS_BIN}" ]]; then - echo "helm-docs already installed at ${HELM_DOCS_BIN}" - exit 0 + installed_version="$("${HELM_DOCS_BIN}" --version 2>/dev/null | awk '{print $NF}')" + if [[ "${installed_version}" == "${expected_version}" ]]; then + echo "helm-docs ${HELM_DOCS_VERSION} already installed at ${HELM_DOCS_BIN}" + exit 0 + fi + echo "helm-docs version mismatch (installed: ${installed_version}, wanted: ${expected_version}); reinstalling..." fi -os="$(uname | tr '[:upper:]' '[:lower:]')" +os="$(uname)" arch="$(uname -m)" case "${arch}" in x86_64) arch="x86_64" ;; diff --git a/scripts/load-tool-versions.sh b/scripts/load-tool-versions.sh new file mode 100644 index 0000000..d39dca9 --- /dev/null +++ b/scripts/load-tool-versions.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Load defaults from scripts/tool-versions.env without overriding existing env vars. +load_tool_versions() { + local root_dir="${1:?root dir required}" + local line key default + + while IFS= read -r line || [[ -n "${line}" ]]; do + [[ "${line}" =~ ^[[:space:]]*# ]] && continue + [[ -z "${line//[[:space:]]/}" ]] && continue + key="${line%%=*}" + default="${line#*=}" + if [[ -z "${!key:-}" ]]; then + export "${key}=${default}" + fi + done < "${root_dir}/scripts/tool-versions.env" +} diff --git a/scripts/tool-versions.env b/scripts/tool-versions.env new file mode 100644 index 0000000..83566ba --- /dev/null +++ b/scripts/tool-versions.env @@ -0,0 +1,8 @@ +# Pinned third-party tool versions for local dev and CI. +# Sourced by shell scripts; included by the Makefile. Override via environment. +# +# HELMCOV_IMAGE: digest-pinned to avoid mutable-tag drift. Mirror to ghcr.io/clickhouse +# when org registry access is available. + +HELM_DOCS_VERSION=v1.14.2 +HELMCOV_IMAGE=ghcr.io/jordan-simonovski/helmcov@sha256:eb659cda7f9c065d3424b33583f0ad6cd8a4eecb6a960172ba3699b1a8ac9c7e From c6d49eac5fef407cdc46e71b9bd05d138b8a3e75 Mon Sep 17 00:00:00 2001 From: Jordan Simonovski Date: Sat, 27 Jun 2026 14:28:39 +1000 Subject: [PATCH 4/5] ci: use helmcov GitHub Action for PR coverage comments Replace Docker-based make coverage in CI with jordan-simonovski/helmcov@v1 so pull requests get upserted coverage summaries with threshold enforcement. Co-authored-by: Cursor --- .github/workflows/helmcov.yaml | 20 +++++++++++--------- AGENTS.md | 10 +++++++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/helmcov.yaml b/.github/workflows/helmcov.yaml index da79c15..43fa9cd 100644 --- a/.github/workflows/helmcov.yaml +++ b/.github/workflows/helmcov.yaml @@ -16,6 +16,10 @@ on: - 'scripts/**' - '.github/workflows/helmcov.yaml' +permissions: + contents: read + pull-requests: write + jobs: helmcov: runs-on: ubuntu-latest @@ -28,14 +32,12 @@ jobs: with: version: v3.12.0 - - name: Run template coverage - run: make coverage + - name: Build chart dependencies + run: make chart-deps - - name: Upload coverage reports - uses: actions/upload-artifact@v4 - if: always() + - name: Run helmcov + uses: jordan-simonovski/helmcov@v1 with: - name: helmcov-reports - path: | - coverage.out - coverage.xml + chart: charts/clickstack + tests: charts/clickstack/tests + threshold: "30" diff --git a/AGENTS.md b/AGENTS.md index 36465ad..85311e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -100,8 +100,12 @@ HELMCOV_IMAGE=ghcr.io/example/helmcov@sha256:... make coverage ``` Uses the digest-pinned image in `scripts/tool-versions.env` with a **30% line -coverage threshold**. Outputs `coverage.out` (Go coverprofile) and `coverage.xml` -(Cobertura). CI runs `make coverage` via `.github/workflows/helmcov.yaml`. +coverage threshold** for local runs. Outputs `coverage.out` (Go coverprofile) and +`coverage.xml` (Cobertura). + +CI runs the [helmcov GitHub Action](https://github.com/jordan-simonovski/helmcov) +via `.github/workflows/helmcov.yaml`, which posts or updates a pull request +comment with line/branch coverage and uncovered details. ### Chart README (helm-docs) @@ -213,7 +217,7 @@ tests: | Workflow | File | Trigger | Purpose | |----------|------|---------|---------| | Helm Chart Tests | `helm-test.yaml` | push/PR to main | Unit tests + example validation | -| Helm Template Coverage | `helmcov.yaml` | push/PR to main | helmcov template line/branch coverage | +| Helm Template Coverage | `helmcov.yaml` | push/PR to main | helmcov action; PR comment with line/branch coverage | | Integration Test | `chart-test.yml` | push/PR/nightly | Kind-based integration suites | | Release | `release.yml` | after tests pass on main | Changeset version + chart release | | Update App Version | `update-app-version.yml` | workflow_dispatch | Bump `appVersion` in Chart.yaml | From b1f7a91c27858d26e6b0f18eaf6a9b5ecdc4a733 Mon Sep 17 00:00:00 2001 From: Jordan Simonovski Date: Sat, 27 Jun 2026 14:31:42 +1000 Subject: [PATCH 5/5] ci: pin helmcov action binary to v0.4.0 v0.3.3 lacks --markdown-file support required by the v1 action entrypoint. Co-authored-by: Cursor --- .github/workflows/helmcov.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/helmcov.yaml b/.github/workflows/helmcov.yaml index 43fa9cd..afaa4b6 100644 --- a/.github/workflows/helmcov.yaml +++ b/.github/workflows/helmcov.yaml @@ -41,3 +41,4 @@ jobs: chart: charts/clickstack tests: charts/clickstack/tests threshold: "30" + version: v0.4.0