Catalog for V2 API Implementation
This change adds a basic catalog endpoint to the API, which returns a list, or partial list, of all of the repositories contained in the registry. Calls to this endpoint are somewhat expensive, as every call requires walking a large part of the registry. Instead, to maintain a list of repositories, you would first call the catalog endpoint to get an initial list, and then use the events API to maintain any future repositories. Signed-off-by: Patrick Devine <patrick.devine@docker.com>
This commit is contained in:
parent
0790a298ed
commit
f3207e76c8
11 changed files with 568 additions and 1 deletions
|
@ -69,6 +69,7 @@ func NewApp(ctx context.Context, configuration configuration.Configuration) *App
|
|||
return http.HandlerFunc(apiBase)
|
||||
})
|
||||
app.register(v2.RouteNameManifest, imageManifestDispatcher)
|
||||
app.register(v2.RouteNameCatalog, catalogDispatcher)
|
||||
app.register(v2.RouteNameTags, tagsDispatcher)
|
||||
app.register(v2.RouteNameBlob, blobDispatcher)
|
||||
app.register(v2.RouteNameBlobUpload, blobUploadDispatcher)
|
||||
|
@ -366,6 +367,9 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
|
|||
// Add username to request logging
|
||||
context.Context = ctxu.WithLogger(context.Context, ctxu.GetLogger(context.Context, "auth.user.name"))
|
||||
|
||||
catalog := app.registry.Catalog(context)
|
||||
context.Catalog = catalog
|
||||
|
||||
if app.nameRequired(r) {
|
||||
repository, err := app.registry.Repository(context, getName(context))
|
||||
|
||||
|
@ -493,6 +497,7 @@ func (app *App) authorized(w http.ResponseWriter, r *http.Request, context *Cont
|
|||
}
|
||||
return fmt.Errorf("forbidden: no repository name")
|
||||
}
|
||||
accessRecords = appendCatalogAccessRecord(accessRecords, r)
|
||||
}
|
||||
|
||||
ctx, err := app.accessController.Authorized(context.Context, accessRecords...)
|
||||
|
@ -538,7 +543,8 @@ func (app *App) eventBridge(ctx *Context, r *http.Request) notifications.Listene
|
|||
// nameRequired returns true if the route requires a name.
|
||||
func (app *App) nameRequired(r *http.Request) bool {
|
||||
route := mux.CurrentRoute(r)
|
||||
return route == nil || route.GetName() != v2.RouteNameBase
|
||||
routeName := route.GetName()
|
||||
return route == nil || (routeName != v2.RouteNameBase && routeName != v2.RouteNameCatalog)
|
||||
}
|
||||
|
||||
// apiBase implements a simple yes-man for doing overall checks against the
|
||||
|
@ -588,6 +594,26 @@ func appendAccessRecords(records []auth.Access, method string, repo string) []au
|
|||
return records
|
||||
}
|
||||
|
||||
// Add the access record for the catalog if it's our current route
|
||||
func appendCatalogAccessRecord(accessRecords []auth.Access, r *http.Request) []auth.Access {
|
||||
route := mux.CurrentRoute(r)
|
||||
routeName := route.GetName()
|
||||
|
||||
if routeName == v2.RouteNameCatalog {
|
||||
resource := auth.Resource{
|
||||
Type: "registry",
|
||||
Name: "catalog",
|
||||
}
|
||||
|
||||
accessRecords = append(accessRecords,
|
||||
auth.Access{
|
||||
Resource: resource,
|
||||
Action: "*",
|
||||
})
|
||||
}
|
||||
return accessRecords
|
||||
}
|
||||
|
||||
// applyRegistryMiddleware wraps a registry instance with the configured middlewares
|
||||
func applyRegistryMiddleware(registry distribution.Namespace, middlewares []configuration.Middleware) (distribution.Namespace, error) {
|
||||
for _, mw := range middlewares {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue