func updatePlacements(view db.Database, spec stitch.Stitch) { var placements db.PlacementSlice for _, sp := range spec.Placements { placements = append(placements, db.Placement{ TargetLabel: sp.TargetLabel, Exclusive: sp.Exclusive, OtherLabel: sp.OtherLabel, Provider: sp.Provider, Size: sp.Size, Region: sp.Region, }) } key := func(val interface{}) interface{} { p := val.(db.Placement) p.ID = 0 return p } dbPlacements := db.PlacementSlice(view.SelectFromPlacement(nil)) _, addSet, removeSet := join.HashJoin(placements, dbPlacements, key, key) for _, toAddIntf := range addSet { toAdd := toAddIntf.(db.Placement) id := view.InsertPlacement().ID toAdd.ID = id view.Commit(toAdd) } for _, toRemove := range removeSet { view.Remove(toRemove.(db.Placement)) } }
func updateConnections(view db.Database, spec stitch.Stitch) { scs, vcs := stitch.ConnectionSlice(spec.Connections), view.SelectFromConnection(nil) dbcKey := func(val interface{}) interface{} { c := val.(db.Connection) return stitch.Connection{ From: c.From, To: c.To, MinPort: c.MinPort, MaxPort: c.MaxPort, } } pairs, stitches, dbcs := join.HashJoin(scs, db.ConnectionSlice(vcs), nil, dbcKey) for _, dbc := range dbcs { view.Remove(dbc.(db.Connection)) } for _, stitchc := range stitches { pairs = append(pairs, join.Pair{L: stitchc, R: view.InsertConnection()}) } for _, pair := range pairs { stitchc := pair.L.(stitch.Connection) dbc := pair.R.(db.Connection) dbc.From = stitchc.From dbc.To = stitchc.To dbc.MinPort = stitchc.MinPort dbc.MaxPort = stitchc.MaxPort view.Commit(dbc) } }
func updatePlacements(view db.Database, spec stitch.Stitch) { stitchPlacements := toDBPlacements(spec.QueryPlacements()) key := func(val interface{}) interface{} { pVal := val.(db.Placement) return struct { tl string rule db.PlacementRule }{pVal.TargetLabel, pVal.Rule} } _, addSet, removeSet := join.HashJoin(stitchPlacements, db.PlacementSlice(view.SelectFromPlacement(nil)), key, key) for _, toAddIntf := range addSet { toAdd := toAddIntf.(db.Placement) newPlacement := view.InsertPlacement() newPlacement.TargetLabel = toAdd.TargetLabel newPlacement.Rule = toAdd.Rule view.Commit(newPlacement) } for _, toRemove := range removeSet { view.Remove(toRemove.(db.Placement)) } }
func machineTxn(view db.Database, stitch stitch.Stitch) error { // XXX: How best to deal with machines that don't specify enough information? maxPrice, _ := stitch.QueryFloat("MaxPrice") stitchMachines := toDBMachine(stitch.QueryMachines(), maxPrice) dbMachines := view.SelectFromMachine(nil) scoreFun := func(left, right interface{}) int { stitchMachine := left.(db.Machine) dbMachine := right.(db.Machine) switch { case dbMachine.Provider != stitchMachine.Provider: return -1 case dbMachine.Region != stitchMachine.Region: return -1 case dbMachine.Size != "" && stitchMachine.Size != dbMachine.Size: return -1 case dbMachine.Role != db.None && dbMachine.Role != stitchMachine.Role: return -1 case dbMachine.DiskSize != stitchMachine.DiskSize: return -1 case dbMachine.PrivateIP == "": return 2 case dbMachine.PublicIP == "": return 1 default: return 0 } } pairs, bootList, terminateList := join.Join(stitchMachines, dbMachines, scoreFun) for _, toTerminate := range terminateList { toTerminate := toTerminate.(db.Machine) view.Remove(toTerminate) } for _, bootSet := range bootList { bootSet := bootSet.(db.Machine) pairs = append(pairs, join.Pair{L: bootSet, R: view.InsertMachine()}) } for _, pair := range pairs { stitchMachine := pair.L.(db.Machine) dbMachine := pair.R.(db.Machine) dbMachine.Role = stitchMachine.Role dbMachine.Size = stitchMachine.Size dbMachine.DiskSize = stitchMachine.DiskSize dbMachine.Provider = stitchMachine.Provider dbMachine.Region = stitchMachine.Region dbMachine.SSHKeys = stitchMachine.SSHKeys view.Commit(dbMachine) } return nil }
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 updateWorker(view db.Database, self db.Minion, store Store, etcdData storeData) { var containers []storeContainer for _, etcdc := range etcdData.containers { if etcdc.Minion == self.PrivateIP { containers = append(containers, etcdc) } } pairs, dbcs, etcdcs := join.Join(view.SelectFromContainer(nil), containers, func(left, right interface{}) int { dbc := left.(db.Container) l := storeContainer{ StitchID: dbc.StitchID, Minion: dbc.Minion, Image: dbc.Image, Command: dbc.Command, Env: dbc.Env, Labels: dbc.Labels, } return containerJoinScore(l, right.(storeContainer)) }) for _, i := range dbcs { dbc := i.(db.Container) view.Remove(dbc) } for _, etcdc := range etcdcs { pairs = append(pairs, join.Pair{ L: view.InsertContainer(), R: etcdc, }) } for _, pair := range pairs { dbc := pair.L.(db.Container) etcdc := pair.R.(storeContainer) dbc.StitchID = etcdc.StitchID dbc.Minion = etcdc.Minion dbc.Image = etcdc.Image dbc.Command = etcdc.Command dbc.Env = etcdc.Env dbc.Labels = etcdc.Labels view.Commit(dbc) } updateContainerIP(view.SelectFromContainer(nil), self.PrivateIP, store) }
func updateContainers(view db.Database, spec stitch.Stitch) { score := func(l, r interface{}) int { left := l.(db.Container) right := r.(db.Container) if left.Image != right.Image || !util.StrSliceEqual(left.Command, right.Command) || !util.StrStrMapEqual(left.Env, right.Env) { return -1 } score := util.EditDistance(left.Labels, right.Labels) if left.StitchID != right.StitchID { score++ } return score } pairs, news, dbcs := join.Join(queryContainers(spec), view.SelectFromContainer(nil), score) for _, dbc := range dbcs { view.Remove(dbc.(db.Container)) } for _, new := range news { pairs = append(pairs, join.Pair{L: new, R: view.InsertContainer()}) } for _, pair := range pairs { newc := pair.L.(db.Container) dbc := pair.R.(db.Container) // By sorting the labels we prevent the database from getting confused // when their order is non deterministic. dbc.Labels = newc.Labels sort.Sort(sort.StringSlice(dbc.Labels)) dbc.Command = newc.Command dbc.Image = newc.Image dbc.Env = newc.Env dbc.StitchID = newc.StitchID view.Commit(dbc) } }
func (sv *supervisor) runAppTransact(view db.Database, dkcsArgs []docker.Container) []string { var tearDowns []string dbKey := func(val interface{}) interface{} { return val.(db.Container).DockerID } dkKey := func(val interface{}) interface{} { return val.(docker.Container).ID } pairs, dbcs, dkcs := join.HashJoin(db.ContainerSlice( view.SelectFromContainer(nil)), docker.ContainerSlice(dkcsArgs), dbKey, dkKey) for _, iface := range dbcs { dbc := iface.(db.Container) tearDowns = append(tearDowns, dbc.DockerID) view.Remove(dbc) } for _, dkc := range dkcs { pairs = append(pairs, join.Pair{L: view.InsertContainer(), R: dkc}) } for _, pair := range pairs { dbc := pair.L.(db.Container) dkc := pair.R.(docker.Container) dbc.DockerID = dkc.ID dbc.Pid = dkc.Pid dbc.Image = dkc.Image dbc.Command = append([]string{dkc.Path}, dkc.Args...) view.Commit(dbc) } return tearDowns }
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) } }