k8s.io/apiserver@v0.31.1/pkg/endpoints/discovery/root_test.go (about)

     1  /*
     2  Copyright 2017 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
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"net/http"
    24  	"net/http/httptest"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  
    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/runtime/serializer"
    33  	utilnet "k8s.io/apimachinery/pkg/util/net"
    34  	"k8s.io/apimachinery/pkg/util/sets"
    35  	"k8s.io/apiserver/pkg/endpoints/request"
    36  )
    37  
    38  var (
    39  	scheme = runtime.NewScheme()
    40  	codecs = serializer.NewCodecFactory(scheme)
    41  )
    42  
    43  func init() {
    44  	// Register Unversioned types under their own special group
    45  	scheme.AddUnversionedTypes(schema.GroupVersion{Group: "", Version: "v1"},
    46  		&metav1.Status{},
    47  		&metav1.APIVersions{},
    48  		&metav1.APIGroupList{},
    49  		&metav1.APIGroup{},
    50  		&metav1.APIResourceList{},
    51  	)
    52  }
    53  
    54  func decodeResponse(t *testing.T, resp *http.Response, obj interface{}) error {
    55  	defer resp.Body.Close()
    56  
    57  	data, err := ioutil.ReadAll(resp.Body)
    58  	t.Log(string(data))
    59  	if err != nil {
    60  		return err
    61  	}
    62  	if err := json.Unmarshal(data, obj); err != nil {
    63  		return err
    64  	}
    65  	return nil
    66  }
    67  
    68  func getGroupList(t *testing.T, server *httptest.Server) (*metav1.APIGroupList, error) {
    69  	resp, err := http.Get(server.URL)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	if resp.StatusCode != http.StatusOK {
    75  		return nil, fmt.Errorf("unexpected server response, expected %d, actual: %d", http.StatusOK, resp.StatusCode)
    76  	}
    77  
    78  	groupList := metav1.APIGroupList{}
    79  	err = decodeResponse(t, resp, &groupList)
    80  	return &groupList, err
    81  }
    82  
    83  func contextHandler(handler http.Handler) http.Handler {
    84  	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    85  		ctx := req.Context()
    86  		resolver := &request.RequestInfoFactory{
    87  			APIPrefixes:          sets.NewString("api", "apis"),
    88  			GrouplessAPIPrefixes: sets.NewString("api"),
    89  		}
    90  		info, err := resolver.NewRequestInfo(req)
    91  		if err == nil {
    92  			ctx = request.WithRequestInfo(ctx, info)
    93  		}
    94  		req = req.WithContext(ctx)
    95  		handler.ServeHTTP(w, req)
    96  	})
    97  }
    98  
    99  func TestDiscoveryAtAPIS(t *testing.T) {
   100  	handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs)
   101  
   102  	server := httptest.NewServer(contextHandler(handler))
   103  
   104  	groupList, err := getGroupList(t, server)
   105  	if err != nil {
   106  		t.Fatalf("unexpected error: %v", err)
   107  	}
   108  	assert.Empty(t, groupList.Groups)
   109  
   110  	// Add a Group.
   111  	extensionsGroupName := "extensions"
   112  	extensionsVersions := []metav1.GroupVersionForDiscovery{
   113  		{
   114  			GroupVersion: extensionsGroupName + "/v1",
   115  			Version:      "v1",
   116  		},
   117  	}
   118  	extensionsPreferredVersion := metav1.GroupVersionForDiscovery{
   119  		GroupVersion: extensionsGroupName + "/preferred",
   120  		Version:      "preferred",
   121  	}
   122  	handler.AddGroup(metav1.APIGroup{
   123  		Name:             extensionsGroupName,
   124  		Versions:         extensionsVersions,
   125  		PreferredVersion: extensionsPreferredVersion,
   126  	})
   127  
   128  	groupList, err = getGroupList(t, server)
   129  	if err != nil {
   130  		t.Fatalf("unexpected error: %v", err)
   131  	}
   132  
   133  	assert.Len(t, groupList.Groups, 1)
   134  	groupListGroup := groupList.Groups[0]
   135  	assert.Equal(t, extensionsGroupName, groupListGroup.Name)
   136  	assert.Equal(t, extensionsVersions, groupListGroup.Versions)
   137  	assert.Equal(t, extensionsPreferredVersion, groupListGroup.PreferredVersion)
   138  	assert.Equal(t, handler.addresses.ServerAddressByClientCIDRs(utilnet.GetClientIP(&http.Request{})), groupListGroup.ServerAddressByClientCIDRs)
   139  
   140  	// Remove the group.
   141  	handler.RemoveGroup(extensionsGroupName)
   142  	groupList, err = getGroupList(t, server)
   143  	if err != nil {
   144  		t.Fatalf("unexpected error: %v", err)
   145  	}
   146  
   147  	assert.Empty(t, groupList.Groups)
   148  }
   149  
   150  func TestDiscoveryOrdering(t *testing.T) {
   151  	handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs)
   152  
   153  	server := httptest.NewServer(handler)
   154  	groupList, err := getGroupList(t, server)
   155  	if err != nil {
   156  		t.Fatalf("unexpected error: %v", err)
   157  	}
   158  	assert.Empty(t, groupList.Groups)
   159  
   160  	// Register three groups
   161  	handler.AddGroup(metav1.APIGroup{Name: "x"})
   162  	handler.AddGroup(metav1.APIGroup{Name: "y"})
   163  	handler.AddGroup(metav1.APIGroup{Name: "z"})
   164  	// Register three additional groups that come earlier alphabetically
   165  	handler.AddGroup(metav1.APIGroup{Name: "a"})
   166  	handler.AddGroup(metav1.APIGroup{Name: "b"})
   167  	handler.AddGroup(metav1.APIGroup{Name: "c"})
   168  	// Make sure re-adding doesn't double-register or make a group lose its place
   169  	handler.AddGroup(metav1.APIGroup{Name: "x"})
   170  
   171  	groupList, err = getGroupList(t, server)
   172  	if err != nil {
   173  		t.Fatalf("unexpected error: %v", err)
   174  	}
   175  
   176  	assert.Len(t, groupList.Groups, 6)
   177  	assert.Equal(t, "x", groupList.Groups[0].Name)
   178  	assert.Equal(t, "y", groupList.Groups[1].Name)
   179  	assert.Equal(t, "z", groupList.Groups[2].Name)
   180  	assert.Equal(t, "a", groupList.Groups[3].Name)
   181  	assert.Equal(t, "b", groupList.Groups[4].Name)
   182  	assert.Equal(t, "c", groupList.Groups[5].Name)
   183  
   184  	// Remove a group.
   185  	handler.RemoveGroup("a")
   186  	groupList, err = getGroupList(t, server)
   187  	if err != nil {
   188  		t.Fatalf("unexpected error: %v", err)
   189  	}
   190  	assert.Len(t, groupList.Groups, 5)
   191  
   192  	// Re-adding should move to the end.
   193  	handler.AddGroup(metav1.APIGroup{Name: "a"})
   194  	groupList, err = getGroupList(t, server)
   195  	if err != nil {
   196  		t.Fatalf("unexpected error: %v", err)
   197  	}
   198  	assert.Len(t, groupList.Groups, 6)
   199  	assert.Equal(t, "x", groupList.Groups[0].Name)
   200  	assert.Equal(t, "y", groupList.Groups[1].Name)
   201  	assert.Equal(t, "z", groupList.Groups[2].Name)
   202  	assert.Equal(t, "b", groupList.Groups[3].Name)
   203  	assert.Equal(t, "c", groupList.Groups[4].Name)
   204  	assert.Equal(t, "a", groupList.Groups[5].Name)
   205  }