Skip to content

Commit 9b91352

Browse files
authored
Do not fail apply-tags if the image config has unknown media type (#40)
Signed-off-by: Mykola Morhun <mmorhun@redhat.com>
1 parent f94dffb commit 9b91352

File tree

3 files changed

+93
-25
lines changed

3 files changed

+93
-25
lines changed

pkg/cliwrappers/skopeo.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ package cliwrappers
22

33
import (
44
"errors"
5+
"fmt"
56
"strconv"
67
"strings"
78

89
l "github.com/konflux-ci/konflux-build-cli/pkg/logger"
910
)
1011

12+
const (
13+
UnsupportedOCIConfigMediaType = "application/vnd.unknown.config.v1+json"
14+
)
15+
1116
var skopeoLog = l.Logger.WithField("logger", "ScopeoCli")
1217

1318
type SkopeoCliInterface interface {
@@ -135,14 +140,17 @@ func (s *SkopeoCli) Inspect(args *SkopeoInspectArgs) (string, error) {
135140

136141
retryer := NewRetryer(func() (string, string, int, error) {
137142
return s.Executor.Execute("skopeo", scopeoArgs...)
138-
}).WithImageRegistryPreset().StopIfOutputContains("unauthorized")
143+
}).WithImageRegistryPreset().
144+
StopIfOutputContains("unauthorized").
145+
// Stop on unsupported config media type
146+
StopIfOutputContains(UnsupportedOCIConfigMediaType)
139147

140148
stdout, stderr, _, err := retryer.Run()
141149
if err != nil {
142150
skopeoLog.Errorf("skopeo inspect failed: %s", err.Error())
143151
skopeoLog.Infof("[stdout]:\n%s", stdout)
144152
skopeoLog.Infof("[stderr]:\n%s", stderr)
145-
return "", err
153+
return "", fmt.Errorf("%w: %s", err, stderr)
146154
}
147155

148156
skopeoLog.Debug("[stdout]:\n" + stdout)

pkg/commands/apply_tags.go

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -113,27 +113,9 @@ func (c *ApplyTags) Run() error {
113113

114114
c.imageByDigest = c.imageName + "@" + c.Params.Digest
115115

116-
var tagsFromLabel []string
117-
if c.Params.LabelWithTags != "" {
118-
var err error
119-
tagsFromLabel, err = c.retrieveTagsFromImageLabel(c.Params.LabelWithTags)
120-
if err != nil {
121-
l.Logger.Errorf("failed to retrieve tags from '%s' label value: %s", c.Params.LabelWithTags, err.Error())
122-
return err
123-
}
124-
for _, tag := range tagsFromLabel {
125-
if !common.IsImageTagValid(tag) {
126-
return fmt.Errorf("tag from label '%s' is invalid", tag)
127-
}
128-
}
129-
130-
if len(tagsFromLabel) > 0 {
131-
l.Logger.Infof("Additional tags from '%s' image label: %s", c.Params.LabelWithTags, strings.Join(tagsFromLabel, ", "))
132-
} else {
133-
l.Logger.Warnf("No tags given in '%s' image label", c.Params.LabelWithTags)
134-
}
135-
} else {
136-
l.Logger.Debug("Label with additional tags is not set")
116+
tagsFromLabel, err := c.retrieveTagsFromImageLabel(c.Params.LabelWithTags)
117+
if err != nil {
118+
return err
137119
}
138120

139121
tags := append(c.Params.NewTags, tagsFromLabel...)
@@ -166,7 +148,13 @@ func (c *ApplyTags) logParams() {
166148
}
167149
}
168150

151+
// retrieveTagsFromImageLabel fetches list of tags from the given image label and interprets the results.
169152
func (c *ApplyTags) retrieveTagsFromImageLabel(labelName string) ([]string, error) {
153+
if labelName == "" {
154+
l.Logger.Debug("Label with additional tags is not set")
155+
return nil, nil
156+
}
157+
170158
inspectArgs := &cliWrappers.SkopeoInspectArgs{
171159
ImageRef: c.imageByDigest,
172160
Format: fmt.Sprintf(`{{ index .Labels "%s" }}`, labelName),
@@ -175,18 +163,40 @@ func (c *ApplyTags) retrieveTagsFromImageLabel(labelName string) ([]string, erro
175163
}
176164
tagsLabelValue, err := c.CliWrappers.SkopeoCli.Inspect(inspectArgs)
177165
if err != nil {
166+
if strings.Contains(err.Error(), cliWrappers.UnsupportedOCIConfigMediaType) {
167+
// Skip the label with tags for unsupported config media type.
168+
// Print warning message and continue.
169+
l.Logger.Warnf("unsupported config media type '%s' of input image. Skipping reading %s image label",
170+
cliWrappers.UnsupportedOCIConfigMediaType, c.Params.LabelWithTags)
171+
return nil, nil
172+
}
173+
l.Logger.Errorf("failed to retrieve tags from '%s' label value: %s", c.Params.LabelWithTags, err.Error())
178174
return nil, err
179175
}
180176
tagsLabelValue = strings.TrimSpace(tagsLabelValue)
181177
l.Logger.Debugf("Tags label value: %s", tagsLabelValue)
182178

183179
if tagsLabelValue == "" {
180+
l.Logger.Warnf("No tags given in '%s' image label", c.Params.LabelWithTags)
184181
return nil, nil
185182
}
186183

187184
tagSeparatorRegex := regexp.MustCompile(`[\s,]+`)
188-
tags := tagSeparatorRegex.Split(tagsLabelValue, -1)
189-
return tags, nil
185+
tagsFromLabel := tagSeparatorRegex.Split(tagsLabelValue, -1)
186+
187+
// Successfully obtained tags from the image label
188+
// Validate the obtained tags
189+
for _, tag := range tagsFromLabel {
190+
if !common.IsImageTagValid(tag) {
191+
return nil, fmt.Errorf("tag from label '%s' is invalid", tag)
192+
}
193+
}
194+
195+
if len(tagsFromLabel) > 0 {
196+
l.Logger.Infof("Additional tags from '%s' image label: %s", c.Params.LabelWithTags, strings.Join(tagsFromLabel, ", "))
197+
}
198+
199+
return tagsFromLabel, nil
190200
}
191201

192202
func (c *ApplyTags) applyTags(tags []string) error {

pkg/commands/apply_tags_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ func Test_retrieveTagsFromImageLabel(t *testing.T) {
191191

192192
mockSkopeoCli := &mockSkopeoCli{}
193193
c := &ApplyTags{
194+
Params: &ApplyTagsParams{LabelWithTags: "label"},
194195
CliWrappers: ApplyTagsCliWrappers{SkopeoCli: mockSkopeoCli},
195196
imageByDigest: imageRef,
196197
}
@@ -296,6 +297,20 @@ func Test_retrieveTagsFromImageLabel(t *testing.T) {
296297
g.Expect(isScopeoInspectCalled).To(BeTrue())
297298
g.Expect(err).To(HaveOccurred())
298299
})
300+
301+
t.Run("should skip tags from label if image has unknown media type in config", func(t *testing.T) {
302+
isScopeoInspectCalled := false
303+
mockSkopeoCli.InspectFunc = func(args *cliwrappers.SkopeoInspectArgs) (string, error) {
304+
isScopeoInspectCalled = true
305+
g.Expect(args.ImageRef).To(Equal(imageRef))
306+
return "", errors.New("unsupported image-specific operation on artifact with type \"application/vnd.unknown.config.v1+json\"")
307+
}
308+
309+
tags, err := c.retrieveTagsFromImageLabel(labelName)
310+
g.Expect(isScopeoInspectCalled).To(BeTrue())
311+
g.Expect(err).ToNot(HaveOccurred())
312+
g.Expect(tags).To(BeNil())
313+
})
299314
}
300315

301316
func Test_applyTags(t *testing.T) {
@@ -543,6 +558,41 @@ func Test_Run(t *testing.T) {
543558
g.Expect(isCreateResultJsonCalled).To(BeTrue())
544559
})
545560

561+
t.Run("should successfully run apply-tags with tags from param and skip tags from label when the image config has unknown media type", func(t *testing.T) {
562+
beforeEach()
563+
tags := []string{"param-1-tag", "param-2-tag"}
564+
const labelWithTagsName = "konflux.additional-tags"
565+
c.Params.NewTags = tags
566+
c.Params.LabelWithTags = labelWithTagsName
567+
568+
isScopeoInspectCalled := false
569+
_mockSkopeoCli.InspectFunc = func(args *cliwrappers.SkopeoInspectArgs) (string, error) {
570+
isScopeoInspectCalled = true
571+
g.Expect(args.ImageRef).To(Equal(c.Params.ImageUrl + "@" + c.Params.Digest))
572+
return "", errors.New("unsupported image-specific operation on artifact with type \"application/vnd.unknown.config.v1+json\"")
573+
}
574+
scopeoCopyCalledTimes := 0
575+
_mockSkopeoCli.CopyFunc = func(args *cliwrappers.SkopeoCopyArgs) error {
576+
g.Expect(args.DestinationImage).To(HaveSuffix("tag"))
577+
scopeoCopyCalledTimes++
578+
return nil
579+
}
580+
isCreateResultJsonCalled := false
581+
_mockResultsWriter.CreateResultJsonFunc = func(result any) (string, error) {
582+
isCreateResultJsonCalled = true
583+
applyTagsResults, ok := result.(ApplyTagsResults)
584+
g.Expect(ok).To(BeTrue())
585+
g.Expect(applyTagsResults.Tags).To(Equal([]string{"param-1-tag", "param-2-tag"}))
586+
return "", nil
587+
}
588+
589+
err := c.Run()
590+
g.Expect(err).ToNot(HaveOccurred())
591+
g.Expect(isScopeoInspectCalled).To(BeTrue())
592+
g.Expect(scopeoCopyCalledTimes).To(Equal(2))
593+
g.Expect(isCreateResultJsonCalled).To(BeTrue())
594+
})
595+
546596
t.Run("should error if creation of a tag failed", func(t *testing.T) {
547597
beforeEach()
548598
tags := []string{"tag1", "tag2", "tag3", "tag4"}

0 commit comments

Comments
 (0)