Skip to content

Commit

Permalink
Return digest property from image name parser
Browse files Browse the repository at this point in the history
image.Split now returns 3 fields: name, tag, and digest. The tag and digest
fields no longer include their respective delimiters (`:` and `@`).
  • Loading branch information
cronik committed Jan 22, 2022
1 parent 7a3c426 commit 727093f
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 32 deletions.
31 changes: 31 additions & 0 deletions api/filters/imagetag/imagetag_test.go
Expand Up @@ -687,6 +687,37 @@ spec:
},
},
},
"new tag and digest": {
input: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
image: nginx:1.2.1@sha256:46d5b90a7f4e9996351ad893a26bcbd27216676ad4d5316088ce351fb2c2c3dd
`,
expectedOutput: `
apiVersion: example.com/v1
kind: Foo
metadata:
name: instance
spec:
image: apache:1.3.0@sha256:xyz
`,
filter: Filter{
ImageTag: types.Image{
Name: "nginx",
NewName: "apache",
NewTag: "1.3.0",
Digest: "sha256:xyz",
},
},
fsSlice: []types.FieldSpec{
{
Path: "spec/image",
},
},
},
}

for tn, tc := range testCases {
Expand Down
19 changes: 15 additions & 4 deletions api/filters/imagetag/updater.go
Expand Up @@ -28,14 +28,25 @@ func (u imageTagUpdater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
return rn, nil
}

name, tag := image.Split(value)
name, tag, digest := image.Split(value)
if u.ImageTag.NewName != "" {
name = u.ImageTag.NewName
}
if u.ImageTag.NewTag != "" {
tag = ":" + u.ImageTag.NewTag
// not overriding tag/digest component, keep original
if u.ImageTag.NewTag == "" && u.ImageTag.Digest == "" {
if tag != "" {
tag = ":" + tag
}
if digest != "" {
tag += "@" + digest
}
}
if u.ImageTag.Digest != "" {
// overriding tag or digest will replace both original tag and digest values
if u.ImageTag.NewTag != "" && u.ImageTag.Digest != "" {
tag = ":" + u.ImageTag.NewTag + "@" + u.ImageTag.Digest
} else if u.ImageTag.NewTag != "" {
tag = ":" + u.ImageTag.NewTag
} else if u.ImageTag.Digest != "" {
tag = "@" + u.ImageTag.Digest
}

Expand Down
53 changes: 31 additions & 22 deletions api/image/image.go
Expand Up @@ -20,38 +20,47 @@ func IsImageMatched(s, t string) bool {

// Split separates and returns the name and tag parts
// from the image string using either colon `:` or at `@` separators.
// Note that the returned tag keeps its separator.
func Split(imageName string) (name string, tag string) {
// image reference pattern: [[host[:port]/]component/]component[:tag][@digest]
func Split(imageName string) (name string, tag string, digest string) {
// check if image name contains a domain
// if domain is present, ignore domain and check for `:`
searchName := imageName
slashIndex := strings.Index(imageName, "/")
if slashIndex > 0 {
searchName = imageName[slashIndex:]
} else {
slashIndex = 0
}

i := strings.LastIndex(imageName, "@")
if i > 0 {
ic := strings.Index(searchName[:i], ":")
if ic > 0 {
if slashIndex > 0 {
i = slashIndex + ic
} else {
i = ic
}
}
} else {
i = strings.LastIndex(searchName, ":")
if i > 0 && slashIndex > 0 {
i = slashIndex + i
}
id := strings.Index(searchName, "@")
ic := strings.Index(searchName, ":")

// no tag or digest
if ic < 0 && id < 0 {
return imageName, "", ""
}

// digest only
if id >= 0 && (id < ic || ic < 0) {
id += slashIndex
name = imageName[:id]
digest = strings.TrimPrefix(imageName[id:], "@")
return name, "", digest
}

if i < 0 {
return imageName, ""
// tag and digest
if id >= 0 && ic >= 0 {
id += slashIndex
ic += slashIndex
name = imageName[:ic]
tag = strings.TrimPrefix(imageName[ic:id], ":")
digest = strings.TrimPrefix(imageName[id:], "@")
return name, tag, digest
}

name = imageName[:i]
tag = imageName[i:]
return
// tag only
ic += slashIndex
name = imageName[:ic]
tag = strings.TrimPrefix(imageName[ic:], ":")
return name, tag, ""
}
27 changes: 21 additions & 6 deletions api/image/image_test.go
Expand Up @@ -61,50 +61,65 @@ func TestSplit(t *testing.T) {
value string
name string
tag string
digest string
}{
{
testName: "no tag",
value: "nginx",
name: "nginx",
tag: "",
digest: "",
},
{
testName: "with tag",
value: "nginx:1.2.3",
name: "nginx",
tag: ":1.2.3",
tag: "1.2.3",
digest: "",
},
{
testName: "with digest",
value: "nginx@sha256:12345",
name: "nginx",
tag: "@sha256:12345",
tag: "",
digest: "sha256:12345",
},
{
testName: "with tag and digest",
value: "nginx:1.2.3@sha256:12345",
name: "nginx",
tag: ":1.2.3@sha256:12345",
tag: "1.2.3",
digest: "sha256:12345",
},
{
testName: "with domain",
value: "docker.io/nginx:1.2.3",
name: "docker.io/nginx",
tag: ":1.2.3",
tag: "1.2.3",
digest: "",
},
{
testName: "with domain and port",
value: "foo.com:443/nginx:1.2.3",
name: "foo.com:443/nginx",
tag: ":1.2.3",
tag: "1.2.3",
digest: "",
},
{
testName: "with domain, port, and digest",
value: "foo.com:443/nginx:1.2.3@sha256:12345",
name: "foo.com:443/nginx",
tag: "1.2.3",
digest: "sha256:12345",
},
}

for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
name, tag := Split(tc.value)
name, tag, digest := Split(tc.value)
assert.Equal(t, tc.name, name)
assert.Equal(t, tc.tag, tag)
assert.Equal(t, tc.digest, digest)
})
}
}

0 comments on commit 727093f

Please sign in to comment.