Skip to content

Commit 8f49573

Browse files
Merge pull request #984 from jacobweinstock/tink-worker-image-pull
[tink worker] Don't error when image pull fails and image exists: ## Description <!--- Please describe what this PR is going to change --> HookOS recently got the capability to embed container images. With this capability, pulling an image is not desired. This is expecially true if the image name is not resolvable or there is no network connection to the registry. An image named `127.0.0.1/embedded/myimage`, for example. Currently, tink worker will always try to pull an image and will fail if the image pull fails. To allow for embedded images to function properly, when an image pull fails we check if the image already exists in the local Docker cache. If it does we don't fail the method call. ## Why is this needed <!--- Link to issue you have raised --> Fixes: # ## How Has This Been Tested? <!--- Please describe in detail how you tested your changes. --> <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> ## How are existing users impacted? What migration steps/scripts do we need? <!--- Fixes a bug, unblocks installation, removes a component of the stack etc --> <!--- Requires a DB migration script, etc. --> ## Checklist: I have: - [ ] updated the documentation and/or roadmap (if required) - [ ] added unit or e2e tests - [ ] provided instructions on how to upgrade
2 parents ca50515 + c0998f9 commit 8f49573

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

cmd/tink-worker/worker/container_manager_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,32 @@ type fakeDockerClient struct {
2626
statusCode int
2727
err error
2828
waitErr error
29+
imageInspectErr error
2930
}
3031

31-
func newFakeDockerClient(containerID, imagePullContent string, delay time.Duration, statusCode int, err, waitErr error) *fakeDockerClient {
32-
return &fakeDockerClient{
32+
type dockerClientOpt func(*fakeDockerClient)
33+
34+
func withImageInspectErr(err error) dockerClientOpt {
35+
return func(c *fakeDockerClient) {
36+
c.imageInspectErr = err
37+
}
38+
}
39+
40+
func newFakeDockerClient(containerID, imagePullContent string, delay time.Duration, statusCode int, err, waitErr error, opts ...dockerClientOpt) *fakeDockerClient {
41+
f := &fakeDockerClient{
3342
containerID: containerID,
3443
imagePullContent: imagePullContent,
3544
delay: delay,
3645
statusCode: statusCode,
3746
err: err,
3847
waitErr: waitErr,
3948
}
49+
50+
for _, opt := range opts {
51+
opt(f)
52+
}
53+
54+
return f
4055
}
4156

4257
func (c *fakeDockerClient) ContainerCreate(

cmd/tink-worker/worker/registry.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type ImagePullStatus struct {
3131
}
3232

3333
// PullImage outputs to stdout the contents of the requested image (relative to the registry).
34+
// If a pull fails but the image already exists then we will return a nil error.
3435
func (m *containerManager) PullImage(ctx context.Context, img string) error {
3536
l := m.getLogger(ctx)
3637
authConfig := registry.AuthConfig{
@@ -46,6 +47,9 @@ func (m *containerManager) PullImage(ctx context.Context, img string) error {
4647

4748
out, err := m.cli.ImagePull(ctx, path.Join(m.registryDetails.Registry, img), image.PullOptions{RegistryAuth: authStr})
4849
if err != nil {
50+
if _, _, err := m.cli.ImageInspectWithRaw(ctx, path.Join(m.registryDetails.Registry, img)); err == nil {
51+
return nil
52+
}
4953
return errors.Wrap(err, "DOCKER PULL")
5054
}
5155
defer func() {

cmd/tink-worker/worker/registry_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88
"testing"
99

10+
"github.com/docker/docker/api/types"
1011
"github.com/docker/docker/api/types/image"
1112
"github.com/go-logr/zapr"
1213
"go.uber.org/zap"
@@ -19,6 +20,10 @@ func (c *fakeDockerClient) ImagePull(context.Context, string, image.PullOptions)
1920
return io.NopCloser(strings.NewReader(c.imagePullContent)), nil
2021
}
2122

23+
func (c *fakeDockerClient) ImageInspectWithRaw(context.Context, string) (types.ImageInspect, []byte, error) {
24+
return types.ImageInspect{}, nil, c.imageInspectErr
25+
}
26+
2227
func TestContainerManagerPullImage(t *testing.T) {
2328
cases := []struct {
2429
name string
@@ -27,6 +32,7 @@ func TestContainerManagerPullImage(t *testing.T) {
2732
registry RegistryConnDetails
2833
clientErr error
2934
wantErr error
35+
imageInspectErr error
3036
}{
3137
{
3238
name: "Happy Path",
@@ -39,19 +45,27 @@ func TestContainerManagerPullImage(t *testing.T) {
3945
responseContent: "{",
4046
clientErr: errors.New("You missed the shot"),
4147
wantErr: errors.New("DOCKER PULL: You missed the shot"),
48+
imageInspectErr: errors.New("Image not in local cache"),
4249
},
4350
{
4451
name: "pull error",
4552
image: "yav.in/4/deathstar:nomedalforchewie",
4653
responseContent: `{"error": "You missed the shot"}`,
4754
wantErr: errors.New("DOCKER PULL: You missed the shot"),
55+
imageInspectErr: errors.New("Image not in local cache"),
56+
},
57+
{
58+
name: "image already exists, no error",
59+
image: "yav.in/4/deathstar:nomedalforchewie",
60+
clientErr: errors.New("You missed the shot"),
61+
wantErr: nil,
4862
},
4963
}
5064

5165
for _, tc := range cases {
5266
t.Run(tc.name, func(t *testing.T) {
5367
logger := zapr.NewLogger(zap.Must(zap.NewDevelopment()))
54-
mgr := NewContainerManager(logger, newFakeDockerClient("", tc.responseContent, 0, 0, tc.clientErr, nil), tc.registry)
68+
mgr := NewContainerManager(logger, newFakeDockerClient("", tc.responseContent, 0, 0, tc.clientErr, nil, withImageInspectErr(tc.imageInspectErr)), tc.registry)
5569

5670
ctx := context.Background()
5771
gotErr := mgr.PullImage(ctx, tc.image)

0 commit comments

Comments
 (0)