From e49cd1ad231c299e4535d189090d7c1dadd9900a Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Fri, 24 Feb 2023 10:41:57 -0600 Subject: [PATCH] enhance(executor tests): Call k8s SetupMock method after CreateBuild in tests (#425) * enhance: extract kubernetes runtime mock setup In order to run the PodTracker mock setup in executor tests, we need to export something * Call k8s SetupMock in executor Build test * test: Add kubernetes SetupMock to executor StreamBuild test * mark exported k8s Mock functions as test-only functions --- executor/linux/build_test.go | 26 +++++++++++++++++++++++++- executor/linux/secret_test.go | 24 ++++++++++++++++++++++++ runtime/kubernetes/mock.go | 15 ++++++++++++++- runtime/kubernetes/pod_tracker.go | 18 ++++++++++++++---- 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/executor/linux/build_test.go b/executor/linux/build_test.go index fa0d0e0e..1ee74edd 100644 --- a/executor/linux/build_test.go +++ b/executor/linux/build_test.go @@ -1529,6 +1529,14 @@ func TestLinux_ExecBuild(t *testing.T) { // go-vela/server has logic to set it to an expected state. _engine.build.SetStatus("running") + // Kubernetes runtime needs to set up the Mock after CreateBuild is called + if test.runtime == constants.DriverKubernetes { + err = _runtime.(kubernetes.MockKubernetesRuntime).SetupMock() + if err != nil { + t.Errorf("Kubernetes runtime SetupMock returned err: %v", err) + } + } + err = _engine.ExecBuild(context.Background()) if test.failure { @@ -1882,8 +1890,16 @@ func TestLinux_StreamBuild(t *testing.T) { t.Errorf("%s unable to create build: %v", test.name, err) } - // simulate ExecBuild() which runs concurrently with StreamBuild() + // simulate AssembleBuild()/ExecBuild() which run concurrently with StreamBuild() go func() { + // This Kubernetes setup would normally be called within AssembleBuild() + if test.runtime == constants.DriverKubernetes { + err = _runtime.(kubernetes.MockKubernetesRuntime).SetupMock() + if err != nil { + t.Errorf("Kubernetes runtime SetupMock returned err: %v", err) + } + } + if test.earlyBuildDone { // imitate build getting canceled or otherwise finishing before ExecBuild gets called. done() @@ -2092,6 +2108,14 @@ func TestLinux_DestroyBuild(t *testing.T) { t.Errorf("%s unable to create build: %v", test.name, err) } + // Kubernetes runtime needs to set up the Mock after CreateBuild is called + if test.runtime == constants.DriverKubernetes { + err = _runtime.(kubernetes.MockKubernetesRuntime).SetupMock() + if err != nil { + t.Errorf("Kubernetes runtime SetupMock returned err: %v", err) + } + } + err = _engine.DestroyBuild(context.Background()) if test.failure { diff --git a/executor/linux/secret_test.go b/executor/linux/secret_test.go index 9cdbcffb..01740c83 100644 --- a/executor/linux/secret_test.go +++ b/executor/linux/secret_test.go @@ -235,6 +235,14 @@ func TestLinux_Secret_delete(t *testing.T) { // add init container info to client _ = _engine.CreateBuild(context.Background()) + // Kubernetes runtime needs to set up the Mock after CreateBuild is called + if test.runtime.Driver() == constants.DriverKubernetes { + err = _engine.Runtime.(kubernetes.MockKubernetesRuntime).SetupMock() + if err != nil { + t.Errorf("Kubernetes runtime SetupMock returned err: %v", err) + } + } + _engine.steps.Store(test.container.ID, test.step) err = _engine.secret.destroy(context.Background(), test.container) @@ -349,6 +357,14 @@ func TestLinux_Secret_exec(t *testing.T) { // add init container info to client _ = _engine.CreateBuild(context.Background()) + // Kubernetes runtime needs to set up the Mock after CreateBuild is called + if test.runtime == constants.DriverKubernetes { + err = _runtime.(kubernetes.MockKubernetesRuntime).SetupMock() + if err != nil { + t.Errorf("Kubernetes runtime SetupMock returned err: %v", err) + } + } + err = _engine.secret.exec(context.Background(), &p.Secrets) if test.failure { @@ -623,6 +639,14 @@ func TestLinux_Secret_stream(t *testing.T) { // add init container info to client _ = _engine.CreateBuild(context.Background()) + // Kubernetes runtime needs to set up the Mock after CreateBuild is called + if test.runtime.Driver() == constants.DriverKubernetes { + err = _engine.Runtime.(kubernetes.MockKubernetesRuntime).SetupMock() + if err != nil { + t.Errorf("Kubernetes runtime SetupMock returned err: %v", err) + } + } + err = _engine.secret.stream(context.Background(), test.container) if test.failure { diff --git a/runtime/kubernetes/mock.go b/runtime/kubernetes/mock.go index b409a157..077d52eb 100644 --- a/runtime/kubernetes/mock.go +++ b/runtime/kubernetes/mock.go @@ -4,14 +4,17 @@ package kubernetes +// Everything in this file should only be used in test code. +// It is exported for use in tests of other packages. + import ( - "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" fakeVelaK8sClient "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/fake" + "github.com/sirupsen/logrus" ) // NewMock returns an Engine implementation that @@ -90,10 +93,20 @@ func NewMock(_pod *v1.Pod, opts ...ClientOpt) (*client, error) { // // This interface is intended for running tests only. type MockKubernetesRuntime interface { + SetupMock() error MarkPodTrackerReady() SimulateResync(*v1.Pod) } +// SetupMock allows the Kubernetes runtime to perform additional Mock-related config. +// Many tests should call this right after they call runtime.SetupBuild (or executor.CreateBuild). +// +// This function is intended for running tests only. +func (c *client) SetupMock() error { + // This assumes that c.Pod.ObjectMeta.Namespace and c.Pod.ObjectMeta.Name are filled in. + return c.PodTracker.setupMockFor(c.Pod) +} + // MarkPodTrackerReady signals that PodTracker has been setup with ContainerTrackers. // // This function is intended for running tests only. diff --git a/runtime/kubernetes/pod_tracker.go b/runtime/kubernetes/pod_tracker.go index 221e881f..65e1b2d8 100644 --- a/runtime/kubernetes/pod_tracker.go +++ b/runtime/kubernetes/pod_tracker.go @@ -251,14 +251,24 @@ func mockPodTracker(log *logrus.Entry, clientset kubernetes.Interface, pod *v1.P return nil, err } + err = tracker.setupMockFor(pod) + if err != nil { + return nil, err + } + + return tracker, err +} + +// setupMockFor initializes the podTracker's internal caches with the given pod. +func (p *podTracker) setupMockFor(pod *v1.Pod) error { // init containerTrackers as well - tracker.TrackContainers(pod.Spec.Containers) + p.TrackContainers(pod.Spec.Containers) // pre-populate the podInformer cache - err = tracker.podInformer.Informer().GetIndexer().Add(pod) + err := p.podInformer.Informer().GetIndexer().Add(pod) if err != nil { - return nil, err + return err } - return tracker, err + return nil }