diff --git a/cmd/apply.go b/cmd/apply.go index 8ad850e5..7e71482b 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewApplyCmd returm apply subcmd +// NewApplyCmd returns apply subcmd func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command { applyOptions := &config.ApplyOptions{} applyImpl := config.NewApplyImpl(globalCfg, applyOptions) diff --git a/cmd/build.go b/cmd/build.go index b21bec48..44e9cd2e 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewBuildCmd returm build subcmd +// NewBuildCmd returns build subcmd func NewBuildCmd(globalCfg *config.GlobalImpl) *cobra.Command { buildOptions := config.NewBuildOptions() buildImpl := config.NewBuildImpl(globalCfg, buildOptions) diff --git a/cmd/cache.go b/cmd/cache.go index 3ccd9234..ab7e3bd6 100644 --- a/cmd/cache.go +++ b/cmd/cache.go @@ -49,7 +49,7 @@ func NewCacheCleanupSubcommand(cacheImpl *config.CacheImpl) *cobra.Command { return cmd } -// NewCacheCmd returm cache subcmd +// NewCacheCmd returns cache subcmd func NewCacheCmd(globalCfg *config.GlobalImpl) *cobra.Command { cacheOptions := config.NewCacheOptions() cacheImpl := config.NewCacheImpl(globalCfg, cacheOptions) diff --git a/cmd/charts.go b/cmd/charts.go index dd2853c5..5e9457f7 100644 --- a/cmd/charts.go +++ b/cmd/charts.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewChartsCmd returm build subcmd +// NewChartsCmd returns charts subcmd func NewChartsCmd(globalCfg *config.GlobalImpl) *cobra.Command { chartsOptions := config.NewChartsOptions() chartsImpl := config.NewChartsImpl(globalCfg, chartsOptions) diff --git a/cmd/delete.go b/cmd/delete.go index 0d8dd940..89ab2aa8 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewDeleteCmd returm build subcmd +// NewDeleteCmd returns delete subcmd func NewDeleteCmd(globalCfg *config.GlobalImpl) *cobra.Command { deleteOptions := config.NewDeleteOptions() deleteImpl := config.NewDeleteImpl(globalCfg, deleteOptions) diff --git a/cmd/deps.go b/cmd/deps.go index ac1d1da0..690e4b8d 100644 --- a/cmd/deps.go +++ b/cmd/deps.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewDepsCmd returm build subcmd +// NewDepsCmd returns deps subcmd func NewDepsCmd(globalCfg *config.GlobalImpl) *cobra.Command { depsOptions := config.NewDepsOptions() depsImpl := config.NewDepsImpl(globalCfg, depsOptions) diff --git a/cmd/destroy.go b/cmd/destroy.go index b4d86346..523d9706 100644 --- a/cmd/destroy.go +++ b/cmd/destroy.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewDestroyCmd returm build subcmd +// NewDestroyCmd returns destroy subcmd func NewDestroyCmd(globalCfg *config.GlobalImpl) *cobra.Command { destroyOptions := config.NewDestroyOptions() destroyImpl := config.NewDestroyImpl(globalCfg, destroyOptions) diff --git a/cmd/diff.go b/cmd/diff.go index 2ce323bf..5633db1e 100644 --- a/cmd/diff.go +++ b/cmd/diff.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewDiffCmd returm build subcmd +// NewDiffCmd returns diff subcmd func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command { diffOptions := config.NewDiffOptions() diffImpl := config.NewDiffImpl(globalCfg, diffOptions) diff --git a/cmd/fetch.go b/cmd/fetch.go index 66c922e6..8c4bcb0b 100644 --- a/cmd/fetch.go +++ b/cmd/fetch.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewFetchCmd returm build subcmd +// NewFetchCmd returns diff subcmd func NewFetchCmd(globalCfg *config.GlobalImpl) *cobra.Command { fetchOptions := config.NewFetchOptions() fetchImpl := config.NewFetchImpl(globalCfg, fetchOptions) diff --git a/cmd/lint.go b/cmd/lint.go index f8d4a64f..40100a73 100644 --- a/cmd/lint.go +++ b/cmd/lint.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewLintCmd returm build subcmd +// NewLintCmd returns lint subcmd func NewLintCmd(globalCfg *config.GlobalImpl) *cobra.Command { lintOptions := config.NewLintOptions() lintImpl := config.NewLintImpl(globalCfg, lintOptions) @@ -35,6 +35,9 @@ func NewLintCmd(globalCfg *config.GlobalImpl) *cobra.Command { f.StringVar(&lintOptions.Args, "args", "", "pass args to helm exec") f.StringArrayVar(&lintOptions.Set, "set", nil, "additional values to be merged into the command") f.StringArrayVar(&lintOptions.Values, "values", nil, "additional value files to be merged into the command") + f.BoolVar(&lintOptions.SkipNeeds, "skip-needs", false, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when 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 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 when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`) return cmd } diff --git a/cmd/list.go b/cmd/list.go index 4b9197ef..63d1c95b 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewListCmd returm build subcmd +// NewListCmd returns list subcmd func NewListCmd(globalCfg *config.GlobalImpl) *cobra.Command { listOptions := config.NewListOptions() listImpl := config.NewListImpl(globalCfg, listOptions) diff --git a/cmd/repos.go b/cmd/repos.go index c67300d2..2d3563a6 100644 --- a/cmd/repos.go +++ b/cmd/repos.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewReposCmd returm build subcmd +// NewReposCmd returns repos subcmd func NewReposCmd(globalCfg *config.GlobalImpl) *cobra.Command { reposOptions := config.NewReposOptions() reposImpl := config.NewReposImpl(globalCfg, reposOptions) diff --git a/cmd/status.go b/cmd/status.go index 32b5fa79..1414ce60 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewStatusCmd returm build subcmd +// NewStatusCmd returns status subcmd func NewStatusCmd(globalCfg *config.GlobalImpl) *cobra.Command { statusOptions := config.NewStatusOptions() statusImpl := config.NewStatusImpl(globalCfg, statusOptions) diff --git a/cmd/sync.go b/cmd/sync.go index adc6e920..95e7930b 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewSyncCmd returm build subcmd +// NewSyncCmd returns sync subcmd func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command { syncOptions := config.NewSyncOptions() syncImpl := config.NewSyncImpl(globalCfg, syncOptions) diff --git a/cmd/template.go b/cmd/template.go index 08444fc1..384fa305 100644 --- a/cmd/template.go +++ b/cmd/template.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewTemplateCmd returm build subcmd +// NewTemplateCmd returm template subcmd func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command { templateOptions := config.NewTemplateOptions() templateImpl := config.NewTemplateImpl(globalCfg, templateOptions) diff --git a/cmd/test.go b/cmd/test.go index 91112273..efd466b7 100644 --- a/cmd/test.go +++ b/cmd/test.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewTestCmd returm build subcmd +// NewTestCmd returns test subcmd func NewTestCmd(globalCfg *config.GlobalImpl) *cobra.Command { testOptions := config.NewTestOptions() testImpl := config.NewTestImpl(globalCfg, testOptions) diff --git a/cmd/version.go b/cmd/version.go index 3910437b..b2961430 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" ) -// NewVersionCmd returm build subcmd +// NewVersionCmd returns version subcmd func NewVersionCmd() *cobra.Command { cmd := &cobra.Command{ Use: "version", diff --git a/cmd/write-values.go b/cmd/write-values.go index be44f755..f00c624d 100644 --- a/cmd/write-values.go +++ b/cmd/write-values.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" ) -// NewWriteValuesCmd returm build subcmd +// NewWriteValuesCmd returns write subcmd func NewWriteValuesCmd(globalCfg *config.GlobalImpl) *cobra.Command { writeValuesOptions := config.NewWriteValuesOptions() writeValuesImpl := config.NewWriteValuesImpl(globalCfg, writeValuesOptions) diff --git a/docs/index.md b/docs/index.md index f43d48b9..6426b36d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -456,6 +456,10 @@ Let's start with a simple `helmfile` and gradually improve it to fit your use-ca Suppose the `helmfile.yaml` representing the desired state of your helm releases looks like: ```yaml +repositories: + - name: prometheus-community + url: https://prometheus-community.github.io/helm-charts + releases: - name: prom-norbac-ubuntu namespace: prometheus @@ -489,7 +493,7 @@ USAGE: helmfile [global options] command [command options] [arguments...] VERSION: - v0.138.6 + 0.145.2 COMMANDS: deps update charts based on their requirements @@ -499,6 +503,7 @@ COMMANDS: template template releases from state file against env (helm template) write-values write values files for releases. Similar to `helmfile template`, write values files instead of manifests. lint lint charts from state file (helm lint) + fetch fetch charts from state file sync sync all resources from state file (repos, releases and chart deps) apply apply all resources from state file only when there are changes status retrieve status of releases in state file @@ -507,7 +512,7 @@ COMMANDS: test test releases from state file (helm test) build output compiled helmfile state(s) as YAML list list releases defined in state file - fetch fetch charts from state file + cache cache management version Show the version for Helmfile. help, h Shows a list of commands or help for one command @@ -520,9 +525,11 @@ GLOBAL OPTIONS: --quiet, -q Silence output. Equivalent to log-level warn --kube-context value Set kubectl context. Uses current context by default --debug Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect + --color Output with color --no-color Output without color --log-level value Set log level, default info --namespace value, -n value Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }} + --chart value, -c value Set chart. Uses the chart set in release by default, and is available in template as {{ .Chart }} --selector value, -l value 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. diff --git a/go.mod b/go.mod index d1f1d4fa..6652c7ce 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 gopkg.in/yaml.v2 v2.4.0 gotest.tools v2.2.0+incompatible - k8s.io/apimachinery v0.23.4 + k8s.io/apimachinery v0.24.3 ) require ( @@ -133,7 +133,7 @@ require ( gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/urfave/cli.v1 v1.20.0 // indirect gopkg.in/yaml.v3 v3.0.1 - sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect + sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) @@ -195,9 +195,9 @@ require ( k8s.io/api v0.23.4 // indirect k8s.io/cli-runtime v0.23.4 // indirect k8s.io/client-go v0.23.4 // indirect - k8s.io/klog/v2 v2.30.0 // indirect - k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect - k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect + k8s.io/klog/v2 v2.60.1 // indirect + k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect + k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect oras.land/oras-go v1.1.0 // indirect sigs.k8s.io/kustomize/api v0.10.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect diff --git a/go.sum b/go.sum index ad83db5c..d1655830 100644 --- a/go.sum +++ b/go.sum @@ -203,6 +203,7 @@ github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -619,6 +620,8 @@ github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/cel-go v0.9.0/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -1974,8 +1977,9 @@ k8s.io/apiextensions-apiserver v0.23.4/go.mod h1:TWYAKymJx7nLMxWCgWm2RYGXHrGlVZn k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.23.4 h1:fhnuMd/xUL3Cjfl64j5ULKZ1/J9n8NuQEgNL+WXWfdM= k8s.io/apimachinery v0.23.4/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= +k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= +k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= @@ -2005,20 +2009,23 @@ k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAE k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw= k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= +k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4= k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kubectl v0.23.4/go.mod h1:Dgb0Rvx/8JKS/C2EuvsNiQc6RZnX0SbHJVG3XUzH6ok= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/metrics v0.23.4/go.mod h1:cl6sY9BdVT3DubbpqnkPIKi6mn/F2ltkU4yH1tEJ3Bo= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20211116205334-6203023598ed h1:ck1fRPWPJWsMd8ZRFsWc6mh/zHp5fZ/shhbrgPUxDAE= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= oras.land/oras-go v1.1.0 h1:tfWM1RT7PzUwWphqHU6ptPU3ZhwVnSw/9nEGf519rYg= oras.land/oras-go v1.1.0/go.mod h1:1A7vR/0KknT2UkJVWh+xMi95I/AhK8ZrxrnUSmXN0bQ= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= @@ -2027,8 +2034,9 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27/go.mod h1:tq2nT0Kx7W+/f2JVE+zxYtUhdjuELJkVpNz+x/QN5R4= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/kustomize/api v0.10.1 h1:KgU7hfYoscuqag84kxtzKdEC3mKMb99DPI3a0eaV1d0= sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8= sigs.k8s.io/kustomize/cmd/config v0.10.2/go.mod h1:K2aW7nXJ0AaT+VA/eO0/dzFLxmpFcTzudmAgDwPY1HQ= diff --git a/pkg/app/diff_test.go b/pkg/app/diff_test.go index 7f22edb4..5302bae7 100644 --- a/pkg/app/diff_test.go +++ b/pkg/app/diff_test.go @@ -160,6 +160,7 @@ func TestDiff(t *testing.T) { upgraded []exectest.Release deleted []exectest.Release log string + overrideContext string }{ // // complex test cases for smoke testing @@ -341,6 +342,58 @@ releases: }, upgraded: []exectest.Release{}, }, + { + name: "upgrade when foo needs bar with context override", + loc: location(), + overrideContext: "hello/world", + files: map[string]string{ + "/path/to/helmfile.yaml": ` +helmDefaults: + kubeContext: hello/world +releases: +- name: bar + chart: mychart2 +- name: foo + chart: mychart1 + needs: + - bar +`, + }, + detailedExitcode: true, + error: "Identified at least one change", + diffs: map[exectest.DiffKey]error{ + {Name: "bar", Chart: "mychart2", Flags: "--kube-contexthello/world--detailed-exitcode"}: helmexec.ExitError{Code: 2}, + {Name: "foo", Chart: "mychart1", Flags: "--kube-contexthello/world--detailed-exitcode"}: helmexec.ExitError{Code: 2}, + }, + upgraded: []exectest.Release{}, + }, + { + name: "upgrade when releaseB needs releaseA with AWS context", + loc: location(), + overrideContext: "arn:aws:eks:us-east-1:1234567890:cluster/myekscluster", + files: map[string]string{ + "/path/to/helmfile.yaml": ` +releases: +- name: releaseA + chart: mychart1 + namespace: namespaceA + kubeContext: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster +- name: releaseB + chart: mychart2 + namespace: namespaceA + kubeContext: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster + needs: + - arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseA +`, + }, + detailedExitcode: true, + error: "Identified at least one change", + diffs: map[exectest.DiffKey]error{ + {Name: "releaseB", Chart: "mychart2", Flags: "--kube-contextarn:aws:eks:us-east-1:1234567890:cluster/myekscluster--namespacenamespaceA--detailed-exitcode"}: helmexec.ExitError{Code: 2}, + {Name: "releaseA", Chart: "mychart1", Flags: "--kube-contextarn:aws:eks:us-east-1:1234567890:cluster/myekscluster--namespacenamespaceA--detailed-exitcode"}: helmexec.ExitError{Code: 2}, + }, + upgraded: []exectest.Release{}, + }, { name: "upgrade when bar needs foo", loc: location(), @@ -1291,15 +1344,20 @@ changing working directory back to "/path/to" t.Errorf("unexpected error creating vals runtime: %v", err) } + overrideKubeContext := "default" + if tc.overrideContext != "" { + overrideKubeContext = tc.overrideContext + } + app := appWithFs(&App{ OverrideHelmBinary: DefaultHelmBinary, glob: filepath.Glob, abs: filepath.Abs, - OverrideKubeContext: "default", + OverrideKubeContext: overrideKubeContext, Env: "default", Logger: logger, helms: map[helmKey]helmexec.Interface{ - createHelmKey("helm", "default"): helm, + createHelmKey("helm", overrideKubeContext): helm, }, valsRuntime: valsRuntime, }, tc.files) diff --git a/pkg/app/testdata/app_diff_test_1/upgrade_when_foo_needs_bar_with_context_override b/pkg/app/testdata/app_diff_test_1/upgrade_when_foo_needs_bar_with_context_override new file mode 100644 index 00000000..5756135c --- /dev/null +++ b/pkg/app/testdata/app_diff_test_1/upgrade_when_foo_needs_bar_with_context_override @@ -0,0 +1,50 @@ +processing file "helmfile.yaml" in directory "." +changing working directory to "/path/to" +first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode= +first-pass uses: &{default map[] map[]} +first-pass rendering output of "helmfile.yaml.part.0": + 0: + 1: helmDefaults: + 2: kubeContext: hello/world + 3: releases: + 4: - name: bar + 5: chart: mychart2 + 6: - name: foo + 7: chart: mychart1 + 8: needs: + 9: - bar +10: + +first-pass produced: &{default map[] map[]} +first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]} +vals: +map[] +defaultVals:[] +second-pass rendering result of "helmfile.yaml.part.0": + 0: + 1: helmDefaults: + 2: kubeContext: hello/world + 3: releases: + 4: - name: bar + 5: chart: mychart2 + 6: - name: foo + 7: chart: mychart1 + 8: needs: + 9: - bar +10: + +merged environment: &{default map[] map[]} +2 release(s) found in helmfile.yaml + +processing 2 groups of releases in this order: +GROUP RELEASES +1 hello/world//bar +2 hello/world//foo + +processing releases in group 1/2: hello/world//bar +processing releases in group 2/2: hello/world//foo +Affected releases are: + bar (mychart2) UPDATED + foo (mychart1) UPDATED + +changing working directory back to "/path/to" diff --git a/pkg/app/testdata/app_diff_test_1/upgrade_when_releaseb_needs_releasea_with_aws_context b/pkg/app/testdata/app_diff_test_1/upgrade_when_releaseb_needs_releasea_with_aws_context new file mode 100644 index 00000000..8d994feb --- /dev/null +++ b/pkg/app/testdata/app_diff_test_1/upgrade_when_releaseb_needs_releasea_with_aws_context @@ -0,0 +1,54 @@ +processing file "helmfile.yaml" in directory "." +changing working directory to "/path/to" +first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default map[] map[]}, overrode= +first-pass uses: &{default map[] map[]} +first-pass rendering output of "helmfile.yaml.part.0": + 0: + 1: releases: + 2: - name: releaseA + 3: chart: mychart1 + 4: namespace: namespaceA + 5: kubeContext: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster + 6: - name: releaseB + 7: chart: mychart2 + 8: namespace: namespaceA + 9: kubeContext: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster +10: needs: +11: - arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseA +12: + +first-pass produced: &{default map[] map[]} +first-pass rendering result of "helmfile.yaml.part.0": {default map[] map[]} +vals: +map[] +defaultVals:[] +second-pass rendering result of "helmfile.yaml.part.0": + 0: + 1: releases: + 2: - name: releaseA + 3: chart: mychart1 + 4: namespace: namespaceA + 5: kubeContext: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster + 6: - name: releaseB + 7: chart: mychart2 + 8: namespace: namespaceA + 9: kubeContext: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster +10: needs: +11: - arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseA +12: + +merged environment: &{default map[] map[]} +2 release(s) found in helmfile.yaml + +processing 2 groups of releases in this order: +GROUP RELEASES +1 arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseA +2 arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseB + +processing releases in group 1/2: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseA +processing releases in group 2/2: arn:aws:eks:us-east-1:1234567890:cluster/myekscluster/namespaceA/releaseB +Affected releases are: + releaseA (mychart1) UPDATED + releaseB (mychart2) UPDATED + +changing working directory back to "/path/to" diff --git a/pkg/config/lint.go b/pkg/config/lint.go index 4017b2ae..17d1c299 100644 --- a/pkg/config/lint.go +++ b/pkg/config/lint.go @@ -12,6 +12,13 @@ type LintOptions struct { Set []string // Values is the values flags to pass to helm lint Values []string + // SkipNeeds is the skip needs flag + SkipNeeds bool + // IncludeNeeds is the include needs flag + IncludeNeeds bool + // IncludeTransitiveNeeds is the include transitive needs flag + IncludeTransitiveNeeds bool + // SkipDeps is the skip deps flag } // NewLintOptions creates a new Apply @@ -34,46 +41,50 @@ func NewLintImpl(g *GlobalImpl, b *LintOptions) *LintImpl { } // Concurrency returns the concurrency -func (c *LintImpl) Concurrency() int { - return c.LintOptions.Concurrency +func (l *LintImpl) Concurrency() int { + return l.LintOptions.Concurrency } // SkipDeps returns the skip deps -func (c *LintImpl) SkipDeps() bool { - return c.LintOptions.SkipDeps +func (l *LintImpl) SkipDeps() bool { + return l.LintOptions.SkipDeps } // Args returns the args -func (c *LintImpl) Args() string { - return c.LintOptions.Args +func (l *LintImpl) Args() string { + return l.LintOptions.Args } // Set returns the Set -func (c *LintImpl) Set() []string { - return c.LintOptions.Set +func (l *LintImpl) Set() []string { + return l.LintOptions.Set } // Values returns the Values -func (c *LintImpl) Values() []string { - return c.LintOptions.Values +func (l *LintImpl) Values() []string { + return l.LintOptions.Values } // SkipCleanUp returns the skip clean up -func (c *LintImpl) SkipCleanup() bool { - return false -} - -// SkipNeeds returns the skip needs -func (c *LintImpl) SkipNeeds() bool { +func (l *LintImpl) SkipCleanup() bool { return false } // IncludeNeeds returns the include needs -func (c *LintImpl) IncludeNeeds() bool { - return false +func (l *LintImpl) IncludeNeeds() bool { + return l.LintOptions.IncludeNeeds || l.LintOptions.IncludeTransitiveNeeds } // IncludeTransitiveNeeds returns the include transitive needs -func (c *LintImpl) IncludeTransitiveNeeds() bool { +func (l *LintImpl) IncludeTransitiveNeeds() bool { + return l.LintOptions.IncludeTransitiveNeeds +} + +// SkipNeeds returns the skip needs +func (l *LintImpl) SkipNeeds() bool { + if !l.LintOptions.IncludeNeeds { + return l.LintOptions.SkipNeeds + } + return false } diff --git a/pkg/state/state.go b/pkg/state/state.go index fbf84361..b50993ef 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -399,7 +399,9 @@ func (st *HelmState) ApplyOverrides(spec *ReleaseSpec) { } if len(components) > 2 { - kubecontext = components[len(components)-3] + // Join all ID components except last 2 (namespace and name) into kubecontext. + // Should be safe because resource names do not contain slashes. + kubecontext = strings.Join(components[:len(components)-2], "/") } else { kubecontext = spec.KubeContext }