Skip to content

Commit

Permalink
registry: report publicDockerImageRepository to image stream if confi…
Browse files Browse the repository at this point in the history
…gured
  • Loading branch information
mfojtik committed Aug 18, 2017
1 parent e3585cc commit d3fe3c1
Show file tree
Hide file tree
Showing 23 changed files with 190 additions and 75 deletions.
4 changes: 2 additions & 2 deletions pkg/cmd/server/admission/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type PluginInitializer struct {
Informers kinternalinformers.SharedInformerFactory
ClusterResourceQuotaInformer quotainformer.ClusterResourceQuotaInformer
ClusterQuotaMapper clusterquotamapping.ClusterQuotaMapper
DefaultRegistryFn imageapi.DefaultRegistryFunc
RegistryHostnameRetriever imageapi.RegistryHostnameRetriever
SecurityInformers securityinformer.SharedInformerFactory
UserInformers userinformer.SharedInformerFactory
}
Expand Down Expand Up @@ -70,7 +70,7 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
wantsSecurityInformer.SetSecurityInformers(i.SecurityInformers)
}
if wantsDefaultRegistryFunc, ok := plugin.(WantsDefaultRegistryFunc); ok {
wantsDefaultRegistryFunc.SetDefaultRegistryFunc(i.DefaultRegistryFn)
wantsDefaultRegistryFunc.SetDefaultRegistryFunc(i.RegistryHostnameRetriever.InternalRegistryHostnameFn())
}
if wantsUserInformer, ok := plugin.(WantsUserInformer); ok {
wantsUserInformer.SetUserInformer(i.UserInformers)
Expand Down
3 changes: 1 addition & 2 deletions pkg/cmd/server/admission/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/openshift/origin/pkg/client"
configapi "github.com/openshift/origin/pkg/cmd/server/api"
imageapi "github.com/openshift/origin/pkg/image/apis/image"
"github.com/openshift/origin/pkg/project/cache"
"github.com/openshift/origin/pkg/quota/controller/clusterquotamapping"
quotainformer "github.com/openshift/origin/pkg/quota/generated/informers/internalversion/quota/internalversion"
Expand Down Expand Up @@ -79,7 +78,7 @@ type WantsSecurityInformer interface {
// WantsDefaultRegistryFunc should be implemented by admission plugins that need to know the default registry
// address.
type WantsDefaultRegistryFunc interface {
SetDefaultRegistryFunc(imageapi.DefaultRegistryFunc)
SetDefaultRegistryFunc(func() (string, bool))
admission.Validator
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/server/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,15 @@ type ImagePolicyConfig struct {
// this policy - typically only administrators or system integrations will have those
// permissions.
AllowedRegistriesForImport *AllowedRegistries
// InternalRegistryHostname sets the hostname for the default internal Docker
// Registry. This can be overriden by using OPENSHIFT_DEFAULT_REGISTRY
// environment variable.
InternalRegistryHostname string
// ExternalRegistryHostname sets the hostname for the default external Docker
// Registry. The external hostname should be set only when the registry is
// exposed externally. The value is used in 'publicDockerImageRepository'
// field in ImageStreams.
ExternalRegistryHostname string
}

// AllowedRegistries represents a list of registries allowed for the image import.
Expand Down
2 changes: 2 additions & 0 deletions pkg/cmd/server/api/v1/swagger_doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ var map_ImagePolicyConfig = map[string]string{
"scheduledImageImportMinimumIntervalSeconds": "ScheduledImageImportMinimumIntervalSeconds is the minimum number of seconds that can elapse between when image streams scheduled for background import are checked against the upstream repository. The default value is 15 minutes.",
"maxScheduledImageImportsPerMinute": "MaxScheduledImageImportsPerMinute is the maximum number of scheduled image streams that will be imported in the background per minute. The default value is 60. Set to -1 for unlimited.",
"allowedRegistriesForImport": "AllowedRegistriesForImport limits the docker registries that normal users may import images from. Set this list to the registries that you trust to contain valid Docker images and that you want applications to be able to import from. Users with permission to create Images or ImageStreamMappings via the API are not affected by this policy - typically only administrators or system integrations will have those permissions.",
"internalRegistryHostname": "InternalRegistryHostname sets the hostname for the default internal Docker Registry. This can be overriden by using OPENSHIFT_DEFAULT_REGISTRY environment variable.",
"externalRegistryHostname": "ExternalRegistryHostname sets the hostname for the default external Docker Registry. The external hostname should be set only when the registry is exposed externally. The value is used in 'publicDockerImageRepository' field in ImageStreams.",
}

func (ImagePolicyConfig) SwaggerDoc() map[string]string {
Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/server/api/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,15 @@ type ImagePolicyConfig struct {
// this policy - typically only administrators or system integrations will have those
// permissions.
AllowedRegistriesForImport *AllowedRegistries `json:"allowedRegistriesForImport,omitempty"`
// InternalRegistryHostname sets the hostname for the default internal Docker
// Registry. This can be overriden by using OPENSHIFT_DEFAULT_REGISTRY
// environment variable.
InternalRegistryHostname string `json:"internalRegistryHostname"`
// ExternalRegistryHostname sets the hostname for the default external Docker
// Registry. The external hostname should be set only when the registry is
// exposed externally. The value is used in 'publicDockerImageRepository'
// field in ImageStreams.
ExternalRegistryHostname string `json:"externalRegistryHostname"`
}

// AllowedRegistries represents a list of registries allowed for the image import.
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/server/origin/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *MasterConfig) newOpenshiftAPIConfig(kubeAPIServerConfig apiserver.Confi
RuleResolver: c.RuleResolver,
SubjectLocator: c.SubjectLocator,
LimitVerifier: c.LimitVerifier,
RegistryNameFn: c.RegistryNameFn,
RegistryHostnameRetriever: c.RegistryHostnameRetriever,
AllowedRegistriesForImport: c.Options.ImagePolicyConfig.AllowedRegistriesForImport,
MaxImagesBulkImportedPerRepository: c.Options.ImagePolicyConfig.MaxImagesBulkImportedPerRepository,
RouteAllocator: c.RouteAllocator(),
Expand Down
10 changes: 5 additions & 5 deletions pkg/cmd/server/origin/master_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ type MasterConfig struct {

// ImageFor is a function that returns the appropriate image to use for a named component
ImageFor func(component string) string
// RegistryNameFn retrieves the name of the integrated registry, or false if no such registry
// RegistryHostnameRetriever retrieves the name of the integrated registry, or false if no such registry
// is available.
RegistryNameFn imageapi.DefaultRegistryFunc
RegistryHostnameRetriever imageapi.RegistryHostnameRetriever

// ExternalVersionCodec is the codec used when serializing annotations, which cannot be changed
// without all clients being aware of the new version.
Expand Down Expand Up @@ -318,7 +318,7 @@ func BuildMasterConfig(options configapi.MasterConfig, informers InformerAccess)
Informers: informers.GetInternalKubeInformers(),
ClusterResourceQuotaInformer: informers.GetQuotaInformers().Quota().InternalVersion().ClusterResourceQuotas(),
ClusterQuotaMapper: clusterQuotaMappingController.GetClusterQuotaMapper(),
DefaultRegistryFn: imageapi.DefaultRegistryFunc(defaultRegistryFunc),
RegistryHostnameRetriever: imageapi.DefaultRegistryHostnameRetriever(defaultRegistryFunc, options.ImagePolicyConfig.ExternalRegistryHostname, options.ImagePolicyConfig.InternalRegistryHostname),
SecurityInformers: informers.GetSecurityInformers(),
UserInformers: informers.GetUserInformers(),
}
Expand Down Expand Up @@ -365,8 +365,8 @@ func BuildMasterConfig(options configapi.MasterConfig, informers InformerAccess)
AdmissionControl: originAdmission,
KubeAdmissionControl: kubeAdmission,

ImageFor: imageTemplate.ExpandOrDie,
RegistryNameFn: imageapi.DefaultRegistryFunc(defaultRegistryFunc),
ImageFor: imageTemplate.ExpandOrDie,
RegistryHostnameRetriever: imageapi.DefaultRegistryHostnameRetriever(defaultRegistryFunc, options.ImagePolicyConfig.ExternalRegistryHostname, options.ImagePolicyConfig.InternalRegistryHostname),

// TODO: migration of versions of resources stored in annotations must be sorted out
ExternalVersionCodec: kapi.Codecs.LegacyCodec(schema.GroupVersion{Group: "", Version: "v1"}),
Expand Down
10 changes: 5 additions & 5 deletions pkg/cmd/server/origin/openshift_apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ type OpenshiftAPIConfig struct {
RuleResolver rbacregistryvalidation.AuthorizationRuleResolver
SubjectLocator authorizer.SubjectLocator
LimitVerifier imageadmission.LimitVerifier
// RegistryNameFn retrieves the name of the integrated registry, or false if no such registry
// is available.
RegistryNameFn imageapi.DefaultRegistryFunc
// RegistryHostnameRetriever retrieves the internal and external hostname of
// the integrated registry, or false if no such registry is available.
RegistryHostnameRetriever imageapi.RegistryHostnameRetriever
AllowedRegistriesForImport *configapi.AllowedRegistries
MaxImagesBulkImportedPerRepository int

Expand Down Expand Up @@ -144,8 +144,8 @@ func (c *OpenshiftAPIConfig) Validate() error {
if c.LimitVerifier == nil {
ret = append(ret, fmt.Errorf("LimitVerifier is required"))
}
if c.RegistryNameFn == nil {
ret = append(ret, fmt.Errorf("RegistryNameFn is required"))
if c.RegistryHostnameRetriever == nil {
ret = append(ret, fmt.Errorf("RegistryHostnameRetriever is required"))
}
if c.RouteAllocator == nil {
ret = append(ret, fmt.Errorf("RouteAllocator is required"))
Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/server/origin/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,12 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string
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.RegistryNameFn, subjectAccessReviewRegistry, c.LimitVerifier)
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.RegistryNameFn)
imageStreamMappingStorage := imagestreammapping.NewREST(imageRegistry, imageStreamRegistry, c.RegistryHostnameRetriever)
imageStreamTagStorage := imagestreamtag.NewREST(imageRegistry, imageStreamRegistry)
importerCache, err := imageimporter.NewImageStreamLayerCache(imageimporter.DefaultImageStreamLayerCacheSize)
if err != nil {
Expand All @@ -231,7 +231,7 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string
insecureImportTransport,
importerDockerClientFn,
c.AllowedRegistriesForImport,
c.RegistryNameFn,
c.RegistryHostnameRetriever,
c.DeprecatedOpenshiftClient.SubjectAccessReviews())
imageStreamImageStorage := imagestreamimage.NewREST(imageRegistry, imageStreamRegistry)

Expand Down
2 changes: 1 addition & 1 deletion pkg/image/admission/imagepolicy/imagepolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func newImagePolicyPlugin(parsed *api.ImagePolicyConfig) (*imagePolicyPlugin, er
}, nil
}

func (a *imagePolicyPlugin) SetDefaultRegistryFunc(fn imageapi.DefaultRegistryFunc) {
func (a *imagePolicyPlugin) SetDefaultRegistryFunc(fn func() (string, bool)) {
a.integratedRegistryMatcher.RegistryMatcher = rules.RegistryNameMatcher(fn)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/image/admission/imagepolicy/rules/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ type RegistryMatcher interface {
Matches(name string) bool
}

type RegistryNameMatcher imageapi.DefaultRegistryFunc
type RegistryNameMatcher func() (string, bool)

func (m RegistryNameMatcher) Matches(name string) bool {
current, ok := imageapi.DefaultRegistryFunc(m)()
current, ok := m()
if !ok {
return false
}
Expand Down
44 changes: 36 additions & 8 deletions pkg/image/apis/image/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,45 @@ var errNoRegistryURLPathAllowed = fmt.Errorf("no path after <host>[:<port>] is a
var errNoRegistryURLQueryAllowed = fmt.Errorf("no query arguments are allowed after <host>[:<port>]")
var errRegistryURLHostEmpty = fmt.Errorf("no host name specified")

// DefaultRegistry returns the default Docker registry (host or host:port), or false if it is not available.
type DefaultRegistry interface {
DefaultRegistry() (string, bool)
// RegistryHostnameRetriever represents an interface for retrieving the hostname
// of internal and external registry.
type RegistryHostnameRetriever interface {
InternalRegistryHostnameFn() func() (string, bool)
ExternalRegistryHostnameFn() func() (string, bool)
}

// DefaultRegistryFunc implements DefaultRegistry for a simple function.
type DefaultRegistryFunc func() (string, bool)
// DefaultRegistryHostnameRetriever is a default implementation of
// RegistryHostnameRetriever.
// The first argument is a function that lazy-loads the value of
// OPENSHIFT_DEFAULT_REGISTRY environment variable.
func DefaultRegistryHostnameRetriever(defaultFn func() (string, bool), external, internal string) RegistryHostnameRetriever {
return &defaultRegistryHostnameRetriever{defaultFn: defaultFn, external: external, internal: internal}
}

type defaultRegistryHostnameRetriever struct {
defaultFn func() (string, bool)
internal, external string
}

// InternalRegistryHostnameFn returns a function that can be used to lazy-load
// the internal Docker Registry hostname. If the master configuration propertly
// InternalRegistryHostname is set, it will prefer that over the lazy-loaded
// environment variable 'OPENSHIFT_DEFAULT_REGISTRY'.
func (r *defaultRegistryHostnameRetriever) InternalRegistryHostnameFn() func() (string, bool) {
if len(r.internal) > 0 {
return func() (string, bool) { return r.internal, true }
}
if r.defaultFn == nil {
return func() (string, bool) { return "", false }
}
return r.defaultFn
}

// DefaultRegistry implements the DefaultRegistry interface for a function.
func (fn DefaultRegistryFunc) DefaultRegistry() (string, bool) {
return fn()
// ExternalRegistryHostnameFn returns a function that can be used to retrieve an
// external/public hostname of Docker Registry. External location can be
// configured in master config using 'ExternalRegistryHostname' property.
func (r *defaultRegistryHostnameRetriever) ExternalRegistryHostnameFn() func() (string, bool) {
return func() (string, bool) { return r.external, len(r.external) > 0 }
}

// ParseImageStreamImageName splits a string into its name component and ID component, and returns an error
Expand Down
4 changes: 2 additions & 2 deletions pkg/image/registry/imagestream/etcd/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type REST struct {
var _ rest.StandardStorage = &REST{}

// NewREST returns a new REST.
func NewREST(optsGetter restoptions.Getter, defaultRegistry imageapi.DefaultRegistry, subjectAccessReviewRegistry subjectaccessreview.Registry, limitVerifier imageadmission.LimitVerifier) (*REST, *StatusREST, *InternalREST, error) {
func NewREST(optsGetter restoptions.Getter, registryHostname imageapi.RegistryHostnameRetriever, subjectAccessReviewRegistry subjectaccessreview.Registry, limitVerifier imageadmission.LimitVerifier) (*REST, *StatusREST, *InternalREST, error) {
store := registry.Store{
Copier: kapi.Scheme,
NewFunc: func() runtime.Object { return &imageapi.ImageStream{} },
Expand All @@ -39,7 +39,7 @@ func NewREST(optsGetter restoptions.Getter, defaultRegistry imageapi.DefaultRegi
subjectAccessReviewRegistry: subjectAccessReviewRegistry,
}
// strategy must be able to load image streams across namespaces during tag verification
strategy := imagestream.NewStrategy(defaultRegistry, subjectAccessReviewRegistry, limitVerifier, rest)
strategy := imagestream.NewStrategy(registryHostname, subjectAccessReviewRegistry, limitVerifier, rest)

store.CreateStrategy = strategy
store.UpdateStrategy = strategy
Expand Down
7 changes: 4 additions & 3 deletions pkg/image/registry/imagestream/etcd/etcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const (
)

var (
testDefaultRegistry = imageapi.DefaultRegistryFunc(func() (string, bool) { return "test", true })
noDefaultRegistry = imageapi.DefaultRegistryFunc(func() (string, bool) { return "", false })
testDefaultRegistry = func() (string, bool) { return "test", true }
noDefaultRegistry = func() (string, bool) { return "", false }
)

type fakeSubjectAccessReviewRegistry struct {
Expand All @@ -48,7 +48,8 @@ func (f *fakeSubjectAccessReviewRegistry) CreateSubjectAccessReview(ctx apireque

func newStorage(t *testing.T) (*REST, *StatusREST, *InternalREST, *etcdtesting.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, latest.Version.Group)
imageStorage, statusStorage, internalStorage, err := NewREST(restoptions.NewSimpleGetter(etcdStorage), noDefaultRegistry, &fakeSubjectAccessReviewRegistry{}, &testutil.FakeImageStreamLimitVerifier{})
registry := imageapi.DefaultRegistryHostnameRetriever(noDefaultRegistry, "", "")
imageStorage, statusStorage, internalStorage, err := NewREST(restoptions.NewSimpleGetter(etcdStorage), registry, &fakeSubjectAccessReviewRegistry{}, &testutil.FakeImageStreamLimitVerifier{})
if err != nil {
t.Fatal(err)
}
Expand Down
Loading

0 comments on commit d3fe3c1

Please sign in to comment.