github.com/danielqsj/helm@v2.0.0-alpha.4.0.20160908204436-976e0ba5199b+incompatible/pkg/kube/client_test.go (about)

     1  /*
     2  Copyright 2016 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 kube
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"io"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"strings"
    26  	"testing"
    27  
    28  	"k8s.io/kubernetes/pkg/api/meta"
    29  	"k8s.io/kubernetes/pkg/api/testapi"
    30  	"k8s.io/kubernetes/pkg/api/unversioned"
    31  	api "k8s.io/kubernetes/pkg/api/v1"
    32  	"k8s.io/kubernetes/pkg/client/unversioned/fake"
    33  	"k8s.io/kubernetes/pkg/kubectl/resource"
    34  	"k8s.io/kubernetes/pkg/runtime"
    35  )
    36  
    37  func TestUpdateResource(t *testing.T) {
    38  
    39  	tests := []struct {
    40  		name       string
    41  		namespace  string
    42  		modified   *resource.Info
    43  		currentObj runtime.Object
    44  		err        bool
    45  		errMessage string
    46  	}{
    47  		{
    48  			name:       "no changes when updating resources",
    49  			modified:   createFakeInfo("nginx", nil),
    50  			currentObj: createFakePod("nginx", nil),
    51  			err:        true,
    52  			errMessage: "Looks like there are no changes for nginx",
    53  		},
    54  		//{
    55  		//name:       "valid update input",
    56  		//modified:   createFakeInfo("nginx", map[string]string{"app": "nginx"}),
    57  		//currentObj: createFakePod("nginx", nil),
    58  		//},
    59  	}
    60  
    61  	for _, tt := range tests {
    62  		err := updateResource(tt.modified, tt.currentObj)
    63  		if err != nil && err.Error() != tt.errMessage {
    64  			t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err)
    65  		}
    66  	}
    67  }
    68  
    69  func TestPerform(t *testing.T) {
    70  	tests := []struct {
    71  		name       string
    72  		namespace  string
    73  		reader     io.Reader
    74  		count      int
    75  		err        bool
    76  		errMessage string
    77  	}{
    78  		{
    79  			name:      "Valid input",
    80  			namespace: "test",
    81  			reader:    strings.NewReader(guestbookManifest),
    82  			count:     6,
    83  		}, {
    84  			name:       "Empty manifests",
    85  			namespace:  "test",
    86  			reader:     strings.NewReader(""),
    87  			err:        true,
    88  			errMessage: "no objects passed to create",
    89  		},
    90  	}
    91  
    92  	for _, tt := range tests {
    93  		results := []*resource.Info{}
    94  
    95  		fn := func(info *resource.Info) error {
    96  			results = append(results, info)
    97  
    98  			if info.Namespace != tt.namespace {
    99  				t.Errorf("%q. expected namespace to be '%s', got %s", tt.name, tt.namespace, info.Namespace)
   100  			}
   101  			return nil
   102  		}
   103  
   104  		c := New(nil)
   105  		c.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
   106  			return &fake.RESTClient{}, nil
   107  		}
   108  
   109  		err := perform(c, tt.namespace, tt.reader, fn)
   110  		if (err != nil) != tt.err {
   111  			t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
   112  		}
   113  		if err != nil && err.Error() != tt.errMessage {
   114  			t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err)
   115  		}
   116  
   117  		if len(results) != tt.count {
   118  			t.Errorf("%q. expected %d result objects, got %d", tt.name, tt.count, len(results))
   119  		}
   120  	}
   121  }
   122  
   123  func TestReal(t *testing.T) {
   124  	t.Skip("This is a live test, comment this line to run")
   125  	if err := New(nil).Create("test", strings.NewReader(guestbookManifest)); err != nil {
   126  		t.Fatal(err)
   127  	}
   128  
   129  	testSvcEndpointManifest := testServiceManifest + "\n---\n" + testEndpointManifest
   130  	c := New(nil)
   131  	if err := c.Create("test-delete", strings.NewReader(testSvcEndpointManifest)); err != nil {
   132  		t.Fatal(err)
   133  	}
   134  
   135  	if err := c.Delete("test-delete", strings.NewReader(testEndpointManifest)); err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	// ensures that delete does not fail if a resource is not found
   140  	if err := c.Delete("test-delete", strings.NewReader(testSvcEndpointManifest)); err != nil {
   141  		t.Fatal(err)
   142  	}
   143  }
   144  
   145  const testServiceManifest = `
   146  kind: Service
   147  apiVersion: v1
   148  metadata:
   149    name: my-service
   150  spec:
   151    selector:
   152      app: myapp
   153    ports:
   154      - port: 80
   155        protocol: TCP
   156        targetPort: 9376
   157  `
   158  
   159  const testEndpointManifest = `
   160  kind: Endpoints
   161  apiVersion: v1
   162  metadata:
   163    name: my-service
   164  subsets:
   165    - addresses:
   166        - ip: "1.2.3.4"
   167      ports:
   168        - port: 9376
   169  `
   170  
   171  const guestbookManifest = `
   172  apiVersion: v1
   173  kind: Service
   174  metadata:
   175    name: redis-master
   176    labels:
   177      app: redis
   178      tier: backend
   179      role: master
   180  spec:
   181    ports:
   182    - port: 6379
   183      targetPort: 6379
   184    selector:
   185      app: redis
   186      tier: backend
   187      role: master
   188  ---
   189  apiVersion: extensions/v1beta1
   190  kind: Deployment
   191  metadata:
   192    name: redis-master
   193  spec:
   194    replicas: 1
   195    template:
   196      metadata:
   197        labels:
   198          app: redis
   199          role: master
   200          tier: backend
   201      spec:
   202        containers:
   203        - name: master
   204          image: gcr.io/google_containers/redis:e2e  # or just image: redis
   205          resources:
   206            requests:
   207              cpu: 100m
   208              memory: 100Mi
   209          ports:
   210          - containerPort: 6379
   211  ---
   212  apiVersion: v1
   213  kind: Service
   214  metadata:
   215    name: redis-slave
   216    labels:
   217      app: redis
   218      tier: backend
   219      role: slave
   220  spec:
   221    ports:
   222      # the port that this service should serve on
   223    - port: 6379
   224    selector:
   225      app: redis
   226      tier: backend
   227      role: slave
   228  ---
   229  apiVersion: extensions/v1beta1
   230  kind: Deployment
   231  metadata:
   232    name: redis-slave
   233  spec:
   234    replicas: 2
   235    template:
   236      metadata:
   237        labels:
   238          app: redis
   239          role: slave
   240          tier: backend
   241      spec:
   242        containers:
   243        - name: slave
   244          image: gcr.io/google_samples/gb-redisslave:v1
   245          resources:
   246            requests:
   247              cpu: 100m
   248              memory: 100Mi
   249          env:
   250          - name: GET_HOSTS_FROM
   251            value: dns
   252          ports:
   253          - containerPort: 6379
   254  ---
   255  apiVersion: v1
   256  kind: Service
   257  metadata:
   258    name: frontend
   259    labels:
   260      app: guestbook
   261      tier: frontend
   262  spec:
   263    ports:
   264    - port: 80
   265    selector:
   266      app: guestbook
   267      tier: frontend
   268  ---
   269  apiVersion: extensions/v1beta1
   270  kind: Deployment
   271  metadata:
   272    name: frontend
   273  spec:
   274    replicas: 3
   275    template:
   276      metadata:
   277        labels:
   278          app: guestbook
   279          tier: frontend
   280      spec:
   281        containers:
   282        - name: php-redis
   283          image: gcr.io/google-samples/gb-frontend:v4
   284          resources:
   285            requests:
   286              cpu: 100m
   287              memory: 100Mi
   288          env:
   289          - name: GET_HOSTS_FROM
   290            value: dns
   291          ports:
   292          - containerPort: 80
   293  `
   294  
   295  func createFakePod(name string, labels map[string]string) runtime.Object {
   296  	objectMeta := createObjectMeta(name, labels)
   297  
   298  	object := &api.Pod{
   299  		ObjectMeta: objectMeta,
   300  	}
   301  
   302  	return object
   303  }
   304  
   305  func createFakeInfo(name string, labels map[string]string) *resource.Info {
   306  	pod := createFakePod(name, labels)
   307  	marshaledObj, _ := json.Marshal(pod)
   308  
   309  	mapping := &meta.RESTMapping{
   310  		Resource: name,
   311  		Scope:    meta.RESTScopeNamespace,
   312  		GroupVersionKind: unversioned.GroupVersionKind{
   313  			Kind:    "Pod",
   314  			Version: "v1",
   315  		}}
   316  
   317  	client := &fake.RESTClient{
   318  		Codec: testapi.Default.Codec(),
   319  		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
   320  			header := http.Header{}
   321  			header.Set("Content-Type", runtime.ContentTypeJSON)
   322  			return &http.Response{
   323  				StatusCode: 200,
   324  				Header:     header,
   325  				Body:       ioutil.NopCloser(bytes.NewReader(marshaledObj)),
   326  			}, nil
   327  		})}
   328  	info := resource.NewInfo(client, mapping, "default", "nginx", false)
   329  
   330  	info.Object = pod
   331  
   332  	return info
   333  }
   334  
   335  func createObjectMeta(name string, labels map[string]string) api.ObjectMeta {
   336  	objectMeta := api.ObjectMeta{Name: name, Namespace: "default"}
   337  
   338  	if labels != nil {
   339  		objectMeta.Labels = labels
   340  	}
   341  
   342  	return objectMeta
   343  }