mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Moving /apis handler to generic server
This commit is contained in:
		@@ -1,6 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
  "swaggerVersion": "1.2",
 | 
			
		||||
  "apis": [
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/apis",
 | 
			
		||||
    "description": "get available API versions"
 | 
			
		||||
   },
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/version",
 | 
			
		||||
    "description": "git code version from which this is built"
 | 
			
		||||
@@ -20,10 +24,6 @@
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/apis/extensions",
 | 
			
		||||
    "description": "get information of a group"
 | 
			
		||||
   },
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/apis",
 | 
			
		||||
    "description": "get available API versions"
 | 
			
		||||
   }
 | 
			
		||||
  ],
 | 
			
		||||
  "apiVersion": "",
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ import (
 | 
			
		||||
	"net/http/pprof"
 | 
			
		||||
	"path"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -301,6 +302,10 @@ type GenericAPIServer struct {
 | 
			
		||||
	ProxyTransport http.RoundTripper
 | 
			
		||||
 | 
			
		||||
	KubernetesServiceNodePort int
 | 
			
		||||
 | 
			
		||||
	// Map storing information about all groups to be exposed in discovery response.
 | 
			
		||||
	// The map is from name to the group.
 | 
			
		||||
	apiGroupsForDiscovery map[string]unversioned.APIGroup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *GenericAPIServer) StorageDecorator() generic.StorageDecorator {
 | 
			
		||||
@@ -415,6 +420,7 @@ func New(c *Config) *GenericAPIServer {
 | 
			
		||||
		ExtraEndpointPorts:   c.ExtraEndpointPorts,
 | 
			
		||||
 | 
			
		||||
		KubernetesServiceNodePort: c.KubernetesServiceNodePort,
 | 
			
		||||
		apiGroupsForDiscovery:     map[string]unversioned.APIGroup{},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var handlerContainer *restful.Container
 | 
			
		||||
@@ -543,6 +549,8 @@ func (s *GenericAPIServer) init(c *Config) {
 | 
			
		||||
	} else {
 | 
			
		||||
		s.InsecureHandler = handler
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.installGroupsDiscoveryHandler()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exposes the given group versions in API.
 | 
			
		||||
@@ -555,6 +563,25 @@ func (s *GenericAPIServer) InstallAPIGroups(groupsInfo []APIGroupInfo) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Installs handler at /apis to list all group versions for discovery
 | 
			
		||||
func (s *GenericAPIServer) installGroupsDiscoveryHandler() {
 | 
			
		||||
	apiserver.AddApisWebService(s.Serializer, s.HandlerContainer, s.APIGroupPrefix, func() []unversioned.APIGroup {
 | 
			
		||||
		// Return the list of supported groups in sorted order (to have a deterministic order).
 | 
			
		||||
		groups := []unversioned.APIGroup{}
 | 
			
		||||
		groupNames := make([]string, len(s.apiGroupsForDiscovery))
 | 
			
		||||
		var i int = 0
 | 
			
		||||
		for groupName := range s.apiGroupsForDiscovery {
 | 
			
		||||
			groupNames[i] = groupName
 | 
			
		||||
			i++
 | 
			
		||||
		}
 | 
			
		||||
		sort.Strings(groupNames)
 | 
			
		||||
		for _, groupName := range groupNames {
 | 
			
		||||
			groups = append(groups, s.apiGroupsForDiscovery[groupName])
 | 
			
		||||
		}
 | 
			
		||||
		return groups
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *GenericAPIServer) Run(options *ServerRunOptions) {
 | 
			
		||||
	// We serve on 2 ports.  See docs/accessing_the_api.md
 | 
			
		||||
	secureLocation := ""
 | 
			
		||||
@@ -692,12 +719,21 @@ func (s *GenericAPIServer) installAPIGroup(apiGroupInfo *APIGroupInfo) error {
 | 
			
		||||
			Versions:         apiVersionsForDiscovery,
 | 
			
		||||
			PreferredVersion: preferedVersionForDiscovery,
 | 
			
		||||
		}
 | 
			
		||||
		s.AddAPIGroupForDiscovery(apiGroup)
 | 
			
		||||
		apiserver.AddGroupWebService(s.Serializer, s.HandlerContainer, apiPrefix+"/"+apiGroup.Name, apiGroup)
 | 
			
		||||
	}
 | 
			
		||||
	apiserver.InstallServiceErrorHandler(s.Serializer, s.HandlerContainer, s.NewRequestInfoResolver(), apiVersions)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *GenericAPIServer) AddAPIGroupForDiscovery(apiGroup unversioned.APIGroup) {
 | 
			
		||||
	s.apiGroupsForDiscovery[apiGroup.Name] = apiGroup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *GenericAPIServer) RemoveAPIGroupForDiscovery(groupName string) {
 | 
			
		||||
	delete(s.apiGroupsForDiscovery, groupName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *GenericAPIServer) getAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupVersion unversioned.GroupVersion, apiPrefix string) (*apiserver.APIGroupVersion, error) {
 | 
			
		||||
	storage := make(map[string]rest.Storage)
 | 
			
		||||
	for k, v := range apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version] {
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@ func TestNew(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
 | 
			
		||||
	config.ProxyTLSClientConfig = &tls.Config{}
 | 
			
		||||
	config.Serializer = api.Codecs
 | 
			
		||||
 | 
			
		||||
	s := New(&config)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -241,23 +241,6 @@ func (m *Master) InstallAPIs(c *Config) {
 | 
			
		||||
	if err := m.InstallAPIGroups(apiGroupsInfo); err != nil {
 | 
			
		||||
		glog.Fatalf("Error in registering group versions: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// This should be done after all groups are registered
 | 
			
		||||
	// TODO: replace the hardcoded "apis".
 | 
			
		||||
	apiserver.AddApisWebService(m.Serializer, m.HandlerContainer, "/apis", func() []unversioned.APIGroup {
 | 
			
		||||
		groups := []unversioned.APIGroup{}
 | 
			
		||||
		for ix := range allGroups {
 | 
			
		||||
			groups = append(groups, allGroups[ix])
 | 
			
		||||
		}
 | 
			
		||||
		m.thirdPartyResourcesLock.Lock()
 | 
			
		||||
		defer m.thirdPartyResourcesLock.Unlock()
 | 
			
		||||
		if m.thirdPartyResources != nil {
 | 
			
		||||
			for key := range m.thirdPartyResources {
 | 
			
		||||
				groups = append(groups, m.thirdPartyResources[key].group)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return groups
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Master) initV1ResourcesStorage(c *Config) {
 | 
			
		||||
@@ -446,6 +429,7 @@ func (m *Master) removeThirdPartyStorage(path string) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		delete(m.thirdPartyResources, path)
 | 
			
		||||
		m.RemoveAPIGroupForDiscovery(getThirdPartyGroupName(path))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@@ -500,6 +484,7 @@ func (m *Master) addThirdPartyResourceStorage(path string, storage *thirdpartyre
 | 
			
		||||
	m.thirdPartyResourcesLock.Lock()
 | 
			
		||||
	defer m.thirdPartyResourcesLock.Unlock()
 | 
			
		||||
	m.thirdPartyResources[path] = thirdPartyEntry{storage, apiGroup}
 | 
			
		||||
	m.AddAPIGroupForDiscovery(apiGroup)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstallThirdPartyResource installs a third party resource specified by 'rsrc'.  When a resource is
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,6 @@ import (
 | 
			
		||||
	etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/intstr"
 | 
			
		||||
 | 
			
		||||
	"github.com/emicklei/go-restful"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
@@ -85,6 +84,8 @@ func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *ass
 | 
			
		||||
 | 
			
		||||
	config.Serializer = api.Codecs
 | 
			
		||||
	config.KubeletClient = client.FakeKubeletClient{}
 | 
			
		||||
	config.APIPrefix = "/api"
 | 
			
		||||
	config.APIGroupPrefix = "/apis"
 | 
			
		||||
 | 
			
		||||
	config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
 | 
			
		||||
	config.ProxyTLSClientConfig = &tls.Config{}
 | 
			
		||||
@@ -269,30 +270,28 @@ func TestDiscoveryAtAPIS(t *testing.T) {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expectGroupName := extensions.GroupName
 | 
			
		||||
	expectVersions := []unversioned.GroupVersionForDiscovery{
 | 
			
		||||
	extensionsGroupName := extensions.GroupName
 | 
			
		||||
	extensionsVersions := []unversioned.GroupVersionForDiscovery{
 | 
			
		||||
		{
 | 
			
		||||
			GroupVersion: testapi.Extensions.GroupVersion().String(),
 | 
			
		||||
			Version:      testapi.Extensions.GroupVersion().Version,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	expectPreferredVersion := unversioned.GroupVersionForDiscovery{
 | 
			
		||||
	extensionsPreferredVersion := unversioned.GroupVersionForDiscovery{
 | 
			
		||||
		GroupVersion: config.StorageVersions[extensions.GroupName],
 | 
			
		||||
		Version:      apiutil.GetVersion(config.StorageVersions[extensions.GroupName]),
 | 
			
		||||
	}
 | 
			
		||||
	assert.Equal(expectGroupName, groupList.Groups[0].Name)
 | 
			
		||||
	assert.Equal(expectVersions, groupList.Groups[0].Versions)
 | 
			
		||||
	assert.Equal(expectPreferredVersion, groupList.Groups[0].PreferredVersion)
 | 
			
		||||
	assert.Equal(extensionsGroupName, groupList.Groups[0].Name)
 | 
			
		||||
	assert.Equal(extensionsVersions, groupList.Groups[0].Versions)
 | 
			
		||||
	assert.Equal(extensionsPreferredVersion, groupList.Groups[0].PreferredVersion)
 | 
			
		||||
 | 
			
		||||
	thirdPartyGV := unversioned.GroupVersionForDiscovery{GroupVersion: "company.com/v1", Version: "v1"}
 | 
			
		||||
	master.thirdPartyResources["/apis/company.com/v1"] = thirdPartyEntry{
 | 
			
		||||
		nil,
 | 
			
		||||
	master.addThirdPartyResourceStorage("/apis/company.com/v1", nil,
 | 
			
		||||
		unversioned.APIGroup{
 | 
			
		||||
			Name:             "company.com",
 | 
			
		||||
			Versions:         []unversioned.GroupVersionForDiscovery{thirdPartyGV},
 | 
			
		||||
			PreferredVersion: thirdPartyGV,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
	resp, err = http.Get(server.URL + "/apis")
 | 
			
		||||
	if !assert.NoError(err) {
 | 
			
		||||
@@ -309,10 +308,13 @@ func TestDiscoveryAtAPIS(t *testing.T) {
 | 
			
		||||
	thirdPartyGroupName := "company.com"
 | 
			
		||||
	thirdPartyExpectVersions := []unversioned.GroupVersionForDiscovery{thirdPartyGV}
 | 
			
		||||
 | 
			
		||||
	assert.Equal(thirdPartyGroupName, groupList.Groups[1].Name)
 | 
			
		||||
	assert.Equal(thirdPartyExpectVersions, groupList.Groups[1].Versions)
 | 
			
		||||
	assert.Equal(thirdPartyGV, groupList.Groups[1].PreferredVersion)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(2, len(groupList.Groups))
 | 
			
		||||
	assert.Equal(thirdPartyGroupName, groupList.Groups[0].Name)
 | 
			
		||||
	assert.Equal(thirdPartyExpectVersions, groupList.Groups[0].Versions)
 | 
			
		||||
	assert.Equal(thirdPartyGV, groupList.Groups[0].PreferredVersion)
 | 
			
		||||
	assert.Equal(extensionsGroupName, groupList.Groups[1].Name)
 | 
			
		||||
	assert.Equal(extensionsVersions, groupList.Groups[1].Versions)
 | 
			
		||||
	assert.Equal(extensionsPreferredVersion, groupList.Groups[1].PreferredVersion)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var versionsToTest = []string{"v1", "v3"}
 | 
			
		||||
@@ -333,9 +335,8 @@ type FooList struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initThirdParty(t *testing.T, version string) (*Master, *etcdtesting.EtcdTestServer, *httptest.Server, *assert.Assertions) {
 | 
			
		||||
	master, etcdserver, _, assert := setUp(t)
 | 
			
		||||
	master, etcdserver, _, assert := newMaster(t)
 | 
			
		||||
 | 
			
		||||
	master.thirdPartyResources = map[string]thirdPartyEntry{}
 | 
			
		||||
	api := &extensions.ThirdPartyResource{
 | 
			
		||||
		ObjectMeta: api.ObjectMeta{
 | 
			
		||||
			Name: "foo.company.com",
 | 
			
		||||
@@ -347,7 +348,6 @@ func initThirdParty(t *testing.T, version string) (*Master, *etcdtesting.EtcdTes
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	master.HandlerContainer = restful.NewContainer()
 | 
			
		||||
	master.thirdPartyStorage = etcdstorage.NewEtcdStorage(etcdserver.Client, testapi.Extensions.Codec(), etcdtest.PathPrefix(), false)
 | 
			
		||||
 | 
			
		||||
	if !assert.NoError(master.InstallThirdPartyResource(api)) {
 | 
			
		||||
@@ -355,7 +355,7 @@ func initThirdParty(t *testing.T, version string) (*Master, *etcdtesting.EtcdTes
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	server := httptest.NewServer(master.HandlerContainer.ServeMux)
 | 
			
		||||
	return &master, etcdserver, server, assert
 | 
			
		||||
	return master, etcdserver, server, assert
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInstallThirdPartyAPIList(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@ func makeThirdPartyPath(group string) string {
 | 
			
		||||
	return thirdpartyprefix + "/" + group
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getThirdPartyGroupName(path string) string {
 | 
			
		||||
	return strings.TrimPrefix(strings.TrimPrefix(path, thirdpartyprefix), "/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// resourceInterface is the interface for the parts of the master that know how to add/remove
 | 
			
		||||
// third party resources.  Extracted into an interface for injection for testing.
 | 
			
		||||
type resourceInterface interface {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user