2020-01-24 15:30:27 +02:00
package cmd
import (
"bytes"
"encoding/json"
"fmt"
"io"
2022-01-11 12:30:40 +02:00
"io/ioutil"
"os"
"path/filepath"
2020-01-24 15:30:27 +02:00
"regexp"
2022-03-08 15:52:43 +02:00
"sort"
2020-01-24 15:30:27 +02:00
"strconv"
"strings"
2022-03-08 15:52:43 +02:00
"text/template"
2020-01-24 15:30:27 +02:00
2022-01-11 12:30:40 +02:00
"github.com/SAP/jenkins-library/pkg/docker"
2022-06-29 12:00:37 +02:00
piperhttp "github.com/SAP/jenkins-library/pkg/http"
2022-02-10 11:25:03 +02:00
"github.com/SAP/jenkins-library/pkg/kubernetes"
2020-01-24 15:30:27 +02:00
"github.com/SAP/jenkins-library/pkg/log"
2020-02-04 11:46:43 +02:00
"github.com/SAP/jenkins-library/pkg/telemetry"
2022-02-28 11:43:55 +02:00
"github.com/pkg/errors"
2022-03-08 15:52:43 +02:00
"helm.sh/helm/v3/pkg/cli/values"
2020-01-24 15:30:27 +02:00
)
2021-12-02 13:18:21 +02:00
func kubernetesDeploy ( config kubernetesDeployOptions , telemetryData * telemetry . CustomData ) {
2022-03-17 18:13:34 +02:00
customTLSCertificateLinks := [ ] string { }
utils := kubernetes . NewDeployUtilsBundle ( customTLSCertificateLinks )
2021-03-25 13:26:44 +02:00
2022-01-28 09:31:34 +02:00
// error situations stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
err := runKubernetesDeploy ( config , telemetryData , utils , log . Writer ( ) )
2021-03-25 13:26:44 +02:00
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "step execution failed" )
}
2020-01-24 15:30:27 +02:00
}
2022-02-10 11:25:03 +02:00
func runKubernetesDeploy ( config kubernetesDeployOptions , telemetryData * telemetry . CustomData , utils kubernetes . DeployUtils , stdout io . Writer ) error {
2022-01-28 09:31:34 +02:00
telemetryData . Custom1Label = "deployTool"
telemetryData . Custom1 = config . DeployTool
2020-04-24 09:37:11 +02:00
if config . DeployTool == "helm" || config . DeployTool == "helm3" {
2022-06-29 12:00:37 +02:00
err := runHelmDeploy ( config , utils , stdout )
// download and execute teardown script
if len ( config . TeardownScript ) > 0 {
log . Entry ( ) . Debugf ( "start running teardownScript script %v" , config . TeardownScript )
if scriptErr := downloadAndExecuteExtensionScript ( config . TeardownScript , config . GithubToken , utils ) ; scriptErr != nil {
if err != nil {
err = fmt . Errorf ( "failed to download/run teardownScript script: %v: %w" , fmt . Sprint ( scriptErr ) , err )
} else {
err = scriptErr
}
}
log . Entry ( ) . Debugf ( "finished running teardownScript script %v" , config . TeardownScript )
}
return err
2021-03-25 13:26:44 +02:00
} else if config . DeployTool == "kubectl" {
2022-01-11 12:30:40 +02:00
return runKubectlDeploy ( config , utils , stdout )
2020-01-24 15:30:27 +02:00
}
2021-03-25 13:26:44 +02:00
return fmt . Errorf ( "Failed to execute deployments" )
2020-01-24 15:30:27 +02:00
}
2022-02-10 11:25:03 +02:00
func runHelmDeploy ( config kubernetesDeployOptions , utils kubernetes . DeployUtils , stdout io . Writer ) error {
2021-03-25 13:26:44 +02:00
if len ( config . ChartPath ) <= 0 {
return fmt . Errorf ( "chart path has not been set, please configure chartPath parameter" )
}
if len ( config . DeploymentName ) <= 0 {
return fmt . Errorf ( "deployment name has not been set, please configure deploymentName parameter" )
}
2022-06-29 12:00:37 +02:00
// download and execute setup script
if len ( config . SetupScript ) > 0 {
log . Entry ( ) . Debugf ( "start running setup script %v" , config . SetupScript )
if err := downloadAndExecuteExtensionScript ( config . SetupScript , config . GithubToken , utils ) ; err != nil {
return fmt . Errorf ( "failed to download/run setup setup script: %w" , err )
}
log . Entry ( ) . Debugf ( "finished running setup script %v" , config . SetupScript )
}
2020-01-24 15:30:27 +02:00
_ , containerRegistry , err := splitRegistryURL ( config . ContainerRegistryURL )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatalf ( "Container registry url '%v' incorrect" , config . ContainerRegistryURL )
}
2021-10-08 14:58:32 +02:00
2022-03-08 15:52:43 +02:00
helmValues , err := defineDeploymentValues ( config , containerRegistry )
if err != nil {
return errors . Wrap ( err , "failed to process deployment values" )
2020-01-24 15:30:27 +02:00
}
2022-02-24 13:01:36 +02:00
2020-01-24 15:30:27 +02:00
helmLogFields := map [ string ] interface { } { }
helmLogFields [ "Chart Path" ] = config . ChartPath
helmLogFields [ "Namespace" ] = config . Namespace
helmLogFields [ "Deployment Name" ] = config . DeploymentName
helmLogFields [ "Context" ] = config . KubeContext
helmLogFields [ "Kubeconfig" ] = config . KubeConfig
log . Entry ( ) . WithFields ( helmLogFields ) . Debug ( "Calling Helm" )
helmEnv := [ ] string { fmt . Sprintf ( "KUBECONFIG=%v" , config . KubeConfig ) }
2020-04-24 09:37:11 +02:00
if config . DeployTool == "helm" && len ( config . TillerNamespace ) > 0 {
2020-01-24 15:30:27 +02:00
helmEnv = append ( helmEnv , fmt . Sprintf ( "TILLER_NAMESPACE=%v" , config . TillerNamespace ) )
}
2020-02-27 13:11:22 +02:00
log . Entry ( ) . Debugf ( "Helm SetEnv: %v" , helmEnv )
2021-12-02 13:18:21 +02:00
utils . SetEnv ( helmEnv )
utils . Stdout ( stdout )
2020-01-24 15:30:27 +02:00
2020-04-24 09:37:11 +02:00
if config . DeployTool == "helm" {
initParams := [ ] string { "init" , "--client-only" }
2021-12-02 13:18:21 +02:00
if err := utils . RunExecutable ( "helm" , initParams ... ) ; err != nil {
2020-04-24 09:37:11 +02:00
log . Entry ( ) . WithError ( err ) . Fatal ( "Helm init call failed" )
}
2020-01-24 15:30:27 +02:00
}
2022-01-11 12:30:40 +02:00
if len ( config . ContainerRegistryUser ) == 0 && len ( config . ContainerRegistryPassword ) == 0 {
log . Entry ( ) . Info ( "No/incomplete container registry credentials provided: skipping secret creation" )
2020-08-18 07:32:36 +02:00
if len ( config . ContainerRegistrySecret ) > 0 {
2022-02-24 13:01:36 +02:00
helmValues . add ( "imagePullSecrets[0].name" , config . ContainerRegistrySecret )
2020-08-18 07:32:36 +02:00
}
2020-08-14 17:16:25 +02:00
} else {
var dockerRegistrySecret bytes . Buffer
2021-12-02 13:18:21 +02:00
utils . Stdout ( & dockerRegistrySecret )
2022-01-11 12:30:40 +02:00
err , kubeSecretParams := defineKubeSecretParams ( config , containerRegistry , utils )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "parameter definition for creating registry secret failed" )
}
2020-08-14 17:16:25 +02:00
log . Entry ( ) . Infof ( "Calling kubectl create secret --dry-run=true ..." )
2021-06-11 10:41:03 +02:00
log . Entry ( ) . Debugf ( "kubectl parameters %v" , kubeSecretParams )
2021-12-02 13:18:21 +02:00
if err := utils . RunExecutable ( "kubectl" , kubeSecretParams ... ) ; err != nil {
2020-08-14 17:16:25 +02:00
log . Entry ( ) . WithError ( err ) . Fatal ( "Retrieving Docker config via kubectl failed" )
}
var dockerRegistrySecretData struct {
Kind string ` json:"kind" `
Data struct {
DockerConfJSON string ` json:".dockerconfigjson" `
} ` json:"data" `
Type string ` json:"type" `
}
if err := json . Unmarshal ( dockerRegistrySecret . Bytes ( ) , & dockerRegistrySecretData ) ; err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "Reading docker registry secret json failed" )
}
// make sure that secret is hidden in log output
log . RegisterSecret ( dockerRegistrySecretData . Data . DockerConfJSON )
2020-01-24 15:30:27 +02:00
2022-03-08 15:52:43 +02:00
log . Entry ( ) . Debugf ( "Secret created: %v" , dockerRegistrySecret . String ( ) )
2020-08-18 07:32:36 +02:00
2020-08-14 17:16:25 +02:00
// pass secret in helm default template way and in Piper backward compatible way
2022-02-24 13:01:36 +02:00
helmValues . add ( "secret.name" , config . ContainerRegistrySecret )
helmValues . add ( "secret.dockerconfigjson" , dockerRegistrySecretData . Data . DockerConfJSON )
helmValues . add ( "imagePullSecrets[0].name" , config . ContainerRegistrySecret )
2020-08-14 17:16:25 +02:00
}
2020-08-06 11:23:36 +02:00
2020-08-18 07:32:36 +02:00
// Deprecated functionality
// only for backward compatible handling of ingress.hosts
// this requires an adoption of the default ingress.yaml template
// Due to the way helm is implemented it is currently not possible to overwrite a part of a list:
// see: https://github.com/helm/helm/issues/5711#issuecomment-636177594
// Recommended way is to use a custom values file which contains the appropriate data
2020-01-24 15:30:27 +02:00
for i , h := range config . IngressHosts {
2022-02-24 13:01:36 +02:00
helmValues . add ( fmt . Sprintf ( "ingress.hosts[%v]" , i ) , h )
2020-01-24 15:30:27 +02:00
}
upgradeParams := [ ] string {
"upgrade" ,
config . DeploymentName ,
config . ChartPath ,
2020-08-18 07:32:36 +02:00
}
for _ , v := range config . HelmValues {
upgradeParams = append ( upgradeParams , "--values" , v )
}
2022-02-28 11:43:55 +02:00
err = helmValues . mapValues ( )
if err != nil {
return errors . Wrap ( err , "failed to map values using 'valuesMapping' configuration" )
}
2020-08-18 07:32:36 +02:00
upgradeParams = append (
upgradeParams ,
2020-01-24 15:30:27 +02:00
"--install" ,
2020-04-24 09:37:11 +02:00
"--namespace" , config . Namespace ,
2022-03-08 15:52:43 +02:00
"--set" , strings . Join ( helmValues . marshal ( ) , "," ) ,
2020-08-18 07:32:36 +02:00
)
2020-01-24 15:30:27 +02:00
2021-01-07 17:52:16 +02:00
if config . ForceUpdates {
upgradeParams = append ( upgradeParams , "--force" )
}
2020-04-24 09:37:11 +02:00
if config . DeployTool == "helm" {
upgradeParams = append ( upgradeParams , "--wait" , "--timeout" , strconv . Itoa ( config . HelmDeployWaitSeconds ) )
}
if config . DeployTool == "helm3" {
2020-11-10 16:43:19 +02:00
upgradeParams = append ( upgradeParams , "--wait" , "--timeout" , fmt . Sprintf ( "%vs" , config . HelmDeployWaitSeconds ) )
}
if ! config . KeepFailedDeployments {
upgradeParams = append ( upgradeParams , "--atomic" )
2020-04-24 09:37:11 +02:00
}
2020-01-24 15:30:27 +02:00
if len ( config . KubeContext ) > 0 {
upgradeParams = append ( upgradeParams , "--kube-context" , config . KubeContext )
}
if len ( config . AdditionalParameters ) > 0 {
upgradeParams = append ( upgradeParams , config . AdditionalParameters ... )
}
2021-12-02 13:18:21 +02:00
utils . Stdout ( stdout )
2020-01-24 15:30:27 +02:00
log . Entry ( ) . Info ( "Calling helm upgrade ..." )
log . Entry ( ) . Debugf ( "Helm parameters %v" , upgradeParams )
2021-12-02 13:18:21 +02:00
if err := utils . RunExecutable ( "helm" , upgradeParams ... ) ; err != nil {
2020-01-24 15:30:27 +02:00
log . Entry ( ) . WithError ( err ) . Fatal ( "Helm upgrade call failed" )
}
2022-01-25 11:42:42 +02:00
2022-06-29 12:00:37 +02:00
// download and execute verification script
if len ( config . VerificationScript ) > 0 {
log . Entry ( ) . Debugf ( "start running verification script %v" , config . VerificationScript )
if err := downloadAndExecuteExtensionScript ( config . VerificationScript , config . GithubToken , utils ) ; err != nil {
return fmt . Errorf ( "failed to download/run verification script: %w" , err )
}
log . Entry ( ) . Debugf ( "finished running verification script %v" , config . VerificationScript )
}
2022-01-25 11:42:42 +02:00
testParams := [ ] string {
"test" ,
config . DeploymentName ,
"--namespace" , config . Namespace ,
}
if config . ShowTestLogs {
testParams = append (
testParams ,
"--logs" ,
)
}
if config . RunHelmTests {
if err := utils . RunExecutable ( "helm" , testParams ... ) ; err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "Helm test call failed" )
}
}
2021-03-25 13:26:44 +02:00
return nil
2020-01-24 15:30:27 +02:00
}
2022-02-10 11:25:03 +02:00
func runKubectlDeploy ( config kubernetesDeployOptions , utils kubernetes . DeployUtils , stdout io . Writer ) error {
2020-01-24 15:30:27 +02:00
_ , containerRegistry , err := splitRegistryURL ( config . ContainerRegistryURL )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatalf ( "Container registry url '%v' incorrect" , config . ContainerRegistryURL )
}
kubeParams := [ ] string {
"--insecure-skip-tls-verify=true" ,
fmt . Sprintf ( "--namespace=%v" , config . Namespace ) ,
}
if len ( config . KubeConfig ) > 0 {
log . Entry ( ) . Info ( "Using KUBECONFIG environment for authentication." )
kubeEnv := [ ] string { fmt . Sprintf ( "KUBECONFIG=%v" , config . KubeConfig ) }
2021-12-02 13:18:21 +02:00
utils . SetEnv ( kubeEnv )
2020-01-24 15:30:27 +02:00
if len ( config . KubeContext ) > 0 {
kubeParams = append ( kubeParams , fmt . Sprintf ( "--context=%v" , config . KubeContext ) )
}
} else {
log . Entry ( ) . Info ( "Using --token parameter for authentication." )
kubeParams = append ( kubeParams , fmt . Sprintf ( "--server=%v" , config . APIServer ) )
kubeParams = append ( kubeParams , fmt . Sprintf ( "--token=%v" , config . KubeToken ) )
}
2022-01-11 12:30:40 +02:00
utils . Stdout ( stdout )
if len ( config . ContainerRegistryUser ) == 0 && len ( config . ContainerRegistryPassword ) == 0 {
log . Entry ( ) . Info ( "No/incomplete container registry credentials provided: skipping secret creation" )
} else {
err , kubeSecretParams := defineKubeSecretParams ( config , containerRegistry , utils )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "parameter definition for creating registry secret failed" )
}
var dockerRegistrySecret bytes . Buffer
utils . Stdout ( & dockerRegistrySecret )
log . Entry ( ) . Infof ( "Creating container registry secret '%v'" , config . ContainerRegistrySecret )
kubeSecretParams = append ( kubeSecretParams , kubeParams ... )
log . Entry ( ) . Debugf ( "Running kubectl with following parameters: %v" , kubeSecretParams )
if err := utils . RunExecutable ( "kubectl" , kubeSecretParams ... ) ; err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "Creating container registry secret failed" )
}
var dockerRegistrySecretData map [ string ] interface { }
if err := json . Unmarshal ( dockerRegistrySecret . Bytes ( ) , & dockerRegistrySecretData ) ; err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "Reading docker registry secret json failed" )
2020-01-24 15:30:27 +02:00
}
2021-06-11 10:41:03 +02:00
2022-01-11 12:30:40 +02:00
// write the json output to a file
2022-03-08 15:52:43 +02:00
tmpFolder := getTempDirForKubeCtlJSON ( )
2022-01-11 12:30:40 +02:00
defer os . RemoveAll ( tmpFolder ) // clean up
jsonData , _ := json . Marshal ( dockerRegistrySecretData )
ioutil . WriteFile ( filepath . Join ( tmpFolder , "secret.json" ) , jsonData , 0777 )
kubeSecretApplyParams := [ ] string { "apply" , "-f" , filepath . Join ( tmpFolder , "secret.json" ) }
if err := utils . RunExecutable ( "kubectl" , kubeSecretApplyParams ... ) ; err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "Creating container registry secret failed" )
2020-01-24 15:30:27 +02:00
}
2022-01-11 12:30:40 +02:00
2020-01-24 15:30:27 +02:00
}
2021-12-02 13:18:21 +02:00
appTemplate , err := utils . FileRead ( config . AppTemplate )
2020-01-24 15:30:27 +02:00
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatalf ( "Error when reading appTemplate '%v'" , config . AppTemplate )
}
2022-03-08 15:52:43 +02:00
values , err := defineDeploymentValues ( config , containerRegistry )
if err != nil {
return errors . Wrap ( err , "failed to process deployment values" )
}
err = values . mapValues ( )
if err != nil {
return errors . Wrap ( err , "failed to map values using 'valuesMapping' configuration" )
2021-10-08 14:58:32 +02:00
}
2020-01-24 15:30:27 +02:00
re := regexp . MustCompile ( ` image:[ ]*<image-name> ` )
2022-03-08 15:52:43 +02:00
placeholderFound := re . Match ( appTemplate )
2020-01-24 15:30:27 +02:00
2022-03-08 15:52:43 +02:00
if placeholderFound {
log . Entry ( ) . Warn ( "image placeholder '<image-name>' is deprecated and does not support multi-image replacement, please use Helm-like template syntax '{{ .Values.image.[image-name].reposotory }}:{{ .Values.image.[image-name].tag }}" )
if values . singleImage {
// Update image name in deployment yaml, expects placeholder like 'image: <image-name>'
appTemplate = [ ] byte ( re . ReplaceAllString ( string ( appTemplate ) , fmt . Sprintf ( "image: %s:%s" , values . get ( "image.repository" ) , values . get ( "image.tag" ) ) ) )
} else {
return fmt . Errorf ( "multi-image replacement not supported for single image placeholder" )
}
}
buf := bytes . NewBufferString ( "" )
tpl , err := template . New ( "appTemplate" ) . Parse ( string ( appTemplate ) )
if err != nil {
return errors . Wrap ( err , "failed to parse app-template file" )
}
err = tpl . Execute ( buf , values . asHelmValues ( ) )
if err != nil {
return errors . Wrap ( err , "failed to render app-template file" )
}
err = utils . FileWrite ( config . AppTemplate , buf . Bytes ( ) , 0700 )
2020-01-24 15:30:27 +02:00
if err != nil {
2022-03-08 15:52:43 +02:00
return errors . Wrapf ( err , "Error when updating appTemplate '%v'" , config . AppTemplate )
2020-01-24 15:30:27 +02:00
}
2021-11-04 15:11:31 +02:00
kubeParams = append ( kubeParams , config . DeployCommand , "--filename" , config . AppTemplate )
2022-03-08 15:52:43 +02:00
if config . ForceUpdates && config . DeployCommand == "replace" {
2021-11-04 15:11:31 +02:00
kubeParams = append ( kubeParams , "--force" )
}
2020-01-24 15:30:27 +02:00
if len ( config . AdditionalParameters ) > 0 {
2021-11-04 15:11:31 +02:00
kubeParams = append ( kubeParams , config . AdditionalParameters ... )
2020-01-24 15:30:27 +02:00
}
2021-12-02 13:18:21 +02:00
if err := utils . RunExecutable ( "kubectl" , kubeParams ... ) ; err != nil {
2021-11-04 15:11:31 +02:00
log . Entry ( ) . Debugf ( "Running kubectl with following parameters: %v" , kubeParams )
2020-01-24 15:30:27 +02:00
log . Entry ( ) . WithError ( err ) . Fatal ( "Deployment with kubectl failed." )
}
2021-03-25 13:26:44 +02:00
return nil
2020-01-24 15:30:27 +02:00
}
2022-03-08 15:52:43 +02:00
type deploymentValues struct {
mapping map [ string ] interface { }
singleImage bool
values [ ] struct {
2022-02-28 11:43:55 +02:00
key , value string
}
2022-02-24 13:01:36 +02:00
}
2022-03-08 15:52:43 +02:00
func ( dv * deploymentValues ) add ( key , value string ) {
dv . values = append ( dv . values , struct {
2022-02-24 13:01:36 +02:00
key string
value string
} {
key : key ,
value : value ,
} )
}
2022-03-08 15:52:43 +02:00
func ( dv deploymentValues ) get ( key string ) string {
for _ , item := range dv . values {
2022-02-28 11:43:55 +02:00
if item . key == key {
return item . value
}
}
return ""
}
2022-03-08 15:52:43 +02:00
func ( dv * deploymentValues ) mapValues ( ) error {
var keys [ ] string
for k := range dv . mapping {
keys = append ( keys , k )
}
sort . Strings ( keys )
for _ , dst := range keys {
srcString , ok := dv . mapping [ dst ] . ( string )
2022-02-28 11:43:55 +02:00
if ! ok {
2022-03-08 15:52:43 +02:00
return fmt . Errorf ( "invalid path '%#v' is used for valuesMapping, only strings are supported" , dv . mapping [ dst ] )
2022-02-28 11:43:55 +02:00
}
2022-03-08 15:52:43 +02:00
if val := dv . get ( srcString ) ; val != "" {
dv . add ( dst , val )
2022-02-28 11:43:55 +02:00
} else {
2022-03-08 15:52:43 +02:00
log . Entry ( ) . Warnf ( "can not map '%s: %s', %s is not set" , dst , dv . mapping [ dst ] , dv . mapping [ dst ] )
2022-02-28 11:43:55 +02:00
}
}
return nil
}
2022-03-08 15:52:43 +02:00
func ( dv deploymentValues ) marshal ( ) [ ] string {
var result [ ] string
for _ , item := range dv . values {
result = append ( result , fmt . Sprintf ( "%s=%s" , item . key , item . value ) )
}
return result
}
func ( dv * deploymentValues ) asHelmValues ( ) map [ string ] interface { } {
valuesOpts := values . Options {
Values : dv . marshal ( ) ,
}
mergedValues , err := valuesOpts . MergeValues ( nil )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatal ( "failed to process deployment values" )
}
return map [ string ] interface { } {
"Values" : mergedValues ,
2022-02-24 13:01:36 +02:00
}
}
2022-03-08 15:52:43 +02:00
func joinKey ( parts ... string ) string {
escapedParts := make ( [ ] string , 0 , len ( parts ) )
replacer := strings . NewReplacer ( "." , "_" , "-" , "_" )
for _ , part := range parts {
escapedParts = append ( escapedParts , replacer . Replace ( part ) )
}
return strings . Join ( escapedParts , "." )
}
func getTempDirForKubeCtlJSON ( ) string {
2022-01-11 12:30:40 +02:00
tmpFolder , err := ioutil . TempDir ( "." , "temp-" )
if err != nil {
log . Entry ( ) . WithError ( err ) . WithField ( "path" , tmpFolder ) . Debug ( "creating temp directory failed" )
}
return tmpFolder
}
2020-01-24 15:30:27 +02:00
func splitRegistryURL ( registryURL string ) ( protocol , registry string , err error ) {
parts := strings . Split ( registryURL , "://" )
if len ( parts ) != 2 || len ( parts [ 1 ] ) == 0 {
return "" , "" , fmt . Errorf ( "Failed to split registry url '%v'" , registryURL )
}
return parts [ 0 ] , parts [ 1 ] , nil
}
func splitFullImageName ( image string ) ( imageName , tag string , err error ) {
parts := strings . Split ( image , ":" )
switch len ( parts ) {
case 0 :
return "" , "" , fmt . Errorf ( "Failed to split image name '%v'" , image )
case 1 :
if len ( parts [ 0 ] ) > 0 {
return parts [ 0 ] , "" , nil
}
return "" , "" , fmt . Errorf ( "Failed to split image name '%v'" , image )
case 2 :
return parts [ 0 ] , parts [ 1 ] , nil
}
return "" , "" , fmt . Errorf ( "Failed to split image name '%v'" , image )
}
2021-06-11 10:41:03 +02:00
2022-02-10 11:25:03 +02:00
func defineKubeSecretParams ( config kubernetesDeployOptions , containerRegistry string , utils kubernetes . DeployUtils ) ( error , [ ] string ) {
2022-01-11 12:30:40 +02:00
targetPath := ""
2021-06-11 10:41:03 +02:00
if len ( config . DockerConfigJSON ) > 0 {
2021-12-02 13:18:21 +02:00
// first enhance config.json with additional pipeline-related credentials if they have been provided
if len ( containerRegistry ) > 0 && len ( config . ContainerRegistryUser ) > 0 && len ( config . ContainerRegistryPassword ) > 0 {
var err error
2022-01-11 12:30:40 +02:00
targetPath , err = docker . CreateDockerConfigJSON ( containerRegistry , config . ContainerRegistryUser , config . ContainerRegistryPassword , "" , config . DockerConfigJSON , utils )
2021-12-02 13:18:21 +02:00
if err != nil {
log . Entry ( ) . Warningf ( "failed to update Docker config.json: %v" , err )
2022-01-11 12:30:40 +02:00
return err , [ ] string { }
2021-12-02 13:18:21 +02:00
}
}
2022-01-11 12:30:40 +02:00
} else {
return fmt . Errorf ( "no docker config json file found to update credentials '%v'" , config . DockerConfigJSON ) , [ ] string { }
}
return nil , [ ] string {
"create" ,
"secret" ,
"generic" ,
2021-06-11 10:41:03 +02:00
config . ContainerRegistrySecret ,
2022-01-11 12:30:40 +02:00
fmt . Sprintf ( "--from-file=.dockerconfigjson=%v" , targetPath ) ,
"--type=kubernetes.io/dockerconfigjson" ,
"--insecure-skip-tls-verify=true" ,
"--dry-run=client" ,
"--output=json" ,
}
2021-06-11 10:41:03 +02:00
}
2022-03-08 15:52:43 +02:00
func defineDeploymentValues ( config kubernetesDeployOptions , containerRegistry string ) ( * deploymentValues , error ) {
var err error
2022-03-09 10:48:19 +02:00
var useDigests bool
2022-03-08 15:52:43 +02:00
dv := & deploymentValues {
mapping : config . ValuesMapping ,
}
if len ( config . ImageNames ) > 0 {
if len ( config . ImageNames ) != len ( config . ImageNameTags ) {
log . SetErrorCategory ( log . ErrorConfiguration )
return nil , fmt . Errorf ( "number of imageNames and imageNameTags must be equal" )
}
2022-03-09 10:48:19 +02:00
if len ( config . ImageDigests ) > 0 {
if len ( config . ImageDigests ) != len ( config . ImageNameTags ) {
log . SetErrorCategory ( log . ErrorConfiguration )
return nil , fmt . Errorf ( "number of imageDigests and imageNameTags must be equal" )
}
useDigests = true
}
2022-03-08 15:52:43 +02:00
for i , key := range config . ImageNames {
name , tag , err := splitFullImageName ( config . ImageNameTags [ i ] )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatalf ( "Container image '%v' incorrect" , config . ImageNameTags [ i ] )
}
2022-03-09 10:48:19 +02:00
if useDigests {
tag = fmt . Sprintf ( "%s@%s" , tag , config . ImageDigests [ i ] )
}
2022-03-08 15:52:43 +02:00
dv . add ( joinKey ( "image" , key , "repository" ) , fmt . Sprintf ( "%v/%v" , containerRegistry , name ) )
dv . add ( joinKey ( "image" , key , "tag" ) , tag )
if len ( config . ImageNames ) == 1 {
dv . singleImage = true
dv . add ( "image.repository" , fmt . Sprintf ( "%v/%v" , containerRegistry , name ) )
dv . add ( "image.tag" , tag )
}
}
} else {
// support either image or containerImageName and containerImageTag
containerImageName := ""
containerImageTag := ""
dv . singleImage = true
if len ( config . Image ) > 0 {
containerImageName , containerImageTag , err = splitFullImageName ( config . Image )
if err != nil {
log . Entry ( ) . WithError ( err ) . Fatalf ( "Container image '%v' incorrect" , config . Image )
}
} else if len ( config . ContainerImageName ) > 0 && len ( config . ContainerImageTag ) > 0 {
containerImageName = config . ContainerImageName
containerImageTag = config . ContainerImageTag
} else {
return nil , fmt . Errorf ( "image information not given - please either set image or containerImageName and containerImageTag" )
}
dv . add ( "image.repository" , fmt . Sprintf ( "%v/%v" , containerRegistry , containerImageName ) )
dv . add ( "image.tag" , containerImageTag )
dv . add ( joinKey ( "image" , containerImageName , "repository" ) , fmt . Sprintf ( "%v/%v" , containerRegistry , containerImageName ) )
dv . add ( joinKey ( "image" , containerImageName , "tag" ) , containerImageTag )
}
return dv , nil
}
2022-06-29 12:00:37 +02:00
func downloadAndExecuteExtensionScript ( script , githubToken string , utils kubernetes . DeployUtils ) error {
setupScript , err := piperhttp . DownloadExecutable ( githubToken , utils , utils , script )
if err != nil {
return fmt . Errorf ( "failed to download script %v: %w" , script , err )
}
err = utils . RunExecutable ( setupScript )
if err != nil {
return fmt . Errorf ( "failed to execute script %v: %w" , script , err )
}
return nil
}