api/handler/cleanup_queued_tar_test.go
Rama main · réplica de lectura del repositorio original.
package handler
import (
"encoding/json"
"errors"
"path/filepath"
"testing"
apimodel "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/db"
"github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/mq/client"
guard "github.com/goodrain/rainbond/pkg/cleanup"
"github.com/jinzhu/gorm"
)
type queuedTarDB struct {
db.Manager
database *gorm.DB
}
func (d queuedTarDB) DB() *gorm.DB { return d.database }
type queuedTarMQ struct {
client.MQClient
send func(client.TaskStruct) error
}
func (q queuedTarMQ) SendBuilderTopic(task client.TaskStruct) error { return q.send(task) }
// capability_id: rainbond.cleanup.tar-admission-before-enqueue
func TestTarAPIReservesBeforeEnqueueAndRetainsLostAcknowledgement(t *testing.T) {
for _, lost := range []bool{false, true} {
database, err := gorm.Open("sqlite3", filepath.Join(t.TempDir(), "enqueue.db"))
if err != nil {
t.Fatal(err)
}
if err := database.AutoMigrate(&model.CleanupStorage{}, &model.CleanupOperation{}).Error; err != nil {
t.Fatal(err)
}
binding, err := guard.ProvisionRegistryStorage(database, "owned-volume", "/registry")
if err != nil {
t.Fatal(err)
}
old := db.GetManager()
db.SetTestManager(queuedTarDB{database: database})
called := 0
handler := &TarImageHandle{MQClient: queuedTarMQ{send: func(task client.TaskStruct) error {
called++
body, err := json.Marshal(task.TaskBody)
if err != nil {
t.Fatal(err)
}
input := task.TaskBody.(map[string]interface{})
expected := guard.NativeTarRequest(guard.StoreIdentity{StorageID: binding.StorageID, Generation: binding.Generation}, input["load_id"].(string), body)
var op model.CleanupOperation
if err := database.Where("operation_id = ?", expected.OperationID).First(&op).Error; err != nil || op.State != "queued" || op.Fingerprint != expected.Fingerprint {
t.Fatal("MQ called before exact-body reservation", err)
}
if lost {
return errors.New("fixture response lost")
}
return nil
}}}
_, apiErr := handler.LoadTarImage("tenant", apimodel.LoadTarImageReq{EventID: "owned", TarFilePath: "owned.tar"})
db.SetTestManager(old)
if called != 1 || (apiErr != nil) != lost {
t.Fatal("incorrect enqueue result")
}
var count int
if err := database.Model(&model.CleanupOperation{}).Where("state = ?", "queued").Count(&count).Error; err != nil || count != 1 {
t.Fatal("queued evidence released before execution", err)
}
database.Close()
}
}
// capability_id: rainbond.cleanup.package-check-before-enqueue
func TestServiceCheckReservesOnlyUploadedPackageSources(t *testing.T) {
for _, kind := range []string{"package_build", "sourcecode-pkg", "sourcecode-git", "docker-compose", "docker-run-tar", "docker-run-image"} {
t.Run(kind, func(t *testing.T) {
database, err := gorm.Open("sqlite3", filepath.Join(t.TempDir(), "check.db"))
if err != nil {
t.Fatal(err)
}
defer database.Close()
if err := database.AutoMigrate(&model.CleanupStorage{}, &model.CleanupOperation{}).Error; err != nil {
t.Fatal(err)
}
binding, err := guard.ProvisionRegistryStorage(database, "owned", "/registry")
if err != nil {
t.Fatal(err)
}
old := db.GetManager()
db.SetTestManager(queuedTarDB{database: database})
defer db.SetTestManager(old)
req := &apimodel.ServiceCheckStruct{}
req.Body.SourceType = kind
req.Body.EventID = "owned"
switch kind {
case "sourcecode-pkg":
req.Body.SourceType = "sourcecode"
req.Body.SourceBody = `{"server_type":"pkg"}`
case "sourcecode-git":
req.Body.SourceType = "sourcecode"
req.Body.SourceBody = `{"server_type":"git"}`
case "docker-run-tar":
req.Body.SourceType = "docker-run"
req.Body.SourceBody = "event owned"
case "docker-run-image":
req.Body.SourceType = "docker-run"
req.Body.SourceBody = "docker run nginx"
}
needs := kind != "sourcecode-git" && kind != "docker-run-image"
calls := 0
h := &ServiceAction{MQClient: queuedTarMQ{send: func(task client.TaskStruct) error {
calls++
raw, err := json.Marshal(task.TaskBody)
if err != nil {
t.Fatal(err)
}
expected := guard.QueuedNativeRequest(guard.StoreIdentity{StorageID: binding.StorageID, Generation: binding.Generation}, "service-check", req.Body.CheckUUID, raw)
var rows []model.CleanupOperation
if err := database.Find(&rows).Error; err != nil {
t.Fatal(err)
}
if needs {
if len(rows) != 1 || rows[0].OperationID != expected.OperationID || rows[0].Fingerprint != expected.Fingerprint || rows[0].State != "queued" {
t.Fatal("package check enqueued without matching reservation")
}
} else if len(rows) != 0 {
t.Fatal("ordinary source check changed behavior")
}
return nil
}}}
if _, _, err := h.ServiceCheck(req); err != nil || calls != 1 {
t.Fatal("check failed", err)
}
})
}
}