Skip to content

Commit c563ace

Browse files
Add integration tests for test external provider
Signed-off-by: Mihaela Balutoiu <[email protected]>
1 parent d09f12d commit c563ace

File tree

10 files changed

+128
-16
lines changed

10 files changed

+128
-16
lines changed

test/integration/config/config.toml

+8
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ description = "Local LXD installation"
5050
protocol = "simplestreams"
5151
skip_verify = false
5252

53+
[[provider]]
54+
name = "test_external"
55+
description = "external test provider"
56+
provider_type = "external"
57+
[provider.external]
58+
config_file = "/etc/garm/test-provider/config"
59+
provider_executable = "/etc/garm/test-provider/garm-external-provider"
60+
5361
[[github]]
5462
name = "${CREDENTIALS_NAME}"
5563
description = "GARM GitHub OAuth token"

test/integration/e2e/client_utils.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,9 @@ func getInstance(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWrit
387387
return &getInstancesResponse.Payload, nil
388388
}
389389

390-
func deleteInstance(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWriter, instanceID string) error {
390+
func deleteInstance(apiCli *client.GarmAPI, apiAuthToken runtime.ClientAuthInfoWriter, instanceID string, forceRemove bool) error {
391391
return apiCli.Instances.DeleteInstance(
392-
clientInstances.NewDeleteInstanceParams().WithInstanceName(instanceID),
392+
clientInstances.NewDeleteInstanceParams().WithInstanceName(instanceID).WithForceRemove(&forceRemove),
393393
apiAuthToken)
394394
}
395395

test/integration/e2e/e2e.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func GracefulCleanup() {
7272
panic(err)
7373
}
7474
for _, instance := range poolInstances {
75-
if err := deleteInstance(cli, authToken, instance.Name); err != nil {
75+
if err := deleteInstance(cli, authToken, instance.Name, false); err != nil {
7676
panic(err)
7777
}
7878
log.Printf("Instance %s deletion initiated", instance.Name)

test/integration/e2e/instances.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ func waitInstanceStatus(name string, status commonParams.InstanceStatus, runnerS
3333
return nil, fmt.Errorf("timeout waiting for instance %s status to reach status %s and runner status %s", name, status, runnerStatus)
3434
}
3535

36-
func waitInstanceToBeRemoved(name string, timeout time.Duration) error {
36+
func DeleteInstance(name string, forceRemove bool) {
37+
if err := deleteInstance(cli, authToken, name, forceRemove); err != nil {
38+
panic(err)
39+
}
40+
log.Printf("Instance %s deletion initiated", name)
41+
}
42+
43+
func WaitInstanceToBeRemoved(name string, timeout time.Duration) error {
3744
var timeWaited time.Duration = 0
3845
var instance *params.Instance
3946

@@ -67,30 +74,30 @@ func waitInstanceToBeRemoved(name string, timeout time.Duration) error {
6774
return fmt.Errorf("instance %s was not removed within the timeout", name)
6875
}
6976

70-
func waitPoolRunningIdleInstances(poolID string, timeout time.Duration) error {
77+
func WaitPoolInstances(poolID string, status commonParams.InstanceStatus, runnerStatus params.RunnerStatus, timeout time.Duration) error {
7178
var timeWaited time.Duration = 0
7279

7380
pool, err := getPool(cli, authToken, poolID)
7481
if err != nil {
7582
return err
7683
}
7784

78-
log.Printf("Waiting for pool %s to have all instances as idle running", poolID)
85+
log.Printf("Waiting for pool %s instances to reach status: %s and runner status: %s", poolID, status, runnerStatus)
7986
for timeWaited < timeout {
8087
poolInstances, err := listPoolInstances(cli, authToken, poolID)
8188
if err != nil {
8289
return err
8390
}
8491

85-
runningIdleCount := 0
92+
instancesCount := 0
8693
for _, instance := range poolInstances {
87-
if instance.Status == commonParams.InstanceRunning && instance.RunnerStatus == params.RunnerIdle {
88-
runningIdleCount++
94+
if instance.Status == status && instance.RunnerStatus == runnerStatus {
95+
instancesCount++
8996
}
9097
}
9198

92-
log.Printf("Pool min idle runners: %d, pool instances: %d, current pool running idle instances: %d", pool.MinIdleRunners, len(poolInstances), runningIdleCount)
93-
if runningIdleCount == int(pool.MinIdleRunners) && runningIdleCount == len(poolInstances) {
99+
log.Printf("Pool %s instance reached status: %s and runner status: %s: %d/%d", poolID, status, runnerStatus, instancesCount, len(poolInstances))
100+
if instancesCount == int(pool.MinIdleRunners) && instancesCount == len(poolInstances) {
94101
return nil
95102
}
96103
time.Sleep(5 * time.Second)
@@ -99,5 +106,5 @@ func waitPoolRunningIdleInstances(poolID string, timeout time.Duration) error {
99106

100107
_ = dumpPoolInstancesDetails(pool.ID)
101108

102-
return fmt.Errorf("timeout waiting for pool %s to have all idle instances running", poolID)
109+
return fmt.Errorf("timeout waiting for pool %s instances to reach status: %s and runner status: %s", poolID, status, runnerStatus)
103110
}

test/integration/e2e/jobs.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ func ValidateJobLifecycle(label string) {
4141
}
4242

4343
// wait for instance to be removed
44-
err = waitInstanceToBeRemoved(instance.Name, 5*time.Minute)
44+
err = WaitInstanceToBeRemoved(instance.Name, 5*time.Minute)
4545
if err != nil {
4646
panic(err)
4747
}
4848

4949
// wait for GARM to rebuild the pool running idle instances
50-
err = waitPoolRunningIdleInstances(instance.PoolID, 6*time.Minute)
50+
err = WaitPoolInstances(instance.PoolID, commonParams.InstanceRunning, params.RunnerIdle, 5*time.Minute)
5151
if err != nil {
5252
panic(err)
5353
}

test/integration/e2e/organizations.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"log"
55
"time"
66

7+
commonParams "github.com/cloudbase/garm-provider-common/params"
78
"github.com/cloudbase/garm/params"
89
)
910

@@ -100,7 +101,7 @@ func WaitOrgRunningIdleInstances(orgID string, timeout time.Duration) {
100101
panic(err)
101102
}
102103
for _, pool := range orgPools {
103-
err := waitPoolRunningIdleInstances(pool.ID, timeout)
104+
err := WaitPoolInstances(pool.ID, commonParams.InstanceRunning, params.RunnerIdle, timeout)
104105
if err != nil {
105106
_ = dumpOrgInstancesDetails(orgID)
106107
panic(err)

test/integration/e2e/repositories.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"log"
55
"time"
66

7+
commonParams "github.com/cloudbase/garm-provider-common/params"
78
"github.com/cloudbase/garm/params"
89
)
910

@@ -95,13 +96,22 @@ func DeleteRepoPool(repoID, repoPoolID string) {
9596
}
9697
}
9798

99+
func DisableRepoPool(repoID, repoPoolID string) {
100+
log.Printf("Disable repo %s pool %s", repoID, repoPoolID)
101+
enabled := false
102+
poolParams := params.UpdatePoolParams{Enabled: &enabled}
103+
if _, err := updateRepoPool(cli, authToken, repoID, repoPoolID, poolParams); err != nil {
104+
panic(err)
105+
}
106+
}
107+
98108
func WaitRepoRunningIdleInstances(repoID string, timeout time.Duration) {
99109
repoPools, err := listRepoPools(cli, authToken, repoID)
100110
if err != nil {
101111
panic(err)
102112
}
103113
for _, pool := range repoPools {
104-
err := waitPoolRunningIdleInstances(pool.ID, timeout)
114+
err := WaitPoolInstances(pool.ID, commonParams.InstanceRunning, params.RunnerIdle, timeout)
105115
if err != nil {
106116
_ = dumpRepoInstancesDetails(repoID)
107117
panic(err)

test/integration/main.go

+25
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ var (
3434
Tags: []string{"repo-runner"},
3535
Enabled: true,
3636
}
37+
repoPoolParams2 = params.CreatePoolParams{
38+
MaxRunners: 2,
39+
MinIdleRunners: 0,
40+
Flavor: "default",
41+
Image: "ubuntu:22.04",
42+
OSType: commonParams.Linux,
43+
OSArch: commonParams.Amd64,
44+
ProviderName: "test_external",
45+
Tags: []string{"repo-runner-2"},
46+
Enabled: true,
47+
}
3748

3849
orgName = os.Getenv("ORG_NAME")
3950
orgWebhookSecret = os.Getenv("ORG_WEBHOOK_SECRET")
@@ -101,6 +112,20 @@ func main() {
101112
repoPool = e2e.CreateRepoPool(repo.ID, repoPoolParams)
102113
_ = e2e.UpdateRepoPool(repo.ID, repoPool.ID, repoPoolParams.MaxRunners, 1)
103114

115+
/////////////////////////////
116+
// Test external provider ///
117+
/////////////////////////////
118+
repoPool2 := e2e.CreateRepoPool(repo.ID, repoPoolParams2)
119+
_ = e2e.UpdateRepoPool(repo.ID, repoPool2.ID, repoPoolParams2.MaxRunners, 1)
120+
e2e.WaitPoolInstances(repoPool2.ID, commonParams.InstanceRunning, params.RunnerPending, 1*time.Minute)
121+
repoPool2 = e2e.GetRepoPool(repo.ID, repoPool2.ID)
122+
e2e.DisableRepoPool(repo.ID, repoPool2.ID)
123+
e2e.DeleteInstance(repoPool2.Instances[0].Name, false)
124+
e2e.WaitPoolInstances(repoPool2.ID, commonParams.InstancePendingDelete, params.RunnerPending, 1*time.Minute)
125+
e2e.DeleteInstance(repoPool2.Instances[0].Name, true) // delete instance with forceRemove
126+
e2e.WaitInstanceToBeRemoved(repoPool2.Instances[0].Name, 1*time.Minute)
127+
e2e.DeleteRepoPool(repo.ID, repoPool2.ID)
128+
104129
///////////////////
105130
// organizations //
106131
///////////////////
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -o pipefail
5+
6+
if [ ! -t 0 ]
7+
then
8+
INPUT=$(cat -)
9+
fi
10+
11+
if [ -z "$GARM_PROVIDER_CONFIG_FILE" ]
12+
then
13+
echo "no config file specified in env"
14+
exit 1
15+
fi
16+
17+
source "$GARM_PROVIDER_CONFIG_FILE"
18+
19+
function CreateInstance() {
20+
if [ -z "$INPUT" ]; then
21+
echo "expected build params in stdin"
22+
exit 1
23+
fi
24+
25+
jq -rnc '{"provider_id": "test-provider-id", "name": "test-instance-name", "os_type": "linux", "os_name": "ubuntu", "os_version": "20.04", "os_arch": "x86_64", "status": "running"}'
26+
}
27+
28+
case "$GARM_COMMAND" in
29+
"CreateInstance")
30+
CreateInstance
31+
;;
32+
"DeleteInstance")
33+
echo "RemoveAllInstances not implemented"
34+
exit 1
35+
;;
36+
"GetInstance")
37+
echo "Get instance with id: ${GARM_INSTANCE_ID}"
38+
;;
39+
"ListInstances")
40+
echo "List instances with pool id: ${GARM_POOL_ID}"
41+
;;
42+
"StartInstance")
43+
echo "Start instance: ${GARM_INSTANCE_NAME} with id: ${GARM_INSTANCE_ID}"
44+
;;
45+
"StopInstance")
46+
echo "Stop instance: ${GARM_INSTANCE_NAME} with id: ${GARM_INSTANCE_ID}"
47+
;;
48+
"RemoveAllInstances")
49+
echo "RemoveAllInstances not implemented"
50+
exit 1
51+
;;
52+
*)
53+
echo "Invalid GARM provider command: \"$GARM_COMMAND\""
54+
exit 1
55+
;;
56+
esac

test/integration/scripts/setup-garm.sh

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ DIR="$(dirname $0)"
55
BINARIES_DIR="$PWD/bin"
66
CONTRIB_DIR="$PWD/contrib"
77
CONFIG_DIR="$PWD/test/integration/config"
8+
CONFIG_DIR_PROV="$PWD/test/integration/provider"
89

910
if [[ ! -f $BINARIES_DIR/garm ]] || [[ ! -f $BINARIES_DIR/garm-cli ]]; then
1011
echo "ERROR: Please build GARM binaries first"
@@ -46,6 +47,10 @@ sudo mkdir -p /etc/garm
4647
cat $CONFIG_DIR/config.toml | envsubst | sudo tee /etc/garm/config.toml
4748
sudo chown -R garm:garm /etc/garm
4849

50+
sudo mkdir /etc/garm/test-provider
51+
sudo touch $CONFIG_DIR_PROV/config
52+
sudo cp $CONFIG_DIR_PROV/* /etc/garm/test-provider
53+
4954
sudo mv $BINARIES_DIR/* /usr/local/bin/
5055
sudo cp $CONTRIB_DIR/garm.service /etc/systemd/system/garm.service
5156

0 commit comments

Comments
 (0)