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

Commit 3b9a6e3

Browse files
committed
Support using bundles both by Named reference and raw ID
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 58e773c commit 3b9a6e3

File tree

16 files changed

+296
-173
lines changed

16 files changed

+296
-173
lines changed

e2e/build_test.go

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,43 @@ func TestBuild(t *testing.T) {
1717
cmd := info.configuredCmd
1818

1919
testDir := path.Join("testdata", "build")
20-
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "single:1.0.0")
20+
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "--tag", "single:1.0.0")
2121
icmd.RunCmd(cmd).Assert(t, icmd.Success)
2222

23-
var cfg string
24-
for _, s := range cmd.Env {
25-
if strings.HasPrefix(s, "DOCKER_CONFIG=") {
26-
cfg = s[14:]
27-
}
28-
}
29-
if cfg == "" {
30-
t.Fatalf("Failed to retrieve docker config folder")
23+
cfg := getDockerConfigDir(t, cmd)
24+
25+
f := path.Join(cfg, "app", "bundles", "docker.io", "library", "single", "_tags", "1.0.0", "bundle.json")
26+
data, err := ioutil.ReadFile(f)
27+
assert.NilError(t, err)
28+
var bndl bundle.Bundle
29+
err = json.Unmarshal(data, &bndl)
30+
assert.NilError(t, err)
31+
32+
built := []string{bndl.InvocationImages[0].Digest, bndl.Images["web"].Digest, bndl.Images["worker"].Digest}
33+
for _, ref := range built {
34+
cmd.Command = dockerCli.Command("inspect", ref)
35+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
3136
}
37+
})
38+
}
39+
40+
func TestBuildWithoutTag(t *testing.T) {
41+
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
42+
cmd := info.configuredCmd
43+
44+
testDir := path.Join("testdata", "build")
45+
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"))
46+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
3247

33-
f := path.Join(cfg, "app", "bundles", "docker.io", "library", "single", "_tags", "1.0.0.json")
48+
cfg := getDockerConfigDir(t, cmd)
49+
50+
f := path.Join(cfg, "app", "bundles", "_ids")
51+
infos, err := ioutil.ReadDir(f)
52+
assert.NilError(t, err)
53+
assert.Equal(t, len(infos), 1)
54+
id := infos[0].Name()
55+
56+
f = path.Join(cfg, "app", "bundles", "_ids", id, "bundle.json")
3457
data, err := ioutil.ReadFile(f)
3558
assert.NilError(t, err)
3659
var bndl bundle.Bundle
@@ -44,3 +67,16 @@ func TestBuild(t *testing.T) {
4467
}
4568
})
4669
}
70+
71+
func getDockerConfigDir(t *testing.T, cmd icmd.Cmd) string {
72+
var cfg string
73+
for _, s := range cmd.Env {
74+
if strings.HasPrefix(s, "DOCKER_CONFIG=") {
75+
cfg = s[14:]
76+
}
77+
}
78+
if cfg == "" {
79+
t.Fatalf("Failed to retrieve docker config folder")
80+
}
81+
return cfg
82+
}

e2e/commands_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestRenderFormatters(t *testing.T) {
7575
cmd := info.configuredCmd
7676

7777
appPath := filepath.Join("testdata", "simple", "simple.dockerapp")
78-
cmd.Command = dockerCli.Command("app", "build", appPath, "a-simple-tag")
78+
cmd.Command = dockerCli.Command("app", "build", appPath, "--tag", "a-simple-tag")
7979
icmd.RunCmd(cmd).Assert(t, icmd.Success)
8080

8181
cmd.Command = dockerCli.Command("app", "render", "--formatter", "json", appPath)
@@ -161,10 +161,10 @@ func TestInspectApp(t *testing.T) {
161161
cmd.Dir = dir.Path()
162162
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
163163
ExitCode: 1,
164-
Err: "invalid reference format",
164+
Err: "could not parse '' as a valid reference",
165165
})
166166

