don't panic during a request when configuring repository middleware. Return a 500 with an appropriate error
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
b5a63d75ea
commit
3853e66f4b
3 changed files with 53 additions and 26 deletions
|
@ -300,7 +300,7 @@ type Middleware struct {
|
||||||
// Name the middleware registers itself as
|
// Name the middleware registers itself as
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
// Flag to disable middleware easily
|
// Flag to disable middleware easily
|
||||||
Disabled bool `yaml:"Disabled,omitempty"`
|
Disabled bool `yaml:"disabled,omitempty"`
|
||||||
// Map of parameters that will be passed to the middleware's initialization function
|
// Map of parameters that will be passed to the middleware's initialization function
|
||||||
Options Parameters `yaml:"options"`
|
Options Parameters `yaml:"options"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,16 +89,17 @@ func NewApp(ctx context.Context, configuration configuration.Configuration) *App
|
||||||
// a health check.
|
// a health check.
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
app.driver, err = applyStorageMiddleware(app.driver, configuration.Middleware["storage"])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
app.configureEvents(&configuration)
|
app.configureEvents(&configuration)
|
||||||
|
|
||||||
app.registry = storage.NewRegistryWithDriver(app.driver)
|
app.registry = storage.NewRegistryWithDriver(app.driver)
|
||||||
for _, mw := range configuration.Middleware["registry"] {
|
app.registry, err = applyRegistryMiddleware(app.registry, configuration.Middleware["registry"])
|
||||||
rmw, err := registrymiddleware.Get(mw.Name, mw.Options, app.registry)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("unable to configure registry middleware (%s): %s", mw.Name, err))
|
panic(err)
|
||||||
}
|
|
||||||
app.registry = rmw
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authType := configuration.Auth.Type()
|
authType := configuration.Auth.Type()
|
||||||
|
@ -111,14 +112,6 @@ func NewApp(ctx context.Context, configuration configuration.Configuration) *App
|
||||||
app.accessController = accessController
|
app.accessController = accessController
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mw := range configuration.Middleware["storage"] {
|
|
||||||
smw, err := storagemiddleware.Get(mw.Name, mw.Options, app.driver)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("unable to configure storage middleware (%s): %v", mw.Name, err))
|
|
||||||
}
|
|
||||||
app.driver = smw
|
|
||||||
}
|
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,12 +251,13 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
|
||||||
repository,
|
repository,
|
||||||
app.eventBridge(context, r))
|
app.eventBridge(context, r))
|
||||||
|
|
||||||
for _, mw := range app.Config.Middleware["repository"] {
|
context.Repository, err = applyRepoMiddleware(context.Repository, app.Config.Middleware["repository"])
|
||||||
rmw, err := repositorymiddleware.Get(mw.Name, mw.Options, context.Repository)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("unable to configure repository middleware (%s): %s", mw.Name, err))
|
ctxu.GetLogger(context).Errorf("error initializing repository middleware: %v", err)
|
||||||
}
|
context.Errors.Push(v2.ErrorCodeUnknown, err)
|
||||||
context.Repository = rmw
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
serveJSON(w, context.Errors)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,3 +427,40 @@ func appendAccessRecords(records []auth.Access, method string, repo string) []au
|
||||||
}
|
}
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// applyRegistryMiddleware wraps a registry instance with the configured middlewares
|
||||||
|
func applyRegistryMiddleware(registry distribution.Registry, middlewares []configuration.Middleware) (distribution.Registry, error) {
|
||||||
|
for _, mw := range middlewares {
|
||||||
|
rmw, err := registrymiddleware.Get(mw.Name, mw.Options, registry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to configure registry middleware (%s): %s", mw.Name, err)
|
||||||
|
}
|
||||||
|
registry = rmw
|
||||||
|
}
|
||||||
|
return registry, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyRepoMiddleware wraps a repository with the configured middlewares
|
||||||
|
func applyRepoMiddleware(repository distribution.Repository, middlewares []configuration.Middleware) (distribution.Repository, error) {
|
||||||
|
for _, mw := range middlewares {
|
||||||
|
rmw, err := repositorymiddleware.Get(mw.Name, mw.Options, repository)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
repository = rmw
|
||||||
|
}
|
||||||
|
return repository, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyStorageMiddleware wraps a storage driver with the configured middlewares
|
||||||
|
func applyStorageMiddleware(driver storagedriver.StorageDriver, middlewares []configuration.Middleware) (storagedriver.StorageDriver, error) {
|
||||||
|
for _, mw := range middlewares {
|
||||||
|
smw, err := storagemiddleware.Get(mw.Name, mw.Options, driver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to configure storage middleware (%s): %v", mw.Name, err)
|
||||||
|
}
|
||||||
|
driver = smw
|
||||||
|
}
|
||||||
|
return driver, nil
|
||||||
|
}
|
||||||
|
|
|
@ -18,10 +18,6 @@ type layerReader struct {
|
||||||
|
|
||||||
var _ distribution.Layer = &layerReader{}
|
var _ distribution.Layer = &layerReader{}
|
||||||
|
|
||||||
func (lr *layerReader) Path() string {
|
|
||||||
return lr.path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lr *layerReader) Digest() digest.Digest {
|
func (lr *layerReader) Digest() digest.Digest {
|
||||||
return lr.digest
|
return lr.digest
|
||||||
}
|
}
|
||||||
|
@ -42,7 +38,7 @@ func (lr *layerReader) Close() error {
|
||||||
func (lr *layerReader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (lr *layerReader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Docker-Content-Digest", lr.digest.String())
|
w.Header().Set("Docker-Content-Digest", lr.digest.String())
|
||||||
|
|
||||||
if url, err := lr.fileReader.driver.URLFor(lr.Path(), map[string]interface{}{}); err == nil {
|
if url, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{}); err == nil {
|
||||||
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
|
http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
|
||||||
|
|
Loading…
Reference in a new issue