Commit Graph

468 Commits

Author SHA1 Message Date
KUOKA Yusuke 78b03e0d92
fix: --state-values-set panic: value of type interface {} is not assignable to type string (#680)
Probably since #647 helmfile has been unable to merge nested maps in environment values if they were loaded from files. This fixes it.

The relevant test is also enhanced so that no further regression like this happens.

Fixes #677
2019-06-12 13:35:04 +09:00
sgandon 11eda66eaa feat: make release version templatized (#671)
Allows the release version to be a Go template.
Resolves #669
2019-06-11 21:52:54 +09:00
KUOKA Yusuke 65d404b276
feat: `helmfile -f <go-getter url>` (#670)
Extends the remote-helmfile feature to also work when loading the first state file.
This should be useful for people who wants to give helmfile a try without ever opening `$EDITOR`.
2019-06-11 14:28:50 +09:00
Eric Bailey 72425aebfc fix: persist original file path when using bases (#672)
* fix: persist original file path when using bases

Prior to this change, the resulting lock file was called `<bases[0]>.lock`,
instead of `<filename>.lock`.

This change ensures the final, merged state has the correct `.FilePath`.

* test: Assert proper FilePath in layered HelmState
2019-06-11 14:01:27 +09:00
Kevin J. Qiu 34fbfb4fd0 fix: convert path to absolute path when doing `helm secret dec` (#664)
Fixes #663
2019-06-10 21:43:20 +09:00
sgandon 56c27c2bd9 fix: fixes a regexp issue for release summary (#666)
There was an issue a the regexp reding the version from helm output.

Fixes #665
2019-06-10 09:18:41 +09:00
Vincent Behar 34c793d87e fix: use the same logic as helm-secrets when decoding secrets (#655)
helm-secrets uses the `HELM_SECRETS_DEC_SUFFIX` env var to define the name of the output file
we should have the same logic in helmfile, to come up with the same filename

It only affects people using the `HELM_SECRETS_DEC_SUFFIX` env var

Use-case: if you want to run multiple `helmfile` commands in parallel, without conflicts. in this case, you need to decrypt secrets with different suffixes.
2019-06-06 21:27:04 +09:00
刘相轩 b9862bdae6 Sync repos before update deps (#660) 2019-06-06 15:23:27 +09:00
刘相轩 e3e7905f07 Sort requirements alphabetically by name. (#659) 2019-06-06 12:30:22 +09:00
KUOKA Yusuke 2e57beb448
feat: bundle helm-s3 and helm-git into container images (#651)
Resolves #435 (Git as chart repository)
Resolves #220 (S3 as chart repository)
Resolves #436 (About bundling helm plugins)

A lot of thanks to @aslafy-z for authoring the awesome helm-git plugin and contributing it to the community!
2019-06-04 23:53:11 +09:00
KUOKA Yusuke 3986f6497e
Update writing-helmfile.md 2019-06-04 23:41:26 +09:00
KUOKA Yusuke 820abbc06d
feat: remote state files (#648)
This change enhances helmfile to accept terraform-module-like URLs in nested state files a.k.a sub-helmfiles.

```yaml
helmfiles:
- # Terraform-module-like URL for importing a remote directory and use a file in it as a nested-state file
  # The nested-state file is locally checked-out along with the remote directory containing it.
  # Therefore all the local paths in the file are resolved relative to the file
  path: git::https://github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0
```

The URL isn't equivalent to terraform module sources. The difference is that we use `@` to distinguish between (1) the path to the repository and directory containing the state file and (2) the path to the state file being loaded. This distinction provides us enough fleibiity to instruct helmfile to check-out necessary and sufficient directory to make the state file works.

Under the hood, it uses [hashicorp/go-getter](https://github.com/hashicorp/go-getter), that is used for [terraform module sources](https://www.terraform.io/docs/modules/sources.html) as well.

Only the git provider without authentication like git-credentials helper is tested. But theoretically any go-getter providers should work. Please feel free to test the provider of your choice and contribute documentation or instruction to use it :)

Resolves #347
2019-06-04 22:59:54 +09:00
KUOKA Yusuke 3710f6233e
feat: state values (#647)
This adds `values` to state files as proposed in #640.

```yaml
values:
- key1: val1
- defaults.yaml

environments:
  default:
  - values:
    - environments/default.yaml
  production:
  - values:
    - environments/production.yaml

```

`{{ .Valuese.key1 }}` evaluates to `val1` if and only if it is not overrode via the production or the default env, or command-line args.

Resolves #640
2019-06-04 16:34:02 +09:00
KUOKA Yusuke 2d2b3e486f
fix: sprig dict funcs are failing on dicts nested under arrays (#646)
Fixes #643
2019-06-04 13:47:05 +09:00
KUOKA Yusuke 65ee6a2124
fix: "cannot unmarshal !!str `<no value>` into bool" errors in state templates (#645)
Seems like we are affected by https://github.com/golang/go/issues/24963. That is, even though we internally use the template option `missingkey=zero`, in some cases it still prints `<no value>` instead of zero values, which has been confusing the state yaml parsing.

This fixes the issue by naively replacing all the remaining occurrences of `<no value>` in the rendered text, while printing debug logs to ease debugging in the future when there is unexpected side-effects introduced by this native method.

Fixes #553
2019-06-04 13:23:38 +09:00
KUOKA Yusuke 1d3f5f8a33
feat: override state(former "enviroment") values via command-line args (#644)
The addition of `--set k1=v1,k2=v2` and `--values file1 --values file2` was originally planned in #361.

But it turned out we already had `--values` for existing helmfile commands like `sync`. Duplicated flags doesn't work, obviously.

So this actually add `--state-values-set k1=v1,k2=v2` and `--set-values-file file1 --set-values-file file2`.

They are called "state" values according to the discussion we had at #640

Resolves #361
2019-06-04 11:03:01 +09:00
KUOKA Yusuke e2d6dc4afa
feat: helmfile as a go library (#639)
* feat: helmfile as a go library

This removes almost all the dependencies from the helmfile core logic to urfave/cli. `main.go` is now a thin wrapper around the core logic implemented in `pkg/app`.
2019-06-04 09:12:00 +09:00
KUOKA Yusuke f6057a1cca
chore: first step towards migration to cobra (#637)
I will start by making as much as possible code in `main.go` independent from urfave/cli, and this illustrates how we can do that by introducing a Config interface that delegates any config value fetch to urfave/cli. We will implement an cobra/pflag impl of the interface when helmfile finally migrates to cobra.
2019-06-01 14:00:26 +09:00
KUOKA Yusuke c68fc5bc50
chore: tidy up pkgs (#636)
for readability and towards potentially making helmfile usable as a go library
2019-06-01 13:36:05 +09:00
KUOKA Yusuke 68b95f14d4
change the nest level of envvals overrides for nested state files(sub-helmfiles) (#635)
We added envvals overrides in the state file via #622 two days ago:

```
helmfiles:
- name: sub.helmfile.yaml
  environment:
    values:
    - mykey: myvalue
```

This change removes the `environment` level in the above cofig, so that it looks like:

```
helmfiles:
- name: sub.helmfile.yaml
  values:
  - mykey: myvalue
``

This is an inevitable breaking change towards #361. But I wanted to break it earlier so that less folks are affected.`

Ref https://github.com/roboll/helmfile/issues/361#issuecomment-497530819
2019-06-01 12:39:31 +09:00
KUOKA Yusuke 9318d8a040
doc: recommend quoting potentially number-like string (#634)
Resolves #608
2019-06-01 11:29:33 +09:00
jonathan cowling msm 44686298f2 Document verify in releases (#632)
Just a one liner in the readme to make it clear there's a `verify` option in the `releases` section 😄
2019-05-31 22:50:45 +09:00
bitsofinfo 206372b7aa feat: upgrade sprig to 2.16.0
Resolves #630
2019-05-31 13:16:49 +09:00
KUOKA Yusuke e1c04971c1
Update README.md 2019-05-30 17:11:42 +09:00
KUOKA Yusuke b3f4586ed8
Fix panic related to env values from files and sprig dict funcs (#625)
* fix: 0.68.0: go panic w/ multiple bases/layers

Fixes #623

* fix: 0.64.1+: getOrNil/hasKey fails on Environment.Values with nested maps

Fixes #624
2019-05-30 15:41:00 +09:00
KUOKA Yusuke 591086dac9
Update README.md 2019-05-29 21:25:59 +09:00
KUOKA Yusuke 1226ea6d1a
feat: specify env values from the parent to the nested state (#622)
* feat: specify env values from the parent to the nested state

Adds the `helmfiles[].environment.values` that accepts a mix of file pathes and inline dictes:

```yaml
helmfiles:
- path: path/to/nested/helmfile.yaml
  environment:
    values:
    - key1: val1
    - values.yaml
```

The values files are loaded in the context of the parent state file. For example, in case the above state file is located at `/path/to/helmfile.yaml`,
`values.yaml` is located at `/path/to/values.yaml` instead of `/path/to/nested/values.yaml`.

Resolves #523

* fix: multiple "bases" declarations yields duplicate releases

Fixes #615

* fix regression in double-rendering with env value overrides

The latest commit broke any state files like the below to NOT pass env value overrides at all:

```
helmfiles:
- path: nested/state.yaml
  environment:
    values:
    - overrides.yaml
```

This fixes the issue.
2019-05-29 19:08:51 +09:00
KUOKA Yusuke 681c866ce1
feat: inline environment values (#621)
Resolves #359
2019-05-28 16:26:00 +09:00
KUOKA Yusuke dd70c857a5
Update README.md 2019-05-28 15:38:17 +09:00
KUOKA Yusuke a896f801ab
feat: optionally allow missing environment values/secrets files (#620)
```yaml
environments:
  default:
    missingFileHandler: Warn
    values:
    - path/to/values.yaml
    secrets:
    - path/to/secrets.yaml
```

`missingFileHandler` set to `Warn`, `Info`, or `Debug` results in helmfile NOT stop when `path/to/values.yaml` or `path/to/secrets.yaml` is missing.

Resolves #548

While implementing the above feature, I also found a bug that has been causing #559. This also fixes that.

To verify it is actually fixed, create an example helmfile.yaml that looks like the below, and run `helmfile diff`:

```
$ cat helmfile.yaml
environments:
  default:
    secrets:
      - env-secrets.yaml

releases:
  - name: myapp
    chart: nginx
    namespace: default
    secrets: [secrets.yaml]    # Notice this file does not exist
    values:
      - ingress:
          enabled: true

$ helmfile diff
could not deduce `environment:` block, configuring only .Environment.Name. error: failed to read helmfile.yaml.part.0: environment values file matching "env-secrets.yaml" does not exist
in ./helmfile.yaml: failed to read helmfile.yaml: environment values file matching "env-secrets.yaml" does not exist
```

Fixes #559
2019-05-28 15:33:45 +09:00
Raj Perera 4a5996d083 feat: ability to exit zero with no releases match selector (#618)
- Change exit code from 2 to 3 when helmfiles have no releases that match a selector
- Introduces new flag `--allow-no-matching-release` to exit 0 when no releases match a selector.

Resolves: #597
2019-05-27 09:53:24 +09:00
KUOKA Yusuke f6264bfa9d
fix: do not complain on missing values files for undesired release (#617)
Fixes #616
2019-05-24 21:40:34 +09:00
KUOKA Yusuke 3b3d3092dd
fix scopelint errors / possible races in hooks (#614)
Ref #612
Fixes #514
2019-05-22 18:50:38 +09:00
KUOKA Yusuke 1012256f16
feat: "base" helmfile state gotmpl is rendered with the envvals inherited from the parent (#613)
Resolves #611
2019-05-22 18:28:10 +09:00
KUOKA Yusuke 90390492a3
feat: expand glob pattern in environment values file path (#610)
This enhances helmfile's internal environment values files loader to expand glob patterns (#606)

Fixes the existing bug that helmfile was unable to load environment values file from absolute path (#549)

Resolves #606
Fixes #549
2019-05-21 16:49:57 +09:00
KUOKA Yusuke 4c9c42d3c5
fix: gotmpl layer was unable to reference env values from other layers when env!=default (#609)
Fixes #604
2019-05-21 14:37:03 +09:00
KUOKA Yusuke bd60548f10
feat: add --skip-deps for `helmfile lint` (#602)
Resolevs #581
2019-05-16 21:31:00 +09:00
KUOKA Yusuke 0534117b62
feat: postsync hooks (#601)
`postsync` events are triggered after each release is applied to the cluster in `helmfile sync` or `helmfile apply`.

This should be a best hook to notify only after each sync failed or succeeded. This can be used for running operations like patching K8s resources managed by helm, but that should be the last-resort. Maybe you should fork/update the chart, or submit a feature request to add `replicated/ship` integration to `helmfile` in that case :)

Resolves #599
2019-05-16 21:24:16 +09:00
KUOKA Yusuke 0104c91fce
feat: support for locking the same chart for two or more versions (#600)
Resolves #598
2019-05-16 21:19:30 +09:00
Yusuke KUOKA a769d1a82a fix integration test 2019-05-15 13:21:48 +09:00
KUOKA Yusuke b0179218b9
fix: helmfile panicing on missing lock file (#596)
Fixes #595
2019-05-15 13:16:22 +09:00
KUOKA Yusuke c9a43ad9cb
feat: Dependency locking (#593)
In order to maintain predictable deployments, as developer I want to generate and use "lock files" for all chart versions retrieved from a helmfile.

This change solves it by (1)enhancing `helmfile deps` to generate a lock file containing all the direct chart dependencies of each helmfile state file and
(2)making other helmfile sub-commands reads the lock file and merge the locked version numbers to the helmfile state file being processed.

The lock file is named after the helmfile state file being locked, so that you can have multiple set of the helmfile state file and the lock file pairs in a directory.

When `helmfile deps` are not explicitly run before commands like `sync`, all the helmfile behavior should remain as before.

Let's say you have `helmfile.1.yaml`:

```
repositories:
- name: stable
  url: https://kubernetes-charts.storage.googleapis.com

releases:
- name: envoy
  chart: stable/envoy
- name: envoy2
  chart: stable/envoy
```

`helmfile deps` generates `helmfile.1.lock` that looks like:

```
dependencies:
- name: envoy
  repository: https://kubernetes-charts.storage.googleapis.com
  version: 1.5.0
digest: sha256:e43b05c8528ea8ef1560f4980a519719ad2a634658abde0a98daefdb83a104e9
generated: 2019-05-14T16:45:37.78205+09:00
```

Under the hood, `helmfile deps` creates a temporary local helm chart with a dummy `Chart.yaml` and `requirements.yaml` deduced from the `helmfile.yaml` content, then runs `helm dependency update` to produce od update the corresponding `requirements.lock` file.

`helmfile` then renames it to match the name of the targeted helmfile state file and moves it,  so that it becomes adjacent to each `helmfile.yaml`.

Other `helmfile` commands like `sync`, `diiff`, `apply`, `lint` read chart version numbers from the lock file.

Resolves #483
2019-05-15 09:39:12 +09:00
KUOKA Yusuke 9eec72b318
Merge pull request #594 from sstarcher/fetch_devel
fix: Fetch devel

Fixes two issues encountered in https://sweetops.slack.com/archives/CE5NGCB9Q/p1557848927155400
2019-05-15 08:55:54 +09:00
Shane Starcher 081107bb82 error is coming back nil sometimes
this does not fix the root issue that is causing a nil error
2019-05-14 15:51:12 -07:00
Shane Starcher af69d1ba97 fetch should honor devel flag 2019-05-14 15:50:44 -07:00
KUOKA Yusuke 53ad91607a
fix: log useful error message when failed walking through the file tree (#592)
Fixes #590
2019-05-14 10:02:50 +09:00
KUOKA Yusuke 255d92064e
Merge pull request #587 from roboll/layering-enhancements
feat: helmfile.yaml layering enhancements

The current  [Layering](https://github.com/roboll/helmfile/blob/master/docs/writing-helmfile.md#layering) system didn't work as documented, as it relies on helmfile to template each "part" of your helmfile.yaml THEN merge them one by one.

The reality was that helmfile template all the parts of your helmfile.yaml at once, and then merge those YAML documents. In https://github.com/roboll/helmfile/issues/388#issuecomment-436186278, @sruon was making a GREAT point that we may need to change helmfile to render templates earlier - that is to evaluate a template per each helmfile.yaml part separated by `---`. Sorry I missed my expertise to follow your great idea last year @sruon  😭 

Anyways, this, in combination with the wrong documentation, has made so many people confused. To finally overcome this situation, here's a fairly large PR that introduces the 2 enhancements:

- `bases:` for easier layering without go template expressions, especially `{{ readFunc "path/to/file" }}`s. This is the first commit of this PR.
- `helmfile.yaml` is splited by the separator `---` at first. Each part is then rendered as a go template(double-render applies as before). Finally, All the results are merged in the order of occurence. I assume this as an enhanced version of @sruon's work. This is the second commit of this PR.

Resolves #388
Resolve #584
Resolves #585 (`HELMFILE_EXPERIMENTA=true -f helmfile.yaml helmfile` disables the whole-file templating, treating the helmfile.yaml as a regular YAML file as the file ext. denotes. Use `helmfile.yaml.gotmpl` or `helmfile.gotmpl` to enable)
Fixes #568 (Use `bases` or `readFile` rather than not importing implicitly with `helmfile.d`
2019-05-14 09:48:20 +09:00
Yusuke KUOKA aef366660b feat: split-render-merge helmfile.yaml parts
This splits your helmfile.yaml by the YAML document separator "---" before evaluating go template expressions as outlined in https://github.com/roboll/helmfile/issues/388#issuecomment-491710348
2019-05-13 21:49:59 +09:00
Yusuke KUOKA 1db205de48 feat: "bases" for easier layerina
This adds the new configuration key `baeses` to your helmfile.yaml files, so that you can layer them without the `readFile` template function, which was a bit unintuitive.

Please see https://github.com/roboll/helmfile/issues/388#issuecomment-491710348 for more context
2019-05-13 21:48:00 +09:00
KUOKA Yusuke 4f83e69bf6
Various U/X improvements for `helmfile apply` (#586)
* Various U/X improvements for `helmfile apply`

This improves the U/X of `helmfile apply`, by allowing you to selectively apply sub-helmfiles.
When you have two or more sub-helmfiles processed, typing `n` to cancel the first doesn't automatically stop the whole helmfile execution.
Instead, it proceeds by diffing the next sub-helmfile, and asks you to apply it, which should be what the user would expect.

To support this workflow, I have suppressed useless exec logs, correct exit status when diff exists in sub-helmfiles but not in the parent helmfile, and made the final error message emitted by helmfile better.

More concretely, this moves more output from `helm` to STDERR and the `debug` log-level.

The overall output from `helmfile` should be a bit more cleaner especially for `apply`, `sync`, `diff` and perhaps other `helmfile` sub-commands, too.

For example, when one of release failed, `helmfile`'s final error message now includes the error message from the failed `helm` execution, like seen in the last line:

```
List of updated releases :
RELEASE   CHART          VERSION
envoy     stable/envoy     1.5.0

List of releases in error :
RELEASE
envoy2
in ./helmfile.yaml: in .helmfiles[0]: in /Users/c-ykuoka/helmfile/helmfile.1.yaml: failed processing release envoy2: helm exited with status 1:
  Error: UPGRADE FAILED: "envoy2" has no deployed releases
```

This way you can better understand what caused helmfile to finally fail.

`helmfile` has been streaminig a lot of stdout and stderr contents from the `helm` commands regardless of the helmfile's log-level. It has been suppressed by default and moved to the `debug` log-level.
You will see that it helps you focus on what was the cause of a failure.

While working on the above, I found an another bug that made `--detailed-exitcode` useless in some case.
That is, `helmfile diff --detailed-exitcode`, when any diff existed only in sub-helmfiles, has been returning an exit code of `1`. It should return `2` when any release had diff and no release had an error, regardless of the target is a sub-helmfile or a parent helmfile. Why? Because that's what `--detailed-exitcode` meant for!

After this PR gets merged, `helmfile diff --detailed-exitcode`  propery return exit code `2` in such cases.

Fixes #543
Resolves #540
2019-05-12 16:26:11 +09:00