167-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "simple-app:1.0.0")
167+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "simple-app:1.0.0")
168168
cmd.Dir = ""
169169
icmd.RunCmd(cmd).Assert(t, icmd.Success)
170170

e2e/images_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import (
1212

1313
func insertBundles(t *testing.T, cmd icmd.Cmd, info dindSwarmAndRegistryInfo) {
1414
// Push an application so that we can later pull it by digest
15-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), info.registryAddress+"/c-myapp")
15+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "--tag", info.registryAddress+"/c-myapp")
1616
icmd.RunCmd(cmd).Assert(t, icmd.Success)
17-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "b-simple-app")
17+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "b-simple-app")
1818
icmd.RunCmd(cmd).Assert(t, icmd.Success)
19-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "a-simple-app")
19+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "a-simple-app")
2020
icmd.RunCmd(cmd).Assert(t, icmd.Success)
2121
}
2222

@@ -86,7 +86,7 @@ func TestImageTag(t *testing.T) {
8686
}
8787

8888
// given a first available image
89-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "a-simple-app")
89+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "a-simple-app")
9090
icmd.RunCmd(cmd).Assert(t, icmd.Success)
9191

9292
singleImageExpectation := `APP IMAGE APP NAME
@@ -112,14 +112,14 @@ a-simple-app:latest simple
112112
dockerAppImageTag("a-simple-app$2", "b-simple-app")
113113
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
114114
ExitCode: 1,
115-
Err: `could not parse 'a-simple-app$2' as a valid reference: invalid reference format`,
115+
Err: `could not parse 'a-simple-app$2' as a valid reference`,
116116
})
117117

118118
// with invalid target reference
119119
dockerAppImageTag("a-simple-app", "b@simple-app")
120120
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
121121
ExitCode: 1,
122-
Err: `could not parse 'b@simple-app' as a valid reference: invalid reference format`,
122+
Err: `could not parse 'b@simple-app' as a valid reference`,
123123
})
124124

125125
// with unexisting source image
@@ -175,7 +175,7 @@ c-simple-app:latest simple
175175
`)
176176

