Browse code

swarm: add log driver support for services

Adds log driver support for service creation and update. Add flags
`--log-driver` and `--log-opt` to match `docker run`. Log drivers are
configured per service.

Signed-off-by: Stephen J Day <stephen.day@docker.com>

Stephen J Day authored on 2016/07/09 10:44:18
Showing 4 changed files
... ...
@@ -358,6 +358,27 @@ func convertPortToPortConfig(
358 358
 	return ports
359 359
 }
360 360
 
361
+type logDriverOptions struct {
362
+	name string
363
+	opts opts.ListOpts
364
+}
365
+
366
+func newLogDriverOptions() logDriverOptions {
367
+	return logDriverOptions{opts: opts.NewListOpts(runconfigopts.ValidateEnv)}
368
+}
369
+
370
+func (ldo *logDriverOptions) toLogDriver() *swarm.Driver {
371
+	if ldo.name == "" {
372
+		return nil
373
+	}
374
+
375
+	// set the log driver only if specified.
376
+	return &swarm.Driver{
377
+		Name:    ldo.name,
378
+		Options: runconfigopts.ConvertKVStringsToMap(ldo.opts.GetAll()),
379
+	}
380
+}
381
+
361 382
 // ValidatePort validates a string is in the expected format for a port definition
362 383
 func ValidatePort(value string) (string, error) {
363 384
 	portMappings, err := nat.ParsePortSpec(value)
... ...
@@ -392,6 +413,8 @@ type serviceOptions struct {
392 392
 	endpoint      endpointOptions
393 393
 
394 394
 	registryAuth bool
395
+
396
+	logDriver logDriverOptions
395 397
 }
396 398
 
397 399
 func newServiceOptions() *serviceOptions {
... ...
@@ -401,6 +424,7 @@ func newServiceOptions() *serviceOptions {
401 401
 		endpoint: endpointOptions{
402 402
 			ports: opts.NewListOpts(ValidatePort),
403 403
 		},
404
+		logDriver: newLogDriverOptions(),
404 405
 	}
405 406
 }
406 407
 
... ...
@@ -427,6 +451,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
427 427
 			Placement: &swarm.Placement{
428 428
 				Constraints: opts.constraints,
429 429
 			},
430
+			LogDriver: opts.logDriver.toLogDriver(),
430 431
 		},
431 432
 		Mode: swarm.ServiceMode{},
432 433
 		UpdateConfig: &swarm.UpdateConfig{
... ...
@@ -482,6 +507,9 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
482 482
 	flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "", "Endpoint mode (vip or dnsrr)")
483 483
 
484 484
 	flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to Swarm agents")
485
+
486
+	flags.StringVar(&opts.logDriver.name, flagLogDriver, "", "Logging driver for service")
487
+	flags.Var(&opts.logDriver.opts, flagLogOpt, "Logging driver options")
485 488
 }
486 489
 
487 490
 const (
... ...
@@ -520,4 +548,6 @@ const (
520 520
 	flagUpdateParallelism  = "update-parallelism"
521 521
 	flagUser               = "user"
522 522
 	flagRegistryAuth       = "registry-auth"
523
+	flagLogDriver          = "log-driver"
524
+	flagLogOpt             = "log-opt"
523 525
 )
... ...
@@ -211,6 +211,11 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
211 211
 		}
212 212
 		updatePorts(flags, &spec.EndpointSpec.Ports)
213 213
 	}
214
+
215
+	if err := updateLogDriver(flags, &spec.TaskTemplate); err != nil {
216
+		return err
217
+	}
218
+
214 219
 	return nil
215 220
 }
216 221
 
... ...
@@ -386,3 +391,27 @@ func updateReplicas(flags *pflag.FlagSet, serviceMode *swarm.ServiceMode) error
386 386
 	serviceMode.Replicated.Replicas = flags.Lookup(flagReplicas).Value.(*Uint64Opt).Value()
387 387
 	return nil
388 388
 }
389
+
390
+// updateLogDriver updates the log driver only if the log driver flag is set.
391
+// All options will be replaced with those provided on the command line.
392
+func updateLogDriver(flags *pflag.FlagSet, taskTemplate *swarm.TaskSpec) error {
393
+	if !flags.Changed(flagLogDriver) {
394
+		return nil
395
+	}
396
+
397
+	name, err := flags.GetString(flagLogDriver)
398
+	if err != nil {
399
+		return err
400
+	}
401
+
402
+	if name == "" {
403
+		return nil
404
+	}
405
+
406
+	taskTemplate.LogDriver = &swarm.Driver{
407
+		Name:    name,
408
+		Options: runconfigopts.ConvertKVStringsToMap(flags.Lookup(flagLogOpt).Value.(*opts.ListOpts).GetAll()),
409
+	}
410
+
411
+	return nil
412
+}
... ...
@@ -28,6 +28,7 @@ func ServiceFromGRPC(s swarmapi.Service) types.Service {
28 28
 				Resources:     resourcesFromGRPC(s.Spec.Task.Resources),
29 29
 				RestartPolicy: restartPolicyFromGRPC(s.Spec.Task.Restart),
30 30
 				Placement:     placementFromGRPC(s.Spec.Task.Placement),
31
+				LogDriver:     driverFromGRPC(s.Spec.Task.LogDriver),
31 32
 			},
32 33
 
33 34
 			Networks:     networks,
... ...
@@ -86,6 +87,7 @@ func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) {
86 86
 		},
87 87
 		Task: swarmapi.TaskSpec{
88 88
 			Resources: resourcesToGRPC(s.TaskTemplate.Resources),
89
+			LogDriver: driverToGRPC(s.TaskTemplate.LogDriver),
89 90
 		},
90 91
 		Networks: networks,
91 92
 	}
... ...
@@ -251,3 +253,25 @@ func placementFromGRPC(p *swarmapi.Placement) *types.Placement {
251 251
 
252 252
 	return r
253 253
 }
254
+
255
+func driverFromGRPC(p *swarmapi.Driver) *types.Driver {
256
+	if p == nil {
257
+		return nil
258
+	}
259
+
260
+	return &types.Driver{
261
+		Name:    p.Name,
262
+		Options: p.Options,
263
+	}
264
+}
265
+
266
+func driverToGRPC(p *types.Driver) *swarmapi.Driver {
267
+	if p == nil {
268
+		return nil
269
+	}
270
+
271
+	return &swarmapi.Driver{
272
+		Name:    p.Name,
273
+		Options: p.Options,
274
+	}
275
+}
... ...
@@ -22,6 +22,7 @@ func TaskFromGRPC(t swarmapi.Task) types.Task {
22 22
 			Resources:     resourcesFromGRPC(t.Spec.Resources),
23 23
 			RestartPolicy: restartPolicyFromGRPC(t.Spec.Restart),
24 24
 			Placement:     placementFromGRPC(t.Spec.Placement),
25
+			LogDriver:     driverFromGRPC(t.Spec.LogDriver),
25 26
 		},
26 27
 		Status: types.TaskStatus{
27 28
 			State:   types.TaskState(strings.ToLower(t.Status.State.String())),