1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-11-06 09:09:19 +02:00

feat(cnbBuild): remove docker config after parsing (#3417)

Co-authored-by: Philipp Stehle <philipp.stehle@sap.com>
This commit is contained in:
Pavel Busko
2022-01-11 10:01:15 +01:00
committed by GitHub
parent f196f3a5a0
commit 547ef5b55d
12 changed files with 142 additions and 84 deletions

View File

@@ -2,7 +2,6 @@ package cmd
import (
"archive/zip"
"encoding/json"
"fmt"
"os"
"path"
@@ -21,7 +20,6 @@ import (
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/docker/cli/cli/config/configfile"
"github.com/pkg/errors"
ignore "github.com/sabhiram/go-gitignore"
)
@@ -295,36 +293,12 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
}
dockerConfigFile := ""
dockerConfig := &configfile.ConfigFile{}
dockerConfigJSON := []byte(`{"auths":{}}`)
if len(config.DockerConfigJSON) > 0 {
dockerConfigFile, err = prepareDockerConfig(config.DockerConfigJSON, utils)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "failed to rename DockerConfigJSON file '%v'", config.DockerConfigJSON)
}
dockerConfigJSON, err = utils.FileRead(dockerConfigFile)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "failed to read DockerConfigJSON file '%v'", config.DockerConfigJSON)
}
}
err = json.Unmarshal(dockerConfigJSON, dockerConfig)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "failed to parse DockerConfigJSON file '%v'", config.DockerConfigJSON)
}
auth := map[string]string{}
for registry, value := range dockerConfig.AuthConfigs {
auth[registry] = fmt.Sprintf("Basic %s", value.Auth)
}
cnbRegistryAuth, err := json.Marshal(auth)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrap(err, "failed to marshal DockerConfigJSON")
}
target := "/workspace"
@@ -374,6 +348,20 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
}
}
cnbRegistryAuth, err := cnbutils.GenerateCnbAuth(dockerConfigFile, utils)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrap(err, "failed to generate CNB_REGISTRY_AUTH")
}
if dockerConfigFile != "" {
err = utils.FileRemove(dockerConfigFile)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrap(err, "failed to remove docker config.json file")
}
}
if len(config.ContainerRegistryURL) == 0 || len(config.ContainerImageName) == 0 || len(config.ContainerImageTag) == 0 {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.New("containerRegistryUrl, containerImageName and containerImageTag must be present")
@@ -411,7 +399,7 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
log.Entry().Info("skipping certificates update")
}
utils.AppendEnv([]string{fmt.Sprintf("CNB_REGISTRY_AUTH=%s", string(cnbRegistryAuth))})
utils.AppendEnv([]string{fmt.Sprintf("CNB_REGISTRY_AUTH=%s", cnbRegistryAuth)})
utils.AppendEnv([]string{"CNB_PLATFORM_API=0.8"})
creatorArgs := []string{

View File

@@ -17,7 +17,6 @@ func newCnbBuildTestsUtils() cnbutils.MockUtils {
utils := cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
DockerMock: &cnbutils.DockerMock{},
}
return utils
}
@@ -118,6 +117,12 @@ func TestRunCnbBuild(t *testing.T) {
assert.Contains(t, runner.Calls[0].Params, "/tmp/buildpacks/order.toml")
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:%s", registry, config.ContainerImageName, config.ContainerImageTag))
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:latest", registry, config.ContainerImageName))
initialFileExists, _ := utils.FileExists("/path/to/test.json")
renamedFileExists, _ := utils.FileExists("/path/to/config.json")
assert.False(t, initialFileExists)
assert.False(t, renamedFileExists)
})
t.Run("success case (customTlsCertificates)", func(t *testing.T) {
@@ -200,7 +205,7 @@ func TestRunCnbBuild(t *testing.T) {
addBuilderFiles(&utils)
err := runCnbBuild(&config, nil, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
assert.EqualError(t, err, "failed to parse DockerConfigJSON file '/path/to/config.json': json: cannot unmarshal string into Go struct field ConfigFile.auths of type types.AuthConfig")
assert.EqualError(t, err, "failed to generate CNB_REGISTRY_AUTH: json: cannot unmarshal string into Go struct field ConfigFile.auths of type types.AuthConfig")
})
t.Run("error case: DockerConfigJSON file not there (config.json)", func(t *testing.T) {
@@ -215,7 +220,7 @@ func TestRunCnbBuild(t *testing.T) {
addBuilderFiles(&utils)
err := runCnbBuild(&config, nil, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
assert.EqualError(t, err, "failed to read DockerConfigJSON file 'not-there/config.json': could not read 'not-there/config.json'")
assert.EqualError(t, err, "failed to generate CNB_REGISTRY_AUTH: could not read 'not-there/config.json'")
})
t.Run("error case: DockerConfigJSON file not there (not config.json)", func(t *testing.T) {

37
pkg/cnbutils/auth.go Normal file
View File

@@ -0,0 +1,37 @@
package cnbutils
import (
"encoding/json"
"fmt"
"github.com/docker/cli/cli/config/configfile"
)
func GenerateCnbAuth(config string, utils BuildUtils) (string, error) {
var err error
dockerConfig := &configfile.ConfigFile{}
if config != "" {
dockerConfigJSON, err := utils.FileRead(config)
if err != nil {
return "", err
}
err = json.Unmarshal(dockerConfigJSON, dockerConfig)
if err != nil {
return "", err
}
}
auth := map[string]string{}
for registry, value := range dockerConfig.AuthConfigs {
auth[registry] = fmt.Sprintf("Basic %s", value.Auth)
}
cnbRegistryAuth, err := json.Marshal(auth)
if err != nil {
return "", err
}
return string(cnbRegistryAuth), nil
}

42
pkg/cnbutils/auth_test.go Normal file
View File

@@ -0,0 +1,42 @@
package cnbutils_test
import (
"testing"
"github.com/SAP/jenkins-library/pkg/cnbutils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
)
func TestGenerateCnbAuth(t *testing.T) {
var mockUtils = &cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
}
t.Run("successfully generates cnb auth env variable", func(t *testing.T) {
mockUtils.AddFile("/test/valid_config.json", []byte("{\"auths\":{\"example.com\":{\"username\":\"username\",\"password\":\"password\",\"auth\":\"dXNlcm5hbWU6cGFzc3dvcmQ=\"}}}"))
auth, err := cnbutils.GenerateCnbAuth("/test/valid_config.json", mockUtils)
assert.NoError(t, err)
assert.Equal(t, "{\"example.com\":\"Basic dXNlcm5hbWU6cGFzc3dvcmQ=\"}", auth)
})
t.Run("successfully generates cnb auth env variable if docker config is not present", func(t *testing.T) {
auth, err := cnbutils.GenerateCnbAuth("", mockUtils)
assert.NoError(t, err)
assert.Equal(t, "{}", auth)
})
t.Run("fails if file not found", func(t *testing.T) {
_, err := cnbutils.GenerateCnbAuth("/not/found", mockUtils)
assert.Error(t, err)
assert.Equal(t, "could not read '/not/found'", err.Error())
})
t.Run("fails if file is invalid json", func(t *testing.T) {
mockUtils.AddFile("/test/invalid_config.json", []byte("not a json"))
_, err := cnbutils.GenerateCnbAuth("/test/invalid_config.json", mockUtils)
assert.Error(t, err)
assert.Equal(t, "invalid character 'o' in literal null (expecting 'u')", err.Error())
})
}

View File

@@ -13,8 +13,8 @@ import (
)
func TestProcessBindings(t *testing.T) {
var mockUtils = func() cnbutils.MockUtils {
var utils = cnbutils.MockUtils{
var mockUtils = func() *cnbutils.MockUtils {
var utils = &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
utils.AddFile("/tmp/somefile.yaml", []byte("some file content"))

View File

@@ -1,35 +1,24 @@
package cnbutils
package cnbutils_test
import (
"testing"
"github.com/SAP/jenkins-library/pkg/cnbutils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
)
var mockUtils = MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
DockerMock: &DockerMock{},
}
func TestBuildpackDownload(t *testing.T) {
var mockUtils = &cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
}
t.Run("successfully downloads a buildpack", func(t *testing.T) {
mockUtils.AddDir("/tmp/testtest")
_, err := DownloadBuildpacks("/test", []string{"test"}, "/test/config.json", mockUtils)
_, err := cnbutils.DownloadBuildpacks("/test", []string{"test"}, "/test/config.json", mockUtils)
assert.NoError(t, err)
assert.True(t, mockUtils.HasRemovedFile("/tmp/testtest"))
})
}
func TestBuildpackCopy(t *testing.T) {
t.Run("successfully downloads a buildpack", func(t *testing.T) {
mockUtils.AddDir("/src/buildpack/0.0.1")
mockUtils.AddDir("/dst")
err := copyBuildPack("/src", "/dst", mockUtils)
assert.NoError(t, err)
})
}

View File

@@ -1,16 +1,17 @@
package cnbutils
package cnbutils_test
import (
"fmt"
"testing"
"github.com/SAP/jenkins-library/pkg/cnbutils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
)
func TestCreateEnvFiles(t *testing.T) {
t.Run("successfully writes environment files", func(t *testing.T) {
mockUtils := MockUtils{
mockUtils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
@@ -20,7 +21,7 @@ func TestCreateEnvFiles(t *testing.T) {
"COMPLEX": "{\"foo\": \"bar=3\"}",
}
err := CreateEnvFiles(mockUtils, "/tmp/platform", envVars)
err := cnbutils.CreateEnvFiles(mockUtils, "/tmp/platform", envVars)
assert.NoError(t, err)
assert.True(t, mockUtils.HasWrittenFile("/tmp/platform/env/FOO"))
@@ -41,7 +42,7 @@ func TestCreateEnvFiles(t *testing.T) {
})
t.Run("raises an error if unable to write to a file", func(t *testing.T) {
mockUtils := MockUtils{
mockUtils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{
FileWriteErrors: map[string]error{
"/tmp/platform/env/FOO": fmt.Errorf("unable to create dir"),
@@ -49,7 +50,7 @@ func TestCreateEnvFiles(t *testing.T) {
},
}
err := CreateEnvFiles(mockUtils, "/tmp/platform", map[string]interface{}{"FOO": "BAR"})
err := cnbutils.CreateEnvFiles(mockUtils, "/tmp/platform", map[string]interface{}{"FOO": "BAR"})
assert.Error(t, err)
assert.Equal(t, err.Error(), "unable to create dir")
})

View File

@@ -1,12 +1,13 @@
//go:build !release
// +build !release
package cnbutils
import (
"io"
"path/filepath"
pkgutil "github.com/GoogleContainerTools/container-diff/pkg/util"
"github.com/SAP/jenkins-library/pkg/docker"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/SAP/jenkins-library/pkg/piperutils"
v1 "github.com/google/go-containerregistry/pkg/v1"
@@ -16,21 +17,13 @@ import (
type MockUtils struct {
*mock.ExecMockRunner
*mock.FilesMock
*DockerMock
}
func (c *MockUtils) GetDockerClient() docker.Download {
return c.DockerMock
}
func (c *MockUtils) GetFileUtils() piperutils.FileUtils {
return c.FilesMock
}
type DockerMock struct{}
func (d *DockerMock) DownloadImageToPath(_, filePath string) (pkgutil.Image, error) {
func (c *MockUtils) DownloadImageToPath(bpack, filePath string) (pkgutil.Image, error) {
fakeImage := fakeImage.FakeImage{}
fakeImage.ConfigFileReturns(&v1.ConfigFile{
Config: v1.Config{
@@ -39,16 +32,19 @@ func (d *DockerMock) DownloadImageToPath(_, filePath string) (pkgutil.Image, err
},
},
}, nil)
c.AddDir(filepath.Join(filePath, "cnb/buildpacks", bpack))
c.AddDir(filepath.Join(filePath, "cnb/buildpacks", bpack, "0.0.1"))
img := pkgutil.Image{
Image: &fakeImage,
}
return img, nil
}
func (d *DockerMock) GetImageSource() (string, error) {
func (c *MockUtils) GetImageSource() (string, error) {
return "imageSource", nil
}
func (d *DockerMock) TarImage(writer io.Writer, image pkgutil.Image) error {
func (c *MockUtils) TarImage(writer io.Writer, image pkgutil.Image) error {
return nil
}

View File

@@ -1,22 +1,22 @@
package cnbutils
package cnbutils_test
import (
"fmt"
"testing"
"github.com/SAP/jenkins-library/pkg/cnbutils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
)
func TestOrderSave(t *testing.T) {
t.Run("successfully Encode struct to toml format (multiple buildpacks)", func(t *testing.T) {
mockUtils := MockUtils{
mockUtils := &cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
DockerMock: &DockerMock{},
}
testBuildpacks := []BuildPackMetadata{
testBuildpacks := []cnbutils.BuildPackMetadata{
{
ID: "paketo-buildpacks/sap-machine",
Version: "1.1.1",
@@ -26,13 +26,13 @@ func TestOrderSave(t *testing.T) {
Version: "2.2.2",
},
}
testOrder := Order{
testOrder := cnbutils.Order{
Utils: mockUtils,
}
var testEntry OrderEntry
var testEntry cnbutils.OrderEntry
testEntry.Group = append(testEntry.Group, testBuildpacks...)
testOrder.Order = []OrderEntry{testEntry}
testOrder.Order = []cnbutils.OrderEntry{testEntry}
err := testOrder.Save("/tmp/order.toml")
@@ -44,15 +44,14 @@ func TestOrderSave(t *testing.T) {
})
t.Run("raises an error if unable to write the file", func(t *testing.T) {
mockUtils := MockUtils{
mockUtils := &cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
DockerMock: &DockerMock{},
}
mockUtils.FileWriteErrors = map[string]error{
"/tmp/order.toml": fmt.Errorf("unable to write to file"),
}
testOrder := Order{
testOrder := cnbutils.Order{
Utils: mockUtils,
}

View File

@@ -41,7 +41,7 @@ version = "5.9.1"
[[build.buildpacks]]
id = "paketo-buildpacks/nodejs"
`
utils := cnbutils.MockUtils{
utils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
@@ -92,7 +92,7 @@ id = "test/inline"
shell = "/bin/bash"
inline = "date"
`
utils := cnbutils.MockUtils{
utils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
@@ -119,7 +119,7 @@ exclude = [
]
`
utils := cnbutils.MockUtils{
utils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
utils.AddFile("project.toml", []byte(projectToml))
@@ -131,7 +131,7 @@ exclude = [
})
t.Run("fails with file not found", func(t *testing.T) {
utils := cnbutils.MockUtils{
utils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
@@ -143,7 +143,7 @@ exclude = [
t.Run("fails to parse corrupted project.toml", func(t *testing.T) {
projectToml := "test123"
utils := cnbutils.MockUtils{
utils := &cnbutils.MockUtils{
FilesMock: &mock.FilesMock{},
}
utils.AddFile("project.toml", []byte(projectToml))

View File

@@ -24,7 +24,7 @@ func TestWriteProjectMetadata(t *testing.T) {
commit = "012548"
describe = "test-commit"
`
mockUtils := cnbutils.MockUtils{
mockUtils := &cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
}

View File

@@ -23,6 +23,7 @@ type FileUtils interface {
Copy(src, dest string) (int64, error)
FileRead(path string) ([]byte, error)
FileWrite(path string, content []byte, perm os.FileMode) error
FileRemove(path string) error
MkdirAll(path string, perm os.FileMode) error
Chmod(path string, mode os.FileMode) error
Glob(pattern string) (matches []string, err error)