diff --git a/hack/import-restrictions.json b/hack/import-restrictions.json index 280323ca1014..9835e9bef222 100644 --- a/hack/import-restrictions.json +++ b/hack/import-restrictions.json @@ -42,11 +42,7 @@ ], "ignoredSubTrees": [ "github.com/openshift/origin/pkg/dockerregistry", - "github.com/openshift/origin/pkg/cmd/dockerregistry", - "github.com/openshift/origin/pkg/cmd/server/origin", - "github.com/openshift/origin/pkg/generate/app", - "github.com/openshift/origin/pkg/image/importer", - "github.com/openshift/origin/pkg/image/registry/imagestreamimport" + "github.com/openshift/origin/pkg/cmd/dockerregistry" ], "forbiddenImportPackageRoots": [ "github.com/openshift/origin/pkg/dockerregistry" diff --git a/pkg/authorization/apiserver/apiserver.go b/pkg/authorization/apiserver/apiserver.go new file mode 100644 index 000000000000..5dd3fbf33fc4 --- /dev/null +++ b/pkg/authorization/apiserver/apiserver.go @@ -0,0 +1,137 @@ +package apiserver + +import ( + "fmt" + "sync" + + "k8s.io/apimachinery/pkg/apimachinery/registered" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/registry/rest" + genericapiserver "k8s.io/apiserver/pkg/server" + restclient "k8s.io/client-go/rest" + rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + kinternalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" + rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" + + authorizationapiv1 "github.com/openshift/origin/pkg/authorization/apis/authorization/v1" + "github.com/openshift/origin/pkg/authorization/authorizer" + "github.com/openshift/origin/pkg/authorization/registry/clusterrole" + "github.com/openshift/origin/pkg/authorization/registry/clusterrolebinding" + "github.com/openshift/origin/pkg/authorization/registry/localresourceaccessreview" + "github.com/openshift/origin/pkg/authorization/registry/localsubjectaccessreview" + "github.com/openshift/origin/pkg/authorization/registry/resourceaccessreview" + "github.com/openshift/origin/pkg/authorization/registry/role" + "github.com/openshift/origin/pkg/authorization/registry/rolebinding" + rolebindingrestrictionetcd "github.com/openshift/origin/pkg/authorization/registry/rolebindingrestriction/etcd" + "github.com/openshift/origin/pkg/authorization/registry/selfsubjectrulesreview" + "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" + "github.com/openshift/origin/pkg/authorization/registry/subjectrulesreview" +) + +type AuthorizationAPIServerConfig struct { + GenericConfig *genericapiserver.Config + + CoreAPIServerClientConfig *restclient.Config + KubeInternalInformers kinternalinformers.SharedInformerFactory + RuleResolver rbacregistryvalidation.AuthorizationRuleResolver + SubjectLocator authorizer.SubjectLocator + + // TODO these should all become local eventually + Scheme *runtime.Scheme + Registry *registered.APIRegistrationManager + Codecs serializer.CodecFactory + + makeV1Storage sync.Once + v1Storage map[string]rest.Storage + v1StorageErr error +} + +type AuthorizationAPIServer struct { + GenericAPIServer *genericapiserver.GenericAPIServer +} + +type completedConfig struct { + *AuthorizationAPIServerConfig +} + +// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. +func (c *AuthorizationAPIServerConfig) Complete() completedConfig { + c.GenericConfig.Complete() + + return completedConfig{c} +} + +// SkipComplete provides a way to construct a server instance without config completion. +func (c *AuthorizationAPIServerConfig) SkipComplete() completedConfig { + return completedConfig{c} +} + +// New returns a new instance of AuthorizationAPIServer from the given config. +func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*AuthorizationAPIServer, error) { + genericServer, err := c.AuthorizationAPIServerConfig.GenericConfig.SkipComplete().New("authorization.openshift.io-apiserver", delegationTarget) // completion is done in Complete, no need for a second time + if err != nil { + return nil, err + } + + s := &AuthorizationAPIServer{ + GenericAPIServer: genericServer, + } + + v1Storage, err := c.V1RESTStorage() + if err != nil { + return nil, err + } + + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authorizationapiv1.GroupName, c.Registry, c.Scheme, metav1.ParameterCodec, c.Codecs) + apiGroupInfo.GroupMeta.GroupVersion = authorizationapiv1.SchemeGroupVersion + apiGroupInfo.VersionedResourcesStorageMap[authorizationapiv1.SchemeGroupVersion.Version] = v1Storage + if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { + return nil, err + } + + return s, nil +} + +func (c *AuthorizationAPIServerConfig) V1RESTStorage() (map[string]rest.Storage, error) { + c.makeV1Storage.Do(func() { + c.v1Storage, c.v1StorageErr = c.newV1RESTStorage() + }) + + return c.v1Storage, c.v1StorageErr +} + +func (c *AuthorizationAPIServerConfig) newV1RESTStorage() (map[string]rest.Storage, error) { + rbacClient, err := rbacclient.NewForConfig(c.GenericConfig.LoopbackClientConfig) + if err != nil { + return nil, err + } + + selfSubjectRulesReviewStorage := selfsubjectrulesreview.NewREST(c.RuleResolver, c.KubeInternalInformers.Rbac().InternalVersion().ClusterRoles().Lister()) + subjectRulesReviewStorage := subjectrulesreview.NewREST(c.RuleResolver, c.KubeInternalInformers.Rbac().InternalVersion().ClusterRoles().Lister()) + subjectAccessReviewStorage := subjectaccessreview.NewREST(c.GenericConfig.Authorizer) + subjectAccessReviewRegistry := subjectaccessreview.NewRegistry(subjectAccessReviewStorage) + localSubjectAccessReviewStorage := localsubjectaccessreview.NewREST(subjectAccessReviewRegistry) + resourceAccessReviewStorage := resourceaccessreview.NewREST(c.GenericConfig.Authorizer, c.SubjectLocator) + resourceAccessReviewRegistry := resourceaccessreview.NewRegistry(resourceAccessReviewStorage) + localResourceAccessReviewStorage := localresourceaccessreview.NewREST(resourceAccessReviewRegistry) + roleBindingRestrictionStorage, err := rolebindingrestrictionetcd.NewREST(c.GenericConfig.RESTOptionsGetter) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + + v1Storage := map[string]rest.Storage{} + v1Storage["resourceAccessReviews"] = resourceAccessReviewStorage + v1Storage["subjectAccessReviews"] = subjectAccessReviewStorage + v1Storage["localSubjectAccessReviews"] = localSubjectAccessReviewStorage + v1Storage["localResourceAccessReviews"] = localResourceAccessReviewStorage + v1Storage["selfSubjectRulesReviews"] = selfSubjectRulesReviewStorage + v1Storage["subjectRulesReviews"] = subjectRulesReviewStorage + v1Storage["roles"] = role.NewREST(rbacClient.RESTClient()) + v1Storage["roleBindings"] = rolebinding.NewREST(rbacClient.RESTClient()) + v1Storage["clusterRoles"] = clusterrole.NewREST(rbacClient.RESTClient()) + v1Storage["clusterRoleBindings"] = clusterrolebinding.NewREST(rbacClient.RESTClient()) + v1Storage["roleBindingRestrictions"] = roleBindingRestrictionStorage + return v1Storage, nil +} diff --git a/pkg/cmd/server/origin/openshift_apiserver.go b/pkg/cmd/server/origin/openshift_apiserver.go index bd9c91a94f70..66454adb7964 100644 --- a/pkg/cmd/server/origin/openshift_apiserver.go +++ b/pkg/cmd/server/origin/openshift_apiserver.go @@ -29,6 +29,7 @@ import ( "github.com/openshift/origin/pkg/api" "github.com/openshift/origin/pkg/api/v1" + authorizationapiserver "github.com/openshift/origin/pkg/authorization/apiserver" "github.com/openshift/origin/pkg/authorization/authorizer" authorizationinformer "github.com/openshift/origin/pkg/authorization/generated/informers/internalversion" buildapiserver "github.com/openshift/origin/pkg/build/apiserver" @@ -39,7 +40,9 @@ import ( oappsapiserver "github.com/openshift/origin/pkg/deploy/apiserver" imageadmission "github.com/openshift/origin/pkg/image/admission" imageapi "github.com/openshift/origin/pkg/image/apis/image" + imageapiserver "github.com/openshift/origin/pkg/image/apiserver" networkapiserver "github.com/openshift/origin/pkg/network/apiserver" + oauthapiserver "github.com/openshift/origin/pkg/oauth/apiserver" "github.com/openshift/origin/pkg/oc/admin/policy" projectauth "github.com/openshift/origin/pkg/project/auth" projectcache "github.com/openshift/origin/pkg/project/cache" @@ -53,7 +56,7 @@ import ( userapiserver "github.com/openshift/origin/pkg/user/apiserver" "github.com/openshift/origin/pkg/version" - authzapiv1 "github.com/openshift/origin/pkg/authorization/apis/authorization/v1" + authorizationapiv1 "github.com/openshift/origin/pkg/authorization/apis/authorization/v1" buildapiv1 "github.com/openshift/origin/pkg/build/apis/build/v1" imageapiv1 "github.com/openshift/origin/pkg/image/apis/image/v1" networkapiv1 "github.com/openshift/origin/pkg/network/apis/network/v1" @@ -84,7 +87,9 @@ type OpenshiftAPIConfig struct { // these are all required to build our storage RuleResolver rbacregistryvalidation.AuthorizationRuleResolver SubjectLocator authorizer.SubjectLocator - LimitVerifier imageadmission.LimitVerifier + + // for Images + LimitVerifier imageadmission.LimitVerifier // RegistryHostnameRetriever retrieves the internal and external hostname of // the integrated registry, or false if no such registry is available. RegistryHostnameRetriever imageapi.RegistryHostnameRetriever @@ -100,6 +105,7 @@ type OpenshiftAPIConfig struct { EnableBuilds bool + // oauth API server ServiceAccountMethod configapi.GrantHandlerType ClusterQuotaMappingController *clusterquotamapping.ClusterQuotaMappingController @@ -242,6 +248,30 @@ func (c *completedConfig) withAppsAPIServer(delegateAPIServer genericapiserver.D return server.GenericAPIServer, legacyStorageMutators{legacyStorageMutatorFunc(legacyDCRollbackMutator.Mutate), &legacyStorageVersionMutator{version: oappsapiv1.SchemeGroupVersion, storage: storage}}, nil } +func (c *completedConfig) withAuthorizationAPIServer(delegateAPIServer genericapiserver.DelegationTarget) (genericapiserver.DelegationTarget, legacyStorageMutator, error) { + config := &authorizationapiserver.AuthorizationAPIServerConfig{ + GenericConfig: c.GenericConfig, + CoreAPIServerClientConfig: c.GenericConfig.LoopbackClientConfig, + KubeInternalInformers: c.KubeInternalInformers, + RuleResolver: c.RuleResolver, + SubjectLocator: c.SubjectLocator, + Codecs: kapi.Codecs, + Registry: kapi.Registry, + Scheme: kapi.Scheme, + } + server, err := config.Complete().New(delegateAPIServer) + if err != nil { + return nil, nil, err + } + storage, err := config.V1RESTStorage() + if err != nil { + return nil, nil, err + } + server.GenericAPIServer.PrepareRun() // this triggers openapi construction + + return server.GenericAPIServer, &legacyStorageVersionMutator{version: authorizationapiv1.SchemeGroupVersion, storage: storage}, nil +} + func (c *completedConfig) withBuildAPIServer(delegateAPIServer genericapiserver.DelegationTarget) (genericapiserver.DelegationTarget, legacyStorageMutator, error) { if !c.EnableBuilds { return delegateAPIServer, legacyStorageMutatorFunc(func(map[schema.GroupVersion]map[string]rest.Storage) {}), nil @@ -268,6 +298,31 @@ func (c *completedConfig) withBuildAPIServer(delegateAPIServer genericapiserver. return server.GenericAPIServer, &legacyStorageVersionMutator{version: buildapiv1.SchemeGroupVersion, storage: storage}, nil } +func (c *completedConfig) withImageAPIServer(delegateAPIServer genericapiserver.DelegationTarget) (genericapiserver.DelegationTarget, legacyStorageMutator, error) { + config := &imageapiserver.ImageAPIServerConfig{ + GenericConfig: c.GenericConfig, + CoreAPIServerClientConfig: c.GenericConfig.LoopbackClientConfig, + LimitVerifier: c.LimitVerifier, + RegistryHostnameRetriever: c.RegistryHostnameRetriever, + AllowedRegistriesForImport: c.AllowedRegistriesForImport, + MaxImagesBulkImportedPerRepository: c.MaxImagesBulkImportedPerRepository, + Codecs: kapi.Codecs, + Registry: kapi.Registry, + Scheme: kapi.Scheme, + } + server, err := config.Complete().New(delegateAPIServer) + if err != nil { + return nil, nil, err + } + storage, err := config.V1RESTStorage() + if err != nil { + return nil, nil, err + } + server.GenericAPIServer.PrepareRun() // this triggers openapi construction + + return server.GenericAPIServer, &legacyStorageVersionMutator{version: imageapiv1.SchemeGroupVersion, storage: storage}, nil +} + func (c *completedConfig) withNetworkAPIServer(delegateAPIServer genericapiserver.DelegationTarget) (genericapiserver.DelegationTarget, legacyStorageMutator, error) { config := &networkapiserver.NetworkAPIServerConfig{ GenericConfig: c.GenericConfig, @@ -288,6 +343,28 @@ func (c *completedConfig) withNetworkAPIServer(delegateAPIServer genericapiserve return server.GenericAPIServer, &legacyStorageVersionMutator{version: networkapiv1.SchemeGroupVersion, storage: storage}, nil } +func (c *completedConfig) withOAuthAPIServer(delegateAPIServer genericapiserver.DelegationTarget) (genericapiserver.DelegationTarget, legacyStorageMutator, error) { + config := &oauthapiserver.OAuthAPIServerConfig{ + GenericConfig: c.GenericConfig, + CoreAPIServerClientConfig: c.GenericConfig.LoopbackClientConfig, + ServiceAccountMethod: c.ServiceAccountMethod, + Codecs: kapi.Codecs, + Registry: kapi.Registry, + Scheme: kapi.Scheme, + } + server, err := config.Complete().New(delegateAPIServer) + if err != nil { + return nil, nil, err + } + storage, err := config.V1RESTStorage() + if err != nil { + return nil, nil, err + } + server.GenericAPIServer.PrepareRun() // this triggers openapi construction + + return server.GenericAPIServer, &legacyStorageVersionMutator{version: oauthapiv1.SchemeGroupVersion, storage: storage}, nil +} + func (c *completedConfig) withTemplateAPIServer(delegateAPIServer genericapiserver.DelegationTarget) (genericapiserver.DelegationTarget, legacyStorageMutator, error) { config := &templateapiserver.TemplateConfig{ GenericConfig: c.GenericConfig, @@ -346,8 +423,11 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) legacyStorageModifier := legacyStorageMutators{} delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withAppsAPIServer) + delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withAuthorizationAPIServer) delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withBuildAPIServer) + delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withImageAPIServer) delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withNetworkAPIServer) + delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withOAuthAPIServer) delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withTemplateAPIServer) delegateAPIServer, legacyStorageModifier = addAPIServerOrDie(delegateAPIServer, legacyStorageModifier, c.withUserAPIServer) @@ -518,9 +598,6 @@ var apiGroupsVersions = []apiGroupInfo{ {PreferredVersion: "v1", Versions: []schema.GroupVersion{projectapiv1.SchemeGroupVersion}}, {PreferredVersion: "v1", Versions: []schema.GroupVersion{quotaapiv1.SchemeGroupVersion}}, {PreferredVersion: "v1", Versions: []schema.GroupVersion{routeapiv1.SchemeGroupVersion}}, - {PreferredVersion: "v1", Versions: []schema.GroupVersion{imageapiv1.SchemeGroupVersion}}, - {PreferredVersion: "v1", Versions: []schema.GroupVersion{authzapiv1.SchemeGroupVersion}}, - {PreferredVersion: "v1", Versions: []schema.GroupVersion{oauthapiv1.SchemeGroupVersion}}, } // isPreferredGroupVersion returns true if the given GroupVersion is preferred version in diff --git a/pkg/cmd/server/origin/storage.go b/pkg/cmd/server/origin/storage.go index 96d27dc87307..c7c3ec661967 100644 --- a/pkg/cmd/server/origin/storage.go +++ b/pkg/cmd/server/origin/storage.go @@ -2,60 +2,23 @@ package origin import ( "fmt" - "time" "github.com/golang/glog" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/registry/rest" - restclient "k8s.io/client-go/rest" - "k8s.io/client-go/util/flowcontrol" authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion" - authzapiv1 "github.com/openshift/origin/pkg/authorization/apis/authorization/v1" - "github.com/openshift/origin/pkg/dockerregistry" - imageapiv1 "github.com/openshift/origin/pkg/image/apis/image/v1" - "github.com/openshift/origin/pkg/image/importer" - imageimporter "github.com/openshift/origin/pkg/image/importer" - "github.com/openshift/origin/pkg/image/registry/image" - imageetcd "github.com/openshift/origin/pkg/image/registry/image/etcd" - "github.com/openshift/origin/pkg/image/registry/imagesecret" - "github.com/openshift/origin/pkg/image/registry/imagesignature" - "github.com/openshift/origin/pkg/image/registry/imagestream" - imagestreametcd "github.com/openshift/origin/pkg/image/registry/imagestream/etcd" - "github.com/openshift/origin/pkg/image/registry/imagestreamimage" - "github.com/openshift/origin/pkg/image/registry/imagestreamimport" - "github.com/openshift/origin/pkg/image/registry/imagestreammapping" - "github.com/openshift/origin/pkg/image/registry/imagestreamtag" - oauthapi "github.com/openshift/origin/pkg/oauth/apis/oauth" - oauthapiv1 "github.com/openshift/origin/pkg/oauth/apis/oauth/v1" - oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion" - accesstokenetcd "github.com/openshift/origin/pkg/oauth/registry/oauthaccesstoken/etcd" - authorizetokenetcd "github.com/openshift/origin/pkg/oauth/registry/oauthauthorizetoken/etcd" - clientetcd "github.com/openshift/origin/pkg/oauth/registry/oauthclient/etcd" - clientauthetcd "github.com/openshift/origin/pkg/oauth/registry/oauthclientauthorization/etcd" projectapiv1 "github.com/openshift/origin/pkg/project/apis/project/v1" projectproxy "github.com/openshift/origin/pkg/project/registry/project/proxy" projectrequeststorage "github.com/openshift/origin/pkg/project/registry/projectrequest/delegated" routeapiv1 "github.com/openshift/origin/pkg/route/apis/route/v1" routeetcd "github.com/openshift/origin/pkg/route/registry/route/etcd" - saoauth "github.com/openshift/origin/pkg/serviceaccounts/oauthclient" quotaapiv1 "github.com/openshift/origin/pkg/quota/apis/quota/v1" appliedclusterresourcequotaregistry "github.com/openshift/origin/pkg/quota/registry/appliedclusterresourcequota" clusterresourcequotaetcd "github.com/openshift/origin/pkg/quota/registry/clusterresourcequota/etcd" - "github.com/openshift/origin/pkg/authorization/registry/clusterrole" - "github.com/openshift/origin/pkg/authorization/registry/clusterrolebinding" - "github.com/openshift/origin/pkg/authorization/registry/localresourceaccessreview" - "github.com/openshift/origin/pkg/authorization/registry/localsubjectaccessreview" - "github.com/openshift/origin/pkg/authorization/registry/resourceaccessreview" - "github.com/openshift/origin/pkg/authorization/registry/role" - "github.com/openshift/origin/pkg/authorization/registry/rolebinding" - rolebindingrestrictionetcd "github.com/openshift/origin/pkg/authorization/registry/rolebindingrestriction/etcd" - "github.com/openshift/origin/pkg/authorization/registry/selfsubjectrulesreview" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" - "github.com/openshift/origin/pkg/authorization/registry/subjectrulesreview" configapi "github.com/openshift/origin/pkg/cmd/server/api" securityapiv1 "github.com/openshift/origin/pkg/security/apis/security/v1" "github.com/openshift/origin/pkg/security/registry/podsecuritypolicyreview" @@ -71,29 +34,6 @@ import ( // TODO this function needs to be broken apart with each API group owning their own storage, probably with two method // per API group to give us legacy and current storage func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string]rest.Storage, error) { - // TODO: allow the system CAs and the local CAs to be joined together. - importTransport, err := restclient.TransportFor(&restclient.Config{}) - if err != nil { - return nil, fmt.Errorf("unable to configure a default transport for importing: %v", err) - } - insecureImportTransport, err := restclient.TransportFor(&restclient.Config{ - TLSClientConfig: restclient.TLSClientConfig{ - Insecure: true, - }, - }) - if err != nil { - return nil, fmt.Errorf("unable to configure a default transport for importing: %v", err) - } - - selfSubjectRulesReviewStorage := selfsubjectrulesreview.NewREST(c.RuleResolver, c.KubeInternalInformers.Rbac().InternalVersion().ClusterRoles().Lister()) - subjectRulesReviewStorage := subjectrulesreview.NewREST(c.RuleResolver, c.KubeInternalInformers.Rbac().InternalVersion().ClusterRoles().Lister()) - subjectAccessReviewStorage := subjectaccessreview.NewREST(c.GenericConfig.Authorizer) - subjectAccessReviewRegistry := subjectaccessreview.NewRegistry(subjectAccessReviewStorage) - localSubjectAccessReviewStorage := localsubjectaccessreview.NewREST(subjectAccessReviewRegistry) - resourceAccessReviewStorage := resourceaccessreview.NewREST(c.GenericConfig.Authorizer, c.SubjectLocator) - resourceAccessReviewRegistry := resourceaccessreview.NewRegistry(resourceAccessReviewStorage) - localResourceAccessReviewStorage := localresourceaccessreview.NewREST(resourceAccessReviewRegistry) - sccStorage := c.SCCStorage // TODO allow this when we're sure that its storing correctly and we want to allow starting up without embedding kube if false && sccStorage == nil { @@ -113,44 +53,6 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string c.KubeClientInternal, ) - imageStorage, err := imageetcd.NewREST(c.GenericConfig.RESTOptionsGetter) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - imageRegistry := image.NewRegistry(imageStorage) - imageSignatureStorage := imagesignature.NewREST(c.DeprecatedOpenshiftClient.Images()) - imageStreamSecretsStorage := imagesecret.NewREST(c.KubeClientInternal.Core()) - imageStreamStorage, imageStreamStatusStorage, internalImageStreamStorage, err := imagestreametcd.NewREST(c.GenericConfig.RESTOptionsGetter, c.RegistryHostnameRetriever, subjectAccessReviewRegistry, c.LimitVerifier) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - imageStreamRegistry := imagestream.NewRegistry(imageStreamStorage, imageStreamStatusStorage, internalImageStreamStorage) - imageStreamMappingStorage := imagestreammapping.NewREST(imageRegistry, imageStreamRegistry, c.RegistryHostnameRetriever) - imageStreamTagStorage := imagestreamtag.NewREST(imageRegistry, imageStreamRegistry) - importerCache, err := imageimporter.NewImageStreamLayerCache(imageimporter.DefaultImageStreamLayerCacheSize) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - importerFn := func(r importer.RepositoryRetriever) imageimporter.Interface { - return imageimporter.NewImageStreamImporter(r, c.MaxImagesBulkImportedPerRepository, flowcontrol.NewTokenBucketRateLimiter(2.0, 3), &importerCache) - } - importerDockerClientFn := func() dockerregistry.Client { - return dockerregistry.NewClient(20*time.Second, false) - } - imageStreamImportStorage := imagestreamimport.NewREST( - importerFn, - imageStreamRegistry, - internalImageStreamStorage, - imageStorage, - c.DeprecatedOpenshiftClient, - importTransport, - insecureImportTransport, - importerDockerClientFn, - c.AllowedRegistriesForImport, - c.RegistryHostnameRetriever, - c.DeprecatedOpenshiftClient.SubjectAccessReviews()) - imageStreamImageStorage := imagestreamimage.NewREST(imageRegistry, imageStreamRegistry) - authorizationClient, err := authorizationclient.NewForConfig(c.GenericConfig.LoopbackClientConfig) if err != nil { return nil, err @@ -176,44 +78,10 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string c.KubeInternalInformers.Rbac().InternalVersion().RoleBindings().Lister(), ) - clientStorage, err := clientetcd.NewREST(c.GenericConfig.RESTOptionsGetter) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - - // If OAuth is disabled, set the strategy to Deny - saAccountGrantMethod := oauthapi.GrantHandlerDeny - if len(c.ServiceAccountMethod) > 0 { - // Otherwise, take the value provided in master-config.yaml - saAccountGrantMethod = oauthapi.GrantHandlerType(c.ServiceAccountMethod) - } - - oauthClient, err := oauthclient.NewForConfig(c.GenericConfig.LoopbackClientConfig) - if err != nil { - return nil, err - } - combinedOAuthClientGetter := saoauth.NewServiceAccountOAuthClientGetter(c.KubeClientInternal.Core(), c.KubeClientInternal.Core(), c.DeprecatedOpenshiftClient, oauthClient.OAuthClients(), saAccountGrantMethod) - authorizeTokenStorage, err := authorizetokenetcd.NewREST(c.GenericConfig.RESTOptionsGetter, combinedOAuthClientGetter) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - accessTokenStorage, err := accesstokenetcd.NewREST(c.GenericConfig.RESTOptionsGetter, combinedOAuthClientGetter) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - clientAuthorizationStorage, err := clientauthetcd.NewREST(c.GenericConfig.RESTOptionsGetter, combinedOAuthClientGetter) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } - clusterResourceQuotaStorage, clusterResourceQuotaStatusStorage, err := clusterresourcequotaetcd.NewREST(c.GenericConfig.RESTOptionsGetter) if err != nil { return nil, fmt.Errorf("error building REST storage: %v", err) } - roleBindingRestrictionStorage, err := rolebindingrestrictionetcd.NewREST(c.GenericConfig.RESTOptionsGetter) - if err != nil { - return nil, fmt.Errorf("error building REST storage: %v", err) - } storage := map[schema.GroupVersion]map[string]rest.Storage{} @@ -227,29 +95,6 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string ), } - storage[oauthapiv1.SchemeGroupVersion] = map[string]rest.Storage{ - "oAuthAuthorizeTokens": authorizeTokenStorage, - "oAuthAccessTokens": accessTokenStorage, - "oAuthClients": clientStorage, - "oAuthClientAuthorizations": clientAuthorizationStorage, - } - - storage[authzapiv1.SchemeGroupVersion] = map[string]rest.Storage{ - "resourceAccessReviews": resourceAccessReviewStorage, - "subjectAccessReviews": subjectAccessReviewStorage, - "localSubjectAccessReviews": localSubjectAccessReviewStorage, - "localResourceAccessReviews": localResourceAccessReviewStorage, - "selfSubjectRulesReviews": selfSubjectRulesReviewStorage, - "subjectRulesReviews": subjectRulesReviewStorage, - - "roles": role.NewREST(c.KubeClientInternal.Rbac().RESTClient()), - "roleBindings": rolebinding.NewREST(c.KubeClientInternal.Rbac().RESTClient()), - "clusterRoles": clusterrole.NewREST(c.KubeClientInternal.Rbac().RESTClient()), - "clusterRoleBindings": clusterrolebinding.NewREST(c.KubeClientInternal.Rbac().RESTClient()), - - "roleBindingRestrictions": roleBindingRestrictionStorage, - } - storage[securityapiv1.SchemeGroupVersion] = map[string]rest.Storage{ "securityContextConstraints": sccStorage, "podSecurityPolicyReviews": podSecurityPolicyReviewStorage, @@ -262,18 +107,6 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string "projectRequests": projectRequestStorage, } - storage[imageapiv1.SchemeGroupVersion] = map[string]rest.Storage{ - "images": imageStorage, - "imagesignatures": imageSignatureStorage, - "imageStreams/secrets": imageStreamSecretsStorage, - "imageStreams": imageStreamStorage, - "imageStreams/status": imageStreamStatusStorage, - "imageStreamImports": imageStreamImportStorage, - "imageStreamImages": imageStreamImageStorage, - "imageStreamMappings": imageStreamMappingStorage, - "imageStreamTags": imageStreamTagStorage, - } - storage[routeapiv1.SchemeGroupVersion] = map[string]rest.Storage{ "routes": routeStorage, "routes/status": routeStatusStorage, diff --git a/pkg/generate/app/cmd/newapp.go b/pkg/generate/app/cmd/newapp.go index 59a56a21df0c..d874eaf26a48 100644 --- a/pkg/generate/app/cmd/newapp.go +++ b/pkg/generate/app/cmd/newapp.go @@ -30,13 +30,13 @@ import ( buildutil "github.com/openshift/origin/pkg/build/util" "github.com/openshift/origin/pkg/client" cmdutil "github.com/openshift/origin/pkg/cmd/util" - "github.com/openshift/origin/pkg/dockerregistry" "github.com/openshift/origin/pkg/generate" "github.com/openshift/origin/pkg/generate/app" "github.com/openshift/origin/pkg/generate/dockerfile" "github.com/openshift/origin/pkg/generate/jenkinsfile" "github.com/openshift/origin/pkg/generate/source" imageapi "github.com/openshift/origin/pkg/image/apis/image" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" outil "github.com/openshift/origin/pkg/util" dockerfileutil "github.com/openshift/origin/pkg/util/docker/dockerfile" ) diff --git a/pkg/generate/app/dockerimagelookup.go b/pkg/generate/app/dockerimagelookup.go index ba6a073d3096..27242576de69 100644 --- a/pkg/generate/app/dockerimagelookup.go +++ b/pkg/generate/app/dockerimagelookup.go @@ -13,8 +13,8 @@ import ( kapi "k8s.io/kubernetes/pkg/api" "github.com/openshift/origin/pkg/client" - "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" ) // DockerClient is the local interface for the docker client diff --git a/pkg/image/apiserver/apiserver.go b/pkg/image/apiserver/apiserver.go new file mode 100644 index 000000000000..24816abfc069 --- /dev/null +++ b/pkg/image/apiserver/apiserver.go @@ -0,0 +1,193 @@ +package apiserver + +import ( + "fmt" + "sync" + "time" + + "k8s.io/apimachinery/pkg/apimachinery/registered" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/registry/rest" + genericapiserver "k8s.io/apiserver/pkg/server" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/util/flowcontrol" + authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion" + coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" + + osclient "github.com/openshift/origin/pkg/client" + configapi "github.com/openshift/origin/pkg/cmd/server/api" + imageadmission "github.com/openshift/origin/pkg/image/admission" + imageapi "github.com/openshift/origin/pkg/image/apis/image" + imageapiv1 "github.com/openshift/origin/pkg/image/apis/image/v1" + "github.com/openshift/origin/pkg/image/importer" + imageimporter "github.com/openshift/origin/pkg/image/importer" + "github.com/openshift/origin/pkg/image/importer/dockerv1client" + "github.com/openshift/origin/pkg/image/registry/image" + imageetcd "github.com/openshift/origin/pkg/image/registry/image/etcd" + "github.com/openshift/origin/pkg/image/registry/imagesecret" + "github.com/openshift/origin/pkg/image/registry/imagesignature" + "github.com/openshift/origin/pkg/image/registry/imagestream" + imagestreametcd "github.com/openshift/origin/pkg/image/registry/imagestream/etcd" + "github.com/openshift/origin/pkg/image/registry/imagestreamimage" + "github.com/openshift/origin/pkg/image/registry/imagestreamimport" + "github.com/openshift/origin/pkg/image/registry/imagestreammapping" + "github.com/openshift/origin/pkg/image/registry/imagestreamtag" +) + +type ImageAPIServerConfig struct { + GenericConfig *genericapiserver.Config + + CoreAPIServerClientConfig *restclient.Config + LimitVerifier imageadmission.LimitVerifier + RegistryHostnameRetriever imageapi.RegistryHostnameRetriever + AllowedRegistriesForImport *configapi.AllowedRegistries + MaxImagesBulkImportedPerRepository int + + // TODO these should all become local eventually + Scheme *runtime.Scheme + Registry *registered.APIRegistrationManager + Codecs serializer.CodecFactory + + makeV1Storage sync.Once + v1Storage map[string]rest.Storage + v1StorageErr error +} + +type ImageAPIServer struct { + GenericAPIServer *genericapiserver.GenericAPIServer +} + +type completedConfig struct { + *ImageAPIServerConfig +} + +// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. +func (c *ImageAPIServerConfig) Complete() completedConfig { + c.GenericConfig.Complete() + + return completedConfig{c} +} + +// SkipComplete provides a way to construct a server instance without config completion. +func (c *ImageAPIServerConfig) SkipComplete() completedConfig { + return completedConfig{c} +} + +// New returns a new instance of ImageAPIServer from the given config. +func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*ImageAPIServer, error) { + genericServer, err := c.ImageAPIServerConfig.GenericConfig.SkipComplete().New("image.openshift.io-apiserver", delegationTarget) // completion is done in Complete, no need for a second time + if err != nil { + return nil, err + } + + s := &ImageAPIServer{ + GenericAPIServer: genericServer, + } + + v1Storage, err := c.V1RESTStorage() + if err != nil { + return nil, err + } + + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(imageapiv1.GroupName, c.Registry, c.Scheme, metav1.ParameterCodec, c.Codecs) + apiGroupInfo.GroupMeta.GroupVersion = imageapiv1.SchemeGroupVersion + apiGroupInfo.VersionedResourcesStorageMap[imageapiv1.SchemeGroupVersion.Version] = v1Storage + if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { + return nil, err + } + + return s, nil +} + +func (c *ImageAPIServerConfig) V1RESTStorage() (map[string]rest.Storage, error) { + c.makeV1Storage.Do(func() { + c.v1Storage, c.v1StorageErr = c.newV1RESTStorage() + }) + + return c.v1Storage, c.v1StorageErr +} + +func (c *ImageAPIServerConfig) newV1RESTStorage() (map[string]rest.Storage, error) { + // TODO: allow the system CAs and the local CAs to be joined together. + importTransport, err := restclient.TransportFor(&restclient.Config{}) + if err != nil { + return nil, fmt.Errorf("unable to configure a default transport for importing: %v", err) + } + insecureImportTransport, err := restclient.TransportFor(&restclient.Config{ + TLSClientConfig: restclient.TLSClientConfig{ + Insecure: true, + }, + }) + if err != nil { + return nil, fmt.Errorf("unable to configure a default transport for importing: %v", err) + } + + deprecatedOpenshiftClientForImages, err := osclient.New(c.GenericConfig.LoopbackClientConfig) + if err != nil { + return nil, err + } + deprecatedOpenshiftClient, err := osclient.New(c.CoreAPIServerClientConfig) + if err != nil { + return nil, err + } + coreClient, err := coreclient.NewForConfig(c.CoreAPIServerClientConfig) + if err != nil { + return nil, err + } + authorizationClient, err := authorizationclient.NewForConfig(c.GenericConfig.LoopbackClientConfig) + if err != nil { + return nil, err + } + + imageStorage, err := imageetcd.NewREST(c.GenericConfig.RESTOptionsGetter) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + imageRegistry := image.NewRegistry(imageStorage) + imageSignatureStorage := imagesignature.NewREST(deprecatedOpenshiftClientForImages.Images()) + imageStreamSecretsStorage := imagesecret.NewREST(coreClient) + imageStreamStorage, imageStreamStatusStorage, internalImageStreamStorage, err := imagestreametcd.NewREST(c.GenericConfig.RESTOptionsGetter, c.RegistryHostnameRetriever, authorizationClient.SubjectAccessReviews(), c.LimitVerifier) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + imageStreamRegistry := imagestream.NewRegistry(imageStreamStorage, imageStreamStatusStorage, internalImageStreamStorage) + imageStreamMappingStorage := imagestreammapping.NewREST(imageRegistry, imageStreamRegistry, c.RegistryHostnameRetriever) + imageStreamTagStorage := imagestreamtag.NewREST(imageRegistry, imageStreamRegistry) + importerCache, err := imageimporter.NewImageStreamLayerCache(imageimporter.DefaultImageStreamLayerCacheSize) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + importerFn := func(r importer.RepositoryRetriever) imageimporter.Interface { + return imageimporter.NewImageStreamImporter(r, c.MaxImagesBulkImportedPerRepository, flowcontrol.NewTokenBucketRateLimiter(2.0, 3), &importerCache) + } + importerDockerClientFn := func() dockerv1client.Client { + return dockerv1client.NewClient(20*time.Second, false) + } + imageStreamImportStorage := imagestreamimport.NewREST( + importerFn, + imageStreamRegistry, + internalImageStreamStorage, + imageStorage, + deprecatedOpenshiftClientForImages, + importTransport, + insecureImportTransport, + importerDockerClientFn, + c.AllowedRegistriesForImport, + c.RegistryHostnameRetriever, + deprecatedOpenshiftClient.SubjectAccessReviews()) + imageStreamImageStorage := imagestreamimage.NewREST(imageRegistry, imageStreamRegistry) + + v1Storage := map[string]rest.Storage{} + v1Storage["images"] = imageStorage + v1Storage["imagesignatures"] = imageSignatureStorage + v1Storage["imageStreams/secrets"] = imageStreamSecretsStorage + v1Storage["imageStreams"] = imageStreamStorage + v1Storage["imageStreams/status"] = imageStreamStatusStorage + v1Storage["imageStreamImports"] = imageStreamImportStorage + v1Storage["imageStreamImages"] = imageStreamImageStorage + v1Storage["imageStreamMappings"] = imageStreamMappingStorage + v1Storage["imageStreamTags"] = imageStreamTagStorage + return v1Storage, nil +} diff --git a/pkg/image/importer/client.go b/pkg/image/importer/client.go index bdbe2343c284..8e30d0c4c0a8 100644 --- a/pkg/image/importer/client.go +++ b/pkg/image/importer/client.go @@ -27,9 +27,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kapi "k8s.io/kubernetes/pkg/api" - "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/apis/image/dockerpre012" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" ) // ErrNotV2Registry is returned when the server does not report itself as a V2 Docker registry diff --git a/pkg/image/importer/client_test.go b/pkg/image/importer/client_test.go index 77f1ae5b1bd1..df4ca45ca003 100644 --- a/pkg/image/importer/client_test.go +++ b/pkg/image/importer/client_test.go @@ -21,8 +21,8 @@ import ( kapi "k8s.io/kubernetes/pkg/api" - "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" ) type mockRetriever struct { diff --git a/pkg/dockerregistry/client.go b/pkg/image/importer/dockerv1client/client.go similarity index 99% rename from pkg/dockerregistry/client.go rename to pkg/image/importer/dockerv1client/client.go index 3e6e18384a61..f456c6caf913 100644 --- a/pkg/dockerregistry/client.go +++ b/pkg/image/importer/dockerv1client/client.go @@ -1,4 +1,4 @@ -package dockerregistry +package dockerv1client import ( "crypto/tls" diff --git a/pkg/dockerregistry/client_test.go b/pkg/image/importer/dockerv1client/client_test.go similarity index 86% rename from pkg/dockerregistry/client_test.go rename to pkg/image/importer/dockerv1client/client_test.go index 0f2e02e8482d..7203b3b6b216 100644 --- a/pkg/dockerregistry/client_test.go +++ b/pkg/image/importer/dockerv1client/client_test.go @@ -1,4 +1,4 @@ -package dockerregistry +package dockerv1client import ( "fmt" @@ -9,8 +9,6 @@ import ( "strings" "testing" "time" - - "github.com/openshift/origin/pkg/dockerregistry/testutil" ) // tests of running registries are done in the integration client test @@ -329,12 +327,12 @@ func TestImageManifest(t *testing.T) { w.Write([]byte(`{}`)) case "/v2/test/image/manifests/latest", "/v2/test/image/manifests/" + manifestDigest: if r.Method == "HEAD" { - w.Header().Set("Content-Length", fmt.Sprintf("%d", len(testutil.SampleImageManifestSchema1))) + w.Header().Set("Content-Length", fmt.Sprintf("%d", len(SampleImageManifestSchema1))) w.Header().Set("Docker-Content-Digest", manifestDigest) w.WriteHeader(http.StatusOK) return } - w.Write([]byte(testutil.SampleImageManifestSchema1)) + w.Write([]byte(SampleImageManifestSchema1)) default: t.Fatalf("unexpected request: %s %s", r.Method, r.URL.RequestURI()) return @@ -353,10 +351,49 @@ func TestImageManifest(t *testing.T) { t.Errorf("empty manifest") } - if string(manifest) != testutil.SampleImageManifestSchema1 { + if string(manifest) != SampleImageManifestSchema1 { t.Errorf("unexpected manifest: %#v", manifest) } <-called <-called } + +const SampleImageManifestSchema1 = `{ + "schemaVersion": 1, + "name": "nm/is", + "tag": "latest", + "architecture": "", + "fsLayers": [ + { + "blobSum": "sha256:b2c5513bd934a7efb412c0dd965600b8cb00575b585eaff1cb980b69037fe6cd" + }, + { + "blobSum": "sha256:2dde6f11a89463bf20dba3b47d8b3b6de7cdcc19e50634e95a18dd95c278768d" + } + ], + "history": [ + { + "v1Compatibility": "{\"size\":18407936}" + }, + { + "v1Compatibility": "{\"size\":19387392}" + } + ], + "signatures": [ + { + "header": { + "jwk": { + "crv": "P-256", + "kid": "5HTY:A24B:L6PG:TQ3G:GMAK:QGKZ:ICD4:S7ZJ:P5JX:UTMP:XZLK:ZXVH", + "kty": "EC", + "x": "j5YnDSyrVIt3NquUKvcZIpbfeD8HLZ7BVBFL4WutRBM", + "y": "PBgFAZ3nNakYN3H9enhrdUrQ_HPYzb8oX5rtJxJo1Y8" + }, + "alg": "ES256" + }, + "signature": "1rXiEmWnf9eL7m7Wy3K4l25-Zv2XXl5GgqhM_yjT0ujPmTn0uwfHcCWlweHa9gput3sECj507eQyGpBOF5rD6Q", + "protected": "eyJmb3JtYXRMZW5ndGgiOjQ4NSwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE2LTA3LTI2VDExOjQ2OjQ2WiJ9" + } + ] +}` diff --git a/pkg/image/importer/importer.go b/pkg/image/importer/importer.go index 4aaa0e2d901f..e51b1924c6b6 100644 --- a/pkg/image/importer/importer.go +++ b/pkg/image/importer/importer.go @@ -22,8 +22,8 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/client-go/util/flowcontrol" - "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" + "github.com/openshift/origin/pkg/image/importer/dockerv1client" ) // Add a dockerregistry.Client to the passed context with this key to support v1 Docker registry importing @@ -577,7 +577,7 @@ func importRepositoryFromDockerV1(ctx gocontext.Context, repository *importRepos applyErrorToRepository(repository, err) return } - client, ok := value.(dockerregistry.Client) + client, ok := value.(dockerv1client.Client) if !ok { err := kapierrors.NewForbidden(imageapi.Resource(""), "", fmt.Errorf("registry %q does not support the v2 Registry API", repository.Registry.Host)) err.ErrStatus.Reason = "NotV2Registry" diff --git a/pkg/image/registry/imagestream/etcd/etcd.go b/pkg/image/registry/imagestream/etcd/etcd.go index 3e855db04ae5..574b6d1e7588 100644 --- a/pkg/image/registry/imagestream/etcd/etcd.go +++ b/pkg/image/registry/imagestream/etcd/etcd.go @@ -8,8 +8,8 @@ import ( "k8s.io/apiserver/pkg/registry/generic/registry" "k8s.io/apiserver/pkg/registry/rest" kapi "k8s.io/kubernetes/pkg/api" + authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" imageadmission "github.com/openshift/origin/pkg/image/admission" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/registry/imagestream" @@ -19,13 +19,12 @@ import ( // REST implements a RESTStorage for image streams against etcd. type REST struct { *registry.Store - subjectAccessReviewRegistry subjectaccessreview.Registry } var _ rest.StandardStorage = &REST{} // NewREST returns a new REST. -func NewREST(optsGetter restoptions.Getter, registryHostname imageapi.RegistryHostnameRetriever, subjectAccessReviewRegistry subjectaccessreview.Registry, limitVerifier imageadmission.LimitVerifier) (*REST, *StatusREST, *InternalREST, error) { +func NewREST(optsGetter restoptions.Getter, registryHostname imageapi.RegistryHostnameRetriever, subjectAccessReviewRegistry authorizationclient.SubjectAccessReviewInterface, limitVerifier imageadmission.LimitVerifier) (*REST, *StatusREST, *InternalREST, error) { store := registry.Store{ Copier: kapi.Scheme, NewFunc: func() runtime.Object { return &imageapi.ImageStream{} }, @@ -36,7 +35,6 @@ func NewREST(optsGetter restoptions.Getter, registryHostname imageapi.RegistryHo rest := &REST{ Store: &store, - subjectAccessReviewRegistry: subjectAccessReviewRegistry, } // strategy must be able to load image streams across namespaces during tag verification strategy := imagestream.NewStrategy(registryHostname, subjectAccessReviewRegistry, limitVerifier, rest) diff --git a/pkg/image/registry/imagestream/etcd/etcd_test.go b/pkg/image/registry/imagestream/etcd/etcd_test.go index 1e54811afe1b..540316c15c8d 100644 --- a/pkg/image/registry/imagestream/etcd/etcd_test.go +++ b/pkg/image/registry/imagestream/etcd/etcd_test.go @@ -9,11 +9,10 @@ import ( apirequest "k8s.io/apiserver/pkg/endpoints/request" etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" kapihelper "k8s.io/kubernetes/pkg/api/helper" + authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" "k8s.io/kubernetes/pkg/registry/registrytest" "github.com/openshift/origin/pkg/api/latest" - authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" "github.com/openshift/origin/pkg/image/admission/testutil" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/util/restoptions" @@ -38,12 +37,14 @@ type fakeSubjectAccessReviewRegistry struct { requestNamespace string } -var _ subjectaccessreview.Registry = &fakeSubjectAccessReviewRegistry{} - -func (f *fakeSubjectAccessReviewRegistry) CreateSubjectAccessReview(ctx apirequest.Context, subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReviewResponse, error) { +func (f *fakeSubjectAccessReviewRegistry) Create(subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReview, error) { f.request = subjectAccessReview - f.requestNamespace = apirequest.NamespaceValue(ctx) - return &authorizationapi.SubjectAccessReviewResponse{Allowed: f.allow}, f.err + f.requestNamespace = subjectAccessReview.Spec.ResourceAttributes.Namespace + return &authorizationapi.SubjectAccessReview{ + Status: authorizationapi.SubjectAccessReviewStatus{ + Allowed: f.allow, + }, + }, f.err } func newStorage(t *testing.T) (*REST, *StatusREST, *InternalREST, *etcdtesting.EtcdTestServer) { diff --git a/pkg/image/registry/imagestream/strategy.go b/pkg/image/registry/imagestream/strategy.go index 6aefb1ebe362..5771a724995c 100644 --- a/pkg/image/registry/imagestream/strategy.go +++ b/pkg/image/registry/imagestream/strategy.go @@ -18,9 +18,10 @@ import ( "k8s.io/apiserver/pkg/storage/names" kapi "k8s.io/kubernetes/pkg/api" kapihelper "k8s.io/kubernetes/pkg/api/helper" + authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" + authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion" - authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" + authorizationutil "github.com/openshift/origin/pkg/authorization/util" imageadmission "github.com/openshift/origin/pkg/image/admission" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/apis/image/validation" @@ -42,7 +43,7 @@ type Strategy struct { // NewStrategy is the default logic that applies when creating and updating // ImageStream objects via the REST API. -func NewStrategy(registryHostname imageapi.RegistryHostnameRetriever, subjectAccessReviewClient subjectaccessreview.Registry, limitVerifier imageadmission.LimitVerifier, imageStreamGetter ResourceGetter) Strategy { +func NewStrategy(registryHostname imageapi.RegistryHostnameRetriever, subjectAccessReviewClient authorizationclient.SubjectAccessReviewInterface, limitVerifier imageadmission.LimitVerifier, imageStreamGetter ResourceGetter) Strategy { return Strategy{ ObjectTyper: kapi.Scheme, NameGenerator: names.SimpleNameGenerator, @@ -431,7 +432,7 @@ func updateObservedGenerationForStatusUpdate(stream, oldStream *imageapi.ImageSt } type TagVerifier struct { - subjectAccessReviewClient subjectaccessreview.Registry + subjectAccessReviewClient authorizationclient.SubjectAccessReviewInterface } func (v *TagVerifier) Verify(old, stream *imageapi.ImageStream, user user.Info) field.ErrorList { @@ -462,21 +463,24 @@ func (v *TagVerifier) Verify(old, stream *imageapi.ImageStream, user user.Info) } // Make sure this user can pull the specified image before allowing them to tag it into another imagestream - subjectAccessReview := authorizationapi.AddUserToSAR(user, &authorizationapi.SubjectAccessReview{ - Action: authorizationapi.Action{ - Verb: "get", - Group: imageapi.LegacyGroupName, - Resource: "imagestreams/layers", - ResourceName: streamName, + subjectAccessReview := authorizationutil.AddUserToSAR(user, &authorizationapi.SubjectAccessReview{ + Spec: authorizationapi.SubjectAccessReviewSpec{ + ResourceAttributes: &authorizationapi.ResourceAttributes{ + Namespace: tagRef.From.Namespace, + Verb: "get", + Group: imageapi.GroupName, + Resource: "imagestreams", + Subresource: "layers", + Name: streamName, + }, }, }) - ctx := apirequest.WithNamespace(apirequest.WithUser(apirequest.NewContext(), user), tagRef.From.Namespace) glog.V(4).Infof("Performing SubjectAccessReview for user=%s, groups=%v to %s/%s", user.GetName(), user.GetGroups(), tagRef.From.Namespace, streamName) - resp, err := v.subjectAccessReviewClient.CreateSubjectAccessReview(ctx, subjectAccessReview) - if err != nil || resp == nil || (resp != nil && !resp.Allowed) { + resp, err := v.subjectAccessReviewClient.Create(subjectAccessReview) + if err != nil || resp == nil || (resp != nil && !resp.Status.Allowed) { message := fmt.Sprintf("%s/%s", tagRef.From.Namespace, streamName) if resp != nil { - message = message + fmt.Sprintf(": %q %q", resp.Reason, resp.EvaluationError) + message = message + fmt.Sprintf(": %q %q", resp.Status.Reason, resp.Status.EvaluationError) } if err != nil { message = message + fmt.Sprintf("- %v", err) diff --git a/pkg/image/registry/imagestream/strategy_test.go b/pkg/image/registry/imagestream/strategy_test.go index 3d1fc29b5b59..2ae9953edc6e 100644 --- a/pkg/image/registry/imagestream/strategy_test.go +++ b/pkg/image/registry/imagestream/strategy_test.go @@ -13,15 +13,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/diff" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/authentication/user" apirequest "k8s.io/apiserver/pkg/endpoints/request" kapi "k8s.io/kubernetes/pkg/api" + authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" kquota "k8s.io/kubernetes/pkg/quota" - authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" + oauthorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" "github.com/openshift/origin/pkg/image/admission" "github.com/openshift/origin/pkg/image/admission/testutil" imageapi "github.com/openshift/origin/pkg/image/apis/image" @@ -46,7 +45,7 @@ func (u *fakeUser) GetGroups() []string { func (u *fakeUser) GetExtra() map[string][]string { return map[string][]string{ - authorizationapi.ScopesKey: {"a", "b"}, + oauthorizationapi.ScopesKey: {"a", "b"}, } } @@ -65,12 +64,14 @@ type fakeSubjectAccessReviewRegistry struct { requestNamespace string } -var _ subjectaccessreview.Registry = &fakeSubjectAccessReviewRegistry{} - -func (f *fakeSubjectAccessReviewRegistry) CreateSubjectAccessReview(ctx apirequest.Context, subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReviewResponse, error) { +func (f *fakeSubjectAccessReviewRegistry) Create(subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReview, error) { f.request = subjectAccessReview - f.requestNamespace = apirequest.NamespaceValue(ctx) - return &authorizationapi.SubjectAccessReviewResponse{Allowed: f.allow}, f.err + f.requestNamespace = subjectAccessReview.Spec.ResourceAttributes.Namespace + return &authorizationapi.SubjectAccessReview{ + Status: authorizationapi.SubjectAccessReviewStatus{ + Allowed: f.allow, + }, + }, f.err } func TestPublicDockerImageRepository(t *testing.T) { @@ -355,15 +356,19 @@ func TestTagVerifier(t *testing.T) { t.Errorf("%s: sar namespace: expected %v, got %v", name, e, a) } expectedSar := &authorizationapi.SubjectAccessReview{ - Action: authorizationapi.Action{ - // Group: "image.openshift.io", - Verb: "get", - Resource: "imagestreams/layers", - ResourceName: "otherstream", - }, - User: "user", - Groups: sets.NewString("group1"), - Scopes: []string{"a", "b"}, + Spec: authorizationapi.SubjectAccessReviewSpec{ + ResourceAttributes: &authorizationapi.ResourceAttributes{ + Namespace: "otherns", + Verb: "get", + Group: "image.openshift.io", + Resource: "imagestreams", + Subresource: "layers", + Name: "otherstream", + }, + User: "user", + Groups: []string{"group1"}, + Extra: map[string]authorizationapi.ExtraValue{oauthorizationapi.ScopesKey: {"a", "b"}}, + }, } if e, a := expectedSar, sar.request; !reflect.DeepEqual(e, a) { t.Errorf("%s: unexpected SAR request: %s", name, diff.ObjectDiff(e, a)) diff --git a/pkg/image/registry/imagestreamimage/rest_test.go b/pkg/image/registry/imagestreamimage/rest_test.go index 4b5b3de8b708..affb4a4874c9 100644 --- a/pkg/image/registry/imagestreamimage/rest_test.go +++ b/pkg/image/registry/imagestreamimage/rest_test.go @@ -13,10 +13,9 @@ import ( etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" + authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" "k8s.io/kubernetes/pkg/registry/registrytest" - authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" "github.com/openshift/origin/pkg/image/admission/testutil" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/registry/image" @@ -33,9 +32,7 @@ var testDefaultRegistry = func() (string, bool) { return "defaultregistry:5000", type fakeSubjectAccessReviewRegistry struct { } -var _ subjectaccessreview.Registry = &fakeSubjectAccessReviewRegistry{} - -func (f *fakeSubjectAccessReviewRegistry) CreateSubjectAccessReview(ctx apirequest.Context, subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReviewResponse, error) { +func (f *fakeSubjectAccessReviewRegistry) Create(subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReview, error) { return nil, nil } diff --git a/pkg/image/registry/imagestreamimport/rest.go b/pkg/image/registry/imagestreamimport/rest.go index bf090e76d8bb..44cdb803d63d 100644 --- a/pkg/image/registry/imagestreamimport/rest.go +++ b/pkg/image/registry/imagestreamimport/rest.go @@ -22,10 +22,10 @@ import ( authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" "github.com/openshift/origin/pkg/client" serverapi "github.com/openshift/origin/pkg/cmd/server/api" - "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" imageapiv1 "github.com/openshift/origin/pkg/image/apis/image/v1" "github.com/openshift/origin/pkg/image/importer" + "github.com/openshift/origin/pkg/image/importer/dockerv1client" "github.com/openshift/origin/pkg/image/registry/imagestream" quotautil "github.com/openshift/origin/pkg/quota/util" ) @@ -35,7 +35,7 @@ type ImporterFunc func(r importer.RepositoryRetriever) importer.Interface // ImporterDockerRegistryFunc returns an instance of a docker client that should be used per invocation of import, // may be nil if no legacy import capability is required. -type ImporterDockerRegistryFunc func() dockerregistry.Client +type ImporterDockerRegistryFunc func() dockerv1client.Client // REST implements the RESTStorage interface for ImageStreamImport type REST struct { diff --git a/pkg/image/registry/imagestreammapping/rest_test.go b/pkg/image/registry/imagestreammapping/rest_test.go index 8302bee297dc..04b982f5f7a6 100644 --- a/pkg/image/registry/imagestreammapping/rest_test.go +++ b/pkg/image/registry/imagestreammapping/rest_test.go @@ -21,10 +21,9 @@ import ( etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" + authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" "k8s.io/kubernetes/pkg/registry/registrytest" - authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" "github.com/openshift/origin/pkg/image/admission/testutil" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/registry/image" @@ -43,9 +42,7 @@ var testDefaultRegistry = func() (string, bool) { return testDefaultRegistryURL, type fakeSubjectAccessReviewRegistry struct { } -var _ subjectaccessreview.Registry = &fakeSubjectAccessReviewRegistry{} - -func (f *fakeSubjectAccessReviewRegistry) CreateSubjectAccessReview(ctx apirequest.Context, subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReviewResponse, error) { +func (f *fakeSubjectAccessReviewRegistry) Create(subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReview, error) { return nil, nil } diff --git a/pkg/image/registry/imagestreamtag/rest_test.go b/pkg/image/registry/imagestreamtag/rest_test.go index 66fe22733abc..1e31de047499 100644 --- a/pkg/image/registry/imagestreamtag/rest_test.go +++ b/pkg/image/registry/imagestreamtag/rest_test.go @@ -17,10 +17,9 @@ import ( etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" + authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" "k8s.io/kubernetes/pkg/registry/registrytest" - authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization" - "github.com/openshift/origin/pkg/authorization/registry/subjectaccessreview" "github.com/openshift/origin/pkg/image/admission/testutil" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/registry/image" @@ -37,9 +36,7 @@ var testDefaultRegistry = func() (string, bool) { return "defaultregistry:5000", type fakeSubjectAccessReviewRegistry struct { } -var _ subjectaccessreview.Registry = &fakeSubjectAccessReviewRegistry{} - -func (f *fakeSubjectAccessReviewRegistry) CreateSubjectAccessReview(ctx apirequest.Context, subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReviewResponse, error) { +func (f *fakeSubjectAccessReviewRegistry) Create(subjectAccessReview *authorizationapi.SubjectAccessReview) (*authorizationapi.SubjectAccessReview, error) { return nil, nil } diff --git a/pkg/oauth/apiserver/apiserver.go b/pkg/oauth/apiserver/apiserver.go new file mode 100644 index 000000000000..70d1c5829f7e --- /dev/null +++ b/pkg/oauth/apiserver/apiserver.go @@ -0,0 +1,145 @@ +package apiserver + +import ( + "fmt" + "sync" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/registry/rest" + genericapiserver "k8s.io/apiserver/pkg/server" + restclient "k8s.io/client-go/rest" + coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" + + osclient "github.com/openshift/origin/pkg/client" + configapi "github.com/openshift/origin/pkg/cmd/server/api" + oauthapi "github.com/openshift/origin/pkg/oauth/apis/oauth" + oauthapiv1 "github.com/openshift/origin/pkg/oauth/apis/oauth/v1" + oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion" + accesstokenetcd "github.com/openshift/origin/pkg/oauth/registry/oauthaccesstoken/etcd" + authorizetokenetcd "github.com/openshift/origin/pkg/oauth/registry/oauthauthorizetoken/etcd" + clientetcd "github.com/openshift/origin/pkg/oauth/registry/oauthclient/etcd" + clientauthetcd "github.com/openshift/origin/pkg/oauth/registry/oauthclientauthorization/etcd" + saoauth "github.com/openshift/origin/pkg/serviceaccounts/oauthclient" + "k8s.io/apimachinery/pkg/apimachinery/registered" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type OAuthAPIServerConfig struct { + GenericConfig *genericapiserver.Config + + CoreAPIServerClientConfig *restclient.Config + ServiceAccountMethod configapi.GrantHandlerType + + // TODO these should all become local eventually + Scheme *runtime.Scheme + Registry *registered.APIRegistrationManager + Codecs serializer.CodecFactory + + makeV1Storage sync.Once + v1Storage map[string]rest.Storage + v1StorageErr error +} + +type OAuthAPIServer struct { + GenericAPIServer *genericapiserver.GenericAPIServer +} + +type completedConfig struct { + *OAuthAPIServerConfig +} + +// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. +func (c *OAuthAPIServerConfig) Complete() completedConfig { + c.GenericConfig.Complete() + + return completedConfig{c} +} + +// SkipComplete provides a way to construct a server instance without config completion. +func (c *OAuthAPIServerConfig) SkipComplete() completedConfig { + return completedConfig{c} +} + +// New returns a new instance of OAuthAPIServer from the given config. +func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*OAuthAPIServer, error) { + genericServer, err := c.OAuthAPIServerConfig.GenericConfig.SkipComplete().New("oauth.openshift.io-apiserver", delegationTarget) // completion is done in Complete, no need for a second time + if err != nil { + return nil, err + } + + s := &OAuthAPIServer{ + GenericAPIServer: genericServer, + } + + v1Storage, err := c.V1RESTStorage() + if err != nil { + return nil, err + } + + apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(oauthapiv1.GroupName, c.Registry, c.Scheme, metav1.ParameterCodec, c.Codecs) + apiGroupInfo.GroupMeta.GroupVersion = oauthapiv1.SchemeGroupVersion + apiGroupInfo.VersionedResourcesStorageMap[oauthapiv1.SchemeGroupVersion.Version] = v1Storage + if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { + return nil, err + } + + return s, nil +} + +func (c *OAuthAPIServerConfig) V1RESTStorage() (map[string]rest.Storage, error) { + c.makeV1Storage.Do(func() { + c.v1Storage, c.v1StorageErr = c.newV1RESTStorage() + }) + + return c.v1Storage, c.v1StorageErr +} + +func (c *OAuthAPIServerConfig) newV1RESTStorage() (map[string]rest.Storage, error) { + + clientStorage, err := clientetcd.NewREST(c.GenericConfig.RESTOptionsGetter) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + + // If OAuth is disabled, set the strategy to Deny + saAccountGrantMethod := oauthapi.GrantHandlerDeny + if len(c.ServiceAccountMethod) > 0 { + // Otherwise, take the value provided in master-config.yaml + saAccountGrantMethod = oauthapi.GrantHandlerType(c.ServiceAccountMethod) + } + + oauthClient, err := oauthclient.NewForConfig(c.GenericConfig.LoopbackClientConfig) + if err != nil { + return nil, err + } + coreClient, err := coreclient.NewForConfig(c.CoreAPIServerClientConfig) + if err != nil { + return nil, err + } + deprecatedClient, err := osclient.New(c.CoreAPIServerClientConfig) + if err != nil { + return nil, err + } + + combinedOAuthClientGetter := saoauth.NewServiceAccountOAuthClientGetter(coreClient, coreClient, deprecatedClient, oauthClient.OAuthClients(), saAccountGrantMethod) + authorizeTokenStorage, err := authorizetokenetcd.NewREST(c.GenericConfig.RESTOptionsGetter, combinedOAuthClientGetter) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + accessTokenStorage, err := accesstokenetcd.NewREST(c.GenericConfig.RESTOptionsGetter, combinedOAuthClientGetter) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + clientAuthorizationStorage, err := clientauthetcd.NewREST(c.GenericConfig.RESTOptionsGetter, combinedOAuthClientGetter) + if err != nil { + return nil, fmt.Errorf("error building REST storage: %v", err) + } + + v1Storage := map[string]rest.Storage{} + v1Storage["oAuthAuthorizeTokens"] = authorizeTokenStorage + v1Storage["oAuthAccessTokens"] = accessTokenStorage + v1Storage["oAuthClients"] = clientStorage + v1Storage["oAuthClientAuthorizations"] = clientAuthorizationStorage + return v1Storage, nil +} diff --git a/test/extended/registry/registry.go b/test/extended/registry/registry.go index c892dcf239f3..97c70c6fbb34 100644 --- a/test/extended/registry/registry.go +++ b/test/extended/registry/registry.go @@ -11,8 +11,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - regclient "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" + regclient "github.com/openshift/origin/pkg/image/importer/dockerv1client" imagesutil "github.com/openshift/origin/test/extended/images" registryutil "github.com/openshift/origin/test/extended/registry/util" exutil "github.com/openshift/origin/test/extended/util" diff --git a/test/integration/dockerregistryclient_test.go b/test/integration/dockerregistryclient_test.go index 096385bde56f..fe31eb01ef40 100644 --- a/test/integration/dockerregistryclient_test.go +++ b/test/integration/dockerregistryclient_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/openshift/origin/pkg/dockerregistry" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" ) const ( diff --git a/test/integration/imageimporter_test.go b/test/integration/imageimporter_test.go index 5ff5008ed9f4..132cdf6d47a1 100644 --- a/test/integration/imageimporter_test.go +++ b/test/integration/imageimporter_test.go @@ -22,9 +22,9 @@ import ( kapi "k8s.io/kubernetes/pkg/api" "github.com/openshift/origin/pkg/client" - "github.com/openshift/origin/pkg/dockerregistry" imageapi "github.com/openshift/origin/pkg/image/apis/image" "github.com/openshift/origin/pkg/image/importer" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" testutil "github.com/openshift/origin/test/util" testserver "github.com/openshift/origin/test/util/server" diff --git a/test/integration/newapp_test.go b/test/integration/newapp_test.go index 073c4f27a420..3b66902cad65 100644 --- a/test/integration/newapp_test.go +++ b/test/integration/newapp_test.go @@ -33,7 +33,6 @@ import ( buildapi "github.com/openshift/origin/pkg/build/apis/build" client "github.com/openshift/origin/pkg/client/testclient" deployapi "github.com/openshift/origin/pkg/deploy/apis/apps" - "github.com/openshift/origin/pkg/dockerregistry" "github.com/openshift/origin/pkg/generate" "github.com/openshift/origin/pkg/generate/app" "github.com/openshift/origin/pkg/generate/app/cmd" @@ -43,6 +42,7 @@ import ( "github.com/openshift/origin/pkg/generate/jenkinsfile" "github.com/openshift/origin/pkg/generate/source" imageapi "github.com/openshift/origin/pkg/image/apis/image" + dockerregistry "github.com/openshift/origin/pkg/image/importer/dockerv1client" clicmd "github.com/openshift/origin/pkg/oc/cli/cmd" templateapi "github.com/openshift/origin/pkg/template/apis/template"