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  }