Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 9d6eb02

Browse files
committed
Bundle is not a command anymore
Code moved to packager Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
1 parent e4fd0c8 commit 9d6eb02

25 files changed

Lines changed: 300 additions & 203 deletions

File tree

Gopkg.lock

Lines changed: 8 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ required = ["github.com/wadey/gocovmerge"]
2323

2424
[[constraint]]
2525
name = "github.com/docker/buildx"
26-
revision = "96fb17b71125d4a11c904bd8a4298bac3b9e11e9"
26+
version = "=v0.3.1"
2727

2828
[[override]]
2929
name = "github.com/moby/buildkit"
30-
revision = "f238f1efb04f00bf0cc147141fda9ddb55c8bc49"
30+
version = "=v0.6.2"
3131

3232
[[override]]
3333
name = "github.com/jaguilar/vt100"

e2e/build_test.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"encoding/json"
55
"github.com/deislabs/cnab-go/bundle"
66
"gotest.tools/assert"
7+
"gotest.tools/fs"
78
"io/ioutil"
8-
"os"
99
"path"
1010
"testing"
1111

@@ -17,10 +17,9 @@ func TestBuild(t *testing.T) {
1717
defer cleanup()
1818

1919
testDir := path.Join("testdata", "build")
20-
tmp, err := ioutil.TempDir("","")
21-
assert.NilError(t, err)
22-
defer os.Remove(tmp)
23-
f := path.Join(tmp, "bundle.json")
20+
dir := fs.NewDir(t, "test-name")
21+
defer dir.Remove()
22+
f := dir.Join("bundle.json")
2423
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "--output", f)
2524
icmd.RunCmd(cmd).Assert(t, icmd.Success)
2625

internal/commands/build.go

