github.com/secure-build/gitlab-runner@v12.5.0+incompatible/executors/kubernetes/exec_test.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package kubernetes 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "net/http" 24 "net/url" 25 "testing" 26 27 api "k8s.io/api/core/v1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 restclient "k8s.io/client-go/rest" 30 "k8s.io/client-go/rest/fake" 31 ) 32 33 type fakeRemoteExecutor struct { 34 method string 35 url *url.URL 36 execErr error 37 } 38 39 func (f *fakeRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { 40 f.method = method 41 f.url = url 42 return f.execErr 43 } 44 45 func TestExec(t *testing.T) { 46 version, codec := testVersionAndCodec() 47 tests := []struct { 48 name, version, podPath, execPath string 49 pod *api.Pod 50 tty, execErr bool 51 }{ 52 { 53 name: "pod exec", 54 version: version, 55 podPath: "/api/" + version + "/namespaces/test/pods/foo", 56 execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", 57 pod: execPod(), 58 }, 59 { 60 name: "pod exec with tty", 61 version: version, 62 podPath: "/api/" + version + "/namespaces/test/pods/foo", 63 execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", 64 pod: execPod(), 65 tty: true, 66 }, 67 { 68 name: "pod exec error", 69 version: version, 70 podPath: "/api/" + version + "/namespaces/test/pods/foo", 71 execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", 72 pod: execPod(), 73 execErr: true, 74 }, 75 } 76 77 for _, test := range tests { 78 // Create a fake kubeClient 79 fakeClient := fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { 80 switch p, m := req.URL.Path, req.Method; { 81 case p == test.podPath && m == "GET": 82 body := objBody(codec, test.pod) 83 return &http.Response{StatusCode: http.StatusOK, Body: body, Header: map[string][]string{ 84 "Content-Type": []string{"application/json"}, 85 }}, nil 86 default: 87 // Ensures no GET is performed when deleting by name 88 t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) 89 return nil, fmt.Errorf("unexpected request") 90 } 91 }) 92 c := testKubernetesClient(version, fakeClient) 93 94 ex := &fakeRemoteExecutor{} 95 if test.execErr { 96 ex.execErr = fmt.Errorf("exec error") 97 } 98 99 bufOut := bytes.NewBuffer([]byte{}) 100 bufErr := bytes.NewBuffer([]byte{}) 101 bufIn := bytes.NewBuffer([]byte{}) 102 103 params := &ExecOptions{ 104 PodName: "foo", 105 ContainerName: "bar", 106 Namespace: "test", 107 Command: []string{"command"}, 108 In: bufIn, 109 Out: bufOut, 110 Err: bufErr, 111 Stdin: true, 112 Executor: ex, 113 Client: c, 114 } 115 err := params.Run() 116 if test.execErr && err != ex.execErr { 117 t.Errorf("%s: Unexpected exec error: %v", test.name, err) 118 continue 119 } 120 if !test.execErr && err != nil { 121 t.Errorf("%s: Unexpected error: %v", test.name, err) 122 continue 123 } 124 if test.execErr { 125 continue 126 } 127 if ex.url.Path != test.execPath { 128 t.Errorf("%s: Did not get expected path for exec request", test.name) 129 continue 130 } 131 if ex.method != "POST" { 132 t.Errorf("%s: Did not get method for exec request: %s", test.name, ex.method) 133 } 134 } 135 } 136 137 func execPod() *api.Pod { 138 return &api.Pod{ 139 ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, 140 Spec: api.PodSpec{ 141 RestartPolicy: api.RestartPolicyAlways, 142 DNSPolicy: api.DNSClusterFirst, 143 Containers: []api.Container{ 144 { 145 Name: "bar", 146 }, 147 }, 148 }, 149 Status: api.PodStatus{ 150 Phase: api.PodRunning, 151 }, 152 } 153 }