Skip to content

Commit

Permalink
enhance(executor tests): Manage k8s mocks for Executor exec tests (#431)
Browse files Browse the repository at this point in the history
  • Loading branch information
cognifloyd authored Feb 27, 2023
1 parent de1eb07 commit a73da0f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 2 deletions.
33 changes: 33 additions & 0 deletions executor/linux/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,36 @@ func TestLinux_ExecBuild(t *testing.T) {
if err != nil {
t.Errorf("Kubernetes runtime SetupMock returned err: %v", err)
}

_runtime.(kubernetes.MockKubernetesRuntime).StartPodTracker(context.Background())

go func() {
_runtime.(kubernetes.MockKubernetesRuntime).SimulateResync(nil)

var stepsRunningCount int

percents := []int{0, 0, 50, 100}
lastIndex := len(percents) - 1
for index, stepsCompletedPercent := range percents {
if index == 0 || index == lastIndex {
stepsRunningCount = 0
} else {
stepsRunningCount = 1
}

err := _runtime.(kubernetes.MockKubernetesRuntime).SimulateStatusUpdate(_pod,
testContainerStatuses(
_pipeline, true, stepsRunningCount, stepsCompletedPercent,
),
)
if err != nil {
t.Errorf("%s - failed to simulate pod update: %s", test.name, err)
}

// simulate exec build duration
time.Sleep(100 * time.Microsecond)
}
}()
}

err = _engine.ExecBuild(context.Background())
Expand Down Expand Up @@ -1910,6 +1940,9 @@ func TestLinux_StreamBuild(t *testing.T) {
if err != nil {
t.Errorf("Kubernetes runtime SetupMock returned err: %v", err)
}

// Runtime.StreamBuild calls PodTracker.Start after the PodTracker is marked Ready
_runtime.(kubernetes.MockKubernetesRuntime).MarkPodTrackerReady()
}

if test.earlyBuildDone {
Expand Down
2 changes: 2 additions & 0 deletions executor/linux/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ func TestLinux_Secret_exec(t *testing.T) {
if err != nil {
t.Errorf("Kubernetes runtime SetupMock returned err: %v", err)
}

go _runtime.(kubernetes.MockKubernetesRuntime).SimulateResync(nil)
}

err = _engine.secret.exec(context.Background(), &p.Secrets)
Expand Down
2 changes: 1 addition & 1 deletion runtime/kubernetes/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func (c *client) AssembleBuild(ctx context.Context, b *pipeline.Build) error {
}
}

// setup containerTeachers now that all containers are defined.
// setup containerTrackers now that all containers are defined.
c.PodTracker.TrackContainers(c.Pod.Spec.Containers)

// send signal to StreamBuild now that PodTracker is ready to be started.
Expand Down
33 changes: 32 additions & 1 deletion runtime/kubernetes/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package kubernetes
// It is exported for use in tests of other packages.

import (
"context"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
Expand Down Expand Up @@ -84,7 +86,8 @@ func NewMock(_pod *v1.Pod, opts ...ClientOpt) (*client, error) {

c.PodTracker = tracker

// The test is responsible for calling c.PodTracker.Start() if needed
// The test is responsible for calling c.PodTracker.Start(ctx) if needed.
// In some cases it is more convenient to call c.(MockKubernetesRuntime).StartPodTracker(ctx)

return c, nil
}
Expand All @@ -95,7 +98,9 @@ func NewMock(_pod *v1.Pod, opts ...ClientOpt) (*client, error) {
type MockKubernetesRuntime interface {
SetupMock() error
MarkPodTrackerReady()
StartPodTracker(context.Context)
SimulateResync(*v1.Pod)
SimulateStatusUpdate(*v1.Pod, []v1.ContainerStatus) error
}

// SetupMock allows the Kubernetes runtime to perform additional Mock-related config.
Expand All @@ -114,6 +119,13 @@ func (c *client) MarkPodTrackerReady() {
close(c.PodTracker.Ready)
}

// StartPodTracker tells the podTracker it can start populating the cache.
//
// This function is intended for running tests only.
func (c *client) StartPodTracker(ctx context.Context) {
c.PodTracker.Start(ctx)
}

// SimulateResync simulates an resync where the PodTracker refreshes its cache.
// This resync is from oldPod to runtime.Pod. If nil, oldPod defaults to runtime.Pod.
//
Expand All @@ -129,3 +141,22 @@ func (c *client) SimulateResync(oldPod *v1.Pod) {
// simulate a re-sync/PodUpdate event
c.PodTracker.HandlePodUpdate(oldPod, c.Pod)
}

// SimulateUpdate simulates an update event from the k8s API.
//
// This function is intended for running tests only.
func (c *client) SimulateStatusUpdate(pod *v1.Pod, containerStatuses []v1.ContainerStatus) error {
// We have to have a full copy here because the k8s client Mock
// replaces the pod it is storing, it does not just update the status.
updatedPod := pod.DeepCopy()
updatedPod.Status.ContainerStatuses = containerStatuses

_, err := c.Kubernetes.CoreV1().Pods(pod.GetNamespace()).
UpdateStatus(
context.Background(),
updatedPod,
metav1.UpdateOptions{},
)

return err
}

0 comments on commit a73da0f

Please sign in to comment.