Skip to content

Commit 9cc94cc

Browse files
Add db scaleset tests
Signed-off-by: Gabriel Adrian Samfira <[email protected]>
1 parent e51b14b commit 9cc94cc

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed

database/sql/pools_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ func (s *PoolsTestSuite) TestListEntityInstances() {
331331
s.Require().Len(instances, 1)
332332
s.Require().Equal(instance.ID, instances[0].ID)
333333
s.Require().Equal(instance.Name, instances[0].Name)
334+
s.Require().Equal(instance.ProviderName, pool.ProviderName)
334335
}
335336

336337
func TestPoolsTestSuite(t *testing.T) {

database/sql/scalesets_test.go

+352
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
package sql
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"testing"
8+
9+
commonParams "github.com/cloudbase/garm-provider-common/params"
10+
11+
dbCommon "github.com/cloudbase/garm/database/common"
12+
"github.com/cloudbase/garm/database/watcher"
13+
garmTesting "github.com/cloudbase/garm/internal/testing"
14+
"github.com/cloudbase/garm/params"
15+
"github.com/stretchr/testify/suite"
16+
)
17+
18+
type ScaleSetsTestSuite struct {
19+
suite.Suite
20+
Store dbCommon.Store
21+
adminCtx context.Context
22+
creds params.GithubCredentials
23+
24+
org params.Organization
25+
repo params.Repository
26+
enterprise params.Enterprise
27+
28+
orgEntity params.GithubEntity
29+
repoEntity params.GithubEntity
30+
enterpriseEntity params.GithubEntity
31+
}
32+
33+
func (s *ScaleSetsTestSuite) SetupTest() {
34+
// create testing sqlite database
35+
ctx := context.Background()
36+
watcher.InitWatcher(ctx)
37+
38+
db, err := NewSQLDatabase(context.Background(), garmTesting.GetTestSqliteDBConfig(s.T()))
39+
if err != nil {
40+
s.FailNow(fmt.Sprintf("failed to create db connection: %s", err))
41+
}
42+
s.Store = db
43+
44+
adminCtx := garmTesting.ImpersonateAdminContext(ctx, db, s.T())
45+
s.adminCtx = adminCtx
46+
47+
githubEndpoint := garmTesting.CreateDefaultGithubEndpoint(adminCtx, db, s.T())
48+
s.creds = garmTesting.CreateTestGithubCredentials(adminCtx, "new-creds", db, s.T(), githubEndpoint)
49+
50+
// create an organization for testing purposes
51+
s.org, err = s.Store.CreateOrganization(s.adminCtx, "test-org", s.creds.Name, "test-webhookSecret", params.PoolBalancerTypeRoundRobin)
52+
if err != nil {
53+
s.FailNow(fmt.Sprintf("failed to create org: %s", err))
54+
}
55+
56+
s.repo, err = s.Store.CreateRepository(s.adminCtx, "test-org", "test-repo", s.creds.Name, "test-webhookSecret", params.PoolBalancerTypeRoundRobin)
57+
if err != nil {
58+
s.FailNow(fmt.Sprintf("failed to create repo: %s", err))
59+
}
60+
61+
s.enterprise, err = s.Store.CreateEnterprise(s.adminCtx, "test-enterprise", s.creds.Name, "test-webhookSecret", params.PoolBalancerTypeRoundRobin)
62+
if err != nil {
63+
s.FailNow(fmt.Sprintf("failed to create enterprise: %s", err))
64+
}
65+
66+
s.orgEntity, err = s.org.GetEntity()
67+
if err != nil {
68+
s.FailNow(fmt.Sprintf("failed to get org entity: %s", err))
69+
}
70+
71+
s.repoEntity, err = s.repo.GetEntity()
72+
if err != nil {
73+
s.FailNow(fmt.Sprintf("failed to get repo entity: %s", err))
74+
}
75+
76+
s.enterpriseEntity, err = s.enterprise.GetEntity()
77+
if err != nil {
78+
s.FailNow(fmt.Sprintf("failed to get enterprise entity: %s", err))
79+
}
80+
81+
s.T().Cleanup(func() {
82+
err := s.Store.DeleteOrganization(s.adminCtx, s.org.ID)
83+
if err != nil {
84+
s.FailNow(fmt.Sprintf("failed to delete org: %s", err))
85+
}
86+
err = s.Store.DeleteRepository(s.adminCtx, s.repo.ID)
87+
if err != nil {
88+
s.FailNow(fmt.Sprintf("failed to delete repo: %s", err))
89+
}
90+
err = s.Store.DeleteEnterprise(s.adminCtx, s.enterprise.ID)
91+
if err != nil {
92+
s.FailNow(fmt.Sprintf("failed to delete enterprise: %s", err))
93+
}
94+
})
95+
}
96+
97+
func (s *ScaleSetsTestSuite) callback(old, newSet params.ScaleSet) error {
98+
s.Require().Equal(old.Name, "test-scaleset")
99+
s.Require().Equal(newSet.Name, "test-scaleset-updated")
100+
s.Require().Equal(old.OSType, commonParams.Linux)
101+
s.Require().Equal(newSet.OSType, commonParams.Windows)
102+
s.Require().Equal(old.OSArch, commonParams.Amd64)
103+
s.Require().Equal(newSet.OSArch, commonParams.Arm64)
104+
s.Require().Equal(old.ExtraSpecs, json.RawMessage(`{"test": 1}`))
105+
s.Require().Equal(newSet.ExtraSpecs, json.RawMessage(`{"test": 111}`))
106+
s.Require().Equal(old.MaxRunners, uint(10))
107+
s.Require().Equal(newSet.MaxRunners, uint(60))
108+
s.Require().Equal(old.MinIdleRunners, uint(5))
109+
s.Require().Equal(newSet.MinIdleRunners, uint(50))
110+
s.Require().Equal(old.Image, "test-image")
111+
s.Require().Equal(newSet.Image, "new-test-image")
112+
s.Require().Equal(old.Flavor, "test-flavor")
113+
s.Require().Equal(newSet.Flavor, "new-test-flavor")
114+
s.Require().Equal(old.GitHubRunnerGroup, "test-group")
115+
s.Require().Equal(newSet.GitHubRunnerGroup, "new-test-group")
116+
s.Require().Equal(old.RunnerPrefix.Prefix, "garm")
117+
s.Require().Equal(newSet.RunnerPrefix.Prefix, "test-prefix2")
118+
s.Require().Equal(old.Enabled, false)
119+
s.Require().Equal(newSet.Enabled, true)
120+
return nil
121+
}
122+
123+
func (s *ScaleSetsTestSuite) TestScaleSetOperations() {
124+
// create a scale set for the organization
125+
createScaleSetPrams := params.CreateScaleSetParams{
126+
Name: "test-scaleset",
127+
ProviderName: "test-provider",
128+
MaxRunners: 10,
129+
MinIdleRunners: 5,
130+
Image: "test-image",
131+
Flavor: "test-flavor",
132+
OSType: commonParams.Linux,
133+
OSArch: commonParams.Amd64,
134+
ExtraSpecs: json.RawMessage(`{"test": 1}`),
135+
GitHubRunnerGroup: "test-group",
136+
}
137+
138+
var orgScaleSet params.ScaleSet
139+
var repoScaleSet params.ScaleSet
140+
var enterpriseScaleSet params.ScaleSet
141+
var err error
142+
143+
s.T().Run("create org scaleset", func(t *testing.T) {
144+
orgScaleSet, err = s.Store.CreateEntityScaleSet(s.adminCtx, s.orgEntity, createScaleSetPrams)
145+
s.Require().NoError(err)
146+
s.Require().NotNil(orgScaleSet)
147+
s.Require().Equal(orgScaleSet.Name, createScaleSetPrams.Name)
148+
s.T().Cleanup(func() {
149+
err := s.Store.DeleteScaleSetByID(s.adminCtx, orgScaleSet.ID)
150+
if err != nil {
151+
s.FailNow(fmt.Sprintf("failed to delete scaleset: %s", err))
152+
}
153+
})
154+
155+
})
156+
157+
s.T().Run("create repo scaleset", func(t *testing.T) {
158+
repoScaleSet, err = s.Store.CreateEntityScaleSet(s.adminCtx, s.repoEntity, createScaleSetPrams)
159+
s.Require().NoError(err)
160+
s.Require().NotNil(repoScaleSet)
161+
s.Require().Equal(repoScaleSet.Name, createScaleSetPrams.Name)
162+
s.T().Cleanup(func() {
163+
err := s.Store.DeleteScaleSetByID(s.adminCtx, repoScaleSet.ID)
164+
if err != nil {
165+
s.FailNow(fmt.Sprintf("failed to delete scaleset: %s", err))
166+
}
167+
})
168+
})
169+
170+
s.T().Run("create enterprise scaleset", func(t *testing.T) {
171+
enterpriseScaleSet, err = s.Store.CreateEntityScaleSet(s.adminCtx, s.enterpriseEntity, createScaleSetPrams)
172+
s.Require().NoError(err)
173+
s.Require().NotNil(enterpriseScaleSet)
174+
s.Require().Equal(enterpriseScaleSet.Name, createScaleSetPrams.Name)
175+
176+
s.T().Cleanup(func() {
177+
err := s.Store.DeleteScaleSetByID(s.adminCtx, enterpriseScaleSet.ID)
178+
if err != nil {
179+
s.FailNow(fmt.Sprintf("failed to delete scaleset: %s", err))
180+
}
181+
})
182+
})
183+
184+
s.T().Run("create list all scalesets", func(t *testing.T) {
185+
allScaleSets, err := s.Store.ListAllScaleSets(s.adminCtx)
186+
s.Require().NoError(err)
187+
s.Require().NotEmpty(allScaleSets)
188+
s.Require().Len(allScaleSets, 3)
189+
})
190+
191+
s.T().Run("list repo scalesets", func(t *testing.T) {
192+
repoScaleSets, err := s.Store.ListEntityScaleSets(s.adminCtx, s.repoEntity)
193+
s.Require().NoError(err)
194+
s.Require().NotEmpty(repoScaleSets)
195+
s.Require().Len(repoScaleSets, 1)
196+
})
197+
198+
s.T().Run("list org scalesets", func(t *testing.T) {
199+
orgScaleSets, err := s.Store.ListEntityScaleSets(s.adminCtx, s.orgEntity)
200+
s.Require().NoError(err)
201+
s.Require().NotEmpty(orgScaleSets)
202+
s.Require().Len(orgScaleSets, 1)
203+
})
204+
205+
s.T().Run("list enterprise scalesets", func(t *testing.T) {
206+
enterpriseScaleSets, err := s.Store.ListEntityScaleSets(s.adminCtx, s.enterpriseEntity)
207+
s.Require().NoError(err)
208+
s.Require().NotEmpty(enterpriseScaleSets)
209+
s.Require().Len(enterpriseScaleSets, 1)
210+
})
211+
212+
s.T().Run("get repo scaleset by ID", func(t *testing.T) {
213+
repoScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, repoScaleSet.ID)
214+
s.Require().NoError(err)
215+
s.Require().NotNil(repoScaleSetByID)
216+
s.Require().Equal(repoScaleSetByID.ID, repoScaleSet.ID)
217+
s.Require().Equal(repoScaleSetByID.Name, repoScaleSet.Name)
218+
})
219+
220+
s.T().Run("get org scaleset by ID", func(t *testing.T) {
221+
orgScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, orgScaleSet.ID)
222+
s.Require().NoError(err)
223+
s.Require().NotNil(orgScaleSetByID)
224+
s.Require().Equal(orgScaleSetByID.ID, orgScaleSet.ID)
225+
s.Require().Equal(orgScaleSetByID.Name, orgScaleSet.Name)
226+
})
227+
228+
s.T().Run("get enterprise scaleset by ID", func(t *testing.T) {
229+
enterpriseScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, enterpriseScaleSet.ID)
230+
s.Require().NoError(err)
231+
s.Require().NotNil(enterpriseScaleSetByID)
232+
s.Require().Equal(enterpriseScaleSetByID.ID, enterpriseScaleSet.ID)
233+
s.Require().Equal(enterpriseScaleSetByID.Name, enterpriseScaleSet.Name)
234+
})
235+
236+
s.T().Run("get scaleset by ID not found", func(t *testing.T) {
237+
_, err = s.Store.GetScaleSetByID(s.adminCtx, 999)
238+
s.Require().Error(err)
239+
s.Require().Contains(err.Error(), "not found")
240+
})
241+
242+
s.T().Run("Set scale set last message ID and desired count", func(t *testing.T) {
243+
err = s.Store.SetScaleSetLastMessageID(s.adminCtx, orgScaleSet.ID, 20)
244+
s.Require().NoError(err)
245+
err = s.Store.SetScaleSetDesiredRunnerCount(s.adminCtx, orgScaleSet.ID, 5)
246+
s.Require().NoError(err)
247+
orgScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, orgScaleSet.ID)
248+
s.Require().NoError(err)
249+
s.Require().NotNil(orgScaleSetByID)
250+
s.Require().Equal(orgScaleSetByID.LastMessageID, int64(20))
251+
s.Require().Equal(orgScaleSetByID.DesiredRunnerCount, 5)
252+
})
253+
254+
updateParams := params.UpdateScaleSetParams{
255+
Name: "test-scaleset-updated",
256+
RunnerPrefix: params.RunnerPrefix{
257+
Prefix: "test-prefix2",
258+
},
259+
OSType: commonParams.Windows,
260+
OSArch: commonParams.Arm64,
261+
ExtraSpecs: json.RawMessage(`{"test": 111}`),
262+
Enabled: garmTesting.Ptr(true),
263+
MaxRunners: garmTesting.Ptr(uint(60)),
264+
MinIdleRunners: garmTesting.Ptr(uint(50)),
265+
Image: "new-test-image",
266+
Flavor: "new-test-flavor",
267+
GitHubRunnerGroup: garmTesting.Ptr("new-test-group"),
268+
}
269+
270+
s.T().Run("update repo scaleset", func(t *testing.T) {
271+
newRepoScaleSet, err := s.Store.UpdateEntityScaleSet(s.adminCtx, s.repoEntity, repoScaleSet.ID, updateParams, s.callback)
272+
s.Require().NoError(err)
273+
s.Require().NotNil(newRepoScaleSet)
274+
s.Require().NoError(s.callback(repoScaleSet, newRepoScaleSet))
275+
})
276+
277+
s.T().Run("update org scaleset", func(t *testing.T) {
278+
newOrgScaleSet, err := s.Store.UpdateEntityScaleSet(s.adminCtx, s.orgEntity, orgScaleSet.ID, updateParams, s.callback)
279+
s.Require().NoError(err)
280+
s.Require().NotNil(newOrgScaleSet)
281+
s.Require().NoError(s.callback(orgScaleSet, newOrgScaleSet))
282+
})
283+
284+
s.T().Run("update enterprise scaleset", func(t *testing.T) {
285+
newEnterpriseScaleSet, err := s.Store.UpdateEntityScaleSet(s.adminCtx, s.enterpriseEntity, enterpriseScaleSet.ID, updateParams, s.callback)
286+
s.Require().NoError(err)
287+
s.Require().NotNil(newEnterpriseScaleSet)
288+
s.Require().NoError(s.callback(enterpriseScaleSet, newEnterpriseScaleSet))
289+
})
290+
291+
s.T().Run("update scaleset not found", func(t *testing.T) {
292+
_, err = s.Store.UpdateEntityScaleSet(s.adminCtx, s.enterpriseEntity, 99999, updateParams, s.callback)
293+
s.Require().Error(err)
294+
s.Require().Contains(err.Error(), "not found")
295+
})
296+
297+
s.T().Run("update scaleset with invalid entity", func(t *testing.T) {
298+
_, err = s.Store.UpdateEntityScaleSet(s.adminCtx, params.GithubEntity{}, enterpriseScaleSet.ID, params.UpdateScaleSetParams{}, nil)
299+
s.Require().Error(err)
300+
s.Require().Contains(err.Error(), "missing entity id")
301+
})
302+
303+
s.T().Run("Create repo scale set instance", func(t *testing.T) {
304+
param := params.CreateInstanceParams{
305+
Name: "test-instance",
306+
Status: commonParams.InstancePendingCreate,
307+
RunnerStatus: params.RunnerPending,
308+
OSType: commonParams.Linux,
309+
OSArch: commonParams.Amd64,
310+
CallbackURL: "http://localhost:8080/callback",
311+
MetadataURL: "http://localhost:8080/metadata",
312+
GitHubRunnerGroup: "test-group",
313+
JitConfiguration: map[string]string{
314+
"test": "test",
315+
},
316+
AgentID: 5,
317+
}
318+
319+
instance, err := s.Store.CreateScaleSetInstance(s.adminCtx, repoScaleSet.ID, param)
320+
s.Require().NoError(err)
321+
s.Require().NotNil(instance)
322+
s.Require().Equal(instance.Name, param.Name)
323+
s.Require().Equal(instance.Status, param.Status)
324+
s.Require().Equal(instance.RunnerStatus, param.RunnerStatus)
325+
s.Require().Equal(instance.OSType, param.OSType)
326+
s.Require().Equal(instance.OSArch, param.OSArch)
327+
s.Require().Equal(instance.CallbackURL, param.CallbackURL)
328+
s.Require().Equal(instance.MetadataURL, param.MetadataURL)
329+
s.Require().Equal(instance.GitHubRunnerGroup, param.GitHubRunnerGroup)
330+
s.Require().Equal(instance.JitConfiguration, param.JitConfiguration)
331+
s.Require().Equal(instance.AgentID, param.AgentID)
332+
333+
s.T().Cleanup(func() {
334+
err := s.Store.DeleteInstanceByName(s.adminCtx, instance.Name)
335+
if err != nil {
336+
s.FailNow(fmt.Sprintf("failed to delete scaleset instance: %s", err))
337+
}
338+
})
339+
})
340+
341+
s.T().Run("List repo scale set instances", func(t *testing.T) {
342+
instances, err := s.Store.ListScaleSetInstances(s.adminCtx, repoScaleSet.ID)
343+
s.Require().NoError(err)
344+
s.Require().NotEmpty(instances)
345+
s.Require().Len(instances, 1)
346+
})
347+
}
348+
349+
func TestScaleSetsTestSuite(t *testing.T) {
350+
t.Parallel()
351+
suite.Run(t, new(ScaleSetsTestSuite))
352+
}

0 commit comments

Comments
 (0)