Remove duplicate keys in labels of `docker info`
| ... | ... |
@@ -223,6 +223,21 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
| 223 | 223 |
for _, attribute := range info.Labels {
|
| 224 | 224 |
fmt.Fprintf(dockerCli.Out(), " %s\n", attribute) |
| 225 | 225 |
} |
| 226 |
+ // TODO: Engine labels with duplicate keys has been deprecated in 1.13 and will be error out |
|
| 227 |
+ // after 3 release cycles (1.16). For now, a WARNING will be generated. The following will |
|
| 228 |
+ // be removed eventually. |
|
| 229 |
+ labelMap := map[string]string{}
|
|
| 230 |
+ for _, label := range info.Labels {
|
|
| 231 |
+ stringSlice := strings.SplitN(label, "=", 2) |
|
| 232 |
+ if len(stringSlice) > 1 {
|
|
| 233 |
+ // If there is a conflict we will throw out an warning |
|
| 234 |
+ if v, ok := labelMap[stringSlice[0]]; ok && v != stringSlice[1] {
|
|
| 235 |
+ fmt.Fprintln(dockerCli.Err(), "WARNING: labels with duplicate keys and conflicting values have been deprecated") |
|
| 236 |
+ break |
|
| 237 |
+ } |
|
| 238 |
+ labelMap[stringSlice[0]] = stringSlice[1] |
|
| 239 |
+ } |
|
| 240 |
+ } |
|
| 226 | 241 |
} |
| 227 | 242 |
|
| 228 | 243 |
fmt.Fprintf(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild) |
| ... | ... |
@@ -396,6 +396,23 @@ func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
|
| 396 | 396 |
return nil, err |
| 397 | 397 |
} |
| 398 | 398 |
|
| 399 |
+ // Labels of the docker engine used to allow multiple values associated with the same key. |
|
| 400 |
+ // This is deprecated in 1.13, and, be removed after 3 release cycles. |
|
| 401 |
+ // The following will check the conflict of labels, and report a warning for deprecation. |
|
| 402 |
+ // |
|
| 403 |
+ // TODO: After 3 release cycles (1.16) an error will be returned, and labels will be |
|
| 404 |
+ // sanitized to consolidate duplicate key-value pairs (config.Labels = newLabels): |
|
| 405 |
+ // |
|
| 406 |
+ // newLabels, err := daemon.GetConflictFreeLabels(config.Labels) |
|
| 407 |
+ // if err != nil {
|
|
| 408 |
+ // return nil, err |
|
| 409 |
+ // } |
|
| 410 |
+ // config.Labels = newLabels |
|
| 411 |
+ // |
|
| 412 |
+ if _, err := daemon.GetConflictFreeLabels(config.Labels); err != nil {
|
|
| 413 |
+ logrus.Warnf("Engine labels with duplicate keys and conflicting values have been deprecated: %s", err)
|
|
| 414 |
+ } |
|
| 415 |
+ |
|
| 399 | 416 |
// Regardless of whether the user sets it to true or false, if they |
| 400 | 417 |
// specify TLSVerify at all then we need to turn on TLS |
| 401 | 418 |
if config.IsValueSet(cliflags.FlagTLSVerify) {
|
| ... | ... |
@@ -232,6 +232,30 @@ func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (strin |
| 232 | 232 |
return advertise, nil |
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 |
+// GetConflictFreeLabels validate Labels for conflict |
|
| 236 |
+// In swarm the duplicates for labels are removed |
|
| 237 |
+// so we only take same values here, no conflict values |
|
| 238 |
+// If the key-value is the same we will only take the last label |
|
| 239 |
+func GetConflictFreeLabels(labels []string) ([]string, error) {
|
|
| 240 |
+ labelMap := map[string]string{}
|
|
| 241 |
+ for _, label := range labels {
|
|
| 242 |
+ stringSlice := strings.SplitN(label, "=", 2) |
|
| 243 |
+ if len(stringSlice) > 1 {
|
|
| 244 |
+ // If there is a conflict we will return an error |
|
| 245 |
+ if v, ok := labelMap[stringSlice[0]]; ok && v != stringSlice[1] {
|
|
| 246 |
+ return nil, fmt.Errorf("conflict labels for %s=%s and %s=%s", stringSlice[0], stringSlice[1], stringSlice[0], v)
|
|
| 247 |
+ } |
|
| 248 |
+ labelMap[stringSlice[0]] = stringSlice[1] |
|
| 249 |
+ } |
|
| 250 |
+ } |
|
| 251 |
+ |
|
| 252 |
+ newLabels := []string{}
|
|
| 253 |
+ for k, v := range labelMap {
|
|
| 254 |
+ newLabels = append(newLabels, fmt.Sprintf("%s=%s", k, v))
|
|
| 255 |
+ } |
|
| 256 |
+ return newLabels, nil |
|
| 257 |
+} |
|
| 258 |
+ |
|
| 235 | 259 |
// ReloadConfiguration reads the configuration in the host and reloads the daemon and server. |
| 236 | 260 |
func ReloadConfiguration(configFile string, flags *pflag.FlagSet, reload func(*Config)) error {
|
| 237 | 261 |
logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile)
|
| ... | ... |
@@ -244,6 +268,23 @@ func ReloadConfiguration(configFile string, flags *pflag.FlagSet, reload func(*C |
| 244 | 244 |
return fmt.Errorf("file configuration validation failed (%v)", err)
|
| 245 | 245 |
} |
| 246 | 246 |
|
| 247 |
+ // Labels of the docker engine used to allow multiple values associated with the same key. |
|
| 248 |
+ // This is deprecated in 1.13, and, be removed after 3 release cycles. |
|
| 249 |
+ // The following will check the conflict of labels, and report a warning for deprecation. |
|
| 250 |
+ // |
|
| 251 |
+ // TODO: After 3 release cycles (1.16) an error will be returned, and labels will be |
|
| 252 |
+ // sanitized to consolidate duplicate key-value pairs (config.Labels = newLabels): |
|
| 253 |
+ // |
|
| 254 |
+ // newLabels, err := GetConflictFreeLabels(newConfig.Labels) |
|
| 255 |
+ // if err != nil {
|
|
| 256 |
+ // return err |
|
| 257 |
+ // } |
|
| 258 |
+ // newConfig.Labels = newLabels |
|
| 259 |
+ // |
|
| 260 |
+ if _, err := GetConflictFreeLabels(newConfig.Labels); err != nil {
|
|
| 261 |
+ logrus.Warnf("Engine labels with duplicate keys and conflicting values have been deprecated: %s", err)
|
|
| 262 |
+ } |
|
| 263 |
+ |
|
| 247 | 264 |
reload(newConfig) |
| 248 | 265 |
return nil |
| 249 | 266 |
} |
| ... | ... |
@@ -35,6 +35,14 @@ see [Feature Deprecation Policy](https://docs.docker.com/engine/#feature-depreca |
| 35 | 35 |
|
| 36 | 36 |
The daemon is moved to a separate binary (`dockerd`), and should be used instead. |
| 37 | 37 |
|
| 38 |
+### Duplicate keys with conflicting values in engine labels |
|
| 39 |
+**Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/)** |
|
| 40 |
+ |
|
| 41 |
+**Target For Removal In Release: v1.16** |
|
| 42 |
+ |
|
| 43 |
+Duplicate keys with conflicting values have been deprecated. A warning is displayed |
|
| 44 |
+in the output, and an error will be returned in the future. |
|
| 45 |
+ |
|
| 38 | 46 |
### Three argument form in `docker import` |
| 39 | 47 |
**Deprecated In Release: [v0.6.7](https://github.com/docker/docker/releases/tag/v0.6.7)** |
| 40 | 48 |
|
| ... | ... |
@@ -220,3 +220,15 @@ func (s *DockerDaemonSuite) TestRegistryMirrors(c *check.C) {
|
| 220 | 220 |
c.Assert(out, checker.Contains, fmt.Sprintf(" %s", registryMirror1))
|
| 221 | 221 |
c.Assert(out, checker.Contains, fmt.Sprintf(" %s", registryMirror2))
|
| 222 | 222 |
} |
| 223 |
+ |
|
| 224 |
+// Test case for #24392 |
|
| 225 |
+func (s *DockerDaemonSuite) TestInfoLabels(c *check.C) {
|
|
| 226 |
+ testRequires(c, SameHostDaemon, DaemonIsLinux) |
|
| 227 |
+ |
|
| 228 |
+ err := s.d.Start("--label", `test.empty=`, "--label", `test.empty=`, "--label", `test.label="1"`, "--label", `test.label="2"`)
|
|
| 229 |
+ c.Assert(err, checker.IsNil) |
|
| 230 |
+ |
|
| 231 |
+ out, err := s.d.Cmd("info")
|
|
| 232 |
+ c.Assert(err, checker.IsNil) |
|
| 233 |
+ c.Assert(out, checker.Contains, "WARNING: labels with duplicate keys and conflicting values have been deprecated") |
|
| 234 |
+} |