parent
							
								
									cc13492623
								
							
						
					
					
						commit
						ac23def893
					
				|  | @ -0,0 +1,28 @@ | ||||||
|  | name: Lint | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: [ main ] | ||||||
|  |   pull_request: | ||||||
|  |     branches: [ main ] | ||||||
|  | 
 | ||||||
|  | env: | ||||||
|  |   GO_VERSION: 1.18 | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   lint: | ||||||
|  |     name: Lint | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     timeout-minutes: 10 | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/setup-go@v3 | ||||||
|  |         with: | ||||||
|  |           go-version: 1.18 | ||||||
|  | 
 | ||||||
|  |       - name: Checkout code | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  | 
 | ||||||
|  |       - name: Golangci lint | ||||||
|  |         uses: golangci/golangci-lint-action@v3 | ||||||
|  |         with: | ||||||
|  |           version: v1.46.2 | ||||||
|  | @ -0,0 +1,352 @@ | ||||||
|  | # This file contains all available configuration options | ||||||
|  | # with their default values. | ||||||
|  | 
 | ||||||
|  | # options for analysis running | ||||||
|  | run: | ||||||
|  |   # default concurrency is a available CPU number | ||||||
|  |   # concurrency: 4 | ||||||
|  | 
 | ||||||
|  |   # timeout for analysis, e.g. 30s, 5m, default is 1m | ||||||
|  |   timeout: 30m | ||||||
|  | 
 | ||||||
|  |   # exit code when at least one issue was found, default is 1 | ||||||
|  |   issues-exit-code: 1 | ||||||
|  | 
 | ||||||
|  |   # include test files or not, default is true | ||||||
|  |   tests: true | ||||||
|  | 
 | ||||||
|  |   # list of build tags, all linters use it. Default is empty list. | ||||||
|  |   # build-tags: | ||||||
|  |   #   - mytag | ||||||
|  | 
 | ||||||
|  |   # which dirs to skip: issues from them won't be reported; | ||||||
|  |   # can use regexp here: generated.*, regexp is applied on full path; | ||||||
|  |   # default value is empty list, but default dirs are skipped independently | ||||||
|  |   # from this option's value (see skip-dirs-use-default). | ||||||
|  |   # skip-dirs: | ||||||
|  |   #   - src/external_libs | ||||||
|  |   #   - autogenerated_by_my_lib | ||||||
|  | 
 | ||||||
|  |   # default is true. Enables skipping of directories: | ||||||
|  |   #   vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ | ||||||
|  |   skip-dirs-use-default: true | ||||||
|  | 
 | ||||||
|  |   # which files to skip: they will be analyzed, but issues from them | ||||||
|  |   # won't be reported. Default value is empty list, but there is | ||||||
|  |   # no need to include all autogenerated files, we confidently recognize | ||||||
|  |   # autogenerated files. If it's not please let us know. | ||||||
|  |   # skip-files: | ||||||
|  |   #   - ".*\\.my\\.go$" | ||||||
|  |   #   - lib/bad.go | ||||||
|  | 
 | ||||||
|  |   # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": | ||||||
|  |   # If invoked with -mod=readonly, the go command is disallowed from the implicit | ||||||
|  |   # automatic updating of go.mod described above. Instead, it fails when any changes | ||||||
|  |   # to go.mod are needed. This setting is most useful to check that go.mod does | ||||||
|  |   # not need updates, such as in a continuous integration and testing system. | ||||||
|  |   # If invoked with -mod=vendor, the go command assumes that the vendor | ||||||
|  |   # directory holds the correct copies of dependencies and ignores | ||||||
|  |   # the dependency descriptions in go.mod. | ||||||
|  |   # modules-download-mode: readonly|release|vendor | ||||||
|  | 
 | ||||||
|  | # output configuration options | ||||||
|  | output: | ||||||
|  |   # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" | ||||||
|  |   format: line-number | ||||||
|  | 
 | ||||||
|  |   # print lines of code with issue, default is true | ||||||
|  |   print-issued-lines: true | ||||||
|  | 
 | ||||||
|  |   # print linter name in the end of issue text, default is true | ||||||
|  |   print-linter-name: true | ||||||
|  | 
 | ||||||
|  | # all available settings of specific linters | ||||||
|  | linters-settings: | ||||||
|  |   errcheck: | ||||||
|  |     # report about not checking of errors in type assetions: `a := b.(MyStruct)`; | ||||||
|  |     # default is false: such cases aren't reported by default. | ||||||
|  |     check-type-assertions: false | ||||||
|  | 
 | ||||||
|  |     # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; | ||||||
|  |     # default is false: such cases aren't reported by default. | ||||||
|  |     check-blank: false | ||||||
|  | 
 | ||||||
|  |     # [deprecated] comma-separated list of pairs of the form pkg:regex | ||||||
|  |     # the regex is used to ignore names within pkg. (default "fmt:.*"). | ||||||
|  |     # see https://github.com/kisielk/errcheck#the-deprecated-method for details | ||||||
|  |     # ignore: fmt:.* | ||||||
|  | 
 | ||||||
|  |     # path to a file containing a list of functions to exclude from checking | ||||||
|  |     # see https://github.com/kisielk/errcheck#excluding-functions for details | ||||||
|  |     # exclude: /path/to/file.txt | ||||||
|  | 
 | ||||||
|  |   # Disable error checking, as errorcheck detects more errors and is more configurable. | ||||||
|  |   gosec: | ||||||
|  |     exclude: | ||||||
|  |     - "G104" | ||||||
|  | 
 | ||||||
|  |   govet: | ||||||
|  |     # report about shadowed variables | ||||||
|  |     check-shadowing: false | ||||||
|  | 
 | ||||||
|  |     # settings per analyzer | ||||||
|  |     settings: | ||||||
|  |       printf: # analyzer name, run `go tool vet help` to see all analyzers | ||||||
|  |         funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer | ||||||
|  |           - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof | ||||||
|  |           - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf | ||||||
|  |           - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf | ||||||
|  |           - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf | ||||||
|  | 
 | ||||||
|  |     # enable or disable analyzers by name | ||||||
|  |     # enable: | ||||||
|  |     #   - atomicalign | ||||||
|  |     # enable-all: false | ||||||
|  |     # disable: | ||||||
|  |     #   - shadow | ||||||
|  |     # disable-all: false | ||||||
|  |   golint: | ||||||
|  |     # minimal confidence for issues, default is 0.8 | ||||||
|  |     min-confidence: 0.8 | ||||||
|  |   gofmt: | ||||||
|  |     # simplify code: gofmt with `-s` option, true by default | ||||||
|  |     simplify: true | ||||||
|  |   goimports: | ||||||
|  |     # put imports beginning with prefix after 3rd-party packages; | ||||||
|  |     # it's a comma-separated list of prefixes | ||||||
|  |     # local-prefixes: github.com/org/project | ||||||
|  |   gocyclo: | ||||||
|  |     # minimal code complexity to report, 30 by default (but we recommend 10-20) | ||||||
|  |     min-complexity: 30 | ||||||
|  |   gocognit: | ||||||
|  |     # minimal code complexity to report, 30 by default (but we recommend 10-20) | ||||||
|  |     min-complexity: 100 | ||||||
|  |   maligned: | ||||||
|  |     # print struct with more effective memory layout or not, false by default | ||||||
|  |     suggest-new: true | ||||||
|  |   dupl: | ||||||
|  |     # tokens count to trigger issue, 150 by default | ||||||
|  |     threshold: 100 | ||||||
|  |   goconst: | ||||||
|  |     # minimal length of string constant, 3 by default | ||||||
|  |     min-len: 3 | ||||||
|  |     # minimal occurrences count to trigger, 3 by default | ||||||
|  |     min-occurrences: 8 | ||||||
|  |   # depguard: | ||||||
|  |   #   list-type: blacklist | ||||||
|  |   #   include-go-root: false | ||||||
|  |   #   packages: | ||||||
|  |   #     - github.com/sirupsen/logrus | ||||||
|  |   #   packages-with-error-messages: | ||||||
|  |   #     # specify an error message to output when a blacklisted package is used | ||||||
|  |   #     github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" | ||||||
|  |   misspell: | ||||||
|  |     # Correct spellings using locale preferences for US or UK. | ||||||
|  |     # Default is to use a neutral variety of English. | ||||||
|  |     # Setting locale to US will correct the British spelling of 'colour' to 'color'. | ||||||
|  |     locale: US | ||||||
|  |     ignore-words: | ||||||
|  |       - GitLab | ||||||
|  |   lll: | ||||||
|  |     # max line length, lines longer will be reported. Default is 120. | ||||||
|  |     # '\t' is counted as 1 character by default, and can be changed with the tab-width option | ||||||
|  |     line-length: 120 | ||||||
|  |     # tab width in spaces. Default to 1. | ||||||
|  |     tab-width: 1 | ||||||
|  |   unused: | ||||||
|  |     # treat code as a program (not a library) and report unused exported identifiers; default is false. | ||||||
|  |     # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: | ||||||
|  |     # if it's called for subdir of a project it can't find funcs usages. All text editor integrations | ||||||
|  |     # with golangci-lint call it on a directory with the changed file. | ||||||
|  |     check-exported: false | ||||||
|  |   unparam: | ||||||
|  |     # Inspect exported functions, default is false. Set to true if no external program/library imports your code. | ||||||
|  |     # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: | ||||||
|  |     # if it's called for subdir of a project it can't find external interfaces. All text editor integrations | ||||||
|  |     # with golangci-lint call it on a directory with the changed file. | ||||||
|  |     check-exported: false | ||||||
|  |   nakedret: | ||||||
|  |     # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 | ||||||
|  |     max-func-lines: 30 | ||||||
|  |   prealloc: | ||||||
|  |     # XXX: we don't recommend using this linter before doing performance profiling. | ||||||
|  |     # For most programs usage of prealloc will be a premature optimization. | ||||||
|  | 
 | ||||||
|  |     # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. | ||||||
|  |     # True by default. | ||||||
|  |     simple: true | ||||||
|  |     range-loops: true # Report preallocation suggestions on range loops, true by default | ||||||
|  |     for-loops: false # Report preallocation suggestions on for loops, false by default | ||||||
|  |   gocritic: | ||||||
|  |     # Which checks should be enabled; can't be combined with 'disabled-checks'; | ||||||
|  |     # See https://go-critic.github.io/overview#checks-overview | ||||||
|  |     # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` | ||||||
|  |     # By default list of stable checks is used. | ||||||
|  |     # enabled-checks: | ||||||
|  |     #   - rangeValCopy | ||||||
|  | 
 | ||||||
|  |     # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty | ||||||
|  |     # disabled-checks: | ||||||
|  |     #   - regexpMust | ||||||
|  | 
 | ||||||
|  |     # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. | ||||||
|  |     # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". | ||||||
|  |     # enabled-tags: | ||||||
|  |     #   - performance | ||||||
|  | 
 | ||||||
|  |     settings: # settings passed to gocritic | ||||||
|  |       captLocal: # must be valid enabled check name | ||||||
|  |         paramsOnly: true | ||||||
|  |     # rangeValCopy: | ||||||
|  |     #   sizeThreshold: 32 | ||||||
|  |   godox: | ||||||
|  |     # report any comments starting with keywords, this is useful for TODO or FIXME comments that | ||||||
|  |     # might be left in the code accidentally and should be resolved before merging | ||||||
|  |     keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting | ||||||
|  |       - TODO | ||||||
|  |       - BUG | ||||||
|  |       - FIXME | ||||||
|  |       - NOTE | ||||||
|  |       - OPTIMIZE # marks code that should be optimized before merging | ||||||
|  |       - HACK # marks hack-arounds that should be removed before merging | ||||||
|  |   dogsled: | ||||||
|  |     # checks assignments with too many blank identifiers; default is 2 | ||||||
|  |     max-blank-identifiers: 2 | ||||||
|  | 
 | ||||||
|  |   whitespace: | ||||||
|  |     multi-if: false   # Enforces newlines (or comments) after every multi-line if statement | ||||||
|  |     multi-func: false # Enforces newlines (or comments) after every multi-line function signature | ||||||
|  |   wsl: | ||||||
|  |     # If true append is only allowed to be cuddled if appending value is | ||||||
|  |     # matching variables, fields or types on line above. Default is true. | ||||||
|  |     strict-append: true | ||||||
|  |     # Allow calls and assignments to be cuddled as long as the lines have any | ||||||
|  |     # matching variables, fields or types. Default is true. | ||||||
|  |     allow-assign-and-call: true | ||||||
|  |     # Allow multiline assignments to be cuddled. Default is true. | ||||||
|  |     allow-multiline-assign: true | ||||||
|  |     # Allow declarations (var) to be cuddled. | ||||||
|  |     allow-cuddle-declarations: false | ||||||
|  |     # Allow trailing comments in ending of blocks | ||||||
|  |     allow-trailing-comment: false | ||||||
|  |     # Force newlines in end of case at this limit (0 = never). | ||||||
|  |     force-case-trailing-whitespace: 0 | ||||||
|  |   revive: | ||||||
|  |     ignore-generated-header: true | ||||||
|  |     severity: warning | ||||||
|  |   funlen: | ||||||
|  |     # Checks the number of lines in a function. | ||||||
|  |     # If lower than 0, disable the check. | ||||||
|  |     # Default: 60 | ||||||
|  |     lines: 280 | ||||||
|  |     # Checks the number of statements in a function. | ||||||
|  |     # If lower than 0, disable the check. | ||||||
|  |     # Default: 40 | ||||||
|  |     statements: 140 | ||||||
|  | 
 | ||||||
|  | linters: | ||||||
|  |   # please, do not use `enable-all`: it's deprecated and will be removed soon. | ||||||
|  |   # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint | ||||||
|  |   disable-all: true | ||||||
|  |   enable: | ||||||
|  |     - bodyclose | ||||||
|  |     - depguard | ||||||
|  |     # - dogsled | ||||||
|  |     # - dupl | ||||||
|  |     - errcheck | ||||||
|  |     - funlen | ||||||
|  |     - gocognit | ||||||
|  |     - goconst | ||||||
|  |     # - gocritic | ||||||
|  |     # - godox | ||||||
|  |     - gofmt | ||||||
|  |     - goimports | ||||||
|  |     - revive | ||||||
|  |     # - gosec | ||||||
|  |     - gosimple | ||||||
|  |     - govet | ||||||
|  |     - ineffassign | ||||||
|  |     # - interfacer | ||||||
|  |     - misspell | ||||||
|  |     - nakedret | ||||||
|  |     - exportloopref | ||||||
|  |     - staticcheck | ||||||
|  |     - structcheck | ||||||
|  |     # - stylecheck | ||||||
|  |     - typecheck | ||||||
|  |     - unconvert | ||||||
|  |     - unparam | ||||||
|  |     - unused | ||||||
|  |     - whitespace | ||||||
|  |   # don't enable: | ||||||
|  |   # - deadcode | ||||||
|  |   # - gochecknoglobals | ||||||
|  |   # - gochecknoinits | ||||||
|  |   # - gocyclo | ||||||
|  |   # - lll | ||||||
|  |   # - maligned | ||||||
|  |   # - prealloc | ||||||
|  |   # - varcheck | ||||||
|  | 
 | ||||||
|  | issues: | ||||||
|  |   # List of regexps of issue texts to exclude, empty list by default. | ||||||
|  |   # But independently from this option we use default exclude patterns, | ||||||
|  |   # it can be disabled by `exclude-use-default: false`. To list all | ||||||
|  |   # excluded by default patterns execute `golangci-lint run --help` | ||||||
|  |   # exclude: | ||||||
|  |   #   - abcdef | ||||||
|  | 
 | ||||||
|  |   # Excluding configuration per-path, per-linter, per-text and per-source | ||||||
|  |   exclude-rules: | ||||||
|  |     # Exclude some linters from running on tests files. | ||||||
|  |     - path: _test\.go | ||||||
|  |       linters: | ||||||
|  |         - gocyclo | ||||||
|  |         - errcheck | ||||||
|  |         - dupl | ||||||
|  |         - gosec | ||||||
|  |         - funlen | ||||||
|  | 
 | ||||||
|  |     # Exclude known linters from partially hard-vendored code, | ||||||
|  |     # which is impossible to exclude via "nolint" comments. | ||||||
|  |     # - path: internal/hmac/ | ||||||
|  |     #   text: "weak cryptographic primitive" | ||||||
|  |     #   linters: | ||||||
|  |     #     - gosec | ||||||
|  | 
 | ||||||
|  |     # Exclude some staticcheck messages | ||||||
|  |     # - linters: | ||||||
|  |     #     - staticcheck | ||||||
|  |     #   text: "SA9003:" | ||||||
|  | 
 | ||||||
|  |     # Exclude lll issues for long lines with go:generate | ||||||
|  |     - linters: | ||||||
|  |         - lll | ||||||
|  |       source: "^//go:generate " | ||||||
|  | 
 | ||||||
|  |   # Independently from option `exclude` we use default exclude patterns, | ||||||
|  |   # it can be disabled by this option. To list all | ||||||
|  |   # excluded by default patterns execute `golangci-lint run --help`. | ||||||
|  |   # Default value for this option is true. | ||||||
|  |   exclude-use-default: false | ||||||
|  | 
 | ||||||
|  |   # Maximum issues count per one linter. Set to 0 to disable. Default is 50. | ||||||
|  |   max-issues-per-linter: 0 | ||||||
|  | 
 | ||||||
|  |   # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. | ||||||
|  |   max-same-issues: 0 | ||||||
|  | 
 | ||||||
|  |   # Show only new issues: if there are unstaged changes or untracked files, | ||||||
|  |   # only those changes are analyzed, else only changes in HEAD~ are analyzed. | ||||||
|  |   # It's a super-useful option for integration of golangci-lint into existing | ||||||
|  |   # large codebase. It's not practical to fix all existing issues at the moment | ||||||
|  |   # of integration: much better don't allow issues in new code. | ||||||
|  |   # Default is false. | ||||||
|  |   new: false | ||||||
|  | 
 | ||||||
|  |   # Show only new issues created after git revision `REV` | ||||||
|  |   # This should be passed as flag during individual CI jobs. | ||||||
|  |   # new-from-rev: REV | ||||||
|  | 
 | ||||||
