From 7839db3048a9da1a01d2c180d438e60c20a88dfc Mon Sep 17 00:00:00 2001 From: NR Alberto Date: Sat, 23 Apr 2022 17:29:19 +0200 Subject: [PATCH] fix replaceAgentImages from panicking, adjust the implementation of that method and create different unit tests suites --- replacer.go | 23 ++++++++---- replacer_test.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 10 deletions(-) diff --git a/replacer.go b/replacer.go index 399865e..07cbef1 100644 --- a/replacer.go +++ b/replacer.go @@ -38,16 +38,25 @@ func replaceLibrary(content string) string { return strings.Replace(content, "@Library('ods-jenkins-shared-library@3.x') _", "@Library('ods-jenkins-shared-library@4.x') _", -1) } +// replaceAgentImages is a method that changes images which follows a quoted pattern like "ods/jenkins-agent-*". +//It considers single, double quotes, and multiple images in the same Jenkinsfile without panicking. func replaceAgentImages(content string) string { - re := regexp.MustCompile(`'ods/jenkins-agent-(.*):.*'`) - matches := re.FindAllStringSubmatch(content, -1) - fmt.Println(matches[0][1]) - if string(matches[0][1]) == "nodejs10-angular" { - return re.ReplaceAllString(content, "'ods/jenkins-agent-nodejs12:4.x'") - } + re := regexp.MustCompile(`(['"]{1}ods/jenkins-agent-)(.*):(.*)(['"]{1})`) + lines := strings.Split(content, "\n") - return re.ReplaceAllString(content, "'ods/jenkins-agent-$1:4.x'") + for idx, line := range lines { + if matches := re.FindStringSubmatch(line); matches != nil { + lines[idx] = func(s1 string, s2 []string) string { + if string(s2[2]) == "nodejs10-angular" { + return re.ReplaceAllString(s1, fmt.Sprintf("%s%s%s", s2[1], "nodejs12:4.x", s2[4])) + } else { + return re.ReplaceAllString(s1, fmt.Sprintf("%s%s%s%s", s2[1], s2[2], ":4.x", s2[4])) + } + }(line, matches) + } + } + return strings.Join(lines, "\n") } func replaceComponentStageImport(content string) string { diff --git a/replacer_test.go b/replacer_test.go index 009845d..f6a8c48 100644 --- a/replacer_test.go +++ b/replacer_test.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "io/ioutil" "testing" ) @@ -16,8 +17,7 @@ func TestReplace(t *testing.T) { args args want string }{ - { - name: "Stage Rollout Single Line", + {name: "Stage Rollout Single Line", args: args{ inputFile: "internal/test/stage-rollout-single-line/Jenkinsfile", convertedFile: "internal/test/stage-rollout-single-line/out/Jenkinsfile", @@ -48,7 +48,7 @@ func TestReplace(t *testing.T) { converted, err := ioutil.ReadFile(tt.args.convertedFile) if err != nil { - t.Errorf("failed to open file: %w", err) + t.Errorf("failed to open file: %v", err) } if got := string(converted); got != string(tt.want) { @@ -67,3 +67,93 @@ func readFile(goldenFile string) string { return string(want) } + +// The focus has been: matching patterns, quotes, duplicity of images, combination of them +func TestTableReplaceAgentImages(t *testing.T) { + + testsDouble := []struct { + input string + expected string + }{ + {input: "ods/jenkins-agent-base:3.0.0", expected: "\"ods/jenkins-agent-base:4.x\""}, + {input: "${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0", expected: "\"${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0\""}, + {input: "ods/jenkins-agent-nodejs10-angular:3.0.0", expected: "\"ods/jenkins-agent-nodejs12:4.x\""}, + {input: "odsalpha/jenkins-agent-nodejs10-angular:3.x", expected: "\"odsalpha/jenkins-agent-nodejs10-angular:3.x\""}, + {input: "odsalpha/jenkins-agent-base:3.x", expected: "\"odsalpha/jenkins-agent-base:3.x\""}, + {input: "", expected: "\"\""}, + {input: "${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest", expected: "\"${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest\""}, + } + + fmt.Println() + t.Logf("#####################################") + t.Logf("## Test suite double quoted values ##") + t.Logf("#####################################\n") + fmt.Println() + for _, test := range testsDouble { + doubleQuoted := fmt.Sprintf("%q", test.input) + if output := replaceAgentImages(doubleQuoted); output != test.expected { + t.Errorf("FAILED; input: %v, expected: %v, received: %v.", doubleQuoted, test.expected, output) + } else { + t.Logf("PASSED; input: %v, expected: %v, received: %v", doubleQuoted, test.expected, output) + } + } + + testsSingle := []struct { + input string + expected string + }{ + {input: "alpha/jenkins-agent-nodejs10-angular:3.x", expected: "'alpha/jenkins-agent-nodejs10-angular:3.x'"}, + {input: "ods/jenkins-agent-maven:3.0.0", expected: "'ods/jenkins-agent-maven:4.x'"}, + {input: "${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0", expected: "'${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'"}, + {input: "ods/jenkins-agent-nodejs10-angular:3.0.0", expected: "'ods/jenkins-agent-nodejs12:4.x'"}, + {input: "", expected: "''"}, + {input: "odsalpha/jenkins-agent-terraform:3.x", expected: "'odsalpha/jenkins-agent-terraform:3.x'"}, + {input: "${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest", expected: "'${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest'"}, + } + + fmt.Println() + fmt.Println() + t.Logf("#####################################") + t.Logf("## Test suite single quoted values ##") + t.Logf("#####################################\n") + fmt.Println() + for _, test := range testsSingle { + singleQuoted := fmt.Sprintf("'%v'", test.input) + if output := replaceAgentImages(singleQuoted); output != test.expected { + t.Errorf("FAILED; input: %v, expected: %v, received: %v.", singleQuoted, test.expected, output) + } else { + t.Logf("PASSED; input: %v, expected: %v, received: %v", singleQuoted, test.expected, output) + } + } + + testsMultiLines := []struct { + input string + expected string + }{ + {input: " 'alpha/jenkins-agent-nodejs10-angular:3.x'\n 'alpha/jenkins-agent-nodejs10-angular:3.x'\n", expected: " 'alpha/jenkins-agent-nodejs10-angular:3.x'\n 'alpha/jenkins-agent-nodejs10-angular:3.x'\n"}, + {input: " 'ods/jenkins-agent-maven:3.0.0'\n 'ods/jenkins-agent-maven:3.0.0'\n", expected: " 'ods/jenkins-agent-maven:4.x'\n 'ods/jenkins-agent-maven:4.x'\n"}, + {input: " 'ods/jenkins-agent-base:3.0.0'\n 'ods/jenkins-agent-base:4.x'\n", expected: " 'ods/jenkins-agent-base:4.x'\n 'ods/jenkins-agent-base:4.x'\n"}, + {input: " 'ods/jenkins-agent-base:4.x'\n 'ods/jenkins-agent-base:3.0.0'\n", expected: " 'ods/jenkins-agent-base:4.x'\n 'ods/jenkins-agent-base:4.x'\n"}, + {input: " '${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'\n '${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'\n", expected: " '${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'\n '${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'\n"}, + {input: " '${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'\n '${dockerRegistry}/ods/jenkins-agent-nodejs12-angular:4.x'\n", expected: " '${dockerRegistry}/ods/jenkins-agent-nodejs10-angular:3.0.0'\n '${dockerRegistry}/ods/jenkins-agent-nodejs12-angular:4.x'\n"}, + {input: " 'ods/jenkins-agent-nodejs10-angular:3.0.0'\n 'ods/jenkins-agent-nodejs12:4.x'\n", expected: " 'ods/jenkins-agent-nodejs12:4.x'\n 'ods/jenkins-agent-nodejs12:4.x'\n"}, + {input: " 'ods/jenkins-agent-nodejs12:4.x'\n 'ods/jenkins-agent-nodejs10-angular:3.0.0'\n", expected: " 'ods/jenkins-agent-nodejs12:4.x'\n 'ods/jenkins-agent-nodejs12:4.x'\n"}, + {input: " '${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest'\n '${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest'\n", expected: " '${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest'\n '${dockerRegistry}/edpp-cd/jenkins-agent-maven-chrome:latest'\n"}, + } + + fmt.Println() + fmt.Println() + t.Logf("######################################") + t.Logf("## Test suite multiple lines values ##") + t.Logf("######################################\n") + fmt.Println() + for _, test := range testsMultiLines { + multiLine := fmt.Sprintf("%v", test.input) + fmt.Println() + if output := replaceAgentImages(multiLine); output != test.expected { + t.Errorf("FAILED; input: %v, expected: %v, received: %v.", multiLine, test.expected, output) + } else { + t.Logf("PASSED; input: %v, expected: %v, received: %v", multiLine, test.expected, output) + } + } +}