Skip to content

Commit 445fe77

Browse files
committed
Add "--service-images" to pull command
This allows users in a single node configuration to optionally pull down the service images defined in an app bundle with: docker app pull --service-images [your app] Fixes: fixes docker#789 Signed-off-by: Andy Doan <[email protected]>
1 parent 6d698be commit 445fe77

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

Diff for: e2e/pushpull_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,28 @@ Unable to find App "unknown": failed to resolve bundle manifest "docker.io/libra
107107
})
108108
}
109109

110+
func TestPushPullServiceImages(t *testing.T) {
111+
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
112+
cmd := info.configuredCmd
113+
ref := info.registryAddress + "/test/push-pull"
114+
tag := ":v.0.0.1"
115+
build(t, cmd, dockerCli, ref+tag, filepath.Join("testdata", "push-pull"))
116+
117+
cmd.Command = dockerCli.Command("app", "push", ref+tag)
118+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
119+
120+
// Make sure this image does not exist so that we can verify the pull works.
121+
cmd.Command = dockerCli.Command("image", "rm", "busybox:1.30.1")
122+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
123+
124+
cmd.Command = dockerCli.Command("app", "pull", "--service-images", ref+tag)
125+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
126+
127+
cmd.Command = dockerCli.Command("image", "inspect", "busybox@sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d")
128+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
129+
})
130+
}
131+
110132
func TestPushInstallBundle(t *testing.T) {
111133
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
112134
cmd := info.configuredCmd

Diff for: internal/commands/pull.go

+51-2
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,73 @@
11
package commands
22

33
import (
4+
"context"
45
"fmt"
56
"os"
67

8+
"github.com/docker/docker/api/types"
79
"github.com/docker/app/internal/cnab"
810
"github.com/docker/app/internal/packager"
911
"github.com/docker/app/internal/store"
1012
"github.com/docker/cli/cli"
1113
"github.com/docker/cli/cli/command"
1214
"github.com/docker/cli/cli/config"
1315
"github.com/docker/distribution/reference"
16+
"github.com/docker/docker/pkg/jsonmessage"
17+
"github.com/docker/docker/registry"
1418
"github.com/pkg/errors"
1519
"github.com/spf13/cobra"
1620
)
1721

22+
type pullOptions struct {
23+
serviceImages bool
24+
}
25+
1826
func pullCmd(dockerCli command.Cli) *cobra.Command {
27+
var opts pullOptions
28+
1929
cmd := &cobra.Command{
2030
Use: "pull APP_IMAGE",
2131
Short: "Pull an App image from a registry",
2232
Example: `$ docker app pull myrepo/myapp:0.1.0`,
2333
Args: cli.ExactArgs(1),
2434
RunE: func(cmd *cobra.Command, args []string) error {
25-
return runPull(dockerCli, args[0])
35+
return runPull(dockerCli, opts, args[0])
2636
},
2737
}
38+
cmd.Flags().BoolVar(&opts.serviceImages, "service-images", false, "Also pull down service images to this host's context")
2839
return cmd
2940
}
3041

31-
func runPull(dockerCli command.Cli, name string) error {
42+
func pullImage(ctx context.Context, cli command.Cli, image string) error {
43+
ref, err := reference.ParseNormalizedNamed(image)
44+
if err != nil {
45+
return err
46+
}
47+
48+
// Resolve the Repository name from fqn to RepositoryInfo
49+
repoInfo, err := registry.ParseRepositoryInfo(ref)
50+
if err != nil {
51+
return err
52+
}
53+
authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
54+
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
55+
if err != nil {
56+
return err
57+
}
58+
options := types.ImagePullOptions{
59+
RegistryAuth: encodedAuth,
60+
}
61+
responseBody, err := cli.Client().ImagePull(ctx, image, options)
62+
if err != nil {
63+
return err
64+
}
65+
defer responseBody.Close()
66+
67+
return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.Out(), cli.Out().FD(), false, nil)
68+
}
69+
70+
func runPull(dockerCli command.Cli, opts pullOptions, name string) error {
3271
appstore, err := store.NewApplicationStore(config.Dir())
3372
if err != nil {
3473
return err
@@ -52,5 +91,15 @@ func runPull(dockerCli command.Cli, name string) error {
5291
}
5392
fmt.Fprintf(os.Stdout, "Successfully pulled %q (%s) from %s\n", bndl.Name, bndl.Version, ref.String())
5493

94+
if opts.serviceImages {
95+
ctx := context.Background()
96+
for name, image := range bndl.Images {
97+
fmt.Fprintf(os.Stdout, "Pulling: %s -> %s\n", name, image.Image)
98+
if err := pullImage(ctx, dockerCli, image.Image); err != nil {
99+
return err
100+
}
101+
}
102+
}
103+
55104
return nil
56105
}

0 commit comments

Comments
 (0)