blob: eba178ca7d69bbc4964b7f09128d04af5e77317e [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
2// SPDX-License-Identifier: Apache-2.0
3
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +02004package manager
5
6import (
7 "context"
8 "testing"
9 "time"
10
11 "golang.org/x/time/rate"
12
13 "source.monogon.dev/cloud/bmaas/bmdb"
14 "source.monogon.dev/cloud/bmaas/bmdb/model"
15 "source.monogon.dev/cloud/lib/component"
16 "source.monogon.dev/cloud/shepherd"
17)
18
19// TestProvisionerSmokes makes sure the Provisioner doesn't go up in flames on
20// the happy path.
21func TestProvisionerSmokes(t *testing.T) {
22 pc := ProvisionerConfig{
23 MaxCount: 10,
24 // We need 3 iterations to provide 10 machines with a chunk size of 4.
25 ReconcileLoopLimiter: rate.NewLimiter(rate.Every(10*time.Second), 3),
26 DeviceCreationLimiter: rate.NewLimiter(rate.Every(time.Second), 10),
27 ChunkSize: 4,
28 }
29
30 provider := newDummyProvider(100)
31
32 p, err := NewProvisioner(provider, pc)
33 if err != nil {
34 t.Fatalf("Could not create Provisioner: %v", err)
35 }
36
37 ctx, ctxC := context.WithCancel(context.Background())
38 defer ctxC()
39
40 b := bmdb.BMDB{
41 Config: bmdb.Config{
42 Database: component.CockroachConfig{
43 InMemory: true,
44 },
45 ComponentName: "test",
46 RuntimeInfo: "test",
47 },
48 }
49 conn, err := b.Open(true)
50 if err != nil {
51 t.Fatalf("Could not create in-memory BMDB: %v", err)
52 }
53
54 go p.Run(ctx, conn)
55
56 sess, err := conn.StartSession(ctx)
57 if err != nil {
58 t.Fatalf("Failed to create BMDB session for verification: %v", err)
59 }
60 for {
61 time.Sleep(100 * time.Millisecond)
62
63 var provided []model.MachineProvided
64 err = sess.Transact(ctx, func(q *model.Queries) error {
65 var err error
66 provided, err = q.GetProvidedMachines(ctx, provider.Type())
67 return err
68 })
69 if err != nil {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010070 t.Fatalf("Transact failed: %v", err)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020071 }
72 if len(provided) < 10 {
73 continue
74 }
75 if len(provided) > 10 {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010076 t.Fatalf("%d machines provided (limit: 10)", len(provided))
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020077 }
78
79 for _, mp := range provided {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010080 provider.muMachines.RLock()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020081 if provider.machines[shepherd.ProviderID(mp.ProviderID)] == nil {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010082 t.Fatalf("BMDB machine %q has unknown provider ID %q", mp.MachineID, mp.ProviderID)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020083 }
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +010084 provider.muMachines.RUnlock()
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020085 }
86
87 return
88 }
89}
90
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +010091// TestProvisioner_resolvePossiblyUsed makes sure the PossiblyUsed availability is
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020092// resolved correctly.
93func TestProvisioner_resolvePossiblyUsed(t *testing.T) {
94 const providedMachineID = "provided-machine"
95
Tim Windelschmidtfdd87ab2023-12-07 18:03:21 +010096 providedMachines := map[shepherd.ProviderID]shepherd.Machine{
97 providedMachineID: nil,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +020098 }
99
100 tests := []struct {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100101 name string
102 machineID shepherd.ProviderID
103 machineAvailability shepherd.Availability
104 wantedAvailability shepherd.Availability
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200105 }{
106 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100107 name: "skip KnownUsed",
108 machineAvailability: shepherd.AvailabilityKnownUsed,
109 wantedAvailability: shepherd.AvailabilityKnownUsed,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200110 },
111 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100112 name: "skip KnownUnused",
113 machineAvailability: shepherd.AvailabilityKnownUnused,
114 wantedAvailability: shepherd.AvailabilityKnownUnused,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200115 },
116 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100117 name: "invalid ID",
118 machineID: shepherd.InvalidProviderID,
119 machineAvailability: shepherd.AvailabilityPossiblyUsed,
120 wantedAvailability: shepherd.AvailabilityKnownUnused,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200121 },
122 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100123 name: "valid ID, not in providedMachines",
124 machineID: "unused-machine",
125 machineAvailability: shepherd.AvailabilityPossiblyUsed,
126 wantedAvailability: shepherd.AvailabilityKnownUnused,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200127 },
128 {
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100129 name: "valid ID, in providedMachines",
130 machineID: providedMachineID,
131 machineAvailability: shepherd.AvailabilityPossiblyUsed,
132 wantedAvailability: shepherd.AvailabilityKnownUsed,
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200133 },
134 }
135 for _, tt := range tests {
136 t.Run(tt.name, func(t *testing.T) {
137 p := &Provisioner{}
Tim Windelschmidtc4dd0032024-02-19 13:13:31 +0100138 if got := p.resolvePossiblyUsed(&dummyMachine{id: tt.machineID, availability: tt.machineAvailability}, providedMachines); got != tt.wantedAvailability {
Tim Windelschmidt8eeae7b2024-12-09 22:52:55 +0100139 t.Fatalf("resolvePossiblyUsed() = %v, want %v", got, tt.wantedAvailability)
Tim Windelschmidtb6308cd2023-10-10 21:19:03 +0200140 }
141 })
142 }
143}