github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/exec/exec_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package exec
    21  
    22  import (
    23  	"context"
    24  	"fmt"
    25  	"net/http"
    26  
    27  	. "github.com/onsi/ginkgo/v2"
    28  	. "github.com/onsi/gomega"
    29  	corev1 "k8s.io/api/core/v1"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/runtime/schema"
    32  	"k8s.io/cli-runtime/pkg/genericiooptions"
    33  	"k8s.io/client-go/kubernetes/scheme"
    34  	restclient "k8s.io/client-go/rest"
    35  	"k8s.io/client-go/rest/fake"
    36  	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
    37  )
    38  
    39  var _ = Describe("Exec", func() {
    40  	It("new exec command", func() {
    41  		tf := cmdtesting.NewTestFactory().WithNamespace("test")
    42  		defer tf.Cleanup()
    43  		codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
    44  		ns := scheme.Codecs.WithoutConversion()
    45  		tf.Client = &fake.RESTClient{
    46  			GroupVersion:         schema.GroupVersion{Group: "", Version: "v1"},
    47  			NegotiatedSerializer: ns,
    48  			Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
    49  				body := cmdtesting.ObjBody(codec, execPod())
    50  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
    51  			}),
    52  		}
    53  		tf.ClientConfigVal = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: scheme.Codecs, GroupVersion: &schema.GroupVersion{Version: "v1"}}}
    54  
    55  		testOptions := &testExecOptions{ExecOptions: NewExecOptions(tf, genericiooptions.NewTestIOStreamsDiscard())}
    56  		execOptions := testOptions.ExecOptions
    57  
    58  		By("complete")
    59  		testOptions.PodName = "foo"
    60  		Expect(execOptions.Complete()).Should(Succeed())
    61  		Expect(execOptions.Config).ShouldNot(BeNil())
    62  		Expect(execOptions.Namespace).Should(Equal("test"))
    63  
    64  		By("validate")
    65  		Expect(testOptions.complete([]string{"test"}))
    66  		Expect(testOptions.validate()).Should(Succeed())
    67  		Expect(testOptions.ContainerName).Should(Equal("test"))
    68  
    69  		By("run")
    70  		Expect(testOptions.Run()).Should(HaveOccurred())
    71  
    72  		// Corner case test
    73  		testOptions.ContainerName = ""
    74  		Expect(testOptions.ExecOptions.validate()).Should(Succeed())
    75  		Expect(testOptions.ContainerName).Should(Equal("bar"))
    76  		testOptions.Pod = nil
    77  		testOptions.PodName = ""
    78  		Expect(testOptions.ExecOptions.validate()).Should(MatchError("failed to get the pod to execute"))
    79  	})
    80  })
    81  
    82  type testExecOptions struct {
    83  	name string
    84  	*ExecOptions
    85  }
    86  
    87  func (o *testExecOptions) complete(args []string) error {
    88  	var err error
    89  	if len(args) == 0 {
    90  		return fmt.Errorf("you must specify the cluster name")
    91  	}
    92  	o.name = args[0]
    93  	if o.PodName == "" {
    94  		return fmt.Errorf("you must specify the instance name")
    95  	}
    96  	o.Pod, err = o.Client.CoreV1().Pods(o.Namespace).Get(context.TODO(), o.PodName, metav1.GetOptions{})
    97  	if err != nil {
    98  		return err
    99  	}
   100  	o.Command = []string{"test"}
   101  	o.ContainerName = "test"
   102  	return nil
   103  }
   104  
   105  func execPod() *corev1.Pod {
   106  	return &corev1.Pod{
   107  		ObjectMeta: metav1.ObjectMeta{
   108  			Name:            "foo",
   109  			Namespace:       "test",
   110  			ResourceVersion: "10",
   111  			Labels: map[string]string{
   112  				"app.kubernetes.io/name": "mysql-apecloud-mysql",
   113  			},
   114  		},
   115  		Spec: corev1.PodSpec{
   116  			RestartPolicy: corev1.RestartPolicyAlways,
   117  			DNSPolicy:     corev1.DNSClusterFirst,
   118  			Containers: []corev1.Container{
   119  				{
   120  					Name: "bar",
   121  				},
   122  			},
   123  		},
   124  		Status: corev1.PodStatus{
   125  			Phase: corev1.PodRunning,
   126  		},
   127  	}
   128  }