Browse code

Add container labels to service create/update

Swarm mode makes it possible through the API to set labels to containers
but not through command line. This tries to fix it.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2016/07/25 18:38:01
Showing 5 changed files
... ...
@@ -30,6 +30,7 @@ func newCreateCommand(dockerCli *client.DockerCli) *cobra.Command {
30 30
 	addServiceFlags(cmd, opts)
31 31
 
32 32
 	flags.VarP(&opts.labels, flagLabel, "l", "Service labels")
33
+	flags.Var(&opts.containerLabels, flagContainerLabel, "Container labels")
33 34
 	flags.VarP(&opts.env, flagEnv, "e", "Set environment variables")
34 35
 	flags.Var(&opts.mounts, flagMount, "Attach a mount to the service")
35 36
 	flags.StringSliceVar(&opts.constraints, flagConstraint, []string{}, "Placement constraints")
... ...
@@ -392,14 +392,15 @@ func ValidatePort(value string) (string, error) {
392 392
 }
393 393
 
394 394
 type serviceOptions struct {
395
-	name    string
396
-	labels  opts.ListOpts
397
-	image   string
398
-	args    []string
399
-	env     opts.ListOpts
400
-	workdir string
401
-	user    string
402
-	mounts  MountOpt
395
+	name            string
396
+	labels          opts.ListOpts
397
+	containerLabels opts.ListOpts
398
+	image           string
399
+	args            []string
400
+	env             opts.ListOpts
401
+	workdir         string
402
+	user            string
403
+	mounts          MountOpt
403 404
 
404 405
 	resources resourceOptions
405 406
 	stopGrace DurationOpt
... ...
@@ -420,8 +421,9 @@ type serviceOptions struct {
420 420
 
421 421
 func newServiceOptions() *serviceOptions {
422 422
 	return &serviceOptions{
423
-		labels: opts.NewListOpts(runconfigopts.ValidateEnv),
424
-		env:    opts.NewListOpts(runconfigopts.ValidateEnv),
423
+		labels:          opts.NewListOpts(runconfigopts.ValidateEnv),
424
+		containerLabels: opts.NewListOpts(runconfigopts.ValidateEnv),
425
+		env:             opts.NewListOpts(runconfigopts.ValidateEnv),
425 426
 		endpoint: endpointOptions{
426 427
 			ports: opts.NewListOpts(ValidatePort),
427 428
 		},
... ...
@@ -442,6 +444,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
442 442
 				Image:           opts.image,
443 443
 				Args:            opts.args,
444 444
 				Env:             opts.env.GetAll(),
445
+				Labels:          runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
445 446
 				Dir:             opts.workdir,
446 447
 				User:            opts.user,
447 448
 				Mounts:          opts.mounts.Value(),
... ...
@@ -516,42 +519,45 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
516 516
 }
517 517
 
518 518
 const (
519
-	flagConstraint          = "constraint"
520
-	flagConstraintRemove    = "constraint-rm"
521
-	flagConstraintAdd       = "constraint-add"
522
-	flagEndpointMode        = "endpoint-mode"
523
-	flagEnv                 = "env"
524
-	flagEnvRemove           = "env-rm"
525
-	flagEnvAdd              = "env-add"
526
-	flagLabel               = "label"
527
-	flagLabelRemove         = "label-rm"
528
-	flagLabelAdd            = "label-add"
529
-	flagLimitCPU            = "limit-cpu"
530
-	flagLimitMemory         = "limit-memory"
531
-	flagMode                = "mode"
532
-	flagMount               = "mount"
533
-	flagMountRemove         = "mount-rm"
534
-	flagMountAdd            = "mount-add"
535
-	flagName                = "name"
536
-	flagNetwork             = "network"
537
-	flagNetworkRemove       = "network-rm"
538
-	flagNetworkAdd          = "network-add"
539
-	flagPublish             = "publish"
540
-	flagPublishRemove       = "publish-rm"
541
-	flagPublishAdd          = "publish-add"
542
-	flagReplicas            = "replicas"
543
-	flagReserveCPU          = "reserve-cpu"
544
-	flagReserveMemory       = "reserve-memory"
545
-	flagRestartCondition    = "restart-condition"
546
-	flagRestartDelay        = "restart-delay"
547
-	flagRestartMaxAttempts  = "restart-max-attempts"
548
-	flagRestartWindow       = "restart-window"
549
-	flagStopGracePeriod     = "stop-grace-period"
550
-	flagUpdateDelay         = "update-delay"
551
-	flagUpdateFailureAction = "update-failure-action"
552
-	flagUpdateParallelism   = "update-parallelism"
553
-	flagUser                = "user"
554
-	flagRegistryAuth        = "with-registry-auth"
555
-	flagLogDriver           = "log-driver"
556
-	flagLogOpt              = "log-opt"
519
+	flagConstraint           = "constraint"
520
+	flagConstraintRemove     = "constraint-rm"
521
+	flagConstraintAdd        = "constraint-add"
522
+	flagContainerLabel       = "container-label"
523
+	flagContainerLabelRemove = "container-label-rm"
524
+	flagContainerLabelAdd    = "container-label-add"
525
+	flagEndpointMode         = "endpoint-mode"
526
+	flagEnv                  = "env"
527
+	flagEnvRemove            = "env-rm"
528
+	flagEnvAdd               = "env-add"
529
+	flagLabel                = "label"
530
+	flagLabelRemove          = "label-rm"
531
+	flagLabelAdd             = "label-add"
532
+	flagLimitCPU             = "limit-cpu"
533
+	flagLimitMemory          = "limit-memory"
534
+	flagMode                 = "mode"
535
+	flagMount                = "mount"
536
+	flagMountRemove          = "mount-rm"
537
+	flagMountAdd             = "mount-add"
538
+	flagName                 = "name"
539
+	flagNetwork              = "network"
540
+	flagNetworkRemove        = "network-rm"
541
+	flagNetworkAdd           = "network-add"
542
+	flagPublish              = "publish"
543
+	flagPublishRemove        = "publish-rm"
544
+	flagPublishAdd           = "publish-add"
545
+	flagReplicas             = "replicas"
546
+	flagReserveCPU           = "reserve-cpu"
547
+	flagReserveMemory        = "reserve-memory"
548
+	flagRestartCondition     = "restart-condition"
549
+	flagRestartDelay         = "restart-delay"
550
+	flagRestartMaxAttempts   = "restart-max-attempts"
551
+	flagRestartWindow        = "restart-window"
552
+	flagStopGracePeriod      = "stop-grace-period"
553
+	flagUpdateDelay          = "update-delay"
554
+	flagUpdateFailureAction  = "update-failure-action"
555
+	flagUpdateParallelism    = "update-parallelism"
556
+	flagUser                 = "user"
557
+	flagRegistryAuth         = "with-registry-auth"
558
+	flagLogDriver            = "log-driver"
559
+	flagLogOpt               = "log-opt"
557 560
 )
... ...
@@ -38,11 +38,13 @@ func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
38 38
 
39 39
 	flags.Var(newListOptsVar(), flagEnvRemove, "Remove an environment variable")
40 40
 	flags.Var(newListOptsVar(), flagLabelRemove, "Remove a label by its key")
41
+	flags.Var(newListOptsVar(), flagContainerLabelRemove, "Remove a container label by its key")
41 42
 	flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path")
42 43
 	flags.Var(newListOptsVar(), flagPublishRemove, "Remove a published port by its target port")
43 44
 	flags.Var(newListOptsVar(), flagNetworkRemove, "Remove a network by name")
44 45
 	flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint")
45 46
 	flags.Var(&opts.labels, flagLabelAdd, "Add or update service labels")
47
+	flags.Var(&opts.containerLabels, flagContainerLabelAdd, "Add or update container labels")
46 48
 	flags.Var(&opts.env, flagEnvAdd, "Add or update environment variables")
47 49
 	flags.Var(&opts.mounts, flagMountAdd, "Add or update a mount on a service")
48 50
 	flags.StringSliceVar(&opts.constraints, flagConstraintAdd, []string{}, "Add or update placement constraints")
... ...
@@ -145,6 +147,7 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
145 145
 
146 146
 	updateString(flagName, &spec.Name)
147 147
 	updateLabels(flags, &spec.Labels)
148
+	updateContainerLabels(flags, &cspec.Labels)
148 149
 	updateString("image", &cspec.Image)
149 150
 	updateStringToSlice(flags, "args", &cspec.Args)
150 151
 	updateEnvironment(flags, &cspec.Env)
... ...
@@ -248,6 +251,26 @@ func updatePlacement(flags *pflag.FlagSet, placement *swarm.Placement) {
248 248
 	placement.Constraints = removeItems(placement.Constraints, toRemove, itemKey)
249 249
 }
250 250
 
251
+func updateContainerLabels(flags *pflag.FlagSet, field *map[string]string) {
252
+	if flags.Changed(flagContainerLabelAdd) {
253
+		if field == nil {
254
+			*field = map[string]string{}
255
+		}
256
+
257
+		values := flags.Lookup(flagContainerLabelAdd).Value.(*opts.ListOpts).GetAll()
258
+		for key, value := range runconfigopts.ConvertKVStringsToMap(values) {
259
+			(*field)[key] = value
260
+		}
261
+	}
262
+
263
+	if field != nil && flags.Changed(flagContainerLabelRemove) {
264
+		toRemove := flags.Lookup(flagContainerLabelRemove).Value.(*opts.ListOpts).GetAll()
265
+		for _, label := range toRemove {
266
+			delete(*field, label)
267
+		}
268
+	}
269
+}
270
+
251 271
 func updateLabels(flags *pflag.FlagSet, field *map[string]string) {
252 272
 	if flags.Changed(flagLabelAdd) {
253 273
 		if *field == nil {
... ...
@@ -18,6 +18,7 @@ Create a new service
18 18
 
19 19
 Options:
20 20
       --constraint value               Placement constraints (default [])
21
+      --container-label value          Service container labels (default [])
21 22
       --endpoint-mode string           Endpoint mode (vip or dnsrr)
22 23
   -e, --env value                      Set environment variables (default [])
23 24
       --help                           Print usage
... ...
@@ -20,6 +20,8 @@ Options:
20 20
       --args string                    Service command args
21 21
       --constraint-add value           Add or update placement constraints (default [])
22 22
       --constraint-rm value            Remove a constraint (default [])
23
+      --container-label-add value      Add or update container labels (default [])
24
+      --container-label-rm value       Remove a container label by its key (default [])
23 25
       --endpoint-mode string           Endpoint mode (vip or dnsrr)
24 26
       --env-add value                  Add or update environment variables (default [])
25 27
       --env-rm value                   Remove an environment variable (default [])