Skip to content

Commit

Permalink
Merge pull request #17885 from deads2k/api-14-legacyinstall
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue (batch tested with PRs 17859, 17885).

Add origin types kubectl scheme 

Fixes #17793 

Builds on #17815

/assign sttts
/assign juanvallejo

This centralizes the legacy install function. The next logical step is going to require that we start plumbing particular schemes or build individual schemes.  I looked at doing that here, but it appears we have some 500 hits just for scheme usage and I haven't decided the optimal solution for something like our graph yet.
  • Loading branch information
openshift-merge-robot authored Dec 20, 2017
2 parents 366bc7d + ec8902b commit 499023e
Show file tree
Hide file tree
Showing 17 changed files with 174 additions and 57 deletions.
7 changes: 6 additions & 1 deletion cmd/oc/oc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (
"time"

"k8s.io/apiserver/pkg/util/logs"
"k8s.io/kubernetes/pkg/kubectl/scheme"

"github.com/openshift/origin/pkg/cmd/util/serviceability"
"github.com/openshift/origin/pkg/oc/cli"

// install all APIs
_ "github.com/openshift/origin/pkg/api/install"
apiinstall "github.com/openshift/origin/pkg/api/install"
apilegacy "github.com/openshift/origin/pkg/api/legacy"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/core/install"
Expand All @@ -31,6 +33,9 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
}

apiinstall.InstallAll(scheme.Scheme, scheme.GroupFactoryRegistry, scheme.Registry)
apilegacy.LegacyInstallAll(scheme.Scheme, scheme.Registry)

