/helmwave

🌊 GitOps for Helm Charts

Primary LanguageGoMIT LicenseMIT

HelmWave

🌊 HelmWave is helm-native tool for deploy your Helm Charts via GitOps.

Inspired by the helmfile

Comparison

🚀 Features 🌊 HelmWave helmfile
Docker image 23 mb 190 mb
Without helm binary
All options helm partially
Helm 3
Helm 2
Parallel helm install/upgrade
Repository Skipping
Install only needs repositories
Tags You can use labels
Store You can use labels
Planfile
Sprig
Call helm via Golang Module Shell Executor
Speed of deploy [*] 10 sec 2 min

* - WIP

📥 Installation

  • Download one of releases
    • $ wget -c https://github.com/zhilyaev/helmwave/releases/download/0.4.0/helmwave-0.4.0-linux-amd64.tar.gz -O - | tar -xz && cp -f helmwave /usr/local/bin/
  • Run as a container
    • $ docker run diamon/helmwave:0.4.0
    • $ docker run --entrypoint=ash -it --rm --name helmwave diamon/helmwave:0.4.0

Build

golang:1.15

$ export GO111MODULE=on
$ git clone git@github.com:zhilyaev/helmwave.git $GOPATH/src/github.com/zhilyaev/helmwave
$ cd $GOPATH/src/github.com/zhilyaev/helmwave
$ go build github.com/zhilyaev/helmwave/cmd/helmwave
$ mv helmwave /usr/local/bin 

🔰 Getting Started

Let's start with a simple helmwave and gradually improve it to fit your use-case!

Suppose the helmwave.yml.tpl representing the desired state of your helm releases looks like:

project: my-project
version: 0.4.0


repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami


.options: &options
  install: true
  namespace: my-namespace


releases:
  - name: redis-a
    chart: bitnami/redis
    options:
      <<: *options

  - name: redis-b
    chart: bitnami/redis
    options:
      <<: *options
$ helmwave deploy

Congratulations!

$ helm list -n my-namespace
NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
redis-a                 my-namespace    1               2020-10-31 17:05:35.829766 +0300 MSK    deployed        redis-11.2.3            6.0.9      
redis-b                 my-namespace    1               2020-10-31 17:05:39.437556 +0300 MSK    deployed        redis-11.2.3            6.0.9  

$ k get po -n my-namespace                                                                                                                         
NAME               READY   STATUS    RESTARTS   AGE
redis-a-master-0   1/1     Running   0          64s
redis-a-slave-0    1/1     Running   0          31s
redis-a-slave-1    1/1     Running   0          62s
redis-b-master-0   1/1     Running   0          59s
redis-b-slave-0    1/1     Running   0          32s
redis-b-slave-1    1/1     Running   0          51s

🔰 Tags

Suppose the helmwave.yml.tpl looks like:

project: my-project
version: 0.4.0


repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami


.options: &options
  install: true
  namespace: my-namespace


releases:
  - name: redis-a
    chart: bitnami/redis
    tags:
      - a
      - redis
    options:
      <<: *options

  - name: redis-b
    chart: bitnami/redis
    tags:
      - b
      - redis
    options:
      <<: *options

  - name: memcached-a
    chart: bitnami/memcached
    tags:
      - a
      - memcached
    options:
      <<: *options

  - name: memcached-b
    chart: bitnami/memcached
    tags:
      - b
      - memcached
    options:
      <<: *options

This command will deploy only redis-a & memcached-a

$ helmwave -t a deploy

This command will deploy only redis-a & redis-b

$ helmwave -t redis deploy

This command will deploy only redis-b

$ helmwave -t redis,b deploy

🔰 Store

It allows pass you custom values to render release.

helmwave.yml:

project: my-project
version: 0.4.0

releases:
  - name: backend
    chart: my/backend
    options:
      install: true
    store:
      secret:
        type: vault
        path: secret/my/frontend
    values:
      - my-custom-values.yml

  - name: frontend
    chart: my/frontend
    options:
      install: true
    store:
      secret:
        type: vault
        path: secret/my/frontend
    values:
      - my-custom-values.yml

my-custom-values.yml:

secretForApp:
  kind: {{ .Release.Store.secret.type }}
  path: {{ .Release.Store.secret.path | quote }}

🛠 CLI Reference

NAME:
   🌊 HelmWave - composer for helm

USAGE:
   helmwave [global options] command [command options] [arguments...]

VERSION:
   0.4.0

DESCRIPTION:
   🏖 This tool helps you compose your helm releases!

AUTHOR:
   💎 Dmitriy Zhilyaev <helmwave+zhilyaev.dmitriy@gmail.com>

COMMANDS:
   render, r                        📄 Render tpl -> yml
   planfile, p, plan                📜 Generate planfile
   repos, rep, repo                 🗄 Sync repositories
   deploy, d, apply, sync, release  🛥 Deploy your helmwave!
   help, h                          🚑 Help me!

GLOBAL OPTIONS:
   --tpl value                 Main tpl file (default: "helmwave.yml.tpl") [$HELMWAVE_TPL_FILE]
   --file value, -f value      Main yml file (default: "helmwave.yml") [$HELMWAVE_FILE, $HELMWAVE_YAML_FILE, $HELMWAVE_YML_FILE]
   --planfile value, -p value  Path to planfile (default: "helmwave.plan") [$HELMWAVE_PLANFILE]
   --tags value, -t value      It allows you choose releases for sync. Example: -t tag1 -t tag3,tag4 [$HELMWAVE_TAGS]
   --parallel helm install     it allows you call helm install in parallel mode  (default: true) [$HELMWAVE_PARALLEL]
   --log-format value          You can set: [ text | json | pad ] (default: "text") [$HELMWAVE_LOG_FORMAT]
   --log-level value           You can set: [ debug | info | warn | panic | fatal | trace ] (default: "info") [$HELMWAVE_LOG_LEVEL, $HELMWAVE_LOG_LVL]
   --version, -v               print the version (default: false)

