package admin import ( "context" "errors" "testing" "github.com/wangjia/pangolin/server/internal/provision" ) // fakeReplacer records the arguments passed to Replace and returns canned values. type fakeReplacer struct { gotNodeID int64 gotUUID string res *provision.ReplaceResult err error } func (f *fakeReplacer) Replace(_ context.Context, nodeID int64, uuid string) (*provision.ReplaceResult, error) { f.gotNodeID, f.gotUUID = nodeID, uuid return f.res, f.err } func TestRealProvision_Replace_DelegatesWithFreshUUID(t *testing.T) { f := &fakeReplacer{res: &provision.ReplaceResult{NewNodeID: 99}} p := NewRealProvision(f) if err := p.Replace(context.Background(), 42, "operator"); err != nil { t.Fatalf("Replace: %v", err) } if f.gotNodeID != 42 { t.Errorf("nodeID = %d, want 42", f.gotNodeID) } // Admin always starts a fresh orchestration: the service mints its own key. if f.gotUUID != "" { t.Errorf("replacementUUID = %q, want empty (fresh start)", f.gotUUID) } if !p.Ready() { t.Error("RealProvision.Ready() = false, want true") } } func TestRealProvision_Replace_PropagatesError(t *testing.T) { sentinel := errors.New("no vendor credentials") p := NewRealProvision(&fakeReplacer{err: sentinel}) if err := p.Replace(context.Background(), 7, "operator"); !errors.Is(err, sentinel) { t.Errorf("Replace error = %v, want %v", err, sentinel) } } func TestRealLifecycle_RejectsUnsupportedTarget(t *testing.T) { // Target validation happens before any DB access, so a nil db is safe here. l := &RealLifecycle{} if err := l.TransitionStatus(context.Background(), 1, "destroyed", "operator"); err == nil { t.Error("TransitionStatus with target=destroyed should error, got nil") } if !l.Ready() { t.Error("RealLifecycle.Ready() = false, want true") } }