From 975e869af9ad6a6d49b311f09b4f58c3443177f0 Mon Sep 17 00:00:00 2001 From: deniseschannon Date: Thu, 7 May 2015 14:29:30 -0700 Subject: [PATCH 1/3] Fixes creating Hash --- docker/container.go | 51 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/docker/container.go b/docker/container.go index 5f8641bb..08bf7309 100644 --- a/docker/container.go +++ b/docker/container.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "os" + "reflect" "sort" "strings" @@ -47,8 +48,54 @@ func getHash(containerCfg *config.ContainerConfig) (string, error) { w.Write([]byte(containerCfg.Id)) w.Write([]byte(containerCfg.Cmd)) if containerCfg.Service != nil { - //TODO: properly hash - w.Write([]byte(fmt.Sprintf("%v", containerCfg.Service))) + //Get values of Service through reflection + val := reflect.ValueOf(containerCfg.Service).Elem() + + //Create slice to sort the keys in Service Config, which allow constant hash ordering + var serviceKeys []string + + //Create a data structure of map of values keyed by a string + unsortedKeyValue := make(map[string]interface{}) + + //Create a data structure of map of type keyed by a string + unsortedKeyType := make(map[string]reflect.Type) + + //Get all keys and values in Service Configuration + for i := 0; i < val.NumField(); i++ { + valueField := val.Field(i) + keyField := val.Type().Field(i) + + serviceKeys = append(serviceKeys, keyField.Name) + unsortedKeyValue[keyField.Name] = valueField.Interface() + unsortedKeyType[keyField.Name] = valueField.Type() + } + + //Sort serviceKeys alphabetically + sort.Strings(serviceKeys) + + //New slice to sort through Labels Map + var labelKeys []string + + //Go through keys and write hash + for i := 0; i < len(serviceKeys); i++ { + serviceValue := unsortedKeyValue[serviceKeys[i]] + serviceType := unsortedKeyType[serviceKeys[i]] + + //Only need to check for Labels key as it's a Map and write hash after sorting the label names + if serviceType == reflect.TypeOf(project.NewSliceorMap(make(map[string]string))) { + for lkey := range serviceValue.(*project.SliceorMap).MapParts() { + labelKeys = append(labelKeys, lkey) + } + sort.Strings(labelKeys) + + for j := 0; j < len(labelKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s%v", labelKeys[j], serviceValue.(*project.SliceorMap).MapParts()[labelKeys[j]]))) + } + } else { + w.Write([]byte(fmt.Sprintf("%v", serviceValue))) + } + + } } if w.Err != nil { From eea38fb1737db5241151b0fadd84b2de7abe3665 Mon Sep 17 00:00:00 2001 From: deniseschannon Date: Fri, 8 May 2015 13:17:52 -0700 Subject: [PATCH 2/3] Updated hashing in case slice order changes --- docker/container.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/docker/container.go b/docker/container.go index 08bf7309..084149b6 100644 --- a/docker/container.go +++ b/docker/container.go @@ -73,28 +73,42 @@ func getHash(containerCfg *config.ContainerConfig) (string, error) { //Sort serviceKeys alphabetically sort.Strings(serviceKeys) - //New slice to sort through Labels Map - var labelKeys []string + //New slice to sort through Keys + //var sliceKeys []string //Go through keys and write hash for i := 0; i < len(serviceKeys); i++ { serviceValue := unsortedKeyValue[serviceKeys[i]] serviceType := unsortedKeyType[serviceKeys[i]] + sliceKeys := []string{} //Only need to check for Labels key as it's a Map and write hash after sorting the label names if serviceType == reflect.TypeOf(project.NewSliceorMap(make(map[string]string))) { for lkey := range serviceValue.(*project.SliceorMap).MapParts() { - labelKeys = append(labelKeys, lkey) + sliceKeys = append(sliceKeys, lkey) } - sort.Strings(labelKeys) + sort.Strings(sliceKeys) - for j := 0; j < len(labelKeys); j++ { - w.Write([]byte(fmt.Sprintf("%s%v", labelKeys[j], serviceValue.(*project.SliceorMap).MapParts()[labelKeys[j]]))) + for j := 0; j < len(sliceKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s%v", sliceKeys[j], serviceValue.(*project.SliceorMap).MapParts()[sliceKeys[j]]))) + } + } else if serviceType == reflect.TypeOf(project.NewStringorslice("TestString")) { + sliceKeys = serviceValue.(*project.Stringorslice).Slice() + sort.Strings(sliceKeys) + + for j := 0; j < len(sliceKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s", sliceKeys[j]))) + } + } else if v, ok := serviceValue.([]string); ok { + sliceKeys = v + sort.Strings(sliceKeys) + + for j := 0; j < len(sliceKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s", sliceKeys[j]))) } } else { w.Write([]byte(fmt.Sprintf("%v", serviceValue))) } - } } From efa14453a398efdb4af5c15658994be029bb3b1c Mon Sep 17 00:00:00 2001 From: deniseschannon Date: Mon, 11 May 2015 10:02:15 -0700 Subject: [PATCH 3/3] Updated hash based on comments --- docker/container.go | 60 ++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/docker/container.go b/docker/container.go index 084149b6..2636cb01 100644 --- a/docker/container.go +++ b/docker/container.go @@ -57,9 +57,6 @@ func getHash(containerCfg *config.ContainerConfig) (string, error) { //Create a data structure of map of values keyed by a string unsortedKeyValue := make(map[string]interface{}) - //Create a data structure of map of type keyed by a string - unsortedKeyType := make(map[string]reflect.Type) - //Get all keys and values in Service Configuration for i := 0; i < val.NumField(); i++ { valueField := val.Field(i) @@ -67,47 +64,44 @@ func getHash(containerCfg *config.ContainerConfig) (string, error) { serviceKeys = append(serviceKeys, keyField.Name) unsortedKeyValue[keyField.Name] = valueField.Interface() - unsortedKeyType[keyField.Name] = valueField.Type() } //Sort serviceKeys alphabetically sort.Strings(serviceKeys) - //New slice to sort through Keys - //var sliceKeys []string - //Go through keys and write hash for i := 0; i < len(serviceKeys); i++ { serviceValue := unsortedKeyValue[serviceKeys[i]] - serviceType := unsortedKeyType[serviceKeys[i]] sliceKeys := []string{} - //Only need to check for Labels key as it's a Map and write hash after sorting the label names - if serviceType == reflect.TypeOf(project.NewSliceorMap(make(map[string]string))) { - for lkey := range serviceValue.(*project.SliceorMap).MapParts() { - sliceKeys = append(sliceKeys, lkey) - } - sort.Strings(sliceKeys) - - for j := 0; j < len(sliceKeys); j++ { - w.Write([]byte(fmt.Sprintf("%s%v", sliceKeys[j], serviceValue.(*project.SliceorMap).MapParts()[sliceKeys[j]]))) - } - } else if serviceType == reflect.TypeOf(project.NewStringorslice("TestString")) { - sliceKeys = serviceValue.(*project.Stringorslice).Slice() - sort.Strings(sliceKeys) - - for j := 0; j < len(sliceKeys); j++ { - w.Write([]byte(fmt.Sprintf("%s", sliceKeys[j]))) - } - } else if v, ok := serviceValue.([]string); ok { - sliceKeys = v - sort.Strings(sliceKeys) - - for j := 0; j < len(sliceKeys); j++ { - w.Write([]byte(fmt.Sprintf("%s", sliceKeys[j]))) - } - } else { + switch s := serviceValue.(type) { + default: w.Write([]byte(fmt.Sprintf("%v", serviceValue))) + case *project.SliceorMap: + for lkey := range s.MapParts() { + if lkey != "io.rancher.os.hash" { + sliceKeys = append(sliceKeys, lkey) + } + } + sort.Strings(sliceKeys) + + for j := 0; j < len(sliceKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s=%v", sliceKeys[j], s.MapParts()[sliceKeys[j]]))) + } + case *project.Stringorslice: + sliceKeys = s.Slice() + sort.Strings(sliceKeys) + + for j := 0; j < len(sliceKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s", sliceKeys[j]))) + } + case []string: + sliceKeys = s + sort.Strings(sliceKeys) + + for j := 0; j < len(sliceKeys); j++ { + w.Write([]byte(fmt.Sprintf("%s", sliceKeys[j]))) + } } } }