func updateContainerIP(containers []db.Container, privateIP string, store Store) { oldIPMap := map[string]string{} selfStore := path.Join(nodeStore, privateIP) etcdIPs, err := store.Get(path.Join(selfStore, minionIPStore)) if err != nil { etcdErr, ok := err.(client.Error) if !ok || etcdErr.Code != client.ErrorCodeKeyNotFound { log.WithError(err).Error("Failed to load current IPs from Etcd") return } } json.Unmarshal([]byte(etcdIPs), &oldIPMap) newIPMap := map[string]string{} for _, c := range containers { newIPMap[strconv.Itoa(c.StitchID)] = c.IP } if util.StrStrMapEqual(oldIPMap, newIPMap) { return } jsonData, err := json.Marshal(newIPMap) if err != nil { log.WithError(err).Error("Failed to marshal minion container IP map") return } err = store.Set(path.Join(selfStore, minionIPStore), string(jsonData), 0) if err != nil { log.WithError(err).Error("Failed to update minion container IP map") } }
func containerJoinScore(left, right storeContainer) int { if left.Minion != right.Minion || 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 }
func updateEtcdLabel(s Store, etcdData storeData, containers []db.Container) (storeData, error) { // Collect a map of labels to all of the containers that have that label. labelContainers := map[string][]db.Container{} for _, c := range containers { for _, l := range c.Labels { labelContainers[l] = append(labelContainers[l], c) } } newMultiHosts := map[string]string{} // Gather the multihost containers and set the IPs of non-multihost containers // at the same time. The single host IPs are retrieved from the map of container // IPs that updateEtcdDocker created. for label, cs := range labelContainers { if len(cs) > 1 { newMultiHosts[label] = "" } } // Etcd is the source of truth for IPs. If the label exists in both etcd and the // db and it is a multihost label, then assign it the IP that etcd has. // Otherwise, it stays unassigned and syncLabelIPs will take care of it. for id := range newMultiHosts { if ip, ok := etcdData.multiHost[id]; ok { newMultiHosts[id] = ip } } // No need to sync the SingleHost IPs, since they get their IPs from the dockerIP // map, which was already synced in updateEtcdDocker syncLabelIPs(newMultiHosts) if util.StrStrMapEqual(newMultiHosts, etcdData.multiHost) { return etcdData, nil } newLabelJSON, _ := json.Marshal(newMultiHosts) if err := s.Set(labelToIPStore, string(newLabelJSON), 0); err != nil { return etcdData, err } etcdData.multiHost = newMultiHosts return etcdData, nil }
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) } }