Skip to content

Commit 8bf6298

Browse files
authored
feat(imagePushToRegistry): Support imageNameTags (#4853)
* add imageNameTags related parameters to step * fix registry+imageNameTags * add debug logging * remove debug logging * update parameter docs --------- Co-authored-by: jliempt <>
1 parent df2e976 commit 8bf6298

4 files changed

+138
-1
lines changed

cmd/imagePushToRegistry.go

+46-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func imagePushToRegistry(config imagePushToRegistryOptions, telemetryData *telem
8181
}
8282

8383
func runImagePushToRegistry(config *imagePushToRegistryOptions, telemetryData *telemetry.CustomData, utils imagePushToRegistryUtils) error {
84-
if !config.PushLocalDockerImage {
84+
if !config.PushLocalDockerImage && !config.UseImageNameTags {
8585
if len(config.TargetImages) == 0 {
8686
config.TargetImages = mapSourceTargetImages(config.SourceImages)
8787
}
@@ -91,6 +91,13 @@ func runImagePushToRegistry(config *imagePushToRegistryOptions, telemetryData *t
9191
}
9292
}
9393

94+
if config.UseImageNameTags {
95+
if len(config.TargetImageNameTags) > 0 && len(config.TargetImageNameTags) != len(config.SourceImageNameTags) {
96+
log.SetErrorCategory(log.ErrorConfiguration)
97+
return errors.New("configuration error: please configure targetImageNameTags and sourceImageNameTags properly")
98+
}
99+
}
100+
94101
// Docker image tags don't allow plus signs in tags, thus replacing with dash
95102
config.SourceImageTag = strings.ReplaceAll(config.SourceImageTag, "+", "-")
96103
config.TargetImageTag = strings.ReplaceAll(config.TargetImageTag, "+", "-")
@@ -115,6 +122,13 @@ func runImagePushToRegistry(config *imagePushToRegistryOptions, telemetryData *t
115122
return errors.Wrap(err, "failed to handle credentials for source registry")
116123
}
117124

125+
if config.UseImageNameTags {
126+
if err := pushImageNameTagsToTargetRegistry(config, utils); err != nil {
127+
return errors.Wrapf(err, "failed to push imageNameTags to target registry")
128+
}
129+
return nil
130+
}
131+
118132
if err := copyImages(config, utils); err != nil {
119133
return errors.Wrap(err, "failed to copy images")
120134
}
@@ -242,6 +256,37 @@ func pushLocalImageToTargetRegistry(config *imagePushToRegistryOptions, utils im
242256
return nil
243257
}
244258

259+
func pushImageNameTagsToTargetRegistry(config *imagePushToRegistryOptions, utils imagePushToRegistryUtils) error {
260+
g, ctx := errgroup.WithContext(context.Background())
261+
g.SetLimit(10)
262+
263+
for i, sourceImageNameTag := range config.SourceImageNameTags {
264+
src := fmt.Sprintf("%s/%s", config.SourceRegistryURL, sourceImageNameTag)
265+
266+
dst := ""
267+
if len(config.TargetImageNameTags) == 0 {
268+
dst = fmt.Sprintf("%s/%s", config.TargetRegistryURL, sourceImageNameTag)
269+
} else {
270+
dst = fmt.Sprintf("%s/%s", config.TargetRegistryURL, config.TargetImageNameTags[i])
271+
}
272+
273+
g.Go(func() error {
274+
log.Entry().Infof("Copying %s to %s...", src, dst)
275+
if err := utils.CopyImage(ctx, src, dst, ""); err != nil {
276+
return err
277+
}
278+
log.Entry().Infof("Copying %s to %s... Done", src, dst)
279+
return nil
280+
})
281+
}
282+
283+
if err := g.Wait(); err != nil {
284+
return err
285+
}
286+
287+
return nil
288+
}
289+
245290
func mapSourceTargetImages(sourceImages []string) map[string]any {
246291
targetImages := make(map[string]any, len(sourceImages))
247292
for _, sourceImage := range sourceImages {

cmd/imagePushToRegistry_generated.go

+38
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/imagePushToRegistry_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,32 @@ func TestRunImagePushToRegistry(t *testing.T) {
7171
assert.Equal(t, "1.0.0-123-456", config.TargetImageTag)
7272
})
7373

74+
t.Run("multiple imageNameTags", func(t *testing.T) {
75+
t.Parallel()
76+
77+
config := imagePushToRegistryOptions{
78+
SourceRegistryURL: "https://source.registry",
79+
SourceImages: []string{"source-image"},
80+
SourceImageNameTags: []string{"com.sap.docker/ppiper:240104-20240227184612",
81+
"com.sap.docker/ppiper:240104-20240227184612-amd64",
82+
"com.sap.docker/ppiper:240104-20240227184612-aarch64",
83+
},
84+
SourceRegistryUser: "sourceuser",
85+
SourceRegistryPassword: "sourcepassword",
86+
TargetRegistryURL: "https://target.registry",
87+
TargetImageTag: "1.0.0-123+456",
88+
TargetRegistryUser: "targetuser",
89+
TargetRegistryPassword: "targetpassword",
90+
UseImageNameTags: true,
91+
}
92+
craneMockUtils := &dockermock.CraneMockUtils{}
93+
utils := newImagePushToRegistryMockUtils(craneMockUtils)
94+
err := runImagePushToRegistry(&config, nil, utils)
95+
assert.NoError(t, err)
96+
createdConfig, err := utils.FileRead(targetDockerConfigPath)
97+
assert.Equal(t, customDockerConfig, string(createdConfig))
98+
})
99+
74100
t.Run("failed to copy image", func(t *testing.T) {
75101
t.Parallel()
76102

resources/metadata/imagePushToRegistry.yaml

+28
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,34 @@ spec:
171171
resourceRef:
172172
- name: commonPipelineEnvironment
173173
param: artifactVersion
174+
- name: useImageNameTags
175+
description: |
176+
Will use the sourceImageNameTags and targetImageNameTags parameters, instead of sourceImages and targetImages.
177+
sourceImageNameTags can be set by a build step, e.g. kanikoExecute, and is then available in the pipeline environment.
178+
type: bool
179+
scope:
180+
- PARAMETERS
181+
- STAGES
182+
- STEPS
183+
- name: sourceImageNameTags
184+
type: "[]string"
185+
description: "List of full names (registry and tag) of the images to be copied. Works in combination with useImageNameTags."
186+
resourceRef:
187+
- name: commonPipelineEnvironment
188+
param: container/imageNameTags
189+
scope:
190+
- PARAMETERS
191+
- STAGES
192+
- STEPS
193+
- name: targetImageNameTags
194+
type: "[]string"
195+
description: |
196+
List of full names (registry and tag) of the images to be deployed. Works in combination with useImageNameTags.
197+
If not set, the value will be the sourceImageNameTags with the targetRegistryUrl incorporated.
198+
scope:
199+
- PARAMETERS
200+
- STAGES
201+
- STEPS
174202
- name: tagLatest
175203
description: "Defines if the image should be tagged as `latest`. The parameter is true if targetImageTag is not specified."
176204
type: bool

0 commit comments

Comments
 (0)