1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-18 05:18:24 +02:00

feat(kaniko): pass image digests to cpe (#3542)

* feat(kaniko): expose image digests to cpe

* fix
This commit is contained in:
Christian Volk 2022-02-17 10:06:54 +01:00 committed by GitHub
parent a1cd6cdb3a
commit 2af9d3aae5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 14 deletions

View File

@ -134,7 +134,7 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus
containerImageNameAndTag := fmt.Sprintf("%v:%v", image, containerImageTag)
dest = []string{"--destination", fmt.Sprintf("%v/%v", containerRegistry, containerImageNameAndTag)}
buildOpts := append(config.BuildOptions, dest...)
err = runKaniko(file, buildOpts, execRunner, fileUtils)
err = runKaniko(file, buildOpts, execRunner, fileUtils, commonPipelineEnvironment)
if err != nil {
return fmt.Errorf("failed to build image '%v' using '%v': %w", image, file, err)
}
@ -206,15 +206,23 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus
}
// no support for building multiple containers
return runKaniko(config.DockerfilePath, config.BuildOptions, execRunner, fileUtils)
return runKaniko(config.DockerfilePath, config.BuildOptions, execRunner, fileUtils, commonPipelineEnvironment)
}
func runKaniko(dockerFilepath string, buildOptions []string, execRunner command.ExecRunner, fileUtils piperutils.FileUtils) error {
func runKaniko(dockerFilepath string, buildOptions []string, execRunner command.ExecRunner, fileUtils piperutils.FileUtils, commonPipelineEnvironment *kanikoExecuteCommonPipelineEnvironment) error {
cwd, err := fileUtils.Getwd()
if err != nil {
return fmt.Errorf("failed to get current working directory: %w", err)
}
kanikoOpts := []string{"--dockerfile", dockerFilepath, "--context", cwd}
tmpDir, err := fileUtils.TempDir("", "*-kanikoExecute")
if err != nil {
return fmt.Errorf("failed to create tmp dir for kanikoExecute: %w", err)
}
digestFilePath := fmt.Sprintf("%s/digest.txt", tmpDir)
kanikoOpts := []string{"--dockerfile", dockerFilepath, "--context", cwd, "--digest-file", digestFilePath}
kanikoOpts = append(kanikoOpts, buildOptions...)
err = execRunner.RunExecutable("/kaniko/executor", kanikoOpts...)
@ -222,5 +230,23 @@ func runKaniko(dockerFilepath string, buildOptions []string, execRunner command.
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrap(err, "execution of '/kaniko/executor' failed")
}
if b, err := fileUtils.FileExists(digestFilePath); err == nil && b {
digest, err := fileUtils.FileRead(digestFilePath)
if err != nil {
return errors.Wrap(err, "error while reading image digest")
}
digestStr := string(digest)
log.Entry().Debugf("image digest: %s", digestStr)
commonPipelineEnvironment.container.imageDigest = string(digestStr)
commonPipelineEnvironment.container.imageDigests = append(commonPipelineEnvironment.container.imageDigests, digestStr)
} else {
log.Entry().Warn("couldn't resolve image digest")
}
return nil
}

View File

@ -38,8 +38,10 @@ type kanikoExecuteCommonPipelineEnvironment struct {
container struct {
registryURL string
imageNameTag string
imageDigest string
imageNames []string
imageNameTags []string
imageDigests []string
}
custom struct {
buildSettingsInfo string
@ -54,8 +56,10 @@ func (p *kanikoExecuteCommonPipelineEnvironment) persist(path, resourceName stri
}{
{category: "container", name: "registryUrl", value: p.container.registryURL},
{category: "container", name: "imageNameTag", value: p.container.imageNameTag},
{category: "container", name: "imageDigest", value: p.container.imageDigest},
{category: "container", name: "imageNames", value: p.container.imageNames},
{category: "container", name: "imageNameTags", value: p.container.imageNameTags},
{category: "container", name: "imageDigests", value: p.container.imageDigests},
{category: "custom", name: "buildSettingsInfo", value: p.custom.buildSettingsInfo},
}
@ -379,8 +383,10 @@ func kanikoExecuteMetadata() config.StepData {
Parameters: []map[string]interface{}{
{"name": "container/registryUrl"},
{"name": "container/imageNameTag"},
{"name": "container/imageDigest"},
{"name": "container/imageNames", "type": "[]string"},
{"name": "container/imageNameTags", "type": "[]string"},
{"name": "container/imageDigests", "type": "[]string"},
{"name": "custom/buildSettingsInfo"},
},
},

View File

@ -68,6 +68,7 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils := &mock.FilesMock{}
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
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)
@ -83,7 +84,7 @@ func TestRunKanikoExecute(t *testing.T) {
assert.Equal(t, "/kaniko/executor", runner.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, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--skip-tls-verify-pull", "--destination", "myImage:tag"}, runner.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"}]`)
@ -92,6 +93,9 @@ func TestRunKanikoExecute(t *testing.T) {
assert.Equal(t, "https://index.docker.io", commonPipelineEnvironment.container.registryURL)
assert.Equal(t, []string{"myImage"}, commonPipelineEnvironment.container.imageNames)
assert.Equal(t, []string{"myImage:tag"}, commonPipelineEnvironment.container.imageNameTags)
assert.Equal(t, "sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0", commonPipelineEnvironment.container.imageDigest)
assert.Equal(t, []string{"sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0"}, commonPipelineEnvironment.container.imageDigests)
})
t.Run("success case - image params", func(t *testing.T) {
@ -115,6 +119,7 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils := &mock.FilesMock{}
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
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)
@ -130,12 +135,15 @@ func TestRunKanikoExecute(t *testing.T) {
assert.Equal(t, "/kaniko/executor", runner.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, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--skip-tls-verify-pull", "--destination", "my.registry.com:50000/myImage:1.2.3-a-x"}, runner.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)
assert.Equal(t, []string{"myImage"}, commonPipelineEnvironment.container.imageNames)
assert.Equal(t, []string{"myImage:1.2.3-a-x"}, commonPipelineEnvironment.container.imageNameTags)
assert.Equal(t, "sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0", commonPipelineEnvironment.container.imageDigest)
assert.Equal(t, []string{"sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0"}, commonPipelineEnvironment.container.imageDigests)
})
t.Run("success case - image params with custom destination", func(t *testing.T) {
@ -156,6 +164,7 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils := &mock.FilesMock{}
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
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)
@ -171,12 +180,15 @@ func TestRunKanikoExecute(t *testing.T) {
assert.Equal(t, "/kaniko/executor", runner.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, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--skip-tls-verify-pull", "--destination", "my.other.registry.com:50000/myImage:3.2.1-a-x"}, runner.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)
assert.Equal(t, []string{"myImage"}, commonPipelineEnvironment.container.imageNames)
assert.Equal(t, []string{"myImage:3.2.1-a-x"}, commonPipelineEnvironment.container.imageNameTags)
assert.Equal(t, "sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0", commonPipelineEnvironment.container.imageDigest)
assert.Equal(t, []string{"sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0"}, commonPipelineEnvironment.container.imageDigests)
})
t.Run("no error case - when cert update skipped", func(t *testing.T) {
@ -198,6 +210,7 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils := &mock.FilesMock{}
fileUtils.AddFile("path/to/docker/config.json", []byte(``))
fileUtils.FileReadErrors = map[string]error{"/kaniko/ssl/certs/ca-certificates.crt": fmt.Errorf("read error")}
fileUtils.AddFile("/tmp/*-kanikoExecutetest/digest.txt", []byte(`sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0`))
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, certClient, fileUtils)
@ -220,6 +233,7 @@ func TestRunKanikoExecute(t *testing.T) {
}
fileUtils := &mock.FilesMock{}
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)
@ -230,7 +244,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, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--skip-tls-verify-pull", "--no-push"}, runner.Calls[1].Params)
})
t.Run("success case - backward compatibility", func(t *testing.T) {
@ -252,12 +266,13 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils := &mock.FilesMock{}
fileUtils.AddFile("path/to/docker/config.json", []byte(`{"auths":{"custom":"test"}}`))
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)
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, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--skip-tls-verify-pull", "--destination", "myImage:tag"}, runner.Calls[1].Params)
})
t.Run("success case - multi image build with root image", func(t *testing.T) {
@ -275,6 +290,7 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils.AddFile("Dockerfile", []byte("some content"))
fileUtils.AddFile("sub1/Dockerfile", []byte("some content"))
fileUtils.AddFile("sub2/Dockerfile", []byte("some content"))
fileUtils.AddFile("/tmp/*-kanikoExecutetest/digest.txt", []byte(`sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0`))
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, nil, fileUtils)
@ -287,9 +303,9 @@ func TestRunKanikoExecute(t *testing.T) {
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"},
{"--dockerfile", "Dockerfile", "--context", cwd, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--destination", "my.registry.com:50000/myImage:myTag"},
{"--dockerfile", filepath.Join("sub1", "Dockerfile"), "--context", cwd, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--destination", "my.registry.com:50000/myImage-sub1:myTag"},
{"--dockerfile", filepath.Join("sub2", "Dockerfile"), "--context", cwd, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--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 {
@ -311,6 +327,9 @@ func TestRunKanikoExecute(t *testing.T) {
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, "sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0")
assert.Equal(t, commonPipelineEnvironment.container.imageDigests, []string{"sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0", "sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0", "sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0"})
})
t.Run("success case - multi image build excluding root image", func(t *testing.T) {
@ -329,6 +348,7 @@ func TestRunKanikoExecute(t *testing.T) {
fileUtils.AddFile("Dockerfile", []byte("some content"))
fileUtils.AddFile("sub1/Dockerfile", []byte("some content"))
fileUtils.AddFile("sub2/Dockerfile", []byte("some content"))
fileUtils.AddFile("/tmp/*-kanikoExecutetest/digest.txt", []byte(`sha256:468dd1253cc9f498fc600454bb8af96d880fec3f9f737e7057692adfe9f7d5b0`))
err := runKanikoExecute(config, &telemetry.CustomData{}, &commonPipelineEnvironment, runner, nil, fileUtils)
@ -340,8 +360,8 @@ func TestRunKanikoExecute(t *testing.T) {
cwd, _ := fileUtils.Getwd()
expectedParams := [][]string{
{"--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"},
{"--dockerfile", filepath.Join("sub1", "Dockerfile"), "--context", cwd, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--destination", "my.registry.com:50000/myImage-sub1:myTag"},
{"--dockerfile", filepath.Join("sub2", "Dockerfile"), "--context", cwd, "--digest-file", "/tmp/*-kanikoExecutetest/digest.txt", "--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 {

View File

@ -174,10 +174,13 @@ spec:
params:
- name: container/registryUrl
- name: container/imageNameTag
- name: container/imageDigest
- name: container/imageNames
type: "[]string"
- name: container/imageNameTags
type: "[]string"
- name: container/imageDigests
type: "[]string"
- name: custom/buildSettingsInfo
containers:
- image: gcr.io/kaniko-project/executor:debug