Change:
for name, item := range table { fakeClient, registry := NewTestGenericEtcdRegistry(t) fakeClient.Data[path] = item.existing <del> err := registry.CreateWithName(api.NewContext(), key, item.toCreate) </del> <ins> err := registry.CreateWithName(api.NewDefaultContext(), key, item.toCreate) </ins> if !item.errOK(err) { t.Errorf("%v: unexpected error: %v", name, err) } <del> if e, a := item.expect, fakeClient.Data[path]; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v:n%s", name, util.ObjectDiff(e, a)) </del> <ins> actual := fakeClient.Data[path] if item.objOK != nil { obj, err := api.Scheme.Decode([]byte(actual.R.Node.Value)) if err != nil { t.Errorf("unable to decode stored value for %#v", actual) continue } if !item.objOK(obj) { t.Errorf("%v: unexpected response: %v", name, actual) } } else { if e, a := item.expect, actual; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v:n%s", name, util.ObjectDiff(e, a)) } </ins> } } } func TestEtcdUpdate(t *testing.T) { podA := &api.Pod{ <ins> ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Status:     api.PodStatus{Host: "machine"}, } podB := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1"}, Status:     api.PodStatus{Host: "machine2"}, } nodeWithPodA := tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value:         runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 1, CreatedIndex:  1, }, }, E: nil, } newerNodeWithPodA := tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value:         runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 2, CreatedIndex:  1, }, }, E: nil, } nodeWithPodB := tools.EtcdResponseWithError{ R: &etcd.Response{ Node: &etcd.Node{ Value:         runtime.EncodeOrDie(testapi.Codec(), podB), ModifiedIndex: 1, CreatedIndex:  1, }, }, E: nil, } emptyNode := tools.EtcdResponseWithError{ R: &etcd.Response{}, E: tools.EtcdErrorNotFound, } path := "/registry/pods/foo" table := map[string]struct { existing    tools.EtcdResponseWithError expect      tools.EtcdResponseWithError toUpdate    runtime.Object allowCreate bool objOK       func(obj runtime.Object) bool errOK       func(error) bool }{ "normal": { existing: nodeWithPodA, expect:   nodeWithPodB, toUpdate: podB, errOK:    func(err error) bool { return err == nil }, }, "notExisting": { existing: emptyNode, expect:   emptyNode, toUpdate: podA, errOK:    func(err error) bool { return errors.IsNotFound(err) }, }, "createIfNotFound": { existing:    emptyNode, toUpdate:    podA, allowCreate: true, objOK:       hasCreated(t, podA), errOK:       func(err error) bool { return err == nil }, }, "outOfDate": { existing: newerNodeWithPodA, expect:   newerNodeWithPodA, toUpdate: podB, errOK:    func(err error) bool { return errors.IsConflict(err) }, }, } for name, item := range table { fakeClient, registry := NewTestGenericEtcdRegistry(t) registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = item.allowCreate fakeClient.Data[path] = item.existing obj, _, err := registry.Update(api.NewDefaultContext(), item.toUpdate) if !item.errOK(err) { t.Errorf("%v: unexpected error: %v", name, err) } actual := fakeClient.Data[path] if item.objOK != nil { if !item.objOK(obj) { t.Errorf("%v: unexpected returned: %#v", name, obj) } actualObj, err := api.Scheme.Decode([]byte(actual.R.Node.Value)) if err != nil { t.Errorf("unable to decode stored value for %#v", actual) continue } if !item.objOK(actualObj) { t.Errorf("%v: unexpected response: %#v", name, actual) } } else { if e, a := item.expect, actual; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v:n%s", name, util.ObjectDiff(e, a)) } } } } // DEPRECATED func TestEtcdUpdateWithName(t *testing.T) { podA := &api.Pod{ </ins> ObjectMeta: api.ObjectMeta{Name: "foo"}, Status:     api.PodStatus{Host: "machine"}, }

Discussion:
The use of AtomicUpdate by genericetcd doesn't handle conflicting writes by rejecting that to a user. It should. Eventually, we may want to hide write conflicts to /pods when status has changed, and to spec when /pods/status changes, but that requires us to have two version counters and that's not worth the effort. Fix incoming.
Also we need a unit/integration test for this.