Harden image admission, resource recovery and session renewal
Add exact-image compatibility policy, experimental admission, paginated build history and shared reauthentication checks. Preserve uncertain Docker creation records, bound frontend resource waits and renew runtime sessions proactively. Lazy-load and split Monaco, add regression and opt-in live Docker fault tests, and record full race and real-browser acceptance results.
This commit is contained in:
+25
-4
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
@@ -41,6 +42,10 @@ func (a *API) intents(w http.ResponseWriter, r *http.Request) {
|
||||
fail(w, 400, "name and fixed version required")
|
||||
return
|
||||
}
|
||||
if !normalBuildAllowed(in.Version) {
|
||||
fail(w, 400, errBuildUnsupported.Error())
|
||||
return
|
||||
}
|
||||
i := store.Intent{ID: store.ID(), UID: u.ID, Name: strings.TrimSpace(in.Name), Version: in.Version, Host: a.runtimeHost(r), Status: "waiting"}
|
||||
if err = a.s.ReserveIntent(i); err != nil {
|
||||
if errors.Is(err, store.ErrInstanceLimit) {
|
||||
@@ -124,21 +129,37 @@ func (a *API) recoverIntents(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
i, err := a.s.GetInstance(in.InstanceID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
a.finishIntent(in.ID, "failed", "instance reservation missing after process restart")
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err == nil && i.Status == "running" {
|
||||
a.finishIntent(in.ID, "success", "")
|
||||
continue
|
||||
}
|
||||
cleanup, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
// Docker may have created the container before its ID reached SQLite.
|
||||
err = a.removeRuntimeContainer(cleanup, runtimeNetwork(in.InstanceID))
|
||||
if err == nil && i.ContainerID == "" {
|
||||
err = a.recoverRuntimeContainer(cleanup, &i)
|
||||
}
|
||||
if err == nil && i.ContainerID != "" {
|
||||
err = a.removeRuntimeContainer(cleanup, i.ContainerID)
|
||||
}
|
||||
if err == nil {
|
||||
err = a.removeRuntimeNetwork(cleanup, in.InstanceID)
|
||||
}
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
a.s.SetInstance(in.InstanceID, "error")
|
||||
a.finishIntent(in.ID, "failed", "instance creation requires recovery: "+err.Error())
|
||||
a.s.AddAudit(in.UID, "instance.recovery_error", in.InstanceID, err.Error())
|
||||
continue
|
||||
}
|
||||
a.s.DeleteInstance(in.InstanceID)
|
||||
_, _ = a.s.DB.Exec("DELETE FROM runtime_creates WHERE instance_id=?", in.InstanceID)
|
||||
_, _ = a.s.DB.Exec("DELETE FROM runtime_networks WHERE instance_id=?", in.InstanceID)
|
||||
a.finishIntent(in.ID, "failed", "instance creation interrupted by process restart")
|
||||
}
|
||||
return nil
|
||||
@@ -180,7 +201,7 @@ func (a *API) processIntents(ctx context.Context) {
|
||||
continue
|
||||
}
|
||||
work, cancel := context.WithTimeout(ctx, 90*time.Second)
|
||||
verified, err := a.verifiedImages(work)
|
||||
verified, err := a.verifiedImagesPoll(work)
|
||||
if err != nil {
|
||||
cancel()
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user