mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
797 lines
32 KiB
Go
797 lines
32 KiB
Go
//go:build unit
|
|
// +build unit
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/SAP/jenkins-library/pkg/buildpacks"
|
|
"github.com/SAP/jenkins-library/pkg/cnbutils"
|
|
piperconf "github.com/SAP/jenkins-library/pkg/config"
|
|
piperhttp "github.com/SAP/jenkins-library/pkg/http"
|
|
"github.com/SAP/jenkins-library/pkg/mock"
|
|
"github.com/SAP/jenkins-library/pkg/telemetry"
|
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
|
"github.com/google/go-containerregistry/pkg/v1/fake"
|
|
"github.com/jarcoal/httpmock"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const imageRegistry = "some-registry"
|
|
|
|
func newCnbBuildTestsUtils() cnbutils.MockUtils {
|
|
imageStub := func(imageRef, target string) (v1.Image, error) {
|
|
fakeImage := &fake.FakeImage{}
|
|
var imageConfig v1.Config
|
|
switch imageRef {
|
|
case "pre-test":
|
|
imageConfig = v1.Config{
|
|
Labels: map[string]string{
|
|
"io.buildpacks.buildpackage.metadata": "{\"id\": \"pre-testbuildpack\", \"version\": \"0.0.1\"}",
|
|
},
|
|
}
|
|
case "post-test":
|
|
imageConfig = v1.Config{
|
|
Labels: map[string]string{
|
|
"io.buildpacks.buildpackage.metadata": "{\"id\": \"post-testbuildpack\", \"version\": \"0.0.1\"}",
|
|
},
|
|
}
|
|
default:
|
|
imageConfig = v1.Config{
|
|
Labels: map[string]string{
|
|
"io.buildpacks.buildpackage.metadata": "{\"id\": \"testbuildpack\", \"version\": \"0.0.1\"}",
|
|
},
|
|
}
|
|
}
|
|
|
|
fakeImage.ConfigFileReturns(&v1.ConfigFile{
|
|
Config: imageConfig,
|
|
}, nil)
|
|
|
|
return fakeImage, nil
|
|
}
|
|
|
|
utils := cnbutils.MockUtils{
|
|
ExecMockRunner: &mock.ExecMockRunner{},
|
|
FilesMock: &mock.FilesMock{},
|
|
DownloadMock: &mock.DownloadMock{
|
|
ImageContentStub: imageStub,
|
|
ImageInfoStub: func(imageRef string) (v1.Image, error) {
|
|
return imageStub(imageRef, "")
|
|
},
|
|
},
|
|
}
|
|
|
|
utils.AddFile("/cnb/order.toml", []byte(`[[order]]
|
|
[[order.group]]
|
|
id = "buildpacks/java"
|
|
version = "1.8.0"
|
|
[[order]]
|
|
[[order.group]]
|
|
id = "buildpacks/nodejs"
|
|
version = "1.6.0"`))
|
|
utils.AddFile("/layers/report.toml", []byte(`[build]
|
|
[image]
|
|
tags = ["localhost:5000/not-found:0.0.1"]
|
|
digest = "sha256:52eac630560210e5ae13eb10797c4246d6f02d425f32b9430ca00bde697c79ec"
|
|
manifest-size = 2388`))
|
|
return utils
|
|
}
|
|
|
|
func addBuilderFiles(utils *cnbutils.MockUtils) {
|
|
utils.FilesMock.AddFile(creatorPath, []byte(`xyz`))
|
|
}
|
|
|
|
func assertLifecycleCalls(t *testing.T, runner *mock.ExecMockRunner, callNo int) {
|
|
require.GreaterOrEqual(t, len(runner.Calls), callNo)
|
|
assert.Equal(t, creatorPath, runner.Calls[callNo-1].Exec)
|
|
for _, arg := range []string{"-no-color", "-buildpacks", "/cnb/buildpacks", "-order", "/cnb/order.toml", "-platform", "/tmp/platform"} {
|
|
assert.Contains(t, runner.Calls[callNo-1].Params, arg)
|
|
}
|
|
}
|
|
|
|
func assetBuildEnv(t *testing.T, utils cnbutils.MockUtils, key, value string) bool {
|
|
env, err := utils.FilesMock.ReadFile(filepath.Join("/tmp/platform/env/", key))
|
|
if !assert.NoError(t, err) {
|
|
return false
|
|
}
|
|
return assert.Equal(t, value, string(env))
|
|
}
|
|
|
|
func TestRunCnbBuild(t *testing.T) {
|
|
configOptions.OpenFile = piperconf.OpenPiperFile
|
|
|
|
t.Setenv("CNB_USER_ID", "1000")
|
|
t.Setenv("CNB_GROUP_ID", "1000")
|
|
|
|
t.Run("prefers direct configuration", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry),
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
RunImage: "my-run-image",
|
|
DefaultProcess: "my-process",
|
|
}
|
|
|
|
projectToml := `[project]
|
|
id = "io.buildpacks.my-app"
|
|
`
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
utils.FilesMock.AddFile("project.toml", []byte(projectToml))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assertLifecycleCalls(t, runner, 2)
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Contains(t, runner.Calls[1].Params, "-run-image")
|
|
assert.Contains(t, runner.Calls[1].Params, "my-run-image")
|
|
assert.Contains(t, runner.Calls[1].Params, "-process-type")
|
|
assert.Contains(t, runner.Calls[1].Params, "my-process")
|
|
assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL)
|
|
assert.Equal(t, "my-image:0.0.1", commonPipelineEnvironment.container.imageNameTag)
|
|
assert.Equal(t, `{"cnbBuild":[{"dockerImage":"paketobuildpacks/builder-jammy-base:latest"}]}`, commonPipelineEnvironment.custom.buildSettingsInfo)
|
|
})
|
|
|
|
t.Run("prefers project descriptor", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry),
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
ProjectDescriptor: "project.toml",
|
|
}
|
|
|
|
projectToml := `[project]
|
|
id = "io.buildpacks.my-app"
|
|
`
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
utils.FilesMock.AddFile("project.toml", []byte(projectToml))
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := &telemetry.CustomData{}
|
|
err := callCnbBuild(&config, telemetryData, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assertLifecycleCalls(t, runner, 2)
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, "io-buildpacks-my-app", config.ContainerImageTag))
|
|
assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL)
|
|
assert.Equal(t, "io-buildpacks-my-app:0.0.1", commonPipelineEnvironment.container.imageNameTag)
|
|
|
|
assert.Equal(t, "sha256:52eac630560210e5ae13eb10797c4246d6f02d425f32b9430ca00bde697c79ec", commonPipelineEnvironment.container.imageDigest)
|
|
assert.Contains(t, commonPipelineEnvironment.container.imageDigests, "sha256:52eac630560210e5ae13eb10797c4246d6f02d425f32b9430ca00bde697c79ec")
|
|
|
|
customDataAsString := telemetryData.Custom1
|
|
customData := &buildpacks.BuildpacksTelemetry{}
|
|
err = json.Unmarshal([]byte(customDataAsString), customData)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 1, len(customData.Data))
|
|
assert.Equal(t, "root", string(customData.Data[0].Path))
|
|
})
|
|
|
|
t.Run("success case (registry with https)", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry),
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assertLifecycleCalls(t, runner, 2)
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL)
|
|
assert.Equal(t, "my-image:0.0.1", commonPipelineEnvironment.container.imageNameTag)
|
|
})
|
|
|
|
t.Run("success case (registry without https)", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assertLifecycleCalls(t, runner, 2)
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Equal(t, fmt.Sprintf("https://%s", config.ContainerRegistryURL), commonPipelineEnvironment.container.registryURL)
|
|
assert.Equal(t, "my-image:0.0.1", commonPipelineEnvironment.container.imageNameTag)
|
|
})
|
|
|
|
t.Run("success case (custom buildpacks and custom env variables, renaming docker conf file, additional tag)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/test.json",
|
|
Buildpacks: []string{"test"},
|
|
BuildEnvVars: map[string]interface{}{
|
|
"FOO": "BAR",
|
|
},
|
|
AdditionalTags: []string{"latest"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assert.Equal(t, creatorPath, runner.Calls[1].Exec)
|
|
assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks")
|
|
assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks/order.toml")
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:latest", config.ContainerRegistryURL, config.ContainerImageName))
|
|
|
|
copiedFileExists, _ := utils.FileExists("/tmp/config.json")
|
|
assert.True(t, copiedFileExists)
|
|
})
|
|
|
|
t.Run("success case (custom buildpacks, pre and post buildpacks and custom env variables, renaming docker conf file, additional tag)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/test.json",
|
|
PreBuildpacks: []string{"pre-test"},
|
|
PostBuildpacks: []string{"post-test"},
|
|
Buildpacks: []string{"test"},
|
|
BuildEnvVars: map[string]interface{}{
|
|
"FOO": "BAR",
|
|
},
|
|
AdditionalTags: []string{"latest"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assert.Equal(t, creatorPath, runner.Calls[1].Exec)
|
|
assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks")
|
|
assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks/order.toml")
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:latest", config.ContainerRegistryURL, config.ContainerImageName))
|
|
|
|
copiedFileExists, _ := utils.FileExists("/tmp/config.json")
|
|
assert.True(t, copiedFileExists)
|
|
})
|
|
|
|
t.Run("success case (custom pre and post buildpacks and custom env variables, renaming docker conf file, additional tag)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/test.json",
|
|
PostBuildpacks: []string{"post-test"},
|
|
PreBuildpacks: []string{"pre-test"},
|
|
BuildEnvVars: map[string]interface{}{
|
|
"FOO": "BAR",
|
|
},
|
|
AdditionalTags: []string{"latest"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assert.Equal(t, creatorPath, runner.Calls[1].Exec)
|
|
assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks")
|
|
assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks/order.toml")
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:latest", config.ContainerRegistryURL, config.ContainerImageName))
|
|
|
|
copiedFileExists, _ := utils.FileExists("/tmp/config.json")
|
|
assert.True(t, copiedFileExists)
|
|
})
|
|
|
|
t.Run("success case (customTlsCertificates)", func(t *testing.T) {
|
|
t.Parallel()
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
httpmock.RegisterResponder(http.MethodGet, "https://test-cert.com/cert.crt", httpmock.NewStringResponder(200, "testCert"))
|
|
client := &piperhttp.Client{}
|
|
client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true})
|
|
|
|
caCertsFile := "/etc/ssl/certs/ca-certificates.crt"
|
|
caCertsTmpFile := "/tmp/ca-certificates.crt"
|
|
registry := "some-registry"
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: registry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
CustomTLSCertificateLinks: []string{"https://test-cert.com/cert.crt", "https://test-cert.com/cert.crt"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(caCertsFile, []byte("test\n"))
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, client)
|
|
require.NoError(t, err)
|
|
|
|
result, err := utils.FilesMock.FileRead(caCertsTmpFile)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "test\ntestCert\ntestCert\n", string(result))
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assert.Contains(t, runner.Env, fmt.Sprintf("SSL_CERT_FILE=%s", caCertsTmpFile))
|
|
assertLifecycleCalls(t, runner, 2)
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
|
|
})
|
|
|
|
t.Run("success case (additionalTags)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
AdditionalTags: []string{"3", "3.1", "3.1", "3.1.5"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
require.NoError(t, err)
|
|
|
|
runner := utils.ExecMockRunner
|
|
assertLifecycleCalls(t, runner, 2)
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:3", config.ContainerRegistryURL, config.ContainerImageName))
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:3.1", config.ContainerRegistryURL, config.ContainerImageName))
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:3.1.5", config.ContainerRegistryURL, config.ContainerImageName))
|
|
})
|
|
|
|
t.Run("success case: build environment variables", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry),
|
|
ProjectDescriptor: "project.toml",
|
|
BuildEnvVars: map[string]interface{}{
|
|
"OPTIONS_KEY": "OPTIONS_VALUE",
|
|
"OVERWRITE": "this should win",
|
|
},
|
|
}
|
|
|
|
projectToml := `[project]
|
|
id = "io.buildpacks.my-app"
|
|
|
|
[[build.env]]
|
|
name="PROJECT_DESCRIPTOR_KEY"
|
|
value="PROJECT_DESCRIPTOR_VALUE"
|
|
|
|
[[build.env]]
|
|
name="OVERWRITE"
|
|
value="this should be overwritten"
|
|
`
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile("project.toml", []byte(projectToml))
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := telemetry.CustomData{}
|
|
err := callCnbBuild(&config, &telemetryData, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
assertLifecycleCalls(t, utils.ExecMockRunner, 2)
|
|
|
|
assetBuildEnv(t, utils, "OPTIONS_KEY", "OPTIONS_VALUE")
|
|
assetBuildEnv(t, utils, "PROJECT_DESCRIPTOR_KEY", "PROJECT_DESCRIPTOR_VALUE")
|
|
assetBuildEnv(t, utils, "OVERWRITE", "this should win")
|
|
})
|
|
|
|
t.Run("pom.xml exists (symlink for the target folder)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.CurrentDir = "/jenkins"
|
|
utils.FilesMock.AddDir("/jenkins")
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
utils.FilesMock.AddFile("/workspace/pom.xml", []byte("test"))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
require.NoError(t, err)
|
|
|
|
runner := utils.ExecMockRunner
|
|
assertLifecycleCalls(t, runner, 2)
|
|
|
|
assert.True(t, utils.FilesMock.HasCreatedSymlink("/jenkins/target", "/workspace/target"))
|
|
})
|
|
|
|
t.Run("no pom.xml exists (no symlink for the target folder)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.CurrentDir = "/jenkins"
|
|
utils.FilesMock.AddDir("/jenkins")
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
require.NoError(t, err)
|
|
|
|
runner := utils.ExecMockRunner
|
|
assertLifecycleCalls(t, runner, 2)
|
|
|
|
assert.False(t, utils.FilesMock.HasCreatedSymlink("/jenkins/target", "/workspace/target"))
|
|
})
|
|
|
|
t.Run("error case: Invalid DockerConfigJSON file", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
ContainerImageName: "my-image",
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":"dXNlcjpwYXNz"}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
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) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
ContainerImageName: "my-image",
|
|
DockerConfigJSON: "not-there/config.json",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
assert.EqualError(t, err, "failed to create/rename DockerConfigJSON file: cannot copy 'not-there/config.json': file does not exist")
|
|
})
|
|
|
|
t.Run("error case: DockerConfigJSON file not there (not config.json)", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
ContainerImageName: "my-image",
|
|
DockerConfigJSON: "not-there",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
assert.EqualError(t, err, "failed to create/rename DockerConfigJSON file: cannot copy 'not-there': file does not exist")
|
|
})
|
|
|
|
t.Run("error case: dockerImage is not a valid builder", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
assert.EqualError(t, err, "the provided dockerImage is not a valid builder: binary '/cnb/lifecycle/creator' not found")
|
|
})
|
|
|
|
t.Run("error case: builder image does not contain tls certificates", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "0.0.1",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
Buildpacks: []string{"test"},
|
|
CustomTLSCertificateLinks: []string{"http://example.com/certs.pem"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
assert.EqualError(t, err, "failed to copy certificates: cannot copy '/etc/ssl/certs/ca-certificates.crt': file does not exist")
|
|
})
|
|
|
|
t.Run("success case (telemetry was added)", func(t *testing.T) {
|
|
t.Parallel()
|
|
registry := "some-registry"
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: registry,
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
ProjectDescriptor: "project.toml",
|
|
AdditionalTags: []string{"latest"},
|
|
Buildpacks: []string{"paketobuildpacks/java", "gcr.io/paketo-buildpacks/node"},
|
|
Bindings: map[string]interface{}{"SECRET": map[string]string{"key": "KEY", "file": "a_file"}},
|
|
Path: "target",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
utils.FilesMock.AddDir("target")
|
|
utils.FilesMock.AddFile("target/project.toml", []byte(`[project]
|
|
id = "test"
|
|
name = "test"
|
|
version = "1.0.0"
|
|
|
|
[build]
|
|
include = []
|
|
exclude = ["*.tar"]
|
|
|
|
[[build.buildpacks]]
|
|
uri = "some-buildpack"`))
|
|
utils.FilesMock.AddFile("a_file", []byte(`{}`))
|
|
utils.FilesMock.AddFile("target/somelib.jar", []byte(`FFFFFF`))
|
|
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := &telemetry.CustomData{}
|
|
err := callCnbBuild(&config, telemetryData, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
require.NoError(t, err)
|
|
|
|
customDataAsString := telemetryData.Custom1
|
|
customData := &buildpacks.BuildpacksTelemetry{}
|
|
err = json.Unmarshal([]byte(customDataAsString), customData)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 3, customData.Version)
|
|
require.Equal(t, 1, len(customData.Data))
|
|
assert.Equal(t, "3.1.5", customData.Data[0].ImageTag)
|
|
assert.Equal(t, "folder", string(customData.Data[0].Path))
|
|
assert.Contains(t, customData.Data[0].AdditionalTags, "latest")
|
|
assert.Contains(t, customData.Data[0].BindingKeys, "SECRET")
|
|
assert.Equal(t, "paketobuildpacks/builder-jammy-base:latest", customData.Data[0].Builder)
|
|
|
|
assert.Contains(t, customData.Data[0].Buildpacks.FromConfig, "paketobuildpacks/java")
|
|
assert.NotContains(t, customData.Data[0].Buildpacks.FromProjectDescriptor, "paketobuildpacks/java")
|
|
assert.Contains(t, customData.Data[0].Buildpacks.FromProjectDescriptor, "bcc73ab1f0a0d3fb0d1bf2b6df5510a25ccd14a761dbc0f5044ea24ead30452b")
|
|
assert.Contains(t, customData.Data[0].Buildpacks.Overall, "paketobuildpacks/java")
|
|
|
|
assert.True(t, customData.Data[0].ProjectDescriptor.Used)
|
|
assert.False(t, customData.Data[0].ProjectDescriptor.IncludeUsed)
|
|
assert.True(t, customData.Data[0].ProjectDescriptor.ExcludeUsed)
|
|
})
|
|
|
|
t.Run("error case, multiple artifacts in path", func(t *testing.T) {
|
|
t.Parallel()
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry),
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
ProjectDescriptor: "project.toml",
|
|
AdditionalTags: []string{"latest"},
|
|
Buildpacks: []string{"paketobuildpacks/java", "gcr.io/paketo-buildpacks/node"},
|
|
Path: "target/*.jar",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
utils.FilesMock.AddDir("target")
|
|
utils.FilesMock.AddFile("target/app.jar", []byte(`FFFFFF`))
|
|
utils.FilesMock.AddFile("target/app-src.jar", []byte(`FFFFFF`))
|
|
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := telemetry.CustomData{}
|
|
err := callCnbBuild(&config, &telemetryData, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
require.EqualError(t, err, "could not resolve path: Failed to resolve glob for 'target/*.jar', matching 2 file(s)")
|
|
})
|
|
|
|
t.Run("success case, artifacts found by glob", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry),
|
|
DockerConfigJSON: "/path/to/config.json",
|
|
ProjectDescriptor: "project.toml",
|
|
AdditionalTags: []string{"latest"},
|
|
Buildpacks: []string{"paketobuildpacks/java", "gcr.io/paketo-buildpacks/node"},
|
|
Path: "**/target",
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
utils.FilesMock.AddDir("target")
|
|
utils.FilesMock.AddFile("target/app.jar", []byte(`FFFFFF`))
|
|
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := telemetry.CustomData{}
|
|
err := callCnbBuild(&config, &telemetryData, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
|
|
require.NoError(t, err)
|
|
runner := utils.ExecMockRunner
|
|
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
|
|
assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag))
|
|
assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL)
|
|
assert.Equal(t, "my-image:3.1.5", commonPipelineEnvironment.container.imageNameTag)
|
|
})
|
|
|
|
t.Run("success case (build env telemetry was added)", func(t *testing.T) {
|
|
t.Parallel()
|
|
registry := "some-registry"
|
|
config := cnbBuildOptions{
|
|
ContainerImageName: "my-image",
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: registry,
|
|
ProjectDescriptor: "project.toml",
|
|
BuildEnvVars: map[string]interface{}{"CONFIG_KEY": "var", "BP_JVM_VERSION": "8"},
|
|
}
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile("project.toml", []byte(`[project]
|
|
id = "test"
|
|
|
|
[build]
|
|
include = []
|
|
|
|
[[build.env]]
|
|
name='PROJECT_KEY'
|
|
value='var'
|
|
|
|
[[build.env]]
|
|
name='BP_NODE_VERSION'
|
|
value='11'
|
|
|
|
[[build.buildpacks]]
|
|
uri = "some-buildpack"
|
|
`))
|
|
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := &telemetry.CustomData{}
|
|
err := callCnbBuild(&config, telemetryData, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
|
require.NoError(t, err)
|
|
|
|
customDataAsString := telemetryData.Custom1
|
|
customData := &buildpacks.BuildpacksTelemetry{}
|
|
err = json.Unmarshal([]byte(customDataAsString), customData)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(customData.Data))
|
|
assert.Contains(t, customData.Data[0].BuildEnv.KeysFromConfig, "CONFIG_KEY")
|
|
assert.NotContains(t, customData.Data[0].BuildEnv.KeysFromProjectDescriptor, "CONFIG_KEY")
|
|
assert.Contains(t, customData.Data[0].BuildEnv.KeysOverall, "CONFIG_KEY")
|
|
|
|
assert.NotContains(t, customData.Data[0].BuildEnv.KeysFromConfig, "PROJECT_KEY")
|
|
assert.Contains(t, customData.Data[0].BuildEnv.KeysFromProjectDescriptor, "PROJECT_KEY")
|
|
assert.Contains(t, customData.Data[0].BuildEnv.KeysOverall, "PROJECT_KEY")
|
|
|
|
assert.Equal(t, "8", customData.Data[0].BuildEnv.KeyValues["BP_JVM_VERSION"])
|
|
assert.Equal(t, "11", customData.Data[0].BuildEnv.KeyValues["BP_NODE_VERSION"])
|
|
assert.NotContains(t, customData.Data[0].BuildEnv.KeyValues, "PROJECT_KEY")
|
|
|
|
assert.Contains(t, customData.Data[0].Buildpacks.Overall, "bcc73ab1f0a0d3fb0d1bf2b6df5510a25ccd14a761dbc0f5044ea24ead30452b")
|
|
})
|
|
|
|
t.Run("success case (multiple images configured)", func(t *testing.T) {
|
|
t.Parallel()
|
|
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
|
config := cnbBuildOptions{
|
|
ContainerImageTag: "3.1.5",
|
|
ContainerRegistryURL: imageRegistry,
|
|
DockerConfigJSON: "/path/to/my-config.json",
|
|
AdditionalTags: []string{"3", "3.1", "3.1", "3.1.5"},
|
|
MultipleImages: []map[string]interface{}{{"ContainerImageName": "my-image-0", "ContainerImageAlias": "simple"}, {"ContainerImageName": "my-image-1"}},
|
|
}
|
|
|
|
expectedImageCount := len(config.MultipleImages)
|
|
|
|
utils := newCnbBuildTestsUtils()
|
|
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
|
addBuilderFiles(&utils)
|
|
|
|
telemetryData := &telemetry.CustomData{}
|
|
err := callCnbBuild(&config, telemetryData, &utils, &commonPipelineEnvironment, &piperhttp.Client{})
|
|
require.NoError(t, err)
|
|
|
|
customDataAsString := telemetryData.Custom1
|
|
customData := &buildpacks.BuildpacksTelemetry{}
|
|
err = json.Unmarshal([]byte(customDataAsString), customData)
|
|
assert.NoError(t, err)
|
|
require.Equal(t, expectedImageCount, len(customData.Data))
|
|
|
|
runner := utils.ExecMockRunner
|
|
require.Equal(t, expectedImageCount, len(runner.Calls)-1)
|
|
for i, call := range runner.Calls {
|
|
if i == 0 { // first call is -version
|
|
continue
|
|
}
|
|
lifecycleCall := i - 1
|
|
assert.Equal(t, 4, len(customData.Data[lifecycleCall].AdditionalTags))
|
|
assertLifecycleCalls(t, runner, i+1)
|
|
containerImageName := fmt.Sprintf("my-image-%d", lifecycleCall)
|
|
assert.Contains(t, call.Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, containerImageName, config.ContainerImageTag))
|
|
assert.Contains(t, call.Params, fmt.Sprintf("%s/%s:3", config.ContainerRegistryURL, containerImageName))
|
|
assert.Contains(t, call.Params, fmt.Sprintf("%s/%s:3.1", config.ContainerRegistryURL, containerImageName))
|
|
assert.Contains(t, call.Params, fmt.Sprintf("%s/%s:3.1.5", config.ContainerRegistryURL, containerImageName))
|
|
}
|
|
|
|
assert.Equal(t, "my-image-0:3.1.5", commonPipelineEnvironment.container.imageNameTag)
|
|
assert.Equal(t, []string{"simple", "my-image-1"}, commonPipelineEnvironment.container.imageNames)
|
|
})
|
|
}
|