@@ -2,49 +2,39 @@ package exporter
2
2
3
3
import (
4
4
"context"
5
- "fmt"
6
5
"strings"
7
6
8
- distref "github.com/distribution/reference"
7
+ "github.com/containerd/log"
8
+ "github.com/distribution/reference"
9
9
"github.com/docker/docker/builder/builder-next/exporter/overrides"
10
- "github.com/docker/docker/image"
11
10
"github.com/moby/buildkit/exporter"
12
11
"github.com/moby/buildkit/exporter/containerimage/exptypes"
13
- "github.com/moby/buildkit/util/progress"
12
+
14
13
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
15
14
)
16
15
17
- // Opt are options for the exporter wrapper.
18
- type Opt struct {
19
- // Callbacks contains callbacks used by the image exporter.
20
- Callbacks BuildkitCallbacks
21
-
22
- // ImageTagger is used to tag the image after it is exported.
23
- ImageTagger ImageTagger
24
- }
25
-
26
16
type BuildkitCallbacks struct {
27
17
// Exported is a Called when an image is exported by buildkit.
28
18
Exported func (ctx context.Context , id string , desc ocispec.Descriptor )
29
- }
30
19
31
- type ImageTagger interface {
32
- TagImage (ctx context.Context , imageID image.ID , newTag distref.Named ) error
20
+ // Named is a callback that is called when an image is created in the
21
+ // containerd image store by buildkit.
22
+ Named func (ctx context.Context , ref reference.NamedTagged , desc ocispec.Descriptor )
33
23
}
34
24
35
25
// Wraps the containerimage exporter's Resolve method to apply moby-specific
36
26
// overrides to the exporter attributes.
37
27
type imageExporterMobyWrapper struct {
38
- exp exporter.Exporter
39
- opt Opt
28
+ exp exporter.Exporter
29
+ callbacks BuildkitCallbacks
40
30
}
41
31
42
32
// NewWrapper returns an exporter wrapper that applies moby specific attributes
43
33
// and hooks the export process.
44
- func NewWrapper (exp exporter.Exporter , opt Opt ) (exporter.Exporter , error ) {
34
+ func NewWrapper (exp exporter.Exporter , callbacks BuildkitCallbacks ) (exporter.Exporter , error ) {
45
35
return & imageExporterMobyWrapper {
46
- exp : exp ,
47
- opt : opt ,
36
+ exp : exp ,
37
+ callbacks : callbacks ,
48
38
}, nil
49
39
}
50
40
@@ -57,9 +47,7 @@ func (e *imageExporterMobyWrapper) Resolve(ctx context.Context, id int, exporter
57
47
if err != nil {
58
48
return nil , err
59
49
}
60
-
61
- // Force the exporter to not use a name so it always creates a dangling image.
62
- exporterAttrs [string (exptypes .OptKeyName )] = ""
50
+ exporterAttrs [string (exptypes .OptKeyName )] = strings .Join (reposAndTags , "," )
63
51
exporterAttrs [string (exptypes .OptKeyUnpack )] = "true"
64
52
if _ , has := exporterAttrs [string (exptypes .OptKeyDanglingPrefix )]; ! has {
65
53
exporterAttrs [string (exptypes .OptKeyDanglingPrefix )] = "moby-dangling"
@@ -73,15 +61,13 @@ func (e *imageExporterMobyWrapper) Resolve(ctx context.Context, id int, exporter
73
61
74
62
return & imageExporterInstanceWrapper {
75
63
ExporterInstance : inst ,
76
- reposAndTags : reposAndTags ,
77
- opt : e .opt ,
64
+ callbacks : e .callbacks ,
78
65
}, nil
79
66
}
80
67
81
68
type imageExporterInstanceWrapper struct {
82
69
exporter.ExporterInstance
83
- reposAndTags []string
84
- opt Opt
70
+ callbacks BuildkitCallbacks
85
71
}
86
72
87
73
func (i * imageExporterInstanceWrapper ) Export (ctx context.Context , src * exporter.Source , inlineCache exptypes.InlineCache , sessionID string ) (map [string ]string , exporter.DescriptorReference , error ) {
@@ -92,31 +78,38 @@ func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter
92
78
93
79
desc := ref .Descriptor ()
94
80
imageID := out [exptypes .ExporterImageDigestKey ]
95
- if i .opt .Callbacks .Exported != nil {
96
- i .opt .Callbacks .Exported (ctx , imageID , desc )
81
+ if i .callbacks .Exported != nil {
82
+ i .callbacks .Exported (ctx , imageID , desc )
83
+ }
84
+
85
+ if i .callbacks .Named != nil {
86
+ i .processNamedCallback (ctx , out , desc )
97
87
}
98
88
99
- err = i .processNamed (ctx , image .ID (imageID ), out , desc )
100
- return out , ref , err
89
+ return out , ref , nil
101
90
}
102
91
103
- func (i * imageExporterInstanceWrapper ) processNamed (ctx context.Context , imageID image.ID , out map [string ]string , desc ocispec.Descriptor ) error {
104
- if len (i .reposAndTags ) == 0 {
105
- return nil
92
+ func (i * imageExporterInstanceWrapper ) processNamedCallback (ctx context.Context , out map [string ]string , desc ocispec.Descriptor ) {
93
+ // TODO(vvoland): Change to exptypes.ExporterImageNameKey when BuildKit v0.21 is vendored.
94
+ imageName := out ["image.name" ]
95
+ if imageName == "" {
96
+ log .G (ctx ).Warn ("image named with empty image.name produced by buildkit" )
97
+ return
106
98
}
107
99
108
- for _ , repoAndTag := range i . reposAndTags {
109
- newTag , err := distref . ParseNamed ( repoAndTag )
100
+ for _ , name := range strings . Split ( imageName , "," ) {
101
+ ref , err := reference . ParseNormalizedNamed ( name )
110
102
if err != nil {
111
- return err
103
+ // Shouldn't happen, but log if it does and continue.
104
+ log .G (ctx ).WithFields (log.Fields {
105
+ "name" : name ,
106
+ "error" : err ,
107
+ }).Warn ("image named with invalid reference produced by buildkit" )
108
+ continue
112
109
}
113
110
114
- done := progress .OneOff (ctx , fmt .Sprintf ("naming to %s" , newTag ))
115
- if err := i .opt .ImageTagger .TagImage (ctx , imageID , newTag ); err != nil {
116
- return done (err )
111
+ if namedTagged , ok := reference .TagNameOnly (ref ).(reference.NamedTagged ); ok {
112
+ i .callbacks .Named (ctx , namedTagged , desc )
117
113
}
118
- done (nil )
119
114
}
120
- out [exptypes .ExporterImageNameKey ] = strings .Join (i .reposAndTags , "," )
121
- return nil
122
115
}
0 commit comments