From f1248425053b808ccd1e89193405048f5e52258c Mon Sep 17 00:00:00 2001 From: Brendan Burns Date: Mon, 26 Jan 2015 16:11:16 -0800 Subject: [PATCH] Clear pod cache on delete. --- pkg/master/pod_cache.go | 7 +++++++ pkg/master/pod_cache_test.go | 30 ++++++++++++++++++++++++++++++ pkg/registry/pod/rest.go | 7 +++++++ pkg/registry/pod/rest_test.go | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/pkg/master/pod_cache.go b/pkg/master/pod_cache.go index 50a293417c7..e75237e3d56 100644 --- a/pkg/master/pod_cache.go +++ b/pkg/master/pod_cache.go @@ -79,6 +79,13 @@ func (p *PodCache) GetPodStatus(namespace, name string) (*api.PodStatus, error) return &value, nil } +func (p *PodCache) ClearPodStatus(namespace, name string) { + p.lock.Lock() + defer p.lock.Unlock() + + delete(p.podStatus, objKey{namespace, name}) +} + func (p *PodCache) getNodeStatusInCache(name string) (*api.NodeStatus, bool) { p.lock.Lock() defer p.lock.Unlock() diff --git a/pkg/master/pod_cache_test.go b/pkg/master/pod_cache_test.go index b3532ed91a5..928bb24bc4e 100644 --- a/pkg/master/pod_cache_test.go +++ b/pkg/master/pod_cache_test.go @@ -125,6 +125,36 @@ func TestPodCacheGet(t *testing.T) { } } +func TestPodCacheDelete(t *testing.T) { + cache := NewPodCache(nil, nil, nil, nil) + + expected := api.PodStatus{ + Info: api.PodInfo{ + "foo": api.ContainerStatus{}, + }, + } + cache.podStatus[objKey{api.NamespaceDefault, "foo"}] = expected + + info, err := cache.GetPodStatus(api.NamespaceDefault, "foo") + if err != nil { + t.Errorf("Unexpected error: %+v", err) + } + if !reflect.DeepEqual(info, &expected) { + t.Errorf("Unexpected mismatch. Expected: %+v, Got: %+v", &expected, info) + } + + cache.ClearPodStatus(api.NamespaceDefault, "foo") + + _, err = cache.GetPodStatus(api.NamespaceDefault, "foo") + if err == nil { + t.Errorf("Unexpected non-error after deleting") + } + if err != client.ErrPodInfoNotAvailable { + t.Errorf("Unexpected error: %v, expecting: %v", err, client.ErrPodInfoNotAvailable) + } + +} + func TestPodCacheGetMissing(t *testing.T) { cache := NewPodCache(nil, nil, nil, nil) diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index d6a3f47145e..2693865bbef 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -32,6 +32,7 @@ import ( type PodStatusGetter interface { GetPodStatus(namespace, name string) (*api.PodStatus, error) + ClearPodStatus(namespace, name string) } // REST implements the RESTStorage interface in terms of a PodRegistry. @@ -77,6 +78,12 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { return apiserver.MakeAsync(func() (runtime.Object, error) { + namespace, found := api.NamespaceFrom(ctx) + if !found { + return &api.Status{Status: api.StatusFailure}, nil + } + rs.podCache.ClearPodStatus(namespace, id) + return &api.Status{Status: api.StatusSuccess}, rs.registry.DeletePod(ctx, id) }), nil } diff --git a/pkg/registry/pod/rest_test.go b/pkg/registry/pod/rest_test.go index 0b63cf726b6..50e0ccd3049 100644 --- a/pkg/registry/pod/rest_test.go +++ b/pkg/registry/pod/rest_test.go @@ -36,6 +36,8 @@ import ( type fakeCache struct { requestedNamespace string requestedName string + clearedNamespace string + clearedName string statusToReturn *api.PodStatus errorToReturn error @@ -47,6 +49,11 @@ func (f *fakeCache) GetPodStatus(namespace, name string) (*api.PodStatus, error) return f.statusToReturn, f.errorToReturn } +func (f *fakeCache) ClearPodStatus(namespace, name string) { + f.clearedNamespace = namespace + f.clearedName = name +} + func expectApiStatusError(t *testing.T, ch <-chan apiserver.RESTResult, msg string) { out := <-ch status, ok := out.Object.(*api.Status) @@ -583,3 +590,31 @@ func TestResourceLocation(t *testing.T) { } } } + +func TestDeletePod(t *testing.T) { + podRegistry := registrytest.NewPodRegistry(nil) + podRegistry.Pod = &api.Pod{ + ObjectMeta: api.ObjectMeta{Name: "foo"}, + Status: api.PodStatus{Host: "machine"}, + } + fakeCache := &fakeCache{} + storage := REST{ + registry: podRegistry, + podCache: fakeCache, + } + ctx := api.NewDefaultContext() + channel, err := storage.Delete(ctx, "foo") + if err != nil { + t.Errorf("unexpected error: %v", err) + } + var result apiserver.RESTResult + select { + case result = <-channel: + // Do nothing, this is expected. + case <-time.After(time.Millisecond * 100): + t.Error("Unexpected timeout on async channel") + } + if fakeCache.clearedNamespace != "default" || fakeCache.clearedName != "foo" { + t.Errorf("Unexpeceted cache delete: %s %s %#v", fakeCache.clearedName, fakeCache.clearedNamespace, result.Object) + } +}