github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/cmd/helmExecute.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path"
     7  	"path/filepath"
     8  
     9  	"github.com/SAP/jenkins-library/pkg/kubernetes"
    10  	"github.com/SAP/jenkins-library/pkg/log"
    11  	"github.com/SAP/jenkins-library/pkg/piperenv"
    12  	"github.com/SAP/jenkins-library/pkg/telemetry"
    13  	"github.com/SAP/jenkins-library/pkg/versioning"
    14  )
    15  
    16  func helmExecute(config helmExecuteOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *helmExecuteCommonPipelineEnvironment) {
    17  	helmConfig := kubernetes.HelmExecuteOptions{
    18  		AdditionalParameters:      config.AdditionalParameters,
    19  		ChartPath:                 config.ChartPath,
    20  		Image:                     config.Image,
    21  		Namespace:                 config.Namespace,
    22  		KubeContext:               config.KubeContext,
    23  		KeepFailedDeployments:     config.KeepFailedDeployments,
    24  		KubeConfig:                config.KubeConfig,
    25  		HelmDeployWaitSeconds:     config.HelmDeployWaitSeconds,
    26  		DockerConfigJSON:          config.DockerConfigJSON,
    27  		AppVersion:                config.AppVersion,
    28  		Dependency:                config.Dependency,
    29  		PackageDependencyUpdate:   config.PackageDependencyUpdate,
    30  		HelmValues:                config.HelmValues,
    31  		FilterTest:                config.FilterTest,
    32  		DumpLogs:                  config.DumpLogs,
    33  		TargetRepositoryURL:       config.TargetRepositoryURL,
    34  		TargetRepositoryName:      config.TargetRepositoryName,
    35  		TargetRepositoryUser:      config.TargetRepositoryUser,
    36  		TargetRepositoryPassword:  config.TargetRepositoryPassword,
    37  		SourceRepositoryName:      config.SourceRepositoryName,
    38  		SourceRepositoryURL:       config.SourceRepositoryURL,
    39  		SourceRepositoryUser:      config.SourceRepositoryUser,
    40  		SourceRepositoryPassword:  config.SourceRepositoryPassword,
    41  		HelmCommand:               config.HelmCommand,
    42  		CustomTLSCertificateLinks: config.CustomTLSCertificateLinks,
    43  		Version:                   config.Version,
    44  		PublishVersion:            config.Version,
    45  		RenderSubchartNotes:       config.RenderSubchartNotes,
    46  	}
    47  
    48  	utils := kubernetes.NewDeployUtilsBundle(helmConfig.CustomTLSCertificateLinks)
    49  
    50  	artifactOpts := versioning.Options{
    51  		VersioningScheme: "library",
    52  	}
    53  
    54  	buildDescriptorFile := ""
    55  	if helmConfig.ChartPath != "" {
    56  		buildDescriptorFile = filepath.Join(helmConfig.ChartPath, "Chart.yaml")
    57  	}
    58  
    59  	artifact, err := versioning.GetArtifact("helm", buildDescriptorFile, &artifactOpts, utils)
    60  	if err != nil {
    61  		log.Entry().WithError(err).Fatalf("getting artifact information failed: %v", err)
    62  	}
    63  	artifactInfo, err := artifact.GetCoordinates()
    64  	if err != nil {
    65  		log.Entry().WithError(err).Fatalf("getting artifact coordinates failed: %v", err)
    66  	}
    67  
    68  	helmConfig.DeploymentName = artifactInfo.ArtifactID
    69  
    70  	if len(helmConfig.PublishVersion) == 0 {
    71  		helmConfig.PublishVersion = artifactInfo.Version
    72  	}
    73  
    74  	helmExecutor := kubernetes.NewHelmExecutor(helmConfig, utils, GeneralConfig.Verbose, log.Writer())
    75  
    76  	// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
    77  	if err := runHelmExecute(config, helmExecutor, utils, commonPipelineEnvironment); err != nil {
    78  		log.Entry().WithError(err).Fatalf("step execution failed: %v", err)
    79  	}
    80  }
    81  
    82  func runHelmExecute(config helmExecuteOptions, helmExecutor kubernetes.HelmExecutor, utils fileHandler, commonPipelineEnvironment *helmExecuteCommonPipelineEnvironment) error {
    83  	if config.RenderValuesTemplate {
    84  		err := parseAndRenderCPETemplate(config, GeneralConfig.EnvRootPath, utils)
    85  		if err != nil {
    86  			log.Entry().WithError(err).Fatalf("failed to parse/render template: %v", err)
    87  		}
    88  	}
    89  	switch config.HelmCommand {
    90  	case "upgrade":
    91  		if err := helmExecutor.RunHelmUpgrade(); err != nil {
    92  			return fmt.Errorf("failed to execute upgrade: %v", err)
    93  		}
    94  	case "lint":
    95  		if err := helmExecutor.RunHelmLint(); err != nil {
    96  			return fmt.Errorf("failed to execute helm lint: %v", err)
    97  		}
    98  	case "install":
    99  		if err := helmExecutor.RunHelmInstall(); err != nil {
   100  			return fmt.Errorf("failed to execute helm install: %v", err)
   101  		}
   102  	case "test":
   103  		if err := helmExecutor.RunHelmTest(); err != nil {
   104  			return fmt.Errorf("failed to execute helm test: %v", err)
   105  		}
   106  	case "uninstall":
   107  		if err := helmExecutor.RunHelmUninstall(); err != nil {
   108  			return fmt.Errorf("failed to execute helm uninstall: %v", err)
   109  		}
   110  	case "dependency":
   111  		if err := helmExecutor.RunHelmDependency(); err != nil {
   112  			return fmt.Errorf("failed to execute helm dependency: %v", err)
   113  		}
   114  	case "publish":
   115  		targetURL, err := helmExecutor.RunHelmPublish()
   116  		if err != nil {
   117  			return fmt.Errorf("failed to execute helm publish: %v", err)
   118  		}
   119  		commonPipelineEnvironment.custom.helmChartURL = targetURL
   120  	default:
   121  		if err := runHelmExecuteDefault(config, helmExecutor, commonPipelineEnvironment); err != nil {
   122  			return err
   123  		}
   124  	}
   125  
   126  	return nil
   127  }
   128  
   129  func runHelmExecuteDefault(config helmExecuteOptions, helmExecutor kubernetes.HelmExecutor, commonPipelineEnvironment *helmExecuteCommonPipelineEnvironment) error {
   130  	if err := helmExecutor.RunHelmLint(); err != nil {
   131  		return fmt.Errorf("failed to execute helm lint: %v", err)
   132  	}
   133  
   134  	if len(config.Dependency) > 0 {
   135  		if err := helmExecutor.RunHelmDependency(); err != nil {
   136  			return fmt.Errorf("failed to execute helm dependency: %v", err)
   137  		}
   138  	}
   139  
   140  	if config.Publish {
   141  		targetURL, err := helmExecutor.RunHelmPublish()
   142  		if err != nil {
   143  			return fmt.Errorf("failed to execute helm publish: %v", err)
   144  		}
   145  		commonPipelineEnvironment.custom.helmChartURL = targetURL
   146  	}
   147  
   148  	return nil
   149  }
   150  
   151  // parseAndRenderCPETemplate allows to parse and render a template which contains references to the CPE
   152  func parseAndRenderCPETemplate(config helmExecuteOptions, rootPath string, utils fileHandler) error {
   153  	cpe := piperenv.CPEMap{}
   154  	err := cpe.LoadFromDisk(path.Join(rootPath, "commonPipelineEnvironment"))
   155  	if err != nil {
   156  		return fmt.Errorf("failed to load values from commonPipelineEnvironment: %v", err)
   157  	}
   158  
   159  	valueFiles := []string{}
   160  	defaultValueFile := fmt.Sprintf("%s/%s", config.ChartPath, "values.yaml")
   161  	defaultValueFileExists, err := utils.FileExists(defaultValueFile)
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	if defaultValueFileExists {
   167  		valueFiles = append(valueFiles, defaultValueFile)
   168  	} else {
   169  		if len(config.HelmValues) == 0 {
   170  			return fmt.Errorf("no value file to proccess, please provide value file(s)")
   171  		}
   172  	}
   173  	valueFiles = append(valueFiles, config.HelmValues...)
   174  
   175  	for _, valueFile := range valueFiles {
   176  		cpeTemplate, err := utils.FileRead(valueFile)
   177  		if err != nil {
   178  			return fmt.Errorf("failed to read file: %v", err)
   179  		}
   180  		generated, err := cpe.ParseTemplateWithDelimiter(string(cpeTemplate), config.TemplateStartDelimiter, config.TemplateEndDelimiter)
   181  		if err != nil {
   182  			return fmt.Errorf("failed to parse template: %v", err)
   183  		}
   184  		err = utils.FileWrite(valueFile, generated.Bytes(), 0700)
   185  		if err != nil {
   186  			return fmt.Errorf("failed to update file: %v", err)
   187  		}
   188  	}
   189  
   190  	return nil
   191  }
   192  
   193  type fileHandler interface {
   194  	FileExists(string) (bool, error)
   195  	FileRead(string) ([]byte, error)
   196  	FileWrite(string, []byte, os.FileMode) error
   197  }