11package commands
22
33import (
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+
1826func 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,13 @@ 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+ pullImage (ctx , dockerCli , image .Image )
99+ }
100+ }
101+
55102 return nil
56103}
0 commit comments