You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +02:00
Introducing syft to generate SBOMS for kaniko builds (#4093)
* Update kanikoExecute.go * Syft function * Change installation directory to ease cleanup * Add createBOM option * Unit tests * Refactor code Co-authored-by: raman-susla-epam <104915202+raman-susla-epam@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/buildsettings"
|
||||
@@ -16,6 +17,50 @@ import (
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
)
|
||||
|
||||
const syftURL = "https://raw.githubusercontent.com/anchore/syft/main/install.sh"
|
||||
|
||||
type kanikoHttpClient interface {
|
||||
piperhttp.Sender
|
||||
DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error
|
||||
}
|
||||
|
||||
func installSyft(shellRunner command.ShellRunner, fileUtils piperutils.FileUtils, httpClient kanikoHttpClient) error {
|
||||
installationScript := "./install.sh"
|
||||
err := httpClient.DownloadFile(syftURL, installationScript, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download syft: %w", err)
|
||||
}
|
||||
|
||||
err = fileUtils.Chmod(installationScript, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = shellRunner.RunShell("/busybox/sh", "cat ./install.sh | sh -s -- -b .")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to install syft: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateSBOM(shellRunner command.ShellRunner, fileUtils piperutils.FileUtils, httpClient kanikoHttpClient, commonPipelineEnvironment *kanikoExecuteCommonPipelineEnvironment) error {
|
||||
shellRunner.AppendEnv([]string{"DOCKER_CONFIG", "/kaniko/.docker"})
|
||||
syftInstallErr := installSyft(shellRunner, fileUtils, httpClient)
|
||||
if syftInstallErr != nil {
|
||||
return syftInstallErr
|
||||
}
|
||||
for index, eachImageTag := range commonPipelineEnvironment.container.imageNameTags {
|
||||
// TrimPrefix needed as syft needs containerRegistry name only
|
||||
syftRunErr := shellRunner.RunShell("/busybox/sh", fmt.Sprintf("./syft %s/%s -o cyclonedx-xml=bom-docker-%v.xml", strings.TrimPrefix(commonPipelineEnvironment.container.registryURL, "https://"), eachImageTag, index))
|
||||
if syftRunErr != nil {
|
||||
return fmt.Errorf("failed to generate SBOM: %w", syftRunErr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func kanikoExecute(config kanikoExecuteOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *kanikoExecuteCommonPipelineEnvironment) {
|
||||
// for command execution use Command
|
||||
c := command.Command{
|
||||
@@ -34,13 +79,13 @@ func kanikoExecute(config kanikoExecuteOptions, telemetryData *telemetry.CustomD
|
||||
|
||||
fileUtils := &piperutils.Files{}
|
||||
|
||||
err := runKanikoExecute(&config, telemetryData, commonPipelineEnvironment, &c, client, fileUtils)
|
||||
err := runKanikoExecute(&config, telemetryData, commonPipelineEnvironment, &c, &c, client, fileUtils)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("Kaniko execution failed")
|
||||
}
|
||||
}
|
||||
|
||||
func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *kanikoExecuteCommonPipelineEnvironment, execRunner command.ExecRunner, httpClient piperhttp.Sender, fileUtils piperutils.FileUtils) error {
|
||||
func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *kanikoExecuteCommonPipelineEnvironment, execRunner command.ExecRunner, shellRunner command.ShellRunner, httpClient kanikoHttpClient, fileUtils piperutils.FileUtils) error {
|
||||
binfmtSupported, _ := docker.IsBinfmtMiscSupportedByHost(fileUtils)
|
||||
|
||||
if !binfmtSupported && len(config.TargetArchitectures) > 0 {
|
||||
@@ -175,7 +220,10 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus
|
||||
containerImageNameAndTag := fmt.Sprintf("%v:%v", config.ContainerImageName, containerImageTag)
|
||||
commonPipelineEnvironment.container.imageNameTag = containerImageNameAndTag
|
||||
}
|
||||
|
||||
if config.CreateBOM {
|
||||
//Syft for multi image, generates bom-docker-(1/2/3).xml
|
||||
return generateSBOM(shellRunner, fileUtils, httpClient, commonPipelineEnvironment)
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
commonPipelineEnvironment.container.imageNames = append(commonPipelineEnvironment.container.imageNames, config.ContainerImageName)
|
||||
@@ -232,7 +280,15 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus
|
||||
}
|
||||
|
||||
// no support for building multiple containers
|
||||
return runKaniko(config.DockerfilePath, config.BuildOptions, config.ReadImageDigest, execRunner, fileUtils, commonPipelineEnvironment)
|
||||
kanikoErr := runKaniko(config.DockerfilePath, config.BuildOptions, config.ReadImageDigest, execRunner, fileUtils, commonPipelineEnvironment)
|
||||
if kanikoErr != nil {
|
||||
return kanikoErr
|
||||
}
|
||||
if config.CreateBOM {
|
||||
// Syft for single image, generates bom-docker-0.xml
|
||||
return generateSBOM(shellRunner, fileUtils, httpClient, commonPipelineEnvironment)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runKaniko(dockerFilepath string, buildOptions []string, readDigest bool, execRunner command.ExecRunner, fileUtils piperutils.FileUtils, commonPipelineEnvironment *kanikoExecuteCommonPipelineEnvironment) error {
|
||||
|
@@ -36,6 +36,7 @@ type kanikoExecuteOptions struct {
|
||||
DockerfilePath string `json:"dockerfilePath,omitempty"`
|
||||
TargetArchitectures []string `json:"targetArchitectures,omitempty"`
|
||||
ReadImageDigest bool `json:"readImageDigest,omitempty"`
|
||||
CreateBOM bool `json:"createBOM,omitempty"`
|
||||
}
|
||||
|
||||
type kanikoExecuteCommonPipelineEnvironment struct {
|
||||
@@ -257,6 +258,7 @@ func addKanikoExecuteFlags(cmd *cobra.Command, stepConfig *kanikoExecuteOptions)
|
||||
cmd.Flags().StringVar(&stepConfig.DockerfilePath, "dockerfilePath", `Dockerfile`, "Defines the location of the Dockerfile relative to the Jenkins workspace.")
|
||||
cmd.Flags().StringSliceVar(&stepConfig.TargetArchitectures, "targetArchitectures", []string{``}, "Defines the target architectures for which the build should run using OS and architecture separated by a comma. (EXPERIMENTAL)")
|
||||
cmd.Flags().BoolVar(&stepConfig.ReadImageDigest, "readImageDigest", false, "")
|
||||
cmd.Flags().BoolVar(&stepConfig.CreateBOM, "createBOM", false, "Creates the bill of materials (BOM) using Syft and stored in a file of CycloneDX 1.4 format.")
|
||||
|
||||
}
|
||||
|
||||
@@ -472,6 +474,15 @@ func kanikoExecuteMetadata() config.StepData {
|
||||
Aliases: []config.Alias{},
|
||||
Default: false,
|
||||
},
|
||||
{
|
||||
Name: "createBOM",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
Containers: []config.Container{
|
||||
|
@@ -36,6 +36,12 @@ func (c *kanikoMockClient) SendRequest(method, url string, body io.Reader, heade
|
||||
}
|
||||
return &http.Response{StatusCode: c.httpStatusCode, Body: ioutil.NopCloser(bytes.NewReader([]byte(c.responseBody)))}, nil
|
||||
}
|
||||
func (c *kanikoMockClient) DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error {
|
||||
if len(c.errorMessage) > 0 {
|
||||
return fmt.Errorf(c.errorMessage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestRunKanikoExecute(t *testing.T) {
|
||||
|
||||
@@ -59,7 +65,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
BuildSettingsInfo: `{"mavenExecuteBuild":[{"dockerImage":"maven"}]}`,
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -69,21 +76,21 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "rm", runner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, runner.Calls[0].Params)
|
||||
assert.Equal(t, "rm", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, execRunner.Calls[0].Params)
|
||||
|
||||
assert.Equal(t, config.CustomTLSCertificateLinks, certClient.urlsCalled)
|
||||
c, err := fileUtils.FileRead("/kaniko/.docker/config.json")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"auths":{"custom":"test"}}`, string(c))
|
||||
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "myImage:tag"}, runner.Calls[1].Params)
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "myImage:tag"}, execRunner.Calls[1].Params)
|
||||
|
||||
assert.Contains(t, commonPipelineEnvironment.custom.buildSettingsInfo, `"mavenExecuteBuild":[{"dockerImage":"maven"}]`)
|
||||
assert.Contains(t, commonPipelineEnvironment.custom.buildSettingsInfo, `"kanikoExecute":[{"dockerImage":"gcr.io/kaniko-project/executor:debug"}]`)
|
||||
@@ -109,7 +116,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
ReadImageDigest: true,
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -120,21 +128,21 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
fileUtils.AddFile("/tmp/*-kanikoExecutetest/digest.txt", []byte(`sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0`))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "rm", runner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, runner.Calls[0].Params)
|
||||
assert.Equal(t, "rm", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, execRunner.Calls[0].Params)
|
||||
|
||||
assert.Equal(t, config.CustomTLSCertificateLinks, certClient.urlsCalled)
|
||||
c, err := fileUtils.FileRead("/kaniko/.docker/config.json")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"auths":{"custom":"test"}}`, string(c))
|
||||
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "myImage:tag", "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt"}, runner.Calls[1].Params)
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "myImage:tag", "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt"}, execRunner.Calls[1].Params)
|
||||
|
||||
assert.Contains(t, commonPipelineEnvironment.custom.buildSettingsInfo, `"mavenExecuteBuild":[{"dockerImage":"maven"}]`)
|
||||
assert.Contains(t, commonPipelineEnvironment.custom.buildSettingsInfo, `"kanikoExecute":[{"dockerImage":"gcr.io/kaniko-project/executor:debug"}]`)
|
||||
@@ -160,7 +168,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -170,21 +179,21 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "rm", runner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, runner.Calls[0].Params)
|
||||
assert.Equal(t, "rm", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, execRunner.Calls[0].Params)
|
||||
|
||||
assert.Equal(t, config.CustomTLSCertificateLinks, certClient.urlsCalled)
|
||||
c, err := fileUtils.FileRead("/kaniko/.docker/config.json")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"auths":{"custom":"test"}}`, string(c))
|
||||
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "my.registry.com:50000/myImage:1.2.3-a-x"}, runner.Calls[1].Params)
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "my.registry.com:50000/myImage:1.2.3-a-x"}, execRunner.Calls[1].Params)
|
||||
|
||||
assert.Equal(t, "myImage:1.2.3-a-x", commonPipelineEnvironment.container.imageNameTag)
|
||||
assert.Equal(t, "https://my.registry.com:50000", commonPipelineEnvironment.container.registryURL)
|
||||
@@ -204,7 +213,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -214,21 +224,21 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "rm", runner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, runner.Calls[0].Params)
|
||||
assert.Equal(t, "rm", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, execRunner.Calls[0].Params)
|
||||
|
||||
assert.Equal(t, config.CustomTLSCertificateLinks, certClient.urlsCalled)
|
||||
c, err := fileUtils.FileRead("/kaniko/.docker/config.json")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"auths":{"custom":"test"}}`, string(c))
|
||||
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "my.other.registry.com:50000/myImage:3.2.1-a-x"}, runner.Calls[1].Params)
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "my.other.registry.com:50000/myImage:3.2.1-a-x"}, execRunner.Calls[1].Params)
|
||||
|
||||
assert.Equal(t, "myImage:3.2.1-a-x", commonPipelineEnvironment.container.imageNameTag)
|
||||
assert.Equal(t, "https://my.other.registry.com:50000", commonPipelineEnvironment.container.registryURL)
|
||||
@@ -251,7 +261,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{}
|
||||
@@ -259,7 +270,7 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(``))
|
||||
fileUtils.FileReadErrors = map[string]error{"/kaniko/ssl/certs/ca-certificates.crt": fmt.Errorf("read error")}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoErrorf(t, err, "failed to update certificates: failed to load file '/kaniko/ssl/certs/ca-certificates.crt': read error")
|
||||
})
|
||||
@@ -272,7 +283,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
DockerfilePath: "Dockerfile",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -281,7 +293,7 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -290,7 +302,7 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
assert.Equal(t, `{"auths":{}}`, string(c))
|
||||
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--no-push"}, runner.Calls[1].Params)
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--no-push"}, execRunner.Calls[1].Params)
|
||||
})
|
||||
|
||||
t.Run("success case - backward compatibility", func(t *testing.T) {
|
||||
@@ -303,7 +315,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -313,11 +326,44 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "myImage:tag"}, runner.Calls[1].Params)
|
||||
assert.Equal(t, []string{"--dockerfile", "Dockerfile", "--context", cwd, "--skip-tls-verify-pull", "--destination", "myImage:tag"}, execRunner.Calls[1].Params)
|
||||
})
|
||||
t.Run("success case - createBOM", func(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
ContainerImage: "myImage:tag",
|
||||
ContainerPreparationCommand: "rm -f /kaniko/.docker/config.json",
|
||||
DockerfilePath: "Dockerfile",
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
CreateBOM: true,
|
||||
}
|
||||
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
responseBody: "testCert",
|
||||
}
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("install.sh", []byte(`echo syft`))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
|
||||
assert.Equal(t, "myImage:tag", commonPipelineEnvironment.container.imageNameTag)
|
||||
assert.Equal(t, "https://index.docker.io", commonPipelineEnvironment.container.registryURL)
|
||||
|
||||
//Syft install and call
|
||||
assert.Contains(t, shellRunner.Calls[0], "cat ./install.sh | sh -s -- -b .")
|
||||
assert.Contains(t, shellRunner.Calls[1], "./syft index.docker.io/myImage:tag -o cyclonedx-xml=bom-docker-0.xml")
|
||||
})
|
||||
|
||||
t.Run("success case - multi image build with root image", func(t *testing.T) {
|
||||
@@ -328,7 +374,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
ContainerMultiImageBuild: true,
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
fileUtils := &mock.FilesMock{}
|
||||
@@ -336,14 +383,14 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("sub1/Dockerfile", []byte("some content"))
|
||||
fileUtils.AddFile("sub2/Dockerfile", []byte("some content"))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, nil, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, nil, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 3, len(runner.Calls))
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[0].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[2].Exec)
|
||||
assert.Equal(t, 3, len(execRunner.Calls))
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[2].Exec)
|
||||
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
expectedParams := [][]string{
|
||||
@@ -352,7 +399,7 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
{"--dockerfile", filepath.Join("sub2", "Dockerfile"), "--context", cwd, "--destination", "my.registry.com:50000/myImage-sub2:myTag"},
|
||||
}
|
||||
// need to go this way since we cannot count on the correct order
|
||||
for _, call := range runner.Calls {
|
||||
for _, call := range execRunner.Calls {
|
||||
found := false
|
||||
for _, expected := range expectedParams {
|
||||
if strings.Join(call.Params, " ") == strings.Join(expected, " ") {
|
||||
@@ -385,7 +432,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
ContainerMultiImageBuildExcludes: []string{"Dockerfile"},
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
fileUtils := &mock.FilesMock{}
|
||||
@@ -393,13 +441,13 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("sub1/Dockerfile", []byte("some content"))
|
||||
fileUtils.AddFile("sub2/Dockerfile", []byte("some content"))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, nil, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, nil, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(runner.Calls))
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[0].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", runner.Calls[1].Exec)
|
||||
assert.Equal(t, 2, len(execRunner.Calls))
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
expectedParams := [][]string{
|
||||
@@ -407,7 +455,7 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
{"--dockerfile", filepath.Join("sub2", "Dockerfile"), "--context", cwd, "--destination", "my.registry.com:50000/myImage-sub2:myTag"},
|
||||
}
|
||||
// need to go this way since we cannot count on the correct order
|
||||
for _, call := range runner.Calls {
|
||||
for _, call := range execRunner.Calls {
|
||||
found := false
|
||||
for _, expected := range expectedParams {
|
||||
if strings.Join(call.Params, " ") == strings.Join(expected, " ") {
|
||||
@@ -426,6 +474,88 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNameTags, "myImage-sub2:myTag")
|
||||
})
|
||||
|
||||
t.Run("success case - multi image build with CreateBOM", func(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
ContainerImageName: "myImage",
|
||||
ContainerImageTag: "myTag",
|
||||
ContainerRegistryURL: "https://my.registry.com:50000",
|
||||
ContainerMultiImageBuild: true,
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
CreateBOM: true,
|
||||
}
|
||||
certClient := &kanikoMockClient{
|
||||
responseBody: "testCert",
|
||||
}
|
||||
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("Dockerfile", []byte("some content"))
|
||||
fileUtils.AddFile("sub1/Dockerfile", []byte("some content"))
|
||||
fileUtils.AddFile("sub2/Dockerfile", []byte("some content"))
|
||||
fileUtils.AddFile("install.sh", []byte(`echo syft`))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 3, len(execRunner.Calls))
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[1].Exec)
|
||||
assert.Equal(t, "/kaniko/executor", execRunner.Calls[2].Exec)
|
||||
|
||||
cwd, _ := fileUtils.Getwd()
|
||||
expectedParams := [][]string{
|
||||
{"--dockerfile", "Dockerfile", "--context", cwd, "--destination", "my.registry.com:50000/myImage:myTag"},
|
||||
{"--dockerfile", filepath.Join("sub1", "Dockerfile"), "--context", cwd, "--destination", "my.registry.com:50000/myImage-sub1:myTag"},
|
||||
{"--dockerfile", filepath.Join("sub2", "Dockerfile"), "--context", cwd, "--destination", "my.registry.com:50000/myImage-sub2:myTag"},
|
||||
}
|
||||
// need to go this way since we cannot count on the correct order
|
||||
for _, call := range execRunner.Calls {
|
||||
found := false
|
||||
for _, expected := range expectedParams {
|
||||
if strings.Join(call.Params, " ") == strings.Join(expected, " ") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, fmt.Sprintf("%v not found", call.Params))
|
||||
}
|
||||
|
||||
assert.Equal(t, "https://my.registry.com:50000", commonPipelineEnvironment.container.registryURL)
|
||||
assert.Equal(t, "myImage:myTag", commonPipelineEnvironment.container.imageNameTag)
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNames, "myImage")
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNames, "myImage-sub1")
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNames, "myImage-sub2")
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNameTags, "myImage:myTag")
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNameTags, "myImage-sub1:myTag")
|
||||
assert.Contains(t, commonPipelineEnvironment.container.imageNameTags, "myImage-sub2:myTag")
|
||||
|
||||
assert.Equal(t, "", commonPipelineEnvironment.container.imageDigest)
|
||||
assert.Empty(t, commonPipelineEnvironment.container.imageDigests)
|
||||
|
||||
//Syft install and call, can we do it better without 2 for loops
|
||||
expectedShellCalls := []string{
|
||||
"cat ./install.sh | sh -s -- -b .",
|
||||
"./syft my.registry.com:50000/myImage:myTag -o cyclonedx-xml=bom-docker-0.xml",
|
||||
"./syft my.registry.com:50000/myImage-sub1:myTag -o cyclonedx-xml=bom-docker-1.xml",
|
||||
"./syft my.registry.com:50000/myImage-sub2:myTag -o cyclonedx-xml=bom-docker-2.xml",
|
||||
}
|
||||
for _, call := range shellRunner.Calls {
|
||||
found := false
|
||||
for _, expected := range expectedShellCalls {
|
||||
if strings.Contains(call, expected) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
t.Run("success case - updating an existing docker config json with addtional credentials", func(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
BuildOptions: []string{"--skip-tls-verify-pull"},
|
||||
@@ -440,7 +570,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
ContainerRegistryPassword: "dummyPassword",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -450,12 +581,12 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths": {"dummyUrl": {"auth": "XXXXXXX"}}}`))
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "rm", runner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, runner.Calls[0].Params)
|
||||
assert.Equal(t, "rm", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, execRunner.Calls[0].Params)
|
||||
|
||||
assert.Equal(t, config.CustomTLSCertificateLinks, certClient.urlsCalled)
|
||||
c, err := fileUtils.FileRead("/kaniko/.docker/config.json")
|
||||
@@ -476,7 +607,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
ContainerRegistryPassword: "dummyPassword",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{
|
||||
@@ -485,12 +617,12 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("/kaniko/ssl/certs/ca-certificates.crt", []byte(``))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "rm", runner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, runner.Calls[0].Params)
|
||||
assert.Equal(t, "rm", execRunner.Calls[0].Exec)
|
||||
assert.Equal(t, []string{"-f", "/kaniko/.docker/config.json"}, execRunner.Calls[0].Params)
|
||||
|
||||
assert.Equal(t, config.CustomTLSCertificateLinks, certClient.urlsCalled)
|
||||
c, err := fileUtils.FileRead("/kaniko/.docker/config.json")
|
||||
@@ -507,11 +639,12 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
}
|
||||
|
||||
cpe := kanikoExecuteCommonPipelineEnvironment{}
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
|
||||
fileUtils := &mock.FilesMock{}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &cpe, runner, nil, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &cpe, execRunner, shellRunner, nil, fileUtils)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, fmt.Sprint(err), "failed to identify image list for multi image build")
|
||||
@@ -527,12 +660,13 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
}
|
||||
|
||||
cpe := kanikoExecuteCommonPipelineEnvironment{}
|
||||
runner := &mock.ExecMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("Dockerfile", []byte("some content"))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &cpe, runner, nil, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &cpe, execRunner, shellRunner, nil, fileUtils)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, fmt.Sprint(err), "no docker files to process, please check exclude list")
|
||||
@@ -547,13 +681,15 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
}
|
||||
|
||||
cpe := kanikoExecuteCommonPipelineEnvironment{}
|
||||
runner := &mock.ExecMockRunner{}
|
||||
runner.ShouldFailOnCommand = map[string]error{"/kaniko/executor": fmt.Errorf("execution failed")}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
|
||||
execRunner.ShouldFailOnCommand = map[string]error{"/kaniko/executor": fmt.Errorf("execution failed")}
|
||||
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("Dockerfile", []byte("some content"))
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &cpe, runner, nil, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &cpe, execRunner, shellRunner, nil, fileUtils)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, fmt.Sprint(err), "failed to build image")
|
||||
@@ -563,8 +699,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
ContainerPreparationCommand: "rm -f /kaniko/.docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{
|
||||
ShouldFailOnCommand: map[string]error{"rm": fmt.Errorf("rm failed")},
|
||||
}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
@@ -572,15 +708,15 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
certClient := &kanikoMockClient{}
|
||||
fileUtils := &mock.FilesMock{}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.EqualError(t, err, "failed to initialize Kaniko container: rm failed")
|
||||
})
|
||||
|
||||
t.Run("error case - Kaniko execution failed", func(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{}
|
||||
|
||||
runner := &mock.ExecMockRunner{
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{
|
||||
ShouldFailOnCommand: map[string]error{"/kaniko/executor": fmt.Errorf("kaniko run failed")},
|
||||
}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
@@ -588,7 +724,7 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
certClient := &kanikoMockClient{}
|
||||
fileUtils := &mock.FilesMock{}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.EqualError(t, err, "execution of '/kaniko/executor' failed: kaniko run failed")
|
||||
})
|
||||
@@ -604,15 +740,15 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
DockerfilePath: "Dockerfile",
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{}
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.FileReadErrors = map[string]error{"/kaniko/ssl/certs/ca-certificates.crt": fmt.Errorf("read error")}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.EqualError(t, err, "failed to update certificates: failed to load file '/kaniko/ssl/certs/ca-certificates.crt': read error")
|
||||
})
|
||||
@@ -621,15 +757,15 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{}
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.FileReadErrors = map[string]error{"path/to/docker/config.json": fmt.Errorf("read error")}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.EqualError(t, err, "failed to read existing docker config json at 'path/to/docker/config.json': read error")
|
||||
})
|
||||
@@ -638,8 +774,8 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
}
|
||||
|
||||
runner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
|
||||
certClient := &kanikoMockClient{}
|
||||
@@ -647,9 +783,48 @@ func TestRunKanikoExecute(t *testing.T) {
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.FileWriteErrors = map[string]error{"/kaniko/.docker/config.json": fmt.Errorf("write error")}
|
||||
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
|
||||
assert.EqualError(t, err, "failed to write file '/kaniko/.docker/config.json': write error")
|
||||
})
|
||||
|
||||
t.Run("error cases - createBOM", func(t *testing.T) {
|
||||
config := &kanikoExecuteOptions{
|
||||
ContainerImage: "myImage:tag",
|
||||
DockerfilePath: "Dockerfile",
|
||||
DockerConfigJSON: "path/to/docker/config.json",
|
||||
ContainerPreparationCommand: "rm -f /kaniko/.docker/config.json",
|
||||
CreateBOM: true,
|
||||
}
|
||||
|
||||
execRunner := &mock.ExecMockRunner{}
|
||||
shellRunner := &mock.ShellMockRunner{}
|
||||
commonPipelineEnvironment := kanikoExecuteCommonPipelineEnvironment{}
|
||||
certClient := &kanikoMockClient{
|
||||
responseBody: "testCert",
|
||||
}
|
||||
fileUtils := &mock.FilesMock{}
|
||||
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
|
||||
fileUtils.AddFile("install.sh", []byte(`echo syft`))
|
||||
|
||||
// Case 1 - Download of syft installation file failed
|
||||
certClient.errorMessage = "Download failed"
|
||||
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient, fileUtils)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, fmt.Sprint(err), certClient.errorMessage)
|
||||
|
||||
// Case 2 - Installation of syft failed, using new kanikoMockClient here
|
||||
certClient1 := &kanikoMockClient{}
|
||||
shellRunner.ShouldFailOnCommand = map[string]error{"cat ./install.sh | sh -s -- -b .": fmt.Errorf("install failed")}
|
||||
err = runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner, certClient1, fileUtils)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, fmt.Sprint(err), "failed to install syft")
|
||||
|
||||
// Case 3 syft run failed, using new ShellMockRunner here
|
||||
shellRunner1 := &mock.ShellMockRunner{}
|
||||
shellRunner1.ShouldFailOnCommand = map[string]error{"./syft index.docker.io/myImage:tag -o cyclonedx-xml=bom-docker-0.xml": fmt.Errorf("run failed")}
|
||||
err = runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, execRunner, shellRunner1, certClient1, fileUtils)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, fmt.Sprint(err), "failed to generate SBOM")
|
||||
})
|
||||
}
|
||||
|
@@ -257,6 +257,14 @@ spec:
|
||||
- STEPS
|
||||
- STAGES
|
||||
- PARAMETERS
|
||||
- name: createBOM
|
||||
type: bool
|
||||
description: Creates the bill of materials (BOM) using Syft and stored in a file of CycloneDX 1.4 format.
|
||||
scope:
|
||||
- GENERAL
|
||||
- STEPS
|
||||
- STAGES
|
||||
- PARAMETERS
|
||||
outputs:
|
||||
resources:
|
||||
- name: commonPipelineEnvironment
|
||||
|
Reference in New Issue
Block a user