github.com/alloyci/alloy-runner@v1.0.1-0.20180222164613-925503ccafd6/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 "io/ioutil" 24 "net/http" 25 "net/url" 26 "testing" 27 28 "k8s.io/kubernetes/pkg/api" 29 "k8s.io/kubernetes/pkg/api/testapi" 30 "k8s.io/kubernetes/pkg/api/unversioned" 31 "k8s.io/kubernetes/pkg/client/restclient" 32 client "k8s.io/kubernetes/pkg/client/unversioned" 33 "k8s.io/kubernetes/pkg/client/unversioned/fake" 34 "k8s.io/kubernetes/pkg/runtime" 35 ) 36 37 type fakeRemoteExecutor struct { 38 method string 39 url *url.URL 40 execErr error 41 } 42 43 func (f *fakeRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { 44 f.method = method 45 f.url = url 46 return f.execErr 47 } 48 49 func TestExec(t *testing.T) { 50 version := testapi.Default.GroupVersion().Version 51 tests := []struct { 52 name, version, podPath, execPath, container string 53 pod *api.Pod 54 tty, execErr bool 55 }{ 56 { 57 name: "pod exec", 58 version: version, 59 podPath: "/api/" + version + "/namespaces/test/pods/foo", 60 execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", 61 pod: execPod(), 62 }, 63 { 64 name: "pod exec with tty", 65 version: version, 66 podPath: "/api/" + version + "/namespaces/test/pods/foo", 67 execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", 68 pod: execPod(), 69 tty: true, 70 }, 71 { 72 name: "pod exec error", 73 version: version, 74 podPath: "/api/" + version + "/namespaces/test/pods/foo", 75 execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", 76 pod: execPod(), 77 execErr: true, 78 }, 79 } 80 81 codec := testapi.Default.Codec() 82 83 for _, test := range tests { 84 // Create a fake kubeClient 85 fakeClient := fake.RESTClient{ 86 Codec: codec, 87 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { 88 switch p, m := req.URL.Path, req.Method; { 89 case p == test.podPath && m == "GET": 90 body := objBody(codec, test.pod) 91 return &http.Response{StatusCode: http.StatusOK, Body: body, Header: map[string][]string{ 92 "Content-Type": []string{"application/json"}, 93 }}, nil 94 default: 95 // Ensures no GET is performed when deleting by name 96 t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) 97 return nil, fmt.Errorf("unexpected request") 98 } 99 }), 100 } 101 c := client.NewOrDie(&restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}}) 102 c.Client = fakeClient.Client 103 c.ExtensionsClient.Client = fakeClient.Client 104 105 ex := &fakeRemoteExecutor{} 106 if test.execErr { 107 ex.execErr = fmt.Errorf("exec error") 108 } 109 110 bufOut := bytes.NewBuffer([]byte{}) 111 bufErr := bytes.NewBuffer([]byte{}) 112 bufIn := bytes.NewBuffer([]byte{}) 113 114 params := &ExecOptions{ 115 PodName: "foo", 116 ContainerName: "bar", 117 Namespace: "test", 118 Command: []string{"command"}, 119 In: bufIn, 120 Out: bufOut, 121 Err: bufErr, 122 Stdin: true, 123 Executor: ex, 124 Client: c, 125 } 126 err := params.Run() 127 if test.execErr && err != ex.execErr { 128 t.Errorf("%s: Unexpected exec error: %v", test.name, err) 129 continue 130 } 131 if !test.execErr && err != nil { 132 t.Errorf("%s: Unexpected error: %v", test.name, err) 133 continue 134 } 135 if test.execErr { 136 continue 137 } 138 if ex.url.Path != test.execPath { 139 t.Errorf("%s: Did not get expected path for exec request", test.name) 140 continue 141 } 142 if ex.method != "POST" { 143 t.Errorf("%s: Did not get method for exec request: %s", test.name, ex.method) 144 } 145 } 146 } 147 148 func execPod() *api.Pod { 149 return &api.Pod{ 150 ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, 151 Spec: api.PodSpec{ 152 RestartPolicy: api.RestartPolicyAlways, 153 DNSPolicy: api.DNSClusterFirst, 154 Containers: []api.Container{ 155 { 156 Name: "bar", 157 }, 158 }, 159 }, 160 Status: api.PodStatus{ 161 Phase: api.PodRunning, 162 }, 163 } 164 } 165 166 func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { 167 return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) 168 }