|  |   # Show only new issues created in git patch with set file path. | ||||||
|  |   # new-from-patch: path/to/patch/file | ||||||
|  | @ -26,7 +26,7 @@ func addApplySubcommand(cliApp *cli.App) { | ||||||
| 			}, | 			}, | ||||||
| 			cli.BoolFlag{ | 			cli.BoolFlag{ | ||||||
| 				Name:  "validate", | 				Name:  "validate", | ||||||
| 				Usage: "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requiers access to a Kubernetes cluster to obtain information necessary for validating, like the list of available API versions", | 				Usage: "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", | ||||||
| 			}, | 			}, | ||||||
| 			cli.IntFlag{ | 			cli.IntFlag{ | ||||||
| 				Name:  "context", | 				Name:  "context", | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ func addDiffSubcommand(cliApp *cli.App) { | ||||||
| 			}, | 			}, | ||||||
| 			cli.BoolFlag{ | 			cli.BoolFlag{ | ||||||
| 				Name:  "validate", | 				Name:  "validate", | ||||||
| 				Usage: "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requiers access to a Kubernetes cluster to obtain information necessary for validating, like the list of available API versions", | 				Usage: "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", | ||||||
| 			}, | 			}, | ||||||
| 
 | 
 | ||||||
| 			cli.IntFlag{ | 			cli.IntFlag{ | ||||||
|  |  | ||||||
|  | @ -119,7 +119,6 @@ func setRootCommandFlags(cliApp *cli.App) { | ||||||
| 			Usage: "Request confirmation before attempting to modify clusters", | 			Usage: "Request confirmation before attempting to modify clusters", | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func toCliError(c *cli.Context, err error) error { | func toCliError(c *cli.Context, err error) error { | ||||||
|  | @ -153,7 +152,7 @@ func configureLogging(c *cli.Context) error { | ||||||
| 	} | 	} | ||||||
| 	logger = helmexec.NewLogger(os.Stderr, logLevel) | 	logger = helmexec.NewLogger(os.Stderr, logLevel) | ||||||
| 	if c.App.Metadata == nil { | 	if c.App.Metadata == nil { | ||||||
| 		// Auto-initialised in 1.19.0
 | 		// Auto-initialized in 1.19.0
 | ||||||
| 		// https://github.com/urfave/cli/blob/master/CHANGELOG.md#1190---2016-11-19
 | 		// https://github.com/urfave/cli/blob/master/CHANGELOG.md#1190---2016-11-19
 | ||||||
| 		c.App.Metadata = make(map[string]interface{}) | 		c.App.Metadata = make(map[string]interface{}) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -51,7 +51,7 @@ func addSyncSubcommand(cliApp *cli.App) { | ||||||
| 			}, | 			}, | ||||||
| 			cli.BoolFlag{ | 			cli.BoolFlag{ | ||||||
| 				Name:  "validate", | 				Name:  "validate", | ||||||
| 				Usage: `ADVANCED CONFIGURATION: When sync is going to involve helm-template as a part of the "chartify" process, it might fail due to missing .Capabilities. This flag makes instructs helmfile to pass --validate to helm-template so it populates .Capabilities and validates your manifests against the Kubernetes cluster you are currently pointing at. Note that this requiers access to a Kubernetes cluster to obtain information necessary for validating, like the list of available API versions`, | 				Usage: `ADVANCED CONFIGURATION: When sync is going to involve helm-template as a part of the "chartify" process, it might fail due to missing .Capabilities. This flag makes instructs helmfile to pass --validate to helm-template so it populates .Capabilities and validates 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`, | ||||||
| 			}, | 			}, | ||||||
| 			cli.BoolFlag{ | 			cli.BoolFlag{ | ||||||
| 				Name:  "wait", | 				Name:  "wait", | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ func addTemplateSubcommand(cliApp *cli.App) { | ||||||
| 			}, | 			}, | ||||||
| 			cli.BoolFlag{ | 			cli.BoolFlag{ | ||||||
| 				Name:  "validate", | 				Name:  "validate", | ||||||
| 				Usage: "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requiers access to a Kubernetes cluster to obtain information necessary for validating, like the list of available API versions", | 				Usage: "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", | ||||||
| 			}, | 			}, | ||||||
| 			cli.BoolFlag{ | 			cli.BoolFlag{ | ||||||
| 				Name:  "include-crds", | 				Name:  "include-crds", | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										4
									
								
								go.mod
								
								
								
								
							|  | @ -30,6 +30,7 @@ require ( | ||||||
| 	go.uber.org/multierr v1.6.0 | 	go.uber.org/multierr v1.6.0 | ||||||
| 	go.uber.org/zap v1.21.0 | 	go.uber.org/zap v1.21.0 | ||||||
| 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c | 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c | ||||||
|  | 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 | ||||||
| 	gopkg.in/yaml.v2 v2.4.0 | 	gopkg.in/yaml.v2 v2.4.0 | ||||||
| 	k8s.io/apimachinery v0.23.4 | 	k8s.io/apimachinery v0.23.4 | ||||||
| ) | ) | ||||||
|  | @ -123,7 +124,6 @@ require ( | ||||||
| 	golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect | 	golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect | ||||||
| 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect | 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect | ||||||
| 	golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect | 	golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect | ||||||
| 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect |  | ||||||
| 	golang.org/x/text v0.3.7 // indirect | 	golang.org/x/text v0.3.7 // indirect | ||||||
| 	golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect | 	golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect | ||||||
| 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect | 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect | ||||||
|  | @ -146,5 +146,5 @@ require ( | ||||||
| 	github.com/hashicorp/go-retryablehttp v0.7.1 // indirect | 	github.com/hashicorp/go-retryablehttp v0.7.1 // indirect | ||||||
| 	github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c // indirect | 	github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c // indirect | ||||||
| 	github.com/pierrec/lz4 v2.3.0+incompatible // indirect | 	github.com/pierrec/lz4 v2.3.0+incompatible // indirect | ||||||
| 	golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 | 	golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect | ||||||
| ) | ) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								main.go
								
								
								
								
							
							
						
						
									
										1
									
								
								main.go
								
								
								
								
							|  | @ -8,7 +8,6 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 
 |  | ||||||
| 	rootCmd := cmd.RootCommand() | 	rootCmd := cmd.RootCommand() | ||||||
| 	err := rootCmd.Run(os.Args) | 	err := rootCmd.Run(os.Args) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ import ( | ||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // App is the main application object.
 | ||||||
| type App struct { | type App struct { | ||||||
| 	OverrideKubeContext string | 	OverrideKubeContext string | ||||||
| 	OverrideHelmBinary  string | 	OverrideHelmBinary  string | ||||||
|  | @ -552,8 +553,7 @@ func (a *App) ListReleases(c ListConfigProvider) error { | ||||||
| 			SkipRepos: true, | 			SkipRepos: true, | ||||||
| 			SkipDeps:  true, | 			SkipDeps:  true, | ||||||
| 		}, func() { | 		}, func() { | ||||||
| 
 | 			// var releases m
 | ||||||
| 			//var releases m
 |  | ||||||
| 			for _, r := range run.state.Releases { | 			for _, r := range run.state.Releases { | ||||||
| 				labels := "" | 				labels := "" | ||||||
| 				if r.Labels == nil { | 				if r.Labels == nil { | ||||||
|  | @ -805,7 +805,7 @@ func (a *App) visitStates(fileOrDir string, defOpts LoadOpts, converge func(*sta | ||||||
| 						Reverse:           defOpts.Reverse, | 						Reverse:           defOpts.Reverse, | ||||||
| 						RetainValuesFiles: defOpts.RetainValuesFiles, | 						RetainValuesFiles: defOpts.RetainValuesFiles, | ||||||
| 					} | 					} | ||||||
| 					//assign parent selector to sub helm selector in legacy mode or do not inherit in experimental mode
 | 					// assign parent selector to sub helm selector in legacy mode or do not inherit in experimental mode
 | ||||||
| 					if (m.Selectors == nil && !isExplicitSelectorInheritanceEnabled()) || m.SelectorsInherited { | 					if (m.Selectors == nil && !isExplicitSelectorInheritanceEnabled()) || m.SelectorsInherited { | ||||||
| 						optsForNestedState.Selectors = opts.Selectors | 						optsForNestedState.Selectors = opts.Selectors | ||||||
| 					} else { | 					} else { | ||||||
|  | @ -915,7 +915,7 @@ func printBatches(batches [][]state.Release) string { | ||||||
| 		fmt.Fprintf(w, "%d\t%s\n", i+1, strings.Join(ids, ", ")) | 		fmt.Fprintf(w, "%d\t%s\n", i+1, strings.Join(ids, ", ")) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	w.Flush() | 	_ = w.Flush() | ||||||
| 
 | 
 | ||||||
| 	return buf.String() | 	return buf.String() | ||||||
| } | } | ||||||
|  | @ -1092,11 +1092,12 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri | ||||||
| 
 | 
 | ||||||
| 	var helmfileDir string | 	var helmfileDir string | ||||||
| 	if specifiedPath != "" { | 	if specifiedPath != "" { | ||||||
| 		if a.fileExistsAt(specifiedPath) { | 		switch { | ||||||
|  | 		case a.fileExistsAt(specifiedPath): | ||||||
| 			return []string{specifiedPath}, nil | 			return []string{specifiedPath}, nil | ||||||
| 		} else if a.directoryExistsAt(specifiedPath) { | 		case a.directoryExistsAt(specifiedPath): | ||||||
| 			helmfileDir = specifiedPath | 			helmfileDir = specifiedPath | ||||||
| 		} else { | 		default: | ||||||
| 			return []string{}, fmt.Errorf("specified state file %s is not found", specifiedPath) | 			return []string{}, fmt.Errorf("specified state file %s is not found", specifiedPath) | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -1113,15 +1114,16 @@ func (a *App) findDesiredStateFiles(specifiedPath string, opts LoadOpts) ([]stri | ||||||
| 			defaultFile = DeprecatedHelmfile | 			defaultFile = DeprecatedHelmfile | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if a.directoryExistsAt(DefaultHelmfileDirectory) { | 		switch { | ||||||
|  | 		case a.directoryExistsAt(DefaultHelmfileDirectory): | ||||||
| 			if defaultFile != "" { | 			if defaultFile != "" { | ||||||
| 				return []string{}, fmt.Errorf("configuration conlict error: you can have either %s or %s, but not both", defaultFile, DefaultHelmfileDirectory) | 				return []string{}, fmt.Errorf("configuration conlict error: you can have either %s or %s, but not both", defaultFile, DefaultHelmfileDirectory) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			helmfileDir = DefaultHelmfileDirectory | 			helmfileDir = DefaultHelmfileDirectory | ||||||
| 		} else if defaultFile != "" { | 		case defaultFile != "": | ||||||
| 			return []string{defaultFile}, nil | 			return []string{defaultFile}, nil | ||||||
| 		} else { | 		default: | ||||||
| 			return []string{}, fmt.Errorf("no state file found. It must be named %s/*.{yaml,yml} or %s, otherwise specified with the --file flag", DefaultHelmfileDirectory, DefaultHelmfile) | 			return []string{}, fmt.Errorf("no state file found. It must be named %s/*.{yaml,yml} or %s, otherwise specified with the --file flag", DefaultHelmfileDirectory, DefaultHelmfile) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1944,6 +1946,7 @@ func directoryExistsAt(path string) bool { | ||||||
| 	return err == nil && fileInfo.Mode().IsDir() | 	return err == nil && fileInfo.Mode().IsDir() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Error is a wrapper around an error that adds context to the error.
 | ||||||
| type Error struct { | type Error struct { | ||||||
| 	msg string | 	msg string | ||||||
| 
 | 
 | ||||||
|  | @ -2084,7 +2087,10 @@ func (a *App) CleanCacheDir(c ListConfigProvider) error { | ||||||
| 	} | 	} | ||||||
| 	for _, e := range dirs { | 	for _, e := range dirs { | ||||||
| 		fmt.Printf("- %s\n", e.Name()) | 		fmt.Printf("- %s\n", e.Name()) | ||||||
| 		os.RemoveAll(filepath.Join(remote.CacheDir(), e.Name())) | 		err := os.RemoveAll(filepath.Join(remote.CacheDir(), e.Name())) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
|  | @ -1275,7 +1275,7 @@ foo 	4       	Fri Nov  1 08:40:07 2019	DEPLOYED	raw-3.1.0	3.1.0      	default | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	t.Run("select non existant release with --allow-no-matching-release", func(t *testing.T) { | 	t.Run("select non existent release with --allow-no-matching-release", func(t *testing.T) { | ||||||
| 		check(t, testcase{ | 		check(t, testcase{ | ||||||
| 			files: map[string]string{ | 			files: map[string]string{ | ||||||
| 				"/path/to/helmfile.yaml": ` | 				"/path/to/helmfile.yaml": ` | ||||||
|  |  | ||||||
|  | @ -612,7 +612,7 @@ releases: | ||||||
|     whatever: yes |     whatever: yes | ||||||
| `, | `, | ||||||
| 	} | 	} | ||||||
| 	//Check with legacy behavior, that is when no explicit selector then sub-helmfiles inherits from command line selector
 | 	// Check with legacy behavior, that is when no explicit selector then sub-helmfiles inherits from command line selector
 | ||||||
| 	legacyTestcases := []struct { | 	legacyTestcases := []struct { | ||||||
| 		label            string | 		label            string | ||||||
| 		expectedReleases []string | 		expectedReleases []string | ||||||
|  | @ -626,7 +626,7 @@ releases: | ||||||
| 	} | 	} | ||||||
| 	runFilterSubHelmFilesTests(legacyTestcases, files, t, "1st EmbeddedSelectors") | 	runFilterSubHelmFilesTests(legacyTestcases, files, t, "1st EmbeddedSelectors") | ||||||
| 
 | 
 | ||||||
| 	//Check with experimental behavior, that is when no explicit selector then sub-helmfiles do no inherit from any selector
 | 	// Check with experimental behavior, that is when no explicit selector then sub-helmfiles do no inherit from any selector
 | ||||||
| 	desiredTestcases := []struct { | 	desiredTestcases := []struct { | ||||||
| 		label            string | 		label            string | ||||||
| 		expectedReleases []string | 		expectedReleases []string | ||||||
|  | @ -640,7 +640,6 @@ releases: | ||||||
| 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | ||||||
| 
 | 
 | ||||||
| 	runFilterSubHelmFilesTests(desiredTestcases, files, t, "2nd EmbeddedSelectors") | 	runFilterSubHelmFilesTests(desiredTestcases, files, t, "2nd EmbeddedSelectors") | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestVisitDesiredStatesWithReleasesFiltered_InheritedSelectors_3leveldeep(t *testing.T) { | func TestVisitDesiredStatesWithReleasesFiltered_InheritedSelectors_3leveldeep(t *testing.T) { | ||||||
|  | @ -665,7 +664,7 @@ releases: | ||||||
|   chart: stable/grafana |   chart: stable/grafana | ||||||
| `, | `, | ||||||
| 	} | 	} | ||||||
| 	//Check with legacy behavior, that is when no explicit selector then sub-helmfiles inherits from command line selector
 | 	// Check with legacy behavior, that is when no explicit selector then sub-helmfiles inherits from command line selector
 | ||||||
| 	legacyTestcases := []struct { | 	legacyTestcases := []struct { | ||||||
| 		label            string | 		label            string | ||||||
| 		expectedReleases []string | 		expectedReleases []string | ||||||
|  | @ -676,7 +675,7 @@ releases: | ||||||
| 	} | 	} | ||||||
| 	runFilterSubHelmFilesTests(legacyTestcases, files, t, "1st 3leveldeep") | 	runFilterSubHelmFilesTests(legacyTestcases, files, t, "1st 3leveldeep") | ||||||
| 
 | 
 | ||||||
| 	//Check with experimental behavior, that is when no explicit selector then sub-helmfiles do no inherit from any selector
 | 	// Check with experimental behavior, that is when no explicit selector then sub-helmfiles do no inherit from any selector
 | ||||||
| 	desiredTestcases := []struct { | 	desiredTestcases := []struct { | ||||||
| 		label            string | 		label            string | ||||||
| 		expectedReleases []string | 		expectedReleases []string | ||||||
|  | @ -689,7 +688,6 @@ releases: | ||||||
| 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | ||||||
| 
 | 
 | ||||||
| 	runFilterSubHelmFilesTests(desiredTestcases, files, t, "2nd 3leveldeep") | 	runFilterSubHelmFilesTests(desiredTestcases, files, t, "2nd 3leveldeep") | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestVisitDesiredStatesWithReleasesFiltered_InheritedSelectors_inherits(t *testing.T) { | func TestVisitDesiredStatesWithReleasesFiltered_InheritedSelectors_inherits(t *testing.T) { | ||||||
|  | @ -724,7 +722,7 @@ releases: | ||||||
|     select: foo |     select: foo | ||||||
| `, | `, | ||||||
| 	} | 	} | ||||||
| 	//Check with legacy behavior, that is when no explicit selector then sub-helmfiles inherits from command line selector
 | 	// Check with legacy behavior, that is when no explicit selector then sub-helmfiles inherits from command line selector
 | ||||||
| 	legacyTestcases := []struct { | 	legacyTestcases := []struct { | ||||||
| 		label            string | 		label            string | ||||||
| 		expectedReleases []string | 		expectedReleases []string | ||||||
|  | @ -736,7 +734,7 @@ releases: | ||||||
| 	} | 	} | ||||||
| 	runFilterSubHelmFilesTests(legacyTestcases, files, t, "1st inherits") | 	runFilterSubHelmFilesTests(legacyTestcases, files, t, "1st inherits") | ||||||
| 
 | 
 | ||||||
| 	//Check with experimental behavior, that is when no explicit selector then sub-helmfiles do no inherit from any selector
 | 	// Check with experimental behavior, that is when no explicit selector then sub-helmfiles do no inherit from any selector
 | ||||||
| 	desiredTestcases := []struct { | 	desiredTestcases := []struct { | ||||||
| 		label            string | 		label            string | ||||||
| 		expectedReleases []string | 		expectedReleases []string | ||||||
|  | @ -750,7 +748,6 @@ releases: | ||||||
| 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | ||||||
| 
 | 
 | ||||||
| 	runFilterSubHelmFilesTests(desiredTestcases, files, t, "2nd inherits") | 	runFilterSubHelmFilesTests(desiredTestcases, files, t, "2nd inherits") | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func runFilterSubHelmFilesTests(testcases []struct { | func runFilterSubHelmFilesTests(testcases []struct { | ||||||
|  | @ -801,7 +798,6 @@ func runFilterSubHelmFilesTests(testcases []struct { | ||||||
| 			t.Errorf("[%s]unexpected releases for selector %s: expected=%v, actual=%v", testName, testcase.label, testcase.expectedReleases, actual) | 			t.Errorf("[%s]unexpected releases for selector %s: expected=%v, actual=%v", testName, testcase.label, testcase.expectedReleases, actual) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestVisitDesiredStatesWithReleasesFiltered_EmbeddedNestedStateAdditionalEnvValues(t *testing.T) { | func TestVisitDesiredStatesWithReleasesFiltered_EmbeddedNestedStateAdditionalEnvValues(t *testing.T) { | ||||||
|  | @ -2257,8 +2253,8 @@ type configImpl struct { | ||||||
| 	includeTransitiveNeeds bool | 	includeTransitiveNeeds bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a configImpl) Selectors() []string { | func (c configImpl) Selectors() []string { | ||||||
| 	return a.selectors | 	return c.selectors | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c configImpl) Set() []string { | func (c configImpl) Set() []string { | ||||||
|  | @ -2399,16 +2395,16 @@ func (a applyConfig) SkipDeps() bool { | ||||||
| 	return a.skipDeps | 	return a.skipDeps | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c applyConfig) SkipNeeds() bool { | func (a applyConfig) SkipNeeds() bool { | ||||||
| 	return c.skipNeeds | 	return a.skipNeeds | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c applyConfig) IncludeNeeds() bool { | func (a applyConfig) IncludeNeeds() bool { | ||||||
| 	return c.includeNeeds | 	return a.includeNeeds | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c applyConfig) IncludeTransitiveNeeds() bool { | func (a applyConfig) IncludeTransitiveNeeds() bool { | ||||||
| 	return c.includeTransitiveNeeds | 	return a.includeTransitiveNeeds | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (a applyConfig) IncludeTests() bool { | func (a applyConfig) IncludeTests() bool { | ||||||
|  | @ -2765,7 +2761,6 @@ releases: | ||||||
| 				t.Errorf("HelmState.TemplateReleases() = [%v], want %v", helm.templated[i].flags[j], wantReleases[i].flags[j]) | 				t.Errorf("HelmState.TemplateReleases() = [%v], want %v", helm.templated[i].flags[j], wantReleases[i].flags[j]) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -4312,11 +4307,12 @@ changing working directory back to "/path/to" | ||||||
| 					skipDiffOnInstall: tc.skipDiffOnInstall, | 					skipDiffOnInstall: tc.skipDiffOnInstall, | ||||||
| 					skipNeeds:         tc.fields.skipNeeds, | 					skipNeeds:         tc.fields.skipNeeds, | ||||||
| 				}) | 				}) | ||||||
| 				if tc.error == "" && applyErr != nil { | 				switch { | ||||||
|  | 				case tc.error == "" && applyErr != nil: | ||||||
| 					t.Fatalf("unexpected error for data defined at %s: %v", tc.loc, applyErr) | 					t.Fatalf("unexpected error for data defined at %s: %v", tc.loc, applyErr) | ||||||
| 				} else if tc.error != "" && applyErr == nil { | 				case tc.error != "" && applyErr == nil: | ||||||
| 					t.Fatalf("expected error did not occur for data defined at %s", tc.loc) | 					t.Fatalf("expected error did not occur for data defined at %s", tc.loc) | ||||||
| 				} else if tc.error != "" && applyErr != nil && tc.error != applyErr.Error() { | 				case tc.error != "" && applyErr != nil && tc.error != applyErr.Error(): | ||||||
| 					t.Fatalf("invalid error: expected %q, got %q", tc.error, applyErr.Error()) | 					t.Fatalf("invalid error: expected %q, got %q", tc.error, applyErr.Error()) | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | @ -4433,7 +4429,6 @@ changing working directory back to "/path/to" | ||||||
| 	for i := range testcases { | 	for i := range testcases { | ||||||
| 		tc := testcases[i] | 		tc := testcases[i] | ||||||
| 		t.Run(tc.name, func(t *testing.T) { | 		t.Run(tc.name, func(t *testing.T) { | ||||||
| 
 |  | ||||||
| 			var helm = &exectest.Helm{ | 			var helm = &exectest.Helm{ | ||||||
| 				DiffMutex:     &sync.Mutex{}, | 				DiffMutex:     &sync.Mutex{}, | ||||||
| 				ChartsMutex:   &sync.Mutex{}, | 				ChartsMutex:   &sync.Mutex{}, | ||||||
|  | @ -4483,12 +4478,12 @@ changing working directory back to "/path/to" | ||||||
| 					skipRepos:              false, | 					skipRepos:              false, | ||||||
| 					includeTransitiveNeeds: false, | 					includeTransitiveNeeds: false, | ||||||
| 				}) | 				}) | ||||||
| 
 | 				switch { | ||||||
| 				if tc.error == "" && depsErr != nil { | 				case tc.error == "" && depsErr != nil: | ||||||
| 					t.Fatalf("unexpected error for data defined at %s: %v", tc.loc, depsErr) | 					t.Fatalf("unexpected error for data defined at %s: %v", tc.loc, depsErr) | ||||||
| 				} else if tc.error != "" && depsErr == nil { | 				case tc.error != "" && depsErr == nil: | ||||||
| 					t.Fatalf("expected error did not occur for data defined at %s", tc.loc) | 					t.Fatalf("expected error did not occur for data defined at %s", tc.loc) | ||||||
| 				} else if tc.error != "" && depsErr != nil && tc.error != depsErr.Error() { | 				case tc.error != "" && depsErr != nil && tc.error != depsErr.Error(): | ||||||
| 					t.Fatalf("invalid error: expected %q, got %q", tc.error, depsErr.Error()) | 					t.Fatalf("invalid error: expected %q, got %q", tc.error, depsErr.Error()) | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,19 +11,19 @@ import ( | ||||||
| 
 | 
 | ||||||
| // TestIsExplicitSelectorInheritanceEnabled tests the isExplicitSelectorInheritanceEnabled function
 | // TestIsExplicitSelectorInheritanceEnabled tests the isExplicitSelectorInheritanceEnabled function
 | ||||||
| func TestIsExplicitSelectorInheritanceEnabled(t *testing.T) { | func TestIsExplicitSelectorInheritanceEnabled(t *testing.T) { | ||||||
| 	//env var ExperimentalEnvVar is not set
 | 	// env var ExperimentalEnvVar is not set
 | ||||||
| 	require.Empty(t, os.Getenv(envvar.Experimental)) | 	require.Empty(t, os.Getenv(envvar.Experimental)) | ||||||
| 	require.False(t, isExplicitSelectorInheritanceEnabled()) | 	require.False(t, isExplicitSelectorInheritanceEnabled()) | ||||||
| 
 | 
 | ||||||
| 	//check for env var ExperimentalEnvVar set to true
 | 	// check for env var ExperimentalEnvVar set to true
 | ||||||
| 	t.Setenv(envvar.Experimental, "true") | 	t.Setenv(envvar.Experimental, "true") | ||||||
| 	require.True(t, isExplicitSelectorInheritanceEnabled()) | 	require.True(t, isExplicitSelectorInheritanceEnabled()) | ||||||
| 
 | 
 | ||||||
| 	//check for env var ExperimentalEnvVar set to anything
 | 	// check for env var ExperimentalEnvVar set to anything
 | ||||||
| 	t.Setenv(envvar.Experimental, "anything") | 	t.Setenv(envvar.Experimental, "anything") | ||||||
| 	require.False(t, isExplicitSelectorInheritanceEnabled()) | 	require.False(t, isExplicitSelectorInheritanceEnabled()) | ||||||
| 
 | 
 | ||||||
| 	//check for env var ExperimentalEnvVar set to ExperimentalSelectorExplicit
 | 	// check for env var ExperimentalEnvVar set to ExperimentalSelectorExplicit
 | ||||||
| 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | 	t.Setenv(envvar.Experimental, ExperimentalSelectorExplicit) | ||||||
| 	require.True(t, isExplicitSelectorInheritanceEnabled()) | 	require.True(t, isExplicitSelectorInheritanceEnabled()) | ||||||
| 
 | 
 | ||||||
|  | @ -34,15 +34,15 @@ func TestIsExplicitSelectorInheritanceEnabled(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| // TestExperimentalModeEnabled tests the experimentalModeEnabled function
 | // TestExperimentalModeEnabled tests the experimentalModeEnabled function
 | ||||||
| func TestExperimentalModeEnabled(t *testing.T) { | func TestExperimentalModeEnabled(t *testing.T) { | ||||||
| 	//env var ExperimentalEnvVar is not set
 | 	// env var ExperimentalEnvVar is not set
 | ||||||
| 	require.Empty(t, os.Getenv(envvar.Experimental)) | 	require.Empty(t, os.Getenv(envvar.Experimental)) | ||||||
| 	require.False(t, experimentalModeEnabled()) | 	require.False(t, experimentalModeEnabled()) | ||||||
| 
 | 
 | ||||||
| 	//check for env var ExperimentalEnvVar set to anything
 | 	// check for env var ExperimentalEnvVar set to anything
 | ||||||
| 	t.Setenv(envvar.Experimental, "anything") | 	t.Setenv(envvar.Experimental, "anything") | ||||||
| 	require.False(t, experimentalModeEnabled()) | 	require.False(t, experimentalModeEnabled()) | ||||||
| 
 | 
 | ||||||
| 	//check for env var ExperimentalEnvVar set to true
 | 	// check for env var ExperimentalEnvVar set to true
 | ||||||
| 	t.Setenv(envvar.Experimental, "true") | 	t.Setenv(envvar.Experimental, "true") | ||||||
| 	require.True(t, experimentalModeEnabled()) | 	require.True(t, experimentalModeEnabled()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -77,7 +77,7 @@ func (ld *desiredStateLoader) Load(f string, opts LoadOpts) (*state.HelmState, e | ||||||
| 			return nil, errors.New("err: Cannot use option --kube-context and set attribute kubeContext.") | 			return nil, errors.New("err: Cannot use option --kube-context and set attribute kubeContext.") | ||||||
| 		} | 		} | ||||||
| 		st.OverrideKubeContext = ld.overrideKubeContext | 		st.OverrideKubeContext = ld.overrideKubeContext | ||||||
| 		// HelmDefaults.KubeContext is also overriden in here
 | 		// HelmDefaults.KubeContext is also overridden in here
 | ||||||
| 		// to set default release value properly.
 | 		// to set default release value properly.
 | ||||||
| 		st.HelmDefaults.KubeContext = ld.overrideKubeContext | 		st.HelmDefaults.KubeContext = ld.overrideKubeContext | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -108,11 +108,12 @@ func TestDestroy_2(t *testing.T) { | ||||||
| 				includeTransitiveNeeds: false, | 				includeTransitiveNeeds: false, | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			if tc.error == "" && destroyErr != nil { | 			switch { | ||||||
|  | 			case tc.error == "" && destroyErr != nil: | ||||||
| 				t.Fatalf("unexpected error: %v", destroyErr) | 				t.Fatalf("unexpected error: %v", destroyErr) | ||||||
| 			} else if tc.error != "" && destroyErr == nil { | 			case tc.error != "" && destroyErr == nil: | ||||||
| 				t.Fatal("expected error did not occur") | 				t.Fatal("expected error did not occur") | ||||||
| 			} else if tc.error != "" && destroyErr != nil && tc.error != destroyErr.Error() { | 			case tc.error != "" && destroyErr != nil && tc.error != destroyErr.Error(): | ||||||
| 				t.Fatalf("invalid error: expected %q, got %q", tc.error, destroyErr.Error()) | 				t.Fatalf("invalid error: expected %q, got %q", tc.error, destroyErr.Error()) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -148,11 +148,12 @@ func TestDestroy(t *testing.T) { | ||||||
| 				logger:      logger, | 				logger:      logger, | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			if tc.error == "" && destroyErr != nil { | 			switch { | ||||||
|  | 			case tc.error == "" && destroyErr != nil: | ||||||
| 				t.Fatalf("unexpected error: %v", destroyErr) | 				t.Fatalf("unexpected error: %v", destroyErr) | ||||||
| 			} else if tc.error != "" && destroyErr == nil { | 			case tc.error != "" && destroyErr == nil: | ||||||
| 				t.Fatal("expected error did not occur") | 				t.Fatal("expected error did not occur") | ||||||
| 			} else if tc.error != "" && destroyErr != nil && tc.error != destroyErr.Error() { | 			case tc.error != "" && destroyErr != nil && tc.error != destroyErr.Error(): | ||||||
| 				t.Fatalf("invalid error: expected %q, got %q", tc.error, destroyErr.Error()) | 				t.Fatalf("invalid error: expected %q, got %q", tc.error, destroyErr.Error()) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ import ( | ||||||
| 
 | 
 | ||||||
| // TestFormatAsTable tests the FormatAsTable function.
 | // TestFormatAsTable tests the FormatAsTable function.
 | ||||||
| func TestFormatAsTable(t *testing.T) { | func TestFormatAsTable(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	h := []*HelmRelease{ | 	h := []*HelmRelease{ | ||||||
| 		{ | 		{ | ||||||
| 			Name:      "test", | 			Name:      "test", | ||||||
|  | @ -78,5 +77,4 @@ func TestFormatAsJson(t *testing.T) { | ||||||
| 	if result != string(expectd) { | 	if result != string(expectd) { | ||||||
| 		t.Errorf("FormatAsJson() = %v, want %v", result, string(expectd)) | 		t.Errorf("FormatAsJson() = %v, want %v", result, string(expectd)) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,5 +19,4 @@ func TestLoadOptsDeepCopy(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	// Check that the new struct is not the same as the old one.
 | 	// Check that the new struct is not the same as the old one.
 | ||||||
| 	require.Equal(t, lOld, lNew, "DeepCopy should return a copy of the LoadOpts struct") | 	require.Equal(t, lOld, lNew, "DeepCopy should return a copy of the LoadOpts struct") | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -55,7 +55,9 @@ func (r *Run) withPreparedCharts(helmfileCommand string, opts state.ChartPrepare | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		defer os.RemoveAll(tempDir) | 		defer func() { | ||||||
|  | 			_ = os.RemoveAll(tempDir) | ||||||
|  | 		}() | ||||||
| 		dir = tempDir | 		dir = tempDir | ||||||
| 	} else { | 	} else { | ||||||
| 		dir = opts.OutputDir | 		dir = opts.OutputDir | ||||||
|  |  | ||||||
|  | @ -51,8 +51,7 @@ func (r *desiredStateLoader) renderPrestate(firstPassEnv *environment.Environmen | ||||||
| 	// create preliminary state, as we may have an environment. Tolerate errors.
 | 	// create preliminary state, as we may have an environment. Tolerate errors.
 | ||||||
| 	prestate, err := c.ParseAndLoad([]byte(sanitized), baseDir, filename, r.env, false, firstPassEnv) | 	prestate, err := c.ParseAndLoad([]byte(sanitized), baseDir, filename, r.env, false, firstPassEnv) | ||||||
| 	if err != nil && r.logger != nil { | 	if err != nil && r.logger != nil { | ||||||
| 		switch err.(type) { | 		if _, ok := err.(*state.StateLoadError); ok { | ||||||
| 		case *state.StateLoadError: |  | ||||||
| 			r.logger.Debugf("could not deduce `environment:` block, configuring only .Environment.Name. error: %v", err) | 			r.logger.Debugf("could not deduce `environment:` block, configuring only .Environment.Name. error: %v", err) | ||||||
| 		} | 		} | ||||||
| 		r.logger.Debugf("error in first-pass rendering: result of \"%s\":\n%s", filename, prependLineNumbers(yamlBuf.String())) | 		r.logger.Debugf("error in first-pass rendering: result of \"%s\":\n%s", filename, prependLineNumbers(yamlBuf.String())) | ||||||
|  |  | ||||||
|  | @ -31,7 +31,6 @@ func makeLoader(files map[string]string, env string) (*desiredStateLoader, *test | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestReadFromYaml_MakeEnvironmentHasNoSideEffects(t *testing.T) { | func TestReadFromYaml_MakeEnvironmentHasNoSideEffects(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	yamlContent := []byte(` | 	yamlContent := []byte(` | ||||||
| environments: | environments: | ||||||
|   staging: |   staging: | ||||||
|  | @ -71,7 +70,6 @@ releases: | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestReadFromYaml_RenderTemplate(t *testing.T) { | func TestReadFromYaml_RenderTemplate(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	defaultValuesYaml := ` | 	defaultValuesYaml := ` | ||||||
| releaseName: "hello" | releaseName: "hello" | ||||||
| conditionalReleaseTag: "yes" | conditionalReleaseTag: "yes" | ||||||
|  | @ -159,7 +157,6 @@ releases: | ||||||
| // even if the pre-render disables the readFile and exec functions.
 | // even if the pre-render disables the readFile and exec functions.
 | ||||||
| // This does not apply to .gotmpl files, which is a nice side-effect.
 | // This does not apply to .gotmpl files, which is a nice side-effect.
 | ||||||
| func TestReadFromYaml_RenderTemplateWithGotmpl(t *testing.T) { | func TestReadFromYaml_RenderTemplateWithGotmpl(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	defaultValuesYamlGotmpl := ` | 	defaultValuesYamlGotmpl := ` | ||||||
| releaseName: {{ readFile "nonIgnoredFile" }} | releaseName: {{ readFile "nonIgnoredFile" }} | ||||||
| ` | ` | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ package app | ||||||
| 
 | 
 | ||||||
| import "errors" | import "errors" | ||||||
| 
 | 
 | ||||||
|  | // ValidateConfig validates the given Helmfile config.
 | ||||||
| func ValidateConfig(conf ApplyConfigProvider) error { | func ValidateConfig(conf ApplyConfigProvider) error { | ||||||
| 	if conf.NoColor() && conf.Color() { | 	if conf.NoColor() && conf.Color() { | ||||||
| 		return errors.New("--color and --no-color cannot be specified at the same time") | 		return errors.New("--color and --no-color cannot be specified at the same time") | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | // Package version is used to get the version of the Helmfile CLI.
 | ||||||
| package version | package version | ||||||
| 
 | 
 | ||||||
|  | // Version is the version of Helmfile
 | ||||||
| var Version string | var Version string | ||||||
|  |  | ||||||
|  | @ -51,7 +51,7 @@ func GetArgs(args string, state *state.HelmState) []string { | ||||||
| 					value := argVal[1] | 					value := argVal[1] | ||||||
| 					argsMap.SetArg(arg, value, false) | 					argsMap.SetArg(arg, value, false) | ||||||
| 				} else { | 				} else { | ||||||
| 					//check if next value is arg to flag
 | 					// check if next value is arg to flag
 | ||||||
| 					if index+1 < len(argsVals) { | 					if index+1 < len(argsVals) { | ||||||
| 						nextVal := argsVals[index+1] | 						nextVal := argsVals[index+1] | ||||||
| 						if strings.HasPrefix(nextVal, "--") { | 						if strings.HasPrefix(nextVal, "--") { | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ import ( | ||||||
| 
 | 
 | ||||||
| // TestGetArgs tests the GetArgs function
 | // TestGetArgs tests the GetArgs function
 | ||||||
| func TestGetArgs(t *testing.T) { | func TestGetArgs(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		args     string | 		args     string | ||||||
| 		expected string | 		expected string | ||||||
|  | @ -86,6 +85,5 @@ func TestSetArg(t *testing.T) { | ||||||
| 			require.NotContainsf(t, ap.flags, test.flag, "expected flag %s to be not set", test.flag) | 			require.NotContainsf(t, ap.flags, test.flag, "expected flag %s to be not set", test.flag) | ||||||
| 			require.NotContainsf(t, ap.m, test.flag, "expected m %s to be not set", test.flag) | 			require.NotContainsf(t, ap.m, test.flag, "expected m %s to be not set", test.flag) | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -9,9 +9,10 @@ import ( | ||||||
| 	"github.com/helmfile/helmfile/pkg/state" | 	"github.com/helmfile/helmfile/pkg/state" | ||||||
| 	"github.com/urfave/cli" | 	"github.com/urfave/cli" | ||||||
| 	"go.uber.org/zap" | 	"go.uber.org/zap" | ||||||
| 	"golang.org/x/crypto/ssh/terminal" | 	"golang.org/x/term" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // nolint: golint
 | ||||||
| type ConfigImpl struct { | type ConfigImpl struct { | ||||||
| 	c *cli.Context | 	c *cli.Context | ||||||
| 
 | 
 | ||||||
|  | @ -239,10 +240,10 @@ func (c ConfigImpl) Color() bool { | ||||||
| 	// we can't rely on helm-diff's ability to auto-detect term for color output.
 | 	// we can't rely on helm-diff's ability to auto-detect term for color output.
 | ||||||
| 	// See https://github.com/roboll/helmfile/issues/2043
 | 	// See https://github.com/roboll/helmfile/issues/2043
 | ||||||
| 
 | 
 | ||||||
| 	term := terminal.IsTerminal(int(os.Stdout.Fd())) | 	terminal := term.IsTerminal(int(os.Stdout.Fd())) | ||||||
| 	// https://github.com/databus23/helm-diff/issues/281
 | 	// https://github.com/databus23/helm-diff/issues/281
 | ||||||
| 	dumb := os.Getenv("TERM") == "dumb" | 	dumb := os.Getenv("TERM") == "dumb" | ||||||
| 	return term && !dumb | 	return terminal && !dumb | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c ConfigImpl) NoColor() bool { | func (c ConfigImpl) NoColor() bool { | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| package environment | package environment | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/google/go-cmp/cmp" |  | ||||||
| 	"testing" | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/google/go-cmp/cmp" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // See https://github.com/roboll/helmfile/issues/1150
 | // See https://github.com/roboll/helmfile/issues/1150
 | ||||||
|  |  | ||||||
|  | @ -18,12 +18,10 @@ func (context *HelmContext) GetTillerlessArgs(helm *execer) []string { | ||||||
| 	if context.Tillerless && !helm.IsHelm3() { | 	if context.Tillerless && !helm.IsHelm3() { | ||||||
| 		if context.TillerNamespace != "" { | 		if context.TillerNamespace != "" { | ||||||
| 			return []string{"tiller", "run", context.TillerNamespace, "--", helm.helmBinary} | 			return []string{"tiller", "run", context.TillerNamespace, "--", helm.helmBinary} | ||||||
| 		} else { | 		} | ||||||
| 		return []string{"tiller", "run", "--", helm.helmBinary} | 		return []string{"tiller", "run", "--", helm.helmBinary} | ||||||
| 	} | 	} | ||||||
| 	} else { |  | ||||||
| 	return []string{} | 	return []string{} | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (context *HelmContext) getTillerlessEnv() map[string]string { | func (context *HelmContext) getTillerlessEnv() map[string]string { | ||||||
|  | @ -41,7 +39,6 @@ func (context *HelmContext) getTillerlessEnv() map[string]string { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return result | 		return result | ||||||
| 	} else { |  | ||||||
| 		return map[string]string{} |  | ||||||
| 	} | 	} | ||||||
|  | 	return map[string]string{} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -52,7 +52,6 @@ func TestGetTillerlessArgs(t *testing.T) { | ||||||
| 			version:    *sr, | 			version:    *sr, | ||||||
| 		} | 		} | ||||||
| 		require.Equalf(t, test.expected, hc.GetTillerlessArgs(he), "expected result %s, received result %s", test.expected, hc.GetTillerlessArgs(he)) | 		require.Equalf(t, test.expected, hc.GetTillerlessArgs(he), "expected result %s, received result %s", test.expected, hc.GetTillerlessArgs(he)) | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -97,6 +96,5 @@ func TestGetTillerlessEnv(t *testing.T) { | ||||||
| 		t.Setenv(kubeconfigEnv, test.kubeconfig) | 		t.Setenv(kubeconfigEnv, test.kubeconfig) | ||||||
| 		result := hc.getTillerlessEnv() | 		result := hc.getTillerlessEnv() | ||||||
| 		require.Equalf(t, test.expected, result, "expected result %s, received result %s", test.expected, result) | 		require.Equalf(t, test.expected, result, "expected result %s, received result %s", test.expected, result) | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -74,7 +74,6 @@ func parseHelmVersion(versionStr string) (semver.Version, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func getHelmVersion(helmBinary string, runner Runner) (semver.Version, error) { | func getHelmVersion(helmBinary string, runner Runner) (semver.Version, error) { | ||||||
| 
 |  | ||||||
| 	// Autodetect from `helm version`
 | 	// Autodetect from `helm version`
 | ||||||
| 	outBytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil) | 	outBytes, err := runner.Execute(helmBinary, []string{"version", "--client", "--short"}, nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -84,15 +83,16 @@ func getHelmVersion(helmBinary string, runner Runner) (semver.Version, error) { | ||||||
| 	return parseHelmVersion(string(outBytes)) | 	return parseHelmVersion(string(outBytes)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func redactedUrl(chart string) string { | func redactedURL(chart string) string { | ||||||
| 	chartUrl, err := url.ParseRequestURI(chart) | 	chartURL, err := url.ParseRequestURI(chart) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return chart | 		return chart | ||||||
| 	} | 	} | ||||||
| 	return chartUrl.Redacted() | 	return chartURL.Redacted() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New for running helm commands
 | // New for running helm commands
 | ||||||
|  | // nolint: golint
 | ||||||
| func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer { | func New(helmBinary string, logger *zap.SugaredLogger, kubeContext string, runner Runner) *execer { | ||||||
| 	// TODO: proper error handling
 | 	// TODO: proper error handling
 | ||||||
| 	version, err := getHelmVersion(helmBinary, runner) | 	version, err := getHelmVersion(helmBinary, runner) | ||||||
|  | @ -206,7 +206,7 @@ func (helm *execer) UpdateDeps(chart string) error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (helm *execer) SyncRelease(context HelmContext, name, chart string, flags ...string) error { | func (helm *execer) SyncRelease(context HelmContext, name, chart string, flags ...string) error { | ||||||
| 	helm.logger.Infof("Upgrading release=%v, chart=%v", name, redactedUrl(chart)) | 	helm.logger.Infof("Upgrading release=%v, chart=%v", name, redactedURL(chart)) | ||||||
| 	preArgs := context.GetTillerlessArgs(helm) | 	preArgs := context.GetTillerlessArgs(helm) | ||||||
| 	env := context.getTillerlessEnv() | 	env := context.getTillerlessEnv() | ||||||
| 
 | 
 | ||||||
|  | @ -270,7 +270,6 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str | ||||||
| 
 | 
 | ||||||
| 	// Cache miss
 | 	// Cache miss
 | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 
 |  | ||||||
| 		secret = &decryptedSecret{} | 		secret = &decryptedSecret{} | ||||||
| 		helm.decryptedSecrets[absPath] = secret | 		helm.decryptedSecrets[absPath] = secret | ||||||
| 
 | 
 | ||||||
|  | @ -288,7 +287,6 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		secret.bytes = secretBytes | 		secret.bytes = secretBytes | ||||||
| 
 |  | ||||||
| 	} else { | 	} else { | ||||||
| 		// Cache hit
 | 		// Cache hit
 | ||||||
| 		helm.logger.Debugf("Found secret in cache %v", absPath) | 		helm.logger.Debugf("Found secret in cache %v", absPath) | ||||||
|  | @ -312,7 +310,9 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return "", err | 				return "", err | ||||||
| 			} | 			} | ||||||
| 			defer tmpFile.Close() | 			defer func() { | ||||||
|  | 				_ = tmpFile.Close() | ||||||
|  | 			}() | ||||||
| 
 | 
 | ||||||
| 			_, err = tmpFile.Write(content) | 			_, err = tmpFile.Write(content) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
|  | @ -334,7 +334,7 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (helm *execer) TemplateRelease(name string, chart string, flags ...string) error { | func (helm *execer) TemplateRelease(name string, chart string, flags ...string) error { | ||||||
| 	helm.logger.Infof("Templating release=%v, chart=%v", name, redactedUrl(chart)) | 	helm.logger.Infof("Templating release=%v, chart=%v", name, redactedURL(chart)) | ||||||
| 	var args []string | 	var args []string | ||||||
| 	if helm.IsHelm3() { | 	if helm.IsHelm3() { | ||||||
| 		args = []string{"template", name, chart} | 		args = []string{"template", name, chart} | ||||||
|  | @ -373,9 +373,9 @@ func (helm *execer) TemplateRelease(name string, chart string, flags ...string) | ||||||
| 
 | 
 | ||||||
| func (helm *execer) DiffRelease(context HelmContext, name, chart string, suppressDiff bool, flags ...string) error { | func (helm *execer) DiffRelease(context HelmContext, name, chart string, suppressDiff bool, flags ...string) error { | ||||||
| 	if context.Writer != nil { | 	if context.Writer != nil { | ||||||
| 		fmt.Fprintf(context.Writer, "Comparing release=%v, chart=%v\n", name, redactedUrl(chart)) | 		fmt.Fprintf(context.Writer, "Comparing release=%v, chart=%v\n", name, redactedURL(chart)) | ||||||
| 	} else { | 	} else { | ||||||
| 		helm.logger.Infof("Comparing release=%v, chart=%v", name, redactedUrl(chart)) | 		helm.logger.Infof("Comparing release=%v, chart=%v", name, redactedURL(chart)) | ||||||
| 	} | 	} | ||||||
| 	preArgs := context.GetTillerlessArgs(helm) | 	preArgs := context.GetTillerlessArgs(helm) | ||||||
| 	env := context.getTillerlessEnv() | 	env := context.getTillerlessEnv() | ||||||
|  | @ -390,15 +390,13 @@ func (helm *execer) DiffRelease(context HelmContext, name, chart string, suppres | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if detailedExitcodeEnabled { | 	if detailedExitcodeEnabled { | ||||||
| 		switch e := err.(type) { | 		e, ok := err.(ExitError) | ||||||
| 		case ExitError: | 		if ok && e.ExitStatus() == 2 { | ||||||
| 			if e.ExitStatus() == 2 { |  | ||||||
| 			if !(suppressDiff) { | 			if !(suppressDiff) { | ||||||
| 				helm.write(context.Writer, out) | 				helm.write(context.Writer, out) | ||||||
| 			} | 			} | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 	} else if !(suppressDiff) { | 	} else if !(suppressDiff) { | ||||||
| 		helm.write(context.Writer, out) | 		helm.write(context.Writer, out) | ||||||
| 	} | 	} | ||||||
|  | @ -413,7 +411,7 @@ func (helm *execer) Lint(name, chart string, flags ...string) error { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (helm *execer) Fetch(chart string, flags ...string) error { | func (helm *execer) Fetch(chart string, flags ...string) error { | ||||||
| 	helm.logger.Infof("Fetching %v", redactedUrl(chart)) | 	helm.logger.Infof("Fetching %v", redactedURL(chart)) | ||||||
| 	out, err := helm.exec(append([]string{"fetch", chart}, flags...), map[string]string{}) | 	out, err := helm.exec(append([]string{"fetch", chart}, flags...), map[string]string{}) | ||||||
| 	helm.info(out) | 	helm.info(out) | ||||||
| 	return err | 	return err | ||||||
|  | @ -432,7 +430,9 @@ func (helm *execer) ChartPull(chart string, flags ...string) error { | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		defer os.RemoveAll(tempDir) | 		defer func() { | ||||||
|  | 			_ = os.RemoveAll(tempDir) | ||||||
|  | 		}() | ||||||
| 		helmArgs = []string{"fetch", ociChartURL, "--version", ociChartTag, "--destination", tempDir} | 		helmArgs = []string{"fetch", ociChartURL, "--version", ociChartTag, "--destination", tempDir} | ||||||
| 	} else { | 	} else { | ||||||
| 		helmArgs = []string{"chart", "pull", chart} | 		helmArgs = []string{"chart", "pull", chart} | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ func (mock *mockRunner) Execute(cmd string, args []string, env map[string]string | ||||||
| 	return mock.output, mock.err | 	return mock.output, mock.err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // nolint: golint
 | ||||||
| func MockExecer(logger *zap.SugaredLogger, kubeContext string) *execer { | func MockExecer(logger *zap.SugaredLogger, kubeContext string) *execer { | ||||||
| 	execer := New("helm", logger, kubeContext, &mockRunner{}) | 	execer := New("helm", logger, kubeContext, &mockRunner{}) | ||||||
| 	return execer | 	return execer | ||||||
|  | @ -816,14 +817,14 @@ func Test_GetVersion(t *testing.T) { | ||||||
| 	helm := New("helm", NewLogger(os.Stdout, "info"), "dev", &helm2Runner) | 	helm := New("helm", NewLogger(os.Stdout, "info"), "dev", &helm2Runner) | ||||||
| 	ver := helm.GetVersion() | 	ver := helm.GetVersion() | ||||||
| 	if ver.Major != 2 || ver.Minor != 16 || ver.Patch != 1 { | 	if ver.Major != 2 || ver.Minor != 16 || ver.Patch != 1 { | ||||||
| 		t.Error(fmt.Sprintf("helmexec.GetVersion - did not detect correct Helm2 version; it was: %+v", ver)) | 		t.Errorf("helmexec.GetVersion - did not detect correct Helm2 version; it was: %+v", ver) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a\n")} | 	helm3Runner := mockRunner{output: []byte("v3.2.4+ge29ce2a\n")} | ||||||
| 	helm = New("helm", NewLogger(os.Stdout, "info"), "dev", &helm3Runner) | 	helm = New("helm", NewLogger(os.Stdout, "info"), "dev", &helm3Runner) | ||||||
| 	ver = helm.GetVersion() | 	ver = helm.GetVersion() | ||||||
| 	if ver.Major != 3 || ver.Minor != 2 || ver.Patch != 4 { | 	if ver.Major != 3 || ver.Minor != 2 || ver.Patch != 4 { | ||||||
| 		t.Error(fmt.Sprintf("helmexec.GetVersion - did not detect correct Helm3 version; it was: %+v", ver)) | 		t.Errorf("helmexec.GetVersion - did not detect correct Helm3 version; it was: %+v", ver) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| package helmexec | package helmexec | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"go.uber.org/zap" |  | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"go.uber.org/zap" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type logWriterGenerator struct { | type logWriterGenerator struct { | ||||||
|  |  | ||||||
|  | @ -10,57 +10,57 @@ func CastKeysToStrings(s interface{}) (map[string]interface{}, error) { | ||||||
| 	switch src := s.(type) { | 	switch src := s.(type) { | ||||||
| 	case map[interface{}]interface{}: | 	case map[interface{}]interface{}: | ||||||
| 		for k, v := range src { | 		for k, v := range src { | ||||||
| 			var str_k string | 			var strK string | ||||||
| 			switch typed_k := k.(type) { | 			switch typedK := k.(type) { | ||||||
| 			case string: | 			case string: | ||||||
| 				str_k = typed_k | 				strK = typedK | ||||||
| 			default: | 			default: | ||||||
| 				return nil, fmt.Errorf("unexpected type of key in map: expected string, got %T: value=%v, map=%v", typed_k, typed_k, src) | 				return nil, fmt.Errorf("unexpected type of key in map: expected string, got %T: value=%v, map=%v", typedK, typedK, src) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			casted_v, err := recursivelyStringifyMapKey(v) | 			castedV, err := recursivelyStringifyMapKey(v) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			new[str_k] = casted_v | 			new[strK] = castedV | ||||||
| 		} | 		} | ||||||
| 	case map[string]interface{}: | 	case map[string]interface{}: | ||||||
| 		for k, v := range src { | 		for k, v := range src { | ||||||
| 			casted_v, err := recursivelyStringifyMapKey(v) | 			castedV, err := recursivelyStringifyMapKey(v) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			new[k] = casted_v | 			new[k] = castedV | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return new, nil | 	return new, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func recursivelyStringifyMapKey(v interface{}) (interface{}, error) { | func recursivelyStringifyMapKey(v interface{}) (interface{}, error) { | ||||||
| 	var casted_v interface{} | 	var castedV interface{} | ||||||
| 	switch typed_v := v.(type) { | 	switch typedV := v.(type) { | ||||||
| 	case map[interface{}]interface{}, map[string]interface{}: | 	case map[interface{}]interface{}, map[string]interface{}: | ||||||
| 		tmp, err := CastKeysToStrings(typed_v) | 		tmp, err := CastKeysToStrings(typedV) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 		casted_v = tmp | 		castedV = tmp | ||||||
| 	case []interface{}: | 	case []interface{}: | ||||||
| 		a := []interface{}{} | 		a := []interface{}{} | ||||||
| 		for i := range typed_v { | 		for i := range typedV { | ||||||
| 			res, err := recursivelyStringifyMapKey(typed_v[i]) | 			res, err := recursivelyStringifyMapKey(typedV[i]) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
| 			a = append(a, res) | 			a = append(a, res) | ||||||
| 		} | 		} | ||||||
| 		casted_v = a | 		castedV = a | ||||||
| 	default: | 	default: | ||||||
| 		casted_v = typed_v | 		castedV = typedV | ||||||
| 	} | 	} | ||||||
| 	return casted_v, nil | 	return castedV, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type arg interface { | type arg interface { | ||||||
|  | @ -169,7 +169,7 @@ func ParseKey(key string) []string { | ||||||
| 			r = append(r, part) | 			r = append(r, part) | ||||||
| 			part = "" | 			part = "" | ||||||
| 		} else { | 		} else { | ||||||
| 			part = part + string(rune) | 			part += string(rune) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if len(part) > 0 { | 	if len(part) > 0 { | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| package plugins | package plugins | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/variantdev/vals" |  | ||||||
| 	"sync" | 	"sync" | ||||||
|  | 
 | ||||||
|  | 	"github.com/variantdev/vals" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
|  |  | ||||||
|  | @ -103,8 +103,7 @@ func (r *Remote) Locate(urlOrPath string) (string, error) { | ||||||
| 	} | 	} | ||||||
| 	fetched, err := r.Fetch(urlOrPath) | 	fetched, err := r.Fetch(urlOrPath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		switch err.(type) { | 		if _, ok := err.(InvalidURLError); ok { | ||||||
| 		case InvalidURLError: |  | ||||||
| 			return urlOrPath, nil | 			return urlOrPath, nil | ||||||
| 		} | 		} | ||||||
| 		return "", err | 		return "", err | ||||||
|  | @ -134,8 +133,7 @@ func IsRemote(goGetterSrc string) bool { | ||||||
| func Parse(goGetterSrc string) (*Source, error) { | func Parse(goGetterSrc string) (*Source, error) { | ||||||
| 	items := strings.Split(goGetterSrc, "::") | 	items := strings.Split(goGetterSrc, "::") | ||||||
| 	var getter string | 	var getter string | ||||||
| 	switch len(items) { | 	if len(items) == 2 { | ||||||
| 	case 2: |  | ||||||
| 		getter = items[0] | 		getter = items[0] | ||||||
| 		goGetterSrc = items[1] | 		goGetterSrc = items[1] | ||||||
| 	} | 	} | ||||||
|  | @ -199,7 +197,7 @@ func (r *Remote) Fetch(goGetterSrc string, cacheDirOpt ...string) (string, error | ||||||
| 		if q.Has("sshkey") { | 		if q.Has("sshkey") { | ||||||
| 			q.Set("sshkey", "redacted") | 			q.Set("sshkey", "redacted") | ||||||
| 		} | 		} | ||||||
| 		paramsKey := strings.Replace(q.Encode(), "&", "_", -1) | 		paramsKey := strings.ReplaceAll(q.Encode(), "&", "_") | ||||||
| 		cacheKey = fmt.Sprintf("%s.%s", dirKey, paramsKey) | 		cacheKey = fmt.Sprintf("%s.%s", dirKey, paramsKey) | ||||||
| 	} else { | 	} else { | ||||||
| 		cacheKey = dirKey | 		cacheKey = dirKey | ||||||
|  |  | ||||||
|  | @ -206,7 +206,9 @@ func (st *HelmState) updateDependenciesInTempDir(shell helmexec.DependencyUpdate | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("unable to create dir: %v", err) | 		return nil, fmt.Errorf("unable to create dir: %v", err) | ||||||
| 	} | 	} | ||||||
| 	defer os.RemoveAll(d) | 	defer func() { | ||||||
|  | 		_ = os.RemoveAll(d) | ||||||
|  | 	}() | ||||||
| 
 | 
 | ||||||
| 	return updateDependencies(st, shell, unresolved, filename, d) | 	return updateDependencies(st, shell, unresolved, filename, d) | ||||||
| } | } | ||||||
|  | @ -219,9 +221,9 @@ func getUnresolvedDependenciess(st *HelmState) (string, *UnresolvedDependencies, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	unresolved := &UnresolvedDependencies{deps: map[string][]unresolvedChartDependency{}} | 	unresolved := &UnresolvedDependencies{deps: map[string][]unresolvedChartDependency{}} | ||||||
| 	//if err := unresolved.Add("stable/envoy", "https://kubernetes-charts.storage.googleapis.com", ""); err != nil {
 | 	// if err := unresolved.Add("stable/envoy", "https://kubernetes-charts.storage.googleapis.com", ""); err != nil {
 | ||||||
| 	//	 panic(err)
 | 	//	 panic(err)
 | ||||||
| 	//}
 | 	// }
 | ||||||
| 
 | 
 | ||||||
| 	for _, r := range st.Releases { | 	for _, r := range st.Releases { | ||||||
| 		repo, chart, ok := resolveRemoteChart(r.Chart) | 		repo, chart, ok := resolveRemoteChart(r.Chart) | ||||||
|  | @ -269,6 +271,7 @@ type chartDependencyManager struct { | ||||||
| 	writeFile func(string, []byte, os.FileMode) error | 	writeFile func(string, []byte, os.FileMode) error | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // nolint: golint
 | ||||||
| func NewChartDependencyManager(name string, logger *zap.SugaredLogger) *chartDependencyManager { | func NewChartDependencyManager(name string, logger *zap.SugaredLogger) *chartDependencyManager { | ||||||
| 	return &chartDependencyManager{ | 	return &chartDependencyManager{ | ||||||
| 		Name:      name, | 		Name:      name, | ||||||
|  | @ -324,7 +327,6 @@ func (m *chartDependencyManager) updateHelm2(shell helmexec.DependencyUpdater, w | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *chartDependencyManager) doUpdate(chartLockFile string, unresolved *UnresolvedDependencies, shell helmexec.DependencyUpdater, wd string) (*ResolvedDependencies, error) { | func (m *chartDependencyManager) doUpdate(chartLockFile string, unresolved *UnresolvedDependencies, shell helmexec.DependencyUpdater, wd string) (*ResolvedDependencies, error) { | ||||||
| 
 |  | ||||||
| 	// Generate `requirements.lock` of the temporary local chart by coping `<basename>.lock`
 | 	// Generate `requirements.lock` of the temporary local chart by coping `<basename>.lock`
 | ||||||
| 	lockFile := m.lockFileName() | 	lockFile := m.lockFileName() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ const ( | ||||||
| 	DefaultHelmBinary = "helm" | 	DefaultHelmBinary = "helm" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // nolint: golint
 | ||||||
| type StateLoadError struct { | type StateLoadError struct { | ||||||
| 	msg   string | 	msg   string | ||||||
| 	Cause error | 	Cause error | ||||||
|  | @ -231,7 +232,6 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if len(envSpec.Secrets) > 0 { | 		if len(envSpec.Secrets) > 0 { | ||||||
| 
 |  | ||||||
| 			var envSecretFiles []string | 			var envSecretFiles []string | ||||||
| 			for _, urlOrPath := range envSpec.Secrets { | 			for _, urlOrPath := range envSpec.Secrets { | ||||||
| 				resolved, skipped, err := st.storage().resolveFile(envSpec.MissingFileHandler, "environment values", urlOrPath) | 				resolved, skipped, err := st.storage().resolveFile(envSpec.MissingFileHandler, "environment values", urlOrPath) | ||||||
|  | @ -305,6 +305,7 @@ func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles | ||||||
| 					results <- secretResult{secret.id, nil, err, secret.path} | 					results <- secretResult{secret.id, nil, err, secret.path} | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  | 				// nolint: staticcheck
 | ||||||
| 				defer func() { | 				defer func() { | ||||||
| 					if err := c.DeleteFile(decFile); err != nil { | 					if err := c.DeleteFile(decFile); err != nil { | ||||||
| 						c.logger.Warnf("removing decrypted file %s: %w", decFile, err) | 						c.logger.Warnf("removing decrypted file %s: %w", decFile, err) | ||||||
|  |  | ||||||
|  | @ -102,7 +102,7 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R | ||||||
| 					return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err) | 					return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err) | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				s, err := renderer.RenderTemplateContentToBuffer([]byte(serialized)) | 				s, err := renderer.RenderTemplateContentToBuffer(serialized) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, serialized, err) | 					return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, serialized, err) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -873,7 +873,7 @@ func (st *HelmState) SyncReleases(affectedReleases *AffectedReleases, helm helme | ||||||
| 					affectedReleases.Upgraded = append(affectedReleases.Upgraded, release) | 					affectedReleases.Upgraded = append(affectedReleases.Upgraded, release) | ||||||
| 					m.Unlock() | 					m.Unlock() | ||||||
| 					installedVersion, err := st.getDeployedVersion(context, helm, release) | 					installedVersion, err := st.getDeployedVersion(context, helm, release) | ||||||
| 					if err != nil { //err is not really impacting so just log it
 | 					if err != nil { // err is not really impacting so just log it
 | ||||||
| 						st.logger.Debugf("getting deployed release version failed:%v", err) | 						st.logger.Debugf("getting deployed release version failed:%v", err) | ||||||
| 					} else { | 					} else { | ||||||
| 						release.installedVersion = installedVersion | 						release.installedVersion = installedVersion | ||||||
|  | @ -1121,6 +1121,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre | ||||||
| 
 | 
 | ||||||
| 				chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex) | 				chartification, clean, err := st.PrepareChartify(helm, release, chartPath, workerIndex) | ||||||
| 				if !opts.SkipCleanup { | 				if !opts.SkipCleanup { | ||||||
|  | 					// nolint: staticcheck
 | ||||||
| 					defer clean() | 					defer clean() | ||||||
| 				} | 				} | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
|  | @ -1350,7 +1351,6 @@ func (o *TemplateOpts) Apply(opts *TemplateOpts) { | ||||||
| // TemplateReleases wrapper for executing helm template on the releases
 | // TemplateReleases wrapper for executing helm template on the releases
 | ||||||
| func (st *HelmState) TemplateReleases(helm helmexec.Interface, outputDir string, additionalValues []string, args []string, workerLimit int, | func (st *HelmState) TemplateReleases(helm helmexec.Interface, outputDir string, additionalValues []string, args []string, workerLimit int, | ||||||
| 	validate bool, opt ...TemplateOpt) []error { | 	validate bool, opt ...TemplateOpt) []error { | ||||||
| 
 |  | ||||||
| 	opts := &TemplateOpts{} | 	opts := &TemplateOpts{} | ||||||
| 	for _, o := range opt { | 	for _, o := range opt { | ||||||
| 		o.Apply(opts) | 		o.Apply(opts) | ||||||
|  | @ -2100,7 +2100,7 @@ func markExcludedReleases(releases []ReleaseSpec, selectors []string, commonLabe | ||||||
| 		// Strip off just the last portion for the name stable/newrelic would give newrelic
 | 		// Strip off just the last portion for the name stable/newrelic would give newrelic
 | ||||||
| 		chartSplit := strings.Split(r.Chart, "/") | 		chartSplit := strings.Split(r.Chart, "/") | ||||||
| 		r.Labels["chart"] = chartSplit[len(chartSplit)-1] | 		r.Labels["chart"] = chartSplit[len(chartSplit)-1] | ||||||
| 		//Merge CommonLabels into release labels
 | 		// Merge CommonLabels into release labels
 | ||||||
| 		for k, v := range commonLabels { | 		for k, v := range commonLabels { | ||||||
| 			r.Labels[k] = v | 			r.Labels[k] = v | ||||||
| 		} | 		} | ||||||
|  | @ -2579,7 +2579,6 @@ func (st *HelmState) chartVersionFlags(release *ReleaseSpec) []string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (st *HelmState) appendApiVersionsFlags(flags []string, r *ReleaseSpec) []string { | func (st *HelmState) appendApiVersionsFlags(flags []string, r *ReleaseSpec) []string { | ||||||
| 
 |  | ||||||
| 	if len(r.ApiVersions) != 0 { | 	if len(r.ApiVersions) != 0 { | ||||||
| 		for _, a := range r.ApiVersions { | 		for _, a := range r.ApiVersions { | ||||||
| 			flags = append(flags, "--api-versions", a) | 			flags = append(flags, "--api-versions", a) | ||||||
|  | @ -2745,7 +2744,9 @@ func (st *HelmState) generateTemporaryReleaseValuesFiles(release *ReleaseSpec, v | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return generatedFiles, err | 				return generatedFiles, err | ||||||
| 			} | 			} | ||||||
| 			defer valfile.Close() | 			defer func() { | ||||||
|  | 				_ = valfile.Close() | ||||||
|  | 			}() | ||||||
| 
 | 
 | ||||||
| 			if _, err := valfile.Write(yamlBytes); err != nil { | 			if _, err := valfile.Write(yamlBytes); err != nil { | ||||||
| 				return generatedFiles, fmt.Errorf("failed to write %s: %v", valfile.Name(), err) | 				return generatedFiles, fmt.Errorf("failed to write %s: %v", valfile.Name(), err) | ||||||
|  | @ -2759,10 +2760,14 @@ func (st *HelmState) generateTemporaryReleaseValuesFiles(release *ReleaseSpec, v | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return generatedFiles, err | 				return generatedFiles, err | ||||||
| 			} | 			} | ||||||
| 			defer valfile.Close() | 			defer func() { | ||||||
|  | 				_ = valfile.Close() | ||||||
|  | 			}() | ||||||
| 
 | 
 | ||||||
| 			encoder := yaml.NewEncoder(valfile) | 			encoder := yaml.NewEncoder(valfile) | ||||||
| 			defer encoder.Close() | 			defer func() { | ||||||
|  | 				_ = encoder.Close() | ||||||
|  | 			}() | ||||||
| 
 | 
 | ||||||
| 			if err := encoder.Encode(typedValue); err != nil { | 			if err := encoder.Encode(typedValue); err != nil { | ||||||
| 				return generatedFiles, err | 				return generatedFiles, err | ||||||
|  | @ -3031,13 +3036,13 @@ func (ar *AffectedReleases) DisplayAffectedReleases(logger *zap.SugaredLogger) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func escape(value string) string { | func escape(value string) string { | ||||||
| 	intermediate := strings.Replace(value, "{", "\\{", -1) | 	intermediate := strings.ReplaceAll(value, "{", "\\{") | ||||||
| 	intermediate = strings.Replace(intermediate, "}", "\\}", -1) | 	intermediate = strings.ReplaceAll(intermediate, "}", "\\}") | ||||||
| 	return strings.Replace(intermediate, ",", "\\,", -1) | 	return strings.ReplaceAll(intermediate, ",", "\\,") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //MarshalYAML will ensure we correctly marshal SubHelmfileSpec structure correctly so it can be unmarshalled at some
 | // MarshalYAML will ensure we correctly marshal SubHelmfileSpec structure correctly so it can be unmarshalled at some
 | ||||||
| //future time
 | // future time
 | ||||||
| func (p SubHelmfileSpec) MarshalYAML() (interface{}, error) { | func (p SubHelmfileSpec) MarshalYAML() (interface{}, error) { | ||||||
| 	type SubHelmfileSpecTmp struct { | 	type SubHelmfileSpecTmp struct { | ||||||
| 		Path               string        `yaml:"path,omitempty"` | 		Path               string        `yaml:"path,omitempty"` | ||||||
|  | @ -3053,10 +3058,9 @@ func (p SubHelmfileSpec) MarshalYAML() (interface{}, error) { | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //UnmarshalYAML will unmarshal the helmfile yaml section and fill the SubHelmfileSpec structure
 | // UnmarshalYAML will unmarshal the helmfile yaml section and fill the SubHelmfileSpec structure
 | ||||||
| //this is required to keep allowing string scalar for defining helmfile
 | // this is required to keep allowing string scalar for defining helmfile
 | ||||||
| func (hf *SubHelmfileSpec) UnmarshalYAML(unmarshal func(interface{}) error) error { | func (hf *SubHelmfileSpec) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||||||
| 
 |  | ||||||
| 	var tmp interface{} | 	var tmp interface{} | ||||||
| 	if err := unmarshal(&tmp); err != nil { | 	if err := unmarshal(&tmp); err != nil { | ||||||
| 		return err | 		return err | ||||||
|  | @ -3081,12 +3085,12 @@ func (hf *SubHelmfileSpec) UnmarshalYAML(unmarshal func(interface{}) error) erro | ||||||
| 		hf.SelectorsInherited = subHelmfileSpecTmp.SelectorsInherited | 		hf.SelectorsInherited = subHelmfileSpecTmp.SelectorsInherited | ||||||
| 		hf.Environment = subHelmfileSpecTmp.Environment | 		hf.Environment = subHelmfileSpecTmp.Environment | ||||||
| 	} | 	} | ||||||
| 	//since we cannot make sur the "console" string can be red after the "path" we must check we don't have
 | 	// since we cannot make sur the "console" string can be red after the "path" we must check we don't have
 | ||||||
| 	//a SubHelmfileSpec with only selector and no path
 | 	// a SubHelmfileSpec with only selector and no path
 | ||||||
| 	if hf.Selectors != nil && hf.Path == "" { | 	if hf.Selectors != nil && hf.Path == "" { | ||||||
| 		return fmt.Errorf("found 'selectors' definition without path: %v", hf.Selectors) | 		return fmt.Errorf("found 'selectors' definition without path: %v", hf.Selectors) | ||||||
| 	} | 	} | ||||||
| 	//also exclude SelectorsInherited to true and explicit selectors
 | 	// also exclude SelectorsInherited to true and explicit selectors
 | ||||||
| 	if hf.SelectorsInherited && len(hf.Selectors) > 0 { | 	if hf.SelectorsInherited && len(hf.Selectors) > 0 { | ||||||
| 		return fmt.Errorf("you cannot use 'SelectorsInherited: true' along with and explicit selector for path: %v", hf.Path) | 		return fmt.Errorf("you cannot use 'SelectorsInherited: true' along with and explicit selector for path: %v", hf.Path) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -44,7 +44,6 @@ func getBoolRefFromStringTemplate(templateRef string) (*bool, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func updateBoolTemplatedValues(r *ReleaseSpec) error { | func updateBoolTemplatedValues(r *ReleaseSpec) error { | ||||||
| 
 |  | ||||||
| 	if r.InstalledTemplate != nil { | 	if r.InstalledTemplate != nil { | ||||||
| 		if installed, err := getBoolRefFromStringTemplate(*r.InstalledTemplate); err != nil { | 		if installed, err := getBoolRefFromStringTemplate(*r.InstalledTemplate); err != nil { | ||||||
| 			return fmt.Errorf("installedTemplate: %v", err) | 			return fmt.Errorf("installedTemplate: %v", err) | ||||||
|  |  | ||||||
|  | @ -201,7 +201,6 @@ func TestHelmState_executeTemplates(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestHelmState_recursiveRefsTemplates(t *testing.T) { | func TestHelmState_recursiveRefsTemplates(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name  string | 		name  string | ||||||
| 		input ReleaseSpec | 		input ReleaseSpec | ||||||
|  |  | ||||||
|  | @ -17,7 +17,6 @@ type result struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (st *HelmState) scatterGather(concurrency int, items int, produceInputs func(), receiveInputsAndProduceIntermediates func(int), aggregateIntermediates func()) { | func (st *HelmState) scatterGather(concurrency int, items int, produceInputs func(), receiveInputsAndProduceIntermediates func(int), aggregateIntermediates func()) { | ||||||
| 
 |  | ||||||
| 	if concurrency < 1 || concurrency > items { | 	if concurrency < 1 || concurrency > items { | ||||||
| 		concurrency = items | 		concurrency = items | ||||||
| 	} | 	} | ||||||
|  | @ -53,7 +52,6 @@ func (st *HelmState) scatterGather(concurrency int, items int, produceInputs fun | ||||||
| 
 | 
 | ||||||
| func (st *HelmState) scatterGatherReleases(helm helmexec.Interface, concurrency int, | func (st *HelmState) scatterGatherReleases(helm helmexec.Interface, concurrency int, | ||||||
| 	do func(ReleaseSpec, int) error) []error { | 	do func(ReleaseSpec, int) error) []error { | ||||||
| 
 |  | ||||||
| 	return st.iterateOnReleases(helm, concurrency, st.Releases, do) | 	return st.iterateOnReleases(helm, concurrency, st.Releases, do) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -144,7 +142,6 @@ func GroupReleasesByDependency(releases []Release, opts PlanOptions) ([][]Releas | ||||||
| 
 | 
 | ||||||
| 	d := dag.New() | 	d := dag.New() | ||||||
| 	for i, r := range releases { | 	for i, r := range releases { | ||||||
| 
 |  | ||||||
| 		id := ReleaseToID(&r.ReleaseSpec) | 		id := ReleaseToID(&r.ReleaseSpec) | ||||||
| 
 | 
 | ||||||
| 		idToReleases[id] = append(idToReleases[id], r) | 		idToReleases[id] = append(idToReleases[id], r) | ||||||
|  |  | ||||||
|  | @ -1244,7 +1244,6 @@ func TestHelmState_SyncReleases_MissingValuesFileForUndesiredRelease(t *testing. | ||||||
| 					t.Fatalf("unexpected error(s): expected=0, got=%d: %v", len(errs), errs) | 					t.Fatalf("unexpected error(s): expected=0, got=%d: %v", len(errs), errs) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -1392,7 +1391,6 @@ func TestHelmState_SyncReleasesAffectedRealeases(t *testing.T) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func testEq(a []*ReleaseSpec, b []*exectest.Release) bool { | func testEq(a []*ReleaseSpec, b []*exectest.Release) bool { | ||||||
| 
 |  | ||||||
| 	// If one is nil, the other must also be nil.
 | 	// If one is nil, the other must also be nil.
 | ||||||
| 	if (a == nil) != (b == nil) { | 	if (a == nil) != (b == nil) { | ||||||
| 		return false | 		return false | ||||||
|  | @ -1473,7 +1471,7 @@ func TestGetDeployedVersion(t *testing.T) { | ||||||
| 			helm := &exectest.Helm{ | 			helm := &exectest.Helm{ | ||||||
| 				Lists: map[exectest.ListKey]string{}, | 				Lists: map[exectest.ListKey]string{}, | ||||||
| 			} | 			} | ||||||
| 			//simulate the helm.list call result
 | 			// simulate the helm.list call result
 | ||||||
| 			helm.Lists[exectest.ListKey{Filter: "^" + tt.release.Name + "$", Flags: "--deleting--deployed--failed--pending"}] = tt.listResult | 			helm.Lists[exectest.ListKey{Filter: "^" + tt.release.Name + "$", Flags: "--deleting--deployed--failed--pending"}] = tt.listResult | ||||||
| 
 | 
 | ||||||
| 			affectedReleases := AffectedReleases{} | 			affectedReleases := AffectedReleases{} | ||||||
|  | @ -1652,10 +1650,8 @@ func TestHelmState_DiffFlags(t *testing.T) { | ||||||
| 					t.Errorf("HelmState.flagsForDiff() for [%s][%s] = %v, want %v", tt.name, tt.releases[j].Name, flags, tt.wantDiffFlags) | 					t.Errorf("HelmState.flagsForDiff() for [%s][%s] = %v, want %v", tt.name, tt.releases[j].Name, flags, tt.wantDiffFlags) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestHelmState_SyncReleasesCleanup(t *testing.T) { | func TestHelmState_SyncReleasesCleanup(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -2,11 +2,13 @@ package state | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/helmfile/helmfile/pkg/remote" |  | ||||||
| 	"go.uber.org/zap" |  | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"sort" | 	"sort" | ||||||
|  | 
 | ||||||
|  | 	"go.uber.org/zap" | ||||||
|  | 
 | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/remote" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Storage struct { | type Storage struct { | ||||||
|  |  | ||||||
|  | @ -83,7 +83,10 @@ func HashObject(obj interface{}) (string, error) { | ||||||
| 		DisableMethods: true, | 		DisableMethods: true, | ||||||
| 		SpewKeys:       true, | 		SpewKeys:       true, | ||||||
| 	} | 	} | ||||||
| 	printer.Fprintf(hash, "%#v", obj) | 	_, err := printer.Fprintf(hash, "%#v", obj) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	sum := fmt.Sprint(hash.Sum32()) | 	sum := fmt.Sprint(hash.Sum32()) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ func TestGenerateID(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	for id, n := range ids { | 	for id, n := range ids { | ||||||
| 		if n > 1 { | 		if n > 1 { | ||||||
| 			t.Fatalf("too many occurences of %s: %d", id, n) | 			t.Fatalf("too many occurrences of %s: %d", id, n) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func isLocalChart(chart string) bool { | func isLocalChart(chart string) bool { | ||||||
| 	regex, _ := regexp.Compile("^[.]?./") | 	regex := regexp.MustCompile("^[.]?./") | ||||||
| 	matched := regex.MatchString(chart) | 	matched := regex.MatchString(chart) | ||||||
| 	if matched { | 	if matched { | ||||||
| 		return true | 		return true | ||||||
|  |  | ||||||
|  | @ -73,7 +73,7 @@ func (f *TestFs) ReadFile(filename string) ([]byte, error) { | ||||||
| 		return []byte(nil), os.ErrNotExist | 		return []byte(nil), os.ErrNotExist | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	f.fileReaderCalls += 1 | 	f.fileReaderCalls++ | ||||||
| 
 | 
 | ||||||
| 	f.successfulReads = append(f.successfulReads, filename) | 	f.successfulReads = append(f.successfulReads, filename) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,6 +35,6 @@ func CaptureStdout(f func()) string { | ||||||
| 	}() | 	}() | ||||||
| 	wg.Wait() | 	wg.Wait() | ||||||
| 	f() | 	f() | ||||||
| 	writer.Close() | 	_ = writer.Close() | ||||||
| 	return <-out | 	return <-out | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -130,7 +130,9 @@ func (c *Context) EnvExec(envs map[string]interface{}, command string, args []in | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		g.Go(func() error { | 		g.Go(func() error { | ||||||
| 			defer stdin.Close() | 			defer func() { | ||||||
|  | 				_ = stdin.Close() | ||||||
|  | 			}() | ||||||
| 
 | 
 | ||||||
| 			size := len(input) | 			size := len(input) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -104,6 +104,7 @@ func TestReadFile_PassAbsPath(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestToYaml_UnsupportedNestedMapKey(t *testing.T) { | func TestToYaml_UnsupportedNestedMapKey(t *testing.T) { | ||||||
| 	expected := `` | 	expected := `` | ||||||
|  | 	// nolint: unconvert
 | ||||||
| 	vals := Values(map[string]interface{}{ | 	vals := Values(map[string]interface{}{ | ||||||
| 		"foo": map[interface{}]interface{}{ | 		"foo": map[interface{}]interface{}{ | ||||||
| 			"bar": "BAR", | 			"bar": "BAR", | ||||||
|  | @ -125,6 +126,7 @@ func TestToYaml(t *testing.T) { | ||||||
| 	expected := `foo: | 	expected := `foo: | ||||||
|   bar: BAR |   bar: BAR | ||||||
| ` | ` | ||||||
|  | 	// nolint: unconvert
 | ||||||
| 	vals := Values(map[string]interface{}{ | 	vals := Values(map[string]interface{}{ | ||||||
| 		"foo": map[string]interface{}{ | 		"foo": map[string]interface{}{ | ||||||
| 			"bar": "BAR", | 			"bar": "BAR", | ||||||
|  | @ -143,6 +145,7 @@ func TestFromYaml(t *testing.T) { | ||||||
| 	raw := `foo: | 	raw := `foo: | ||||||
|   bar: BAR |   bar: BAR | ||||||
| ` | ` | ||||||
|  | 	// nolint: unconvert
 | ||||||
| 	expected := Values(map[string]interface{}{ | 	expected := Values(map[string]interface{}{ | ||||||
| 		"foo": map[string]interface{}{ | 		"foo": map[string]interface{}{ | ||||||
| 			"bar": "BAR", | 			"bar": "BAR", | ||||||
|  | @ -276,7 +279,6 @@ func TestRequired(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| // TestRequiredEnv tests that RequiredEnv returns an error if the environment variable is not set.
 | // TestRequiredEnv tests that RequiredEnv returns an error if the environment variable is not set.
 | ||||||
| func TestRequiredEnv(t *testing.T) { | func TestRequiredEnv(t *testing.T) { | ||||||
| 
 |  | ||||||
| 	// test that the environment variable is not set
 | 	// test that the environment variable is not set
 | ||||||
| 	envKey := "HelmFile" | 	envKey := "HelmFile" | ||||||
| 	envVal, err := RequiredEnv(envKey) | 	envVal, err := RequiredEnv(envKey) | ||||||
|  | @ -298,7 +300,6 @@ func TestRequiredEnv(t *testing.T) { | ||||||
| 	envVal, err = RequiredEnv(envKey) | 	envVal, err = RequiredEnv(envKey) | ||||||
| 	require.Nilf(t, err, "Expected no error to be returned when environment variable %s is set to a non-empty string", envKey) | 	require.Nilf(t, err, "Expected no error to be returned when environment variable %s is set to a non-empty string", envKey) | ||||||
| 	require.Equalf(t, expected, envVal, "Expected %s to be returned when environment variable %s is set to a non-empty string", expected, envKey) | 	require.Equalf(t, expected, envVal, "Expected %s to be returned when environment variable %s is set to a non-empty string", expected, envKey) | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // TestExec tests that Exec returns the expected output.
 | // TestExec tests that Exec returns the expected output.
 | ||||||
|  |  | ||||||
|  | @ -2,8 +2,9 @@ package tmpl | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"github.com/Masterminds/sprig/v3" |  | ||||||
| 	"text/template" | 	"text/template" | ||||||
|  | 
 | ||||||
|  | 	"github.com/Masterminds/sprig/v3" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (c *Context) CreateFuncMap() template.FuncMap { | func (c *Context) CreateFuncMap() template.FuncMap { | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ import ( | ||||||
| 	"github.com/variantdev/vals" | 	"github.com/variantdev/vals" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| //to generate mock run mockgen -source=expand_secret_ref.go -destination=expand_secrets_mock.go -package=tmpl
 | // to generate mock run mockgen -source=expand_secret_ref.go -destination=expand_secrets_mock.go -package=tmpl
 | ||||||
| type valClient interface { | type valClient interface { | ||||||
| 	Eval(template map[string]interface{}) (map[string]interface{}, error) | 	Eval(template map[string]interface{}) (map[string]interface{}, error) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,9 +2,10 @@ package tmpl | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/helmfile/helmfile/pkg/environment" |  | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/environment" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var emptyEnvTmplData = map[string]interface{}{ | var emptyEnvTmplData = map[string]interface{}{ | ||||||
|  | @ -50,8 +51,7 @@ func TestRenderToBytes_Yaml(t *testing.T) { | ||||||
| ` | ` | ||||||
| 	valuesFile := "values.yaml" | 	valuesFile := "values.yaml" | ||||||
| 	r := NewFileRenderer(func(filename string) ([]byte, error) { | 	r := NewFileRenderer(func(filename string) ([]byte, error) { | ||||||
| 		switch filename { | 		if filename == valuesFile { | ||||||
| 		case valuesFile: |  | ||||||
| 			return []byte(valuesYamlContent), nil | 			return []byte(valuesYamlContent), nil | ||||||
| 		} | 		} | ||||||
| 		return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", valuesFile, filename) | 		return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", valuesFile, filename) | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ func get(path string, varArgs ...interface{}) (interface{}, error) { | ||||||
| 		def = varArgs[0] | 		def = varArgs[0] | ||||||
| 		obj = varArgs[1] | 		obj = varArgs[1] | ||||||
| 	default: | 	default: | ||||||
| 		return nil, fmt.Errorf("unexpected number of args pased to the template function get(path, [def, ]obj): expected 1 or 2, got %d, args was %v", len(varArgs), varArgs) | 		return nil, fmt.Errorf("unexpected number of args passed to the template function get(path, [def, ]obj): expected 1 or 2, got %d, args was %v", len(varArgs), varArgs) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if path == "" { | 	if path == "" { | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ type TextRenderer interface { | ||||||
| 	RenderTemplateText(text string) (string, error) | 	RenderTemplateText(text string) (string, error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // nolint: golint
 | ||||||
| func NewTextRenderer(readFile func(filename string) ([]byte, error), basePath string, data interface{}) *templateTextRenderer { | func NewTextRenderer(readFile func(filename string) ([]byte, error), basePath string, data interface{}) *templateTextRenderer { | ||||||
| 	return &templateTextRenderer{ | 	return &templateTextRenderer{ | ||||||
| 		ReadText: readFile, | 		ReadText: readFile, | ||||||
|  |  | ||||||
|  | @ -93,15 +93,15 @@ func run(cmd *cobra.Command, args []string) { | ||||||
| 		for _, p := range ps.list { | 		for _, p := range ps.list { | ||||||
| 			switch { | 			switch { | ||||||
| 			case p.left != nil && p.right == nil: | 			case p.left != nil && p.right == nil: | ||||||
| 				fmt.Fprintf(os.Stderr, "Only in %s: %s\n", leftPath, p.left.getId()) | 				fmt.Fprintf(os.Stderr, "Only in %s: %s\n", leftPath, p.left.getID()) | ||||||
| 				exitCode = 1 | 				exitCode = 1 | ||||||
| 			case p.left == nil && p.right != nil: | 			case p.left == nil && p.right != nil: | ||||||
| 				fmt.Fprintf(os.Stderr, "Only in %s: %s\n", rightPath, p.right.getId()) | 				fmt.Fprintf(os.Stderr, "Only in %s: %s\n", rightPath, p.right.getID()) | ||||||
| 				exitCode = 1 | 				exitCode = 1 | ||||||
| 			default: | 			default: | ||||||
| 				diff := deep.Equal(p.left, p.right) | 				diff := deep.Equal(p.left, p.right) | ||||||
| 				if diff != nil { | 				if diff != nil { | ||||||
| 					id := p.left.getId() | 					id := p.left.getID() | ||||||
| 					fmt.Fprintf(os.Stderr, "< %s %s\n", id, leftPath) | 					fmt.Fprintf(os.Stderr, "< %s %s\n", id, leftPath) | ||||||
| 					fmt.Fprintf(os.Stderr, "> %s %s\n", id, rightPath) | 					fmt.Fprintf(os.Stderr, "> %s %s\n", id, rightPath) | ||||||
| 					for _, d := range diff { | 					for _, d := range diff { | ||||||
|  | @ -160,7 +160,9 @@ func readManifest(path string) ([]resource, error) { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	defer f.Close() | 	defer func() { | ||||||
|  | 		_ = f.Close() | ||||||
|  | 	}() | ||||||
| 	decoder := yaml.NewYAMLToJSONDecoder(f) | 	decoder := yaml.NewYAMLToJSONDecoder(f) | ||||||
| 	resources := []resource{} | 	resources := []resource{} | ||||||
| 	for { | 	for { | ||||||
|  | @ -179,7 +181,7 @@ func readManifest(path string) ([]resource, error) { | ||||||
| 	return resources, nil | 	return resources, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (res resource) getId() string { | func (res resource) getID() string { | ||||||
| 	meta, err := res.getMeta() | 	meta, err := res.getMeta() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Sprintf("%v", res) | 		return fmt.Sprintf("%v", res) | ||||||
|  | @ -202,7 +204,6 @@ func (res resource) getId() string { | ||||||
| 	} | 	} | ||||||
| 	gvk := strings.Join([]string{gv, k}, "_") | 	gvk := strings.Join([]string{gv, k}, "_") | ||||||
| 	return strings.Join([]string{gvk, ns, nm}, "|") | 	return strings.Join([]string{gvk, ns, nm}, "|") | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // lifted from kustomize/kyaml/kio/filters/merge3.go
 | // lifted from kustomize/kyaml/kio/filters/merge3.go
 | ||||||
|  | @ -267,7 +268,6 @@ func (p *pair) add(node resource, source diffSource) error { | ||||||
| 		return fmt.Errorf("unknown diff source value: %s", source) | 		return fmt.Errorf("unknown diff source value: %s", source) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
|  |  | ||||||
|  | @ -242,5 +242,4 @@ func TestTmplStrings(t *testing.T) { | ||||||
| 			require.Equal(t, tc.output, tplResult.String()) | 			require.Equal(t, tc.output, tplResult.String()) | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -113,10 +113,10 @@ func computeDiff(formatter aurora.Aurora, a interface{}, b interface{}) (string, | ||||||
| 		switch { | 		switch { | ||||||
| 		case strings.HasPrefix(s, "+"): | 		case strings.HasPrefix(s, "+"): | ||||||
| 			diffs = append(diffs, formatter.Bold(formatter.Green(s)).String()) | 			diffs = append(diffs, formatter.Bold(formatter.Green(s)).String()) | ||||||
| 			ndiffs += 1 | 			ndiffs++ | ||||||
| 		case strings.HasPrefix(s, "-"): | 		case strings.HasPrefix(s, "-"): | ||||||
| 			diffs = append(diffs, formatter.Bold(formatter.Red(s)).String()) | 			diffs = append(diffs, formatter.Bold(formatter.Red(s)).String()) | ||||||
| 			ndiffs += 1 | 			ndiffs++ | ||||||
| 		default: | 		default: | ||||||
| 			diffs = append(diffs, s) | 			diffs = append(diffs, s) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue