Fix error handling for delete pod (#685)
* Fix error handling for delete pod - Error handling was looking for a k8s error from the provider, but providers should be using errdefs. - Error handling was returning early if pod was not found and deleting from k8s in all other cases. * Don't run unit tests twice
This commit is contained in:
6
Makefile
6
Makefile
@@ -83,11 +83,9 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@echo "Testing..."
|
|
||||||
$Q go test -mod=vendor $(if $V,-v) $(allpackages) # install -race libs to speed up next run
|
|
||||||
ifndef CI
|
ifndef CI
|
||||||
@echo "Testing Outside CI..."
|
@echo "Testing..."
|
||||||
$Q GODEBUG=cgocheck=2 go test -mod=vendor $(allpackages)
|
$Q go test -mod=vendor $(if $V,-v) $(allpackages)
|
||||||
else
|
else
|
||||||
@echo "Testing in CI..."
|
@echo "Testing in CI..."
|
||||||
$Q mkdir -p test
|
$Q mkdir -p test
|
||||||
|
|||||||
12
node/pod.go
12
node/pod.go
@@ -145,20 +145,18 @@ func (pc *PodController) deletePod(ctx context.Context, namespace, name string)
|
|||||||
ctx = addPodAttributes(ctx, span, pod)
|
ctx = addPodAttributes(ctx, span, pod)
|
||||||
|
|
||||||
var delErr error
|
var delErr error
|
||||||
if delErr = pc.provider.DeletePod(ctx, pod); delErr != nil && errors.IsNotFound(delErr) {
|
if delErr = pc.provider.DeletePod(ctx, pod); delErr != nil && !errdefs.IsNotFound(delErr) {
|
||||||
span.SetStatus(delErr)
|
span.SetStatus(delErr)
|
||||||
return delErr
|
return delErr
|
||||||
}
|
}
|
||||||
|
|
||||||
log.G(ctx).Debug("Deleted pod from provider")
|
log.G(ctx).Debug("Deleted pod from provider")
|
||||||
|
|
||||||
if !errors.IsNotFound(delErr) {
|
if err := pc.forceDeletePodResource(ctx, namespace, name); err != nil {
|
||||||
if err := pc.forceDeletePodResource(ctx, namespace, name); err != nil {
|
span.SetStatus(err)
|
||||||
span.SetStatus(err)
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.G(ctx).Info("Deleted pod from Kubernetes")
|
|
||||||
}
|
}
|
||||||
|
log.G(ctx).Info("Deleted pod from Kubernetes")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
pkgerrors "github.com/pkg/errors"
|
||||||
"github.com/virtual-kubelet/virtual-kubelet/errdefs"
|
"github.com/virtual-kubelet/virtual-kubelet/errdefs"
|
||||||
testutil "github.com/virtual-kubelet/virtual-kubelet/internal/test/util"
|
testutil "github.com/virtual-kubelet/virtual-kubelet/internal/test/util"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,6 +36,8 @@ type mockProvider struct {
|
|||||||
creates int
|
creates int
|
||||||
updates int
|
updates int
|
||||||
deletes int
|
deletes int
|
||||||
|
|
||||||
|
errorOnDelete error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockProvider) CreatePod(ctx context.Context, pod *corev1.Pod) error {
|
func (m *mockProvider) CreatePod(ctx context.Context, pod *corev1.Pod) error {
|
||||||
@@ -64,6 +69,9 @@ func (m *mockProvider) GetPodStatus(ctx context.Context, namespace, name string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockProvider) DeletePod(ctx context.Context, p *corev1.Pod) error {
|
func (m *mockProvider) DeletePod(ctx context.Context, p *corev1.Pod) error {
|
||||||
|
if m.errorOnDelete != nil {
|
||||||
|
return m.errorOnDelete
|
||||||
|
}
|
||||||
delete(m.pods, path.Join(p.GetNamespace(), p.GetName()))
|
delete(m.pods, path.Join(p.GetNamespace(), p.GetName()))
|
||||||
m.deletes++
|
m.deletes++
|
||||||
return nil
|
return nil
|
||||||
@@ -293,3 +301,63 @@ func TestPodNoSpecChange(t *testing.T) {
|
|||||||
assert.Check(t, is.Equal(svr.mock.creates, 1))
|
assert.Check(t, is.Equal(svr.mock.creates, 1))
|
||||||
assert.Check(t, is.Equal(svr.mock.updates, 0))
|
assert.Check(t, is.Equal(svr.mock.updates, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPodDelete(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
desc string
|
||||||
|
delErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []testCase{
|
||||||
|
{desc: "no error on delete", delErr: nil},
|
||||||
|
{desc: "not found error on delete", delErr: errdefs.NotFound("not found")},
|
||||||
|
{desc: "unknown error on delete", delErr: pkgerrors.New("random error")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
c := newTestController()
|
||||||
|
c.mock.errorOnDelete = tc.delErr
|
||||||
|
|
||||||
|
pod := &corev1.Pod{}
|
||||||
|
pod.ObjectMeta.Namespace = "default"
|
||||||
|
pod.ObjectMeta.Name = "nginx"
|
||||||
|
pod.Spec = corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
corev1.Container{
|
||||||
|
Name: "nginx",
|
||||||
|
Image: "nginx:1.15.12",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pc := c.client.CoreV1().Pods("default")
|
||||||
|
|
||||||
|
p, err := pc.Create(pod)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
err = c.createOrUpdatePod(ctx, p) // make sure it's actually created
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Check(t, is.Equal(c.mock.creates, 1))
|
||||||
|
|
||||||
|
err = c.deletePod(ctx, pod.Namespace, pod.Name)
|
||||||
|
assert.Equal(t, pkgerrors.Cause(err), err)
|
||||||
|
|
||||||
|
var expectDeletes int
|
||||||
|
if tc.delErr == nil {
|
||||||
|
expectDeletes = 1
|
||||||
|
}
|
||||||
|
assert.Check(t, is.Equal(c.mock.deletes, expectDeletes))
|
||||||
|
|
||||||
|
expectDeleted := tc.delErr == nil || errdefs.IsNotFound(tc.delErr)
|
||||||
|
|
||||||
|
_, err = pc.Get(pod.Name, metav1.GetOptions{})
|
||||||
|
if expectDeleted {
|
||||||
|
assert.Assert(t, errors.IsNotFound(err))
|
||||||
|
} else {
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user