mirror of
https://github.com/distribution/distribution.git
synced 2025-08-01 23:18:31 +00:00
Merge 402ac1fcb6
into 97495e5397
This commit is contained in:
commit
2ace517601
@ -104,7 +104,6 @@ func SetDefaultLogger(logger Logger) {
|
||||
// required.
|
||||
func getLogrusLogger(ctx context.Context, keys ...interface{}) *logrus.Entry {
|
||||
var logger *logrus.Entry
|
||||
|
||||
// Get a logger, if it is present.
|
||||
loggerInterface := ctx.Value(loggerKey{})
|
||||
if loggerInterface != nil {
|
||||
|
@ -59,7 +59,7 @@ const defaultCheckInterval = 10 * time.Second
|
||||
// on this object that will be accessible from all requests. Any writable
|
||||
// fields should be protected.
|
||||
type App struct {
|
||||
context.Context
|
||||
Context context.Context
|
||||
|
||||
Config *configuration.Configuration
|
||||
|
||||
@ -92,6 +92,8 @@ type App struct {
|
||||
// requests. The app only implements ServeHTTP and can be wrapped in other
|
||||
// handlers accordingly.
|
||||
func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
logger := dcontext.GetLogger(ctx)
|
||||
|
||||
app := &App{
|
||||
Config: config,
|
||||
Context: ctx,
|
||||
@ -100,7 +102,7 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
}
|
||||
|
||||
// Register the handler dispatchers.
|
||||
app.register(v2.RouteNameBase, func(ctx *Context, r *http.Request) http.Handler {
|
||||
app.register(v2.RouteNameBase, func(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
return http.HandlerFunc(apiBase)
|
||||
})
|
||||
app.register(v2.RouteNameManifest, manifestDispatcher)
|
||||
@ -120,7 +122,7 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
}
|
||||
|
||||
var err error
|
||||
app.driver, err = factory.Create(app, config.Storage.Type(), storageParams)
|
||||
app.driver, err = factory.Create(ctx, config.Storage.Type(), storageParams)
|
||||
if err != nil {
|
||||
// TODO(stevvooe): Move the creation of a service into a protected
|
||||
// method, where this is created lazily. Its status can be queried via
|
||||
@ -150,9 +152,9 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
}
|
||||
}
|
||||
|
||||
startUploadPurger(app, app.driver, dcontext.GetLogger(app), purgeConfig)
|
||||
startUploadPurger(app.Context, app.driver, logger, purgeConfig)
|
||||
|
||||
app.driver, err = applyStorageMiddleware(app, app.driver, config.Middleware["storage"])
|
||||
app.driver, err = applyStorageMiddleware(ctx, app.driver, config.Middleware["storage"])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -217,7 +219,7 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
}
|
||||
}
|
||||
if redirectDisabled {
|
||||
dcontext.GetLogger(app).Infof("backend redirection disabled")
|
||||
logger.Infof("backend redirection disabled")
|
||||
} else {
|
||||
options = append(options, storage.EnableRedirect)
|
||||
}
|
||||
@ -288,15 +290,15 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
panic("redis configuration required to use for layerinfo cache")
|
||||
}
|
||||
if _, ok := cc["blobdescriptorsize"]; ok {
|
||||
dcontext.GetLogger(app).Warnf("blobdescriptorsize parameter is not supported with redis cache")
|
||||
logger.Warnf("blobdescriptorsize parameter is not supported with redis cache")
|
||||
}
|
||||
cacheProvider := rediscache.NewRedisBlobDescriptorCacheProvider(app.redis)
|
||||
localOptions := append(options, storage.BlobDescriptorCacheProvider(cacheProvider))
|
||||
app.registry, err = storage.NewRegistry(app, app.driver, localOptions...)
|
||||
app.registry, err = storage.NewRegistry(ctx, app.driver, localOptions...)
|
||||
if err != nil {
|
||||
panic("could not create registry: " + err.Error())
|
||||
}
|
||||
dcontext.GetLogger(app).Infof("using redis blob descriptor cache")
|
||||
logger.Infof("using redis blob descriptor cache")
|
||||
case "inmemory":
|
||||
blobDescriptorSize := memorycache.DefaultSize
|
||||
configuredSize, ok := cc["blobdescriptorsize"]
|
||||
@ -310,14 +312,14 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
|
||||
cacheProvider := memorycache.NewInMemoryBlobDescriptorCacheProvider(blobDescriptorSize)
|
||||
localOptions := append(options, storage.BlobDescriptorCacheProvider(cacheProvider))
|
||||
app.registry, err = storage.NewRegistry(app, app.driver, localOptions...)
|
||||
app.registry, err = storage.NewRegistry(ctx, app.driver, localOptions...)
|
||||
if err != nil {
|
||||
panic("could not create registry: " + err.Error())
|
||||
}
|
||||
dcontext.GetLogger(app).Infof("using inmemory blob descriptor cache")
|
||||
logger.Infof("using inmemory blob descriptor cache")
|
||||
default:
|
||||
if v != "" {
|
||||
dcontext.GetLogger(app).Warnf("unknown cache type %q, caching disabled", config.Storage["cache"])
|
||||
logger.Warnf("unknown cache type %q, caching disabled", config.Storage["cache"])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -330,7 +332,7 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
}
|
||||
}
|
||||
|
||||
app.registry, err = applyRegistryMiddleware(app, app.registry, app.driver, config.Middleware["registry"])
|
||||
app.registry, err = applyRegistryMiddleware(ctx, app.registry, app.driver, config.Middleware["registry"])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -343,7 +345,7 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
panic(fmt.Sprintf("unable to configure authorization (%s): %v", authType, err))
|
||||
}
|
||||
app.accessController = accessController
|
||||
dcontext.GetLogger(app).Debugf("configured %q access controller", authType)
|
||||
logger.Debugf("configured %q access controller", authType)
|
||||
}
|
||||
|
||||
// configure as a pull through cache
|
||||
@ -353,12 +355,12 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||
panic(err.Error())
|
||||
}
|
||||
app.isCache = true
|
||||
dcontext.GetLogger(app).Info("Registry configured as a proxy cache to ", config.Proxy.RemoteURL)
|
||||
logger.Info("Registry configured as a proxy cache to ", config.Proxy.RemoteURL)
|
||||
}
|
||||
var ok bool
|
||||
app.repoRemover, ok = app.registry.(distribution.RepositoryRemover)
|
||||
if !ok {
|
||||
dcontext.GetLogger(app).Warnf("Registry does not implement RepositoryRemover. Will not be able to delete repos and tags")
|
||||
logger.Warnf("Registry does not implement RepositoryRemover. Will not be able to delete repos and tags")
|
||||
}
|
||||
|
||||
return app
|
||||
@ -399,7 +401,7 @@ func (app *App) RegisterHealthChecks(healthRegistries ...*health.Registry) {
|
||||
|
||||
updater := health.NewThresholdStatusUpdater(app.Config.Health.StorageDriver.Threshold)
|
||||
healthRegistry.Register("storagedriver_"+app.Config.Storage.Type(), updater)
|
||||
go health.Poll(app, updater, storageDriverCheck, interval)
|
||||
go health.Poll(app.Context, updater, storageDriverCheck, interval)
|
||||
}
|
||||
|
||||
for _, fileChecker := range app.Config.Health.FileCheckers {
|
||||
@ -407,10 +409,10 @@ func (app *App) RegisterHealthChecks(healthRegistries ...*health.Registry) {
|
||||
if interval == 0 {
|
||||
interval = defaultCheckInterval
|
||||
}
|
||||
dcontext.GetLogger(app).Infof("configuring file health check path=%s, interval=%d", fileChecker.File, interval/time.Second)
|
||||
dcontext.GetLogger(app.Context).Infof("configuring file health check path=%s, interval=%d", fileChecker.File, interval/time.Second)
|
||||
u := health.NewStatusUpdater()
|
||||
healthRegistry.Register(fileChecker.File, u)
|
||||
go health.Poll(app, u, checks.FileChecker(fileChecker.File), interval)
|
||||
go health.Poll(app.Context, u, checks.FileChecker(fileChecker.File), interval)
|
||||
}
|
||||
|
||||
for _, httpChecker := range app.Config.Health.HTTPCheckers {
|
||||
@ -426,10 +428,10 @@ func (app *App) RegisterHealthChecks(healthRegistries ...*health.Registry) {
|
||||
|
||||
checker := checks.HTTPChecker(httpChecker.URI, statusCode, httpChecker.Timeout, httpChecker.Headers)
|
||||
|
||||
dcontext.GetLogger(app).Infof("configuring HTTP health check uri=%s, interval=%d, threshold=%d", httpChecker.URI, interval/time.Second, httpChecker.Threshold)
|
||||
dcontext.GetLogger(app.Context).Infof("configuring HTTP health check uri=%s, interval=%d, threshold=%d", httpChecker.URI, interval/time.Second, httpChecker.Threshold)
|
||||
updater := health.NewThresholdStatusUpdater(httpChecker.Threshold)
|
||||
healthRegistry.Register(httpChecker.URI, updater)
|
||||
go health.Poll(app, updater, checker, interval)
|
||||
go health.Poll(app.Context, updater, checker, interval)
|
||||
}
|
||||
|
||||
for _, tcpChecker := range app.Config.Health.TCPCheckers {
|
||||
@ -440,10 +442,10 @@ func (app *App) RegisterHealthChecks(healthRegistries ...*health.Registry) {
|
||||
|
||||
checker := checks.TCPChecker(tcpChecker.Addr, tcpChecker.Timeout)
|
||||
|
||||
dcontext.GetLogger(app).Infof("configuring TCP health check addr=%s, interval=%d, threshold=%d", tcpChecker.Addr, interval/time.Second, tcpChecker.Threshold)
|
||||
dcontext.GetLogger(app.Context).Infof("configuring TCP health check addr=%s, interval=%d, threshold=%d", tcpChecker.Addr, interval/time.Second, tcpChecker.Threshold)
|
||||
updater := health.NewThresholdStatusUpdater(tcpChecker.Threshold)
|
||||
healthRegistry.Register(tcpChecker.Addr, updater)
|
||||
go health.Poll(app, updater, checker, interval)
|
||||
go health.Poll(app.Context, updater, checker, interval)
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,11 +491,11 @@ func (app *App) configureEvents(configuration *configuration.Configuration) {
|
||||
var sinks []events.Sink
|
||||
for _, endpoint := range configuration.Notifications.Endpoints {
|
||||
if endpoint.Disabled {
|
||||
dcontext.GetLogger(app).Infof("endpoint %s disabled, skipping", endpoint.Name)
|
||||
dcontext.GetLogger(app.Context).Infof("endpoint %s disabled, skipping", endpoint.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
dcontext.GetLogger(app).Infof("configuring endpoint %v (%v), timeout=%s, headers=%v", endpoint.Name, endpoint.URL, endpoint.Timeout, endpoint.Headers)
|
||||
dcontext.GetLogger(app.Context).Infof("configuring endpoint %v (%v), timeout=%s, headers=%v", endpoint.Name, endpoint.URL, endpoint.Timeout, endpoint.Headers)
|
||||
endpoint := notifications.NewEndpoint(endpoint.Name, endpoint.URL, notifications.EndpointConfig{
|
||||
Timeout: endpoint.Timeout,
|
||||
Threshold: endpoint.Threshold,
|
||||
@ -526,13 +528,13 @@ func (app *App) configureEvents(configuration *configuration.Configuration) {
|
||||
|
||||
app.events.source = notifications.SourceRecord{
|
||||
Addr: hostname,
|
||||
InstanceID: dcontext.GetStringValue(app, "instance.id"),
|
||||
InstanceID: dcontext.GetStringValue(app.Context, "instance.id"),
|
||||
}
|
||||
}
|
||||
|
||||
func (app *App) configureRedis(cfg *configuration.Configuration) {
|
||||
if len(cfg.Redis.Options.Addrs) == 0 {
|
||||
dcontext.GetLogger(app).Infof("redis not configured")
|
||||
dcontext.GetLogger(app.Context).Infof("redis not configured")
|
||||
return
|
||||
}
|
||||
|
||||
@ -603,7 +605,7 @@ func (app *App) configureRedis(cfg *configuration.Configuration) {
|
||||
|
||||
// Enable metrics instrumentation.
|
||||
if err := redisotel.InstrumentMetrics(app.redis); err != nil {
|
||||
dcontext.GetLogger(app).Errorf("failed to instrument metrics on redis: %v", err)
|
||||
dcontext.GetLogger(app.Context).Errorf("failed to instrument metrics on redis: %v", err)
|
||||
}
|
||||
|
||||
// setup expvar
|
||||
@ -631,7 +633,7 @@ func (app *App) createPool(cfg redis.UniversalOptions) redis.UniversalClient {
|
||||
|
||||
// configureLogHook prepares logging hook parameters.
|
||||
func (app *App) configureLogHook(configuration *configuration.Configuration) {
|
||||
entry, ok := dcontext.GetLogger(app).(*logrus.Entry)
|
||||
entry, ok := dcontext.GetLogger(app.Context).(*logrus.Entry)
|
||||
if !ok {
|
||||
// somehow, we are not using logrus
|
||||
return
|
||||
@ -669,7 +671,7 @@ func (app *App) configureSecret(configuration *configuration.Configuration) {
|
||||
panic(fmt.Sprintf("could not generate random bytes for HTTP secret: %v", err))
|
||||
}
|
||||
configuration.HTTP.Secret = string(secretBytes[:])
|
||||
dcontext.GetLogger(app).Warn("No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable.")
|
||||
dcontext.GetLogger(app.Context).Warn("No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,7 +692,7 @@ func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// for the route. The dispatcher will use this to dynamically create request
|
||||
// specific handlers for each endpoint without creating a new router for each
|
||||
// request.
|
||||
type dispatchFunc func(ctx *Context, r *http.Request) http.Handler
|
||||
type dispatchFunc func(ctx *Context, app *App, r *http.Request) http.Handler
|
||||
|
||||
// TODO(stevvooe): dispatchers should probably have some validation error
|
||||
// chain with proper error reporting.
|
||||
@ -763,12 +765,12 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
|
||||
}
|
||||
|
||||
// assign and decorate the authorized repository with an event bridge.
|
||||
context.Repository, context.RepositoryRemover = notifications.Listen(
|
||||
context.Repository, _ = notifications.Listen(
|
||||
repository,
|
||||
context.App.repoRemover,
|
||||
app.repoRemover,
|
||||
app.eventBridge(context, r))
|
||||
|
||||
context.Repository, err = applyRepoMiddleware(app, context.Repository, app.Config.Middleware["repository"])
|
||||
context.Repository, err = applyRepoMiddleware(app.Context, context.Repository, app.Config.Middleware["repository"])
|
||||
if err != nil {
|
||||
dcontext.GetLogger(context).Errorf("error initializing repository middleware: %v", err)
|
||||
context.Errors = append(context.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
@ -780,7 +782,7 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(context, r).ServeHTTP(w, r)
|
||||
dispatch(context, app, r).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
@ -834,7 +836,6 @@ func (app *App) context(w http.ResponseWriter, r *http.Request) *Context {
|
||||
"vars.uuid"))
|
||||
|
||||
context := &Context{
|
||||
App: app,
|
||||
Context: ctx,
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ func TestAppDispatcher(t *testing.T) {
|
||||
}
|
||||
|
||||
varCheckingDispatcher := func(expectedVars map[string]string) dispatchFunc {
|
||||
return func(ctx *Context, r *http.Request) http.Handler {
|
||||
return func(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
// Always checks the same name context
|
||||
if ctx.Repository.Named().Name() != getName(ctx) {
|
||||
t.Fatalf("unexpected name: %q != %q", ctx.Repository.Named().Name(), "foo/bar")
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// blobDispatcher uses the request context to build a blobHandler.
|
||||
func blobDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
func blobDispatcher(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
dgst, err := getDigest(ctx)
|
||||
if err != nil {
|
||||
|
||||
@ -36,7 +36,7 @@ func blobDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
http.MethodHead: http.HandlerFunc(blobHandler.GetBlob),
|
||||
}
|
||||
|
||||
if !ctx.readOnly {
|
||||
if !app.readOnly {
|
||||
mhandler[http.MethodDelete] = http.HandlerFunc(blobHandler.DeleteBlob)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||
"github.com/distribution/distribution/v3/registry/storage"
|
||||
@ -18,9 +19,10 @@ import (
|
||||
|
||||
// blobUploadDispatcher constructs and returns the blob upload handler for the
|
||||
// given request context.
|
||||
func blobUploadDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
func blobUploadDispatcher(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
buh := &blobUploadHandler{
|
||||
Context: ctx,
|
||||
Config: app.Config,
|
||||
UUID: getUploadUUID(ctx),
|
||||
}
|
||||
|
||||
@ -29,7 +31,7 @@ func blobUploadDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
http.MethodHead: http.HandlerFunc(buh.GetUploadStatus),
|
||||
}
|
||||
|
||||
if !ctx.readOnly {
|
||||
if !app.readOnly {
|
||||
handler[http.MethodPost] = http.HandlerFunc(buh.StartBlobUpload)
|
||||
handler[http.MethodPatch] = http.HandlerFunc(buh.PatchBlobData)
|
||||
handler[http.MethodPut] = http.HandlerFunc(buh.PutBlobUploadComplete)
|
||||
@ -53,6 +55,8 @@ func blobUploadDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
type blobUploadHandler struct {
|
||||
*Context
|
||||
|
||||
Config *configuration.Configuration
|
||||
|
||||
// UUID identifies the upload instance for the current request. Using UUID
|
||||
// to key blob writers since this implementation uses UUIDs.
|
||||
UUID string
|
||||
@ -271,7 +275,7 @@ func (buh *blobUploadHandler) CancelBlobUpload(w http.ResponseWriter, r *http.Re
|
||||
}
|
||||
|
||||
func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) http.Handler {
|
||||
state, err := hmacKey(ctx.Config.HTTP.Secret).unpackUploadState(r.FormValue("_state"))
|
||||
state, err := hmacKey(buh.Config.HTTP.Secret).unpackUploadState(r.FormValue("_state"))
|
||||
if err != nil {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
dcontext.GetLogger(ctx).Infof("error resolving upload: %v", err)
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||
"github.com/distribution/distribution/v3/registry/storage/driver"
|
||||
"github.com/gorilla/handlers"
|
||||
@ -15,9 +17,11 @@ import (
|
||||
|
||||
const defaultReturnedEntries = 100
|
||||
|
||||
func catalogDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
func catalogDispatcher(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
catalogHandler := &catalogHandler{
|
||||
Context: ctx,
|
||||
Context: ctx,
|
||||
Config: app.Config,
|
||||
registry: app.registry,
|
||||
}
|
||||
|
||||
return handlers.MethodHandler{
|
||||
@ -27,6 +31,8 @@ func catalogDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
|
||||
type catalogHandler struct {
|
||||
*Context
|
||||
Config *configuration.Configuration
|
||||
registry distribution.Namespace
|
||||
}
|
||||
|
||||
type catalogAPIResponse struct {
|
||||
@ -40,7 +46,7 @@ func (ch *catalogHandler) GetCatalog(w http.ResponseWriter, r *http.Request) {
|
||||
lastEntry := q.Get("last")
|
||||
|
||||
entries := defaultReturnedEntries
|
||||
maximumConfiguredEntries := ch.App.Config.Catalog.MaxEntries
|
||||
maximumConfiguredEntries := ch.Config.Catalog.MaxEntries
|
||||
|
||||
// parse n, if n is negative abort with an error
|
||||
if n := q.Get("n"); n != "" {
|
||||
@ -71,7 +77,7 @@ func (ch *catalogHandler) GetCatalog(w http.ResponseWriter, r *http.Request) {
|
||||
if entries == 0 {
|
||||
moreEntries = false
|
||||
} else {
|
||||
returnedRepositories, err := ch.App.registry.Repositories(ch.Context, repos, lastEntry)
|
||||
returnedRepositories, err := ch.registry.Repositories(ch.Context, repos, lastEntry)
|
||||
if err != nil {
|
||||
_, pathNotFound := err.(driver.PathNotFoundError)
|
||||
if err != io.EOF && !pathNotFound {
|
||||
|
@ -17,17 +17,12 @@ import (
|
||||
// handlers. Resources that don't need to be shared across handlers should not
|
||||
// be on this object.
|
||||
type Context struct {
|
||||
// App points to the application structure that created this context.
|
||||
*App
|
||||
context.Context
|
||||
|
||||
// Repository is the repository for the current request. All requests
|
||||
// should be scoped to a single repository. This field may be nil.
|
||||
Repository distribution.Repository
|
||||
|
||||
// RepositoryRemover provides method to delete a repository
|
||||
RepositoryRemover distribution.RepositoryRemover
|
||||
|
||||
// Errors is a collection of errors encountered during the request to be
|
||||
// returned to the client API. If errors are added to the collection, the
|
||||
// handler *must not* start the response via http.ResponseWriter.
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/internal/dcontext"
|
||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||
@ -42,9 +43,11 @@ const (
|
||||
|
||||
// manifestDispatcher takes the request context and builds the
|
||||
// appropriate handler for handling manifest requests.
|
||||
func manifestDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
func manifestDispatcher(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
manifestHandler := &manifestHandler{
|
||||
Context: ctx,
|
||||
isCache: app.isCache,
|
||||
Config: app.Config,
|
||||
}
|
||||
ref := getReference(ctx)
|
||||
dgst, err := digest.Parse(ref)
|
||||
@ -60,7 +63,7 @@ func manifestDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
http.MethodHead: http.HandlerFunc(manifestHandler.GetManifest),
|
||||
}
|
||||
|
||||
if !ctx.readOnly {
|
||||
if !app.readOnly {
|
||||
mhandler[http.MethodPut] = http.HandlerFunc(manifestHandler.PutManifest)
|
||||
mhandler[http.MethodDelete] = http.HandlerFunc(manifestHandler.DeleteManifest)
|
||||
}
|
||||
@ -72,6 +75,11 @@ func manifestDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
type manifestHandler struct {
|
||||
*Context
|
||||
|
||||
Config *configuration.Configuration
|
||||
|
||||
// isCache is true if this registry is configured as a pull through cache
|
||||
isCache bool
|
||||
|
||||
// One of tag or digest gets set, depending on what is present in context.
|
||||
Tag string
|
||||
Digest digest.Digest
|
||||
@ -362,7 +370,7 @@ func (imh *manifestHandler) PutManifest(w http.ResponseWriter, r *http.Request)
|
||||
// applyResourcePolicy checks whether the resource class matches what has
|
||||
// been authorized and allowed by the policy configuration.
|
||||
func (imh *manifestHandler) applyResourcePolicy(manifest distribution.Manifest) error {
|
||||
allowedClasses := imh.App.Config.Policy.Repository.Classes
|
||||
allowedClasses := imh.Config.Policy.Repository.Classes
|
||||
if len(allowedClasses) == 0 {
|
||||
return nil
|
||||
}
|
||||
@ -431,7 +439,7 @@ func (imh *manifestHandler) applyResourcePolicy(manifest distribution.Manifest)
|
||||
func (imh *manifestHandler) DeleteManifest(w http.ResponseWriter, r *http.Request) {
|
||||
dcontext.GetLogger(imh).Debug("DeleteImageManifest")
|
||||
|
||||
if imh.App.isCache {
|
||||
if imh.isCache {
|
||||
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnsupported)
|
||||
return
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// tagsDispatcher constructs the tags handler api endpoint.
|
||||
func tagsDispatcher(ctx *Context, r *http.Request) http.Handler {
|
||||
func tagsDispatcher(ctx *Context, app *App, r *http.Request) http.Handler {
|
||||
tagsHandler := &tagsHandler{
|
||||
Context: ctx,
|
||||
}
|
||||
|
@ -231,6 +231,7 @@ func setDirectoryURL(directoryurl string) *acme.Client {
|
||||
// ListenAndServe runs the registry's HTTP server.
|
||||
func (registry *Registry) ListenAndServe() error {
|
||||
config := registry.config
|
||||
logger := dcontext.GetLogger(registry.app.Context)
|
||||
|
||||
ln, err := listener.NewListener(config.HTTP.Net, config.HTTP.Addr)
|
||||
if err != nil {
|
||||
@ -245,19 +246,19 @@ func (registry *Registry) ListenAndServe() error {
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown minimum TLS level '%s' specified for http.tls.minimumtls", config.HTTP.TLS.MinimumTLS)
|
||||
}
|
||||
dcontext.GetLogger(registry.app).Infof("restricting TLS version to %s or higher", config.HTTP.TLS.MinimumTLS)
|
||||
logger.Infof("restricting TLS version to %s or higher", config.HTTP.TLS.MinimumTLS)
|
||||
|
||||
var tlsCipherSuites []uint16
|
||||
// configuring cipher suites are no longer supported after the tls1.3.
|
||||
// (https://go.dev/blog/tls-cipher-suites)
|
||||
if tlsMinVersion > tls.VersionTLS12 {
|
||||
dcontext.GetLogger(registry.app).Warnf("restricting TLS cipher suites to empty. Because configuring cipher suites is no longer supported in %s", config.HTTP.TLS.MinimumTLS)
|
||||
logger.Warnf("restricting TLS cipher suites to empty. Because configuring cipher suites is no longer supported in %s", config.HTTP.TLS.MinimumTLS)
|
||||
} else {
|
||||
tlsCipherSuites, err = getCipherSuites(config.HTTP.TLS.CipherSuites)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dcontext.GetLogger(registry.app).Infof("restricting TLS cipher suites to: %s", strings.Join(getCipherSuiteNames(tlsCipherSuites), ","))
|
||||
logger.Infof("restricting TLS cipher suites to: %s", strings.Join(getCipherSuiteNames(tlsCipherSuites), ","))
|
||||
}
|
||||
|
||||
tlsConf := &tls.Config{
|
||||
@ -303,7 +304,7 @@ func (registry *Registry) ListenAndServe() error {
|
||||
}
|
||||
|
||||
for _, subj := range pool.Subjects() { //nolint:staticcheck // FIXME(thaJeztah): ignore SA1019: ac.(*accessController).rootCerts.Subjects has been deprecated since Go 1.18: if s was returned by SystemCertPool, Subjects will not include the system roots. (staticcheck)
|
||||
dcontext.GetLogger(registry.app).Debugf("CA Subject: %s", string(subj))
|
||||
logger.Debugf("CA Subject: %s", string(subj))
|
||||
}
|
||||
|
||||
if config.HTTP.TLS.ClientAuth != "" {
|
||||
@ -322,9 +323,9 @@ func (registry *Registry) ListenAndServe() error {
|
||||
}
|
||||
|
||||
ln = tls.NewListener(ln, tlsConf)
|
||||
dcontext.GetLogger(registry.app).Infof("listening on %v, tls", ln.Addr())
|
||||
logger.Infof("listening on %v, tls", ln.Addr())
|
||||
} else {
|
||||
dcontext.GetLogger(registry.app).Infof("listening on %v", ln.Addr())
|
||||
logger.Infof("listening on %v", ln.Addr())
|
||||
}
|
||||
|
||||
if config.HTTP.DrainTimeout == 0 {
|
||||
@ -344,7 +345,7 @@ func (registry *Registry) ListenAndServe() error {
|
||||
case err := <-serveErr:
|
||||
return err
|
||||
case <-registry.quit:
|
||||
dcontext.GetLogger(registry.app).Info("stopping server gracefully. Draining connections for ", config.HTTP.DrainTimeout)
|
||||
logger.Info("stopping server gracefully. Draining connections for ", config.HTTP.DrainTimeout)
|
||||
// shutdown the server with a grace period of configured timeout
|
||||
c, cancel := context.WithTimeout(context.Background(), config.HTTP.DrainTimeout)
|
||||
defer cancel()
|
||||
|
Loading…
Reference in New Issue
Block a user