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

Broken single containerImage argument has been removed (#3065)

* Broken single containerImage argument has been removed

Co-authored-by: Ralf Pannemans <ralf.pannemans@sap.com>

* revert containerRegistryUrl param name

Co-authored-by: Pavel Busko <pavel.busko@sap.com>

* mark containerImageName, containerImageTag and containerRegistryUrl as mandatory arguments

Co-authored-by: Pavel Busko <pavel.busko@sap.com>
Co-authored-by: Ralf Pannemans <ralf.pannemans@sap.com>

Co-authored-by: Ralf Pannemans <ralf.pannemans@sap.com>
Co-authored-by: Benjamin Haegenlaeuer <benjamin.haegenlaeuer@sap.com>
This commit is contained in:
Pavel Busko 2021-08-26 14:26:54 +02:00 committed by GitHub
parent 016599c1f1
commit 01c687bbdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 58 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path"
"regexp"
"strings"
"github.com/SAP/jenkins-library/pkg/command"
@ -131,7 +132,7 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
}
} else {
log.Entry().Debugf("Filterd out '%s'", sourceFile)
log.Entry().Debugf("Filtered out '%s'", sourceFile)
}
}
@ -139,29 +140,24 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
var containerImageTag string
if len(config.ContainerRegistryURL) > 0 && len(config.ContainerImageName) > 0 && len(config.ContainerImageTag) > 0 {
containerRegistry, err := docker.ContainerRegistryFromURL(config.ContainerRegistryURL)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "failed to read registry url %s", config.ContainerRegistryURL)
var containerRegistry string
if matched, _ := regexp.MatchString("^(http|https)://.*", config.ContainerRegistryURL); matched {
containerRegistry, err = docker.ContainerRegistryFromURL(config.ContainerRegistryURL)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "failed to read containerRegistryUrl %s", config.ContainerRegistryURL)
}
} else {
containerRegistry = config.ContainerRegistryURL
}
containerImage = fmt.Sprintf("%s/%s", containerRegistry, config.ContainerImageName)
containerImageTag = strings.ReplaceAll(config.ContainerImageTag, "+", "-")
commonPipelineEnvironment.container.registryURL = config.ContainerRegistryURL
commonPipelineEnvironment.container.imageNameTag = containerImage
} else if len(config.ContainerImage) > 0 {
containerRegistry, err := docker.ContainerRegistryFromImage(config.ContainerImage)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "invalid registry part in image %s", config.ContainerImage)
}
containerImage = config.ContainerImage
// errors are already caught with previous call to docker.ContainerRegistryFromImage
containerImageTag, _ := docker.ContainerImageNameTagFromImage(config.ContainerImage)
commonPipelineEnvironment.container.registryURL = fmt.Sprintf("https://%s", containerRegistry)
commonPipelineEnvironment.container.imageNameTag = containerImageTag
} else {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.New("either containerImage or containerImageName and containerImageTag must be present")
return errors.New("containerRegistryUrl, containerImageName and containerImageTag must be present")
}
err = utils.RunExecutable("/cnb/lifecycle/detector")

View File