basename := filepath.Base(os.Args[0])
command := cli.CommandFor(basename)
if err := command.Execute(); err != nil {
Expand Down
44 changes: 32 additions & 12 deletions pkg/api/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package install

import (
kv1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api/legacyscheme"
kapi "k8s.io/kubernetes/pkg/apis/core"
kapiv1 "k8s.io/kubernetes/pkg/apis/core/v1"
Expand All @@ -21,19 +24,20 @@ import (
_ "k8s.io/kubernetes/pkg/apis/settings/install"
_ "k8s.io/kubernetes/pkg/apis/storage/install"

_ "github.com/openshift/origin/pkg/apps/apis/apps/install"
_ "github.com/openshift/origin/pkg/authorization/apis/authorization/install"
_ "github.com/openshift/origin/pkg/build/apis/build/install"
_ "github.com/openshift/origin/pkg/cmd/server/api/install"
_ "github.com/openshift/origin/pkg/image/apis/image/install"
_ "github.com/openshift/origin/pkg/network/apis/network/install"
_ "github.com/openshift/origin/pkg/oauth/apis/oauth/install"
_ "github.com/openshift/origin/pkg/project/apis/project/install"
_ "github.com/openshift/origin/pkg/quota/apis/quota/install"
_ "github.com/openshift/origin/pkg/route/apis/route/install"
_ "github.com/openshift/origin/pkg/security/apis/security/install"
_ "github.com/openshift/origin/pkg/template/apis/template/install"
_ "github.com/openshift/origin/pkg/user/apis/user/install"

apps "github.com/openshift/origin/pkg/apps/apis/apps/install"
authz "github.com/openshift/origin/pkg/authorization/apis/authorization/install"
build "github.com/openshift/origin/pkg/build/apis/build/install"
image "github.com/openshift/origin/pkg/image/apis/image/install"
network "github.com/openshift/origin/pkg/network/apis/network/install"
oauth "github.com/openshift/origin/pkg/oauth/apis/oauth/install"
project "github.com/openshift/origin/pkg/project/apis/project/install"
quota "github.com/openshift/origin/pkg/quota/apis/quota/install"
route "github.com/openshift/origin/pkg/route/apis/route/install"
security "github.com/openshift/origin/pkg/security/apis/security/install"
template "github.com/openshift/origin/pkg/template/apis/template/install"
user "github.com/openshift/origin/pkg/user/apis/user/install"

metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -592,3 +596,19 @@ func init() {
return false, nil
})
}

func InstallAll(scheme *runtime.Scheme, groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager) {
// add Origin types to the given scheme
apps.Install(groupFactoryRegistry, registry, scheme)
authz.Install(groupFactoryRegistry, registry, scheme)
build.Install(groupFactoryRegistry, registry, scheme)
image.Install(groupFactoryRegistry, registry, scheme)
network.Install(groupFactoryRegistry, registry, scheme)
oauth.Install(groupFactoryRegistry, registry, scheme)
project.Install(groupFactoryRegistry, registry, scheme)
quota.Install(groupFactoryRegistry, registry, scheme)
route.Install(groupFactoryRegistry, registry, scheme)
security.Install(groupFactoryRegistry, registry, scheme)
template.Install(groupFactoryRegistry, registry, scheme)
user.Install(groupFactoryRegistry, registry, scheme)
}
107 changes: 107 additions & 0 deletions pkg/api/legacy/apigroups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package legacy

import (
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"

appsapi "github.com/openshift/origin/pkg/apps/apis/apps"
appsapiv1 "github.com/openshift/origin/pkg/apps/apis/apps/v1"
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
authorizationapiv1 "github.com/openshift/origin/pkg/authorization/apis/authorization/v1"
buildapi "github.com/openshift/origin/pkg/build/apis/build"
buildapiv1 "github.com/openshift/origin/pkg/build/apis/build/v1"
imageapi "github.com/openshift/origin/pkg/image/apis/image"
imageapiv1 "github.com/openshift/origin/pkg/image/apis/image/v1"
networkapi "github.com/openshift/origin/pkg/network/apis/network"
networkapiv1 "github.com/openshift/origin/pkg/network/apis/network/v1"
oauthapi "github.com/openshift/origin/pkg/oauth/apis/oauth"
oauthapiv1 "github.com/openshift/origin/pkg/oauth/apis/oauth/v1"
projectapi "github.com/openshift/origin/pkg/project/apis/project"
projectapiv1 "github.com/openshift/origin/pkg/project/apis/project/v1"
quotaapi "github.com/openshift/origin/pkg/quota/apis/quota"
quotaapiv1 "github.com/openshift/origin/pkg/quota/apis/quota/v1"
routeapi "github.com/openshift/origin/pkg/route/apis/route"
routeapiv1 "github.com/openshift/origin/pkg/route/apis/route/v1"
securityapi "github.com/openshift/origin/pkg/security/apis/security"
securityapiv1 "github.com/openshift/origin/pkg/security/apis/security/v1"
templateapi "github.com/openshift/origin/pkg/template/apis/template"
templateapiv1 "github.com/openshift/origin/pkg/template/apis/template/v1"
userapi "github.com/openshift/origin/pkg/user/apis/user"
userapiv1 "github.com/openshift/origin/pkg/user/apis/user/v1"
)

func InstallLegacyApps(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(appsapi.GroupName, appsapi.AddToSchemeInCoreGroup, appsapiv1.AddToSchemeInCoreGroup, sets.NewString(), registry, scheme)
}

func InstallLegacyAuthorization(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(authorizationapi.GroupName, authorizationapi.AddToSchemeInCoreGroup, authorizationapiv1.AddToSchemeInCoreGroup,
sets.NewString("ClusterRole", "ClusterRoleBinding", "ClusterPolicy", "ClusterPolicyBinding", "ResourceAccessReviewResponse", "SubjectAccessReviewResponse"),
registry, scheme,
)
}

func InstallLegacyBuild(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(buildapi.GroupName, buildapi.AddToSchemeInCoreGroup, buildapiv1.AddToSchemeInCoreGroup, sets.NewString(), registry, scheme)
}

func InstallLegacyImage(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(imageapi.GroupName, imageapi.AddToSchemeInCoreGroup, imageapiv1.AddToSchemeInCoreGroup,
sets.NewString("Image", "ImageSignature"),
registry, scheme,
)
}

func InstallLegacyNetwork(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(networkapi.GroupName, networkapi.AddToSchemeInCoreGroup, networkapiv1.AddToSchemeInCoreGroup,
sets.NewString("ClusterNetwork", "HostSubnet", "NetNamespace"),
registry, scheme,
)
}

func InstallLegacyOAuth(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(oauthapi.GroupName, oauthapi.AddToSchemeInCoreGroup, oauthapiv1.AddToSchemeInCoreGroup,
sets.NewString("OAuthAccessToken", "OAuthAuthorizeToken", "OAuthClient", "OAuthClientAuthorization"),
registry, scheme,
)
}

func InstallLegacyProject(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(projectapi.GroupName, projectapi.AddToSchemeInCoreGroup, projectapiv1.AddToSchemeInCoreGroup,
sets.NewString("Project", "ProjectRequest"),
registry, scheme,
)
}

func InstallLegacyQuota(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(quotaapi.GroupName, quotaapi.AddToSchemeInCoreGroup, quotaapiv1.AddToSchemeInCoreGroup,
sets.NewString("ClusterResourceQuota"),
registry, scheme,
)
}

func InstallLegacyRoute(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(routeapi.GroupName, routeapi.AddToSchemeInCoreGroup, routeapiv1.AddToSchemeInCoreGroup, sets.NewString(), registry, scheme)
}

func InstallLegacySecurity(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(securityapi.GroupName, securityapi.AddToSchemeInCoreGroup, securityapiv1.AddToSchemeInCoreGroup,
sets.NewString("SecurityContextConstraints"),
registry, scheme,
)
}

func InstallLegacyTemplate(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(templateapi.GroupName, templateapi.AddToSchemeInCoreGroup, templateapiv1.AddToSchemeInCoreGroup,
sets.NewString("BrokerTemplateInstance"),
registry, scheme,
)
}

func InstallLegacyUser(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacy(userapi.GroupName, userapi.AddToSchemeInCoreGroup, userapiv1.AddToSchemeInCoreGroup,
sets.NewString("User", "Identity", "UserIdentityMapping", "Group"),
registry, scheme,
)
}
15 changes: 15 additions & 0 deletions pkg/api/legacy/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ var (
coreV1 = schema.GroupVersion{Group: "", Version: "v1"}
)

func LegacyInstallAll(scheme *runtime.Scheme, registry *registered.APIRegistrationManager) {
InstallLegacyApps(scheme, registry)
InstallLegacyAuthorization(scheme, registry)
InstallLegacyBuild(scheme, registry)
InstallLegacyImage(scheme, registry)
InstallLegacyNetwork(scheme, registry)
InstallLegacyOAuth(scheme, registry)
InstallLegacyProject(scheme, registry)
InstallLegacyQuota(scheme, registry)
InstallLegacyRoute(scheme, registry)
InstallLegacySecurity(scheme, registry)
InstallLegacyTemplate(scheme, registry)
InstallLegacyUser(scheme, registry)
}

func InstallLegacy(group string, addToCore, addToCoreV1 func(*runtime.Scheme) error, rootScopedKinds sets.String, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
interfacesFor := interfacesForGroup(group)

Expand Down
3 changes: 1 addition & 2 deletions pkg/apps/apis/apps/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import (
legacy "github.com/openshift/origin/pkg/api/legacy"
appsapi "github.com/openshift/origin/pkg/apps/apis/apps"
appsapiv1 "github.com/openshift/origin/pkg/apps/apis/apps/v1"
"k8s.io/apimachinery/pkg/util/sets"
)

func init() {
legacy.InstallLegacy(appsapi.GroupName, appsapi.AddToSchemeInCoreGroup, appsapiv1.AddToSchemeInCoreGroup, sets.NewString(), legacyscheme.Registry, legacyscheme.Scheme)
legacy.InstallLegacyApps(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/authorization/apis/authorization/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ import (
)

func init() {
legacy.InstallLegacy(authorizationapi.GroupName, authorizationapi.AddToSchemeInCoreGroup, authorizationapiv1.AddToSchemeInCoreGroup,
sets.NewString("ClusterRole", "ClusterRoleBinding", "ClusterPolicy", "ClusterPolicyBinding", "ResourceAccessReviewResponse", "SubjectAccessReviewResponse"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyAuthorization(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
3 changes: 1 addition & 2 deletions pkg/build/apis/build/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import (
"github.com/openshift/origin/pkg/api/legacy"
buildapi "github.com/openshift/origin/pkg/build/apis/build"
buildapiv1 "github.com/openshift/origin/pkg/build/apis/build/v1"
"k8s.io/apimachinery/pkg/util/sets"
)

func init() {
legacy.InstallLegacy(buildapi.GroupName, buildapi.AddToSchemeInCoreGroup, buildapiv1.AddToSchemeInCoreGroup, sets.NewString(), legacyscheme.Registry, legacyscheme.Scheme)
legacy.InstallLegacyBuild(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/image/apis/image/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import (
)

func init() {
legacy.InstallLegacy(imageapi.GroupName, imageapi.AddToSchemeInCoreGroup, imageapiv1.AddToSchemeInCoreGroup,
sets.NewString("Image", "ImageSignature"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyImage(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/network/apis/network/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
)

func init() {
legacy.InstallLegacy(sdnapi.GroupName, sdnapi.AddToSchemeInCoreGroup, sdnapiv1.AddToSchemeInCoreGroup,
sets.NewString("ClusterNetwork", "HostSubnet", "NetNamespace"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyNetwork(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/oauth/apis/oauth/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
)

func init() {
legacy.InstallLegacy(oauthapi.GroupName, oauthapi.AddToSchemeInCoreGroup, oauthapiv1.AddToSchemeInCoreGroup,
sets.NewString("OAuthAccessToken", "OAuthAuthorizeToken", "OAuthClient", "OAuthClientAuthorization"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyOAuth(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/project/apis/project/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
)

func init() {
legacy.InstallLegacy(projectapi.GroupName, projectapi.AddToSchemeInCoreGroup, projectapiv1.AddToSchemeInCoreGroup,
sets.NewString("Project", "ProjectRequest"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyProject(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/quota/apis/quota/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
)

func init() {
legacy.InstallLegacy(quotaapi.GroupName, quotaapi.AddToSchemeInCoreGroup, quotaapiv1.AddToSchemeInCoreGroup,
sets.NewString("ClusterResourceQuota"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyQuota(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
3 changes: 1 addition & 2 deletions pkg/route/apis/route/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import (
"github.com/openshift/origin/pkg/api/legacy"
routeapi "github.com/openshift/origin/pkg/route/apis/route"
routeapiv1 "github.com/openshift/origin/pkg/route/apis/route/v1"
"k8s.io/apimachinery/pkg/util/sets"
)

func init() {
legacy.InstallLegacy(routeapi.GroupName, routeapi.AddToSchemeInCoreGroup, routeapiv1.AddToSchemeInCoreGroup, sets.NewString(), legacyscheme.Registry, legacyscheme.Scheme)
legacy.InstallLegacyRoute(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/security/apis/security/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ import (

func init() {
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
legacy.InstallLegacy(securityapi.GroupName, securityapi.AddToSchemeInCoreGroup, securityapiv1.AddToSchemeInCoreGroup,
sets.NewString("SecurityContextConstraints"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacySecurity(legacyscheme.Scheme, legacyscheme.Registry)
}

// Install registers the API group and adds types to a scheme
Expand Down
5 changes: 1 addition & 4 deletions pkg/template/apis/template/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
)

func init() {
legacy.InstallLegacy(templateapi.GroupName, templateapi.AddToSchemeInCoreGroup, templateapiv1.AddToSchemeInCoreGroup,
sets.NewString("BrokerTemplateInstance"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyTemplate(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
5 changes: 1 addition & 4 deletions pkg/user/apis/user/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
)

func init() {
legacy.InstallLegacy(userapi.GroupName, userapi.AddToSchemeInCoreGroup, userapiv1.AddToSchemeInCoreGroup,
sets.NewString("User", "Identity", "UserIdentityMapping", "Group"),
legacyscheme.Registry, legacyscheme.Scheme,
)
legacy.InstallLegacyUser(legacyscheme.Scheme, legacyscheme.Registry)
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
}

Expand Down
4 changes: 2 additions & 2 deletions vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 499023e

Please sign in to comment.