feat: `helmfile template --skip-cleanup` (#1570)
* feat: `helmfile template --skip-cleanup` Resolves #1517
This commit is contained in:
		
							parent
							
								
									5a15b65b94
								
							
						
					
					
						commit
						88884b68dc
					
				
							
								
								
									
										4
									
								
								main.go
								
								
								
								
							
							
						
						
									
										4
									
								
								main.go
								
								
								
								
							|  | @ -256,6 +256,10 @@ func main() { | |||
| 					Name:  "skip-deps", | ||||
| 					Usage: "skip running `helm repo update` and `helm dependency build`", | ||||
| 				}, | ||||
| 				cli.BoolFlag{ | ||||
| 					Name:  "skip-cleanup", | ||||
| 					Usage: "Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security", | ||||
| 				}, | ||||
| 			}, | ||||
| 			Action: action(func(run *app.App, c configImpl) error { | ||||
| 				return run.Template(c) | ||||
|  |  | |||
|  | @ -218,6 +218,9 @@ func (a *App) Diff(c DiffConfigProvider) error { | |||
| } | ||||
| 
 | ||||
| func (a *App) Template(c TemplateConfigProvider) error { | ||||
| 
 | ||||
| 	opts := []LoadOption{SetRetainValuesFiles(c.SkipCleanup())} | ||||
| 
 | ||||
| 	return a.ForEachState(func(run *Run) (ok bool, errs []error) { | ||||
| 		// `helm template` in helm v2 does not support local chart.
 | ||||
| 		// So, we set forceDownload=true for helm v2 only
 | ||||
|  | @ -233,7 +236,7 @@ func (a *App) Template(c TemplateConfigProvider) error { | |||
| 		} | ||||
| 
 | ||||
| 		return | ||||
| 	}) | ||||
| 	}, opts...) | ||||
| } | ||||
| 
 | ||||
| func (a *App) WriteValues(c WriteValuesConfigProvider) error { | ||||
|  | @ -1437,6 +1440,7 @@ func (a *App) template(r *Run, c TemplateConfigProvider) (bool, []error) { | |||
| 				Set:               c.Set(), | ||||
| 				IncludeCRDs:       c.IncludeCRDs(), | ||||
| 				OutputDirTemplate: c.OutputDirTemplate(), | ||||
| 				SkipCleanup:       c.SkipCleanup(), | ||||
| 			} | ||||
| 			return subst.TemplateReleases(helm, c.OutputDir(), c.Values(), args, c.Concurrency(), c.Validate(), opts) | ||||
| 		})) | ||||
|  |  | |||
|  | @ -2241,6 +2241,7 @@ type configImpl struct { | |||
| 	set         []string | ||||
| 	output      string | ||||
| 	includeCRDs bool | ||||
| 	skipCleanup bool | ||||
| 	skipDeps    bool | ||||
| } | ||||
| 
 | ||||
