* Light up UpdatePod This PR updates the vkublet/pod.go createOrUpdate(..) method to actually handle updates. It gets the pod from the provider as before, but now if it exists the method checks the hash of the spec against the spec of the new pod. If they've changed, it calls UpdatePod(..). Also makes a small change to the Server struct to swap from kuberentes.Clientset to kubernetes.Interface to better facilitate testing with fake ClientSet. Co-Authored-By: Brian Goff <cpuguy83@gmail.com>
287 lines
6.0 KiB
Go
287 lines
6.0 KiB
Go
package vkubelet
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/virtual-kubelet/virtual-kubelet/providers/mock"
|
|
testutil "github.com/virtual-kubelet/virtual-kubelet/test/util"
|
|
"gotest.tools/assert"
|
|
is "gotest.tools/assert/cmp"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/client-go/kubernetes/fake"
|
|
)
|
|
|
|
type FakeProvider struct {
|
|
*mock.MockProvider
|
|
createFn func()
|
|
updateFn func()
|
|
}
|
|
|
|
func (f *FakeProvider) CreatePod(ctx context.Context, pod *corev1.Pod) error {
|
|
f.createFn()
|
|
return f.MockProvider.CreatePod(ctx, pod)
|
|
}
|
|
|
|
func (f *FakeProvider) UpdatePod(ctx context.Context, pod *corev1.Pod) error {
|
|
f.updateFn()
|
|
return f.MockProvider.CreatePod(ctx, pod)
|
|
}
|
|
|
|
type TestServer struct {
|
|
*Server
|
|
mock *FakeProvider
|
|
client *fake.Clientset
|
|
}
|
|
|
|
func newMockProvider(t *testing.T) (*mock.MockProvider, error) {
|
|
return mock.NewMockProviderMockConfig(
|
|
mock.MockConfig{},
|
|
"vk123",
|
|
"linux",
|
|
"127.0.0.1",
|
|
443,
|
|
)
|
|
}
|
|
|
|
func newTestServer(t *testing.T) *TestServer {
|
|
|
|
mockProvider, err := newMockProvider(t)
|
|
assert.Check(t, is.Nil(err))
|
|
|
|
fk8s := fake.NewSimpleClientset()
|
|
|
|
fakeProvider := &FakeProvider{
|
|
MockProvider: mockProvider,
|
|
}
|
|
|
|
rm := testutil.FakeResourceManager()
|
|
|
|
tsvr := &TestServer{
|
|
Server: &Server{
|
|
namespace: "default",
|
|
nodeName: "vk123",
|
|
provider: fakeProvider,
|
|
resourceManager: rm,
|
|
k8sClient: fk8s,
|
|
},
|
|
mock: fakeProvider,
|
|
client: fk8s,
|
|
}
|
|
return tsvr
|
|
}
|
|
|
|
func TestPodHashingEqual(t *testing.T) {
|
|
p1 := corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
corev1.Container{
|
|
Name: "nginx",
|
|
Image: "nginx:1.15.12-perl",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
h1 := hashPodSpec(p1)
|
|
|
|
p2 := corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
corev1.Container{
|
|
Name: "nginx",
|
|
Image: "nginx:1.15.12-perl",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
h2 := hashPodSpec(p2)
|
|
assert.Check(t, is.Equal(h1, h2))
|
|
}
|
|
|
|
func TestPodHashingDifferent(t *testing.T) {
|
|
p1 := corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
corev1.Container{
|
|
Name: "nginx",
|
|
Image: "nginx:1.15.12",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
h1 := hashPodSpec(p1)
|
|
|
|
p2 := corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
corev1.Container{
|
|
Name: "nginx",
|
|
Image: "nginx:1.15.12-perl",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
h2 := hashPodSpec(p2)
|
|
assert.Check(t, h1 != h2)
|
|
}
|
|
|
|
func TestPodCreateNewPod(t *testing.T) {
|
|
svr := newTestServer(t)
|
|
|
|
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",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
created := false
|
|
updated := false
|
|
// The pod doesn't exist, we should invoke the CreatePod() method of the provider
|
|
svr.mock.createFn = func() {
|
|
created = true
|
|
}
|
|
svr.mock.updateFn = func() {
|
|
updated = true
|
|
}
|
|
er := testutil.FakeEventRecorder(5)
|
|
err := svr.createOrUpdatePod(context.Background(), pod, er)
|
|
assert.Check(t, is.Nil(err))
|
|
// createOrUpdate called CreatePod but did not call UpdatePod because the pod did not exist
|
|
assert.Check(t, created)
|
|
assert.Check(t, !updated)
|
|
}
|
|
|
|
func TestPodUpdateExisting(t *testing.T) {
|
|
svr := newTestServer(t)
|
|
|
|
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",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
err := svr.mock.MockProvider.CreatePod(context.Background(), pod)
|
|
assert.Check(t, is.Nil(err))
|
|
created := false
|
|
updated := false
|
|
// The pod doesn't exist, we should invoke the CreatePod() method of the provider
|
|
svr.mock.createFn = func() {
|
|
created = true
|
|
}
|
|
svr.mock.updateFn = func() {
|
|
updated = true
|
|
}
|
|
|
|
pod2 := &corev1.Pod{}
|
|
pod2.ObjectMeta.Namespace = "default"
|
|
pod2.ObjectMeta.Name = "nginx"
|
|
pod2.Spec = corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
corev1.Container{
|
|
Name: "nginx",
|
|
Image: "nginx:1.15.12-perl",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
er := testutil.FakeEventRecorder(5)
|
|
err = svr.createOrUpdatePod(context.Background(), pod2, er)
|
|
assert.Check(t, is.Nil(err))
|
|
|
|
// createOrUpdate didn't call CreatePod but did call UpdatePod because the spec changed
|
|
assert.Check(t, !created)
|
|
assert.Check(t, updated)
|
|
}
|
|
|
|
func TestPodNoSpecChange(t *testing.T) {
|
|
svr := newTestServer(t)
|
|
|
|
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",
|
|
Ports: []corev1.ContainerPort{
|
|
corev1.ContainerPort{
|
|
ContainerPort: 443,
|
|
Protocol: "tcp",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
err := svr.mock.MockProvider.CreatePod(context.Background(), pod)
|
|
assert.Check(t, is.Nil(err))
|
|
created := false
|
|
updated := false
|
|
// The pod doesn't exist, we should invoke the CreatePod() method of the provider
|
|
svr.mock.createFn = func() {
|
|
created = true
|
|
}
|
|
svr.mock.updateFn = func() {
|
|
updated = true
|
|
}
|
|
|
|
er := testutil.FakeEventRecorder(5)
|
|
err = svr.createOrUpdatePod(context.Background(), pod, er)
|
|
assert.Check(t, is.Nil(err))
|
|
|
|
// createOrUpdate didn't call CreatePod or UpdatePod, spec didn't change
|
|
assert.Check(t, !created)
|
|
assert.Check(t, !updated)
|
|
}
|