@@ -2,9 +2,11 @@ package swarm
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67
78 "github.com/docker/cli/cli/command"
9+ servicecli "github.com/docker/cli/cli/command/service"
810 "github.com/docker/cli/cli/command/stack/options"
911 "github.com/docker/cli/cli/compose/convert"
1012 composetypes "github.com/docker/cli/cli/compose/types"
@@ -13,10 +15,9 @@ import (
1315 "github.com/docker/docker/api/types/swarm"
1416 apiclient "github.com/docker/docker/client"
1517 "github.com/docker/docker/errdefs"
16- "github.com/pkg/errors"
1718)
1819
19- func deployCompose (ctx context.Context , dockerCli command.Cli , opts options.Deploy , config * composetypes.Config ) error {
20+ func deployCompose (ctx context.Context , dockerCli command.Cli , opts * options.Deploy , config * composetypes.Config ) error {
2021 if err := checkDaemonIsSwarmManager (ctx , dockerCli ); err != nil {
2122 return err
2223 }
@@ -60,7 +61,17 @@ func deployCompose(ctx context.Context, dockerCli command.Cli, opts options.Depl
6061 if err != nil {
6162 return err
6263 }
63- return deployServices (ctx , dockerCli , services , namespace , opts .SendRegistryAuth , opts .ResolveImage )
64+
65+ serviceIDs , err := deployServices (ctx , dockerCli , services , namespace , opts .SendRegistryAuth , opts .ResolveImage )
66+ if err != nil {
67+ return err
68+ }
69+
70+ if opts .Detach {
71+ return nil
72+ }
73+
74+ return waitOnServices (ctx , dockerCli , serviceIDs , opts .Quiet )
6475}
6576
6677func getServicesDeclaredNetworks (serviceConfigs []composetypes.ServiceConfig ) map [string ]struct {} {
@@ -87,11 +98,11 @@ func validateExternalNetworks(ctx context.Context, client apiclient.NetworkAPICl
8798 network , err := client .NetworkInspect (ctx , networkName , types.NetworkInspectOptions {})
8899 switch {
89100 case errdefs .IsNotFound (err ):
90- return errors .Errorf ("network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed" , networkName )
101+ return fmt .Errorf ("network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed" , networkName )
91102 case err != nil :
92103 return err
93104 case network .Scope != "swarm" :
94- return errors .Errorf ("network %q is declared as external, but it is not in the right scope: %q instead of \" swarm\" " , networkName , network .Scope )
105+ return fmt .Errorf ("network %q is declared as external, but it is not in the right scope: %q instead of \" swarm\" " , networkName , network .Scope )
95106 }
96107 }
97108 return nil
@@ -106,13 +117,13 @@ func createSecrets(ctx context.Context, dockerCli command.Cli, secrets []swarm.S
106117 case err == nil :
107118 // secret already exists, then we update that
108119 if err := client .SecretUpdate (ctx , secret .ID , secret .Meta .Version , secretSpec ); err != nil {
109- return errors . Wrapf ( err , "failed to update secret %s" , secretSpec .Name )
120+ return fmt . Errorf ( "failed to update secret %s: %w " , secretSpec .Name , err )
110121 }
111122 case errdefs .IsNotFound (err ):
112123 // secret does not exist, then we create a new one.
113124 fmt .Fprintf (dockerCli .Out (), "Creating secret %s\n " , secretSpec .Name )
114125 if _ , err := client .SecretCreate (ctx , secretSpec ); err != nil {
115- return errors . Wrapf ( err , "failed to create secret %s" , secretSpec .Name )
126+ return fmt . Errorf ( "failed to create secret %s: %w " , secretSpec .Name , err )
116127 }
117128 default :
118129 return err
@@ -130,13 +141,13 @@ func createConfigs(ctx context.Context, dockerCli command.Cli, configs []swarm.C
130141 case err == nil :
131142 // config already exists, then we update that
132143 if err := client .ConfigUpdate (ctx , config .ID , config .Meta .Version , configSpec ); err != nil {
133- return errors . Wrapf ( err , "failed to update config %s" , configSpec .Name )
144+ return fmt . Errorf ( "failed to update config %s: %w " , configSpec .Name , err )
134145 }
135146 case errdefs .IsNotFound (err ):
136147 // config does not exist, then we create a new one.
137148 fmt .Fprintf (dockerCli .Out (), "Creating config %s\n " , configSpec .Name )
138149 if _ , err := client .ConfigCreate (ctx , configSpec ); err != nil {
139- return errors . Wrapf ( err , "failed to create config %s" , configSpec .Name )
150+ return fmt . Errorf ( "failed to create config %s: %w " , configSpec .Name , err )
140151 }
141152 default :
142153 return err
@@ -169,26 +180,28 @@ func createNetworks(ctx context.Context, dockerCli command.Cli, namespace conver
169180
170181 fmt .Fprintf (dockerCli .Out (), "Creating network %s\n " , name )
171182 if _ , err := client .NetworkCreate (ctx , name , createOpts ); err != nil {
172- return errors . Wrapf ( err , "failed to create network %s" , name )
183+ return fmt . Errorf ( "failed to create network %s: %w " , name , err )
173184 }
174185 }
175186 return nil
176187}
177188
178- func deployServices (ctx context.Context , dockerCli command.Cli , services map [string ]swarm.ServiceSpec , namespace convert.Namespace , sendAuth bool , resolveImage string ) error {
189+ func deployServices (ctx context.Context , dockerCli command.Cli , services map [string ]swarm.ServiceSpec , namespace convert.Namespace , sendAuth bool , resolveImage string ) ([] string , error ) {
179190 apiClient := dockerCli .Client ()
180191 out := dockerCli .Out ()
181192
182193 existingServices , err := getStackServices (ctx , apiClient , namespace .Name ())
183194 if err != nil {
184- return err
195+ return nil , err
185196 }
186197
187198 existingServiceMap := make (map [string ]swarm.Service )
188199 for _ , service := range existingServices {
189200 existingServiceMap [service .Spec .Name ] = service
190201 }
191202
203+ var serviceIDs []string
204+
192205 for internalName , serviceSpec := range services {
193206 var (
194207 name = namespace .Scope (internalName )
@@ -200,7 +213,7 @@ func deployServices(ctx context.Context, dockerCli command.Cli, services map[str
200213 // Retrieve encoded auth token from the image reference
201214 encodedAuth , err = command .RetrieveAuthTokenFromImage (dockerCli .ConfigFile (), image )
202215 if err != nil {
203- return err
216+ return nil , err
204217 }
205218 }
206219
@@ -241,12 +254,14 @@ func deployServices(ctx context.Context, dockerCli command.Cli, services map[str
241254
242255 response , err := apiClient .ServiceUpdate (ctx , service .ID , service .Version , serviceSpec , updateOpts )
243256 if err != nil {
244- return errors . Wrapf ( err , "failed to update service %s" , name )
257+ return nil , fmt . Errorf ( "failed to update service %s: %w " , name , err )
245258 }
246259
247260 for _ , warning := range response .Warnings {
248261 fmt .Fprintln (dockerCli .Err (), warning )
249262 }
263+
264+ serviceIDs = append (serviceIDs , service .ID )
250265 } else {
251266 fmt .Fprintf (out , "Creating service %s\n " , name )
252267
@@ -257,10 +272,29 @@ func deployServices(ctx context.Context, dockerCli command.Cli, services map[str
257272 createOpts .QueryRegistry = true
258273 }
259274
260- if _ , err := apiClient .ServiceCreate (ctx , serviceSpec , createOpts ); err != nil {
261- return errors .Wrapf (err , "failed to create service %s" , name )
275+ response , err := apiClient .ServiceCreate (ctx , serviceSpec , createOpts )
276+ if err != nil {
277+ return nil , fmt .Errorf ("failed to create service %s: %w" , name , err )
262278 }
279+
280+ serviceIDs = append (serviceIDs , response .ID )
281+ }
282+ }
283+
284+ return serviceIDs , nil
285+ }
286+
287+ func waitOnServices (ctx context.Context , dockerCli command.Cli , serviceIDs []string , quiet bool ) error {
288+ var errs []error
289+ for _ , serviceID := range serviceIDs {
290+ if err := servicecli .WaitOnService (ctx , dockerCli , serviceID , quiet ); err != nil {
291+ errs = append (errs , fmt .Errorf ("%s: %w" , serviceID , err ))
263292 }
264293 }
294+
295+ if len (errs ) > 0 {
296+ return errors .Join (errs ... )
297+ }
298+
265299 return nil
266300}
0 commit comments