|  | @ -2264,6 +2265,10 @@ func (c configImpl) Validate() bool { | |||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (c configImpl) SkipCleanup() bool { | ||||
| 	return c.skipCleanup | ||||
| } | ||||
| 
 | ||||
| func (c configImpl) SkipDeps() bool { | ||||
| 	return c.skipDeps | ||||
| } | ||||
|  |  | |||
|  | @ -134,6 +134,7 @@ type TemplateConfigProvider interface { | |||
| 	OutputDirTemplate() string | ||||
| 	Validate() bool | ||||
| 	SkipDeps() bool | ||||
| 	SkipCleanup() bool | ||||
| 	OutputDir() string | ||||
| 	IncludeCRDs() bool | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ type execer struct { | |||
| 	extra                []string | ||||
| 	decryptedSecretMutex sync.Mutex | ||||
| 	decryptedSecrets     map[string]*decryptedSecret | ||||
| 	writeTempFile        func([]byte) (string, error) | ||||
| } | ||||
| 
 | ||||
| func NewLogger(writer io.Writer, logLevel string) *zap.SugaredLogger { | ||||
|  | @ -278,16 +279,32 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str | |||
| 		defer secret.mutex.RUnlock() | ||||
| 	} | ||||
| 
 | ||||
| 	tmpFile, err := ioutil.TempFile("", "secret") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	tempFile := helm.writeTempFile | ||||
| 
 | ||||
| 	if tempFile == nil { | ||||
| 		tempFile = func(content []byte) (string, error) { | ||||
| 			tmpFile, err := ioutil.TempFile("", "secret") | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 
 | ||||
| 			_, err = tmpFile.Write(content) | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 
 | ||||
| 			return tmpFile.Name(), nil | ||||
| 		} | ||||
| 	} | ||||
| 	_, err = tmpFile.Write(secret.bytes) | ||||
| 
 | ||||
| 	tmpFileName, err := tempFile(secret.bytes) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return tmpFile.Name(), err | ||||
| 	helm.logger.Debugf("Decrypted %s into %s", absPath, tmpFileName) | ||||
| 
 | ||||
| 	return tmpFileName, err | ||||
| } | ||||
| 
 | ||||
| func (helm *execer) TemplateRelease(name string, chart string, flags ...string) error { | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ package helmexec | |||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
|  | @ -257,6 +258,12 @@ func Test_DecryptSecret(t *testing.T) { | |||
| 	var buffer bytes.Buffer | ||||
| 	logger := NewLogger(&buffer, "debug") | ||||
| 	helm := MockExecer(logger, "dev") | ||||
| 
 | ||||
| 	tmpFilePath := "path/to/temp/file" | ||||
| 	helm.writeTempFile = func(content []byte) (string, error) { | ||||
| 		return tmpFilePath, nil | ||||
| 	} | ||||
| 
 | ||||
| 	helm.DecryptSecret(HelmContext{}, "secretName") | ||||
| 	cwd, err := filepath.Abs(".") | ||||
| 	if err != nil { | ||||
|  | @ -270,9 +277,10 @@ Decrypting secret %s/secretName | |||
| exec: helm --kube-context dev secrets dec %s/secretName | ||||
| Preparing to decrypt secret %s/secretName | ||||
| Found secret in cache %s/secretName | ||||
| `, cwd, cwd, cwd, cwd, cwd) | ||||
| 	if buffer.String() != expected { | ||||
| 		t.Errorf("helmexec.DecryptSecret()\nactual = %v\nexpect = %v", buffer.String(), expected) | ||||
| Decrypted %s/secretName into path/to/temp/file | ||||
| `, cwd, cwd, cwd, cwd, cwd, cwd) | ||||
| 	if d := cmp.Diff(expected, buffer.String()); d != "" { | ||||
| 		t.Errorf("helmexec.DecryptSecret(): want (-), got (+):\n%s", d) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -670,6 +670,10 @@ func (st *HelmState) SyncReleases(affectedReleases *AffectedReleases, helm helme | |||
| 	preps, prepErrs := st.prepareSyncReleases(helm, additionalValues, workerLimit, opts) | ||||
| 
 | ||||
| 	defer func() { | ||||
| 		if opts.SkipCleanup { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		for _, p := range preps { | ||||
| 			st.removeFiles(p.files) | ||||
| 		} | ||||
|  | @ -1125,6 +1129,7 @@ func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, | |||
| 
 | ||||
| type TemplateOpts struct { | ||||
| 	Set               []string | ||||
| 	SkipCleanup       bool | ||||
| 	OutputDirTemplate string | ||||
| 	IncludeCRDs       bool | ||||
| } | ||||
|  | @ -1136,7 +1141,9 @@ func (o *TemplateOpts) Apply(opts *TemplateOpts) { | |||
| } | ||||
| 
 | ||||
| // TemplateReleases wrapper for executing helm template on the releases
 | ||||
| func (st *HelmState) TemplateReleases(helm helmexec.Interface, outputDir string, additionalValues []string, args []string, workerLimit int, validate bool, opt ...TemplateOpt) []error { | ||||
| func (st *HelmState) TemplateReleases(helm helmexec.Interface, outputDir string, additionalValues []string, args []string, workerLimit int, | ||||
| 	validate bool, opt ...TemplateOpt) []error { | ||||
| 
 | ||||
| 	opts := &TemplateOpts{} | ||||
| 	for _, o := range opt { | ||||
| 		o.Apply(opts) | ||||
|  | @ -1156,6 +1163,10 @@ func (st *HelmState) TemplateReleases(helm helmexec.Interface, outputDir string, | |||
| 		flags, files, err := st.flagsForTemplate(helm, release, 0) | ||||
| 
 | ||||
| 		defer func() { | ||||
| 			if opts.SkipCleanup { | ||||
| 				return | ||||
| 			} | ||||
| 
 | ||||
| 			st.removeFiles(files) | ||||
| 		}() | ||||
| 
 | ||||
|  | @ -1571,6 +1582,10 @@ func (st *HelmState) DiffReleases(helm helmexec.Interface, additionalValues []st | |||
| 	preps, prepErrs := st.prepareDiffReleases(helm, additionalValues, workerLimit, detailedExitCode, includeTests, suppressSecrets, opts) | ||||
| 
 | ||||
| 	defer func() { | ||||
| 		if opts.SkipCleanup { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		for _, p := range preps { | ||||
| 			st.removeFiles(p.files) | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue