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

Commit e4fd0c8

Browse files
committed
e2e test to check build command
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
1 parent fd10e25 commit e4fd0c8

10 files changed

Lines changed: 124 additions & 5 deletions

File tree

e2e/build_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package e2e
2+
3+
import (
4+
"encoding/json"
5+
"github.com/deislabs/cnab-go/bundle"
6+
"gotest.tools/assert"
7+
"io/ioutil"
8+
"os"
9+
"path"
10+
"testing"
11+
12+
"gotest.tools/icmd"
13+
)
14+
15+
func TestBuild(t *testing.T) {
16+
cmd, cleanup := dockerCli.createTestCmd()
17+
defer cleanup()
18+
19+
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")
24+
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "--output", f)
25+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
26+
27+
data, err := ioutil.ReadFile(f)
28+
assert.NilError(t, err)
29+
var bndl bundle.Bundle
30+
err = json.Unmarshal(data, &bndl)
31+
assert.NilError(t, err)
32+
33+
built := []string { bndl.InvocationImages[0].Digest, bndl.Images["web"].Digest, bndl.Images["worker"].Digest }
34+
for _, ref := range built {
35+
cmd.Command = dockerCli.Command("inspect", ref)
36+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
37+
}
38+
}

e2e/commands_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ func TestRenderFormatters(t *testing.T) {
7575
defer cleanup()
7676

7777
appPath := filepath.Join("testdata", "simple", "simple.dockerapp")
78+
cmd.Command = dockerCli.Command("app", "build", appPath)
79+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
80+
7881
cmd.Command = dockerCli.Command("app", "render", "--formatter", "json", appPath)
7982
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
8083
golden.Assert(t, result.Stdout(), "expected-json-render.golden")

e2e/helper_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ func runWithDindSwarmAndRegistry(t *testing.T, todo func(dindSwarmAndRegistryInf
4343
// Solution found is: fix the port of the registry to be the same internally and externally
4444
// and run the dind container in the same network namespace: this way 127.0.0.1:<registry-port> both resolves to the registry from the client and from dind
4545

46-
swarm := NewContainer("docker:18.09-dind", 2375, "--insecure-registry", fmt.Sprintf("127.0.0.1:%d", registryPort))
46+
swarm := NewContainer("docker:19.03.2-dind", 2375, "--insecure-registry", fmt.Sprintf("127.0.0.1:%d", registryPort))
4747
swarm.Start(t, "--expose", strconv.FormatInt(int64(registryPort), 10),
4848
"-p", fmt.Sprintf("%d:%d", registryPort, registryPort),
49-
"-p", "2375")
49+
"-p", "2375",
50+
"-e", "DOCKER_TLS_CERTDIR=") // Disable certificate generate on DinD startup
5051
defer swarm.Stop(t)
5152

5253
registry := NewContainer("registry:2", registryPort)
@@ -76,6 +77,9 @@ func runWithDindSwarmAndRegistry(t *testing.T, todo func(dindSwarmAndRegistryInf
7677
cmd.Command = dockerCli.Command("load", "-i", tmpDir.Join("cnab-app-base.tar.gz"))
7778
icmd.RunCmd(cmd).Assert(t, icmd.Success)
7879

80+
cmd.Command = dockerCli.Command("pull", "busybox:1.30.1")
81+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
82+
7983
info := dindSwarmAndRegistryInfo{
8084
configuredCmd: cmd,
8185
registryAddress: registry.GetAddress(t),
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: "3.6"
2+
services:
3+
web:
4+
build:
5+
context: ./web
6+
worker:
7+
build:
8+
context: ./worker
9+
db:
10+
image: postgres:9.3
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 1.1.0-beta1
2+
name: simple
3+
description: "new fancy webapp with microservices"
4+
maintainers:
5+
- name: John Developer
6+
email: john.dev@example.com

e2e/testdata/build/single.dockerapp/parameters.yml

Whitespace-only changes.

e2e/testdata/build/web/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FROM scratch
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FROM scratch

internal/commands/build.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/moby/buildkit/session/auth/authprovider"
1212
"github.com/opencontainers/go-digest"
1313
"github.com/sirupsen/logrus"
14+
"io/ioutil"
1415
"os"
1516
"path/filepath"
1617
"strings"
@@ -35,6 +36,7 @@ type buildOptions struct {
3536
progress string
3637
pull bool
3738
tag string
39+
out string
3840
}
3941

4042
func buildCmd(dockerCli command.Cli) *cobra.Command {
@@ -57,7 +59,8 @@ func buildCmd(dockerCli command.Cli) *cobra.Command {
5759
flags.BoolVar(&opts.noCache, "no-cache", false, "Do not use cache when building the image")
5860
flags.StringVar(&opts.progress, "progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output")
5961
flags.BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image")
60-
cmd.Flags().StringVarP(&opts.tag, "tag", "t", "", "Name and optionally a tag in the 'name:tag' format")
62+
flags.StringVarP(&opts.out, "output", "o", "", "Dump generated bundle into a file")
63+
flags.StringVarP(&opts.tag, "tag", "t", "", "Name and optionally a tag in the 'name:tag' format")
6164

6265
return cmd
6366
}
@@ -76,6 +79,7 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
7679
}
7780

7881
ctx := appcontext.Context()
82+
7983
compose, err := bake.ParseCompose(app.Composes()[0]) // Fixme can have > 1 composes ?
8084
if err != nil {
8185
return nil, err
@@ -106,7 +110,7 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
106110
}
107111

108112
if logrus.IsLevelEnabled(logrus.DebugLevel) {
109-
dt, err := json.MarshalIndent(map[string]map[string]bake.Target{"target": targets}, "", " ")
113+
dt, err := json.MarshalIndent(targets, "", " ")
110114
if err != nil {
111115
return nil, err
112116
}
@@ -152,6 +156,13 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
152156
}
153157

154158
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+
}
155166

156167
for service, r := range resp {
157168
digest := r.ExporterResponse["containerimage.digest"]
@@ -189,8 +200,23 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
189200
digest := digest.SHA256.FromBytes(b.Bytes())
190201
ref = sha{digest}
191202
}
203+
204+
205+
if opt.out != "" {
206+
b, err := json.MarshalIndent(bundle, "", " ")
207+
if err != nil {
208+
return ref, err
209+
}
210+
if opt.out == "-" {
211+
_, err = os.Stdout.Write(b)
212+
} else {
213+
err = ioutil.WriteFile(opt.out, b, 0644)
214+
}
215+
return ref, err
216+
}
217+
192218
if err := persistInBundleStore(ref, bundle); err != nil {
193-
return nil, err
219+
return ref, err
194220
}
195221

196222
return ref, nil

internal/commands/bundle.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package commands
22

33
import (
4+
"bytes"
5+
"context"
46
"fmt"
57
"github.com/deislabs/cnab-go/bundle"
68
"github.com/docker/app/internal/packager"
@@ -10,8 +12,11 @@ import (
1012
"github.com/docker/cli/cli/command"
1113
"github.com/docker/cli/cli/config"
1214
"github.com/docker/distribution/reference"
15+
dockertypes "github.com/docker/docker/api/types"
16+
"github.com/docker/docker/pkg/jsonmessage"
1317
"github.com/pkg/errors"
1418
"github.com/sirupsen/logrus"
19+
"io/ioutil"
1520
)
1621

1722
func makeBundleFromApp(dockerCli command.Cli, app *types.App, refOverride reference.NamedTagged) (*bundle.Bundle, error) {
@@ -22,6 +27,31 @@ func makeBundleFromApp(dockerCli command.Cli, app *types.App, refOverride refere
2227
return nil, err
2328
}
2429

30+
buildContext := bytes.NewBuffer(nil)
31+
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
32+
return nil, err
33+
}
34+
35+
logrus.Debugf("Building invocation image %s", invocationImageName)
36+
buildResp, err := dockerCli.Client().ImageBuild(context.TODO(), buildContext, dockertypes.ImageBuildOptions{
37+
Dockerfile: "Dockerfile",
38+
Tags: []string{invocationImageName},
39+
BuildArgs: map[string]*string{},
40+
})
41+
if err != nil {
42+
return nil, err
43+
}
44+
defer buildResp.Body.Close()
45+
46+
if err := jsonmessage.DisplayJSONMessagesStream(buildResp.Body, ioutil.Discard, 0, false, func(jsonmessage.JSONMessage) {}); err != nil {
47+
// If the invocation image can't be found we will get an error of the form:
48+
// manifest for docker/cnab-app-base:v0.6.0-202-gbaf0b246c7 not found
49+
if err.Error() == fmt.Sprintf("manifest for %s not found", packager.BaseInvocationImage(dockerCli)) {
50+
return nil, fmt.Errorf("unable to resolve Docker App base image: %s", packager.BaseInvocationImage(dockerCli))
51+
}
52+
return nil, err
53+
}
54+
2555
return packager.ToCNAB(app, invocationImageName)
2656
}
2757

0 commit comments

Comments
 (0)