func testContainerTxn(t *testing.T, conn db.Conn, spec string) { compiled, err := stitch.FromJavascript(spec, stitch.DefaultImportGetter) assert.Nil(t, err) var containers []db.Container conn.Transact(func(view db.Database) error { updatePolicy(view, db.Master, compiled.String()) containers = view.SelectFromContainer(nil) return nil }) for _, e := range queryContainers(compiled) { found := false for i, c := range containers { if e.Image == c.Image && reflect.DeepEqual(e.Command, c.Command) && util.EditDistance(c.Labels, e.Labels) == 0 { containers = append(containers[:i], containers[i+1:]...) found = true break } } assert.True(t, found) } assert.Empty(t, containers) }
func syncDB(view db.Database, dkcsArg []docker.Container) ([]string, []db.Container) { score := func(left, right interface{}) int { dbc := left.(db.Container) dkc := right.(docker.Container) // Depending on the container, the command in the database could be // either The command plus it's arguments, or just it's arguments. To // handle that case, we check both. cmd1 := dkc.Args cmd2 := append([]string{dkc.Path}, dkc.Args...) dbcCmd := dbc.Command for key, value := range dbc.Env { if dkc.Env[key] != value { return -1 } } var dkcLabels []string for label, value := range dkc.Labels { if !docker.IsUserLabel(label) || value != docker.LabelTrueValue { continue } dkcLabels = append(dkcLabels, docker.ParseUserLabel(label)) } switch { case dkc.Image != dbc.Image: return -1 case len(dbcCmd) != 0 && !strEq(dbcCmd, cmd1) && !strEq(dbcCmd, cmd2): return -1 case dkc.ID == dbc.DockerID: return 0 default: return util.EditDistance(dbc.Labels, dkcLabels) } } pairs, dbcs, dkcs := join.Join(view.SelectFromContainer(nil), dkcsArg, score) for _, pair := range pairs { dbc := pair.L.(db.Container) dbc.DockerID = pair.R.(docker.Container).ID view.Commit(dbc) } var term []string for _, dkc := range dkcs { term = append(term, dkc.(docker.Container).ID) } var boot []db.Container for _, dbc := range dbcs { boot = append(boot, dbc.(db.Container)) } return term, boot }
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 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 testContainerTxn(conn db.Conn, spec string) string { var containers []db.Container conn.Transact(func(view db.Database) error { updatePolicy(view, db.Master, spec) containers = view.SelectFromContainer(nil) return nil }) var sc scanner.Scanner compiled, err := stitch.New(*sc.Init(strings.NewReader(spec)), "", false) if err != nil { return err.Error() } for _, e := range queryContainers(compiled) { found := false for i, c := range containers { if e.Image == c.Image && reflect.DeepEqual(e.Command, c.Command) && util.EditDistance(c.Labels, e.Labels) == 0 { containers = append(containers[:i], containers[i+1:]...) found = true break } } if found == false { return fmt.Sprintf("Missing expected label set: %v\n%v", e, containers) } } if len(containers) > 0 { return spew.Sprintf("Unexpected containers: %s", containers) } return "" }