diff --git a/.github/workflows/publish-b.yml b/.github/workflows/publish-b.yml index 13fbdada..470e808f 100644 --- a/.github/workflows/publish-b.yml +++ b/.github/workflows/publish-b.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: helmwave/setup-action@v0.3.0 with: - version: '0.31.0' + version: '0.32.1' - run: helmwave schema > schema.json - uses: actions/checkout@v3 with: diff --git a/.gitignore b/.gitignore index 0888f934..3e2ffa66 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,6 @@ Temporary Items .idea/ +.vscode/ site/ -**/.helmwave/ \ No newline at end of file +**/.helmwave/ diff --git a/docs/anno.md b/docs/anno.md index 76c243b9..92655563 100644 --- a/docs/anno.md +++ b/docs/anno.md @@ -15,7 +15,10 @@ metadata: ## Helmwave's annotations -!!! danger "Initially annotations used `helmwave.dev/` namespace but in [:material-tag: v0.31.1](https://github.com/helmwave/helmwave/releases/tag/v0.31.1) it was switched to `helmwave.app/` with backward compatibility." +!!! danger "Initially annotations used `helmwave.dev/` namespace" + + In [:material-tag: v0.31.1](https://github.com/helmwave/helmwave/releases/tag/v0.31.1) it was switched to `helmwave.app/` with backward compatibility. + In [:material-tag: v0.32.0](https://github.com/helmwave/helmwave/releases/tag/v0.32.0) support for old annotations was dropped. ### `helmwave.app/skip-diff` diff --git a/docs/comparison.md b/docs/comparison.md index 18e39b0e..05141286 100644 --- a/docs/comparison.md +++ b/docs/comparison.md @@ -1,6 +1,7 @@ # Comparison to alternatives -> Some comparisons may be outdated as we don't check every release. If any of the tools have improved, please open a [PR](https://github.com/helmwave/docs/issues/new). +> Some comparisons may be outdated as we don't check every release. If any of the tools have improved, please open +> a [PR](https://github.com/helmwave/docs/issues/new). ## As table @@ -14,6 +15,7 @@ | **Live-tracking :simple-kubernetes: k8s resources** | [Kubedog](https://github.com/werf/kubedog) | No | No | | Get application logs | [Kubedog](https://github.com/werf/kubedog) | No | No | | Get :simple-kubernetes: k8s events | [Kubedog](https://github.com/werf/kubedog) and :simple-helm: helm progress | No | No | +| **Automatically rollback based on metrics** | `monitors` | No | No | | Labels | `tags` | `labels` | ? | | Manage kube-context via iac | Yes | Yes | Yes | | Parallel releases | Yes | Yes | Releases with the same priority can be executed in parallel. | @@ -27,22 +29,25 @@ | OCI | `registries` | option in `repositories` | only `pull`, not `login` | | Lifecycle Hooks | Yes (pre_up, post_up, pre_down, post_down, pre_rollback, post_rollback, pre_build, post_build) | Yes (prepare, preapply, presync, preuninstall, postuninstall, postsync, cleanup) | No | | Sub-main config | No | Yes | ? | -| manage render values | `render` option and options for setting delimiters | by file extension | ? | +| manage render values | `renderer` option and options for setting delimiters | by file extension | ? | | Remote values | HTTP/HTTPS only | `go-getter` | ? | | **Planfile** | Yes | No | No | | Vault / AWS SSM | via `gomplate` datasources | custom functions | ? | - ## Why not bare Helm? ### Managing multiple environments -Imagine you have multiple environments for same release (e.g. dev, stage, production, etc.). You likely have different settings. +Imagine you have multiple environments for same release (e.g. dev, stage, production, etc.). You likely have different +settings. === ":simple-helm: helm" - You will likely have bunch of bash scripts that run helm with different values files. It is quite hard to support and improve. + + You will likely have bunch of bash scripts that run helm with different values files. It is quite hard to support and + improve. === "🌊 helmwave" + Set up `helmwave.yml.tpl` to include different values for different environments. Check out [:material-duck: the example](../examples/single-app-multi-envs) @@ -52,10 +57,14 @@ Check out [:material-duck: the example](../examples/single-app-multi-envs) For example, you need to pass docker image tag. === ":simple-helm: helm" - Either you template values file (e.g. with ansible/jinja2 or any other templater) or you pass every individual value via `--set`. + + Either you template values file (e.g. with ansible/jinja2 or any other templater) or you pass every individual value + via `--set`. === "🌊 helmwave" - Every values file are templated via `sprig` or `gomplate` which allows you to generate any values even with external commands. + + Every values file are templated via `sprig` or `gomplate` which allows you to generate any values even with external + commands. Check out [:material-duck: the example](../examples/pass-git-tag) @@ -64,50 +73,63 @@ Check out [:material-duck: the example](../examples/pass-git-tag) Imagine you need to deploy more than 1 release (e.g. deploy 10+ microservices to dynamic feature environment). === ":simple-helm: helm" + Either deploy releases one-by-one or create an umbrella chart (we think it is bad pattern). === "🌊 helmwave" + All releases are deployed in parallel with a dependency mechanism. Check out [:material-duck: the example](../examples/umbrella-evil) ### Managing dependencies between releases -Imagine you need to deploy some DBMS and an app that uses it. While DBMS is provisioning (or scheduling) your app already starts failing probes. It may lead to failing app release. +Imagine you need to deploy some DBMS and an app that uses it. While DBMS is provisioning (or scheduling) your app +already starts failing probes. It may lead to failing app release. === ":simple-helm: helm" + Manually deploy releases one-by-one. === "🌊 helmwave" + Use `depends_on` to set up explicit dependencies between releases. ### Release stuck in pending state -If your CI for some reason killed helm process your next `helm upgrade` will fail because release is in `pending-upgrade` state. +If your CI for some reason killed helm process your next `helm upgrade` will fail because release is +in `pending-upgrade` state. === ":simple-helm: helm" - You need to either do `helm rollback` (doesn't work for `pending-install`) or `helm delete` (destructive in production) and try upgrade one more time. + + You need to either do `helm rollback` (doesn't work for `pending-install`) or `helm delete` (destructive in production) + and try upgrade one more time. === "🌊 helmwave" + Use `pending_release_strategy` to automatically do rollbacks or delete before upgrade if required. ### Live-tracking release === ":simple-helm: helm" + You can enable debug logs which will provide you logs of what helm does. === "🌊 helmwave" + Use [kubedog](https://github.com/werf/kubedog) to show status progress. Check out [:material-duck: the example](../examples/kubedog) ## Why not [Helmfile](https://github.com/helmfile/helmfile) ![GitHub Repo stars](https://img.shields.io/github/stars/helmfile/helmfile)? -We don't consider helmwave as a helmfile killer. Helmfile is an awesome project that really inspired us to implement the same in a bit different way with some other features. Probably there would be no helmwave if there was no helmfile. +We don't consider helmwave as a helmfile killer. Helmfile is an awesome project that really inspired us to implement the +same in a bit different way with some other features. Probably there would be no helmwave if there was no helmfile. ### Helm execution === "helmfile" + Helmfile runs `helm` via `os.Exec`. It means that: - You need `helm` binary as well as a lot of other dependencies (e.g. libc). Helmfile's official docker image requires for around 300MB. @@ -115,31 +137,37 @@ We don't consider helmwave as a helmfile killer. Helmfile is an awesome project - `os.Exec` is not the fastest way to run helm. If 10ns of overhead does really matter to you. === "🌊 helmwave" + Helmwave runs `helm` as an internal bundled library. It means that: - Helmwave already contains builtin specific (we try to keep it up to date) `helm` version. - There are no helmwave dependencies at all - it can be completely static binary. Official docker image requires for around 30MB. And it can run both in musl and glibc environments. - We constantly check out new `helm` features and try to enhance them in helmwave. - ### Live-tracking release === "helmfile" - Only helm progress is available although there is [a discussion about kubedog integration](https://github.com/helmfile/helmfile/discussions/660). + + Only helm progress is available although there + is [a discussion about kubedog integration](https://github.com/helmfile/helmfile/discussions/660). === "🌊 helmwave" + Use [kubedog](https://github.com/werf/kubedog) to show status progress. Check out [:material-duck: the example](../examples/kubedog) ### Release stuck in pending state -If your CI for some reason killed helm process your next `helm upgrade` will fail because release is in `pending-upgrade` state. +If your CI for some reason killed helm process your next `helm upgrade` will fail because release is +in `pending-upgrade` state. === "helmfile" + The same as for helm === "🌊 helmwave" + Use `pending_release_strategy` to automatically do rollbacks or delete before upgrade if required. ### Templating engine @@ -147,7 +175,10 @@ If your CI for some reason killed helm process your next `helm upgrade` will fai By templating engine we understand collection of builtin functions for default golang templates. === "helmfile" + Helmfile only supports `sprig` as a template engine. === "🌊 helmwave" - Every values file can be templated via `sprig` or `gomplate` (or even non-templated at all). Gomplate is an awesome huge engine that has a lot of features. + + Every values file can be templated via `sprig` or `gomplate` (or even non-templated at all). Gomplate is an awesome huge + engine that has a lot of features. diff --git a/docs/examples/helmfile-migration/README.md b/docs/examples/helmfile-migration/README.md new file mode 100644 index 00000000..569987b0 --- /dev/null +++ b/docs/examples/helmfile-migration/README.md @@ -0,0 +1,189 @@ +# Helmfile migration + +Suppose we have next `helmfile.yaml` + +```yaml title="helmfile.yaml" +{% include "./helmfile.yaml" %} +``` + +How to migrate it to `helmwave.yml.tpl`? + +## Repository + +=== "helmfile" + + ```yaml + repositories: + - name: gitlab + url: https://charts.gitlab.io/ + ``` + +=== "🌊 helmwave" + + ```yaml + repositories: + - name: gitlab + url: https://charts.gitlab.io/ + ``` + +## Environments + +Helmwave can use gomplate templater to resolve this problem. + +```shell +export HELMWAVE_TEMPLATER=gomplate +``` + +=== "helmfile" + + ```yaml + environments: + dev: + kubeContext: dev + values: + - filebeat: + enabled: true + - minio: + enabled: true + - gitlab: + enabled: false + - grafana: + enabled: true + prod: + kubeContext: prod + values: + - filebeat: + enabled: true + - minio: + enabled: false + - gitlab: + enabled: true + - grafana: + enabled: false + ``` + +=== "🌊 helmwave" + + 1. Create `envs.yml` for storing environment settings. + + ```yaml title="envs.yml" + {% include "./envs.yml" %} + ``` + + 2. Add next code to helwmave.yml.tpl + + ```yaml title="helwmave.yml.tpl" + {{- $env := getenv "ENV" -}} + + {{- defineDatasource "envs" "envs.yml" -}} + {{- $envs := (ds "envs").envs -}} + + # It'll chose env setting by $ENV + {{ $e := index $envs $env }} + ... + ``` + +## Matching release with environment + +=== "helmfile" + + ```yaml + environments: + dev: + kubeContext: dev + values: + - gitlab: + enabled: false + ... + releases: + - name: gitlab + condition: gitlab.enabled + ... + ``` + +=== "🌊 helmwave" + + ```yaml title="helwmave.yml.tpl" + ... + {{ $r := $e.releases }} + releases: + {{- if (index $r "gitlab") }} + - name: gitlab + chart: gitlab/gitlab + version: 7.2.2 + namespace: gitlab + tags: ["gitlab"] + values: + - ./values/{{ $env }}/gitlab.yaml + {{- end }} + ... + ``` + +## Helm Defaults + +Just use yaml anchors. + +=== "helmfile" + + ```yaml + helmDefaults: + atomic: true + historyMax: 3 + timeout: 1200 + ``` + +=== "🌊 helmwave" + + ```yaml title="helwmave.yml.tpl" + .options: &options + atomic: true + timeout: 1200 + max_history: 3 + + releases: + - name: gitlab + <<: *options + ``` + +### Matching kubecontext with environment + +=== "helmfile" + + ```yaml + environments: + dev: + kubeContext: dev + ``` + +=== "🌊 helmwave" + + ```yaml title="helwmave.yml.tpl" + {{- $kubecontext := $e.kubecontext -}} + .options: &options + atomic: true + timeout: 1200 + max_history: 3 + context: {{ $kubecontext }} + + releases: + - name: gitlab + <<: *options + ``` + +## Results + +=== "helmfile" + + ```yaml + {% include "./helmfile.yaml" %} + ``` + +=== "🌊 helmwave" + + ```yaml title="helmwave.yml.tpl" + {% include "./helmwave.yml.tpl" %} + ``` + + ```yaml title="envs.yml" + {% include "./envs.yml" %} + ``` diff --git a/docs/examples/helmfile-migration/envs.yml b/docs/examples/helmfile-migration/envs.yml new file mode 100644 index 00000000..42dce17f --- /dev/null +++ b/docs/examples/helmfile-migration/envs.yml @@ -0,0 +1,14 @@ +envs: + dev: + kubecontext: dev + releases: + minio: true + grafana: true + filebeat: true + + prod: + kubecontext: prod + releases: + gitlab: true + filebeat: true + diff --git a/docs/examples/helmfile-migration/helmfile.yaml b/docs/examples/helmfile-migration/helmfile.yaml new file mode 100644 index 00000000..d2090a52 --- /dev/null +++ b/docs/examples/helmfile-migration/helmfile.yaml @@ -0,0 +1,68 @@ +environments: + dev: + kubeContext: dev + values: + - filebeat: + enabled: true + - minio: + enabled: true + - gitlab: + enabled: false + - grafana: + enabled: true + prod: + kubeContext: prod + values: + - filebeat: + enabled: true + - minio: + enabled: false + - gitlab: + enabled: true + - grafana: + enabled: false + +repositories: + - name: gitlab + url: https://charts.gitlab.io/ + +helmDefaults: + atomic: true + historyMax: 3 + timeout: 1200 + +releases: + - name: gitlab + condition: gitlab.enabled + chart: gitlab/gitlab + version: 7.2.2 + namespace: gitlab + values: + - ./values/{{ .Environment.Name }}/gitlab.yaml + + - name: minio + condition: minio.enabled + chart: ./charts/minio + namespace: minio + values: + - ./values/{{ .Environment.Name }}/minio.gotmpl + secrets: + - ./values/{{ .Environment.Name }}/minio-secret.yaml + + - name: grafana + condition: grafana.enabled + chart: ./charts/grafana + namespace: grafana + values: + - ./values/{{ .Environment.Name }}/grafana.yaml + secrets: + - ./values/{{ .Environment.Name }}/grafana-secrets.yaml + + - name: filebeat + condition: filebeat.enabled + chart: ./charts/filebeat + namespace: filebeat + values: + - ./values/{{ .Environment.Name }}/filebeat.yaml + secrets: + - ./values/{{ .Environment.Name }}/filebeat-secrets.yaml diff --git a/docs/examples/helmfile-migration/helmwave.yml.tpl b/docs/examples/helmfile-migration/helmwave.yml.tpl new file mode 100644 index 00000000..27c8ae2a --- /dev/null +++ b/docs/examples/helmfile-migration/helmwave.yml.tpl @@ -0,0 +1,64 @@ +{{- $env := getenv "ENV" -}} + +{{- defineDatasource "envs" "envs.yml" -}} +{{- $envs := (ds "envs").envs -}} + +{{ $e := index $envs $env }} +{{- $kubecontext := $e.kubecontext -}} +{{ $r := $e.releases }} + +repositories: + - name: gitlab + url: https://charts.gitlab.io/ + +.options: &options + context: {{ $kubecontext }} + atomic: true + timeout: 1200 + max_history: 3 + +releases: + {{- if (index $r "gitlab") }} + - name: gitlab + <<: *options + chart: gitlab/gitlab + version: 7.2.2 + namespace: gitlab + tags: ["gitlab"] + values: + - ./values/{{ $env }}/gitlab.yaml + {{- end }} + + {{- if (index $r "minio") }} + - name: minio + chart: ./charts/minio + namespace: minio + values: + - ./values/{{ $env }}/minio.yaml + secrets: + - src: ./values/{{ $env }}/minio-secret.yaml + renderer: sops + {{- end }} + + {{- if (index $r "grafana") }} + - name: grafana + chart: ./charts/grafana + namespace: grafana + values: + - src: ./values/{{ $env }}/grafana.yaml + renderer: copy + secrets: + - src: ./values/{{ $env }}/grafana-secret.yaml + renderer: sops + {{- end }} + + {{- if (index $r "filebeat") }} + - name: filebeat + chart: ./charts/filebeat + namespace: filebeat + values: + - ./values/{{ $env }}/filebeat.yaml + secrets: + - src: ./values/{{ $env }}/filebeat-secret.yaml + renderer: sops + {{- end }} diff --git a/docs/examples/kubedog/helmwave.yml b/docs/examples/kubedog/helmwave.yml index dfd7f114..f0a99576 100644 --- a/docs/examples/kubedog/helmwave.yml +++ b/docs/examples/kubedog/helmwave.yml @@ -1,14 +1,18 @@ -project: "Example: kubedog" -version: "⟨⟨ ver ⟩⟩" +#project: "Example: kubedog" +#version: "⟨⟨ ver ⟩⟩" -repositories: - - name: bitnami - url: https://charts.bitnami.com/bitnami + +registries: + - host: registry-1.docker.io + +#repositories: +# - name: bitnami +# url: https://charts.bitnami.com/bitnami releases: - name: my1 chart: - name: bitnami/redis + name: oci://registry-1.docker.io/bitnamicharts/redis version: 16.8.5 values: - values.yml diff --git a/docs/examples/kubedog/values.yml b/docs/examples/kubedog/values.yml index 9cbb6388..62b929a5 100644 --- a/docs/examples/kubedog/values.yml +++ b/docs/examples/kubedog/values.yml @@ -1,7 +1,7 @@ # Uncommented it if you need -#commonAnnotations: -# helmwave.app/show-service-messages: "true" -# helmwave.app/show-logs-only-for-containers: "redis" +commonAnnotations: + helmwave.app/show-service-messages: "true" + helmwave.app/show-logs-only-for-containers: "redis" podAnnotations: datetime: {{ now }} diff --git a/docs/examples/monitors/README.md b/docs/examples/monitors/README.md new file mode 100644 index 00000000..8f172f8c --- /dev/null +++ b/docs/examples/monitors/README.md @@ -0,0 +1,79 @@ +--- +hide: + - toc +--- +# 🔎 Monitors + +Monitors run custom releases validations and can rollback releases. + +### Monitors flow + +```mermaid +flowchart LR + helmwave_up[helmwave up] + exit0[exit 0] + exit1[exit 1] + + helmwave_up --> release1[upgrade release 1] + helmwave_up --> release2[upgrade release 2] + helmwave_up --> release3[upgrade release 3] + + release1 -- succeeded --> monitor1_start + release2 -- succeeded --> monitor1_start + release2 -- succeeded --> monitor2_start + release3 -- succeeded --> monitor2_start + + monitor1_failed -.rollback release.->release_rollback1[rollback release 1] + monitor1_failed -.rollback release.->release_rollback2[rollback release 2] + monitor2_failed -.rollback release.->release_rollback2[rollback release 2] + monitor2_failed -.rollback release.->release_rollback3[rollback release 3] + + release_rollback1 -.-> exit1 + release_rollback2 -.-> exit1 + release_rollback3 -.-> exit1 + + monitor1_succeeded -.-> exit0 + monitor2_succeeded -.-> exit0 + + subgraph monitor1[Monitor 1] + monitor1_start[Monitor start] + monitor1_iteration[Monitor iteration] + monitor1_failed[Monitor failed] + monitor1_succeeded[Monitor succeeded] + + monitor1_start --> monitor1_iteration + monitor1_iteration --next iteration--> monitor1_iteration + monitor1_iteration --failure threshold or total timeout-->monitor1_failed + monitor1_iteration --success threshold-->monitor1_succeeded + end + + subgraph monitor2[Monitor 2] + monitor2_start[Monitor start] + monitor2_iteration[Monitor iteration] + monitor2_failed[Monitor failed] + monitor2_succeeded[Monitor succeeded] + + monitor2_start --> monitor2_iteration + monitor2_iteration --next iteration--> monitor2_iteration + monitor2_iteration --failure threshold or total timeout-->monitor2_failed + monitor2_iteration --success threshold-->monitor2_succeeded + end +``` + +- Each monitor starts when its all dependant releases succeeded +- Each monitor runs its iterations every `iterval` with `iteration_timeout` +- Consecutive successful iterations are counted towards `success_threshold` +- Consecutive failed iterations are counted towards `failure_threshold` +- After all monitors exited dependant releases do actions for their failed monitors + +### Demo + +[![asciicast](https://asciinema.org/a/NMGo0NMZOMQjtx0bZPxtlETaL.svg)](https://asciinema.org/a/NMGo0NMZOMQjtx0bZPxtlETaL) + +```yaml title="helmwave.yml" +{% include "./helmwave.yml" %} +``` + +```shell title="$ helmwave build --diff-mode none" +{% include "./log" %} +``` \ No newline at end of file diff --git a/docs/examples/monitors/helmwave.yml b/docs/examples/monitors/helmwave.yml new file mode 100644 index 00000000..30eb1722 --- /dev/null +++ b/docs/examples/monitors/helmwave.yml @@ -0,0 +1,44 @@ +registries: + - host: registry-1.docker.io + +monitors: + - name: nats-up-metric + type: prometheus + total_timeout: 1m # fail if it flaps between success and failure for so long + iteration_timeout: 1s + interval: 2s + success_threshold: 5 + failure_threshold: 5 + prometheus: + url: http://localhost:9090 + expr: | + up == 1 + - name: nats-delivered-metric + type: prometheus + total_timeout: 1m # fail if it flaps between success and failure for so long + iteration_timeout: 5s + interval: 10s + success_threshold: 5 + failure_threshold: 5 + prometheus: + url: http://localhost:9090 + expr: | + sum(rate(nats_consumer_delivered_consumer_seq[15s])) > 0 + +.options: &options + namespace: nats + create_namespace: true + wait: true + timeout: 1m + max_history: 3 # best practice + chart: + # For example, we will use bitnami/nats chart, because it's small and fast + name: oci://registry-1.docker.io/bitnamicharts/nats + version: 7.8.3 # best practice + +releases: + - name: nats + <<: *options + monitors: + - name: nats-up-metric + - name: nats-delivered-metric diff --git a/docs/examples/monitors/log b/docs/examples/monitors/log new file mode 100644 index 00000000..7003692f --- /dev/null +++ b/docs/examples/monitors/log @@ -0,0 +1,102 @@ +[INFO]: 🔨 Building releases... +[INFO]: 🔨 Building values... +[INFO]: 🔨 no values provided + release: nats@nats +[INFO]: 🔨 Building repositories... +[INFO]: 🔨 Building registries... +[INFO]: 🗄 registry has been added to the plan + registry: registry-1.docker.io +[INFO]: 🔨 Building charts... +[INFO]: Pulled: registry-1.docker.io/bitnamicharts/nats:7.8.3 +[INFO]: Digest: sha256:5f80350b8a85177e4a9c7ed968f77c47bedcc461418172fb66594bc61fa1ffac +[INFO]: 🔨 Building manifests... +[INFO]: ❎ skipping updating dependencies for remote chart + release: nats@nats +[INFO]: Pulled: registry-1.docker.io/bitnamicharts/nats:7.8.3 +[INFO]: Digest: sha256:5f80350b8a85177e4a9c7ed968f77c47bedcc461418172fb66594bc61fa1ffac +[INFO]: ✅ manifest done + release: nats@nats +[INFO]: 🔨 Building graphs... +[INFO]: show graph: +┌───────────┐ +│ nats@nats │ +└───────────┘ + +[INFO]: 🏗 Plan + registries: + - registry-1.docker.io + releases: + - nats@nats + repositories: + - +[INFO]: 🆚 Skip diffing +[INFO]: 🏗 Planfile is ready! +[INFO]: 🏗 Plan + releases: + - nats@nats + repositories: + - + registries: + - registry-1.docker.io +[INFO]: 🗄 sync repositories... +[INFO]: 🗄 sync registries... +[INFO]: 🛥 sync releases... +[INFO]: 🛥 deploying... + release: nats@nats +[INFO]: ✅ + release: nats@nats +[INFO]: monitor succeeded + monitor: nats-up-metric + streak: 1/5 +[INFO]: monitor succeeded + monitor: nats-up-metric + streak: 2/5 +[INFO]: monitor succeeded + streak: 3/5 + monitor: nats-up-metric +[INFO]: monitor succeeded + streak: 4/5 + monitor: nats-up-metric +[INFO]: monitor did not succeed + monitor: nats-delivered-metric + streak: 1/5 + error: result is empty +[INFO]: monitor succeeded + monitor: nats-up-metric + streak: 5/5 +[INFO]: ✅ + monitor: nats-up-metric +[INFO]: monitor did not succeed + monitor: nats-delivered-metric + streak: 2/5 + error: result is empty +[INFO]: monitor did not succeed + error: result is empty + monitor: nats-delivered-metric + streak: 3/5 +[INFO]: monitor did not succeed + error: result is empty + streak: 4/5 + monitor: nats-delivered-metric +[INFO]: monitor did not succeed + monitor: nats-delivered-metric + streak: 5/5 + error: result is empty +[ERROR]: ❌ monitor failed + monitor: nats-delivered-metric + error: monitor triggered failure threshold +[ERROR]: monitors failed, need to take actions + error: one of goroutines in waitgroup sent error: 1 error occurred: + * monitor triggered failure threshold + + +[INFO]: chose action to perform for failed monitors + action: rollback + release: nats@nats +[INFO]: Releases Success 1 / 1 +[INFO]: Monitors Success 1 / 2 + NAME | ERROR +------------------------+--------------------------------- + nats-delivered-metric | monitor triggered failure + | threshold +[FATAL]: deploy failed diff --git a/docs/examples/umbrella-evil/README.md b/docs/examples/umbrella-evil/README.md index c0117943..28209249 100644 --- a/docs/examples/umbrella-evil/README.md +++ b/docs/examples/umbrella-evil/README.md @@ -6,7 +6,7 @@ Why is Umbrella chart evil? - You must keep extra chart. - You have new layer for conventional values. -- Umbrella chart doesn't provide separate your environments. +- Umbrella chart doesn't provide you environments separation. - When sub-chart is modified, you need to fix it twice. !!! info "Suppose that you need to describe the next architecture." diff --git a/docs/examples/values-disable-render/README.md b/docs/examples/values-disable-render/README.md new file mode 100644 index 00000000..a552e5ef --- /dev/null +++ b/docs/examples/values-disable-render/README.md @@ -0,0 +1,16 @@ +# Disable templating + +> Introduced in [:material-tag: v0.20.0](https://github.com/helmwave/helmwave/releases/tag/v0.20.0) as `render: false` + +> Changed in [:material-tag: v0.32.0](https://github.com/helmwave/helmwave/releases/tag/v0.32.0) as `renderer: copy` + +Sometimes we need to disable templating values. For example, prometheus rules. + +```yaml title="helmwave.yml" +{% include "./helmwave.yml" %} +``` + + +```yaml title="values.yml" +{% include "./values.yml" %} +``` diff --git a/docs/examples/values-render-flag/helmwave.yml b/docs/examples/values-disable-render/helmwave.yml similarity index 93% rename from docs/examples/values-render-flag/helmwave.yml rename to docs/examples/values-disable-render/helmwave.yml index 9bce132b..fb1f2419 100644 --- a/docs/examples/values-render-flag/helmwave.yml +++ b/docs/examples/values-disable-render/helmwave.yml @@ -15,4 +15,4 @@ releases: chart: bitnami/nginx values: - src: values.yml - render: false + renderer: copy diff --git a/docs/examples/values-render-flag/values.yml b/docs/examples/values-disable-render/values.yml similarity index 100% rename from docs/examples/values-render-flag/values.yml rename to docs/examples/values-disable-render/values.yml diff --git a/docs/examples/values-render-flag/README.md b/docs/examples/values-render-flag/README.md deleted file mode 100644 index a40767c7..00000000 --- a/docs/examples/values-render-flag/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Render flag for values - -Sometimes we need to disable render values. For example prometheus rules. - - -```yaml title="values.yml" -{% include "./values.yml" %} -``` - - -```yaml title="helmwave.yml" -{% include "./helmwave.yml" %} -``` diff --git a/docs/examples/values-sops/README.md b/docs/examples/values-sops/README.md new file mode 100644 index 00000000..101ea818 --- /dev/null +++ b/docs/examples/values-sops/README.md @@ -0,0 +1,15 @@ +# Decode values with SOPS + +> Introduced in [:material-tag: v0.32.0](https://github.com/helmwave/helmwave/releases/tag/v0.32.0) + +[SOPS](https://github.com/getsops/sops) is an awesome tool to provide easy way to encode and decode files. +Helmwave allows you to automatically decode them during `helmwave build`. + +```yaml title="values.yml" +{% include "./values.yml" %} +``` + + +```yaml title="helmwave.yml" +{% include "./helmwave.yml" %} +``` diff --git a/docs/examples/values-sops/helmwave.yml b/docs/examples/values-sops/helmwave.yml new file mode 100644 index 00000000..12a282fe --- /dev/null +++ b/docs/examples/values-sops/helmwave.yml @@ -0,0 +1,18 @@ +project: "Example: values render flag" +version: "⟨⟨ ver ⟩⟩" + +repositories: + - name: bitnami + url: https://charts.bitnami.com/bitnami + +.options: &options + namespace: my-namespace + wait: true + +releases: + - name: nginx + <<: *options + chart: bitnami/nginx + values: + - src: values.yml + renderer: sops diff --git a/docs/examples/values-sops/values.yml b/docs/examples/values-sops/values.yml new file mode 100644 index 00000000..bdeb827a --- /dev/null +++ b/docs/examples/values-sops/values.yml @@ -0,0 +1,30 @@ +#ENC[AES256_GCM,data:GgOHfI2ALHVRMutwzbbj1xB/AO0oz9IQExewzxqn+A==,iv:2SMqOaISe7ErBHgrG0fUAEG2PZ0VxPk217eWxnjug5k=,tag:NfTKnKsz3Tq4VILEDvvFkA==,type:comment] +#ENC[AES256_GCM,data:Cw==,iv:ROEhMOyTjnApauHRyZZbqWCCIKaWY+5DVM8fWlZtslg=,tag:HEEQpFaEGUKM2VusUC+0mw==,type:comment] +metrics: + service: + annotations: + prometheus.io/scrape: ENC[AES256_GCM,data:2L7+8w==,iv:/deSPkA8lPHHJVUGoIDd0x368mPsGMAFAPenAeXz68Y=,tag:efKHi/5X/wJPVSqI6oHldA==,type:str] + prometheus.io/port: ENC[AES256_GCM,data:bErIwr71Yuv1nT+pha8e97Tspo015YWTMfSrSd/aRqyqBA==,iv:lodkK84z6MHtzrQBdMIe+KtaDdZjlagu3F0qpfOU7rs=,tag:jMslNtzbJe6/cYQnKf9OlQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-09-11T16:44:33Z" + mac: ENC[AES256_GCM,data:5+vWLYhYCmaKZvuQpRpDKZNS0z9EL1VpppuIssKqG4XFmoLgeigjc4noa2LLuM3iY9rHy+ICNcjdzWIjHhA1Zw6T7B6TpkTR3xyyzqQZ6fx8yw1QfZVE/MRac6Zg5/UIGoTocJzwfHUE84wzn5Na/9FclDYwGYR2O6dvMOrm5uU=,iv:owmjYXD7wib62U+qZPgG1U3SbGU48NLRx4j7yK+UoTA=,tag:tMjD5M4kJBguvQ3DoFeyvg==,type:str] + pgp: + - created_at: "2023-09-11T16:44:32Z" + enc: | + -----BEGIN PGP MESSAGE----- + + hF4DMeHY6nye/U4SAQdAEzD3I/ufCNIhuaAPZ1/8RtzZEVLlEaPlGk6FYviyinAw + +fynfTRvLNdFFXrRUdQibDEc3kJ8v5n/vpto3OYwXSDV3VXflXYVxKHIcXwkAgIy + 1GgBCQIQhKZtYYky8MLckqiWoJhvH7p/K7U9DGZkSGrv6f7YJJ2OtpkkDvpZHHAQ + ghdGY8M9T0zU/ZN+9xRgsp7n/ukk/w6ChwZdg7ebCNAMGAdWOu2F+rERckMTEwBI + rRMNUMbeTNMjwA== + =eETi + -----END PGP MESSAGE----- + fp: DCB1B50CC55217886566ED93FFA4CA11112C922E + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/docs/tpl.md b/docs/tpl.md index 60421bb9..1ef86015 100644 --- a/docs/tpl.md +++ b/docs/tpl.md @@ -19,6 +19,10 @@ We recommend using [`gomplate`](#gomplate). You should use helmwave to render values of your chart. +!!! note "Overriding templater" + + You can override used templater using [`renderer` option in values](examples/values-disable-render/README.md) + ## [Sprig](http://masterminds.github.io/sprig/) diff --git a/docs/yaml.md b/docs/yaml.md index b07b4670..fb436454 100644 --- a/docs/yaml.md +++ b/docs/yaml.md @@ -44,7 +44,7 @@ Reserved for the future. Helmwave will check the current version and project version. -In the future, it is planned to check major compatibility. +In the future, it is planned to check major compatibility. ## registries[] @@ -59,7 +59,6 @@ Describe which [OCI registries](https://helm.sh/docs/topics/registries/) need to | password | 🙅 | string | "" | | insecure | 🙅 | bool | false | - === ":material-duck: private oci" ```yaml @@ -67,7 +66,7 @@ Describe which [OCI registries](https://helm.sh/docs/topics/registries/) need to ``` === ":material-duck: public oci" - + ```yaml {% include "./examples/oci-public/helmwave.yml" %} ``` @@ -82,14 +81,12 @@ Username for the registry. !!! note "only if registry is private" - ### password Password for the registry. !!! note "only if registry is private" - ## repositories[] :simple-helm: helm [repositories](https://helm.sh/docs/helm/helm_repo) also know as `helm repo add` @@ -125,7 +122,6 @@ Username for the repository. Password for the repository. - ### force Update existing repository exists if settings differ. @@ -135,8 +131,8 @@ Update existing repository exists if settings differ. > Aka global hooks. Introduced in [:material-tag: v0.28.0](https://github.com/helmwave/helmwave/releases/tag/v0.28.0) We don't call lifecycle the hooks on purpose -so as not to confuse you with the original functionality of [:simple-helm: helm hooks](https://helm.sh/docs/topics/charts_hooks/). - +so as not to confuse you with the original functionality +of [:simple-helm: helm hooks](https://helm.sh/docs/topics/charts_hooks/). | field | required | type | default | |:-------------:|:--------:|:------:|:-------:| @@ -149,7 +145,6 @@ so as not to confuse you with the original functionality of [:simple-helm: helm | pre_rollback | 🙅 | []Hook | [] | | post_rollback | 🙅 | []Hook | [] | - ```mermaid flowchart LR pre_build --> post_build @@ -165,8 +160,8 @@ flowchart LR To each lifecycle command several environment variables are passed: - `${HELMWAVE_LIFECYCLE_TYPE}` - contains lifecycle stage/type (`pre_build`/`post_build`/etc.) -- `${HELMWAVE_LIFECYCLE_RELEASE_UNIQNAME}` - *(only for per-release lifecycle)* contains release uniqname (`release@namespace`) - +- `${HELMWAVE_LIFECYCLE_RELEASE_UNIQNAME}` - *(only for per-release lifecycle)* contains release + uniqname (`release@namespace`) ** Hook ** @@ -202,6 +197,7 @@ To each lifecycle command several environment variables are passed: show: true allow_failure: false ``` + ### show > Introduced in [:material-tag: v0.28.0](https://github.com/helmwave/helmwave/releases/tag/v0.29.0) @@ -214,6 +210,117 @@ Show output of the command. Allow failure of the command. +## monitors[] + +> Introduced in [:material-tag: v0.32.0](https://github.com/helmwave/helmwave/releases/tag/v0.32.0) + +Monitors run after all dependant releases succeeded. They are triggered every `interval` and end when: + +- Either `success_threshold` is met - monitor succeeds +- Either `failure_threshold` is met - monitor fails +- Or `total_timeout` is triggered - monitor fails + +| field | required | type | default | +|:-----------------:|:--------:|:--------:|:-------:| +| **name** | ✅ | string | "" | +| **type** | ✅ | string | "" | +| total_timeout | 🙅 | interval | 5m | +| iteration_timeout | 🙅 | interval | 10s | +| interval | 🙅 | interval | 1m | +| success_threshold | 🙅 | int | 3 | +| failure_threshold | 🙅 | int | 3 | +| prometheus | 🙅 | object | {} | +| http | 🙅 | object | {} | + +[:material-duck: example](examples/monitors/README.md) + +### **name** + +Monitor name, must be unique. + +### **type** + +Type of monitor to run. Must be one of: + +- `prometheus` +- `http` + +### total_timeout + +Total timeout for whole monitor run. If monitor haven't finished within `total_timeout`, it is considered as failed. + +### iteration_timout + +Timeout for each monitor iteration. If monitor iteration haven't finished within `iteration_timeout`, iteration is +considered as failed. + +### interval + +Interval between iterations. Must be lower than `iteration_timeout`. + +### success_threshold + +Count of sequential succeeded iterations that make monitor succeed. + +### failure_threshold + +Count of sequential failed iterations that make monitor fail. + +### prometheus + +| field | required | type | default | +|:--------:|:--------:|:------:|:-------:| +| **url** | ✅ | string | "" | +| **expr** | ✅ | string | "" | +| insecure | 🙅 | bool | false | + +#### **url** + +Prometheus base URL + +#### **expr** + +Prometheus expression to query on each iteration. Iteration is considered successful if expression returns 1 or more +rows. + +#### insecure + +Whether to skip SSL certificate validation + +### http + +| field | required | type | default | +|:------------------:|:--------:|:------:|:-------:| +| **url** | ✅ | string | "" | +| **expected_codes** | ✅ | []int | [] | +| method | 🙅 | string | "HEAD" | +| body | 🙅 | string | "" | +| headers | 🙅 | object | {} | +| insecure | 🙅 | bool | false | + +#### **url** + +URL to query + +#### **expected_codes** + +List of expected HTTP response codes that are considered to be successful + +#### method + +HTTP method to query + +#### body + +HTTP body to send + +#### headers + +Map of HTTP headers to set in request + +#### insecure + +Whether to skip SSL certificate validation ## releases[] @@ -231,6 +338,7 @@ Almost all options that are here are native :simple-helm: helm options. | store | 🙅 | object | {} | ✅ | | | lifecycle | 🙅 | object | {} | ✅ | | | depends_on | 🙅 | array | [] | ✅ | | +| monitors | 🙅 | array | [] | ✅ | | | allow_failure | 🙅 | bool | false | | | | pending_release_strategy | 🙅 | string | "" | | | | wait | 🙅 | bool | false | | :simple-helm: | @@ -270,7 +378,6 @@ Release name. I hope you know what it is. > Introduced in [:material-tag: v0.5.0](https://github.com/helmwave/helmwave/releases/tag/v0.5.0) - | field | required | type | default | |:----------------------:|:--------:|:------:|:-------:| | **name** | ✅ | string | "" | @@ -291,7 +398,7 @@ Release name. I hope you know what it is. `chart` can be an object or a string. If it's a string, it will be treated as a `name`. === "short syntax" - + > Introduced in [:material-tag: v0.20.0](https://github.com/helmwave/helmwave/releases/tag/v0.20.0) @@ -312,8 +419,8 @@ Release name. I hope you know what it is. name: my-chart ``` - -!!! tip "If chart is remote it will be downloaded into `.helmwave/charts` and downloaded archive will be used during deploy." +!!! tip "If chart is remote it will be downloaded into `.helmwave/charts` and downloaded archive will be used during +deploy." #### name @@ -371,14 +478,12 @@ Disable Helm dependency update. Disable Helm repository refresh. - ### create_namespace > Introduced in [:material-tag: v0.12.0](https://github.com/helmwave/helmwave/releases/tag/v0.12.0) If set to `true` Helmwave will create the release namespace if not present. - ```shell helm upgrade --install --create-namespace my-release my-chart --namespace my-namespace ``` @@ -391,8 +496,6 @@ releases: create_namespace: true ``` - - ### values[] > Introduced in [:material-tag: v0.5.0](https://github.com/helmwave/helmwave/releases/tag/v0.5.0) @@ -406,7 +509,7 @@ releases: | delimiter_left | 🙅 | string | "{{" | | delimiter_right | 🙅 | string | "}}" | | strict | 🙅 | bool | false | -| render | 🙅 | bool | true | +| renderer | 🙅 | string | "" | === "short syntax" @@ -424,7 +527,7 @@ releases: delimiter_left: "{{" delimiter_right: "}}" strict: false - render: true + renderer: "" ``` #### **src** @@ -440,31 +543,35 @@ You can change the delimiter that helmwave uses to render values. [:material-duck: example](../examples/values-delimiter-flags/) -#### render +#### renderer -> Introduced in [:material-tag: v0.20.0](https://github.com/helmwave/helmwave/releases/tag/v0.20.0) - +> Introduced in [:material-tag: v0.32.0](https://github.com/helmwave/helmwave/releases/tag/v0.32.0) -Allows disabling templating values at all. +Allows overriding how values file is rendered. These renderers are supported: -[:material-duck: example](examples/values-render-flag/README.md) +- `sprig` - template file with `sprig` (overrides global `--templater` argument) +- `gomplate` - template file with `gomplate` (overrides global `--templater` argument) +- `copy` - do not template file at all (overrides global `--templater` argument) +- `sops` - use [sops](https://github.com/getsops/sops) to decode encrypted file + +- [:material-duck: example](examples/values-sops/README.md) +- [:material-duck: example](examples/values-disable-render/README.md) #### strict > Introduced in [:material-tag: v0.20.0](https://github.com/helmwave/helmwave/releases/tag/v0.20.0) - + Allows to fail if values file doesn't exist. [:material-duck: example](examples/values-strict-flag/README.md) ### tags[] + > Aka labels. Introduced in [:material-tag: v0.4.0](https://github.com/helmwave/helmwave/releases/tag/v0.4.0) Tags allow you to choose releases for build. - - [:material-duck: example](examples/tags/README.md) ### offline_kube_version @@ -472,13 +579,11 @@ Tags allow you to choose releases for build. > Introduced in [:material-tag: v0.27.3](https://github.com/helmwave/helmwave/releases/tag/v0.27.3) If `offline_kube_version` set helmwave will use this version to build plan. -Without this option, helmwave will ask :simple-kubernetes: kubernetes for a version. +Without this option, helmwave will ask :simple-kubernetes: kubernetes for a version. It is very useful if you want to build a plan without access to a cluster. Combine `offline_kube_version` and `--diff-mode=local` or `--diff-mode=none` to build a plan without kubernetes. - - [:material-duck: example](examples/private-env/README.md) ### store @@ -511,7 +616,8 @@ It allows passing your custom fields from `helmwave.yml` to values. `depends_on` is a list of releases that allow you to deploy a sequence. -!!! example "Example for [3-tier](https://searchsoftwarequality.techtarget.com/definition/3-tier-application) application" +!!! example "Example for [3-tier](https://searchsoftwarequality.techtarget.com/definition/3-tier-application) +application" ```mermaid graph LR @@ -519,7 +625,6 @@ It allows passing your custom fields from `helmwave.yml` to values. ``` *If you don't see a graph, please reload the page.* - Your `helmwave.yml` should look like this: ```yaml @@ -541,16 +646,16 @@ releases: #### **name** -Name of release (dependency) that has to be installed/upgraded before this release (dependant). If dependency is not in a plan, it will be added to a plan. +Name of release (dependency) that has to be installed/upgraded before this release (dependant). If dependency is not in +a plan, it will be added to a plan. Name support 2 kind of definitions: uniq name `@` or just ``. If namespace is not specified, it will be taken from namespace filed of release. - The same configuration can be written in 2 ways: === "``" - + > Introduced in [:material-tag: v0.21.1](https://github.com/helmwave/helmwave/releases/tag/v0.21.1) ```yaml @@ -577,10 +682,8 @@ The same configuration can be written in 2 ways: namespace: test ``` - Both of them will be normalized to `redis@test` in a planfile. - #### tag > Introduced in [:material-tag: v0.24.0](https://github.com/helmwave/helmwave/releases/tag/v0.24.0) @@ -597,8 +700,35 @@ The planfile (`.helmwave/planfile` by default) will have a normalized list of re If dependency is not found in all available releases, helmwave will not fail due to missing dependency. +It allows setting explicit dependencies between releases. Dependant release will start upgrading only after all its +dependencies finished upgrading -It allows setting explicit dependencies between releases. Dependant release will start upgrading only after all its dependencies finished upgrading +### monitors[] + +> Introduced in [:material-tag: v0.32.0](https://github.com/helmwave/helmwave/releases/tag/v0.32.0) + +Which monitors should be triggered after the releases is successfully deployed. + +| field | required | type | default | +|:--------:|:--------:|:------:|:-------:| +| **name** | ✅ | string | "" | +| action | 🙅 | string | "" | + +[:material-duck: example](examples/monitors/README.md) + +#### **name** + +Name of the monitor to trigger + +#### action + +Action to perform if the monitor is failed. Should be one of: + +- `""` - do nothing +- `rollback` - rollback release to the previous version +- `uninstall` - uninstall release + +If multiple monitors of the release failed and they have different actions, chosen action is a random one from the list. ### allow_failure @@ -680,7 +810,8 @@ Allow deletion of new resources created in this upgrade when upgrade fails. ### devel -> Removed in [:material-tag: v0.29.3](https://github.com/helmwave/helmwave/releases/tag/v0.29.3) as it wasn't functioning properly. +> Removed in [:material-tag: v0.29.3](https://github.com/helmwave/helmwave/releases/tag/v0.29.3) as it wasn't +> functioning properly. If you need to use development version, set `version: ">0.0.0-0"`. @@ -724,7 +855,6 @@ Allows deleting and then creating resources (pods) when needed instead of updati !!! tip "We don't recommend using this option." - ### reset_values > Introduced in [:material-tag: v0.5.0](https://github.com/helmwave/helmwave/releases/tag/v0.5.0) @@ -773,4 +903,5 @@ You can use custom commands to change rendered manifests. > Introduced in [:material-tag: v0.31.0](https://github.com/helmwave/helmwave/releases/tag/v0.31.0) -If enabled, rendered [chart notes](https://helm.sh/docs/chart_template_guide/notes_files/) will be shown after successful release. \ No newline at end of file +If enabled, rendered [chart notes](https://helm.sh/docs/chart_template_guide/notes_files/) will be shown after +successful release. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index ae0a247e..e0ff6aed 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -42,6 +42,8 @@ nav: - examples/umbrella-evil/README.md - examples/private-env/README.md - examples/lifecycle/README.md + - examples/monitors/README.md + - examples/helmfile-migration/README.md - OCI: - examples/oci-private/README.md - examples/oci-public/README.md @@ -49,8 +51,9 @@ nav: - examples/private-github-repo/README.md - examples/private-gitlab-repo/README.md - Values flags: + - examples/values-disable-render/README.md + - SOPS: examples/values-sops/README.md - examples/values-delimiter-flags/README.md - - examples/values-render-flag/README.md - examples/values-strict-flag/README.md - Data sources: - examples/vault/README.md @@ -111,7 +114,7 @@ theme: - search.highlight extra: - ver: 0.31.0 + ver: 0.32.1 version: provider: mike default: latest