diff --git a/pkg/cmd/server/origin/aggregator.go b/pkg/cmd/server/origin/aggregator.go index ca86582b9a4a..7da0fdd20baa 100644 --- a/pkg/cmd/server/origin/aggregator.go +++ b/pkg/cmd/server/origin/aggregator.go @@ -25,6 +25,8 @@ import ( "net/http" "strings" + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" @@ -123,16 +125,74 @@ func createAggregatorServer(aggregatorConfig *aggregatorapiserver.Config, delega } func makeAPIService(gv schema.GroupVersion) *apiregistration.APIService { + apiServicePriority, ok := apiVersionPriorities[gv] + if !ok { + // if we aren't found, then we shouldn't register ourselves because it could result in a CRD group version + // being permanently stuck in the APIServices list. + glog.Infof("Skipping APIService creation for %v", gv) + return nil + } return &apiregistration.APIService{ ObjectMeta: metav1.ObjectMeta{Name: gv.Version + "." + gv.Group}, Spec: apiregistration.APIServiceSpec{ - Group: gv.Group, - Version: gv.Version, - Priority: 100, + Group: gv.Group, + Version: gv.Version, + GroupPriorityMinimum: apiServicePriority.group, + VersionPriority: apiServicePriority.version, }, } } +type priority struct { + group int32 + version int32 +} + +// The proper way to resolve this letting the aggregator know the desired group and version-within-group order of the underlying servers +// is to refactor the genericapiserver.DelegationTarget to include a list of priorities based on which APIs were installed. +// This requires the APIGroupInfo struct to evolve and include the concept of priorities and to avoid mistakes, the core storage map there needs to be updated. +// That ripples out every bit as far as you'd expect, so for 1.7 we'll include the list here instead of being built up during storage. +var apiVersionPriorities = map[schema.GroupVersion]priority{ + {Group: "", Version: "v1"}: {group: 18000, version: 1}, + // extensions is above the rest for CLI compatibility, though the level of unqalified resource compatibility we + // can reasonably expect seems questionable. + {Group: "extensions", Version: "v1beta1"}: {group: 17900, version: 1}, + // to my knowledge, nothing below here collides + {Group: "apps", Version: "v1beta1"}: {group: 17800, version: 1}, + {Group: "authentication.k8s.io", Version: "v1"}: {group: 17700, version: 15}, + {Group: "authentication.k8s.io", Version: "v1beta1"}: {group: 17700, version: 9}, + {Group: "authorization.k8s.io", Version: "v1"}: {group: 17600, version: 15}, + {Group: "authorization.k8s.io", Version: "v1beta1"}: {group: 17600, version: 9}, + {Group: "autoscaling", Version: "v1"}: {group: 17500, version: 15}, + {Group: "autoscaling", Version: "v2alpha1"}: {group: 17500, version: 9}, + {Group: "batch", Version: "v1"}: {group: 17400, version: 15}, + {Group: "batch", Version: "v2alpha1"}: {group: 17400, version: 9}, + {Group: "certificates.k8s.io", Version: "v1beta1"}: {group: 17300, version: 9}, + {Group: "networking.k8s.io", Version: "v1"}: {group: 17200, version: 15}, + {Group: "policy", Version: "v1beta1"}: {group: 17100, version: 9}, + {Group: "rbac.authorization.k8s.io", Version: "v1beta1"}: {group: 17000, version: 12}, + {Group: "rbac.authorization.k8s.io", Version: "v1alpha1"}: {group: 17000, version: 9}, + {Group: "settings.k8s.io", Version: "v1alpha1"}: {group: 16900, version: 9}, + {Group: "storage.k8s.io", Version: "v1"}: {group: 16800, version: 15}, + {Group: "storage.k8s.io", Version: "v1beta1"}: {group: 16800, version: 9}, + {Group: "apiextensions.k8s.io", Version: "v1beta1"}: {group: 16700, version: 9}, + + // arbitrarily starting openshift around 10000. + // bump authorization above RBAC + {Group: "authorization.openshift.io", Version: "v1"}: {group: 17050, version: 15}, + {Group: "build.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "apps.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "image.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "oauth.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "project.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "quota.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "route.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "network.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "security.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "template.openshift.io", Version: "v1"}: {group: 9900, version: 15}, + {Group: "user.openshift.io", Version: "v1"}: {group: 9900, version: 15}, +} + func apiServicesToRegister(delegateAPIServer genericapiserver.DelegationTarget, registration autoregister.AutoAPIServiceRegistration) []*apiregistration.APIService { apiServices := []*apiregistration.APIService{} @@ -154,14 +214,9 @@ func apiServicesToRegister(delegateAPIServer genericapiserver.DelegationTarget, } apiService := makeAPIService(schema.GroupVersion{Group: tokens[2], Version: tokens[3]}) - - // TODO this is probably an indication that we need explicit and precise control over the discovery chain - // but for now its a special case - // apps has to come last for compatibility with 1.5 kubectl clients - if apiService.Spec.Group == "apps" { - apiService.Spec.Priority = 110 + if apiService == nil { + continue } - registration.AddAPIServiceToSync(apiService) apiServices = append(apiServices, apiService) }