Skip to content

Commit 410ada9

Browse files
committed
feat(image): introduce WithCredentials* to select how pull credentials are retrieved
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 461793d commit 410ada9

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

image/options.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package image
22

33
import (
44
"errors"
5+
"fmt"
56
"io"
67

78
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
89

910
"github.com/docker/docker/api/types/build"
1011
"github.com/docker/docker/api/types/image"
1112
"github.com/docker/go-sdk/client"
13+
"github.com/docker/go-sdk/config"
1214
)
1315

1416
// BuildOption is a function that configures the build options.
@@ -40,9 +42,39 @@ func WithBuildOptions(options build.ImageBuildOptions) BuildOption {
4042
type PullOption func(*pullOptions) error
4143

4244
type pullOptions struct {
43-
client client.SDKClient
44-
pullOptions image.PullOptions
45-
pullHandler func(r io.ReadCloser) error
45+
client client.SDKClient
46+
pullOptions image.PullOptions
47+
pullHandler func(r io.ReadCloser) error
48+
credentialsFn func(string) (string, string, error)
49+
}
50+
51+
// WithCredentialsFn sets the function to retrieve credentials for an image to be pulled
52+
func WithCredentialsFn(credentialsFn func(string) (string, string, error)) PullOption {
53+
return func(opts *pullOptions) error {
54+
opts.credentialsFn = credentialsFn
55+
return nil
56+
}
57+
}
58+
59+
// WithCredentialsFromConfig configures pull to retrieve credentials from the CLI config
60+
func WithCredentialsFromConfig(opts *pullOptions) error {
61+
opts.credentialsFn = func(imageName string) (string, string, error) {
62+
authConfigs, err := config.AuthConfigs(imageName)
63+
if err != nil {
64+
return "", "", err
65+
}
66+
67+
// there must be only one auth config for the image
68+
if len(authConfigs) > 1 {
69+
return "", "", fmt.Errorf("multiple auth configs found for image %s, expected only one", imageName)
70+
}
71+
72+
for _, ac := range authConfigs {
73+
return ac.Username, ac.Password, nil
74+
}
75+
return "", "", nil
76+
}
77+
return nil
4678
}
4779

4880
// WithPullClient sets the pull client used to pull the image.

image/pull.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,37 +46,35 @@ func Pull(ctx context.Context, imageName string, opts ...PullOption) error {
4646
pullOpts.client = sdk
4747
}
4848

49+
if pullOpts.credentialsFn == nil {
50+
if err := WithCredentialsFromConfig(pullOpts); err != nil {
51+
return fmt.Errorf("set credentials for pull option: %w", err)
52+
}
53+
}
54+
4955
if imageName == "" {
5056
return errors.New("image name is not set")
5157
}
5258

53-
authConfigs, err := config.AuthConfigs(imageName)
59+
username, password, err := pullOpts.credentialsFn(imageName)
5460
if err != nil {
55-
pullOpts.client.Logger().Warn("failed to get image auth, setting empty credentials for the image", "image", imageName, "error", err)
56-
} else {
57-
// there must be only one auth config for the image
58-
if len(authConfigs) > 1 {
59-
return fmt.Errorf("multiple auth configs found for image %s, expected only one", imageName)
60-
}
61-
62-
var tmp config.AuthConfig
63-
for _, ac := range authConfigs {
64-
tmp = ac
65-
}
61+
return fmt.Errorf("failed to retrieve registry credentials for %s: %w", imageName, err)
62+
}
6663

67-
authConfig := config.AuthConfig{
68-
Username: tmp.Username,
69-
Password: tmp.Password,
70-
}
71-
encodedJSON, err := json.Marshal(authConfig)
72-
if err != nil {
73-
pullOpts.client.Logger().Warn("failed to marshal image auth, setting empty credentials for the image", "image", imageName, "error", err)
74-
} else {
75-
pullOpts.pullOptions.RegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON)
76-
}
64+
authConfig := config.AuthConfig{
65+
Username: username,
66+
Password: password,
67+
}
68+
encodedJSON, err := json.Marshal(authConfig)
69+
if err != nil {
70+
pullOpts.client.Logger().Warn("failed to marshal image auth, setting empty credentials for the image", "image", imageName, "error", err)
71+
} else {
72+
pullOpts.pullOptions.RegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON)
7773
}
7874

79-
var pull io.ReadCloser
75+
var (
76+
pull io.ReadCloser
77+
)
8078
err = backoff.RetryNotify(
8179
func() error {
8280
pull, err = pullOpts.client.ImagePull(ctx, imageName, pullOpts.pullOptions)

0 commit comments

Comments
 (0)