This pr fixes auto-wrapping of booleans and integers into quotes when using --state-values-set by:
- Adding: --state-values-set-string flag for intentional string set of boolean or integer
- Changing: --state-values-set flag not wrapping now
- Removing -
Resolves https://github.com/roboll/helmfile/issues/1347
Signed-off-by: Tunahan Sezen <sezentunahan@outlook.com>
* Allow secrets to be excluded from inheritance, small docs update
Signed-off-by: Alex Vorona <alex@vorona.com.ua>
* Fix typo in docs
Signed-off-by: Alex Vorona <alex@vorona.com.ua>
---------
Signed-off-by: Alex Vorona <alex@vorona.com.ua>
* Add "PostRendererArgs" option to be passed to helm
This allows using PowerShell scripts on Windows as Post Renderer.
Signed-off-by: Maarten Boekhold <maarten.boekhold@finastra.com>
* fix: support large output with --enable-live-ouput
This replaces Scanner with ReadString to handle large amount of data returned by helm ouptut when executing diff action
- Changing pkg/helmexec/runner_test.go TestLiveOutput test, adding test with large amount of data, reproducing the issue before applying this fix
- Changing pkg/helmexec/runner.go Scanner with Readstring
Resolves https://github.com/helmfile/helmfile/issues/893
Signed-off-by: Franck Labatut <franck.labatut@ubisoft.com>
* fix: prevent data race
Signed-off-by: Franck Labatut <franck.labatut@ubisoft.com>
---------
Signed-off-by: Franck Labatut <franck.labatut@ubisoft.com>
* Fix symlink behaviour
Make sure to evaluate symlinks when the path is not absolute and not
local. Otherwise just fall back to regular absolute paths.
Signed-off-by: Zoltán Reegn <zoltan.reegn@gmail.com>
Removes reference to non-existent Helm 3 images
Updates version
Corrects bind mounts for current Dockerfile
Signed-off-by: Daniel Key <daniel@pointyshinyburning.org>
* feat: make environment context available
This feature adds the "{{.Environment.KubeContext}}" variable.
Discussion #829
Signed-off-by: sewieland <sebastian.wieland@iav.de>
* chore: fix tests which compare logging outputs
This commit adds an addtional space wherever needed to the expected log outputs due to the added "KubeContext" in the environment struct.
Discussion #829
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
* docs: added documentation for `Environment.KubeContext`
Discussion #829
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
* test: make sure the `Environment.KubeContext` is mapped out correctly
Discussion #829
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
---------
Signed-off-by: sewieland <sebastian.wieland@iav.de>
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
Co-authored-by: sewieland <sebastian.wieland@iav.de>
... by using plain indented code blocks instead of indented fenced
code blocks.
While here also fix list rendering and add missing Go template escaping
in inline `values` map example.
Signed-off-by: Stoned Elipot <stoned.elipot@gmail.com>
* Disable double-rendering in V1
We are going to force users to separate environments and releases sections in every helmfile.yaml in the [Helmfile V1](https://github.com/helmfile/helmfile/blob/main/docs/proposals/towards-1.0.md). The goal of separation was to make the helmfile.yaml rendering result not dependent on the double-rendering and therefore the feature should be safe to be turned off in V1.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix helmfile template rendering error log for v1
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Add test for helmfile template debug log differences between v0 and v1 modes
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix helmfile template render debug log to not mention "first-pass" in v1 mode
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
The go-getter driver (named `Remote`) is used to implement remote values. I found some unused functions in its implementation. This commit removes those unused functions so that it becomes more maintainable.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Ref https://github.com/helmfile/helmfile/discussions/593
* implemented --reset-values flag overriding .helmDefaults.reuseValues=true
* tests for --reset-values flag
* fixed pkg/app tests
* added tests for both reset & reuse flags given
* added appendValuesControlMode method for --reuse/reset-values flag processing
* updated code comments & docs
Signed-off-by: Karol Ossowski <k@koralsky.pl>
This should fix#435 for Helmfile v0.x releases since the next v0.150.0.
We introduce a new envvar to opt-in to the new YAML library, so that you can give it a shot before upgrading your Helmfile to v1. The same envvar can be used to opt-out of the new YAML library after you upgrade to Helmfile v1, giving you a more flexible migration story.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Previously a values template rendering failure resulted in a cryptic error message like:
```
g release templates in "input.yaml": failed executing templates in release "input.yaml"."foo1": failed executing template expressions in release "foo1".values[0] = "[98 97 115 101 76 97 98 101 108 58 32 34 123 123 32 103 101 116 32 46 82 101 108 101 97 115 101 46 76 97 98 101 108 115 32 92 34 98 97 115 101 92 34 32 92 34 78 79 84 95 73 78 72 69 82 73 84 69 68 92 34 32 125 125 34 10]": template: stringTemplate:1: unexpected "\\" in operand
```
The issue was that the values template at the value position of the YAML dict was printed as a formatted byte array. We now print it as a standard string so that it is easily readable.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
This is a successor to #596. We need a smooth migration path from `gopkg.in/yaml.v2`, and this pull request moves it forward with `goccy/go-yaml` instead of `gopkg.in/yaml.v3`. Merging this unblocks users stuck in Helmfile v0.146.x or earlier due to #435, so that they can upgrade to 0.147.x or greater without updating their helmfile configs.
We previously tried to upgrade to `yaml.v3` (https://github.com/helmfile/helmfile/issues/394) in Helmfile v0.x, presuming it won't break anything. Apparently, it broke use-cases where you want to layer release's `values` field over three or more release templates and releases (#435).
We then tried to bring back `yaml.v2` for Helmfile v0.x and keep `yaml.v3` for the upcoming Helmfile v1. However, it failed due to incompatibility in the Unmarshaller interface between `yaml.v2` and `yaml.v3` (https://github.com/helmfile/helmfile/pull/596).
`goccy/go-yaml` is, from my observation, a well-maintained alternative to `yaml.v2`. One of its premises is that it enables us to swap the implementation from `gopkg.in/yaml.v2` to `goccy/go-yaml` just by replacing the import directive. It seems to use the same `Unmarshaller` interface as yaml.v2 too.
Once this PR gets merged, I'd like to follow-up with adding a new build-time variable and an envvar to set the proper default for the yaml parser Helmfile uses and the ability to switch the parser at runtime. All in all, the next Helmfile release, v0.150.0 will get reverted to use `gopkg.in/yaml.v2` by default which resolves#435.
New users who started using Helmfile since any of v0.148.0, v0.148.1, and v0.149.0 might be already relying on the new behavior, They might need to specify a new envvar to enable `goccy/go-yaml`.
Signed-off-by: yxxhero <aiopsclub@163.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: yxxhero <aiopsclub@163.com>
This is a successor to #442 rebuilt on top of #594 so that we can merge this while we are still at Hemlfile v0.x without worrying any backward-incompatibility.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
This is a successor to #440 rebuilt on top of #594 so that we can merge this while we are still at Hemlfile v0.x without worrying any backward-incompatibility. Much appreciation to @yxxhero for the original work!
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* feat: Helmfile V1 mode
We add a new "V1 mode" to Helmfile so that you can seemlessly upgrade Helmfile from the current v0.x to the upcoming v1.0.
The idea is that we build both v0 and v1 binaries from the same tagged commit within the main branch, with different defaults for the "V1 mode"- the V1 mode is disabled by default for v0.x binaries, while it is enabled by default for v1.x binaries.
The V1 mode can be overrode at runtime via envvar. That is, even after upgrading the binary to v1, you will not see any backward-incompatible changes while you explicitly set an envvar, `HELMFILE_V1MODE=true`, at runtime.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
All the dependencies get correctly installed when dealing with remote
charts.
If there's a local chart that depends on remote dependencies then those
don't get automatically installed. See #526. They end up with this
error:
```
Error: no cached repository for helm-manager-b6cf96b91af4f01317d185adfbe32610179e5246214be9646a52cb0b86032272 found. (try 'helm repo update'): open /root/.cache/helm/repository/helm-manager-b6cf96b91af4f01317d185adfbe32610179e5246214be9646a52cb0b86032272-index.yaml: no such file or directory
```
One workaround for that would be to add the repositories from the local
charts. Something like this:
```
cd local-chart/ && helm dependency list $dir 2> /dev/null | tail +2 | head -n -1 | awk '{ print "helm repo add " $1 " " $3 }' | while read cmd; do $cmd; done
```
This however is not trivial to parse and implement.
An easier fix which I did here is just to not allow doing
`--skip-refresh` for local repositories.
Fixes#526
Signed-off-by: Indrek Juhkam <indrek@urgas.eu>
Signed-off-by: Indrek Juhkam <indrek@urgas.eu>
Signed-off-by: yxxhero <aiopsclub@163.com>
1. only implement post-renderer flags this patch
2. As mumoshu advise, add helmfile flags `--post-render` and add the
postRenderer config in helmDefaults and release. the priority is
helmfile flags > release > helmDefaults.
3. fix the test case in state_test.go and some other tests.
Signed-off-by: guofutan <guofutan@tencent.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
All the dependencies get correctly installed when dealing with remote
charts.
If there's a local chart that depends on remote dependencies then those
don't get automatically installed. See #526. They end up with this
error:
```
Error: no cached repository for helm-manager-b6cf96b91af4f01317d185adfbe32610179e5246214be9646a52cb0b86032272 found. (try 'helm repo update'): open /root/.cache/helm/repository/helm-manager-b6cf96b91af4f01317d185adfbe32610179e5246214be9646a52cb0b86032272-index.yaml: no such file or directory
```
One workaround for that would be to add the repositories from the local
charts. Something like this:
```
cd local-chart/ && helm dependency list $dir 2> /dev/null | tail +2 | head -n -1 | awk '{ print "helm repo add " $1 " " $3 }' | while read cmd; do $cmd; done
```
This however is not trivial to parse and implement.
An easier fix which I did here is just to not allow doing
`--skip-refresh` for local repositories.
Fixes#526
Signed-off-by: Indrek Juhkam <indrek@urgas.eu>
Signed-off-by: Indrek Juhkam <indrek@urgas.eu>
* fetch checksum when possible
* use sha256sum -c to validate checksum
* use tar features to extract artifacts
* validate installed pkg in-place
Signed-off-by: Cyril Jouve <jv.cyril@gmail.com>
Signed-off-by: Cyril Jouve <jv.cyril@gmail.com>
* refactor integrations
Signed-off-by: yxxhero <aiopsclub@163.com>
* Update the integration test directory structure to better correlate the test script with testdata
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Undo the test-cases directory renaming to make the diff more easy to understand
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* fix ci
Signed-off-by: yxxhero <aiopsclub@163.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
* Enhance `make fmt` to cover running gci for golangci-lint compat
I have been using `make fmt` for formatting code before submitting a pull request. It turned out not to work in some cases where you added a new import because the default go-fmt obviously do not organize imports as the golangci-lint and gci expect.
This fixes that, by adding a gci command to the `make fmt` target.
Please note that this does not cover installing gci. If you need, please submit another pull request to add something like a `make install-gci` and make the `make fmt` depenedent on that target, so that one can get automatic gci installation when running `make fmt` for first time.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* We don't need running gci via make on CI as we already run it as part of golangci-lint run
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Use the new runWithLogCapture helper instead of the long boilerplate to capture the log for snapshot testing.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Allow configuring the lockfile in the state. This makes it possible for
example maintain a lock per environment.
Signed-off-by: Lassi Pölönen <lassi.polonen@iki.fi>
Signed-off-by: Lassi Pölönen <lassi.polonen@iki.fi>
This improves the `helmfile sync` performance.
From the code: `BuildDeps` is used only by `runHelmDepBuilds`, which
only is used by `PrepareCharts` which is finally only used by
`withPreparedCharts`.
`withPreparedCharts` already does `SyncReposOnce` which means we do not
have to refresh the local repository cache on each chart build.
This is only supported in Helm v3.
This seems to be mostly affecting helmfiles which have a lot of releases
and those release charts use sub dependencies.
I saw significant performance improvements for a helmfile with 45
releases, 2 repositories, and most of the charts also had their own
dependencies. Results:
Before the patch:
* real 9m10.565s
* real 9m38.335s
* real 9m14.941s
* real 5m13.106s (with cache)
After the patch:
* real 6m51.965s
* real 6m36.605s
* real 6m31.685s
* real 3m0.271s (with cache)
These were tested with:
```
rm -rf ~/.cache/helmfile ~/.cache/helm ~/.config/helm/repositories.* && helmfile sync ...
```
The result with `(with cache)` was without deleting the caches first.
From these metrics it seems that the sync duration decreased 20-45%
depending on the run, release count, dependencies and if the cache was
used or not.
As far as I understand, this should be backward-compatible change.
Signed-off-by: Indrek Juhkam <indrek@urgas.eu>
Signed-off-by: Indrek Juhkam <indrek@urgas.eu>
I had been unhappy with the fact that our go-test output had a lot of debug log messages which obfuscated test results.
I'm finally removeing all those by directing the test log output to io.Discard.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Most shells do not support hyphens in environment variables.
However, there are cases where you may want to include hyphens in the repository name.
Therefore, I have included a process in `gatherOCIUsernamePassword` to replace hyphens with underbar.
Signed-off-by: mugioka <okamugi0722@gmail.com>
* feat: show live output from the Helm binary
Signed-off-by: Rodrigo Fior Kuntzer <rodrigo@miro.com>
* fixup! Merge branch 'main' into enable-live-output
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
This changes list command so it doesn't run withPreparedCharts,
and just lists releases instead
Signed-off-by: Viktor Oreshkin <imselfish@stek29.rocks>
* add interactive in sync & remove --interactive in global options
Signed-off-by: yxxhero <aiopsclub@163.com>
* fix unittest
Signed-off-by: yxxhero <aiopsclub@163.com>
* same behave as apply when in interactive
Signed-off-by: yxxhero <aiopsclub@163.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
We would like to add back --set flag to apply subcommand, which was
accidentally removed after switching to cobra (#234)
Signed-off-by: Michal Jura <mjura@suse.com>
Fixing releases being included which do not match the environment
requested, which is a regression introduced by #234. The issue remains
when Helmfile state values are supplied, which is not a regression and
will be addressed separately.
Partial resolution for #271
Signed-off-by: David Ackroyd <dackroyd@fairfaxmedia.com.au>
Signed-off-by: David Ackroyd <dackroyd@fairfaxmedia.com.au>
If remote file isn't present in repo we will add it anyway to the files list and check `if len(files) == 0 {` never will be true. That leads to missing section with `MissingFileHandler`.
That fix check that cloned file actually exists. In that case if we add a link to non-existing remote file `MissingFileHandler` will be called as expected.
Signed-off-by: Vladimir Kuznichenkov <kuzaxak.tech@gmail.com>
Until now, the 'images' workflow was separated into two different jobs,
one for just building the images in e.g. pull requests and the other
one for building and pushing the images e.g. after a merge to the 'main'
branch, which resulted in code repetitions. Also, both jobs used
different approaches, one (build) using a 'matrix strategy' based on
the file name of the Dockerfile, the other one (build and push) having a
seperate build and push step for each Dockerfile.
With this change, both jobs have been unified into a single "build and
optionally push" job to remove the repetitions, which now also shares
the same approach - a matrix strategy based on the file names of the
Dockerfiles.
The package naming now follows a clear schema based on the file name of
the Dockerfile. 'Dockerfile' will result in a 'helmfile' package,
'Dockerfile.ubuntu' will result in a 'helmfile-ubuntu' package and so
on. In order to keep the 'helmfile-debian-stable-slim' image package
name, the 'Dockerfile.debian' had to be renamed to
'Dockerfile.debian-stable-slim' accordingly.
Furthermore, the evaluation of the condition whether a push is intended
(or not) has been moved directly to the 'push' flag of the
'docker/build-push-action'.
Signed-off-by: Patrick Hobusch <patrick.hobusch@gmail.com>
This similar to #239, but different in that it involves a local helm chart repo server instead of a local OCI registry as the container of the chart used in tests.
This also adds a new `localChartRepoServer.enabled` config to the `config.yaml` of each test case directory to enable the local helm repo server in the test, which might be useful when you want to add another test case that involes a remote chart(which is hosted in the local chart repo server).
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Signed-off-by: Tsubasa Nagasawa <toversus2357@gmail.com>
This adds OCI registry support for adhoc dependencies.
The users can now add their OCI hosted charts as dependencies to helm releases:
* Bump chartify version to v0.10.0
* Add an example helmfile to advanced usage section
so that it might be even more clear if the reported problem has been introduced by the prev release or a long-standing one which existed for longer time period.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
This commit replaces `os.Setenv` with `t.Setenv` in tests. The
environment variable is automatically restored to its original value
when the test and all its subtests complete.
Reference: https://pkg.go.dev/testing#T.Setenv
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
* Make a few helmfile sub-commands to consistently support needs-related flags
* helmfile-diff adds support for --include-transitive-needs
* helmfile-template adds support for --skip-needs
* helmfile-lint adds support for --skip-needs, --include-needs, and --include-transitive-needs
Ref https://github.com/roboll/helmfile/issues/2055
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix a few helmfile-lint needs related bugs and add tests
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Is include-transitive-needs realy working as intended? 🤔
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Confirm that it does fail on unselected need by default
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Add missing testdata
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Test helmfile-template for include/skip needs support
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix a few terms
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Add more tests to better know the current helmfile-diff behavior around needs
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix failing tests
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix helmfile-diff to consistently handle skip/include-needs
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Extract testhelper.RequireLog for reusing
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix all bugs and test cases for TestDiff and TestDiff_2
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix TestDiff_2
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix TestDiff
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix TestDiffWithNeeds
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Unify behavior on including disabled releases as needs for lint and template
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* Fix bug that --include-transitive-needs does not imply include-needs
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
We will be using this automation which is triggered on every new tag created in this repo for the upcoming helmfile 0.145.0 release.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
Our CI workflows and docker builds already use 1.18 but our go.mod was left with 1.17. This bumps it to 1.18.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
It turned out we lack some important information that is necessary to make it a real bug without guesswork.
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
I've asked a few times by @yxxhero if he deserves a seat as a maintainer of the Helmfile project.
Seeing the amount and the number of his recent contributions, and the nature of his contributions (add tests and fix bugs and CI issues, review PRs), I think he is in a relatively unique position compared to existing maintainers, and we can work better together!
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
* introduce DISABLE_INSECURE_FEATURES to disable insecure executions
Signed-off-by: Quan TRAN <account@itscaro.me>
* disable remote sources when DISABLE_INSECURE_FEATURES is set to "true"
Signed-off-by: Quan TRAN <account@itscaro.me>
* refactor envvar package
Signed-off-by: Quan TRAN <account@itscaro.me>
* (test) fix test fixtures
Signed-off-by: Quan TRAN <account@itscaro.me>
* use absolute path to avoid unit test failure
Signed-off-by: Quan TRAN <account@itscaro.me>
* Fix conflicts
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
* Adds feature to fetch environment values from remote
The releases and environment section allow for values files on the local
disk.
This enhancement allows for referencing remote (go-getter) files to be
fetched, cached and referenced.
In addition when fetching a remote git source with a ssh key the ssh key
will not be part of the caching folder name. This avoids two problems:
1. Don't leak sensitive information in the name of the caching folder
2. Base64 encoded SSH keys are very long. On some file systems the max
lenght of the directory name is hit when using the full base64
information in the path name.
The sshkey informations are reducted. Because of this fixed string
there is a change of colloding cache names. The likelihood of this
collision is very low. The git repo and git reference need to be the
same, but the sshkey can change. This will result in the same source to
be checkout out and referenced.
Signed-off-by: Lüchinger Dominic <dev@snowgarden.ch>
* Update pkg/state/storage.go
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
Since helm-diff has added an ability to auto-detect the term to decide if it should output with color or not, helmfile had been defaulted to no-color.
This resoloves that, by adding a term-detection logic that is same as helm-diff.
As a part of this work, I have also implemented a new global flag `--color`, which is used for forcing color without relying on the term-detection logic implemented in helmfile or explicitly setting the HELM_DIFF_COLOR envvar. I hope it is useful for folks.
Ref https://github.com/roboll/helmfile/issues/2043
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
When chartify is involved due to the use of `forceNamespace`, `strategicMergePatches`, `jsonPatches`, and so on, We had been internally mutating the Release.Chart with the path to the local temporary directory that contains the modified version of the chart.
This resulted in us unintentionally making `helmfile deps` to remove entries for the chart being modified out of helmfile.lock file, which resulted in issues like #2110.
To be clear, although the original issue is reported to occur for `strategicMergePatches`, I believe that it occurered also for any remote charts using `jsonPatches` and `forceNamespace` too.
I also believe this has been the issue since our introduction of chartify (maybe a year or so ago??), and I guess why it took so much time to be found and reported is that not so many people with chartify in combination with `helmfile deps` 🤔
Lastly, this changes chart names surfaced in the various log output from Helmfile, from temporary chart paths to the chart name/path declared in the helmfile.yaml. I think this is generally a good change, no fear of being a breaking change. But if anyone has any concern about that, please feel free to comment/report/etc.
Ref https://github.com/roboll/helmfile/issues/2110
Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
This adds support for `kube-version` and `api-versions` to be available to `chartify` so that it works even if your release requires `chartify` due to that you use features like `forceNamespace`, `jsonPatches`, `strategicMergePatches`, and so on.
This also enhances `ReleaseSpec` which corresponds to each item of `releases[]` in your `helmfile.yaml` to also accept `kubeVersion` and `apiVersions`, in addition to the top-level `kubeVersion` and `apiVersions` we have today.
The top-level ones works as the default values for release-specific ones. If you have been using the top-level ones, keep using it. It is backward-compatible. If you want to specify it per release, because, for example, your releases are deployed across clusters(in case you differentiate `kubeContext` fields), try the new fields added to the release spec.
Resolves#1864
This release of chartify fixes a single bug in chartify that resulted in a few issues when your chart had dependencies. One of issues is the mysterious "no cached repository for helm-manager-HASH found" error mentioned in https://github.com/variantdev/chartify/pull/31. Another is #2117 which was due to the bug resulted in rendering some resources, CRDs in the case, twice.
See https://github.com/variantdev/chartify/releases/tag/v0.9.5 for more information.
This release fixes an issue when you tried to chartify a local chart whose directory name does not match the name of the chart defined in Chart.yaml.
See https://github.com/variantdev/chartify/releases/tag/v0.9.4 for more information.
This should fix a few issues, most notably that adhoc dependencies breaks when some of original chart dependencies are unresolvable with `helm dep up` and/or `helm dep build`.
https://github.com/variantdev/chartify/releases/tag/v0.9.2
It turned out that Helmfile has never had support for release template on `needs`.
This adds that, along with the new end-to-end test suite to verify helmfile template output with snapshot testing involving a real `helmfile build` command.
Ref #2098
Use the value of the `condition` field instead of the `installed` field of a release in the `enabled` column of helmfile list.
The value of the `installed` field is shown in a new `installed` column.
Fixes#1920
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
Adds a new templating function called `readDir`. With `readDir` users can read the contents of a specified directory and get a list of all contained files. This is useful when reading a bunch of files from a directory. The following example shows a snippet of a values file for configuring a Logstash deployment. Using only `readFile`, a user must specify each file by hand and adjust this list as the number of files to be read grows.
```yaml
logstash:
configs:
logstash.yml: |
{{- tpl (readFile "config/logstash.yml.gotmpl") . | nindent 6 }}
jvm.options: |
{{- readFile "config/jvm.options" | nindent 6 }}
pipelines.yml: |
{{- readFile "config/pipelines.yml" | nindent 6 }}
pipelines:
beats-log4j.conf: |
{{- readFile "config/pipelines/beats-log4j.conf" | nindent 6 }}
nginx-access.conf: |
{{- readFile "config/pipelines/nginx-access.conf" | nindent 6 }}
nginx-error.conf: |
{{- readFile "config/pipelines/nginx-error.conf" | nindent 6 }}
syslog-logs.conf: |
{{- readFile "config/pipelines/syslog-logs.conf" | nindent 6 }}
tcp-logs.conf: |
{{- readFile "config/pipelines/tcp-logs.conf" | nindent 6 }}
udp-debug.conf: |
{{- readFile "config/pipelines/udp-debug.conf" | nindent 6 }}
udp-logs.conf: |
{{- readFile "config/pipelines/udp-logs.conf" | nindent 6 }}
certificates:
ca.crt: |
{{- readFile "config/certificates/ca.crt" | nindent 6 }}
logstash.crt: |
{{- readFile "config/certificates/logstash.crt" | nindent 6 }}
logstash.key: |
{{- readFile "config/certificates/logstash.key" | nindent 6 }}
```
With `readDir` the above snippet can be rewritten as follows:
```yaml
logstash:
configs:
{{- range readDir "config" }}
{{ base . }}: |
{{- if hasSuffix "gotmpl" . }}
{{- tpl (readFile .) $ | nindent 6 }}
{{- else }}
{{- readFile . | nindent 6 }}
{{- end }}
{{- end }}
pipelines:
{{- range readDir "config/pipelines" }}
{{ base . }}: |
{{- readFile . | nindent 6 }}
{{- end }}
certificates:
{{- range readDir "config/certificates" }}
{{ base . }}: |
{{- readFile . | nindent 6 }}
{{- end }}
```
Fixes#1646
This will allow us to use the new `fromJson` and `mustFromJson` functions
among others.
Co-authored-by: Graeme Gillies <ggillies@gitlab.com>
Parses a new field in repositories named `skipTLSVerify` and if set to `true`, it appends `--insecure-skip-tls-verify` in `helm repo add` command.
This should be useful with internal self-signed repos, mitm proxies etc.
Resolves#1871
* Do fail on a possible typo in `needs` entries
Helmfile kindly fails with a friendly error when you made a typo in a `needs` entry, i.e. a `needs` entry included a reference to a release that is not defined in the helmfile config.
Example Output:
```
in ./helmfile.needs.yaml: release(s) "app" depend(s) on an undefined release "infrastructure/cert-manager2". Perhaps you made a typo in `needs` or forgot defining a release named "cert-manager2" with appropriate `namespace` and `kubeContext`?
```
This prevents issues like #1959
* Fix regression in helmfile-diff (This may break when you had two or more duplicated releases that are intended to be de-duplicated before DAG calculation using selectors
* Fix regression when you used selector to deduplicate releases before DAG calculation
* Comments
* Fix regressions in helmfile-apply and helmfile-sync
* Fix regression in duplicate release detection
Currently it's not possible to use `.Environment` values in `*.gomtpl` files. The documentation states the opposite:
https://github.com/roboll/helmfile#environment (2nd paragraph).
The problem is already described in #1090.
This PR fixes this bug.
Fixes#1090
Co-authored-by: Peter Aichinger <petera@topdesk.com>
* Guard collectNeeds-method against infinite recursion.
* Also check for namespace and kubecontext when collecting needs.
Co-authored-by: Peter Aichinger <petera@topdesk.com>
It turned out the Helm 2.17.0 binary is nowhere now. I considered a bit about checking for a newer Helm 2.x releases as an alternative but I resisted as it is almost a year since EoL of Helm 2. Thanks Helm 2. Long live Helm 3!
Apparently we needed to pass `--validate` on helm-template run by chartify when the targeted chart contains Capabilities.APIVersions in a chart template. Otherwise, you can never make such chart work with chartify, as at apply time helm template expressions that involved Capabilities.APIVersions are already nowhere.
- Add debian image based on `stable-slim`, desire for this is largely
around my use case using Azure DevOps which makes it challenging to
use images which are not glibc based.
- Drop support for helm2 in the docker images. This is a tricky one but
given that I was having errors during the docker build for helm2 and
the fact that it has been EoL for a long time now made me think that
this was the correct move.
- As a "while I'm in here" I've upgraded kubectl and helm. I've popped
on the most current patch of the last release (v1.20.3) to give a
slightly broader support for different Kubernetes versions.
- Reworked CI to support pushing a debian and alpine base, and dropped
support for the helm2 versions.
This adds the ability to include the --pass-credentials flag to the helm add repo command by:
- Adding repo.passCredentials to the helmfile yaml
- Changing state, helmexec, and app to include RepositorySpec.PassCredentials
Resolves#1898
Co-authored-by: almed4 <alexandre.meddin@ingka.ikea.com>
This release includes new `ref+tfstates3://` and `ref+tfstategs://` backends for reading terraform states stored in s3 and google cloud storage, and features a new aws-sdk-go that supports AWS SSO, and the fix to allow referencing a local tfstate file by the absolute path.
See https://github.com/variantdev/vals/releases/tag/v0.14.0 for all the changes.
#1772 broke `--selector` with `needs` in many ways.
The two biggest problems I've encountered were:
- duplicate releases even if you've provided a proper `selector` to deduplicate
- sync/deletion ordering broken when you have `needs`
For the first issue, we had to update `getSelectedReleases` function to also calculate the "selected releases and releases needed by the selected releases", and use that to calculate the DAG. That should have been done in #1772.
The latter started happening after I've fixed the first issue. The source of the issue was that `needs` turned out to be ambiguous in a few cases.
Previously, `needs: ["foo/bar"]` had two meanings. One for "needs release bar in kubecontext foo", another for "needs release bar in namespace foo".
Moreover, `needs: ["foo/bar/baz"]` had three meanings.
- `needs release baz in tiller namespace foo and namespace baz`
- `needs release baz in namespace bar in kubecontext foo`
- `needs release baz in tiller namespace bar in kubecontext foo`.
Especially, the first meaning doesn't make sense at all. Helm 2 solely use tillerNamespace for namespacing the release and Helm 3 uses namespace for that.
This fix sorts all the bugs and issues I've found so far around that, by changing the meanings of the above two examples as follows:
- `foo/bar` means `namespace=foo,name=bar` for Helm 3 and `tillerNamespace=foo,name=bar` for Helm 2
- `needs release bar in kubecontext foo` is now `foo//bar`. Notice the extra `/` between `foo` and `bar`.
- `foo/bar/baz` means `kubecontext=foo,namespace=bar,name=baz` for Helm 3 and `kubecontext=foo,tillerNamespace=bar,name=baz` in Helm 2
Fixes#1818
* tests: fix vagrant test run
* feat: added an option to specify the different diff output format
* renamed diff-output to output
* renamed diff-output to output
Co-authored-by: Andrey Tuzhilin <andrey@zelf.co>
* Add test for helmfile-destroy with selector
I was curious if destroy with a selector is working at all while reading https://github.com/roboll/helmfile/issues/1750#issuecomment-823521572. So I added this test for verification. From the test result, it is working, though.
* Add one more test case for destroying disabled but installed release
* Add --{include,skip}-needs to helmfile-sync and helmfile-apply
* Add --include-needs to helmfile-template
* Add TODO related to #1018
* Add a few new test files to cover new functionalities
* Update apply test to incorporate the change that the destroy and sync steps target affected releases only
Helmfile has been providing a feature called "adhoc chart dependency" that basially enabled you to add Chart.yaml `dependencies` entry adhocly without forking or modifying the chart.
It was missing the support for using a local chart as the adhoc dependency. This patch adds that.
Usage:
`releases[].dependencies[].chart` is enhanced to accept the fs path to the local chart:
```
releases:
- name: foo
chart: ./path/to/foo
dependencies:
- chart: ./path/to/bar
```
Resolves#1762
Ref https://github.com/roboll/helmfile/issues/809#issuecomment-814423653
This is not what had been requested originally in #809 but anyway- This enables you to limit helm-dep-up run by helmfile-deps by selector. For example, `helmfile -l name=foo deps` should result in only the release named `foo` to be helm-dep-uped.
We use kustomize in two places. One for turning kustomize into a chart, and another for patching manifests and the chart.
This fixes the former to work with kustomize v4.
Fixes#1688
Related to #494
This feature is mostly a built-in alternative to the `incubator/raw` chart without external dependency and has
access to helmfile's own template functions and template data.
The expected use-case of this feature is to add arbitrary K8s resources to your deployment.
Unlike the original issue raised in #494 this doesn't enable you to add arbitary resources to a release. That's another story. But this would be a good foundation for that, too.
Secret files ending with .gotmpl are now also rendered as a gotemplate.
```
releases:
- name: myapp
secrets:
- secrets.yaml.gotmpl
```
Note that currently, .gotmpl files must be valid YAML files as well.
The expected use-case of this feature is to compose a YAML array from values and encrypted secrets.
Without this feature, you would have tried to do something like the below, which didn't work.
**Example (doesn't work!)**
`values.yaml.gotmpl`:
```
environment:
- name: MY_EXTERNAL_IP
value: |
{{ exec "./get-external-ip.sh" (list "") }}
```
`secrets.yaml`:
```
_sops:
#...
environment:
- name: MY_SECRET_VALUE
value: (encrypted by sops)
```
`helmfile.yaml`:
```
releases:
- name: foo
values:
- values.yaml
secrets:
- secrets.yaml
```
This doesn't work because `values.yaml` and the decrypted `secrets.yaml` are passed to `helm` to be merged, and helm overrides the array instead of merging or concatenating the arrays.
**Example (works!)**
Instead of `values.yaml` and `secrets.yaml`, you provide a single `secrets.yaml.gotmpl` that is a valid YAML and encrypted by sops:
```
_sops:
#...
environment:
- name: MY_EXTERNAL_IP
value: |
{{ exec "./get-external-ip.sh" (list "") }}
- name: MY_SECRET_VALUE
value: (encrypted by sops)
```
`helmfile.yaml`:
```
releases:
- name: foo
secrets:
- secrets.yaml.gotmpl
```
Helmfile decrypts the gotmpl by handing it over to helm-secrets and then renders the result as a gotmpl file. The end result is that you have a two-element array `environments` that can be just passed to helm.
Resolves#1700
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
Adds `--chart` flag for overriding the selected release's chart ad-hoc-ly like `helmfile --chart $CHART template`.
This is handy when e.g. you want to have an ArgoCD application per each release in your helmfile.yaml, while also providing the ability to customize the release's chart without touching helmfile.yaml.
See https://github.com/roboll/helmfile/issues/1690#issuecomment-812321354 for more context.
Closes#1690
This enables you to write a `kubectl-apply` hook more declaratively than writing `command` and `args`:
```
releases:
- name: myapp
chart: mychart
hooks:
- events: ["presync"]
kubectlApply:
filename: path/to/manifests
#kustomize: path/to/kustomize
```
This would allow cli flag `--kube-context` to override value in helmDefaults allowing to use different values in local development and CI context.
Co-authored-by: Andrey Tuzhilin <andrey@3adigital.ru>
* Update referance for helm-secrets to latest maintained fork
* Missed a referance in the docs to an older edition of helm secrets
* Removed docker2 changes back to original method
Co-authored-by: Nathan Flynn <nflynn@williamhill.co.uk>
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
- replace deprecated helm-secrets with the currently active helm-secrets
```plain
Deprecation Info
Please note, this project is no longer being maintained.
Link to active helm-secret plugin could be found in helm documentation: https://helm.sh/docs/community/related/#helm-plugins
```
* Fix OCI support
I have seen various issues related to the OCI repository support recently added to Helmfile.
This is the patch that should fix all the issues Im aware of until now.
Adding documentation for this feature: https://github.com/helm/helm/pull/6819
not being aware of this, make turn helm2 to 3 migrations very complicated.
This finishes the work started at #1619 by introducing the following changes:
- You can now set `HELMFILE_TEMPDIR` and `CHARTIFY_TEMPDIR` as the directory to persist temporary values files rendered by helmfile and temporary charts generated by chartify. Note that chartify is used internally when you use kustomize integration or raw K8s manifests as a chart.
- Helmfile uses the hash sum of the release config and the values file content in the file name of the temporary values file.
In combination with `HELMFILE_TEMPDIR` and `CHARTIFY_TEMPDIR`, this enables helmfile to use the stable file names for temporary values files, which contribute to stabilize log messages like `Comparing release=appset, chart=PATH/TO/TEMPORARY/CHART`, where the `PATH/TO/TEMPORARY/CHART` had been randomized due to formerly random helmfile tempdir and temporary values file names, and random chartify tempdir.
You can try this feature with a script like:
```
tempdir=$(mktemp -d -t helmfile)
HELMFILE_TEMPDIR=${tempdir} CHARTIFY_TEMPDIR=${tempdir} helmfile diff
rm -rf ${tempdir}
```
`helmfile-diff` sorts multiple and concurrent helm-diff outputs and stabilizes writes to stdout.
It's required to use the stdout from helmfile-diff to detect if there was another change(s) between 2 points in time.
For example, terraform-provider-helmfile runs a helmfile-diff on `terraform plan` and another on `terraform apply`. `terraform`, by design, fails when helmfile-diff outputs were not equivalent. Stabilized helmfile-diff output rescues that.
This improves helmfile-apply with two things:
- Some users had timing-out issues or annoyed by huge output from helm-diff run as part of helmfile-apply on first install. `--skip-diff-on-install` skips running helm-diff for releases being newly installed, so that you can avoid those issues.
- Some users had difficultly or found it not straight-forward to install CRDs and custom resources from separate charts in one helmfile-apply (#1353). The new helmfile.yaml release field `disableValidationOnInstall: true` adds `--disable-validation` to helm-diff only for releases being newly released, which should mostly resolve the issue.
Resolves#1353
Please see the updated `advanced-features.md` for more details.
This is often used for adding common labels and annotations to any resources rendered from a Helm chart.
* feat: enable EnableBashCompletion to get --generate-bash-completion command line flag
* feat: add scripts for bash and zsh
* feat: document shell completion
Small update to the readme repository examples since Google is no longer officially supporting hosting the stable/incubator helm charts. The official helm docs are using these repos now, eg. https://helm.sh/docs/intro/quickstart/.
This deprecates the old `--retain-values` which was not working as intended.
Also see #1570 - there's now `--skip-cleanup` for `helmfile-template`, too.
This allows you to use helmfile-template output as a GitOps source, when the template output contains CRDs and you use Helm 3.
Helm 3 by default removes CRDs from the template output. If you want to git-commit helmfile-template containing CRDs for GitOps and you use Helm 3 for templating, the only way is provide this newly added `--include-crds` flag.
I had mistakenly inverted the necessary flag to turn off the legacy processing on selectors that should be used only for helmfile commands that does not support DAGs/needs.
Fixes#1552
`helm dep up` is now skipped while running helm-x/chartify when the chart/directory is obtained by running go-getter, or `skipDeps` is configured using a command-line flag, helmDefaults, or release configuration.
Resolves#1547
Changes:
* Bump helm to v3.3.4.
* Bump kubectl to v1.18.9
* Update Dockerfile to be a little more verbose to help understand which command in a chain failed.
Signed-off-by: Jake Hill <jake@naphta.uk>
Before opening a bug report, please search for the behaviour in the existing issues.
Go ahead to https://github.com/helmfile/helmfile/search?q=&type= and fill in the error message you received from Helmfile or the keywords you think appropriate.
- type:markdown
id:thankyou
attributes:
value:|
Thank you for taking your time to file a bug report! To confirm it's a bug, we need some information to reproduce it.
- type:input
id:os
attributes:
label:Operating system
description:"Which operating system do you use? Please provide the version as well."
placeholder:"ex. Ubuntu 20.04.4 LTS"
validations:
required:true
- type:input
id:helmfile
attributes:
label:Helmfile Version
description:"Please provide the version number of Helmfile you used. If it isn't the latest, please upgrade first."
placeholder:"Run `helmfile version` to print it."
validations:
required:true
- type:input
id:helm
attributes:
label:Helm Version
description:"Please provide the version number of Helm you used. If it isn't the latest, please upgrade first."
placeholder:"Run `helm version` to print it."
validations:
required:true
- type:textarea
id:bug-description
attributes:
label:Bug description
description:What happened?
validations:
required:true
- type:textarea
id:helmfile-yaml
attributes:
label:Example helmfile.yaml
description:"Please provide an example helmfile.yaml that can be used to reproduce the issue locally."
validations:
required:true
- type:textarea
id:helmfile-error
attributes:
label:"Error message you've seen (if any)"
description:"Please provide the error message emitted by Helmfile."
validations:
required:true
- type:input
id:repo
attributes:
label:Steps to reproduce
description:Please provide the URL to a GitHub repository that contains a helmfile.yaml, other companion files, and a README.md with the steps to reproduce the bug.
validations:
required:true
- type:input
id:helmfile_working_ver
attributes:
label:Working Helmfile Version
description:"Please provide the highest version number of Helmfile that doesn't result in the above problem."
placeholder:"Run `helmfile version` to print it."
validations:
required:true
- type:input
id:discussion
attributes:
label:Relevant discussion
description:Please provide the URL to a relevant GitHub Discussion.
[](https://github.com/helmfile/helmfile/pkgs/container/helmfile)
This project is maintained by a small team of four and therefore lacks the resource to provide security fixes in a very timely manner.
That said, even though we are very passionate about making Helmfile rock solid security wise, all issues are handled on the best effort basis.
If you have important business(es) that relies on this project, please consider sponsoring the maintainers, so that they can commit more on providing such service.
> *Note* that we don't currently have project-wide sponsorship enabled as we don't know how to share the amount of sponsorships with fairness.
> Please sponsor individuals instead! Thanks for your understanding.
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 0.144.0 | :white_check_mark: |
| < 0.144.0| :x: |
## Reporting a Vulnerability
To report a security issue, please email helmfile-security@googlegroups.com with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue.
A maintainer will try to respond within 5 working days. If the issue is confirmed as a vulnerability, a Security Advisory will be opened. This project currently tries to follow a 90 day disclosure timeline.
| Organization | Workload | More Info | Location | Added |
|---|---|---|---|---|
| [reddit.com](https://www.reddit.com/) | production | [GitHub issue](https://github.com/roboll/helmfile/issues/96#issue-312012249), [Talk](https://www.slideshare.net/GregoryTaylor11/helm-at-reddit-from-local-dev-staging-to-production) | San Francisco, CA | April 2018 |
| [gitlab.com](https://gitlab.com/) | production | [Gitlab Project](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/tree/master) | * | August 2022 |
| [ricardo.ch](https://www.ricardo.ch/) | production | We're deploying our complete application platform using Helmfile. | Zug, Switzerland | April 2018 |
| [Hellofresh](https://engineering.hellofresh.com/) | production | We've been using helmfile in production since April 2018 for deploying all our infrastructure applications | Berlin, Germany | April 2018 |
| [Cherre](https://cherre.com/) | production | We have no public posts about using Helmfile, but we have been using it for a long time now | New York, NY | October 2018 |
@@ -24,7 +25,16 @@ information to this file.
| [American Express](https://www.americanexpress.com) | proof-of-concept | Orchestration of both internal cluster workloads and local developer environments. | London, GB | January 2020 |
| [Sportradar](https://www.sportradar.com) | production | Since mid-2019, we've been deploying our core infrastructure and several application stacks with Helmfile. | St. Gallen, Switzerland | March 2020 |
| [PedidosYa](https://www.pedidosya.com) | production | | Montevideo, Uruguay | June 2020 |
| [Jenkins OSS](https://jenkins.io) | production | [jenkins-infra/charts](https://github.com/jenkins-infra/charts) | * | July 2020 |
| [Jenkins](https://jenkins.io) | production | [jenkins-infra/kubernetes-management](https://github.com/jenkins-infra/kubernetes-management) | * | July 2020 |
| [SettleMint](https://settlemint.com) | production | The SettleMint platform allows enterprises to spin up k8s clusters and deploy production grade blockchain networks and additional services. Helmfile is in charge of deploying these networks and services on demand out of the self service management ui. | Belgium, Singapore, UAE, India | October 2020 |
| [AutoTrader (UK)](https://www.autotrader.co.uk) | production | We've used Helmfile for 2+ years to deploy 400+ services | UK | October 2020 |
| [Trend Micro](https://www.trendmicro.com) | production | We manage 9 k8s clusters in a mono git repository with Helmfile | Taipei, Taiwan | December 2019 |
| [William Hill](https://www.williamhill.com) | production | We have standardised on Helmfile for managing both our application services and our Kubernetes platform components. | International | March 2021 |
| [The Hyve](https://www.thehyve.nl) | production | We've been using Helmfile since 2019 to deploy [Radar-base applications](https://github.com/RADAR-base/RADAR-Kubernetes). [Blog Post](https://www.thehyve.nl/articles/kubernetes-added-to-radar-base) | Utrecht, Netherlands | April 2021 |
| [IKEA US](https://www.ikea.com) | production | We started using Helmfile this year to shrink the boilerplate involved in deploying or microservices to cloud Kubernetes clusters. | Utrecht, Netherlands | April 2021 |
| [ShareGate](https://www.sharegate.com) | production | Used to deploy and sync our kubernetes workloads in Azure, using Azure Pipelines and custom extensions to [install](https://marketplace.visualstudio.com/items?itemName=GSoft.HelmfileInstaller) and [execute](https://marketplace.visualstudio.com/items?itemName=GSoft.HelmfileRunner) the cli. | Montreal, Canada | June 2021 |
| [subshell](https://subshell.com) | production | We're using helmfile since 2021 to deploy all our Kubernetes workloads into our clusters. We love helmfile for its simplicity and power. Thank you! | Hamburg, Germany | August 2022 |
| [Norddeutscher Rundfunk](https://www.ndr.de) | production | Using Helmfile since 2020 to deploy workloads to several similar clusters (dev, qa, prod, test, etc.) for sites tagesschau.de and sportschau.de. Thank you so much for your awesome work! | Hamburg, Germany | August 2022 |
| [Dealhub](https://dealhub.io/) | production | Helmfile was an essential part of our k8s migration. Keep up the good work! | Holon, Israel | January 2023 |
| [BlueLabs](https://bluelabs.eu/) | production | Helmfile is the cornerstone of our lightweight, auditable and centralized GKE deployments. | Europe | February 2021 |
f.StringArrayVar(&applyOptions.Set,"set",nil,"additional values to be merged into the helm command --set flag")
f.StringArrayVar(&applyOptions.Values,"values",nil,"additional value files to be merged into the helm command --values flag")
f.IntVar(&applyOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.BoolVar(&applyOptions.Validate,"validate",false,"validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the list of available API versions")
f.IntVar(&applyOptions.Context,"context",0,"output NUM lines of context around changes")
f.StringVar(&applyOptions.Output,"output","","output format for diff plugin")
f.BoolVar(&applyOptions.DetailedExitcode,"detailed-exitcode",false,"return a non-zero exit code 2 instead of 0 when there were changes detected AND the changes are synced successfully")
f.BoolVar(&applyOptions.StripTrailingCR,"strip-trailing-cr",false,"strip trailing carriage return on input")
f.StringVar(&applyOptions.DiffArgs,"diff-args","",`pass args to helm helm-diff`)
f.StringVar(&globalCfg.GlobalOptions.Args,"args","","pass args to helm exec")
if!runtime.V1Mode{
// TODO: Remove this function once Helmfile v0.x
f.BoolVar(&applyOptions.RetainValuesFiles,"retain-values-files",false,"DEPRECATED: Use skip-cleanup instead")
f.BoolVar(&applyOptions.SkipCleanup,"skip-cleanup",false,"Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
f.BoolVar(&applyOptions.SkipCRDs,"skip-crds",false,"if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
f.BoolVar(&applyOptions.SkipNeeds,"skip-needs",true,`do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
f.BoolVar(&applyOptions.IncludeNeeds,"include-needs",false,`automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
f.BoolVar(&applyOptions.IncludeTransitiveNeeds,"include-transitive-needs",false,`like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
f.BoolVar(&applyOptions.SkipDiffOnInstall,"skip-diff-on-install",false,"Skips running helm-diff on releases being newly installed on this apply. Useful when the release manifests are too huge to be reviewed, or it's too time-consuming to diff at all")
f.BoolVar(&applyOptions.IncludeTests,"include-tests",false,"enable the diffing of the helm test hooks")
f.StringArrayVar(&applyOptions.Suppress,"suppress",nil,"suppress specified Kubernetes objects in the diff output. Can be provided multiple times. For example: --suppress KeycloakClient --suppress VaultSecret")
f.BoolVar(&applyOptions.SuppressSecrets,"suppress-secrets",false,"suppress secrets in the diff output. highly recommended to specify on CI/CD use-cases")
f.BoolVar(&applyOptions.ShowSecrets,"show-secrets",false,"do not redact secret values in the diff output. should be used for debug purpose only")
f.BoolVar(&applyOptions.NoHooks,"no-hooks",false,"do not diff changes made by hooks.")
f.BoolVar(&applyOptions.SuppressDiff,"suppress-diff",false,"suppress diff in the output. Usable in new installs")
f.StringVar(&diffOptions.DiffArgs,"diff-args","",`pass args to helm helm-diff`)
f.StringVar(&globalCfg.GlobalOptions.Args,"args","","pass args to helm diff")
f.StringArrayVar(&diffOptions.Set,"set",nil,"additional values to be merged into the helm command --set flag")
f.StringArrayVar(&diffOptions.Values,"values",nil,"additional value files to be merged into the helm command --values flag")
f.IntVar(&diffOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.BoolVar(&diffOptions.Validate,"validate",false,"validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the diff of available API versions")
f.BoolVar(&diffOptions.SkipNeeds,"skip-needs",true,`do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
f.BoolVar(&diffOptions.IncludeTests,"include-tests",false,"enable the diffing of the helm test hooks")
f.BoolVar(&diffOptions.IncludeNeeds,"include-needs",false,`automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
f.BoolVar(&diffOptions.IncludeTransitiveNeeds,"include-transitive-needs",false,`like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
f.BoolVar(&diffOptions.SkipDiffOnInstall,"skip-diff-on-install",false,"Skips running helm-diff on releases being newly installed on this apply. Useful when the release manifests are too huge to be reviewed, or it's too time-consuming to diff at all")
f.BoolVar(&diffOptions.ShowSecrets,"show-secrets",false,"do not redact secret values in the output. should be used for debug purpose only")
f.BoolVar(&diffOptions.NoHooks,"no-hooks",false,"do not diff changes made by hooks.")
f.BoolVar(&diffOptions.DetailedExitcode,"detailed-exitcode",false,"return a detailed exit code")
f.BoolVar(&diffOptions.StripTrailingCR,"strip-trailing-cr",false,"strip trailing carriage return on input")
f.IntVar(&diffOptions.Context,"context",0,"output NUM lines of context around changes")
f.StringVar(&diffOptions.Output,"output","","output format for diff plugin")
f.BoolVar(&diffOptions.SuppressSecrets,"suppress-secrets",false,"suppress secrets in the output. highly recommended to specify on CI/CD use-cases")
f.StringArrayVar(&diffOptions.Suppress,"suppress",nil,"suppress specified Kubernetes objects in the output. Can be provided multiple times. For example: --suppress KeycloakClient --suppress VaultSecret")
f.IntVar(&fetchOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.StringVar(&fetchOptions.OutputDir,"output-dir","","directory to store charts (default: temporary directory which is deleted when the command terminates)")
f.StringVar(&fetchOptions.OutputDirTemplate,"output-dir-template",state.DefaultFetchOutputDirTemplate,"go text template for generating the output directory")
f.IntVar(&lintOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.StringVar(&globalCfg.GlobalOptions.Args,"args","","pass args to helm exec")
f.StringArrayVar(&lintOptions.Set,"set",nil,"additional values to be merged into the helm command --set flag")
f.StringArrayVar(&lintOptions.Values,"values",nil,"additional value files to be merged into the helm command --values flag")
f.BoolVar(&lintOptions.SkipNeeds,"skip-needs",true,`do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
f.BoolVar(&lintOptions.IncludeNeeds,"include-needs",false,`automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
f.BoolVar(&lintOptions.IncludeTransitiveNeeds,"include-transitive-needs",false,`like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
fs.StringVarP(&globalOptions.HelmBinary,"helm-binary","b",app.DefaultHelmBinary,"Path to the helm binary")
fs.StringVarP(&globalOptions.KustomizeBinary,"kustomize-binary","k",app.DefaultKustomizeBinary,"Path to the kustomize binary")
fs.StringVarP(&globalOptions.File,"file","f","","load config from file or directory. defaults to \"`helmfile.yaml`\" or \"helmfile.yaml.gotmpl\" or \"helmfile.d\" (means \"helmfile.d/*.yaml\" or \"helmfile.d/*.yaml.gotmpl\") in this preference. Specify - to load the config from the standard input.")
fs.StringVarP(&globalOptions.Environment,"environment","e","",`specify the environment name. Overrides "HELMFILE_ENVIRONMENT" OS environment variable when specified. defaults to "default"`)
fs.StringArrayVar(&globalOptions.StateValuesSet,"state-values-set",nil,"set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).")
fs.StringArrayVar(&globalOptions.StateValuesSetString,"state-values-set-string",nil,"set state STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).")
fs.StringArrayVar(&globalOptions.StateValuesFile,"state-values-file",nil,"specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).")
fs.BoolVar(&globalOptions.SkipDeps,"skip-deps",false,`skip running "helm repo update" and "helm dependency build"`)
fs.BoolVar(&globalOptions.StripArgsValuesOnExitError,"strip-args-values-on-exit-error",true,`Strip the potential secret values of the helm command args contained in a helmfile error message`)
fs.BoolVar(&globalOptions.DisableForceUpdate,"disable-force-update",false,`do not force helm repos to update when executing "helm repo add"`)
fs.BoolVarP(&globalOptions.Quiet,"quiet","q",false,"Silence output. Equivalent to log-level warn")
fs.StringVar(&globalOptions.KubeContext,"kube-context","","Set kubectl context. Uses current context by default")
fs.BoolVar(&globalOptions.Debug,"debug",false,"Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect")
fs.BoolVar(&globalOptions.Color,"color",false,"Output with color")
fs.BoolVar(&globalOptions.NoColor,"no-color",false,"Output without color")
fs.StringVarP(&globalOptions.Namespace,"namespace","n","","Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }}")
fs.StringVarP(&globalOptions.Chart,"chart","c","","Set chart. Uses the chart set in release by default, and is available in template as {{ .Chart }}")
fs.StringArrayVarP(&globalOptions.Selector,"selector","l",nil,`Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar.
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
"--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases.
The name of a release can be used as a label: "--selector name=myrelease"`)
fs.BoolVar(&globalOptions.AllowNoMatchingRelease,"allow-no-matching-release",false,`Do not exit with an error code if the provided selector has no matching releases.`)
fs.BoolVar(&globalOptions.EnableLiveOutput,"enable-live-output",globalOptions.EnableLiveOutput,`Show live output from the Helm binary Stdout/Stderr into Helmfile own Stdout/Stderr.
It only applies for the Helm CLI commands, Stdout/Stderr for Hooks are still displayed only when it's execution finishes.`)
fs.BoolVarP(&globalOptions.Interactive,"interactive","i",false,"Request confirmation before attempting to modify clusters")
f.StringVar(&globalCfg.GlobalOptions.Args,"args","","pass args to helm sync")
f.StringArrayVar(&syncOptions.Set,"set",nil,"additional values to be merged into the helm command --set flag")
f.StringArrayVar(&syncOptions.Values,"values",nil,"additional value files to be merged into the helm command --values flag")
f.IntVar(&syncOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.BoolVar(&syncOptions.Validate,"validate",false,"validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the sync of available API versions")
f.BoolVar(&syncOptions.SkipNeeds,"skip-needs",true,`do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
f.BoolVar(&syncOptions.SkipCRDs,"skip-crds",false,"if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
f.BoolVar(&syncOptions.IncludeNeeds,"include-needs",false,`automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
f.BoolVar(&syncOptions.IncludeTransitiveNeeds,"include-transitive-needs",false,`like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
f.StringVar(&globalCfg.GlobalOptions.Args,"args","","pass args to helm template")
f.StringArrayVar(&templateOptions.Set,"set",nil,"additional values to be merged into the helm command --set flag")
f.StringArrayVar(&templateOptions.Values,"values",nil,"additional value files to be merged into the helm command --values flag")
f.StringVar(&templateOptions.OutputDir,"output-dir","","output directory to pass to helm template (helm template --output-dir)")
f.StringVar(&templateOptions.OutputDirTemplate,"output-dir-template","","go text template for generating the output directory. Default: {{ .OutputDir }}/{{ .State.BaseName }}-{{ .State.AbsPathSHA1 }}-{{ .Release.Name}}")
f.IntVar(&templateOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.BoolVar(&templateOptions.Validate,"validate",false,"validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the template of available API versions")
f.BoolVar(&templateOptions.IncludeCRDs,"include-crds",false,"include CRDs in the templated output")
f.BoolVar(&templateOptions.SkipTests,"skip-tests",false,"skip tests from templated output")
f.BoolVar(&templateOptions.SkipNeeds,"skip-needs",true,`do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
f.BoolVar(&templateOptions.IncludeNeeds,"include-needs",false,`automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
f.BoolVar(&templateOptions.IncludeTransitiveNeeds,"include-transitive-needs",false,`like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
f.BoolVar(&templateOptions.SkipCleanup,"skip-cleanup",false,"Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
f.StringVar(&templateOptions.PostRenderer,"post-renderer","",`pass --post-renderer to "helm template" or "helm upgrade --install"`)
f.StringArrayVar(&templateOptions.PostRendererArgs,"post-renderer-args",nil,`pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
f.StringVar(&templateOptions.KubeVersion,"kube-version","",`pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`)
f.IntVar(&writeValuesOptions.Concurrency,"concurrency",0,"maximum number of concurrent helm processes to run, 0 is unlimited")
f.StringArrayVar(&writeValuesOptions.Set,"set",nil,"additional values to be merged into the helm command --set flag")
f.StringArrayVar(&writeValuesOptions.Values,"values",nil,"additional value files to be merged into the helm command --values flag")
f.StringVar(&writeValuesOptions.OutputFileTemplate,"output-file-template","","go text template for generating the output file. Default: {{ .State.BaseName }}-{{ .State.AbsPathSHA1 }}/{{ .Release.Name}}.yaml")
Let's say you have a `helmfile.yaml` that looks like the below:
@@ -57,7 +60,7 @@ bases:
Followed by the below steps:
- Running `kustomize edit set image $IMAGE` for every `$IMAGE` generated from your values.yaml
- Running `kustomize edit set image $IMAGE` for every `$IMAGE` generated from your values.yaml
- Running `kustomize edit set nameprefix $NAMEPREFIX` with the nameprefix specified in your values.yaml
- Running `kustomize edit set namesuffix $NAMESUFFIX` with the namesuffix specified in your values.yaml
- Running `kustomize edit set namespace $NS` with the namespace specified in your values.yaml
@@ -90,16 +93,26 @@ which can be included in the temporary chart.
After all, Helmfile just installs the temporary chart like standard charts, which allows you to manage everything with Helmfile regardless of each app is declared using a Helm chart or a kustomization.
Please also see [test/advanced/helmfile.yaml](https://github.com/roboll/helmfile/tree/master/test/advanced/helmfile.yaml) for an example of kustomization support and more.
Please also see [test/advanced/helmfile.yaml](https://github.com/helmfile/helmfile/tree/master/test/advanced/helmfile.yaml) for an example of kustomization support and more.
## Adhoc Customization of Helm charts
### Adhoc Kustomization of Helm charts
With Helmfile's integration with Kustomize, not only deploying Kustomization as a Helm chart, you can kustomize charts before installation.
Currently, Helmfile allows you to set the following fields for kustomizing the chart:
@@ -134,4 +147,186 @@ Please note that the second `data` field `bar` is coming from the strategic-merg
There's also `releases[].jsonPatches` that works similarly to `strategicMergePatches` but has additional capability to remove fields.
Please also see [test/advanced/helmfile.yaml](https://github.com/roboll/helmfile/tree/master/test/advanced/helmfile.yaml) for an example of patching support and more.
Please also see [test/advanced/helmfile.yaml](https://github.com/helmfile/helmfile/tree/master/test/advanced/helmfile.yaml) for an example of patching support and more.
#### `transformers`
You can set `transformers` to apply [Kustomize's transformers](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/configureBuiltinPlugin.md#configuring-the-builtin-plugins-instead).
Each item can be a path to a YAML or Go template file, or an embedded transformer declaration as a YAML hash.
It's often used to add common labels and annotations to your resources.
In the below example, we add common annotations and labels every resource rendered from the `aws-load-balancer-controller` chart:
```yaml
releases:
- name:"aws-load-balancer-controller"
namespace:"kube-system"
forceNamespace:"kube-system"
chart:"center/aws/aws-load-balancer-controller"
transformers:
- apiVersion:builtin
kind:AnnotationsTransformer
metadata:
name:notImportantHere
annotations:
area:51
greeting:take me to your leader
fieldSpecs:
- path:metadata/annotations
create:true
- apiVersion:builtin
kind:LabelTransformer
metadata:
name:notImportantHere
labels:
foo:bar
fieldSpecs:
- path:metadata/labels
create:true
```
As explained earlier, `transformers` can be not only a list of embedded transformers, but also YAML or Go template files, or a mix of those three kinds.
```yaml
transformers:
# Embedded transformer
- apiVersion:builtin
kind:AnnotationsTransformer
metadata:
name:notImportantHere
annotations:
area:51
greeting:take me to your leader
fieldSpecs:
- path:metadata/annotations
create:true
# YAML file
- path/to/transformer.yaml
# Go template
# The same set of template parameters as release values files templates is available.
- path/to/transformer.yaml.gotmpl
```
Please see https://github.com/kubernetes-sigs/kustomize/blob/master/examples/configureBuiltinPlugin.md#configuring-the-builtin-plugins-instead for more information on how to declare transformers.
### Adding dependencies without forking the chart
With Helmfile, you can add chart dependencies to a Helm chart without forking it.
An example `helmfile.yaml` that adds a `stable/envoy` dependency to the release `foo` looks like the below:
```yaml
repositories:
- name:stable
url:https://charts.helm.sh/stable
releases:
- name:foo
chart:./path/to/foo
dependencies:
- chart:stable/envoy
version:1.5
```
When Helmfile encounters `releases[].dependencies`, it creates another temporary chart from `./path/to/foo` and adds the following `dependencies` to the `Chart.yaml`, so that you don't need to fork the chart.
```yaml
dependencies:
- name:envoy
repo:https://charts.helm.sh/stable
condition:envoy.enabled
```
A Helm chart can have two or more dependencies for the same chart with different `alias`es. To give your dependency an `alias`, define it like you would do in a standard `Chart.yaml`:
```yaml
repositories:
- name:stable
url:https://charts.helm.sh/stable
releases:
- name:foo
chart:./path/to/foo
dependencies:
- chart:stable/envoy
version:1.5
alias:bar
- chart:stable/envoy
version:1.5
alias:baz
```
which will tweaks the temporary chart's `Chart.yaml` to have:
```yaml
dependencies:
- alias:bar
name:envoy
repo:https://charts.helm.sh/stable
condition:bar.enabled
- alias:baz
name:envoy
repo:https://charts.helm.sh/stable
condition:baz.enabled
```
Please see #649 for more context around this feature.
After the support for adhoc dependency to local chart (#1765),
you can even write local file paths relative to `helmfile.yaml` in `chart`:
```yaml
releases:
- name:foo
chart:./path/to/foo
dependencies:
- chart:./path/to/bar
```
Internally, Helmfile creates another temporary chart from the local chart `./path/to/foo`, and modifies the chart's `Chart.yaml` dependencies to look like:
```yaml
dependencies:
- alias:bar
name:bar
repo:file:///abs/path/to/bar
condition:bar.enabled
```
Please read https://github.com/roboll/helmfile/issues/1762#issuecomment-816341251 for more details.
#### OCI chart dependencies
With Helmfile version v0.146.0 or later, you can add OCI chart to chart dependencies.
An example `helmfile.yaml` that adds a OCI chart dependency to the release `foo` looks like the below:
```yaml
releases:
- name:foo
chart:./path/to/foo
dependencies:
- chart:oci://my-oci-registry/helm-repo/envoy
version:1.5
```
### Lockfile per environment
In some cases it can be handy for CI/CD pipelines to be able to roll out updates gradually for environments, such as staging and production while using the same
set of charts. This can be achieved by using `lockFilePath` in combination with environments, such as:
Using manifest files in conjunction with command line argument can be a bit confusing.
# Paths Overview
A few rules to clear up this ambiguity:
Using manifest files in conjunction with command line argument can be abit confusing.
A few rules to clear up this ambiguity:
- Absolute paths are always resolved as absolute paths
- Relative paths referenced *in* the helmfile manifest itself are relative to that manifest
- Relative paths referenced on the command line are relative to the current working directory the user is in
- Relative paths referenced from within the helmfile loaded from the standard input using `helmfile -f -` are relative to the current working directory
### Examples
There are several examples that we can go through in the `/examples` folder which demonstrate this.
There are several examples that we can go through in the [`/examples`](../examples/) folder which demonstrate this.
**Local Execution**
This is an example of a Helmfile manifest referencing a local value directly.
This is an example of a Helmfile manifest referencing a local value directly.
**Relative Paths in Helmfile w/ --values overrides**
This is an example of a Helmfile manifest using relative paths for values including an additional `--values` from the command line.
This is an example of a Helmfile manifest using relative paths for values including an additional `--values` from the command line.
NOTE: The `--values` is resolved relative to the CWD of the terminal *not* the Helmfile manifest. You can see this with the `replicas` being adjusted to 3 now for the deployment.
I'd like to make 3 breaking changes to Helmfile and mark it as 1.0, so that we can better communicate with the current and future Helmfile users about our stance on maintaining Helmfile.
Note that every breaking change should have an easy alternative way to achieve the same goal achieved using the removed functionality.
## The changes in 1.0
1. [Forbid the use of `environments` and `releases` within a single helmfile.yaml.gotmpl part](#forbid-the-use-of-environments-and-releases-within-a-single-helmfileyamlgotmpl-part)
2. [Force `.gotmpl` file extension for `helmfile.yaml` in case you want helmfile to render it as a go template before yaml parsing.](#force-gotmpl-file-extension-for-helmfileyaml-in-case-you-want-helmfile-to-render-it-as-a-go-template-before-yaml-parsing)
3. [Remove the `--args` flag from the `helmfile` command](#remove-the---args-flag-from-the-helmfile-command)
4. [Remove `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` in favor of `HELMFILE_DISABLE_INSECURE_FEATURES`](#remove-helmfile_skip_insecure_template_functions-in-favor-of-helmfile_disable_insecure_features)
5. [The long deprecated `charts.yaml` has been finally removed](#the-long-deprecated-chartsyaml-has-been-finally-removed)
### Forbid the use of `environments` and `releases` within a single helmfile.yaml.gotmpl part
- Helmfile currently relies on a hack called "double rendering" which no one understands correctly (I suppose) to solve the chicken-and-egg problem of rendering the helmfile template(which requires helmfile to parse `environments` as yaml first) and parsing the rendered helmfile as yaml(which requires helmfile to render the template first).
- By forcing (or print a big warning) the user to do separate helmfile parts for `environments` and `releases`, it's very unlikely Helmfile needs double-rendering at all.
- After this change, every helmfile.yaml written this way:
environments:
default:
values:
- foo: bar
releases:
- name: myapp
chart: charts/myapp
values:
- {{ .Values | toYaml | nindent 4 }}
must be rewritten like:
environments:
default:
values:
- foo: bar
---
releases:
- name: myapp
chart: charts/myapp
values:
- {{ .Values | toYaml | nindent 4 }}
It might not be a deal breaker as you already had to separate helmfile parts when you need to generate `environments` dynamically:
environments:
default:
values:
- foo: bar
---
environments:
default:
values:
- {{ .Values | toYaml | nindent 6}}}
- bar: baz
---
releases:
- name: myapp
chart: charts/myapp
values:
- {{ .Values | toYaml | nindent 4 }}
If you're already using any helmfile.yaml files that are written in the first style, do start using `---` today! It will probably reveal and fix unintended template evaluations. If you start using `---` today, you won't need to do anything after Helmfile 1.0.
### Force `.gotmpl` file extension for `helmfile.yaml` in case you want helmfile to render it as a go template before yaml parsing.
- As the primary maintainer of the project, I'm tired of explaining why Helmfile renders go template expressions embedded in a yaml comment. [The latest example of it](https://github.com/helmfile/helmfile/issues/127).
- When we first introduced helmfile the ability to render helmfile.yaml as a go template, I did propose it to require `.gotmpl` file extension to enable the feature. But none of active helmfile users and contributors at that time agreed with it (although I didn't have a very strong opinion on the matter either), so we enabled it without the extension. I consider it as a tech debt now.
### Remove the `--args` flag from the `helmfile` command
- It has been provided as-is, and never intended to work reliably because it's fundamentally flawed because we have no way to specify which args to be passed to which `helm` commands being called by which `helmfile` command.
- However, I periodically see a new user finds it's not working and reporting it as a bug([the most recent example](https://github.com/roboll/helmfile/issues/2034#issuecomment-1147059088)). It's not a fault of the user. It's our fault that left this broken feature.
- Every use-case previsouly covered (by any chance) with `--args` should be covered in new `helmfile.yaml` fields or flags.
### Remove `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` in favor of `HELMFILE_DISABLE_INSECURE_FEATURES`
- This option didn't make much sense in practice. Generally, you'd want to disable all the insecure features altogether to make your deployment secure, or not disable any features. Disabling all is already possible via `HELMFILE_DISABLE_INSECURE_FEATURES `. In addition, `HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS` literally made every insecure template function to silently skipped without any error or warning, which made debugging unnecessarily hard when the user accidentally used an insecure function.
- See https://github.com/helmfile/helmfile/pull/564 for more context.
### The long deprecated `charts.yaml` has been finally removed
Helmfile used to load `helmfile.yaml` or `charts.yaml` when you omitted the `-f` flag. `charts.yaml` has been deprecated for a long time but never been removed. We take v1 as a chance to finally remove it.
## After 1.0
We won't add any backward-incompatible changes while in 1.x, as long as it's inevitable to fix unseen important bug(s).
We also quit saying [Helmfile is in its early days](https://github.com/helmfile/helmfile#status) in your README as... it's just untrue today.
The `env` function allows you to declare a particular environment variable as an optional for template rendering.
If the environment variable is unset or empty, the template rendering will continue with an empty string as a value.
```yaml
{{ $envValue := env "envName" }}
```
#### `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.
```yaml
{{ $envValue := requiredEnv "envName" }}
```
> If the environment variable value starts with '/' (forward slash) and [Git for Windows](https://git-scm.com/download/win) is used, you must set `MSYS_NO_PATHCONV=1` to preserve values as-is, or the environment variable value will be prefixed with the `C:\Program Files\Git`. [reference](https://github.com/git-for-windows/build-extra/blob/main/ReleaseNotes.md#known-issues)
#### `exec`
The `exec` function allows you to run a command, returning the stdout of the command. When the command fails, the template rendering will fail with an error message.
The `envExec` function allows you to run a command with environment variables declared on-the-fly in addition to existing environment variables, returning the stdout of the command. When the command fails, the template rendering will fail with an error message.
The `isFile` function allows you to check if a file exists. On failure, the template rendering will fail with an error message.
```yaml
{{ if isFile "./myfile" }}
```
#### `readFile`
The `readFile` function allows you to read a file and return its content as the function output. On failure, the template rendering will fail with an error message.
```yaml
{{ $fileContent := readFile "./myfile" }}
```
#### `readDir`
The `readDir` function returns a list of the relative paths to the files contained within the directory. (No folders included. Use `readDirEntries` if you need folders too)
```yaml
{{ range $index,$item := readDir "./testdata/tmpl/sample_folder/" }}
{{- $itemSplit := splitList "/" $item -}}
{{- if contains "\\" $item -}}
{{- $itemSplit = splitList "\\" $item -}}
{{- end -}}
{{- $itemValue := $itemSplit | last -}}
{{- $itemValue -}}
{{- end -}}
```
#### `readDirEntries`
The `readDirEntries` function returns a list of [DirEntry](https://pkg.go.dev/os#DirEntry) contained within the directory
```yaml
{{ range $index,$item := readDirEntries "./testdata/tmpl/sample_folder/" }}
{{- if $item.IsDir -}}
{{- $item.Name -}}
{{- end -}}
{{- end -}}
```
#### `toYaml`
The `toYaml` function allows you to convert a value to YAML string. When has failed, the template rendering will fail with an error message.
```yaml
{{ $yaml := $value | toYaml }}
```
#### `fromYaml`
The `fromYaml` function allows you to convert a YAML string to a value. When has failed, the template rendering will fail with an error message.
```yaml
{{ $value := $yamlString | fromYaml }}
```
#### `setValueAtPath`
The `setValueAtPath` function allows you to set a value at a path. When has failed, the template rendering will fail with an error message.
The `get` function allows you to get a value at a path. you can set a default value when the path is not found. When has failed, the template rendering will fail with an error message.
```yaml
{{ $Getvalue := $value | get "path.key" "defaultValue" }}
```
#### `getOrNil`
The `getOrNil` function allows you to get a value at a path. it will return nil when the value of path is not found. When has failed, the template rendering will fail with an error message.
The `required` function returns the second argument as-is only if it is not empty. If empty, the template rendering will fail with an error message containing the first argument.
```yaml
{{ $requiredValue := $value | required "value not set" }}
```
#### `fetchSecretValue`
The `fetchSecretValue` function parses the argument as a [vals](https://github.com/helmfile/vals) ref URL, retrieves and returns the remote secret value referred by the URL. In case it failed to access the remote secret backend for whatever reason or the URL was invalid, the template rendering will fail with an error message.
The `expandSecretRefs` function takes an object as the argument and expands every [vals](https://github.com/helmfile/vals) secret reference URL embedded in the object's values. See ["Remote Secrets" page in our documentation](./remote-secrets.md) for more information.
The 'include' function allows including and rendering nested templates. The function returns the created template or an error if any occurred. It will load functions from `_*.tpl` files in the directory where the helmfile.yaml is located.
For nested helmfile.yaml files, it will load `_*.tpl` files in the directory where each nested helmfile.yaml is located. example: [include](https://github.com/helmfile/helmfile/tree/main/test/integration/test-cases/include-template-func/input)
waitTemplate: '{{`{{ eq .Release.Labels.tag "safe" | not }}`}}'
# ...
- `set` block values:
# ...
setTemplate:
- name: '{{`{{ .Release.Name }}`}}'
values: '{{`{{ .Release.Namespace }}`}}'
# ...
- `values` and `secrets` file paths:
# ...
valuesTemplate:
- config/{{`{{ .Release.Name }}`}}/values.yaml
secrets:
- config/{{`{{ .Release.Name }}`}}/secrets.yaml
# ...
- inline `values` map:
# ...
valuesTemplate:
- image:
tag: '{{`{{ .Release.Labels.tag }}`}}'
# ...
Previously, we've been using YAML anchors for release template inheritance.
It turned out not work well when you wanted to nest templates for complex use cases and/or you want a fine control over which fields to inherit or not.
Thus we added a new way for inheritance, which uses the `inherit` field we introduced above.
See [issue helmfile/helmfile#435](https://github.com/helmfile/helmfile/issues/435#issuecomment-1362177510) for more context.
You might also find [issue roboll/helmfile#428](https://github.com/roboll/helmfile/issues/428) useful for more context on how we originally designed the release template and what it's supposed to solve.
## Layering Release Values
@@ -135,13 +165,13 @@ Please note, that it is not possible to layer `values` sections. If `values` is
> See **Layering State Template Files** if you're layering templates.
You may occasionally end up with many helmfiles that shares common parts like which repositories to use, and whichi release to be bundled by default.
You may occasionally end up with many helmfiles that shares common parts like which repositories to use, and which release to be bundled by default.
Use Layering to extract the common parts into a dedicated *library helmfile*s, so that each helmfile becomes DRY.
Let's assume that your `helmfile.yaml` looks like:
```
```yaml
bases:
- environments.yaml
@@ -256,23 +286,23 @@ In the following example `helmfile.yaml.gotmpl`, each `---` separated part of th
`helmfile.yaml.gotmpl`:
```yaml
# Part 1: Reused Enviroment Values
# Part 1: Reused Environment Values
bases:
- myenv.yaml
---
# Part 2: Reused Defaults
bases:
- mydefaults.yaml
- mydefaults.yaml.gotmpl
---
# Part 3: Dynamic Releases
releases:
- name: test1
chart: mychart-{{ .Values.myname }}
values:
replicaCount: 1
image:
repository: "nginx"
tag: "latest"
- replicaCount: 1
image:
repository: "nginx"
tag: "latest"
```
Suppose the `myenv.yaml` and `test.env.yaml` loaded in the first part looks like:
@@ -301,7 +331,6 @@ Where the gotmpl file loaded in the second part looks like:
```yaml
helmDefaults:
tillerNamespace: kube-system
kubeContext: {{ .Values.kubeContext }}
verify: false
{{ if .Values.wait }}
@@ -314,13 +343,12 @@ helmDefaults:
force: true
```
Each go template is rendered in the context where `.Values` is inherited from the previous part.
Each go template is rendered in the context where `.Values` is inherited from the previous part.
So in `mydefaults.yaml.gotmpl`, both `.Values.kubeContext` and `.Values.wait` are valid as they do exist in the environment values inherited from the previous part(=the first part) of your `helmfile.yaml.gotmpl`, and therefore the template is rendered to:
```yaml
helmDefaults:
tillerNamespace: kube-system
kubeContext: test
verify: false
wait: false
@@ -341,7 +369,7 @@ releases:
image:
repository: "nginx"
tag: "latest"
````
```
hence rendered to:
@@ -356,3 +384,42 @@ releases:
repository: "nginx"
tag: "latest"
```
## Re-using environment state in sub-helmfiles
Do you want to decouple the environment state loading from the sub-helmfiles and load it only once?
This example shows how to do this:
```yaml
environments:
stage:
values:
- env/stage.yaml
prod:
values:
- env/prod.yaml
---
helmfiles:
- path: releases/myrelease/helmfile.yaml
values:
- {{ toYaml .Values | nindent 4 }}
# pass the current state values to the sub-helmfile
# add other values to use overlay logic here
```
and `releases/myrelease/helmfile.yaml` is as DRY as
```yaml
releases:
- name: mychart-{{ .Values.myrelease.myname }}
installed: {{ .Values | get "myrelease.enabled" false }}
chart: mychart
version: {{ .Values.myrelease.version }}
labels:
chart: mychart
values:
- values.yaml.gotmpl
# templated values would also inherit the values passed from upstream
This example is intended to show how you can use Helmfile with ArgoCD in a private way. The example deployment demonstrates how to deploy ArgoCD with the helmfile plugin, and how to use helmfile within ArgoCD to connect to various private external systems.
If you intend to follow this example, please pay close attention to the caveats. This chart will not work if you deploy it as-is, you will need to customise many parts of it to match the infrastructure of your organisation.
## What is the point of this chart?
There are many organisations out there which would like to widen Kubernetes adoption but struggle with the requirement to keep all data confidential and follow best practices. For example, one best practice is to to implement a CI/CD process for all deployments including Helm charts. As part of this process we may want to keep secrets in private Vault secret storage, use Helm charts from a private chart museum, customised Helm values from a private Git repository and docker images from a private docker repository. ArgoCD alone cannot do all of these things at once, but we can achieve this if we configure it with Helmfile.
This example is intended to show how you COULD use ArgoCD together with Helmfile to implement a fully private CI/CD system. Your deployment may be a litte bit different, or very different to this example. It's intended only as an example.
The helm chart in this repo can be deployed with Helmfile, if you follow the prerequisites. In order for the deployment to work correctly, you will need to follow the prerequisites and update all of the `values.yaml` file entries with a `# TODO` comment.
What are the interactions between the different systems?
* ArgoCD will run on Kubernetes. We must use a custom build of ArgoCD as the official build doesn't ship with the runtime binaries which we will need to execute Helmfile and interact with Vault.
* ArgoCD interacts with AzureAD for SSO. ArgoCD has to be configured as an enterprise app in Azure AD for authorization and authentication by an administrator. We put the client ID and client secrets into Vault for safe keeping.
* ArgoCD interacts with Vault in order to pull secrets for customising Helm deployments. Sometimes we need to inject secrets into the values.yaml file of a Helm deployment. ArgoCD will use an AppRole for authentication into Vault, and this is done once during the deployment. The ArgoCD Vault credentials are saved in Vault for safe keeping.
* ArgoCD may need to interact with a private Git server. This is so that ArgoCD can access the `helmfile.yaml` files before executing Helmfile. Additional configuration files (like `conf.d` and other `values.yaml`) files can be kept in here.
* ArgoCD will authenticate to a private chart museum. This is so that we can keep the private helm charts private.
# Prerequisites
##Docker image
* Build the docker image from the `argocd.dockerfile` file in this folder.
* Upload the image to your private docker registry and make a note of the registry URL and tag.
* Customise the `values.yaml` file in this folder.
Replace `argo-cd.global.image.repository` for the docker registry URL of your private registry.
Replace `argo-cd.global.image.tag` for the tag which you used to upload your private docker image.
## Configure Single Sign-On for ArgoCD
* Log into AzureAD as an administrator.
* Create a new App Registration in your tenant for ArgoCD.
* Create a new Client ID and client secret.
* Save the client ID and client secret into your vault server.
- Save the client ID and client secret into Vault. Suggested keys: `internal/argocd/auth#azure_oidc_client_id` and `internal/argocd/auth#azure_oidc_client_secret`.
* Update `values.yaml` for your deployment
- Update `argo-cd.server.config.oidc.config` - replace `SOME_AZURE_AD_TENANT` for your actual plaintext AzureAD tenant ID.
- Update `argo-cd.server.config.oidc.config` - replace `SOME_AZURE_AD_UUID` for your actual plaintext AzureAD client app ID.
- Verify that the Vault path specified in `argo-cd.config.secret.extra.oidc.azure.clientSecret` is the correct path in Vault.
* Customise the ingress objects in the source to match what your expected external URL will be. Update `values.yaml` to have the correct values for the hostname you plan to use.
- `argo-cd.config.server.(url|hostname)`
```yaml
url: 'https://my.argocd.deployment.org' # TODO
hostname: my.argocd.deployment.org #TODO
```
## Configure authentication from ArgoCD into Vault (or read next section on how to disable it)
* Read the documentation from Hashicorp on AppRoles. Provision a new AppRole for ArgoCD with policies.
- In the example the authentication path in Vault is assumed to be `auth/approle/login`. If that's not the case then update line 123 in `values.yaml`.
* Store the AppRole credentials for ArgoCD in Vault. We will use Helmfile to pull them from here when we launch the chart.
- Suggested paths: `internal/vault/argocd#role_id` and `internal/vault/argocd#secret_id`
* Verify that the Vault paths in `values.yaml` are correct
- `argo-cd.config.secret.extra.vault_role_id`
- `argo-cd.config.secret.extra.vault_secret_id`
* Replace `ROLE_ID` and `SECRET_ID` in `values.yaml` (line 124) with the actual plaintext values (values key `argocd.server.config.configManagementPlugins`). This is not 100% secure but was the only way that I could manage to get the rest of the deployment working. I advise you add `values.yaml` to `.gitignore` after doing this step.
## Disable Vault (optional)
If you are not going to use Vault, then you need to update the values to get your deployment to use Helmfile.
* If you are not going to use Vault, then remove the line in `values.yaml` that starts with `export VAULT_TOKEN=...`.
##Configure authentication from ArgoCD into private Git repository
* Create a new API user in your Git system (username + password auth). ArgoCD will use these credentials to pull `values.yaml` and `helmfile.yaml` for your project.
* Save the username and password into Vault
- Recommended keys: `internal/git/users/argocd#username` and `internal/git/users/argocd#password`
* Verify that the Vault paths in `values.yaml` are correct
- `argo-cd.config.secret.extra.git_username`
- `argo-cd.config.secret.extra.git_password`
* Update the settings in `values.yaml` for repositories - remove the example Git URLS and replace with actual Git URLs for your project.
## Configure authentication from ArgoCD to your private Docker registry and Chartmuseum
* This guide is written with Harbor in mind, which is both a docker registry and chart museum. If you have separate systems in place you might need to configure these things separately.
* Create a new set of credentials for Harbor and save them into Vault.
- If everything worked correctly, then ArgoCD should have deployed using your customised docker image into your cluster.
* If the ingress deployed correctly then we should be able to access the UI: https://my.argocd.deployment.org
* Grab the admin password from `argocd-initial-admin-secret secret` and use it to log into the UI.
```bash
echo "<password>" | base64 -d
```
* Verify that SSO works by signing on with AzureAD.
* Verify that Helmfile appears in the list of configured plugins in the UI.
# Configure ArgoCD apps for deployment with Helmfile
* Log into ArgoCD in the UI and configure a new app.
* Make sure that it's using the Helmfile plugin.
* For the source, select one of the Git repos which you configured previously.
* Make sure that your Helm repo (including `helmfile.yaml` is present in the Git repository).
* ArgoCD will pull the project from your private Git server and read the `helmfile.yaml` file.
* ArgoCD will also execute helmfile directly in the container using the files checked out from your project.
* If you configured ArgoCD with logins for Vault and private Chartmuseums, these can be used in ArgoCD by Helmfile.
* You can use the diff feature and resource views in ArgoCD when using Helmfile. Unfortunately you can no longer use the `values.yaml` editor in the UI. You can change `values.yaml` for deployments by creating `values.yaml` files and committing them to the folders in your project Git repo. You can also customise them using `!vault` tags.
If you would like an example, this ArgoCD + helmfile deployment can itself be deployed by ArgoCD + helmfile (you may need to drop the pods after you do deploy this way). Any other projects - just structure them in the same way as this example.
Be careful when reconfiguring a project which was previously deploy by ArgoCD with Helmfile. There are some differences around the way in which annotations are used.
labels:# Arbitrary key value pairs for filtering releases
env:prod
chart:"."# the chart being installed to create this release, referenced by `repository/chart` syntax
version:3.2.2# the semver of the chart. range constraint is supported
missingFileHandler:Warn# set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
# will attempt to decrypt secrets using helm-secrets plugin
Usage:"update charts based on the contents of requirements.yaml",
Flags:[]cli.Flag{
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.BoolFlag{
Name:"skip-repos",
Usage:"skip running `helm repo update` before running `helm dependency build`",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Deps(c)
}),
},
{
Name:"repos",
Usage:"sync repositories from state file (helm repo add && helm repo update)",
Flags:[]cli.Flag{
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Repos(c)
}),
},
{
Name:"charts",
Usage:"DEPRECATED: sync releases from state file (helm upgrade --install)",
Flags:[]cli.Flag{
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.DeprecatedSyncCharts(c)
}),
},
{
Name:"diff",
Usage:"diff releases from state file against env (helm diff)",
Flags:[]cli.Flag{
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.BoolFlag{
Name:"skip-deps",
Usage:"skip running `helm repo update` and `helm dependency build`",
},
cli.BoolFlag{
Name:"detailed-exitcode",
Usage:"return a non-zero exit code when there are changes",
},
cli.BoolFlag{
Name:"include-tests",
Usage:"enable the diffing of the helm test hooks",
},
cli.BoolFlag{
Name:"suppress-secrets",
Usage:"suppress secrets in the output. highly recommended to specify on CI/CD use-cases",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
cli.IntFlag{
Name:"context",
Value:0,
Usage:"output NUM lines of context around changes",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Diff(c)
}),
},
{
Name:"template",
Usage:"template releases from state file against env (helm template)",
Flags:[]cli.Flag{
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm template",
},
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.StringFlag{
Name:"output-dir",
Usage:"output directory to pass to helm template (helm template --output-dir)",
},
cli.StringFlag{
Name:"output-dir-template",
Usage:"go text template for generating the output directory. Default: {{ .OutputDir }}/{{ .State.BaseName }}-{{ .State.AbsPathSHA1 }}-{{ .Release.Name}}",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent downloads of release charts",
},
cli.BoolFlag{
Name:"validate",
Usage:"validate your manifests against the Kubernetes cluster you are currently pointing at",
},
cli.BoolFlag{
Name:"skip-deps",
Usage:"skip running `helm repo update` and `helm dependency build`",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Template(c)
}),
},
{
Name:"write-values",
Usage:"write values files for releases. Similar to `helmfile template`, write values files instead of manifests.",
Flags:[]cli.Flag{
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.StringFlag{
Name:"output-file-template",
Usage:"go text template for generating the output file. Default: {{ .State.BaseName }}-{{ .State.AbsPathSHA1 }}/{{ .Release.Name}}.yaml",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent downloads of release charts",
},
cli.BoolFlag{
Name:"skip-deps",
Usage:"skip running `helm repo update` and `helm dependency build`",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.WriteValues(c)
}),
},
{
Name:"lint",
Usage:"lint charts from state file (helm lint)",
Flags:[]cli.Flag{
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent downloads of release charts",
},
cli.BoolFlag{
Name:"skip-deps",
Usage:"skip running `helm repo update` and `helm dependency build`",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Lint(c)
}),
},
{
Name:"sync",
Usage:"sync all resources from state file (repos, releases and chart deps)",
Flags:[]cli.Flag{
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.BoolFlag{
Name:"skip-deps",
Usage:"skip running `helm repo update` and `helm dependency build`",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Sync(c)
}),
},
{
Name:"apply",
Usage:"apply all resources from state file only when there are changes",
Flags:[]cli.Flag{
cli.StringSliceFlag{
Name:"set",
Usage:"additional values to be merged into the command",
},
cli.StringSliceFlag{
Name:"values",
Usage:"additional value files to be merged into the command",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
cli.IntFlag{
Name:"context",
Value:0,
Usage:"output NUM lines of context around changes",
},
cli.BoolFlag{
Name:"detailed-exitcode",
Usage:"return a non-zero exit code 2 instead of 0 when there were changes detected AND the changes are synced successfully",
},
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.BoolFlag{
Name:"retain-values-files",
Usage:"Stop cleaning up values files passed to Helm. Together with --log-level=debug, you can manually rerun helm commands as Helmfile did for debugging purpose",
},
cli.BoolFlag{
Name:"include-tests",
Usage:"enable the diffing of the helm test hooks",
},
cli.BoolFlag{
Name:"suppress-secrets",
Usage:"suppress secrets in the diff output. highly recommended to specify on CI/CD use-cases",
},
cli.BoolFlag{
Name:"suppress-diff",
Usage:"suppress diff in the output. Usable in new installs",
},
cli.BoolFlag{
Name:"skip-deps",
Usage:"skip running `helm repo update` and `helm dependency build`",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Apply(c)
}),
},
{
Name:"status",
Usage:"retrieve status of releases in state file",
Flags:[]cli.Flag{
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Status(c)
}),
},
{
Name:"delete",
Usage:"DEPRECATED: delete releases from state file (helm delete)",
Flags:[]cli.Flag{
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
cli.BoolFlag{
Name:"purge",
Usage:"purge releases i.e. free release names and histories",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Delete(c)
}),
},
{
Name:"destroy",
Usage:"deletes and then purges releases",
Flags:[]cli.Flag{
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass args to helm exec",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Destroy(c)
}),
},
{
Name:"test",
Usage:"test releases from state file (helm test)",
Flags:[]cli.Flag{
cli.BoolFlag{
Name:"cleanup",
Usage:"delete test pods upon completion",
},
cli.StringFlag{
Name:"args",
Value:"",
Usage:"pass additional args to helm exec",
},
cli.IntFlag{
Name:"timeout",
Value:300,
Usage:"maximum time for tests to run before being considered failed",
},
cli.IntFlag{
Name:"concurrency",
Value:0,
Usage:"maximum number of concurrent helm processes to run, 0 is unlimited",
},
},
Action:action(func(run*app.App,cconfigImpl)error{
returnrun.Test(c)
}),
},
{
Name:"build",
Usage:"output compiled helmfile state(s) as YAML",
Flags:[]cli.Flag{
cli.BoolFlag{
Name:"embed-values",
Usage:"Read all the values files for every release and embed into the output helmfile.yaml",
t.Run("fail on unselected need by default",func(t*testing.T){
check(t,testcase{
selectors:[]string{"app=test"},
error:`in ./helmfile.yaml: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
t.Fatalf("unable to update lint log snapshot: %v",err)
}
}
assert.Equal(t,wantLog,gotLog)
}
t.Run("fail on unselected need by default",func(t*testing.T){
check(t,testcase{
selectors:[]string{"app=test"},
error:`in ./helmfile.yaml: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
t.Fatalf("unable to update lint log snapshot: %v",err)
}
}
assert.Equal(t,wantLog,gotLog)
}
t.Run("fail on unselected need by default",func(t*testing.T){
check(t,testcase{
selectors:[]string{"app=test"},
error:`in ./helmfile.yaml: release "default/default/external-secrets" depends on "default/kube-system/kubernetes-external-secrets" which does not match the selectors. Please add a selector like "--selector name=kubernetes-external-secrets", or indicate whether to skip (--skip-needs) or include (--include-needs) these dependencies`,
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.