Skip to content
This repository was archived by the owner on May 4, 2021. It is now read-only.

Commit 6c559ff

Browse files
authored
Implement pulling base images by digest. (#326)
This will allow base images that are formatted like: ``` FROM gcr.io/makisu-project/makisu-alpine:v0.1.11@sha256:fc80186c3b46b19d3fc2df062250a85c95dd57380ac4fe19ad20d26358b9a3a5 ``` or ``` FROM gcr.io/makisu-project/makisu-alpine@sha256:fc80186c3b46b19d3fc2df062250a85c95dd57380ac4fe19ad20d26358b9a3a5 ``` Which allows a base image to be specified by an immutable digest instead of a, potentially floating, tag. Closes #235.
1 parent b267401 commit 6c559ff

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

lib/docker/image/image_name.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,12 @@ func (name Name) IsValid() bool {
8282

8383
// ShortName returns the name of the image without the registry information
8484
func (name Name) ShortName() string {
85-
return fmt.Sprintf("%s:%s", name.GetRepository(), name.tag)
85+
separator := ":"
86+
// If the tag contains a :, it must be a digest tag of the form <digest-algo>:<digest>. Should stringify as <repository>@<digest-algo>:<digest>
87+
if strings.Contains(name.tag, ":") {
88+
separator = "@"
89+
}
90+
return fmt.Sprintf("%s%s%s", name.GetRepository(), separator, name.tag)
8691
}
8792

8893
// String returns the full name of the image with the registry information if available
@@ -103,15 +108,33 @@ func ParseName(input string) (Name, error) {
103108

104109
slashIndex := strings.LastIndex(input, "/")
105110
sepIndex := strings.LastIndex(input, ":")
111+
digestIndex := strings.LastIndex(input, "@")
106112
if sepIndex < slashIndex || sepIndex == -1 {
107113
// <ip>:<port>/<repo>
108114
// <dns>:<port>/<repo>
109115
// <dns>/<repo>
110116
// <repo>
111117
result.repository = input
112118
result.tag = "latest"
119+
} else if digestIndex < sepIndex && digestIndex > slashIndex {
120+
result.repository = input[:digestIndex]
121+
sepIndex = strings.LastIndex(result.repository, ":")
122+
if sepIndex >= slashIndex && sepIndex != -1 {
123+
// A tag can still be specified for informational purposes if a digest is specified
124+
// <ip>:<port>/<repo>:<tag>@<digest-algo>:<digest>
125+
// <dns>:<port>/<repo>:<tag>@<digest-algo>:<digest>
126+
// <repo>:<tag>@<digest-algo>:<digest>
127+
result.repository = input[:sepIndex]
128+
}
129+
// else if no tag is specified result.repository = input[:digestIndex]
130+
// <ip>:<port>/<repo>@<digest-algo>:<digest>
131+
// <dns>:<port>/<repo>@<digest-algo>:<digest>
132+
// <repo>@<digest-algo>:<digest>
133+
134+
// When pulling by digest, the docker API expects <digest-algo>:<digest> to take the place of the tag
135+
result.tag = input[digestIndex+1:]
113136
} else {
114-
// if sepIndex >= slashIndex && sepIndex == -1
137+
// if sepIndex >= slashIndex && sepIndex != -1 && (digestIndex < slashIndex || digestIndex > sepIndex) -1)
115138
// <ip>:<port>/<repo>:<tag>
116139
// <dns>:<port>/<repo>:<tag>
117140
// <repo>:<tag>

lib/docker/image/image_name_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ func TestParseImageName(t *testing.T) {
5454
require.True(name.IsValid())
5555
require.Equal("127.0.0.1:5002/evanescence-golang-1:latest", name.String())
5656

57+
name, err = ParseNameForPull("127.0.0.1:5002/king-gizzard-golang-1@sha256:2a3dd484ecfcf9343994e0f6c2af0a6faf1af7f7e499905793643f91e90edcb3")
58+
require.NoError(err)
59+
require.Equal(name.GetRegistry(), "127.0.0.1:5002")
60+
require.Equal(name.GetRepository(), "king-gizzard-golang-1")
61+
require.Equal(name.GetTag(), "sha256:2a3dd484ecfcf9343994e0f6c2af0a6faf1af7f7e499905793643f91e90edcb3")
62+
require.True(name.IsValid())
63+
require.Equal("127.0.0.1:5002/king-gizzard-golang-1@sha256:2a3dd484ecfcf9343994e0f6c2af0a6faf1af7f7e499905793643f91e90edcb3", name.String())
64+
65+
name, err = ParseNameForPull("127.0.0.1:5002/king-gizzard-golang-1:v1.0.0@sha256:2a3dd484ecfcf9343994e0f6c2af0a6faf1af7f7e499905793643f91e90edcb3")
66+
require.NoError(err)
67+
require.Equal(name.GetRegistry(), "127.0.0.1:5002")
68+
require.Equal(name.GetRepository(), "king-gizzard-golang-1")
69+
require.Equal(name.GetTag(), "sha256:2a3dd484ecfcf9343994e0f6c2af0a6faf1af7f7e499905793643f91e90edcb3")
70+
require.True(name.IsValid())
71+
require.Equal("127.0.0.1:5002/king-gizzard-golang-1@sha256:2a3dd484ecfcf9343994e0f6c2af0a6faf1af7f7e499905793643f91e90edcb3", name.String())
72+
73+
name, err = ParseNameForPull("127.0.0.1:5002/king-gizzard-golang-1:tag-with-an-@-in-it")
74+
require.NoError(err)
75+
require.Equal(name.GetRegistry(), "127.0.0.1:5002")
76+
require.Equal(name.GetRepository(), "king-gizzard-golang-1")
77+
require.Equal(name.GetTag(), "tag-with-an-@-in-it")
78+
require.True(name.IsValid())
79+
require.Equal("127.0.0.1:5002/king-gizzard-golang-1:tag-with-an-@-in-it", name.String())
80+
5781
name, err = ParseNameForPull("docker-registry01-sjc1:5055/uber-usi/haproxy-agent:sjc1-produ-0000000027")
5882
require.NoError(err)
5983
require.Equal(name.GetRegistry(), "docker-registry01-sjc1:5055")

test/python/test_build.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ def test_build_remove(registry1, storage_dir):
3131
assert code == 0, err
3232

3333

34+
def test_build_from_sha256(registry1, storage_dir):
35+
new_image = utils.new_image_name()
36+
context_dir = os.path.join(
37+
os.getcwd(), 'testdata/build-context/from-sha256')
38+
utils.makisu_build_image(
39+
new_image, context_dir, storage_dir, registry=registry1.addr)
40+
code, err = utils.docker_run_image(registry1.addr, new_image)
41+
assert code == 0, err
42+
43+
3444
def test_build_symlink(registry1, storage_dir):
3545
new_image = utils.new_image_name()
3646
context_dir = os.path.join(
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM alpine@sha256:26a8d1303ea6109122ba2df7fafcfbe77ddc3988a2c34e818398b8ed4a20b03d
2+
3+
ENTRYPOINT ["/bin/sh", "-c", "[ \"$(cat /etc/alpine-release)\" == '3.8.4' ]"]

0 commit comments

Comments
 (0)