func updateDBLabels(view db.Database, etcdData storeData, ipMap map[string]string) { // Gather all of the label keys and IPs for single host labels, and IPs of // the containers in a given label. containerIPs := map[string][]string{} labelIPs := map[string]string{} labelKeys := map[string]struct{}{} for _, c := range etcdData.containers { for _, l := range c.Labels { labelKeys[l] = struct{}{} cIP := ipMap[strconv.Itoa(c.StitchID)] if _, ok := etcdData.multiHost[l]; !ok { labelIPs[l] = cIP } // The ordering of IPs between function calls will be consistent // because the containers are sorted by their StitchIDs when // inserted into etcd. containerIPs[l] = append(containerIPs[l], cIP) } } labelKeyFunc := func(val interface{}) interface{} { return val.(db.Label).Label } labelKeySlice := join.StringSlice{} for l := range labelKeys { labelKeySlice = append(labelKeySlice, l) } pairs, dbls, dirKeys := join.HashJoin(db.LabelSlice(view.SelectFromLabel(nil)), labelKeySlice, labelKeyFunc, nil) for _, dbl := range dbls { view.Remove(dbl.(db.Label)) } for _, key := range dirKeys { pairs = append(pairs, join.Pair{L: view.InsertLabel(), R: key}) } for _, pair := range pairs { dbl := pair.L.(db.Label) dbl.Label = pair.R.(string) if _, ok := etcdData.multiHost[dbl.Label]; ok { dbl.IP = etcdData.multiHost[dbl.Label] dbl.MultiHost = true } else { dbl.IP = labelIPs[dbl.Label] dbl.MultiHost = false } dbl.ContainerIPs = containerIPs[dbl.Label] view.Commit(dbl) } }
func testUpdateDBLabels(t *testing.T, view db.Database) { labelStruct := map[string]string{"a": "10.0.0.2"} ipMap := map[string]string{"1": "10.0.0.3", "2": "10.0.0.4"} containerSlice := []storeContainer{ { StitchID: 1, Labels: []string{"a", "b"}, }, { StitchID: 2, Labels: []string{"a"}, }, } updateDBLabels(view, storeData{ containers: containerSlice, multiHost: labelStruct, }, ipMap) type labelIPs struct { labelIP string containerIPs []string } lip := map[string]labelIPs{} for _, l := range view.SelectFromLabel(nil) { _, ok := lip[l.Label] assert.False(t, ok) lip[l.Label] = labelIPs{ labelIP: l.IP, containerIPs: l.ContainerIPs, } } resultLabels := map[string]labelIPs{ "a": { labelIP: "10.0.0.2", containerIPs: []string{"10.0.0.3", "10.0.0.4"}, }, "b": { labelIP: "10.0.0.3", containerIPs: []string{"10.0.0.3"}, }, } assert.Equal(t, resultLabels, lip) }
func testReadLabelTransact(t *testing.T, view db.Database) { dir := directory(map[string]map[string]string{ "a": {"IP": "10.0.0.2"}, "b": {"IP": "10.0.0.3"}, "c": {"IP": "10.0.0.4"}, }) readLabelTransact(view, dir) lip := map[string]string{} for _, l := range view.SelectFromLabel(nil) { lip[l.Label] = l.IP } exp := map[string]string{ "a": "10.0.0.2", "b": "10.0.0.3", "c": "10.0.0.4", } if !eq(lip, exp) { t.Error(spew.Sprintf("Found: %s\nExpected: %s\n", lip, exp)) } delete(dir, "c") delete(exp, "c") dir["b"]["IP"] = "10.0.0.4" exp["b"] = "10.0.0.4" readLabelTransact(view, dir) lip = map[string]string{} for _, l := range view.SelectFromLabel(nil) { lip[l.Label] = l.IP } if !eq(lip, exp) { t.Error(spew.Sprintf("Found: %s\nExpected: %s\n", lip, exp)) } }
func readLabelTransact(view db.Database, dir directory) { lKey := func(val interface{}) interface{} { return val.(db.Label).Label } pairs, dbls, dirKeys := join.HashJoin(db.LabelSlice(view.SelectFromLabel(nil)), join.StringSlice(dir.keys()), lKey, nil) for _, dbl := range dbls { view.Remove(dbl.(db.Label)) } for _, key := range dirKeys { pairs = append(pairs, join.Pair{L: view.InsertLabel(), R: key}) } for _, pair := range pairs { dbl := pair.L.(db.Label) dbl.Label = pair.R.(string) dbl.IP = dir[dbl.Label]["IP"] _, dbl.MultiHost = dir[dbl.Label]["MultiHost"] view.Commit(dbl) } }