fix: prune missing image indexes and align instance creation payload

This commit is contained in:
2026-10-14 19:37:52 +08:00
parent 15910a086f
commit 3bf197206a
6 changed files with 125 additions and 24 deletions
+100 -5
View File
@@ -173,7 +173,7 @@ func TestImageIndexLocalInventory(t *testing.T) {
}
deleted.Store(true)
w = imageRequest(a.images, sid, "GET", "")
if err := json.Unmarshal(w.Body.Bytes(), &images); err != nil || w.Code != 200 || len(images) != 1 || images[0].Status != "missing" {
if err := json.Unmarshal(w.Body.Bytes(), &images); err != nil || w.Code != 200 || len(images) != 0 {
t.Fatal(w.Body.String(), err)
}
})
@@ -226,17 +226,112 @@ func TestImageIndexUsageMissingAndDockerFailure(t *testing.T) {
t.Fatal(status, err)
}
mode.Store(2)
check("missing", 2)
if _, err := a.s.DB.Exec("DELETE FROM instances WHERE id='two'"); err != nil {
t.Fatal(err)
for refresh := 0; refresh < 3; refresh++ {
w := imageRequest(a.images, sid, "GET", "")
if w.Code != 200 || strings.TrimSpace(w.Body.String()) != "[]" {
t.Fatal(w.Code, w.Body.String())
}
var count int
if err := a.s.DB.QueryRow("SELECT count(*) FROM images").Scan(&count); err != nil || count != 0 {
t.Fatal(count, err)
}
}
var count int
if err := a.s.DB.QueryRow("SELECT count(*) FROM instances WHERE image_id='image'").Scan(&count); err != nil || count != 2 {
t.Fatal(count, err)
}
if err := a.s.DB.QueryRow("SELECT status FROM image_builds WHERE image_id='image'").Scan(&status); err != nil || status != "missing" {
t.Fatal(status, err)
}
check("missing", 1)
verified, err := a.verifiedImages(context.Background())
if err != nil || len(verified) != 0 {
t.Fatal(verified, err)
}
}
func TestImageIndexFailurePreservesRows(t *testing.T) {
for _, mode := range []string{"list", "inspect", "rollback"} {
t.Run(mode, func(t *testing.T) {
a, _ := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/v1.47/images/json" {
if mode == "list" {
w.WriteHeader(500)
} else {
writeJSON(w, []any{})
}
return
}
if mode == "inspect" && strings.Contains(r.URL.Path, "second") {
w.WriteHeader(500)
return
}
w.WriteHeader(404)
})
seedVerifiedImage(t, a, "first", "1.0.0")
seedVerifiedImage(t, a, "second", "2.0.0")
if _, err := a.s.DB.Exec("INSERT INTO images(image_id,version,status,built_at) VALUES('first','1.0.0','available','2'),('second','2.0.0','available','1')"); err != nil {
t.Fatal(err)
}
if mode == "rollback" {
if _, err := a.s.DB.Exec("CREATE TRIGGER deny_second_delete BEFORE DELETE ON images WHEN OLD.image_id='second' BEGIN SELECT RAISE(FAIL,'unavailable'); END"); err != nil {
t.Fatal(err)
}
}
if images, err := a.imageIndex(context.Background()); err == nil || images != nil {
t.Fatalf("images=%v err=%v", images, err)
}
for _, query := range []string{"SELECT count(*) FROM images WHERE status='available'", "SELECT count(*) FROM image_builds WHERE status='success'"} {
var count int
if err := a.s.DB.QueryRow(query).Scan(&count); err != nil || count != 2 {
t.Fatal(query, count, err)
}
}
})
}
}
func TestImageIndexMissingHistoryAndBlockedReimport(t *testing.T) {
var present atomic.Bool
var inspections atomic.Int32
a, _ := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/v1.47/images/json" {
if present.Load() {
writeJSON(w, []any{map[string]any{"Id": "image", "Labels": map[string]string{"dsh-mgr.role": "runtime"}}})
} else {
writeJSON(w, []any{})
}
return
}
inspections.Add(1)
if !present.Load() {
w.WriteHeader(404)
return
}
writeImageInspect(w, "image", "0.2.0-rc.1")
})
seedVerifiedImage(t, a, "image", "0.2.0-rc.1")
if _, err := a.s.DB.Exec("UPDATE image_admissions SET state='blocked',evidence='unsafe'"); err != nil {
t.Fatal(err)
}
for refresh := 0; refresh < 3; refresh++ {
if images, err := a.imageIndex(context.Background()); err != nil || len(images) != 0 {
t.Fatal(images, err)
}
}
if inspections.Load() != 1 {
t.Fatalf("missing history caused %d inspections", inspections.Load())
}
present.Store(true)
images, err := a.imageIndex(context.Background())
if err != nil || len(images) != 1 || images[0].Status != "blocked" || images[0].Selectable || images[0].AdmissionReason != "unsafe" {
t.Fatal(images, err)
}
var status string
if err := a.s.DB.QueryRow("SELECT status FROM image_builds WHERE image_id='image'").Scan(&status); err != nil || status != "missing" {
t.Fatal(status, err)
}
}
func TestBuildDiskPolicy(t *testing.T) {
a, _ := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) { t.Error("unexpected build") })
if err := a.checkBuildDisk(context.Background()); err != nil {