Merge pull request #33384 from deads2k/api-14-move-storage-files

Automatic merge from submit-queue

move the REST storage creation to its proper packages

Moves the `RESTStorageProvider` interfaces to their proper packages.
This commit is contained in:
Kubernetes Submit Queue 2016-09-26 06:16:43 -07:00 committed by GitHub
commit 4219d9584b
22 changed files with 229 additions and 194 deletions

View File

@ -55,9 +55,34 @@ import (
"k8s.io/kubernetes/pkg/healthz"
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/master/ports"
controlleretcd "k8s.io/kubernetes/pkg/registry/controller/etcd"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/generic/registry"
"k8s.io/kubernetes/pkg/routes"
"k8s.io/kubernetes/pkg/runtime"
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
"k8s.io/kubernetes/pkg/storage/storagebackend"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/golang/glog"
"github.com/prometheus/client_golang/prometheus"
// RESTStorage installers
appsrest "k8s.io/kubernetes/pkg/registry/apps/rest"
authenticationrest "k8s.io/kubernetes/pkg/registry/authentication/rest"
authorizationrest "k8s.io/kubernetes/pkg/registry/authorization/rest"
autoscalingrest "k8s.io/kubernetes/pkg/registry/autoscaling/rest"
batchrest "k8s.io/kubernetes/pkg/registry/batch/rest"
certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest"
extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest"
policyrest "k8s.io/kubernetes/pkg/registry/policy/rest"
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
storagerest "k8s.io/kubernetes/pkg/registry/storage/rest"
// direct etcd registry dependencies
"k8s.io/kubernetes/pkg/registry/core/componentstatus"
configmapetcd "k8s.io/kubernetes/pkg/registry/core/configmap/etcd"
controlleretcd "k8s.io/kubernetes/pkg/registry/core/controller/etcd"
"k8s.io/kubernetes/pkg/registry/core/endpoint"
endpointsetcd "k8s.io/kubernetes/pkg/registry/core/endpoint/etcd"
eventetcd "k8s.io/kubernetes/pkg/registry/core/event/etcd"
@ -82,17 +107,6 @@ import (
serviceaccountetcd "k8s.io/kubernetes/pkg/registry/core/serviceaccount/etcd"
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
thirdpartyresourcedataetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata/etcd"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/generic/registry"
rbacstorage "k8s.io/kubernetes/pkg/registry/rbac/storage"
"k8s.io/kubernetes/pkg/routes"
"k8s.io/kubernetes/pkg/runtime"
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
"k8s.io/kubernetes/pkg/storage/storagebackend"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/golang/glog"
"github.com/prometheus/client_golang/prometheus"
)
const (
@ -224,19 +238,19 @@ func New(c *Config) (*Master, error) {
if c.RESTStorageProviders == nil {
c.RESTStorageProviders = map[string]genericapiserver.RESTStorageProvider{}
}
c.RESTStorageProviders[appsapi.GroupName] = AppsRESTStorageProvider{}
c.RESTStorageProviders[autoscaling.GroupName] = AutoscalingRESTStorageProvider{}
c.RESTStorageProviders[batch.GroupName] = BatchRESTStorageProvider{}
c.RESTStorageProviders[certificates.GroupName] = CertificatesRESTStorageProvider{}
c.RESTStorageProviders[extensions.GroupName] = ExtensionsRESTStorageProvider{
c.RESTStorageProviders[appsapi.GroupName] = appsrest.RESTStorageProvider{}
c.RESTStorageProviders[authenticationv1beta1.GroupName] = authenticationrest.RESTStorageProvider{Authenticator: c.Authenticator}
c.RESTStorageProviders[authorization.GroupName] = authorizationrest.RESTStorageProvider{Authorizer: c.Authorizer}
c.RESTStorageProviders[autoscaling.GroupName] = autoscalingrest.RESTStorageProvider{}
c.RESTStorageProviders[batch.GroupName] = batchrest.RESTStorageProvider{}
c.RESTStorageProviders[certificates.GroupName] = certificatesrest.RESTStorageProvider{}
c.RESTStorageProviders[extensions.GroupName] = extensionsrest.RESTStorageProvider{
ResourceInterface: m,
DisableThirdPartyControllerForTesting: m.disableThirdPartyControllerForTesting,
}
c.RESTStorageProviders[policy.GroupName] = PolicyRESTStorageProvider{}
c.RESTStorageProviders[rbac.GroupName] = &rbacstorage.RESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser}
c.RESTStorageProviders[storage.GroupName] = StorageRESTStorageProvider{}
c.RESTStorageProviders[authenticationv1beta1.GroupName] = AuthenticationRESTStorageProvider{Authenticator: c.Authenticator}
c.RESTStorageProviders[authorization.GroupName] = AuthorizationRESTStorageProvider{Authorizer: c.Authorizer}
c.RESTStorageProviders[policy.GroupName] = policyrest.RESTStorageProvider{}
c.RESTStorageProviders[rbac.GroupName] = &rbacrest.RESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser}
c.RESTStorageProviders[storage.GroupName] = storagerest.RESTStorageProvider{}
m.InstallAPIs(c)
// TODO: Attempt clean shutdown?
@ -566,7 +580,7 @@ func (m *Master) HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (boo
if err != nil {
return false, err
}
path := makeThirdPartyPath(group)
path := extensionsrest.MakeThirdPartyPath(group)
m.thirdPartyResourcesLock.Lock()
defer m.thirdPartyResourcesLock.Unlock()
entry := m.thirdPartyResources[path]
@ -599,7 +613,7 @@ func (m *Master) removeThirdPartyStorage(path, resource string) error {
delete(entry.storage, resource)
if len(entry.storage) == 0 {
delete(m.thirdPartyResources, path)
m.RemoveAPIGroupForDiscovery(getThirdPartyGroupName(path))
m.RemoveAPIGroupForDiscovery(extensionsrest.GetThirdPartyGroupName(path))
} else {
m.thirdPartyResources[path] = entry
}
@ -720,7 +734,7 @@ func (m *Master) InstallThirdPartyResource(rsrc *extensions.ThirdPartyResource)
Version: rsrc.Versions[0].Name,
Kind: kind,
})
path := makeThirdPartyPath(group)
path := extensionsrest.MakeThirdPartyPath(group)
groupVersion := unversioned.GroupVersionForDiscovery{
GroupVersion: group + "/" + rsrc.Versions[0].Name,
@ -770,7 +784,7 @@ func (m *Master) thirdpartyapi(group, kind, version, pluralResource string) *api
internalVersion := unversioned.GroupVersion{Group: group, Version: runtime.APIVersionInternal}
externalVersion := unversioned.GroupVersion{Group: group, Version: version}
apiRoot := makeThirdPartyPath("")
apiRoot := extensionsrest.MakeThirdPartyPath("")
return &apiserver.APIGroupVersion{
Root: apiRoot,
GroupVersion: externalVersion,
@ -793,7 +807,7 @@ func (m *Master) thirdpartyapi(group, kind, version, pluralResource string) *api
MinRequestTimeout: m.MinRequestTimeout(),
ResourceLister: dynamicLister{m, makeThirdPartyPath(group)},
ResourceLister: dynamicLister{m, extensionsrest.MakeThirdPartyPath(group)},
}
}

View File

@ -53,6 +53,7 @@ import (
"k8s.io/kubernetes/pkg/registry/core/endpoint"
"k8s.io/kubernetes/pkg/registry/core/namespace"
ipallocator "k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest"
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/registrytest"
@ -1127,7 +1128,7 @@ func testInstallThirdPartyResourceRemove(t *testing.T, version string) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item)
}
path := makeThirdPartyPath("company.com")
path := extensionsrest.MakeThirdPartyPath("company.com")
master.RemoveThirdPartyResource(path + "/foos")
resp, err = http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")

View File

@ -17,21 +17,10 @@ limitations under the License.
package master
import (
"fmt"
"strings"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
expapi "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apiserver"
thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource/etcd"
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/sets"
)
const thirdpartyprefix = "/apis"
// dynamicLister is used to list resources for dynamic third party
// apis. It implements the apiserver.APIResourceLister interface
type dynamicLister struct {
@ -44,103 +33,3 @@ func (d dynamicLister) ListAPIResources() []unversioned.APIResource {
}
var _ apiserver.APIResourceLister = &dynamicLister{}
func makeThirdPartyPath(group string) string {
if len(group) == 0 {
return thirdpartyprefix
}
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 {
// Remove a third party resource based on the RESTful path for that resource, the path is <api-group-path>/<resource-plural-name>
RemoveThirdPartyResource(path string) error
// Install a third party resource described by 'rsrc'
InstallThirdPartyResource(rsrc *expapi.ThirdPartyResource) error
// Is a particular third party resource currently installed?
HasThirdPartyResource(rsrc *expapi.ThirdPartyResource) (bool, error)
// List all currently installed third party resources, the returned
// names are of the form <api-group-path>/<resource-plural-name>
ListThirdPartyResources() []string
}
// ThirdPartyController is a control loop that knows how to synchronize ThirdPartyResource objects with
// RESTful resources which are present in the API server.
type ThirdPartyController struct {
master resourceInterface
thirdPartyResourceRegistry *thirdpartyresourceetcd.REST
}
// Synchronize a single resource with RESTful resources on the master
func (t *ThirdPartyController) SyncOneResource(rsrc *expapi.ThirdPartyResource) error {
// TODO: we also need to test if the existing installed resource matches the resource we are sync-ing.
// Currently, if there is an older, incompatible resource installed, we won't remove it. We should detect
// older, incompatible resources and remove them before testing if the resource exists.
hasResource, err := t.master.HasThirdPartyResource(rsrc)
if err != nil {
return err
}
if !hasResource {
return t.master.InstallThirdPartyResource(rsrc)
}
return nil
}
// Synchronize all resources with RESTful resources on the master
func (t *ThirdPartyController) SyncResources() error {
list, err := t.thirdPartyResourceRegistry.List(api.NewDefaultContext(), nil)
if err != nil {
return err
}
return t.syncResourceList(list)
}
func (t *ThirdPartyController) syncResourceList(list runtime.Object) error {
existing := sets.String{}
switch list := list.(type) {
case *expapi.ThirdPartyResourceList:
// Loop across all schema objects for third party resources
for ix := range list.Items {
item := &list.Items[ix]
// extract the api group and resource kind from the schema
_, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(item)
if err != nil {
return err
}
// place it in the set of resources that we expect, so that we don't delete it in the delete pass
existing.Insert(makeThirdPartyPath(group))
// ensure a RESTful resource for this schema exists on the master
if err := t.SyncOneResource(item); err != nil {
return err
}
}
default:
return fmt.Errorf("expected a *ThirdPartyResourceList, got %#v", list)
}
// deletion phase, get all installed RESTful resources
installed := t.master.ListThirdPartyResources()
for _, installedAPI := range installed {
found := false
// search across the expected restful resources to see if this resource belongs to one of the expected ones
for _, apiPath := range existing.List() {
if installedAPI == apiPath || strings.HasPrefix(installedAPI, apiPath+"/") {
found = true
break
}
}
// not expected, delete the resource
if !found {
if err := t.master.RemoveThirdPartyResource(installedAPI); err != nil {
return err
}
}
}
return nil
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -24,11 +24,11 @@ import (
petsetetcd "k8s.io/kubernetes/pkg/registry/apps/petset/etcd"
)
type AppsRESTStorageProvider struct{}
type RESTStorageProvider struct{}
var _ genericapiserver.RESTStorageProvider = &AppsRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p AppsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(appsapiv1alpha1.SchemeGroupVersion) {
@ -39,7 +39,7 @@ func (p AppsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource generica
return apiGroupInfo, true
}
func (p AppsRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := appsapiv1alpha1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -25,13 +25,13 @@ import (
"k8s.io/kubernetes/pkg/registry/authentication/tokenreview"
)
type AuthenticationRESTStorageProvider struct {
type RESTStorageProvider struct {
Authenticator authenticator.Request
}
var _ genericapiserver.RESTStorageProvider = &AuthenticationRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p AuthenticationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
// TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled.
// if p.Authenticator == nil {
// return genericapiserver.APIGroupInfo{}, false
@ -47,7 +47,7 @@ func (p AuthenticationRESTStorageProvider) NewRESTStorage(apiResourceConfigSourc
return apiGroupInfo, true
}
func (p AuthenticationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := authenticationv1beta1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -27,13 +27,13 @@ import (
"k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview"
)
type AuthorizationRESTStorageProvider struct {
type RESTStorageProvider struct {
Authorizer authorizer.Authorizer
}
var _ genericapiserver.RESTStorageProvider = &AuthorizationRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p AuthorizationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
if p.Authorizer == nil {
return genericapiserver.APIGroupInfo{}, false
}
@ -48,7 +48,7 @@ func (p AuthorizationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource
return apiGroupInfo, true
}
func (p AuthorizationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := authorizationv1beta1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -24,11 +24,11 @@ import (
horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/autoscaling/horizontalpodautoscaler/etcd"
)
type AutoscalingRESTStorageProvider struct{}
type RESTStorageProvider struct{}
var _ genericapiserver.RESTStorageProvider = &AutoscalingRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p AutoscalingRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) {
@ -39,7 +39,7 @@ func (p AutoscalingRESTStorageProvider) NewRESTStorage(apiResourceConfigSource g
return apiGroupInfo, true
}
func (p AutoscalingRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := autoscalingapiv1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -26,11 +26,11 @@ import (
scheduledjobetcd "k8s.io/kubernetes/pkg/registry/batch/scheduledjob/etcd"
)
type BatchRESTStorageProvider struct{}
type RESTStorageProvider struct{}
var _ genericapiserver.RESTStorageProvider = &BatchRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) {
@ -45,7 +45,7 @@ func (p BatchRESTStorageProvider) NewRESTStorage(apiResourceConfigSource generic
return apiGroupInfo, true
}
func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := batchapiv1.SchemeGroupVersion
storage := map[string]rest.Storage{}
@ -57,7 +57,7 @@ func (p BatchRESTStorageProvider) v1Storage(apiResourceConfigSource genericapise
return storage
}
func (p BatchRESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v2alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := batchapiv2alpha1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -24,11 +24,11 @@ import (
certificateetcd "k8s.io/kubernetes/pkg/registry/certificates/certificates/etcd"
)
type CertificatesRESTStorageProvider struct{}
type RESTStorageProvider struct{}
var _ genericapiserver.RESTStorageProvider = &CertificatesRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p CertificatesRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(certificatesapiv1alpha1.SchemeGroupVersion) {
@ -39,7 +39,7 @@ func (p CertificatesRESTStorageProvider) NewRESTStorage(apiResourceConfigSource
return apiGroupInfo, true
}
func (p CertificatesRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := certificatesapiv1alpha1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -16,4 +16,4 @@ limitations under the License.
// Package controller provides Registry interface and it's RESTStorage
// implementation for storing ReplicationController api objects.
package controller // import "k8s.io/kubernetes/pkg/registry/controller"
package controller // import "k8s.io/kubernetes/pkg/registry/core/controller"

View File

@ -28,7 +28,7 @@ import (
"k8s.io/kubernetes/pkg/apis/autoscaling/validation"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/controller"
"k8s.io/kubernetes/pkg/registry/core/controller"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/generic/registry"
"k8s.io/kubernetes/pkg/runtime"

View File

@ -23,8 +23,8 @@ import (
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/registry/controller"
"k8s.io/kubernetes/pkg/registry/controller/etcd"
"k8s.io/kubernetes/pkg/registry/core/controller"
"k8s.io/kubernetes/pkg/registry/core/controller/etcd"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"time"
@ -39,14 +39,14 @@ import (
"k8s.io/kubernetes/pkg/util/wait"
)
type ExtensionsRESTStorageProvider struct {
ResourceInterface resourceInterface
type RESTStorageProvider struct {
ResourceInterface ResourceInterface
DisableThirdPartyControllerForTesting bool
}
var _ genericapiserver.RESTStorageProvider = &ExtensionsRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p ExtensionsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(extensions.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
@ -57,7 +57,7 @@ func (p ExtensionsRESTStorageProvider) NewRESTStorage(apiResourceConfigSource ge
return apiGroupInfo, true
}
func (p ExtensionsRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := extensionsapiv1beta1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -0,0 +1,131 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rest
import (
"fmt"
"strings"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource/etcd"
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/sets"
)
// 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 {
// Remove a third party resource based on the RESTful path for that resource, the path is <api-group-path>/<resource-plural-name>
RemoveThirdPartyResource(path string) error
// Install a third party resource described by 'rsrc'
InstallThirdPartyResource(rsrc *extensions.ThirdPartyResource) error
// Is a particular third party resource currently installed?
HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (bool, error)
// List all currently installed third party resources, the returned
// names are of the form <api-group-path>/<resource-plural-name>
ListThirdPartyResources() []string
}
const thirdpartyprefix = "/apis"
// ThirdPartyController is a control loop that knows how to synchronize ThirdPartyResource objects with
// RESTful resources which are present in the API server.
type ThirdPartyController struct {
master ResourceInterface
thirdPartyResourceRegistry *thirdpartyresourceetcd.REST
}
// Synchronize a single resource with RESTful resources on the master
func (t *ThirdPartyController) SyncOneResource(rsrc *extensions.ThirdPartyResource) error {
// TODO: we also need to test if the existing installed resource matches the resource we are sync-ing.
// Currently, if there is an older, incompatible resource installed, we won't remove it. We should detect
// older, incompatible resources and remove them before testing if the resource exists.
hasResource, err := t.master.HasThirdPartyResource(rsrc)
if err != nil {
return err
}
if !hasResource {
return t.master.InstallThirdPartyResource(rsrc)
}
return nil
}
// Synchronize all resources with RESTful resources on the master
func (t *ThirdPartyController) SyncResources() error {
list, err := t.thirdPartyResourceRegistry.List(api.NewDefaultContext(), nil)
if err != nil {
return err
}
return t.syncResourceList(list)
}
func (t *ThirdPartyController) syncResourceList(list runtime.Object) error {
existing := sets.String{}
switch list := list.(type) {
case *extensions.ThirdPartyResourceList:
// Loop across all schema objects for third party resources
for ix := range list.Items {
item := &list.Items[ix]
// extract the api group and resource kind from the schema
_, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(item)
if err != nil {
return err
}
// place it in the set of resources that we expect, so that we don't delete it in the delete pass
existing.Insert(MakeThirdPartyPath(group))
// ensure a RESTful resource for this schema exists on the master
if err := t.SyncOneResource(item); err != nil {
return err
}
}
default:
return fmt.Errorf("expected a *ThirdPartyResourceList, got %#v", list)
}
// deletion phase, get all installed RESTful resources
installed := t.master.ListThirdPartyResources()
for _, installedAPI := range installed {
found := false
// search across the expected restful resources to see if this resource belongs to one of the expected ones
for _, apiPath := range existing.List() {
if installedAPI == apiPath || strings.HasPrefix(installedAPI, apiPath+"/") {
found = true
break
}
}
// not expected, delete the resource
if !found {
if err := t.master.RemoveThirdPartyResource(installedAPI); err != nil {
return err
}
}
}
return nil
}
func MakeThirdPartyPath(group string) string {
if len(group) == 0 {
return thirdpartyprefix
}
return thirdpartyprefix + "/" + group
}
func GetThirdPartyGroupName(path string) string {
return strings.TrimPrefix(strings.TrimPrefix(path, thirdpartyprefix), "/")
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"testing"
@ -40,7 +40,7 @@ func (f *FakeAPIInterface) RemoveThirdPartyResource(path string) error {
func (f *FakeAPIInterface) InstallThirdPartyResource(rsrc *expapi.ThirdPartyResource) error {
f.installed = append(f.installed, rsrc)
_, group, _ := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc)
f.apis = append(f.apis, makeThirdPartyPath(group))
f.apis = append(f.apis, MakeThirdPartyPath(group))
return nil
}
@ -49,7 +49,7 @@ func (f *FakeAPIInterface) HasThirdPartyResource(rsrc *expapi.ThirdPartyResource
return false, nil
}
_, group, _ := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc)
path := makeThirdPartyPath(group)
path := MakeThirdPartyPath(group)
for _, api := range f.apis {
if api == path {
return true, nil

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -24,11 +24,11 @@ import (
poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/policy/poddisruptionbudget/etcd"
)
type PolicyRESTStorageProvider struct{}
type RESTStorageProvider struct{}
var _ genericapiserver.RESTStorageProvider = &PolicyRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p PolicyRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1alpha1.SchemeGroupVersion) {
@ -39,7 +39,7 @@ func (p PolicyRESTStorageProvider) NewRESTStorage(apiResourceConfigSource generi
return apiGroupInfo, true
}
func (p PolicyRESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := policyapiv1alpha1.SchemeGroupVersion
storage := map[string]rest.Storage{}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package storage
package rest
import (
"fmt"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package master
package rest
import (
"k8s.io/kubernetes/pkg/api/rest"
@ -24,12 +24,12 @@ import (
storageclassetcd "k8s.io/kubernetes/pkg/registry/storage/storageclass/etcd"
)
type StorageRESTStorageProvider struct {
type RESTStorageProvider struct {
}
var _ genericapiserver.RESTStorageProvider = &StorageRESTStorageProvider{}
var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{}
func (p StorageRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(storageapiv1beta1.SchemeGroupVersion) {
@ -40,7 +40,7 @@ func (p StorageRESTStorageProvider) NewRESTStorage(apiResourceConfigSource gener
return apiGroupInfo, true
}
func (p StorageRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter genericapiserver.RESTOptionsGetter) map[string]rest.Storage {
version := storageapiv1beta1.SchemeGroupVersion
storage := map[string]rest.Storage{}