177177
// given a new application
178-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "push-pull")
178+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "--tag", "push-pull")
179179
icmd.RunCmd(cmd).Assert(t, icmd.Success)
180180
expectImageListOutput(t, cmd, `APP IMAGE APP NAME
181181
a-simple-app:0.1 simple

e2e/pushpull_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func TestPushInstallBundle(t *testing.T) {
195195
ref := info.registryAddress + "/test/push-bundle"
196196

197197
// render the app to a bundle, we use the app from the push pull test above.
198-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "a-simple-app:1.0.0")
198+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "--tag", "a-simple-app:1.0.0")
199199
icmd.RunCmd(cmd).Assert(t, icmd.Success)
200200

201201
// push it and install to check it is available
@@ -243,7 +243,7 @@ func TestPushInstallBundle(t *testing.T) {
243243
cmdIsolatedStore.Env = append(cmdIsolatedStore.Env, "DOCKER_CONTEXT=swarm-context")
244244

245245
// bundle the app again but this time with a tag to store it into the bundle store
246-
cmdIsolatedStore.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), ref2)
246+
cmdIsolatedStore.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "--tag", ref2)
247247
icmd.RunCmd(cmdIsolatedStore).Assert(t, icmd.Success)
248248
// Push the app without tagging it explicitly
249249
cmdIsolatedStore.Command = dockerCli.Command("app", "push", ref2)

internal/commands/build/build.go

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,14 @@ type buildOptions struct {
3939
func Cmd(dockerCli command.Cli) *cobra.Command {
4040
var opts buildOptions
4141
cmd := &cobra.Command{
42-
Use: "build [APP_NAME] [APP_IMAGE]",
42+
Use: "build [APP_NAME] [OPTIONS]",
4343
Short: "Build service images for the application",
44-
Example: `$ docker app build myapp.dockerapp my/app:1.0.0`,
45-
Args: cli.ExactArgs(2),
44+
Example: `$ docker app build myapp.dockerapp --tag my/app:1.0.0`,
45+
Args: cli.ExactArgs(1),
4646
RunE: func(cmd *cobra.Command, args []string) error {
47-
opts.tag = args[1]
48-
tag, err := runBuild(dockerCli, args[0], opts)
47+
ref, err := runBuild(dockerCli, args[0], opts)
4948
if err == nil {
50-
fmt.Printf("Successfully build %s\n", tag.String())
49+
fmt.Printf("Successfully build %s\n", ref.String())
5150
}
5251
return err
5352
},
@@ -56,23 +55,19 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
5655
flags := cmd.Flags()
5756
flags.BoolVar(&opts.noCache, "no-cache", false, "Do not use cache when building the image")
5857
flags.StringVar(&opts.progress, "progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output")
58+
flags.StringVarP(&opts.tag, "tag", "t", "", "Application image and optionally a tag in the 'image:tag' format")
5959
flags.BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image")
6060

6161
return cmd
6262
}
6363

64-
func runBuild(dockerCli command.Cli, application string, opt buildOptions) (reference.Named, error) {
64+
func runBuild(dockerCli command.Cli, application string, opt buildOptions) (reference.Reference, error) {
6565
err := checkMinimalEngineVersion(dockerCli)
6666
if err != nil {
6767
return nil, err
6868
}
6969

70-
if opt.tag == "" {
71-
// FIXME temporary, until we get support for Digest in bundleStore and other commands
72-
return nil, fmt.Errorf("A tag is required to run docker app build")
73-
}
74-
75-
var ref reference.Named
70+
var ref reference.Reference
7671
ref, err = packager.GetNamedTagged(opt.tag)
7772
if err != nil {
7873
return nil, err
@@ -128,16 +123,7 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
128123
return nil, err
129124
}
130125

131-
if ref == nil {
132-
if ref, err = computeDigest(bundle); err != nil {
133-
return nil, err
134-
}
135-
}
136-
137-
if err = packager.PersistInBundleStore(ref, bundle); err != nil {
138-
return nil, err
139-
}
140-
return ref, nil
126+
return packager.PersistInBundleStore(ref, bundle)
141127
}
142128

143129
func checkMinimalEngineVersion(dockerCli command.Cli) error {

internal/commands/build/digest.go

Lines changed: 0 additions & 43 deletions
This file was deleted.

internal/commands/cnab.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/deislabs/cnab-go/driver"
1818
dockerDriver "github.com/deislabs/cnab-go/driver/docker"
1919
"github.com/docker/app/internal"
20+
"github.com/docker/app/internal/commands/image"
2021
"github.com/docker/app/internal/log"
2122
"github.com/docker/app/internal/packager"
2223
appstore "github.com/docker/app/internal/store"
@@ -283,25 +284,24 @@ func resolveBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name
283284
return nil, "", fmt.Errorf("could not resolve bundle %q", name)
284285
}
285286

286-
func getBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name string) (*bundle.Bundle, reference.Named, error) {
287-
ref, err := reference.ParseNormalizedNamed(name)
287+
func getBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name string) (*bundle.Bundle, reference.Reference, error) {
288+
ref, err := image.StringToRef(name)
288289
if err != nil {
289-
return nil, nil, errors.Wrap(err, name)
290+
return nil, nil, err
290291
}
291-
tagRef := reference.TagNameOnly(ref)
292-
293-
bndl, err := bundleStore.Read(tagRef)
292+
bndl, err := bundleStore.Read(ref)
294293
if err != nil {
295-
fmt.Fprintf(dockerCli.Err(), "Unable to find application image %q locally\n", reference.FamiliarString(tagRef))
294+
fmt.Fprintf(dockerCli.Err(), "Unable to find application image %q locally\n", reference.FamiliarString(ref))
296295

297-
bndl, err = pullBundle(dockerCli, bundleStore, tagRef)
298-
if err != nil {
299-
return nil, nil, err
296+
if named, ok := ref.(reference.Named); ok {
297+
bndl, err = pullBundle(dockerCli, bundleStore, named)
298+
if err != nil {
299+
return nil, nil, err
300+
}
300301
}
301-
return bndl, tagRef, nil
302302
}
303303

304-
return bndl, tagRef, nil
304+
return bndl, ref, nil
305305
}
306306

307307
func pullBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, tagRef reference.Named) (*bundle.Bundle, error) {
@@ -314,7 +314,7 @@ func pullBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, tagRef
314314
if err != nil {
315315
return nil, err
316316
}
317-
if err := bundleStore.Store(tagRef, bndl); err != nil {
317+
if _, err := bundleStore.Store(tagRef, bndl); err != nil {
318318
return nil, err
319319
}
320320
return bndl, nil

internal/commands/image/list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func runList(dockerCli command.Cli, bundleStore store.BundleStore) error {
5151
return printImages(dockerCli, pkgs)
5252
}
5353

54-
func getPackages(bundleStore store.BundleStore, references []reference.Named) ([]pkg, error) {
54+
func getPackages(bundleStore store.BundleStore, references []reference.Reference) ([]pkg, error) {
5555
packages := make([]pkg, len(references))
5656
for i, ref := range references {
5757
b, err := bundleStore.Read(ref)
@@ -112,6 +112,6 @@ var (
112112
)
113113

114114
type pkg struct {
115-
ref reference.Named
115+
ref reference.Reference
116116
bundle *bundle.Bundle
117117
}

internal/commands/image/rm.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,15 @@ $ docker app image rm docker.io/library/myapp@sha256:beef...`,
4747
}
4848

