garm/test/integration/organizations_test.go

206 lines
7.5 KiB
Go
Raw Normal View History

2024-06-09 23:06:01 +03:00
//go:build integration
// +build integration
// Copyright 2025 Cloudbase Solutions SRL
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
2024-06-09 23:06:01 +03:00
package integration
import (
"context"
"fmt"
"time"
"github.com/google/go-github/v72/github"
2024-06-09 23:06:01 +03:00
commonParams "github.com/cloudbase/garm-provider-common/params"
"github.com/cloudbase/garm/params"
)
func (suite *GarmSuite) TestOrganizations() {
organization := suite.CreateOrg(orgName, suite.credentialsName, orgWebhookSecret)
org := suite.UpdateOrg(organization.ID, fmt.Sprintf("%s-clone", suite.credentialsName))
suite.NotEqual(organization, org, "organization not updated")
orgHookInfo := suite.InstallOrgWebhook(org.ID)
suite.ValidateOrgWebhookInstalled(suite.ghToken, orgHookInfo.URL, orgName)
suite.UninstallOrgWebhook(org.ID)
suite.ValidateOrgWebhookUninstalled(suite.ghToken, orgHookInfo.URL, orgName)
_ = suite.InstallOrgWebhook(org.ID)
suite.ValidateOrgWebhookInstalled(suite.ghToken, orgHookInfo.URL, orgName)
orgPoolParams := params.CreatePoolParams{
MaxRunners: 2,
MinIdleRunners: 0,
Flavor: "default",
Image: "ubuntu:24.04",
2024-06-09 23:06:01 +03:00
OSType: commonParams.Linux,
OSArch: commonParams.Amd64,
ProviderName: "lxd_local",
Tags: []string{"org-runner"},
Enabled: true,
}
orgPool := suite.CreateOrgPool(org.ID, orgPoolParams)
orgPoolGot := suite.GetOrgPool(org.ID, orgPool.ID)
suite.Equal(orgPool, orgPoolGot, "organization pool mismatch")
suite.DeleteOrgPool(org.ID, orgPool.ID)
orgPool = suite.CreateOrgPool(org.ID, orgPoolParams)
orgPoolUpdated := suite.UpdateOrgPool(org.ID, orgPool.ID, orgPoolParams.MaxRunners, 1)
suite.NotEqual(orgPool, orgPoolUpdated, "organization pool not updated")
suite.WaitOrgRunningIdleInstances(org.ID, 6*time.Minute)
}
func (suite *GarmSuite) CreateOrg(orgName, credentialsName, orgWebhookSecret string) *params.Organization {
t := suite.T()
t.Logf("Create org with org_name %s", orgName)
orgParams := params.CreateOrgParams{
Name: orgName,
CredentialsName: credentialsName,
WebhookSecret: orgWebhookSecret,
}
org, err := createOrg(suite.cli, suite.authToken, orgParams)
suite.NoError(err, "error creating organization")
return org
}
func (suite *GarmSuite) UpdateOrg(id, credentialsName string) *params.Organization {
t := suite.T()
t.Logf("Update org with org_id %s", id)
updateParams := params.UpdateEntityParams{
CredentialsName: credentialsName,
}
org, err := updateOrg(suite.cli, suite.authToken, id, updateParams)
suite.NoError(err, "error updating organization")
return org
}
func (suite *GarmSuite) InstallOrgWebhook(id string) *params.HookInfo {
t := suite.T()
t.Logf("Install org webhook with org_id %s", id)
webhookParams := params.InstallWebhookParams{
WebhookEndpointType: params.WebhookEndpointDirect,
}
_, err := installOrgWebhook(suite.cli, suite.authToken, id, webhookParams)
suite.NoError(err, "error installing organization webhook")
webhookInfo, err := getOrgWebhook(suite.cli, suite.authToken, id)
suite.NoError(err, "error getting organization webhook")
return webhookInfo
}
func (suite *GarmSuite) ValidateOrgWebhookInstalled(ghToken, url, orgName string) {
hook, err := getGhOrgWebhook(url, ghToken, orgName)
suite.NoError(err, "error getting github webhook")
suite.NotNil(hook, "github webhook with url %s, for org %s was not properly installed", url, orgName)
}
func getGhOrgWebhook(url, ghToken, orgName string) (*github.Hook, error) {
client := getGithubClient(ghToken)
ghOrgHooks, _, err := client.Organizations.ListHooks(context.Background(), orgName, nil)
if err != nil {
return nil, err
}
for _, hook := range ghOrgHooks {
hookURL := hook.Config.GetURL()
if hookURL == url {
2024-06-09 23:06:01 +03:00
return hook, nil
}
}
return nil, nil
}
func (suite *GarmSuite) UninstallOrgWebhook(id string) {
t := suite.T()
t.Logf("Uninstall org webhook with org_id %s", id)
err := uninstallOrgWebhook(suite.cli, suite.authToken, id)
suite.NoError(err, "error uninstalling organization webhook")
}
func (suite *GarmSuite) ValidateOrgWebhookUninstalled(ghToken, url, orgName string) {
hook, err := getGhOrgWebhook(url, ghToken, orgName)
suite.NoError(err, "error getting github webhook")
suite.Nil(hook, "github webhook with url %s, for org %s was not properly uninstalled", url, orgName)
}
func (suite *GarmSuite) CreateOrgPool(orgID string, poolParams params.CreatePoolParams) *params.Pool {
t := suite.T()
t.Logf("Create org pool with org_id %s", orgID)
pool, err := createOrgPool(suite.cli, suite.authToken, orgID, poolParams)
suite.NoError(err, "error creating organization pool")
return pool
}
func (suite *GarmSuite) GetOrgPool(orgID, orgPoolID string) *params.Pool {
t := suite.T()
t.Logf("Get org pool with org_id %s and pool_id %s", orgID, orgPoolID)
pool, err := getOrgPool(suite.cli, suite.authToken, orgID, orgPoolID)
suite.NoError(err, "error getting organization pool")
return pool
}
func (suite *GarmSuite) DeleteOrgPool(orgID, orgPoolID string) {
t := suite.T()
t.Logf("Delete org pool with org_id %s and pool_id %s", orgID, orgPoolID)
err := deleteOrgPool(suite.cli, suite.authToken, orgID, orgPoolID)
suite.NoError(err, "error deleting organization pool")
}
func (suite *GarmSuite) UpdateOrgPool(orgID, orgPoolID string, maxRunners, minIdleRunners uint) *params.Pool {
t := suite.T()
t.Logf("Update org pool with org_id %s and pool_id %s", orgID, orgPoolID)
poolParams := params.UpdatePoolParams{
MinIdleRunners: &minIdleRunners,
MaxRunners: &maxRunners,
}
pool, err := updateOrgPool(suite.cli, suite.authToken, orgID, orgPoolID, poolParams)
suite.NoError(err, "error updating organization pool")
return pool
}
func (suite *GarmSuite) WaitOrgRunningIdleInstances(orgID string, timeout time.Duration) {
t := suite.T()
orgPools, err := listOrgPools(suite.cli, suite.authToken, orgID)
suite.NoError(err, "error listing organization pools")
for _, pool := range orgPools {
err := suite.WaitPoolInstances(pool.ID, commonParams.InstanceRunning, params.RunnerIdle, timeout)
if err != nil {
suite.dumpOrgInstancesDetails(orgID)
t.Errorf("timeout waiting for organization %s instances to reach status: %s and runner status: %s", orgID, commonParams.InstanceRunning, params.RunnerIdle)
}
}
}
func (suite *GarmSuite) dumpOrgInstancesDetails(orgID string) {
t := suite.T()
// print org details
t.Logf("Dumping org details with org_id %s", orgID)
org, err := getOrg(suite.cli, suite.authToken, orgID)
suite.NoError(err, "error getting organization")
err = printJSONResponse(org)
suite.NoError(err, "error printing organization")
// print org instances details
t.Logf("Dumping org instances details for org %s", orgID)
instances, err := listOrgInstances(suite.cli, suite.authToken, orgID)
suite.NoError(err, "error listing organization instances")
for _, instance := range instances {
instance, err := getInstance(suite.cli, suite.authToken, instance.Name)
suite.NoError(err, "error getting instance")
t.Logf("Instance info for instace %s", instance.Name)
err = printJSONResponse(instance)
suite.NoError(err, "error printing instance")
}
}