1
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
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
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
175 _, _ = lw.Watch(metav1.ListOptions{ResourceVersion: item.rv})
176 handler.ValidateRequest(t, item.location, "GET", nil)
177 })
178 }
179 }
180
View as plain text