kvm2: apply the milestone review
Shorter start wait with immediate verdicts for dead or paused domains, ListByTag without state or address RPCs, Timeout for an expired check round, no adoption of unmarked domains, reference-counted keyed locks, dead options removed, HEAD fallback on any non-2xx. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -152,6 +152,17 @@ func serveStatus(code int) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, _ *http.Request) { http.Error(w, http.StatusText(code), code) }
|
||||
}
|
||||
|
||||
// headFails answers HEAD with code and hands every other method to next.
|
||||
func headFails(code int, next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodHead {
|
||||
http.Error(w, http.StatusText(code), code)
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveImage_table(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := withDefaults(provider.KVMConfig{Images: map[string]provider.KVMImage{
|
||||
@@ -883,17 +894,30 @@ func TestImageSizeIfUncached_headThenGetFallback(t *testing.T) {
|
||||
wantMethods: []string{http.MethodHead},
|
||||
},
|
||||
{
|
||||
name: "HEAD not allowed falls back to GET with the body closed",
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodHead {
|
||||
http.Error(w, "nope", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
serveBytes(body)(w, r)
|
||||
},
|
||||
name: "HEAD not allowed falls back to GET with the body closed",
|
||||
handler: headFails(http.StatusMethodNotAllowed, serveBytes(body)),
|
||||
wantSize: int64(len(body)),
|
||||
wantMethods: []string{http.MethodHead, http.MethodGet},
|
||||
},
|
||||
{
|
||||
name: "HEAD forbidden falls back to GET",
|
||||
handler: headFails(http.StatusForbidden, serveBytes(body)),
|
||||
wantSize: int64(len(body)),
|
||||
wantMethods: []string{http.MethodHead, http.MethodGet},
|
||||
},
|
||||
{
|
||||
name: "HEAD not implemented falls back to GET",
|
||||
handler: headFails(http.StatusNotImplemented, serveBytes(body)),
|
||||
wantSize: int64(len(body)),
|
||||
wantMethods: []string{http.MethodHead, http.MethodGet},
|
||||
},
|
||||
{
|
||||
name: "HEAD refused and GET 404 is permanent from the GET",
|
||||
handler: headFails(http.StatusMethodNotAllowed, serveStatus(http.StatusNotFound)),
|
||||
wantMethods: []string{http.MethodHead, http.MethodGet},
|
||||
wantClass: provider.ErrPermanent,
|
||||
wantErr: "404",
|
||||
},
|
||||
{
|
||||
name: "marker present means nothing to download",
|
||||
handler: serveBytes(body),
|
||||
@@ -902,16 +926,16 @@ func TestImageSizeIfUncached_headThenGetFallback(t *testing.T) {
|
||||
wantMethods: nil,
|
||||
},
|
||||
{
|
||||
name: "404 is permanent",
|
||||
name: "404 on both is permanent",
|
||||
handler: serveStatus(http.StatusNotFound),
|
||||
wantMethods: []string{http.MethodHead},
|
||||
wantMethods: []string{http.MethodHead, http.MethodGet},
|
||||
wantClass: provider.ErrPermanent,
|
||||
wantErr: "404",
|
||||
},
|
||||
{
|
||||
name: "503 is transient",
|
||||
name: "503 on both is transient",
|
||||
handler: serveStatus(http.StatusServiceUnavailable),
|
||||
wantMethods: []string{http.MethodHead},
|
||||
wantMethods: []string{http.MethodHead, http.MethodGet},
|
||||
wantClass: provider.ErrTransient,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user