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>
| ... | ... |
@@ -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())), |