Lines changed: 105 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8+
"github.com/deislabs/cnab-go/bundle"
89
"github.com/docker/app/internal/packager"
10+
"github.com/docker/app/types"
911
"github.com/docker/distribution/reference"
12+
"github.com/moby/buildkit/client"
1013
"github.com/moby/buildkit/session"
1114
"github.com/moby/buildkit/session/auth/authprovider"
1215
"github.com/opencontainers/go-digest"
@@ -26,7 +29,6 @@ import (
2629
_ "github.com/docker/buildx/driver/docker" // required to get default driver registered, see driver/docker/factory.go:14
2730
"github.com/docker/cli/cli"
2831
"github.com/docker/cli/cli/command"
29-
dockerclient "github.com/docker/docker/client"
3032
"github.com/moby/buildkit/util/appcontext"
3133
"github.com/spf13/cobra"
3234
)
@@ -45,7 +47,7 @@ func buildCmd(dockerCli command.Cli) *cobra.Command {
4547
Use: "build [APPLICATION]",
4648
Short: "Build service images for the application",
4749
Example: `$ docker app build myapp.dockerapp`,
48-
Args: cli.RequiresRangeArgs(1, 1),
50+
Args: cli.ExactArgs(1),
4951
RunE: func(cmd *cobra.Command, args []string) error {
5052
tag, err := runBuild(dockerCli, args[0], opts)
5153
if err == nil {
@@ -73,33 +75,20 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
7375
defer app.Cleanup()
7476
appname := app.Name
7577

76-
bundle, err := makeBundleFromApp(dockerCli, app, nil)
78+
bundle, err := packager.MakeBundleFromApp(dockerCli, app, nil)
7779
if err != nil {
7880
return nil, err
7981
}
8082

81-
ctx := appcontext.Context()
82-
83-
compose, err := bake.ParseCompose(app.Composes()[0]) // Fixme can have > 1 composes ?
83+
targets, err := parseCompose(app)
8484
if err != nil {
8585
return nil, err
8686
}
8787

88-
targets := map[string]bake.Target{}
89-
for _, n := range compose.ResolveGroup("default") {
90-
t, err := compose.ResolveTarget(n)
91-
if err != nil {
92-
return nil, err
93-
}
94-
if t != nil {
95-
targets[n] = *t
96-
}
97-
}
98-
9988
for service, t := range targets {
10089
if strings.HasPrefix(*t.Context, ".") {
10190
// Relative path in compose file under x.dockerapp refers to parent folder
102-
// FIXME docker app init should maybe udate them ?
91+
// FIXME docker app init should maybe update them ?
10392
path, err := filepath.Abs(appname + "/../" + (*t.Context)[1:])
10493
if err != nil {
10594
return nil, err
@@ -108,33 +97,19 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
10897
targets[service] = t
10998
}
11099
}
111-
112-
if logrus.IsLevelEnabled(logrus.DebugLevel) {
113-
dt, err := json.MarshalIndent(targets, "", " ")
114-
if err != nil {
115-
return nil, err
116-
}
117-
logrus.Debug(string(dt))
118-
}
100+
debugTargets(targets)
119101

120102
buildopts, err := bake.TargetsToBuildOpt(targets, opt.noCache, opt.pull)
121103
if err != nil {
122104
return nil, err
123105
}
124106

125-
buildContext := bytes.NewBuffer(nil)
126-
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
107+
buildopts["invocation-image"], err = createInvocationImageBuildOptions(dockerCli, app)
108+
if err != nil {
127109
return nil, err
128110
}
129111

130-
buildopts["invocation-image"] = build.Options{
131-
Inputs: build.Inputs{
132-
InStream: buildContext,
133-
ContextPath: "-",
134-
},
135-
Session: []session.Attachable{authprovider.NewDockerAuthProvider(os.Stderr)},
136-
}
137-
112+
ctx := appcontext.Context()
138113
d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client(), nil, "", nil)
139114
if err != nil {
140115
return nil, err
@@ -146,23 +121,19 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
146121
},
147122
}
148123

149-
ctx2, cancel := context.WithCancel(context.TODO())
124+
ctx2, cancel := context.WithCancel(ctx)
150125
defer cancel()
151126

152127
pw := progress.NewPrinter(ctx2, os.Stderr, opt.progress)
153-
resp, err := build.Build(ctx2, driverInfo, buildopts, dockerAPI(dockerCli), dockerCli.ConfigFile(), pw)
128+
129+
// We rely on buildx "docker" builder integrated in docker engine, so don't nee a DockerAPI here
130+
resp, err := build.Build(ctx2, driverInfo, buildopts, nil, dockerCli.ConfigFile(), pw)
154131
if err != nil {
155132
return nil, err
156133
}
157134

158135
fmt.Println("Successfully built service images")
159-
if logrus.IsLevelEnabled(logrus.DebugLevel) {
160-
dt, err := json.MarshalIndent(resp, "", " ")
161-
if err != nil {
162-
return nil, err
163-
}
164-
logrus.Debug(string(dt))
165-
}
136+
debugSolveResponses(resp)
166137

167138
for service, r := range resp {
168139
digest := r.ExporterResponse["containerimage.digest"]
@@ -175,33 +146,21 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
175146
image.Digest = digest
176147
bundle.Images[service] = image
177148
}
178-
fmt.Printf(" - %s : %s\n", service, digest)
179-
}
180-
181-
if logrus.IsLevelEnabled(logrus.DebugLevel) {
182-
dt, err := json.MarshalIndent(resp, "", " ")
183-
if err != nil {
184-
return nil, err
185-
}
186-
logrus.Debug(string(dt))
149+
fmt.Fprintf(dockerCli.Out(), " - %s : %s\n", service, digest)
187150
}
151+
debugBundle(bundle)
188152

189153
var ref reference.Named
190-
ref, err = getNamedTagged(opt.tag)
154+
ref, err = packager.GetNamedTagged(opt.tag)
191155
if err != nil {
192156
return nil, err
193157
}
194158
if ref == nil {
195-
b := bytes.Buffer{}
196-
_, err := bundle.WriteTo(&b)
197-
if err != nil {
159+
if ref, err = computeDigest(bundle); err != nil {
198160
return nil, err
199161
}
200-
digest := digest.SHA256.FromBytes(b.Bytes())
201-
ref = sha{digest}
202162
}
203163

204-
205164
if opt.out != "" {
206165
b, err := json.MarshalIndent(bundle, "", " ")
207166
if err != nil {
@@ -215,45 +174,110 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
215174
return ref, err
216175
}
217176

218-
if err := persistInBundleStore(ref, bundle); err != nil {
177+
if err := packager.PersistInBundleStore(ref, bundle); err != nil {
219178
return ref, err
220179
}
221180

222181
return ref, nil
223182
}
224183

225-
type sha struct {
226-
d digest.Digest
184+
func computeDigest(bundle *bundle.Bundle) (reference.Named, error) {
185+
b := bytes.Buffer{}
186+
_, err := bundle.WriteTo(&b)
187+
if err != nil {
188+
return nil, err
189+
}
190+
digest := digest.SHA256.FromBytes(b.Bytes())
191+
ref := sha{digest}
192+
return ref, nil
227193
}
228194

229-
func (s sha) Digest() digest.Digest {
230-
return s.d
195+
func createInvocationImageBuildOptions(dockerCli command.Cli, app *types.App) (build.Options, error) {
196+
buildContext := bytes.NewBuffer(nil)
197+
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
198+
return build.Options{}, err
199+
}
200+
return build.Options{
201+
Inputs: build.Inputs{
202+
InStream: buildContext,
203+
ContextPath: "-",
204+
},
205+
Session: []session.Attachable{authprovider.NewDockerAuthProvider(os.Stderr)},
206+
}, nil
231207
}
232208

233-
func (s sha) String() string {
234-
return s.d.String()
209+
func debugTargets(targets map[string]bake.Target) {
210+
if logrus.IsLevelEnabled(logrus.DebugLevel) {
211+
dt, err := json.MarshalIndent(targets, "", " ")
212+
if err != nil {
213+
logrus.Debugf("Failed to marshal Buildx response: %s", err.Error())
214+
} else {
215+
logrus.Debug(string(dt))
216+
}
217+
}
235218
}
236219

237-
func (s sha) Name() string {
238-
return s.d.String()
220+
func debugBundle(bundle *bundle.Bundle) {
221+
if logrus.IsLevelEnabled(logrus.DebugLevel) {
222+
dt, err := json.MarshalIndent(bundle, "", " ")
223+
if err != nil {
224+
logrus.Debugf("Failed to marshal Bundle: %s", err.Error())
225+
} else {
226+
logrus.Debug(string(dt))
227+
}
228+
}
239229
}
240230

231+
func debugSolveResponses(resp map[string]*client.SolveResponse) {
232+
if logrus.IsLevelEnabled(logrus.DebugLevel) {
233+
dt, err := json.MarshalIndent(resp, "", " ")
234+
if err != nil {
235+
logrus.Debugf("Failed to marshal Buildx response: %s", err.Error())
236+
} else {
237+
logrus.Debug(string(dt))
238+
}
239+
}
240+
}
241+
242+
// parseCompose do parse app compose file and extract buildx targets
243+
func parseCompose(app *types.App) (map[string]bake.Target, error) {
244+
compose, err := bake.ParseCompose(app.Composes()[0])
245+
// Fixme can have > 1 composes ?
246+
if err != nil {
247+
return nil, err
248+
}
249+
targets := map[string]bake.Target{}
250+
for _, n := range compose.ResolveGroup("default") {
251+
t, err := compose.ResolveTarget(n)
252+
if err != nil {
253+
return nil, err
254+
}
255+
if t != nil {
256+
targets[n] = *t
257+
}
258+
}
259+
return targets, nil
260+
}
261+
262+
263+
type sha struct {
264+
d digest.Digest
265+
}
241266
var _ reference.Named = sha{""}
242267
var _ reference.Digested = sha{""}
243268

244-
245-
/// FIXME copy from vendor/github.com/docker/buildx/commands/util.go:318 could probably be made public
246-
func dockerAPI(dockerCli command.Cli) *api {
247-
return &api{dockerCli: dockerCli}
269+
// Digest implement Digested.Digest()
270+
func (s sha) Digest() digest.Digest {
271+
return s.d
248272
}
249273

250-
type api struct {
251-
dockerCli command.Cli
274+
// Digest implement Named.String()
275+
func (s sha) String() string {
276+
return s.d.String()
252277
}
253278

254-
func (a *api) DockerAPI(name string) (dockerclient.APIClient, error) {
255-
if name == "" {
256-
name = a.dockerCli.CurrentContext()
257-
}
258-
return nil, fmt.Errorf("Only support default context in this prototype")
279+
// Digest implement Named.Name()
280+
func (s sha) Name() string {
281+
return s.d.String()
259282
}
283+

internal/commands/cnab.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func extractAndLoadAppBasedBundle(dockerCli command.Cli, name string) (*bundle.B
239239
return nil, "", err
240240
}
241241
defer app.Cleanup()
242-
bndl, err := makeBundleFromApp(dockerCli, app, nil)
242+
bndl, err := packager.MakeBundleFromApp(dockerCli, app, nil)
243243
return bndl, "", err
244244
}
245245

0 commit comments

Comments
 (0)