github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/step/helm/step_helm_apply.go (about)

     1  package helm
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/pkg/errors"
    11  	"github.com/spf13/cobra"
    12  
    13  	"github.com/jenkins-x/jx-logging/pkg/log"
    14  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    15  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    16  	"github.com/olli-ai/jx/v2/pkg/cmd/opts/step"
    17  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    18  	"github.com/olli-ai/jx/v2/pkg/config"
    19  	"github.com/olli-ai/jx/v2/pkg/gits"
    20  	"github.com/olli-ai/jx/v2/pkg/helm"
    21  	configio "github.com/olli-ai/jx/v2/pkg/io"
    22  	"github.com/olli-ai/jx/v2/pkg/io/secrets"
    23  	"github.com/olli-ai/jx/v2/pkg/kube"
    24  	"github.com/olli-ai/jx/v2/pkg/kube/naming"
    25  	"github.com/olli-ai/jx/v2/pkg/platform"
    26  	"github.com/olli-ai/jx/v2/pkg/secreturl/fakevault"
    27  	"github.com/olli-ai/jx/v2/pkg/util"
    28  	"github.com/olli-ai/jx/v2/pkg/vault"
    29  )
    30  
    31  // StepHelmApplyOptions contains the command line flags
    32  type StepHelmApplyOptions struct {
    33  	StepHelmOptions
    34  
    35  	Namespace          string
    36  	ReleaseName        string
    37  	Wait               bool
    38  	Force              bool
    39  	DisableHelmVersion bool
    40  	Boot               bool
    41  	Vault              bool
    42  	NoVault            bool
    43  	NoMasking          bool
    44  	ProviderValuesDir  string
    45  	MultiTemplates     bool
    46  }
    47  
    48  var (
    49  	StepHelmApplyLong = templates.LongDesc(`
    50  		Applies the helm chart in a given directory.
    51  
    52  		This step is usually used to apply any GitOps promotion changes into a Staging or Production cluster.
    53  
    54          Environment Variables:
    55  		- JX_NO_DELETE_TMP_DIR="true" - prevents the removal of the temporary directory.
    56  `)
    57  
    58  	StepHelmApplyExample = templates.Examples(`
    59  		# apply the chart in the env folder to namespace jx-staging
    60  		jx step helm apply --dir env --namespace jx-staging
    61  
    62  `)
    63  
    64  	defaultValueFileNames = []string{"values.yaml", "myvalues.yaml", helm.SecretsFileName, filepath.Join("env", helm.SecretsFileName)}
    65  )
    66  
    67  func NewCmdStepHelmApply(commonOpts *opts.CommonOptions) *cobra.Command {
    68  	options := StepHelmApplyOptions{
    69  		StepHelmOptions: StepHelmOptions{
    70  			StepOptions: step.StepOptions{
    71  				CommonOptions: commonOpts,
    72  			},
    73  		},
    74  	}
    75  	cmd := &cobra.Command{
    76  		Use:     "apply",
    77  		Short:   "Applies the helm chart in a given directory",
    78  		Aliases: []string{""},
    79  		Long:    StepHelmApplyLong,
    80  		Example: StepHelmApplyExample,
    81  		Run: func(cmd *cobra.Command, args []string) {
    82  			options.Cmd = cmd
    83  			options.Args = args
    84  			err := options.Run()
    85  			helper.CheckErr(err)
    86  		},
    87  	}
    88  	options.addStepHelmFlags(cmd)
    89  
    90  	cmd.Flags().StringVarP(&options.Namespace, "namespace", "", "", "The Kubernetes namespace to apply the helm chart to")
    91  	cmd.Flags().StringVarP(&options.ReleaseName, "name", "n", "", "The name of the release")
    92  	cmd.Flags().BoolVarP(&options.Wait, "wait", "", true, "Wait for Kubernetes readiness probe to confirm deployment")
    93  	cmd.Flags().BoolVarP(&options.Force, "force", "f", true, "Whether to to pass '--force' to helm to help deal with upgrading if a previous promote failed")
    94  	cmd.Flags().BoolVar(&options.DisableHelmVersion, "no-helm-version", false, "Don't set Chart version before applying")
    95  	cmd.Flags().BoolVarP(&options.Vault, "vault", "", false, "Helm secrets are stored in vault")
    96  	cmd.Flags().BoolVarP(&options.Boot, "boot", "", false, "In Boot mode we load the Version Stream from the 'jx-requirements.yml' and use that to replace any missing versions in the 'requirements.yaml' file from the Version Stream")
    97  	cmd.Flags().BoolVarP(&options.NoVault, "no-vault", "", false, "Disables loading secrets from Vault. e.g. if bootstrapping core services like Ingress before we have a Vault")
    98  	cmd.Flags().BoolVarP(&options.NoMasking, "no-masking", "", false, "The effective 'values.yaml' file is output to the console with parameters masked. Enabling this flag will show the unmasked secrets in the console output")
    99  	cmd.Flags().StringVarP(&options.ProviderValuesDir, "provider-values-dir", "", "", "The optional directory of kubernetes provider specific override values.tmpl.yaml files a kubernetes provider specific folder")
   100  	cmd.Flags().BoolVarP(&options.MultiTemplates, "multi-templates", "", false, "Calls helm template on each sub chart instead of globally, to avoid conflict among charts with different versions")
   101  
   102  	return cmd
   103  }
   104  
   105  func (o *StepHelmApplyOptions) Run() error {
   106  	var err error
   107  	chartName := o.Dir
   108  	dir := o.Dir
   109  	releaseName := o.ReleaseName
   110  
   111  	// let allow arguments to be passed in like for `helm install releaseName dir`
   112  	args := o.Args
   113  	if releaseName == "" && len(args) > 0 {
   114  		releaseName = args[0]
   115  	}
   116  	if dir == "" && len(args) > 1 {
   117  		dir = args[1]
   118  	}
   119  
   120  	if dir == "" {
   121  		dir, err = os.Getwd()
   122  		if err != nil {
   123  			return err
   124  		}
   125  	}
   126  
   127  	if !o.DisableHelmVersion {
   128  		(&StepHelmVersionOptions{
   129  			StepHelmOptions: StepHelmOptions{
   130  				StepOptions: step.StepOptions{
   131  					CommonOptions: &opts.CommonOptions{},
   132  				},
   133  			},
   134  		}).Run() //nolint:errcheck
   135  	}
   136  	helmBinary, noTiller, helmTemplate, err := o.TeamHelmBin()
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	ns, err := o.GetDeployNamespace(o.Namespace)
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	kubeClient, err := o.KubeClient()
   147  	if err != nil {
   148  		return err
   149  	}
   150  
   151  	err = kube.EnsureNamespaceCreated(kubeClient, ns, nil, nil)
   152  	if err != nil {
   153  		return err
   154  	}
   155  
   156  	_, devNs, err := o.KubeClientAndDevNamespace()
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	if releaseName == "" {
   162  		if devNs == ns {
   163  			releaseName = platform.JenkinsXPlatformRelease
   164  		} else {
   165  			releaseName = ns
   166  
   167  			if helmBinary != "helm" || noTiller || helmTemplate {
   168  				releaseName = "jx"
   169  			}
   170  		}
   171  	}
   172  	info := util.ColorInfo
   173  
   174  	path, err := filepath.Abs(dir)
   175  	if err != nil {
   176  		return errors.Wrapf(err, "could not find absolute path of dir %s", dir)
   177  	}
   178  	dir = path
   179  
   180  	devGitInfo, err := o.FindGitInfo(dir)
   181  	if err != nil {
   182  		log.Logger().Warnf("could not find a git repository in the directory %s: %s\n", dir, err.Error())
   183  	}
   184  	rootTmpDir, err := ioutil.TempDir("", "jx-helm-apply-")
   185  	if err != nil {
   186  		return errors.Wrapf(err, "failed to create a temporary directory to apply the helm chart")
   187  	}
   188  	if os.Getenv("JX_NO_DELETE_TMP_DIR") != "true" {
   189  		defer os.RemoveAll(rootTmpDir) //nolint:errcheck
   190  	}
   191  
   192  	if os.Getenv(kube.DisableBuildLockEnvKey) == "" {
   193  		release, err := kube.AcquireBuildLock(kubeClient, devNs, ns)
   194  		if err != nil {
   195  			return errors.Wrapf(err, "fail to acquire the lock")
   196  		}
   197  		defer release() //nolint:errcheck
   198  	}
   199  
   200  	// lets use the same child dir name as the original as helm is quite particular about the name of the directory it runs from
   201  	_, name := filepath.Split(dir)
   202  	if name == "" {
   203  		return fmt.Errorf("could not find the relative name of the directory %s", dir)
   204  	}
   205  	tmpDir := filepath.Join(rootTmpDir, name)
   206  	log.Logger().Debugf("Copying the helm source directory %s to a temporary location for building and applying %s\n", info(dir), info(tmpDir))
   207  
   208  	err = os.MkdirAll(tmpDir, util.DefaultWritePermissions)
   209  	if err != nil {
   210  		return errors.Wrapf(err, "failed to helm temporary dir %s", tmpDir)
   211  	}
   212  	err = util.CopyDir(dir, tmpDir, true)
   213  	if err != nil {
   214  		return errors.Wrapf(err, "failed to copy helm dir %s to temporary dir %s", dir, tmpDir)
   215  	}
   216  	dir = tmpDir
   217  	log.Logger().Debugf("Applying helm chart at %s as release name %s to namespace %s", info(dir), info(releaseName), info(ns))
   218  
   219  	o.Helm().SetCWD(dir)
   220  
   221  	valueFiles := []string{}
   222  	for _, name := range defaultValueFileNames {
   223  		file := filepath.Join(dir, name)
   224  		exists, err := util.FileExists(file)
   225  		if exists && err == nil {
   226  			valueFiles = append(valueFiles, file)
   227  		}
   228  	}
   229  
   230  	vaultSecretLocation := o.GetSecretsLocation() == secrets.VaultLocationKind
   231  	if vaultSecretLocation && o.NoVault {
   232  		// lets install a fake secret URL client to avoid spurious vault errors
   233  		o.SetSecretURLClient(fakevault.NewFakeClient())
   234  	}
   235  	if (vaultSecretLocation || o.Vault) && !o.NoVault {
   236  		store := configio.NewFileStore()
   237  		secretsFiles, err := o.fetchSecretFilesFromVault(dir, store)
   238  		if err != nil {
   239  			return errors.Wrap(err, "fetching secrets files from vault")
   240  		}
   241  		for _, sf := range secretsFiles {
   242  			if util.StringArrayIndex(valueFiles, sf) < 0 {
   243  				log.Logger().Debugf("adding secret file %s", sf)
   244  				valueFiles = append(valueFiles, sf)
   245  			}
   246  		}
   247  		defer func() {
   248  			for _, secretsFile := range secretsFiles {
   249  				err := util.DestroyFile(secretsFile)
   250  				if err != nil {
   251  					log.Logger().Warnf("Failed to cleanup the secrets files (%s): %v",
   252  						strings.Join(secretsFiles, ", "), err)
   253  				}
   254  			}
   255  		}()
   256  	}
   257  
   258  	requirements, requirementsFileName, err := o.getRequirements()
   259  	if err != nil {
   260  		return errors.Wrap(err, "loading the requirements")
   261  	}
   262  
   263  	secretURLClient, err := o.GetSecretURLClient(secrets.ToSecretsLocation(string(requirements.SecretStorage)))
   264  	if err != nil {
   265  		return errors.Wrap(err, "failed to create a Secret RL client")
   266  	}
   267  
   268  	DefaultEnvironments(requirements, devGitInfo)
   269  
   270  	funcMap, err := o.createFuncMap(requirements)
   271  	if err != nil {
   272  		return err
   273  	}
   274  	chartValues, params, err := helm.GenerateValues(requirements, funcMap, dir, nil, true, secretURLClient)
   275  	if err != nil {
   276  		return errors.Wrapf(err, "generating values.yaml for tree from %s", dir)
   277  	}
   278  	if o.ProviderValuesDir != "" && requirementsFileName != "" {
   279  		chartValues, err = o.overwriteProviderValues(requirements, requirementsFileName, chartValues, params, o.ProviderValuesDir)
   280  		if err != nil {
   281  			return errors.Wrapf(err, "failed to overwrite provider values in dir: %s", dir)
   282  		}
   283  	}
   284  
   285  	chartValuesFile := filepath.Join(dir, helm.ValuesFileName)
   286  	err = ioutil.WriteFile(chartValuesFile, chartValues, 0600)
   287  	if err != nil {
   288  		return errors.Wrapf(err, "writing values.yaml for tree to %s", chartValuesFile)
   289  	}
   290  	log.Logger().Debugf("Wrote chart values.yaml %s generated from directory tree", chartValuesFile)
   291  
   292  	data, err := ioutil.ReadFile(chartValuesFile)
   293  	if err != nil {
   294  		log.Logger().Warnf("failed to load file %s: %s", chartValuesFile, err.Error())
   295  	} else {
   296  		log.Logger().Debugf("generated helm %s", chartValuesFile)
   297  
   298  		valuesText := string(data)
   299  		if !o.NoMasking {
   300  			masker := kube.NewLogMaskerFromMap(params.AsMap())
   301  			valuesText = masker.MaskLog(valuesText)
   302  		}
   303  
   304  		log.Logger().Debugf("\n%s\n", util.ColorStatus(valuesText))
   305  	}
   306  
   307  	log.Logger().Debugf("Using values files: %s", strings.Join(valueFiles, ", "))
   308  
   309  	if o.Boot {
   310  		err = o.replaceMissingVersionsFromVersionStream(requirements, dir)
   311  		if err != nil {
   312  			return errors.Wrapf(err, "failed to replace missing versions in the requirements.yaml in dir %s", dir)
   313  		}
   314  	}
   315  	if o.MultiTemplates {
   316  		err = o.HelmInitDependencyBuildNoLint(dir, o.DefaultReleaseCharts())
   317  	} else {
   318  		err = o.HelmInitDependencyBuild(dir, o.DefaultReleaseCharts(), valueFiles)
   319  	}
   320  	if err != nil {
   321  		return err
   322  	}
   323  
   324  	// Unpack all dependencies
   325  	err = o.UnpackCharts(dir)
   326  	if err != nil {
   327  		return err
   328  	}
   329  
   330  	// apply the vault URLs to the value files
   331  	err = filepath.Walk(filepath.Join(dir, "charts"), func(path string, info os.FileInfo, err error) error {
   332  		if filepath.Base(path) == helm.ValuesFileName {
   333  
   334  			newFiles, cleanup, err := helm.DecorateWithSecrets([]string{path}, secretURLClient)
   335  			defer cleanup() //nolint:errcheck
   336  			if err != nil {
   337  				return errors.Wrapf(err, "decorating %s with secrets", path)
   338  			}
   339  			err = os.Rename(newFiles[0], path)
   340  			if err != nil {
   341  				return errors.Wrapf(err, "moving decorated file %s to %s", newFiles[0], path)
   342  			}
   343  		}
   344  		return nil
   345  	})
   346  	if err != nil {
   347  		return errors.Wrapf(err, "walking %s/charts", dir)
   348  	}
   349  
   350  	err = o.applyAppsTemplateOverrides(chartName)
   351  	if err != nil {
   352  		return errors.Wrap(err, "applying app chart overrides")
   353  	}
   354  	err = o.applyTemplateOverrides(chartName)
   355  	if err != nil {
   356  		return errors.Wrap(err, "applying chart overrides")
   357  	}
   358  
   359  	setValues, setStrings := o.getChartValues(ns)
   360  
   361  	helmOptions := helm.InstallChartOptions{
   362  		Chart:          chartName,
   363  		ReleaseName:    releaseName,
   364  		Ns:             ns,
   365  		NoForce:        !o.Force,
   366  		SetValues:      setValues,
   367  		SetStrings:     setStrings,
   368  		ValueFiles:     valueFiles,
   369  		Dir:            dir,
   370  		MultiTemplates: o.MultiTemplates,
   371  	}
   372  	if o.Boot {
   373  		helmOptions.VersionsGitURL = requirements.VersionStream.URL
   374  		helmOptions.VersionsGitRef = requirements.VersionStream.Ref
   375  	}
   376  
   377  	if o.Wait {
   378  		helmOptions.Wait = true
   379  		err = o.InstallChartWithOptionsAndTimeout(helmOptions, "600")
   380  	} else {
   381  		err = o.InstallChartWithOptions(helmOptions)
   382  	}
   383  	if err != nil {
   384  		return errors.Wrapf(err, "upgrading helm chart '%s'", chartName)
   385  	}
   386  	return nil
   387  }
   388  
   389  // getRequirements tries to load the requirements either from the team settings or local requirements file
   390  func (o *StepHelmApplyOptions) getRequirements() (*config.RequirementsConfig, string, error) {
   391  	// Try to load first the requirements from current directory
   392  	requirements, requirementsFileName, err := config.LoadRequirementsConfig(o.Dir, config.DefaultFailOnValidationError)
   393  	if err == nil {
   394  		return requirements, requirementsFileName, nil
   395  	}
   396  
   397  	// When no requirements file is found, try to load the requirements from team settings
   398  	jxClient, ns, err := o.JXClient()
   399  	if err != nil {
   400  		return nil, "", errors.Wrap(err, "getting the jx client")
   401  	}
   402  	teamSettings, err := kube.GetDevEnvTeamSettings(jxClient, ns)
   403  	if err != nil {
   404  		return nil, "", errors.Wrap(err, "getting the team setting from the cluster")
   405  	}
   406  
   407  	requirements, err = config.GetRequirementsConfigFromTeamSettings(teamSettings)
   408  	if err != nil {
   409  		return nil, "", errors.Wrap(err, "getting the requirements from team settings")
   410  	}
   411  	// TODO: Workaround for non-boot clusters. Remove when we get rid of jx install. (APB)
   412  	if requirements == nil {
   413  		requirements = config.NewRequirementsConfig()
   414  		requirementsFileName = config.RequirementsConfigFileName
   415  		return requirements, requirementsFileName, nil
   416  	}
   417  
   418  	return requirements, "", nil
   419  }
   420  
   421  // DefaultEnvironments ensures we have valid values for environment owner and repository names.
   422  // if none are configured lets default them from smart defaults
   423  func DefaultEnvironments(c *config.RequirementsConfig, devGitInfo *gits.GitRepository) {
   424  	defaultOwner := c.Cluster.EnvironmentGitOwner
   425  	clusterName := c.Cluster.ClusterName
   426  	for i := range c.Environments {
   427  		env := &c.Environments[i]
   428  		if !c.GitOps {
   429  			if env.Key == kube.LabelValueDevEnvironment && devGitInfo != nil {
   430  				if env.Owner == "" {
   431  					env.Owner = devGitInfo.Organisation
   432  				}
   433  				if env.Repository == "" {
   434  					env.Repository = devGitInfo.Name
   435  				}
   436  				if env.GitServer == "" {
   437  					env.GitServer = devGitInfo.HostURL()
   438  				}
   439  				if env.GitKind == "" {
   440  					env.GitKind = gits.SaasGitKind(env.GitServer)
   441  				}
   442  			}
   443  		}
   444  		if env.Owner == "" {
   445  			env.Owner = defaultOwner
   446  		}
   447  		if env.Repository == "" {
   448  			if clusterName != "" {
   449  				env.Repository = naming.ToValidName("environment-" + clusterName + "-" + env.Key)
   450  			} else {
   451  				log.Logger().Warnf("there is no 'cluster.clusterName' value set in the 'jx-requirements.yml' file. Please specify the 'repository' for environment: %s", env.Key)
   452  			}
   453  		}
   454  	}
   455  }
   456  
   457  func (o *StepHelmApplyOptions) applyTemplateOverrides(chartName string) error {
   458  	log.Logger().Debugf("Applying chart overrides")
   459  	templateOverrides, err := filepath.Glob(chartName + "/../*/templates/*.yaml")
   460  	for _, overrideSrc := range templateOverrides {
   461  		if !strings.Contains(overrideSrc, "/env/") {
   462  			data, err := ioutil.ReadFile(overrideSrc)
   463  			if err == nil {
   464  				writeTemplateParts := strings.Split(overrideSrc, string(os.PathSeparator))
   465  				depChartsDir := filepath.Join(chartName, "charts")
   466  				depChartName := writeTemplateParts[len(writeTemplateParts)-3]
   467  				templateName := writeTemplateParts[len(writeTemplateParts)-1]
   468  				depChartDir := filepath.Join(depChartsDir, depChartName)
   469  				if _, err := os.Stat(depChartDir); os.IsNotExist(err) {
   470  					// If there is no charts/<depChartName> dir it means that it's not a dependency of this chart
   471  					continue
   472  				}
   473  				// // If the chart directory does not exist explode the tgz
   474  				// if exists, err := util.DirExists(depChartDir); err == nil && !exists {
   475  				// 	chartArchives, _ := filepath.Glob(filepath.Join(depChartsDir, depChartName+"*.tgz"))
   476  				// 	if len(chartArchives) == 1 {
   477  				// 		log.Logger().Debugf("Exploding chart %s", chartArchives[0])
   478  				// 		err = archiver.Unarchive(chartArchives[0], depChartsDir)
   479  				// 		if err != nil {
   480  				// 			return errors.Wrapf(err, "unable to unarchive %s to destination %s", chartArchives[0], depChartDir)
   481  				// 		}
   482  				// 		// Remove the unexploded chart
   483  				// 		err = os.Remove(chartArchives[0])
   484  				// 		if err != nil {
   485  				// 			return errors.Wrapf(err, "unable to remove chart %s", chartArchives[0])
   486  				// 		}
   487  				// 	}
   488  				// }
   489  				overrideDst := filepath.Join(depChartDir, "templates", templateName)
   490  				log.Logger().Debugf("Copying chart override %s", overrideSrc)
   491  				err = ioutil.WriteFile(overrideDst, data, util.DefaultWritePermissions)
   492  				if err != nil {
   493  					log.Logger().Warnf("Error copying template %s to %s %v", overrideSrc, overrideDst, err)
   494  				}
   495  
   496  			}
   497  		}
   498  	}
   499  	return err
   500  }
   501  
   502  func (o *StepHelmApplyOptions) applyAppsTemplateOverrides(chartName string) error {
   503  	log.Logger().Debugf("Applying Apps chart overrides")
   504  	templateOverrides, err := filepath.Glob(chartName + "/../*/*/templates/app.yaml")
   505  	for _, overrideSrc := range templateOverrides {
   506  		data, err := ioutil.ReadFile(overrideSrc)
   507  		if err == nil {
   508  			writeTemplateParts := strings.Split(overrideSrc, string(os.PathSeparator))
   509  			depChartsDir := filepath.Join(chartName, "charts")
   510  			depChartName := writeTemplateParts[len(writeTemplateParts)-3]
   511  			templateName := writeTemplateParts[len(writeTemplateParts)-1]
   512  			depChartDir := filepath.Join(depChartsDir, depChartName)
   513  			// chartArchives, _ := filepath.Glob(filepath.Join(depChartsDir, depChartName+"*.tgz"))
   514  			// if len(chartArchives) == 1 {
   515  			// 	uuid, _ := uuid.NewUUID()
   516  			// 	log.Logger().Debugf("Exploding App chart %s", chartArchives[0])
   517  			// 	explodedChartTempDir := filepath.Join(os.TempDir(), uuid.String())
   518  			// 	if err = archiver.Unarchive(chartArchives[0], explodedChartTempDir); err != nil {
   519  			// 		return defineAppsChartOverridingError(chartName, err)
   520  			// 	}
   521  			// 	overrideDst := filepath.Join(explodedChartTempDir, depChartName, "templates", templateName)
   522  			if exists, err := util.DirExists(depChartDir); exists {
   523  				overrideDst := filepath.Join(depChartDir, "templates", templateName)
   524  				log.Logger().Debugf("Copying chart override %s", overrideSrc)
   525  				err = ioutil.WriteFile(overrideDst, data, util.DefaultWritePermissions)
   526  				if err != nil {
   527  					log.Logger().Warnf("Error copying template %s to %s %v", overrideSrc, overrideDst, err)
   528  				}
   529  				// if err = os.Remove(chartArchives[0]); err != nil {
   530  				// 	return defineAppsChartOverridingError(chartName, err)
   531  				// }
   532  				// if err = archiver.Archive([]string{filepath.Join(explodedChartTempDir, depChartName)}, chartArchives[0]); err != nil {
   533  				// 	return defineAppsChartOverridingError(chartName, err)
   534  				// }
   535  				// if err = os.RemoveAll(explodedChartTempDir); err != nil {
   536  				// 	log.Logger().Warnf("There was a problem deleting the temp folder %s", depChartDir)
   537  				// }
   538  			}
   539  		}
   540  	}
   541  	return err
   542  }
   543  
   544  func defineAppsChartOverridingError(chartName string, err error) error {
   545  	return errors.Wrapf(err, "there was a problem overriding the chart %s", chartName)
   546  }
   547  
   548  func (o *StepHelmApplyOptions) fetchSecretFilesFromVault(dir string, store configio.ConfigStore) ([]string, error) {
   549  	log.Logger().Debugf("Fetching secrets from vault into directory %q", dir)
   550  	files := []string{}
   551  	client, err := o.SystemVaultClient("")
   552  	if err != nil {
   553  		return files, errors.Wrap(err, "retrieving the system Vault")
   554  	}
   555  	secretNames, err := client.List(vault.GitOpsSecretsPath)
   556  	if err != nil {
   557  		return files, errors.Wrap(err, "listing the GitOps secrets in Vault")
   558  	}
   559  	secretPaths := []string{}
   560  	for _, secretName := range secretNames {
   561  		if secretName == vault.GitOpsTemplatesPath {
   562  			templatesPath := vault.GitOpsSecretPath(vault.GitOpsTemplatesPath)
   563  			templatesSecretNames, err := client.List(templatesPath)
   564  			if err == nil {
   565  				for _, templatesSecretName := range templatesSecretNames {
   566  					templateSecretPath := vault.GitOpsTemplatesPath + templatesSecretName
   567  					secretPaths = append(secretPaths, templateSecretPath)
   568  				}
   569  			}
   570  		} else {
   571  			secretPaths = append(secretPaths, secretName)
   572  		}
   573  	}
   574  
   575  	for _, secretPath := range secretPaths {
   576  		gitopsSecretPath := vault.GitOpsSecretPath(secretPath)
   577  		secret, err := client.ReadYaml(gitopsSecretPath)
   578  		if err != nil {
   579  			return files, errors.Wrapf(err, "retrieving the secret %q from Vault", secretPath)
   580  		}
   581  		if secret == "" {
   582  			return files, fmt.Errorf("secret %q is empty", secretPath)
   583  		}
   584  		secretFile := filepath.Join(dir, secretPath)
   585  		err = store.Write(secretFile, []byte(secret))
   586  		if err != nil {
   587  			return files, errors.Wrapf(err, "saving the secret file %q", secretFile)
   588  		}
   589  		log.Logger().Debugf("Saved secrets file %s", util.ColorInfo(secretFile))
   590  		files = append(files, secretFile)
   591  	}
   592  	return files, nil
   593  }