...

Source file src/k8s.io/client-go/discovery/helper_blackbox_test.go

Documentation: k8s.io/client-go/discovery

     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  }
   187  

View as plain text