@ -17,7 +17,6 @@ import (
)
type cnbBuildOptions struct {
ContainerImage string `json:"containerImage,omitempty"`
ContainerImageName string `json:"containerImageName,omitempty"`
ContainerImageTag string `json:"containerImageTag,omitempty"`
ContainerRegistryURL string `json:"containerRegistryUrl,omitempty"`
@ -133,13 +132,15 @@ func CnbBuildCommand() *cobra.Command {
}
func addCnbBuildFlags(cmd *cobra.Command, stepConfig *cnbBuildOptions) {
cmd.Flags().StringVar(&stepConfig.ContainerImage, "containerImage", os.Getenv("PIPER_containerImage"), "Defines the full name of the Docker image to be created including registry, image name and tag like `my.docker.registry/path/myImageName:myTag`. If left empty, image will not be pushed.")
cmd.Flags().StringVar(&stepConfig.ContainerImageName, "containerImageName", os.Getenv("PIPER_containerImageName"), "Name of the container which will be built - will be used instead of parameter `containerImage`")
cmd.Flags().StringVar(&stepConfig.ContainerImageTag, "containerImageTag", os.Getenv("PIPER_containerImageTag"), "Tag of the container which will be built - will be used instead of parameter `containerImage`")
cmd.Flags().StringVar(&stepConfig.ContainerRegistryURL, "containerRegistryUrl", os.Getenv("PIPER_containerRegistryUrl"), "http(s) url of the Container registry where the image should be pushed to - will be used instead of parameter `containerImage`")
cmd.Flags().StringVar(&stepConfig.ContainerImageName, "containerImageName", os.Getenv("PIPER_containerImageName"), "Name of the container which will be built")
cmd.Flags().StringVar(&stepConfig.ContainerImageTag, "containerImageTag", os.Getenv("PIPER_containerImageTag"), "Tag of the container which will be built")
cmd.Flags().StringVar(&stepConfig.ContainerRegistryURL, "containerRegistryUrl", os.Getenv("PIPER_containerRegistryUrl"), "Container registry where the image should be pushed to")
cmd.Flags().StringVar(&stepConfig.Path, "path", os.Getenv("PIPER_path"), "The path should either point to your sources or an artifact build before.")
cmd.Flags().StringVar(&stepConfig.DockerConfigJSON, "dockerConfigJSON", os.Getenv("PIPER_dockerConfigJSON"), "Path to the file `.docker/config.json` - this is typically provided by your CI/CD system. You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).")
cmd.MarkFlagRequired("containerImageName")
cmd.MarkFlagRequired("containerImageTag")
cmd.MarkFlagRequired("containerRegistryUrl")
cmd.MarkFlagRequired("dockerConfigJSON")
}
@ -157,21 +158,12 @@ func cnbBuildMetadata() config.StepData {
{Name: "dockerConfigJsonCredentialsId", Description: "Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)). You can create it like explained in the Docker Success Center in the article about [how to generate a new auth in the config.json file](https://success.docker.com/article/generate-new-auth-in-config-json-file).", Type: "jenkins"},
},
Parameters: []config.StepParameters{
{
Name: "containerImage",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_containerImage"),
},
{
Name: "containerImageName",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Mandatory: true,
Aliases: []config.Alias{{Name: "dockerImageName"}},
Default: os.Getenv("PIPER_containerImageName"),
},
@ -185,7 +177,7 @@ func cnbBuildMetadata() config.StepData {
},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Mandatory: true,
Aliases: []config.Alias{{Name: "artifactVersion"}},
Default: os.Getenv("PIPER_containerImageTag"),
},
@ -199,7 +191,7 @@ func cnbBuildMetadata() config.StepData {
},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Mandatory: true,
Aliases: []config.Alias{{Name: "dockerRegistryUrl"}},
Default: os.Getenv("PIPER_containerRegistryUrl"),
},

View File

