Merge pull request #19040 from nikhiljindal/serverLibrary

api server library: moving API registration logic to generic api server
This commit is contained in:
Nikhil Jindal 2016-01-04 14:31:33 -08:00
commit af9834ea75
6 changed files with 232 additions and 170 deletions

View File

@ -1,14 +1,14 @@
{ {
"swaggerVersion": "1.2", "swaggerVersion": "1.2",
"apis": [ "apis": [
{
"path": "/api/v1",
"description": "API at /api/v1"
},
{ {
"path": "/version", "path": "/version",
"description": "git code version from which this is built" "description": "git code version from which this is built"
}, },
{
"path": "/api/v1",
"description": "API at /api/v1"
},
{ {
"path": "/api", "path": "/api",
"description": "get available API versions" "description": "get available API versions"

View File

@ -78,7 +78,7 @@ func (a *APIInstaller) Install(ws *restful.WebService) (apiResources []unversion
for _, path := range paths { for _, path := range paths {
apiResource, err := a.registerResourceHandlers(path, a.group.Storage[path], ws, proxyHandler) apiResource, err := a.registerResourceHandlers(path, a.group.Storage[path], ws, proxyHandler)
if err != nil { if err != nil {
errors = append(errors, err) errors = append(errors, fmt.Errorf("error in registering resource: %s, %v", path, err))
} }
if apiResource != nil { if apiResource != nil {
apiResources = append(apiResources, *apiResource) apiResources = append(apiResources, *apiResource)

View File

@ -18,6 +18,7 @@ package genericapiserver
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"net" "net"
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
@ -27,7 +28,9 @@ import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver"
"k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/auth/authorizer" "k8s.io/kubernetes/pkg/auth/authorizer"
@ -128,6 +131,21 @@ type APIGroupVersionOverride struct {
ResourceOverrides map[string]bool ResourceOverrides map[string]bool
} }
// Info about an API group.
type APIGroupInfo struct {
GroupMeta latest.GroupMeta
// Info about the resources in this group. Its a map from version to resource to the storage.
VersionedResourcesStorageMap map[string]map[string]rest.Storage
// True, if this is the legacy group ("/v1").
IsLegacyGroup bool
// OptionsExternalVersion controls the APIVersion used for common objects in the
// schema like api.Status, api.DeleteOptions, and api.ListOptions. Other implementors may
// define a version "v1beta1" but want to use the Kubernetes "v1" internal objects.
// If nil, defaults to groupMeta.GroupVersion.
// TODO: Remove this when https://github.com/kubernetes/kubernetes/issues/19018 is fixed.
OptionsExternalVersion *unversioned.GroupVersion
}
// Config is a structure used to configure a GenericAPIServer. // Config is a structure used to configure a GenericAPIServer.
type Config struct { type Config struct {
StorageDestinations StorageDestinations StorageDestinations StorageDestinations
@ -229,8 +247,8 @@ type GenericAPIServer struct {
enableSwaggerSupport bool enableSwaggerSupport bool
enableProfiling bool enableProfiling bool
enableWatchCache bool enableWatchCache bool
ApiPrefix string APIPrefix string
ApiGroupPrefix string APIGroupPrefix string
corsAllowedOriginList []string corsAllowedOriginList []string
authenticator authenticator.Request authenticator authenticator.Request
authorizer authorizer.Authorizer authorizer authorizer.Authorizer
@ -351,8 +369,8 @@ func New(c *Config) *GenericAPIServer {
enableSwaggerSupport: c.EnableSwaggerSupport, enableSwaggerSupport: c.EnableSwaggerSupport,
enableProfiling: c.EnableProfiling, enableProfiling: c.EnableProfiling,
enableWatchCache: c.EnableWatchCache, enableWatchCache: c.EnableWatchCache,
ApiPrefix: c.APIPrefix, APIPrefix: c.APIPrefix,
ApiGroupPrefix: c.APIGroupPrefix, APIGroupPrefix: c.APIGroupPrefix,
corsAllowedOriginList: c.CorsAllowedOriginList, corsAllowedOriginList: c.CorsAllowedOriginList,
authenticator: c.Authenticator, authenticator: c.Authenticator,
authorizer: c.Authorizer, authorizer: c.Authorizer,
@ -397,8 +415,8 @@ func New(c *Config) *GenericAPIServer {
func (s *GenericAPIServer) NewRequestInfoResolver() *apiserver.RequestInfoResolver { func (s *GenericAPIServer) NewRequestInfoResolver() *apiserver.RequestInfoResolver {
return &apiserver.RequestInfoResolver{ return &apiserver.RequestInfoResolver{
sets.NewString(strings.Trim(s.ApiPrefix, "/"), strings.Trim(s.ApiGroupPrefix, "/")), // all possible API prefixes sets.NewString(strings.Trim(s.APIPrefix, "/"), strings.Trim(s.APIGroupPrefix, "/")), // all possible API prefixes
sets.NewString(strings.Trim(s.ApiPrefix, "/")), // APIPrefixes that won't have groups (legacy) sets.NewString(strings.Trim(s.APIPrefix, "/")), // APIPrefixes that won't have groups (legacy)
} }
} }
@ -504,6 +522,102 @@ func (s *GenericAPIServer) init(c *Config) {
} }
} }
// Exposes the given group versions in API.
func (s *GenericAPIServer) InstallAPIGroups(groupsInfo []APIGroupInfo) error {
for _, apiGroupInfo := range groupsInfo {
if err := s.installAPIGroup(&apiGroupInfo); err != nil {
return err
}
}
return nil
}
func (s *GenericAPIServer) installAPIGroup(apiGroupInfo *APIGroupInfo) error {
apiPrefix := s.APIGroupPrefix
if apiGroupInfo.IsLegacyGroup {
apiPrefix = s.APIPrefix
}
// Install REST handlers for all the versions in this group.
apiVersions := []string{}
for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions {
apiVersions = append(apiVersions, groupVersion.Version)
apiGroupVersion, err := s.getAPIGroupVersion(apiGroupInfo, groupVersion, apiPrefix)
if err != nil {
return err
}
if apiGroupInfo.OptionsExternalVersion != nil {
apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion
}
if err := apiGroupVersion.InstallREST(s.HandlerContainer); err != nil {
return fmt.Errorf("Unable to setup API %v: %v", apiGroupInfo, err)
}
}
// Install the version handler.
if apiGroupInfo.IsLegacyGroup {
// Add a handler at /api to enumerate the supported api versions.
apiserver.AddApiWebService(s.HandlerContainer, apiPrefix, apiVersions)
} else {
// Add a handler at /apis/<groupName> to enumerate all versions supported by this group.
apiVersionsForDiscovery := []unversioned.GroupVersionForDiscovery{}
for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions {
apiVersionsForDiscovery = append(apiVersionsForDiscovery, unversioned.GroupVersionForDiscovery{
GroupVersion: groupVersion.String(),
Version: groupVersion.Version,
})
}
preferedVersionForDiscovery := unversioned.GroupVersionForDiscovery{
GroupVersion: apiGroupInfo.GroupMeta.GroupVersion.String(),
Version: apiGroupInfo.GroupMeta.GroupVersion.Version,
}
apiGroup := unversioned.APIGroup{
Name: apiGroupInfo.GroupMeta.GroupVersion.Group,
Versions: apiVersionsForDiscovery,
PreferredVersion: preferedVersionForDiscovery,
}
apiserver.AddGroupWebService(s.HandlerContainer, apiPrefix+"/"+apiGroup.Name, apiGroup)
}
apiserver.InstallServiceErrorHandler(s.HandlerContainer, s.NewRequestInfoResolver(), apiVersions)
return nil
}
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] {
storage[strings.ToLower(k)] = v
}
version, err := s.newAPIGroupVersion(apiGroupInfo.GroupMeta, groupVersion)
version.Root = apiPrefix
version.Storage = storage
return version, err
}
func (s *GenericAPIServer) newAPIGroupVersion(groupMeta latest.GroupMeta, groupVersion unversioned.GroupVersion) (*apiserver.APIGroupVersion, error) {
versionInterface, err := groupMeta.InterfacesFor(groupVersion)
if err != nil {
return nil, err
}
return &apiserver.APIGroupVersion{
RequestInfoResolver: s.NewRequestInfoResolver(),
Creater: api.Scheme,
Convertor: api.Scheme,
Typer: api.Scheme,
GroupVersion: groupVersion,
Linker: groupMeta.SelfLinker,
Mapper: groupMeta.RESTMapper,
Codec: versionInterface.Codec,
Admit: s.AdmissionControl,
Context: s.RequestContextMapper,
MinRequestTimeout: s.MinRequestTimeout,
}, nil
}
// InstallSwaggerAPI installs the /swaggerapi/ endpoint to allow schema discovery // InstallSwaggerAPI installs the /swaggerapi/ endpoint to allow schema discovery
// and traversal. It is optional to allow consumers of the Kubernetes GenericAPIServer to // and traversal. It is optional to allow consumers of the Kubernetes GenericAPIServer to
// register their own web services into the Kubernetes mux prior to initialization // register their own web services into the Kubernetes mux prior to initialization

View File

@ -21,8 +21,13 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"net/http/httptest"
"testing" "testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
@ -57,8 +62,8 @@ func TestNew(t *testing.T) {
assert.Equal(s.enableUISupport, config.EnableUISupport) assert.Equal(s.enableUISupport, config.EnableUISupport)
assert.Equal(s.enableSwaggerSupport, config.EnableSwaggerSupport) assert.Equal(s.enableSwaggerSupport, config.EnableSwaggerSupport)
assert.Equal(s.enableProfiling, config.EnableProfiling) assert.Equal(s.enableProfiling, config.EnableProfiling)
assert.Equal(s.ApiPrefix, config.APIPrefix) assert.Equal(s.APIPrefix, config.APIPrefix)
assert.Equal(s.ApiGroupPrefix, config.APIGroupPrefix) assert.Equal(s.APIGroupPrefix, config.APIGroupPrefix)
assert.Equal(s.corsAllowedOriginList, config.CorsAllowedOriginList) assert.Equal(s.corsAllowedOriginList, config.CorsAllowedOriginList)
assert.Equal(s.authenticator, config.Authenticator) assert.Equal(s.authenticator, config.Authenticator)
assert.Equal(s.authorizer, config.Authorizer) assert.Equal(s.authorizer, config.Authorizer)
@ -80,6 +85,54 @@ func TestNew(t *testing.T) {
assert.Equal(s.ProxyTransport.(*http.Transport).TLSClientConfig, config.ProxyTLSClientConfig) assert.Equal(s.ProxyTransport.(*http.Transport).TLSClientConfig, config.ProxyTLSClientConfig)
} }
// Verifies that AddGroupVersions works as expected.
func TestInstallAPIGroups(t *testing.T) {
_, etcdserver, config, assert := setUp(t)
defer etcdserver.Terminate(t)
config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
config.ProxyTLSClientConfig = &tls.Config{}
config.APIPrefix = "/apiPrefix"
config.APIGroupPrefix = "/apiGroupPrefix"
s := New(&config)
apiGroupMeta := latest.GroupOrDie(api.GroupName)
extensionsGroupMeta := latest.GroupOrDie(extensions.GroupName)
apiGroupsInfo := []APIGroupInfo{
{
// legacy group version
GroupMeta: *apiGroupMeta,
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},
IsLegacyGroup: true,
},
{
// extensions group version
GroupMeta: *extensionsGroupMeta,
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},
OptionsExternalVersion: &apiGroupMeta.GroupVersion,
},
}
s.InstallAPIGroups(apiGroupsInfo)
server := httptest.NewServer(s.HandlerContainer.ServeMux)
validPaths := []string{
// "/api"
config.APIPrefix,
// "/api/v1"
config.APIPrefix + "/" + apiGroupMeta.GroupVersion.Version,
// "/apis/extensions"
config.APIGroupPrefix + "/" + extensionsGroupMeta.GroupVersion.Group,
// "/apis/extensions/v1beta1"
config.APIGroupPrefix + "/" + extensionsGroupMeta.GroupVersion.String(),
}
for _, path := range validPaths {
_, err := http.Get(server.URL + path)
if !assert.NoError(err) {
t.Errorf("unexpected error: %v, for path: %s", err, path)
}
}
}
// TestNewHandlerContainer verifies that NewHandlerContainer uses the // TestNewHandlerContainer verifies that NewHandlerContainer uses the
// mux provided // mux provided
func TestNewHandlerContainer(t *testing.T) { func TestNewHandlerContainer(t *testing.T) {

View File

@ -30,8 +30,6 @@ import (
"k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
apiutil "k8s.io/kubernetes/pkg/api/util"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver"
"k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver"
@ -159,14 +157,8 @@ func New(c *Config) *Master {
} }
func (m *Master) InstallAPIs(c *Config) { func (m *Master) InstallAPIs(c *Config) {
apiVersions := []string{} apiGroupsInfo := []genericapiserver.APIGroupInfo{}
// Install v1 unless disabled.
if !m.ApiGroupVersionOverrides["api/v1"].Disable {
if err := m.api_v1(c).InstallREST(m.HandlerContainer); err != nil {
glog.Fatalf("Unable to setup API v1: %v", err)
}
apiVersions = append(apiVersions, "v1")
}
// Run the tunnel. // Run the tunnel.
healthzChecks := []healthz.HealthzChecker{} healthzChecks := []healthz.HealthzChecker{}
if m.tunneler != nil { if m.tunneler != nil {
@ -180,12 +172,24 @@ func (m *Master) InstallAPIs(c *Config) {
// TODO(nikhiljindal): Refactor generic parts of support services (like /versions) to genericapiserver. // TODO(nikhiljindal): Refactor generic parts of support services (like /versions) to genericapiserver.
apiserver.InstallSupport(m.MuxHelper, m.RootWebService, c.EnableProfiling, healthzChecks...) apiserver.InstallSupport(m.MuxHelper, m.RootWebService, c.EnableProfiling, healthzChecks...)
// Install v1 unless disabled.
if !m.ApiGroupVersionOverrides["api/v1"].Disable {
// Install v1 API.
m.initV1ResourcesStorage(c)
apiGroupInfo := genericapiserver.APIGroupInfo{
GroupMeta: *latest.GroupOrDie(api.GroupName),
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
"v1": m.v1ResourcesStorage,
},
IsLegacyGroup: true,
}
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
}
// Install root web services // Install root web services
m.HandlerContainer.Add(m.RootWebService) m.HandlerContainer.Add(m.RootWebService)
apiserver.AddApiWebService(m.HandlerContainer, c.APIPrefix, apiVersions)
apiserver.InstallServiceErrorHandler(m.HandlerContainer, m.NewRequestInfoResolver(), apiVersions)
// allGroups records all supported groups at /apis // allGroups records all supported groups at /apis
allGroups := []unversioned.APIGroup{} allGroups := []unversioned.APIGroup{}
// Install extensions unless disabled. // Install extensions unless disabled.
@ -193,33 +197,41 @@ func (m *Master) InstallAPIs(c *Config) {
m.thirdPartyStorage = c.StorageDestinations.APIGroups[extensions.GroupName].Default m.thirdPartyStorage = c.StorageDestinations.APIGroups[extensions.GroupName].Default
m.thirdPartyResources = map[string]thirdPartyEntry{} m.thirdPartyResources = map[string]thirdPartyEntry{}
expVersion := m.experimental(c) extensionResources := m.getExtensionResources(c)
extensionsGroupMeta := latest.GroupOrDie(extensions.GroupName)
if err := expVersion.InstallREST(m.HandlerContainer); err != nil { // Update the prefered version as per StorageVersions in the config.
glog.Fatalf("Unable to setup experimental api: %v", err) storageVersion, found := c.StorageVersions[extensionsGroupMeta.GroupVersion.Group]
}
g, err := latest.Group(extensions.GroupName)
if err != nil {
glog.Fatalf("Unable to setup experimental api: %v", err)
}
expAPIVersions := []unversioned.GroupVersionForDiscovery{
{
GroupVersion: expVersion.GroupVersion.String(),
Version: expVersion.GroupVersion.Version,
},
}
storageVersion, found := c.StorageVersions[g.GroupVersion.Group]
if !found { if !found {
glog.Fatalf("Couldn't find storage version of group %v", g.GroupVersion.Group) glog.Fatalf("Couldn't find storage version of group %v", extensionsGroupMeta.GroupVersion.Group)
}
preferedGroupVersion, err := unversioned.ParseGroupVersion(storageVersion)
if err != nil {
glog.Fatalf("Error in parsing group version %s: %v", storageVersion, err)
}
extensionsGroupMeta.GroupVersion = preferedGroupVersion
apiGroupInfo := genericapiserver.APIGroupInfo{
GroupMeta: *extensionsGroupMeta,
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
"v1beta1": extensionResources,
},
OptionsExternalVersion: &latest.GroupOrDie(api.GroupName).GroupVersion,
}
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
extensionsGVForDiscovery := unversioned.GroupVersionForDiscovery{
GroupVersion: extensionsGroupMeta.GroupVersion.String(),
Version: extensionsGroupMeta.GroupVersion.Version,
} }
group := unversioned.APIGroup{ group := unversioned.APIGroup{
Name: g.GroupVersion.Group, Name: extensionsGroupMeta.GroupVersion.Group,
Versions: expAPIVersions, Versions: []unversioned.GroupVersionForDiscovery{extensionsGVForDiscovery},
PreferredVersion: unversioned.GroupVersionForDiscovery{GroupVersion: storageVersion, Version: apiutil.GetVersion(storageVersion)}, PreferredVersion: extensionsGVForDiscovery,
} }
apiserver.AddGroupWebService(m.HandlerContainer, c.APIGroupPrefix+"/"+latest.GroupOrDie(extensions.GroupName).GroupVersion.Group, group)
allGroups = append(allGroups, group) allGroups = append(allGroups, group)
apiserver.InstallServiceErrorHandler(m.HandlerContainer, m.NewRequestInfoResolver(), []string{expVersion.GroupVersion.String()}) }
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 // This should be done after all groups are registered
@ -398,39 +410,6 @@ func (m *Master) getServersToValidate(c *Config) map[string]apiserver.Server {
return serversToValidate return serversToValidate
} }
func (m *Master) defaultAPIGroupVersion() *apiserver.APIGroupVersion {
return &apiserver.APIGroupVersion{
Root: m.ApiPrefix,
RequestInfoResolver: m.NewRequestInfoResolver(),
Mapper: latest.GroupOrDie(api.GroupName).RESTMapper,
Creater: api.Scheme,
Convertor: api.Scheme,
Typer: api.Scheme,
Linker: latest.GroupOrDie(api.GroupName).SelfLinker,
Admit: m.AdmissionControl,
Context: m.RequestContextMapper,
MinRequestTimeout: m.MinRequestTimeout,
}
}
// api_v1 returns the resources and codec for API version v1.
func (m *Master) api_v1(c *Config) *apiserver.APIGroupVersion {
m.initV1ResourcesStorage(c)
storage := make(map[string]rest.Storage)
for k, v := range m.v1ResourcesStorage {
storage[strings.ToLower(k)] = v
}
version := m.defaultAPIGroupVersion()
version.Storage = storage
version.GroupVersion = unversioned.GroupVersion{Version: "v1"}
version.Codec = v1.Codec
return version
}
// HasThirdPartyResource returns true if a particular third party resource currently installed. // HasThirdPartyResource returns true if a particular third party resource currently installed.
func (m *Master) HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (bool, error) { func (m *Master) HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (bool, error) {
_, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc) _, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc)
@ -575,8 +554,8 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV
} }
} }
// experimental returns the resources and codec for the experimental api // getExperimentalResources returns the resources for extenstions api
func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion { func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
// All resources except these are disabled by default. // All resources except these are disabled by default.
enabledResources := sets.NewString("jobs", "horizontalpodautoscalers", "ingresses") enabledResources := sets.NewString("jobs", "horizontalpodautoscalers", "ingresses")
resourceOverrides := m.ApiGroupVersionOverrides["extensions/v1beta1"].ResourceOverrides resourceOverrides := m.ApiGroupVersionOverrides["extensions/v1beta1"].ResourceOverrides
@ -640,30 +619,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
storage["ingresses"] = ingressStorage storage["ingresses"] = ingressStorage
storage["ingresses/status"] = ingressStatusStorage storage["ingresses/status"] = ingressStatusStorage
} }
return storage
extensionsGroup := latest.GroupOrDie(extensions.GroupName)
optionsExternalVersion := latest.GroupOrDie(api.GroupName).GroupVersion
return &apiserver.APIGroupVersion{
Root: m.ApiGroupPrefix,
RequestInfoResolver: m.NewRequestInfoResolver(),
Creater: api.Scheme,
Convertor: api.Scheme,
Typer: api.Scheme,
Mapper: extensionsGroup.RESTMapper,
Codec: extensionsGroup.Codec,
Linker: extensionsGroup.SelfLinker,
Storage: storage,
GroupVersion: extensionsGroup.GroupVersion,
OptionsExternalVersion: &optionsExternalVersion,
Admit: m.AdmissionControl,
Context: m.RequestContextMapper,
MinRequestTimeout: m.MinRequestTimeout,
}
} }
// findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP. // findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP.

View File

@ -30,11 +30,9 @@ import (
"testing" "testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
apiutil "k8s.io/kubernetes/pkg/api/util" apiutil "k8s.io/kubernetes/pkg/api/util"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/kubelet/client"
@ -102,8 +100,8 @@ func TestNew(t *testing.T) {
// Verify many of the variables match their config counterparts // Verify many of the variables match their config counterparts
assert.Equal(master.enableCoreControllers, config.EnableCoreControllers) assert.Equal(master.enableCoreControllers, config.EnableCoreControllers)
assert.Equal(master.tunneler, config.Tunneler) assert.Equal(master.tunneler, config.Tunneler)
assert.Equal(master.ApiPrefix, config.APIPrefix) assert.Equal(master.APIPrefix, config.APIPrefix)
assert.Equal(master.ApiGroupPrefix, config.APIGroupPrefix) assert.Equal(master.APIGroupPrefix, config.APIGroupPrefix)
assert.Equal(master.ApiGroupVersionOverrides, config.APIGroupVersionOverrides) assert.Equal(master.ApiGroupVersionOverrides, config.APIGroupVersionOverrides)
assert.Equal(master.RequestContextMapper, config.RequestContextMapper) assert.Equal(master.RequestContextMapper, config.RequestContextMapper)
assert.Equal(master.MasterCount, config.MasterCount) assert.Equal(master.MasterCount, config.MasterCount)
@ -160,35 +158,6 @@ func TestFindExternalAddress(t *testing.T) {
assert.Error(err, "expected findExternalAddress to fail on a node with missing ip information") assert.Error(err, "expected findExternalAddress to fail on a node with missing ip information")
} }
// TestApi_v1 verifies that the unexported api_v1 function does indeed
// utilize the correct Version and Codec.
func TestApi_v1(t *testing.T) {
_, etcdserver, config, assert := setUp(t)
defer etcdserver.Terminate(t)
// config.KubeletClient = client.FakeKubeletClient{}
config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
config.ProxyTLSClientConfig = &tls.Config{}
s := genericapiserver.New(config.Config)
master := &Master{
GenericAPIServer: s,
tunneler: config.Tunneler,
}
version := master.api_v1(&config)
assert.Equal(unversioned.GroupVersion{Version: "v1"}, version.GroupVersion, "Version was not v1: %s", version.GroupVersion)
assert.Equal(v1.Codec, version.Codec, "version.Codec was not for v1: %s", version.Codec)
// Verify that version storage has all the resources.
for k, v := range master.v1ResourcesStorage {
k = strings.ToLower(k)
val, ok := version.Storage[k]
assert.True(ok, "ok: %s", ok)
assert.Equal(val, v)
}
}
// TestNewBootstrapController verifies master fields are properly copied into controller // TestNewBootstrapController verifies master fields are properly copied into controller
func TestNewBootstrapController(t *testing.T) { func TestNewBootstrapController(t *testing.T) {
// Tests a subset of inputs to ensure they are set properly in the controller // Tests a subset of inputs to ensure they are set properly in the controller
@ -248,36 +217,6 @@ func TestControllerServicePorts(t *testing.T) {
assert.Equal(1010, controller.ExtraServicePorts[1].Port) assert.Equal(1010, controller.ExtraServicePorts[1].Port)
} }
// TestDefaultAPIGroupVersion verifies that the unexported defaultAPIGroupVersion
// creates the expected APIGroupVersion based off of master.
func TestDefaultAPIGroupVersion(t *testing.T) {
master, etcdserver, _, assert := setUp(t)
defer etcdserver.Terminate(t)
apiGroup := master.defaultAPIGroupVersion()
assert.Equal(apiGroup.Root, master.ApiPrefix)
assert.Equal(apiGroup.Admit, master.AdmissionControl)
assert.Equal(apiGroup.Context, master.RequestContextMapper)
assert.Equal(apiGroup.MinRequestTimeout, master.MinRequestTimeout)
}
// TestExpapi verifies that the unexported exapi creates
// the an experimental unversioned.APIGroupVersion.
func TestExpapi(t *testing.T) {
master, etcdserver, config, assert := setUp(t)
defer etcdserver.Terminate(t)
extensionsGroupMeta := latest.GroupOrDie(extensions.GroupName)
expAPIGroup := master.experimental(&config)
assert.Equal(expAPIGroup.Root, master.ApiGroupPrefix)
assert.Equal(expAPIGroup.Mapper, extensionsGroupMeta.RESTMapper)
assert.Equal(expAPIGroup.Codec, extensionsGroupMeta.Codec)
assert.Equal(expAPIGroup.Linker, extensionsGroupMeta.SelfLinker)
assert.Equal(expAPIGroup.GroupVersion, extensionsGroupMeta.GroupVersion)
}
// TestGetNodeAddresses verifies that proper results are returned // TestGetNodeAddresses verifies that proper results are returned
// when requesting node addresses. // when requesting node addresses.
func TestGetNodeAddresses(t *testing.T) { func TestGetNodeAddresses(t *testing.T) {