github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/kube/client_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 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 kube 18 19 import ( 20 "crypto/rsa" 21 "crypto/tls" 22 "crypto/x509" 23 "encoding/base64" 24 "encoding/pem" 25 "fmt" 26 "math/big" 27 "math/rand" 28 "net" 29 "net/http" 30 "net/http/httptest" 31 "testing" 32 "time" 33 ) 34 35 func getClient(url string) *Client { 36 return &Client{ 37 baseURL: url, 38 client: &http.Client{}, 39 token: "abcd", 40 namespace: "ns", 41 } 42 } 43 44 func TestNamespace(t *testing.T) { 45 c1 := &Client{ 46 baseURL: "a", 47 namespace: "ns1", 48 } 49 c2 := c1.Namespace("ns2") 50 if c1 == c2 { 51 t.Error("Namespace modified in place.") 52 } 53 if c2.baseURL != c1.baseURL { 54 t.Error("Didn't copy over struct members.") 55 } 56 if c2.namespace != "ns2" { 57 t.Errorf("Got wrong namespace. Got %s, expected ns2", c2.namespace) 58 } 59 } 60 61 func TestListPods(t *testing.T) { 62 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 63 if r.Method != http.MethodGet { 64 t.Errorf("Bad method: %s", r.Method) 65 } 66 if r.URL.Path != "/api/v1/namespaces/ns/pods" { 67 t.Errorf("Bad request path: %s", r.URL.Path) 68 } 69 fmt.Fprint(w, `{"items": [{}, {}]}`) 70 })) 71 defer ts.Close() 72 c := getClient(ts.URL) 73 ps, err := c.ListPods(nil) 74 if err != nil { 75 t.Errorf("Didn't expect error: %v", err) 76 } 77 if len(ps) != 2 { 78 t.Error("Expected two pods.") 79 } 80 } 81 82 func TestDeletePod(t *testing.T) { 83 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 84 if r.Method != http.MethodDelete { 85 t.Errorf("Bad method: %s", r.Method) 86 } 87 if r.URL.Path != "/api/v1/namespaces/ns/pods/po" { 88 t.Errorf("Bad request path: %s", r.URL.Path) 89 } 90 })) 91 defer ts.Close() 92 c := getClient(ts.URL) 93 err := c.DeletePod("po") 94 if err != nil { 95 t.Errorf("Didn't expect error: %v", err) 96 } 97 } 98 99 func TestGetPod(t *testing.T) { 100 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 101 if r.Method != http.MethodGet { 102 t.Errorf("Bad method: %s", r.Method) 103 } 104 if r.URL.Path != "/api/v1/namespaces/ns/pods/po" { 105 t.Errorf("Bad request path: %s", r.URL.Path) 106 } 107 fmt.Fprint(w, `{"metadata": {"name": "abcd"}}`) 108 })) 109 defer ts.Close() 110 c := getClient(ts.URL) 111 po, err := c.GetPod("po") 112 if err != nil { 113 t.Errorf("Didn't expect error: %v", err) 114 } 115 if po.Metadata.Name != "abcd" { 116 t.Errorf("Wrong name: %s", po.Metadata.Name) 117 } 118 } 119 120 func TestCreatePod(t *testing.T) { 121 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 122 if r.Method != http.MethodPost { 123 t.Errorf("Bad method: %s", r.Method) 124 } 125 if r.URL.Path != "/api/v1/namespaces/ns/pods" { 126 t.Errorf("Bad request path: %s", r.URL.Path) 127 } 128 fmt.Fprint(w, `{"metadata": {"name": "abcd"}}`) 129 })) 130 defer ts.Close() 131 c := getClient(ts.URL) 132 po, err := c.CreatePod(Pod{}) 133 if err != nil { 134 t.Errorf("Didn't expect error: %v", err) 135 } 136 if po.Metadata.Name != "abcd" { 137 t.Errorf("Wrong name: %s", po.Metadata.Name) 138 } 139 } 140 141 func TestCreateConfigMap(t *testing.T) { 142 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 143 if r.Method != http.MethodPost { 144 t.Errorf("Bad method: %s", r.Method) 145 } 146 if r.URL.Path != "/api/v1/namespaces/ns/configmaps" { 147 t.Errorf("Bad request path: %s", r.URL.Path) 148 } 149 fmt.Fprint(w, `{"metadata": {"name": "abcd"}}`) 150 })) 151 defer ts.Close() 152 c := getClient(ts.URL) 153 if _, err := c.CreateConfigMap(ConfigMap{}); err != nil { 154 t.Errorf("Didn't expect error: %v", err) 155 } 156 } 157 158 func TestReplaceConfigMap(t *testing.T) { 159 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 160 if r.Method != http.MethodPut { 161 t.Errorf("Bad method: %s", r.Method) 162 } 163 if r.URL.Path != "/api/v1/namespaces/ns/configmaps/config" { 164 t.Errorf("Bad request path: %s", r.URL.Path) 165 } 166 fmt.Fprint(w, `{"metadata": {"name": "abcd"}}`) 167 })) 168 defer ts.Close() 169 c := getClient(ts.URL) 170 if _, err := c.ReplaceConfigMap("config", ConfigMap{}); err != nil { 171 t.Errorf("Didn't expect error: %v", err) 172 } 173 } 174 175 // TestNewClient messes around with certs and keys and such to just make sure 176 // that our cert handling is done properly. We create root and client keys, 177 // then server and client certificates, then ensure that the client can talk 178 // to the server. 179 // See https://ericchiang.github.io/post/go-tls/ for implementation details. 180 func TestNewClient(t *testing.T) { 181 r := rand.New(rand.NewSource(42)) 182 rootKey, err := rsa.GenerateKey(r, 2048) 183 if err != nil { 184 t.Fatalf("Generating key: %v", err) 185 } 186 tmpl := &x509.Certificate{ 187 SerialNumber: big.NewInt(42), 188 SignatureAlgorithm: x509.SHA256WithRSA, 189 NotBefore: time.Now(), 190 NotAfter: time.Now().Add(time.Hour), 191 BasicConstraintsValid: true, 192 IsCA: true, 193 KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, 194 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 195 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 196 } 197 certDER, err := x509.CreateCertificate(r, tmpl, tmpl, &rootKey.PublicKey, rootKey) 198 if err != nil { 199 t.Fatalf("Creating cert: %v", err) 200 } 201 rootCert, err := x509.ParseCertificate(certDER) 202 if err != nil { 203 t.Fatalf("Parsing cert: %v", err) 204 } 205 rootCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) 206 rootKeyPEM := pem.EncodeToMemory(&pem.Block{ 207 Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rootKey), 208 }) 209 rootTLSCert, err := tls.X509KeyPair(rootCertPEM, rootKeyPEM) 210 if err != nil { 211 t.Fatalf("Creating KeyPair: %v", err) 212 } 213 214 clientKey, err := rsa.GenerateKey(r, 2048) 215 if err != nil { 216 t.Fatalf("Creating key: %v", err) 217 } 218 219 clientCertTmpl := &x509.Certificate{ 220 BasicConstraintsValid: true, 221 SerialNumber: big.NewInt(43), 222 SignatureAlgorithm: x509.SHA256WithRSA, 223 NotBefore: time.Now(), 224 NotAfter: time.Now().Add(time.Hour), 225 KeyUsage: x509.KeyUsageDigitalSignature, 226 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 227 } 228 clientCertDER, err := x509.CreateCertificate(r, clientCertTmpl, rootCert, &clientKey.PublicKey, rootKey) 229 if err != nil { 230 t.Fatalf("Creating cert: %v", err) 231 } 232 clientCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: clientCertDER}) 233 clientKeyPEM := pem.EncodeToMemory(&pem.Block{ 234 Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(clientKey), 235 }) 236 237 certPool := x509.NewCertPool() 238 certPool.AppendCertsFromPEM(rootCertPEM) 239 240 clus := &Cluster{ 241 ClientCertificate: base64.StdEncoding.EncodeToString(clientCertPEM), 242 ClientKey: base64.StdEncoding.EncodeToString(clientKeyPEM), 243 ClusterCACertificate: base64.StdEncoding.EncodeToString(rootCertPEM), 244 } 245 s := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("{}")) })) 246 s.TLS = &tls.Config{ 247 Certificates: []tls.Certificate{rootTLSCert}, 248 ClientCAs: certPool, 249 ClientAuth: tls.RequireAndVerifyClientCert, 250 } 251 s.StartTLS() 252 defer s.Close() 253 clus.Endpoint = s.URL 254 cl, err := NewClient(clus, "default") 255 if err != nil { 256 t.Fatalf("Failed to create client: %v", err) 257 } 258 if _, err := cl.GetPod("p"); err != nil { 259 t.Fatalf("Failed to talk to server: %v", err) 260 } 261 }