Merge pull request #18484 from brendandburns/3rdparty5

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2015-12-19 10:12:35 -08:00
commit 44fc4d3f34
3 changed files with 63 additions and 14 deletions

View File

@ -254,8 +254,8 @@ func AddApiWebService(container *restful.Container, apiPrefix string, versions [
}
// Adds a service to return the supported api versions at /apis.
func AddApisWebService(container *restful.Container, apiPrefix string, groups []unversioned.APIGroup) {
rootAPIHandler := RootAPIHandler(groups)
func AddApisWebService(container *restful.Container, apiPrefix string, f func() []unversioned.APIGroup) {
rootAPIHandler := RootAPIHandler(f)
ws := new(restful.WebService)
ws.Path(apiPrefix)
ws.Doc("get available API versions")
@ -308,10 +308,10 @@ func APIVersionHandler(versions ...string) restful.RouteFunction {
}
// RootAPIHandler returns a handler which will list the provided groups and versions as available.
func RootAPIHandler(groups []unversioned.APIGroup) restful.RouteFunction {
func RootAPIHandler(f func() []unversioned.APIGroup) restful.RouteFunction {
return func(req *restful.Request, resp *restful.Response) {
// TODO: use restful's Response methods
writeJSON(http.StatusOK, api.Codec, &unversioned.APIGroupList{Groups: groups}, resp.ResponseWriter, true)
writeJSON(http.StatusOK, api.Codec, &unversioned.APIGroupList{Groups: f()}, resp.ResponseWriter, true)
}
}

View File

@ -111,8 +111,8 @@ type Master struct {
// storage for third party objects
thirdPartyStorage storage.Interface
// map from api path to storage for those objects
thirdPartyResources map[string]*thirdpartyresourcedataetcd.REST
// map from api path to a tuple of (storage for the objects, APIGroup)
thirdPartyResources map[string]thirdPartyEntry
// protects the map
thirdPartyResourcesLock sync.RWMutex
@ -120,6 +120,13 @@ type Master struct {
tunneler Tunneler
}
// thirdPartyEntry combines objects storage and API group into one struct
// for easy lookup.
type thirdPartyEntry struct {
storage *thirdpartyresourcedataetcd.REST
group unversioned.APIGroup
}
// New returns a new instance of Master from the given config.
// Certain config fields will be set to a default value if unset.
// Certain config fields must be specified, including:
@ -184,7 +191,7 @@ func (m *Master) InstallAPIs(c *Config) {
// Install extensions unless disabled.
if !m.ApiGroupVersionOverrides["extensions/v1beta1"].Disable {
m.thirdPartyStorage = c.StorageDestinations.APIGroups[extensions.GroupName].Default
m.thirdPartyResources = map[string]*thirdpartyresourcedataetcd.REST{}
m.thirdPartyResources = map[string]thirdPartyEntry{}
expVersion := m.experimental(c)
@ -217,7 +224,20 @@ func (m *Master) InstallAPIs(c *Config) {
// This should be done after all groups are registered
// TODO: replace the hardcoded "apis".
apiserver.AddApisWebService(m.HandlerContainer, "/apis", allGroups)
apiserver.AddApisWebService(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) {
@ -432,7 +452,7 @@ func (m *Master) removeThirdPartyStorage(path string) error {
defer m.thirdPartyResourcesLock.Unlock()
storage, found := m.thirdPartyResources[path]
if found {
if err := m.removeAllThirdPartyResources(storage); err != nil {
if err := m.removeAllThirdPartyResources(storage.storage); err != nil {
return err
}
delete(m.thirdPartyResources, path)
@ -486,10 +506,10 @@ func (m *Master) ListThirdPartyResources() []string {
return result
}
func (m *Master) addThirdPartyResourceStorage(path string, storage *thirdpartyresourcedataetcd.REST) {
func (m *Master) addThirdPartyResourceStorage(path string, storage *thirdpartyresourcedataetcd.REST, apiGroup unversioned.APIGroup) {
m.thirdPartyResourcesLock.Lock()
defer m.thirdPartyResourcesLock.Unlock()
m.thirdPartyResources[path] = storage
m.thirdPartyResources[path] = thirdPartyEntry{storage, apiGroup}
}
// InstallThirdPartyResource installs a third party resource specified by 'rsrc'. When a resource is
@ -518,7 +538,7 @@ func (m *Master) InstallThirdPartyResource(rsrc *extensions.ThirdPartyResource)
Versions: []unversioned.GroupVersionForDiscovery{groupVersion},
}
apiserver.AddGroupWebService(m.HandlerContainer, path, apiGroup)
m.addThirdPartyResourceStorage(path, thirdparty.Storage[strings.ToLower(kind)+"s"].(*thirdpartyresourcedataetcd.REST))
m.addThirdPartyResourceStorage(path, thirdparty.Storage[strings.ToLower(kind)+"s"].(*thirdpartyresourcedataetcd.REST), apiGroup)
apiserver.InstallServiceErrorHandler(m.HandlerContainer, m.NewRequestInfoResolver(), []string{thirdparty.GroupVersion.String()})
return nil
}

View File

@ -41,7 +41,6 @@ import (
"k8s.io/kubernetes/pkg/registry/endpoint"
"k8s.io/kubernetes/pkg/registry/namespace"
"k8s.io/kubernetes/pkg/registry/registrytest"
thirdpartyresourcedatastorage "k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
@ -343,6 +342,36 @@ func TestDiscoveryAtAPIS(t *testing.T) {
assert.Equal(expectGroupName, groupList.Groups[0].Name)
assert.Equal(expectVersions, groupList.Groups[0].Versions)
assert.Equal(expectPreferredVersion, groupList.Groups[0].PreferredVersion)
thirdPartyGV := unversioned.GroupVersionForDiscovery{GroupVersion: "company.com/v1", Version: "v1"}
master.thirdPartyResources["/apis/company.com/v1"] = thirdPartyEntry{
nil,
unversioned.APIGroup{
Name: "company.com",
Versions: []unversioned.GroupVersionForDiscovery{thirdPartyGV},
PreferredVersion: thirdPartyGV,
},
}
resp, err = http.Get(server.URL + "/apis")
if !assert.NoError(err) {
t.Errorf("unexpected error: %v", err)
}
assert.Equal(http.StatusOK, resp.StatusCode)
assert.NoError(decodeResponse(resp, &groupList))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
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)
}
var versionsToTest = []string{"v1", "v3"}
@ -365,7 +394,7 @@ type FooList struct {
func initThirdParty(t *testing.T, version string) (*Master, *etcdtesting.EtcdTestServer, *httptest.Server, *assert.Assertions) {
master, etcdserver, _, assert := setUp(t)
master.thirdPartyResources = map[string]*thirdpartyresourcedatastorage.REST{}
master.thirdPartyResources = map[string]thirdPartyEntry{}
api := &extensions.ThirdPartyResource{
ObjectMeta: api.ObjectMeta{
Name: "foo.company.com",