blob: aea771791c898f3dbf90f0a07063f69ab37056ac [file] [log] [blame]
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +02001package manager
2
3import (
4 "context"
5 "testing"
6 "time"
7
8 "golang.org/x/time/rate"
9
10 "source.monogon.dev/cloud/bmaas/bmdb"
11 "source.monogon.dev/cloud/bmaas/bmdb/model"
12 "source.monogon.dev/cloud/lib/component"
13 "source.monogon.dev/cloud/shepherd"
14)
15
16// TestProvisionerSmokes makes sure the Provisioner doesn't go up in flames on
17// the happy path.
18func TestProvisionerSmokes(t *testing.T) {
19 pc := ProvisionerConfig{
20 MaxCount: 10,
21 // We need 3 iterations to provide 10 machines with a chunk size of 4.
22 ReconcileLoopLimiter: rate.NewLimiter(rate.Every(10*time.Second), 3),
23 DeviceCreationLimiter: rate.NewLimiter(rate.Every(time.Second), 10),
24 ChunkSize: 4,
25 }
26
27 provider := newDummyProvider(100)
28
29 p, err := NewProvisioner(provider, pc)
30 if err != nil {
31 t.Fatalf("Could not create Provisioner: %v", err)
32 }
33
34 ctx, ctxC := context.WithCancel(context.Background())
35 defer ctxC()
36
37 b := bmdb.BMDB{
38 Config: bmdb.Config{
39 Database: component.CockroachConfig{
40 InMemory: true,
41 },
42 ComponentName: "test",
43 RuntimeInfo: "test",
44 },
45 }
46 conn, err := b.Open(true)
47 if err != nil {
48 t.Fatalf("Could not create in-memory BMDB: %v", err)
49 }
50
51 go p.Run(ctx, conn)
52
53 sess, err := conn.StartSession(ctx)
54 if err != nil {
55 t.Fatalf("Failed to create BMDB session for verification: %v", err)
56 }
57 for {
58 time.Sleep(100 * time.Millisecond)
59
60 var provided []model.MachineProvided
61 err = sess.Transact(ctx, func(q *model.Queries) error {
62 var err error
63 provided, err = q.GetProvidedMachines(ctx, provider.Type())
64 return err
65 })
66 if err != nil {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010067 t.Fatalf("Transact failed: %v", err)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020068 }
69 if len(provided) < 10 {
70 continue
71 }
72 if len(provided) > 10 {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010073 t.Fatalf("%d machines provided (limit: 10)", len(provided))
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020074 }
75
76 for _, mp := range provided {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010077 provider.muMachines.RLock()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020078 if provider.machines[shepherd.ProviderID(mp.ProviderID)] == nil {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010079 t.Fatalf("BMDB machine %q has unknown provider ID %q", mp.MachineID, mp.ProviderID)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020080 }
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010081 provider.muMachines.RUnlock()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020082 }
83
84 return
85 }
86}
87
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010088// TestProvisioner_resolvePossiblyUsed makes sure the PossiblyUsed availability is
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020089// resolved correctly.
90func TestProvisioner_resolvePossiblyUsed(t *testing.T) {
91 const providedMachineID = "provided-machine"
92
Tim Windelschmidtfdd87ab2023-12-07 18:03:21 +010093 providedMachines := map[shepherd.ProviderID]shepherd.Machine{
94 providedMachineID: nil,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020095 }
96
97 tests := []struct {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010098 name string
99 machineID shepherd.ProviderID
100 machineAvailability shepherd.Availability
101 wantedAvailability shepherd.Availability
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200102 }{
103 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100104 name: "skip KnownUsed",
105 machineAvailability: shepherd.AvailabilityKnownUsed,
106 wantedAvailability: shepherd.AvailabilityKnownUsed,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200107 },
108 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100109 name: "skip KnownUnused",
110 machineAvailability: shepherd.AvailabilityKnownUnused,
111 wantedAvailability: shepherd.AvailabilityKnownUnused,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200112 },
113 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100114 name: "invalid ID",
115 machineID: shepherd.InvalidProviderID,
116 machineAvailability: shepherd.AvailabilityPossiblyUsed,
117 wantedAvailability: shepherd.AvailabilityKnownUnused,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200118 },
119 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100120 name: "valid ID, not in providedMachines",
121 machineID: "unused-machine",
122 machineAvailability: shepherd.AvailabilityPossiblyUsed,
123 wantedAvailability: shepherd.AvailabilityKnownUnused,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200124 },
125 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100126 name: "valid ID, in providedMachines",
127 machineID: providedMachineID,
128 machineAvailability: shepherd.AvailabilityPossiblyUsed,
129 wantedAvailability: shepherd.AvailabilityKnownUsed,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200130 },
131 }
132 for _, tt := range tests {
133 t.Run(tt.name, func(t *testing.T) {
134 p := &Provisioner{}
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100135 if got := p.resolvePossiblyUsed(&dummyMachine{id: tt.machineID, availability: tt.machineAvailability}, providedMachines); got != tt.wantedAvailability {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +0100136 t.Fatalf("resolvePossiblyUsed() = %v, want %v", got, tt.wantedAvailability)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200137 }
138 })
139 }
140}