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