4949
func runRm(bundleStore store.BundleStore, app string) error {
50-
ref, err := reference.ParseNormalizedNamed(app)
50+
ref, err := StringToRef(app)
5151
if err != nil {
5252
return err
5353
}
5454

55-
tagged := reference.TagNameOnly(ref)
56-
if err := bundleStore.Remove(tagged); err != nil {
55+
if err := bundleStore.Remove(ref); err != nil {
5756
return err
5857
}
5958

60-
fmt.Println("Deleted: " + reference.FamiliarString(tagged))
59+
fmt.Println("Deleted: " + reference.FamiliarString(ref))
6160
return nil
6261
}

internal/commands/image/tag.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func runTag(bundleStore store.BundleStore, srcAppImage, destAppImage string) err
4444
}
4545

4646
func readBundle(name string, bundleStore store.BundleStore) (*bundle.Bundle, error) {
47-
cnabRef, err := stringToRef(name)
47+
cnabRef, err := StringToRef(name)
4848
if err != nil {
4949
return nil, err
5050
}
@@ -57,19 +57,17 @@ func readBundle(name string, bundleStore store.BundleStore) (*bundle.Bundle, err
5757
}
5858

5959
func storeBundle(bundle *bundle.Bundle, name string, bundleStore store.BundleStore) error {
60-
cnabRef, err := stringToRef(name)
60+
cnabRef, err := StringToRef(name)
6161
if err != nil {
6262
return err
6363
}
64-
65-
return bundleStore.Store(cnabRef, bundle)
64+
_, err = bundleStore.Store(cnabRef, bundle)
65+
return err
6666
}
6767

68-
func stringToRef(name string) (reference.Named, error) {
69-
cnabRef, err := reference.ParseNormalizedNamed(name)
70-
if err != nil {
71-
return nil, fmt.Errorf("could not parse '%s' as a valid reference: %v", name, err)
68+
func StringToRef(s string) (reference.Reference, error) {
69+
if named, err := reference.ParseNormalizedNamed(s); err == nil {
70+
return reference.TagNameOnly(named), nil
7271
}
73-
74-
return reference.TagNameOnly(cnabRef), nil
72+
return store.FromString(s)
7573
}

0 commit comments

Comments
 (0)