Render, r

Transform helmwave.yml.tpl to helmwave.yml

Suppose the helmwave.yml.tpl looks like:

project: {{ env "CI_PROJECT_NAME" }}
version: 0.4.0


repositories:
- name: your-private-git-repo-hosted-charts
  url: https://{{ env "GITHUB_TOKEN"}}@raw.githubusercontent.com/foo/bar/master/


.options: &options
  install: true
  namespace: {{ env "NS" }}


releases:
  - name: redis-a
    chart: bitnami/redis
    options:
      <<: *options

This command will render helmwave.yml.tpl to helmwave.yml

$ export NS=stage
$ export CI_PROJECT_NAME=my-project
$ export GITHUB_TOKEN=my-secret-token
$ helmwave render

Once applied, your helmwave.yml will look like:

project: my-project
version: 0.4.0


repositories:
- name: your-private-git-repo-hosted-charts
  url: https://my-secret-token@raw.githubusercontent.com/foo/bar/master/


.options: &options
  install: true
  namespace: stage


releases:
  - name: redis-a
    chart: bitnami/redis
    options:
      <<: *options

Planfile, plan

This command will generate helmwave.plan.

helmwave.plan is an object save to yaml.

helmwave.plan looks like
project: my-project
version: 0.4.0
repositories:
- name: bitnami
  url: https://charts.bitnami.com/bitnami
  username: ""
  password: ""
  certfile: ""
  keyfile: ""
  cafile: ""
  insecureskiptlsverify: false
  force: false
releases:
- name: redis-a
  chart: bitnami/redis
  tags: []
  values: []
  options:
    chartpathoptions:
      cafile: ""
      certfile: ""
      keyfile: ""
      insecureskiptlsverify: false
      keyring: ""
      password: ""
      repourl: ""
      username: ""
      verify: false
      version: ""
    install: true
    devel: false
    namespace: my-namespace
    skipcrds: false
    timeout: 0s
    wait: false
    disablehooks: false
    dryrun: false
    force: false
    resetvalues: false
    reusevalues: false
    recreate: false
    maxhistory: 0
    atomic: false
    cleanuponfail: false
    subnotes: false
    description: ""
    postrenderer: null
    disableopenapivalidation: false
- name: redis-b
  chart: bitnami/redis
  tags: []
  values: []
  options:
    chartpathoptions:
      cafile: ""
      certfile: ""
      keyfile: ""
      insecureskiptlsverify: false
      keyring: ""
      password: ""
      repourl: ""
      username: ""
      verify: false
      version: ""
    install: true
    devel: false
    namespace: my-namespace
    skipcrds: false
    timeout: 0s
    wait: false
    disablehooks: false
    dryrun: false
    force: false
    resetvalues: false
    reusevalues: false
    recreate: false
    maxhistory: 0
    atomic: false
    cleanuponfail: false
    subnotes: false
    description: ""
    postrenderer: null
    disableopenapivalidation: false

📄 Templating

HelmWave uses Go templates for templating.

Helmwave supports all built-in functions, Sprig library, and several advanced functions:

  • toYaml marshals a map into a string
  • fromYaml reads a golang string and generates a map
  • readFile get file as string
  • get (Sprig's original get is available as sprigGet)
  • setValueAtPath PATH NEW_VALUE traverses a golang map, replaces the value at the PATH with NEW_VALUE
  • requiredEnv The requiredEnv function allows you to declare a particular environment variable as required for template rendering. If the environment variable is unset or empty, the template rendering will fail with an error message.

readFile

my-releases.yml
releases:
- name: redis
  repo: bitnami
- name: memcached
  repo: bitnami
helmwave.yml.tpl
project: my
version: 0.4.0


repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami


.global: &global
  install: true


releases:
{{- with readFile "my-releases.yml" | fromYaml | get "releases" }}
  {{- range $v := . }}
  - name: {{ $v | get "name" }}
    chart: {{ $v | get "repo" }}/{{ $v | get "name" }}
    options:
      <<: *global
  {{- end }}
{{- end }}
$ helmwave render
helmwave.yml
project: my
version: 0.4.0

repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

.global: &global
  install: true

releases:
  - name: redis
    chart: bitnami/redis
    options:
      <<: *global
  - name: memcached
    chart: bitnami/memcached
    options:
      <<: *global

🛸 Coming soon...

  • Dependencies helm release
  • OCI, testing...
  • Force Update repositories
  • Formatting output
  • Applying from planfile
  • Dependencies helmwave
  • More templating functions

🧬 Full Configuration

🗄 Repository

- name: bitnami
  url: https://charts.bitnami.com/bitnami
  username: ""
  password: ""
  certfile: ""
  keyfile: ""
  cafile: ""
  insecureskiptlsverify: false
  force: false

🛥 Release

- name: redis
  chart: bitnami/redis
  tags: []
  values: []
  store: 
  options:
    install: true
    devel: false
    namespace: b
    skipcrds: false
    timeout: 0s
    wait: false
    disablehooks: false
    dryrun: false
    force: false
    resetvalues: false
    reusevalues: false
    recreate: false
    maxhistory: 0
    atomic: false
    cleanuponfail: false
    subnotes: false
    description: ""
    postrenderer: null
    disableopenapivalidation: false
    chartpathoptions:
      cafile: ""
      certfile: ""
      keyfile: ""
      insecureskiptlsverify: false
      keyring: ""
      password: ""
      repourl: ""
      username: ""
      verify: false
      version: ""