mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-03-05 15:15:44 +02:00
(fix) gitopsUpdateDeployment - integration test for kustomize (#3572)
* (fix) gitopsUpdateDeployment - integration test for kustomize Signed-off-by: Michael Sprauer <Michael.Sprauer@sap.com> * (fix) test: dash login shell is "-l" Signed-off-by: Michael Sprauer <Michael.Sprauer@sap.com> Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
parent
af7496d012
commit
2c04f0acad
@ -79,7 +79,7 @@ func (g *gitopsUpdateDeploymentGitUtils) PlainClone(username, password, serverUR
|
||||
var err error
|
||||
g.repository, err = gitUtil.PlainClone(username, password, serverURL, directory)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "plain clone failed")
|
||||
return errors.Wrapf(err, "plain clone failed '%s'", serverURL)
|
||||
}
|
||||
g.worktree, err = g.repository.Worktree()
|
||||
return errors.Wrap(err, "failed to retrieve worktree")
|
||||
|
@ -315,7 +315,7 @@ func gitopsUpdateDeploymentMetadata() config.StepData {
|
||||
Containers: []config.Container{
|
||||
{Image: "dtzar/helm-kubectl:3.3.4", WorkingDir: "/config", Options: []config.Option{{Name: "-u", Value: "0"}}, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "tool", Value: "helm"}}}}},
|
||||
{Image: "dtzar/helm-kubectl:2.17.0", WorkingDir: "/config", Options: []config.Option{{Name: "-u", Value: "0"}}, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "tool", Value: "kubectl"}}}}},
|
||||
{Image: "k8s.gcr.io/kustomize/kustomize:v3.8.7", WorkingDir: "/config", Options: []config.Option{{Name: "-u", Value: "0"}}, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "tool", Value: "kustomize"}}}}},
|
||||
{Image: "nekottyo/kustomize-kubeval:kustomizev4", WorkingDir: "/config", Options: []config.Option{{Name: "-u", Value: "0"}}, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "tool", Value: "kustomize"}}}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -4,8 +4,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/magiconair/properties/assert"
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
@ -25,7 +29,7 @@ import (
|
||||
// Please note that so far this was only tested with debian/ubuntu based containers.
|
||||
//
|
||||
// Non-exhaustive list of assumptions those functions make:
|
||||
// - Bash is available in the container
|
||||
// - the following commands are available in the container: sh, chown, sleep
|
||||
// - If the option TestDir is not provided, the test project must be in the container image in the directory /project
|
||||
|
||||
// IntegrationTestDockerExecRunnerBundle is used to construct an instance of IntegrationTestDockerExecRunner
|
||||
@ -102,8 +106,10 @@ func givenThisContainer(t *testing.T, bundle IntegrationTestDockerExecRunnerBund
|
||||
}
|
||||
|
||||
if testRunner.Mounts != nil {
|
||||
wd, _ := os.Getwd()
|
||||
for src, dst := range testRunner.Mounts {
|
||||
params = append(params, "-v", fmt.Sprintf("%s:%s", src, dst))
|
||||
localSrc := path.Join(wd, src)
|
||||
params = append(params, "-v", fmt.Sprintf("%s:%s", localSrc, dst))
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +123,7 @@ func givenThisContainer(t *testing.T, bundle IntegrationTestDockerExecRunnerBund
|
||||
t.Fatalf("Starting test container has failed %s", err)
|
||||
}
|
||||
|
||||
if len(bundle.TestDir) > 0 {
|
||||
if len(bundle.TestDir) > 0 && testRunner.User != "" {
|
||||
err = testRunner.Runner.RunExecutable("docker", "exec", "-u=root", testRunner.ContainerName, "chown", "-R", testRunner.User, "/project")
|
||||
if err != nil {
|
||||
t.Fatalf("Chown /project has failed %s", err)
|
||||
@ -125,7 +131,7 @@ func givenThisContainer(t *testing.T, bundle IntegrationTestDockerExecRunnerBund
|
||||
}
|
||||
|
||||
for _, scriptLine := range testRunner.Setup {
|
||||
err := testRunner.Runner.RunExecutable("docker", "exec", testRunner.ContainerName, "/bin/bash", "-c", scriptLine)
|
||||
err := testRunner.Runner.RunExecutable("docker", "exec", testRunner.ContainerName, "/bin/sh", "-c", scriptLine)
|
||||
if err != nil {
|
||||
t.Fatalf("Running setup script in test container has failed %s", err)
|
||||
}
|
||||
@ -159,7 +165,7 @@ func setupPiperBinary(t *testing.T, testRunner IntegrationTestDockerExecRunner,
|
||||
if err != nil {
|
||||
t.Fatalf("Making command wrapper in container executable has failed %s", err)
|
||||
}
|
||||
err = testRunner.Runner.RunExecutable("docker", "exec", testRunner.ContainerName, "/bin/bash", "/piper-wrapper", "/piper", "version")
|
||||
err = testRunner.Runner.RunExecutable("docker", "exec", testRunner.ContainerName, "/bin/sh", "/piper-wrapper", "/piper", "version")
|
||||
if err != nil {
|
||||
t.Fatalf("Running piper failed. "+
|
||||
"Please check that '%s' is the correct binary, and is compiled for this configuration: 'GOOS=linux GOARCH=amd64'. Error text: %s", localPiper, err)
|
||||
@ -167,30 +173,40 @@ func setupPiperBinary(t *testing.T, testRunner IntegrationTestDockerExecRunner,
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) whenRunningPiperCommand(command string, parameters ...string) error {
|
||||
args := []string{"exec", "--workdir", "/project", d.ContainerName, "/bin/bash", "--login", "/piper-wrapper", "/piper", command}
|
||||
args := []string{"exec", "--workdir", "/project", d.ContainerName, "/bin/sh", "-l", "/piper-wrapper", "/piper", command}
|
||||
args = append(args, parameters...)
|
||||
return d.Runner.RunExecutable("docker", args...)
|
||||
err := d.Runner.RunExecutable("docker", args...)
|
||||
if err != nil {
|
||||
stdOut, err := d.getPiperOutput()
|
||||
return errors.Wrapf(err, "piper output: \n%s", stdOut.String())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) runScriptInsideContainer(script string) error {
|
||||
args := []string{"exec", "--workdir", "/project", d.ContainerName, "/bin/bash", "--login", "-c", script}
|
||||
args := []string{"exec", "--workdir", "/project", d.ContainerName, "/bin/sh", "-l", "-c", script}
|
||||
return d.Runner.RunExecutable("docker", args...)
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) assertHasOutput(t *testing.T, want string) {
|
||||
buffer := new(bytes.Buffer)
|
||||
d.Runner.Stdout(buffer)
|
||||
err := d.Runner.RunExecutable("docker", "exec", d.ContainerName, "cat", "/tmp/test-log.txt")
|
||||
d.Runner.Stdout(log.Writer())
|
||||
buffer, err := d.getPiperOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get log output of container %s", d.ContainerName)
|
||||
}
|
||||
|
||||
if !strings.Contains(buffer.String(), want) {
|
||||
t.Fatalf("Assertion has failed. Expected output %s in command output.\n%s", want, buffer.String())
|
||||
assert.Equal(t, buffer.String(), want, "Unexpected command output")
|
||||
}
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) getPiperOutput() (*bytes.Buffer, error) {
|
||||
buffer := new(bytes.Buffer)
|
||||
d.Runner.Stdout(buffer)
|
||||
err := d.Runner.RunExecutable("docker", "exec", d.ContainerName, "cat", "/tmp/test-log.txt")
|
||||
d.Runner.Stdout(log.Writer())
|
||||
return buffer, err
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) assertHasFile(t *testing.T, want string) {
|
||||
err := d.Runner.RunExecutable("docker", "exec", d.ContainerName, "stat", want)
|
||||
if err != nil {
|
||||
@ -198,6 +214,38 @@ func (d *IntegrationTestDockerExecRunner) assertHasFile(t *testing.T, want strin
|
||||
}
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) assertFileContentEquals(t *testing.T, fileWant string, contentWant string) {
|
||||
d.assertHasFile(t, fileWant)
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
d.Runner.Stdout(buffer)
|
||||
err := d.Runner.RunExecutable("docker", "cp", d.ContainerName+":/"+fileWant, "-")
|
||||
if err != nil {
|
||||
t.Fatalf("Copy file has failed. Expected file %s to exist in container. %s", fileWant, err)
|
||||
}
|
||||
|
||||
tarReader := tar.NewReader(buffer)
|
||||
header, err := tarReader.Next()
|
||||
if err == io.EOF {
|
||||
t.Fatal("Empty tar received")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Cant read tar: %s", err)
|
||||
}
|
||||
if header.Typeflag != tar.TypeReg {
|
||||
t.Fatalf("Expected a file, but received %c", header.Typeflag)
|
||||
}
|
||||
str := new(bytes.Buffer)
|
||||
_, err = io.Copy(str, tarReader)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get tar file content: %s", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(str.String(), contentWant) {
|
||||
assert.Equal(t, str.String(), contentWant, fmt.Sprintf("Unexpected content of file '%s'", fileWant))
|
||||
}
|
||||
}
|
||||
|
||||
func (d *IntegrationTestDockerExecRunner) terminate(t *testing.T) {
|
||||
err := d.Runner.RunExecutable("docker", "rm", "-f", d.ContainerName)
|
||||
if err != nil {
|
||||
|
38
integration/integration_gitopsUpdateDeployment_test.go
Normal file
38
integration/integration_gitopsUpdateDeployment_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
// can be execute with go test -tags=integration ./integration/...
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGitopsUpdateDeploymentIT(t *testing.T) {
|
||||
container := givenThisContainer(t, IntegrationTestDockerExecRunnerBundle{
|
||||
Image: "nekottyo/kustomize-kubeval:kustomizev4",
|
||||
TestDir: []string{"testdata", "TestGitopsUpdateIntegration", "kustomize", "workdir"},
|
||||
Mounts: map[string]string{"./testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo": "/gitopsRepo-source"},
|
||||
Setup: []string{"cp -r /gitopsRepo-source /gitopsRepo"},
|
||||
})
|
||||
defer container.terminate(t)
|
||||
|
||||
err := container.whenRunningPiperCommand("gitopsUpdateDeployment", "--containerImageNameTag=image:456")
|
||||
if err != nil {
|
||||
t.Fatalf("Calling piper command failed %s\n", err)
|
||||
}
|
||||
err = container.Runner.RunExecutable("docker", "exec", container.ContainerName, "git", "clone", "/gitopsRepo", "/tmp/repo")
|
||||
if err != nil {
|
||||
t.Fatalf("Cloing of bare repo failed")
|
||||
}
|
||||
|
||||
container.assertHasOutput(t, "SUCCESS")
|
||||
container.assertHasOutput(t, "[kustomize] updating")
|
||||
container.assertFileContentEquals(t, "/tmp/repo/kustomization.yaml", `images:
|
||||
- name: test-project
|
||||
newName: image
|
||||
newTag: "456"
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization`)
|
||||
}
|
1
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/HEAD
vendored
Normal file
1
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/HEAD
vendored
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
6
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/config
vendored
Normal file
6
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/config
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
1
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/description
vendored
Normal file
1
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/description
vendored
Normal file
@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
1
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/refs/heads/main
vendored
Normal file
1
integration/testdata/TestGitopsUpdateIntegration/kustomize/gitopsRepo/refs/heads/main
vendored
Normal file
@ -0,0 +1 @@
|
||||
bc34719dfe857a5d9ada1cbecf0292008ca0022e
|
11
integration/testdata/TestGitopsUpdateIntegration/kustomize/workdir/.pipeline/config.yml
vendored
Normal file
11
integration/testdata/TestGitopsUpdateIntegration/kustomize/workdir/.pipeline/config.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
general:
|
||||
maven:
|
||||
globalSettingsFile: settings.xml
|
||||
stages:
|
||||
steps:
|
||||
gitopsUpdateDeployment:
|
||||
serverUrl: file:///gitopsRepo
|
||||
tool: 'kustomize'
|
||||
deploymentName: 'test-project'
|
||||
filePath: "kustomization.yaml"
|
||||
branchName: "main"
|
@ -187,7 +187,7 @@ spec:
|
||||
params:
|
||||
- name: tool
|
||||
value: kubectl
|
||||
- image: k8s.gcr.io/kustomize/kustomize:v3.8.7
|
||||
- image: nekottyo/kustomize-kubeval:kustomizev4
|
||||
workingDir: /config
|
||||
options:
|
||||
- name: -u
|
||||
|
Loading…
x
Reference in New Issue
Block a user