k8s.io/client-go@v0.31.1/discovery/helper_blackbox_test.go (about) 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 discovery_test 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "errors" 23 "io" 24 "net/http" 25 "strings" 26 "testing" 27 28 v1 "k8s.io/api/core/v1" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/runtime" 31 "k8s.io/apimachinery/pkg/runtime/schema" 32 "k8s.io/apimachinery/pkg/util/sets" 33 "k8s.io/client-go/discovery" 34 restclient "k8s.io/client-go/rest" 35 "k8s.io/client-go/rest/fake" 36 ) 37 38 func objBody(object interface{}) io.ReadCloser { 39 output, err := json.MarshalIndent(object, "", "") 40 if err != nil { 41 panic(err) 42 } 43 return io.NopCloser(bytes.NewReader([]byte(output))) 44 } 45 46 func TestServerSupportsVersion(t *testing.T) { 47 tests := []struct { 48 name string 49 requiredVersion schema.GroupVersion 50 serverVersions []string 51 expectErr func(err error) bool 52 sendErr error 53 statusCode int 54 }{ 55 { 56 name: "explicit version supported", 57 requiredVersion: schema.GroupVersion{Version: "v1"}, 58 serverVersions: []string{"/version1", v1.SchemeGroupVersion.String()}, 59 statusCode: http.StatusOK, 60 }, 61 { 62 name: "explicit version not supported on server", 63 requiredVersion: schema.GroupVersion{Version: "v1"}, 64 serverVersions: []string{"version1"}, 65 expectErr: func(err error) bool { return strings.Contains(err.Error(), `server does not support API version "v1"`) }, 66 statusCode: http.StatusOK, 67 }, 68 { 69 name: "Status 403 Forbidden for core/v1 group returns error and is unsupported", 70 requiredVersion: schema.GroupVersion{Version: "v1"}, 71 serverVersions: []string{"/version1", v1.SchemeGroupVersion.String()}, 72 expectErr: func(err error) bool { return strings.Contains(err.Error(), "unknown") }, 73 statusCode: http.StatusForbidden, 74 }, 75 { 76 name: "Status 404 Not Found for core/v1 group returns empty and is unsupported", 77 requiredVersion: schema.GroupVersion{Version: "v1"}, 78 serverVersions: []string{"/version1", v1.SchemeGroupVersion.String()}, 79 expectErr: func(err error) bool { 80 return strings.Contains(err.Error(), "server could not find the requested resource") 81 }, 82 statusCode: http.StatusNotFound, 83 }, 84 { 85 name: "connection refused error", 86 serverVersions: []string{"version1"}, 87 sendErr: errors.New("connection refused"), 88 expectErr: func(err error) bool { return strings.Contains(err.Error(), "connection refused") }, 89 statusCode: http.StatusOK, 90 }, 91 } 92 93 for _, test := range tests { 94 fakeClient := fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { 95 if test.sendErr != nil { 96 return nil, test.sendErr 97 } 98 header := http.Header{} 99 header.Set("Content-Type", runtime.ContentTypeJSON) 100 return &http.Response{StatusCode: test.statusCode, Header: header, Body: objBody(&metav1.APIVersions{Versions: test.serverVersions})}, nil 101 }) 102 c := discovery.NewDiscoveryClientForConfigOrDie(&restclient.Config{}) 103 c.RESTClient().(*restclient.RESTClient).Client = fakeClient 104 err := discovery.ServerSupportsVersion(c, test.requiredVersion) 105 if err == nil && test.expectErr != nil { 106 t.Errorf("expected error, got nil for [%s].", test.name) 107 } 108 if err != nil { 109 if test.expectErr == nil || !test.expectErr(err) { 110 t.Errorf("unexpected error for [%s]: %v.", test.name, err) 111 } 112 continue 113 } 114 } 115 } 116 117 func TestFilteredBy(t *testing.T) { 118 all := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool { 119 return true 120 }) 121 none := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool { 122 return false 123 }) 124 onlyV2 := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool { 125 return strings.HasSuffix(gv, "/v2") || gv == "v2" 126 }) 127 onlyBar := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool { 128 return r.Kind == "Bar" 129 }) 130 131 foo := []*metav1.APIResourceList{ 132 { 133 GroupVersion: "foo/v1", 134 APIResources: []metav1.APIResource{ 135 {Name: "bar", Kind: "Bar"}, 136 {Name: "test", Kind: "Test"}, 137 }, 138 }, 139 { 140 GroupVersion: "foo/v2", 141 APIResources: []metav1.APIResource{ 142 {Name: "bar", Kind: "Bar"}, 143 {Name: "test", Kind: "Test"}, 144 }, 145 }, 146 { 147 GroupVersion: "foo/v3", 148 APIResources: []metav1.APIResource{}, 149 }, 150 } 151 152 tests := []struct { 153 input []*metav1.APIResourceList 154 pred discovery.ResourcePredicate 155 expectedResources []string 156 }{ 157 {nil, all, []string{}}, 158 {[]*metav1.APIResourceList{ 159 {GroupVersion: "foo/v1"}, 160 }, all, []string{}}, 161 {foo, all, []string{"foo/v1.bar", "foo/v1.test", "foo/v2.bar", "foo/v2.test"}}, 162 {foo, onlyV2, []string{"foo/v2.bar", "foo/v2.test"}}, 163 {foo, onlyBar, []string{"foo/v1.bar", "foo/v2.bar"}}, 164 {foo, none, []string{}}, 165 } 166 for i, test := range tests { 167 filtered := discovery.FilteredBy(test.pred, test.input) 168 169 if expected, got := sets.NewString(test.expectedResources...), sets.NewString(stringify(filtered)...); !expected.Equal(got) { 170 t.Errorf("[%d] unexpected group versions: expected=%v, got=%v", i, test.expectedResources, stringify(filtered)) 171 } 172 } 173 } 174 175 func stringify(rls []*metav1.APIResourceList) []string { 176 result := []string{} 177 for _, rl := range rls { 178 for _, r := range rl.APIResources { 179 result = append(result, rl.GroupVersion+"."+r.Name) 180 } 181 if len(rl.APIResources) == 0 { 182 result = append(result, rl.GroupVersion) 183 } 184 } 185 return result 186 }