From 802a4833312b0f35b57910e7c9c64606adec4ec4 Mon Sep 17 00:00:00 2001 From: David Elie-Dit-Cosaque Date: Mon, 12 Aug 2024 16:49:17 -0500 Subject: [PATCH] pod: add unit test for executor --- pkg/pod/pod.go | 32 +++++++++++++---- pkg/pod/pod_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 7 deletions(-) diff --git a/pkg/pod/pod.go b/pkg/pod/pod.go index 796c1c759..710c0a448 100644 --- a/pkg/pod/pod.go +++ b/pkg/pod/pod.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net/http" + "net/url" "os" "time" @@ -28,6 +29,12 @@ import ( "github.com/openshift-kni/eco-goinfra/pkg/msg" ) +// GetRestURL Function to use to get the Executor REST URL. +var GetRestURL = getRestExecutorURL + +// NewSPDYExecutor Function to use for the pod remote executor. +var NewSPDYExecutor = remotecommand.NewSPDYExecutor + // Builder provides a struct for pod object from the cluster and a pod definition. type Builder struct { // Pod definition, used to create the pod object. @@ -463,15 +470,14 @@ func (builder *Builder) WaitUntilCondition(condition corev1.PodConditionType, ti }) } -// ExecCommand runs command in the pod and returns the buffer output. -func (builder *Builder) ExecCommand(command []string, containerName ...string) (bytes.Buffer, error) { +// getRestExecutorURL Gets a executor REST URL in the real cluster. +func getRestExecutorURL(builder *Builder, command []string, containerName ...string) (*url.URL, error) { if valid, err := builder.validate(); !valid { - return bytes.Buffer{}, err + return &url.URL{}, err } var ( - buffer bytes.Buffer - cName string + cName string ) if len(containerName) > 0 { @@ -498,10 +504,22 @@ func (builder *Builder) ExecCommand(command []string, containerName ...string) ( TTY: true, }, scheme.ParameterCodec) - exec, err := remotecommand.NewSPDYExecutor(builder.apiClient.Config, "POST", req.URL()) + return req.URL(), nil +} +// ExecCommand runs command in the pod and returns the buffer output. +func (builder *Builder) ExecCommand(command []string, containerName ...string) (bytes.Buffer, error) { + url, err := GetRestURL(builder, command, containerName...) if err != nil { - return buffer, err + return bytes.Buffer{}, err + } + + var buffer bytes.Buffer + + exec, err := NewSPDYExecutor(builder.apiClient.Config, "POST", url) + + if err != nil { + return bytes.Buffer{}, err } err = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{ diff --git a/pkg/pod/pod_test.go b/pkg/pod/pod_test.go index df9fb17e3..7dc9d4c70 100644 --- a/pkg/pod/pod_test.go +++ b/pkg/pod/pod_test.go @@ -1,6 +1,10 @@ package pod import ( + "bytes" + "context" + "net/url" + "reflect" "testing" "time" @@ -10,6 +14,8 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/runtime" k8sfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/remotecommand" ) func buildValidContainterBuilder() *ContainerBuilder { @@ -240,3 +246,85 @@ func getErrorString(err error) string { return err.Error() } + +func TestBuilder_ExecCommand(t *testing.T) { + type args struct { + command []string + containerName []string + } + + tests := []struct { + name string + args args + pod *corev1.Pod + want bytes.Buffer + wantErr bool + }{ + { + name: "ok", + args: args{ + command: []string{"ls"}, + containerName: []string{"test"}, + }, + pod: generateTestPod("test1", "ns1", corev1.PodRunning, corev1.PodReady, false), + want: *bytes.NewBufferString("Command fake output"), + wantErr: false, + }, + } + for _, testcase := range tests { + t.Run(testcase.name, func(t *testing.T) { + var runtimeObjects []runtime.Object + runtimeObjects = append(runtimeObjects, testcase.pod) + builder, err := buildPodTestBuilderWithFakeObjects(runtimeObjects, testcase.pod.Name, testcase.pod.Namespace) + assert.Nil(t, err) + + NewSPDYExecutor = fakeNewSPDYExecutor + GetRestURL = getFakeRestURL + got, err := builder.ExecCommand(testcase.args.command, testcase.args.containerName...) + + if (err != nil) != testcase.wantErr { + t.Errorf("Builder.ExecCommand() error = %v, wantErr %v", err, testcase.wantErr) + + return + } + + if !reflect.DeepEqual(got, testcase.want) { + t.Errorf("Builder.ExecCommand() = %v, want %v", got, testcase.want) + } + }) + } +} + +func getFakeRestURL(builder *Builder, command []string, containerName ...string) (*url.URL, error) { + if valid, err := builder.validate(); !valid { + return &url.URL{}, err + } + + return &url.URL{}, nil +} + +var fakeNewSPDYExecutor = func(config *rest.Config, method string, url *url.URL) (remotecommand.Executor, error) { + return &fakeExecutor{method: method, url: url}, nil +} + +type fakeExecutor struct { + method string + url *url.URL +} + +func (f *fakeExecutor) StreamWithContext(ctx context.Context, options remotecommand.StreamOptions) error { + if options.Stdout != nil { + buf := new(bytes.Buffer) + buf.WriteString("Command fake output") + + if _, err := options.Stdout.Write(buf.Bytes()); err != nil { + return err + } + } + + return nil +} + +func (f *fakeExecutor) Stream(options remotecommand.StreamOptions) error { + return nil +}