...

Source file src/k8s.io/kubernetes/pkg/client/tests/listwatch_test.go

Documentation: k8s.io/kubernetes/pkg/client/tests

     1  /*
     2  Copyright 2015 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 tests
    18  
    19  import (
    20  	"net/http/httptest"
    21  	"net/url"
    22  	"testing"
    23  
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/fields"
    26  	"k8s.io/apimachinery/pkg/runtime/schema"
    27  	clientset "k8s.io/client-go/kubernetes"
    28  	restclient "k8s.io/client-go/rest"
    29  	. "k8s.io/client-go/tools/cache"
    30  	utiltesting "k8s.io/client-go/util/testing"
    31  )
    32  
    33  func parseSelectorOrDie(s string) fields.Selector {
    34  	selector, err := fields.ParseSelector(s)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  	return selector
    39  }
    40  
    41  // buildQueryValues is a convenience function for knowing if a namespace should be in a query param or not
    42  func buildQueryValues(query url.Values) url.Values {
    43  	v := url.Values{}
    44  	for key, values := range query {
    45  		for _, value := range values {
    46  			v.Add(key, value)
    47  		}
    48  	}
    49  
    50  	return v
    51  }
    52  
    53  func buildLocation(resourcePath string, query url.Values) string {
    54  	return resourcePath + "?" + query.Encode()
    55  }
    56  
    57  func TestListWatchesCanList(t *testing.T) {
    58  	fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam("v1")
    59  	table := []struct {
    60  		desc          string
    61  		location      string
    62  		resource      string
    63  		namespace     string
    64  		fieldSelector fields.Selector
    65  	}{
    66  		{
    67  			desc:          "node",
    68  			location:      "/api/v1/nodes",
    69  			resource:      "nodes",
    70  			namespace:     metav1.NamespaceAll,
    71  			fieldSelector: parseSelectorOrDie(""),
    72  		},
    73  		{
    74  			desc: "pod with 'assigned' field selector",
    75  			location: buildLocation(
    76  				"/api/v1/pods",
    77  				buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})),
    78  			resource:      "pods",
    79  			namespace:     metav1.NamespaceAll,
    80  			fieldSelector: fields.Set{"spec.host": ""}.AsSelector(),
    81  		},
    82  		{
    83  			desc: "pod in namespace 'foo'",
    84  			location: buildLocation(
    85  				"/api/v1/namespaces/foo/pods",
    86  				buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})),
    87  			resource:      "pods",
    88  			namespace:     "foo",
    89  			fieldSelector: fields.Set{"spec.host": ""}.AsSelector(),
    90  		},
    91  	}
    92  	for _, item := range table {
    93  		t.Run(item.desc, func(t *testing.T) {
    94  			handler := utiltesting.FakeHandler{
    95  				StatusCode:   500,
    96  				ResponseBody: "",
    97  				T:            t,
    98  			}
    99  			server := httptest.NewServer(&handler)
   100  			defer server.Close()
   101  			client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
   102  			lw := NewListWatchFromClient(client.CoreV1().RESTClient(), item.resource, item.namespace, item.fieldSelector)
   103  			lw.DisableChunking = true
   104  			// This test merely tests that the correct request is made.
   105  			_, _ = lw.List(metav1.ListOptions{})
   106  			handler.ValidateRequest(t, item.location, "GET", nil)
   107  		})
   108  	}
   109  }
   110  
   111  func TestListWatchesCanWatch(t *testing.T) {
   112  	fieldSelectorQueryParamName := metav1.FieldSelectorQueryParam("v1")
   113  	table := []struct {
   114  		desc          string
   115  		rv            string
   116  		location      string
   117  		resource      string
   118  		namespace     string
   119  		fieldSelector fields.Selector
   120  	}{
   121  		{
   122  			desc: "node without rv",
   123  			location: buildLocation(
   124  				"/api/v1/nodes",
   125  				buildQueryValues(url.Values{"watch": []string{"true"}})),
   126  			rv:            "",
   127  			resource:      "nodes",
   128  			namespace:     metav1.NamespaceAll,
   129  			fieldSelector: parseSelectorOrDie(""),
   130  		},
   131  		{
   132  			desc: "node with rv",
   133  			location: buildLocation(
   134  				"/api/v1/nodes",
   135  				buildQueryValues(url.Values{"resourceVersion": []string{"42"}, "watch": []string{"true"}})),
   136  			rv:            "42",
   137  			resource:      "nodes",
   138  			namespace:     metav1.NamespaceAll,
   139  			fieldSelector: parseSelectorOrDie(""),
   140  		},
   141  		{
   142  			desc: "pod with 'assigned' field selector",
   143  			location: buildLocation(
   144  				"/api/v1/pods",
   145  				buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}, "watch": []string{"true"}})),
   146  			rv:            "0",
   147  			resource:      "pods",
   148  			namespace:     metav1.NamespaceAll,
   149  			fieldSelector: fields.Set{"spec.host": ""}.AsSelector(),
   150  		},
   151  		{
   152  			desc: "pod with namespace foo and assigned field selector",
   153  			location: buildLocation(
   154  				"/api/v1/namespaces/foo/pods",
   155  				buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}, "watch": []string{"true"}})),
   156  			rv:            "0",
   157  			resource:      "pods",
   158  			namespace:     "foo",
   159  			fieldSelector: fields.Set{"spec.host": ""}.AsSelector(),
   160  		},
   161  	}
   162  
   163  	for _, item := range table {
   164  		t.Run(item.desc, func(t *testing.T) {
   165  			handler := utiltesting.FakeHandler{
   166  				StatusCode:   500,
   167  				ResponseBody: "",
   168  				T:            t,
   169  			}
   170  			server := httptest.NewServer(&handler)
   171  			defer server.Close()
   172  			client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
   173  			lw := NewListWatchFromClient(client.CoreV1().RESTClient(), item.resource, item.namespace, item.fieldSelector)
   174  			// This test merely tests that the correct request is made.
   175  			_, _ = lw.Watch(metav1.ListOptions{ResourceVersion: item.rv})
   176  			handler.ValidateRequest(t, item.location, "GET", nil)
   177  		})
   178  	}
   179  }
   180  

View as plain text