forked from moby/buildkit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
resolver.go
92 lines (77 loc) · 2.52 KB
/
resolver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package pull
import (
"context"
"net/http"
"time"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/auth"
"github.com/moby/buildkit/source"
"github.com/moby/buildkit/util/resolver"
"github.com/moby/buildkit/util/tracing"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
func NewResolver(ctx context.Context, rfn resolver.ResolveOptionsFunc, sm *session.Manager, imageStore images.Store, mode source.ResolveMode, ref string) remotes.Resolver {
opt := docker.ResolverOptions{
Client: http.DefaultClient,
}
if rfn != nil {
opt = rfn(ref)
}
opt.Credentials = getCredentialsFromSession(ctx, sm)
r := docker.NewResolver(opt)
if imageStore == nil || mode == source.ResolveModeForcePull {
return r
}
return withLocalResolver{r, imageStore, mode}
}
func getCredentialsFromSession(ctx context.Context, sm *session.Manager) func(string) (string, string, error) {
id := session.FromContext(ctx)
if id == "" {
return nil
}
return func(host string) (string, string, error) {
timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
caller, err := sm.Get(timeoutCtx, id)
if err != nil {
return "", "", err
}
return auth.CredentialsFunc(tracing.ContextWithSpanFromContext(context.TODO(), ctx), caller)(host)
}
}
// A remotes.Resolver which checks the local image store if the real
// resolver cannot find the image, essentially falling back to a local
// image if one is present.
//
// We do not override the Fetcher or Pusher methods:
//
// - Fetcher is called by github.com/containerd/containerd/remotes/:fetch()
// only after it has checked for the content locally, so avoid the
// hassle of interposing a local-fetch proxy and simply pass on the
// request.
// - Pusher wouldn't make sense to push locally, so just forward.
type withLocalResolver struct {
remotes.Resolver
is images.Store
mode source.ResolveMode
}
func (r withLocalResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) {
if r.mode == source.ResolveModePreferLocal {
if img, err := r.is.Get(ctx, ref); err == nil {
return ref, img.Target, nil
}
}
n, desc, err := r.Resolver.Resolve(ctx, ref)
if err == nil {
return n, desc, err
}
if r.mode == source.ResolveModeDefault {
if img, err := r.is.Get(ctx, ref); err == nil {
return ref, img.Target, nil
}
}
return "", ocispec.Descriptor{}, err
}