@ -27,13 +27,13 @@ func TestRunCnbBuild(t *testing.T) {
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
t.Run("success case", func(t *testing.T) {
t.Run("success case (registry with https)", func(t *testing.T) {
t.Parallel()
registy := "some-registry"
registry := "some-registry"
config := cnbBuildOptions{
ContainerImageName: "my-image",
ContainerImageTag: "0.0.1",
ContainerRegistryURL: fmt.Sprintf("https://%s", registy),
ContainerRegistryURL: fmt.Sprintf("https://%s", registry),
DockerConfigJSON: "/path/to/config.json",
}
@ -48,14 +48,38 @@ func TestRunCnbBuild(t *testing.T) {
assert.Equal(t, "/cnb/lifecycle/detector", runner.Calls[0].Exec)
assert.Equal(t, "/cnb/lifecycle/builder", runner.Calls[1].Exec)
assert.Equal(t, "/cnb/lifecycle/exporter", runner.Calls[2].Exec)
assert.Equal(t, []string{fmt.Sprintf("%s/%s:%s", registy, config.ContainerImageName, config.ContainerImageTag), fmt.Sprintf("%s/%s:latest", registy, config.ContainerImageName)}, runner.Calls[2].Params)
assert.Equal(t, []string{fmt.Sprintf("%s/%s:%s", registry, config.ContainerImageName, config.ContainerImageTag), fmt.Sprintf("%s/%s:latest", registry, config.ContainerImageName)}, runner.Calls[2].Params)
})
t.Run("success case (registry without https)", func(t *testing.T) {
t.Parallel()
registry := "some-registry"
config := cnbBuildOptions{
ContainerImageName: "my-image",
ContainerImageTag: "0.0.1",
ContainerRegistryURL: registry,
DockerConfigJSON: "/path/to/config.json",
}
utils := newCnbBuildTestsUtils()
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
err := runCnbBuild(&config, &telemetry.CustomData{}, utils, &commonPipelineEnvironment)
assert.NoError(t, err)
runner := utils.ExecMockRunner
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
assert.Equal(t, "/cnb/lifecycle/detector", runner.Calls[0].Exec)
assert.Equal(t, "/cnb/lifecycle/builder", runner.Calls[1].Exec)
assert.Equal(t, "/cnb/lifecycle/exporter", runner.Calls[2].Exec)
assert.Equal(t, []string{fmt.Sprintf("%s/%s:%s", registry, config.ContainerImageName, config.ContainerImageTag), fmt.Sprintf("%s/%s:latest", registry, config.ContainerImageName)}, runner.Calls[2].Params)
})
t.Run("error case: Invalid DockerConfigJSON file", func(t *testing.T) {
t.Parallel()
config := cnbBuildOptions{
ContainerImage: "my-image",
DockerConfigJSON: "/path/to/config.json",
ContainerImageName: "my-image",
DockerConfigJSON: "/path/to/config.json",
}
utils := newCnbBuildTestsUtils()
@ -68,8 +92,8 @@ func TestRunCnbBuild(t *testing.T) {
t.Run("error case: DockerConfigJSON file not there", func(t *testing.T) {
t.Parallel()
config := cnbBuildOptions{
ContainerImage: "my-image",
DockerConfigJSON: "not-there",
ContainerImageName: "my-image",
DockerConfigJSON: "not-there",
}
utils := newCnbBuildTestsUtils()

View File

@ -15,10 +15,10 @@ func TestNpmProject(t *testing.T) {
TestDir: []string{"testdata", "TestMtaIntegration", "npm"},
})
container.whenRunningPiperCommand("cnbBuild", "--containerImage", "not-found")
container.whenRunningPiperCommand("cnbBuild", "--containerImageName", "not-found", "--containerImageTag", "0.0.1", "--containerRegistryUrl", "test")
container.assertHasOutput(t, "running command: /cnb/lifecycle/detector")
container.assertHasOutput(t, "Paketo NPM Start Buildpack")
container.assertHasOutput(t, "Saving not-found")
container.assertHasOutput(t, "failed to write image to the following tags: [not-found:")
container.assertHasOutput(t, "Saving test/not-found:0.0.1")
container.assertHasOutput(t, "failed to write image to the following tags: [test/not-found:0.0.1")
}

View File

@ -9,18 +9,12 @@ spec:
description: Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)). You can create it like explained in the Docker Success Center in the article about [how to generate a new auth in the config.json file](https://success.docker.com/article/generate-new-auth-in-config-json-file).
type: jenkins
params:
- name: containerImage
type: string
description: Defines the full name of the Docker image to be created including registry, image name and tag like `my.docker.registry/path/myImageName:myTag`. If left empty, image will not be pushed.
scope:
- PARAMETERS
- STAGES
- STEPS
- name: containerImageName
aliases:
- name: dockerImageName
type: string
description: Name of the container which will be built - will be used instead of parameter `containerImage`
mandatory: true
description: Name of the container which will be built
scope:
- GENERAL
- PARAMETERS
@ -30,7 +24,8 @@ spec:
aliases:
- name: artifactVersion
type: string
description: Tag of the container which will be built - will be used instead of parameter `containerImage`
mandatory: true
description: Tag of the container which will be built
scope:
- GENERAL
- PARAMETERS
@ -43,7 +38,8 @@ spec:
aliases:
- name: dockerRegistryUrl
type: string
description: http(s) url of the Container registry where the image should be pushed to - will be used instead of parameter `containerImage`
mandatory: true
description: Container registry where the image should be pushed to
scope:
- GENERAL
- PARAMETERS

View File

@ -43,11 +43,13 @@ public class CnbBuildTest extends BasePiperTest {
}
)
stepRule.step.cnbBuild(script: nullScript, containerImage: 'foo:bar', dockerConfigJsonCredentialsId: 'DOCKER_CREDENTIALS')
stepRule.step.cnbBuild(script: nullScript, containerImageName: 'foo', containerImageTag: 'bar', containerRegistryUrl: 'test', dockerConfigJsonCredentialsId: 'DOCKER_CREDENTIALS')
assertThat(calledWithParameters.size(), is(3))
assertThat(calledWithParameters.size(), is(5))
assertThat(calledWithParameters.script, is(nullScript))
assertThat(calledWithParameters.containerImage, is('foo:bar'))
assertThat(calledWithParameters.containerImageName, is('foo'))
assertThat(calledWithParameters.containerImageTag, is('bar'))
assertThat(calledWithParameters.containerRegistryUrl, is('test'))
assertThat(calledWithParameters.dockerConfigJsonCredentialsId, is('DOCKER_CREDENTIALS'))
assertThat(calledWithStepName, is('cnbBuild'))