From 1eca0c73ac1abbcf9e1317ceff2c70017af5776f Mon Sep 17 00:00:00 2001 From: Mihaela Balutoiu Date: Fri, 28 Jul 2023 16:05:35 +0300 Subject: [PATCH] testing --- .github/workflows/integration-tests.yml | 77 +- integration/e2e.go | 1339 +++++++++++++++++++++++ 2 files changed, 1363 insertions(+), 53 deletions(-) create mode 100644 integration/e2e.go diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 79f1da77..b5d0a811 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -2,13 +2,10 @@ name: Integration Tests on: push: branches: - - main - pull_request: - branches: - - main + - test-e2e-wip jobs: - garm-cli-test: + integration-tests: runs-on: ubuntu-latest steps: - name: Checkout @@ -30,9 +27,6 @@ jobs: - name: Setup GARM server shell: bash run: | - set -e - set -o pipefail - sudo useradd --shell /usr/bin/false --system --groups lxd --no-create-home garm sudo mkdir -p /etc/garm /var/log/garm @@ -93,6 +87,16 @@ jobs: public = true protocol = "simplestreams" skip_verify = false + + [[github]] + name = "mihaelabalutoiu" + description = "github token of user mihaelabalutoiu" + oauth2_token = "${{ secrets.AUTH2_TOKEN_SECRETS }}" + + [[github]] + name = "mihaelabalutoiu-clone" + description = "github token of user mihaelabalutoiu-clone" + oauth2_token = "${{ secrets.AUTH2_TOKEN_SECRETS }}" EOF sudo mv config.toml /etc/garm/config.toml sudo chown -R garm:garm /etc/garm /var/log/garm @@ -120,53 +124,20 @@ jobs: wait_open_port 127.0.0.1 9997 - - name: Test GARM API with garm-cli tool + - name: Run integration tests shell: bash run: | - set -e - set -x - set -o pipefail - - GARM_URL="http://127.0.0.1:9997" - ADMIN_USERNAME='admin' - ADMIN_PASWORD='Ma*jirksiCr9esrT8DGQPrfx*XKnBVZo' - - garm-cli init --debug \ - --name="local_garm" \ - --url $GARM_URL \ - --email root@localhost \ - --username $ADMIN_USERNAME \ - --password $ADMIN_PASWORD - - garm-cli profile add --debug \ - --name="local_garm_2" \ - --url $GARM_URL \ - --username $ADMIN_USERNAME \ - --password $ADMIN_PASWORD - - garm-cli profile login --debug \ - --username $ADMIN_USERNAME \ - --password $ADMIN_PASWORD - - garm-cli metrics-token --debug create - - garm-cli provider --debug list - - garm-cli profile --debug list - - garm-cli runner --debug list --all - - garm-cli credentials --debug list - - garm-cli job --debug list - - garm-cli org --debug list - - garm-cli repo --debug list - - garm-cli enterprise --debug list - - garm-cli pool --debug list --all + export GARM_BASE_URL="http://127.0.0.1:9997" + export GARM_USERNAME='admin' + export GARM_PASSWORD='~Cxe3+Qf;KO~2!I>> Login") + loginParams := params.PasswordLoginParams{ + Username: username, + Password: password, + } + token, err := login(cli, loginParams) + handleError(err) + printResponse(token) + authToken = openapiRuntimeClient.BearerToken(token) + cfg.Managers = []config.Manager{ + { + Name: name, + BaseURL: baseURL, + Token: token, + }, + } + cfg.ActiveManager = name + err = cfg.SaveConfig() + handleError(err) +} + +func FirstRun() { + existingCfg, err := config.LoadConfig() + handleError(err) + if existingCfg != nil { + if existingCfg.HasManager(name) { + log.Println(">>> Already initialized") + return + } + } + + log.Println(">>> First run") + newUser := params.NewUserParams{ + Username: username, + Password: password, + FullName: fullName, + Email: email, + } + user, err := firstRun(cli, newUser) + handleError(err) + printResponse(user) +} + +// //////////////////////////// +// Credentials and Providers // +// //////////////////////////// +func ListCredentials() { + log.Println(">>> List credentials") + credentials, err := listCredentials(cli, authToken) + handleError(err) + printResponse(credentials) +} + +func ListProviders() { + log.Println(">>> List providers") + providers, err := listProviders(cli, authToken) + handleError(err) + printResponse(providers) +} + +// //////// +// Jobs // +// //////// +func ListJobs() { + log.Println(">>> List jobs") + jobs, err := listJobs(cli, authToken) + handleError(err) + printResponse(jobs) +} + +// ////////////////// +// / Metrics Token // +// ////////////////// +func GetMetricsToken() { + log.Println(">>> Get metrics token") + token, err := getMetricsToken(cli, authToken) + handleError(err) + printResponse(token) +} + +// /////////////// +// Repositories // +// /////////////// +func CreateRepo() { + repos, err := listRepos(cli, authToken) + handleError(err) + if len(repos) > 0 { + log.Println(">>> Repo already exists, skipping create") + repoID = repos[0].ID + return + } + log.Println(">>> Create repo") + createParams := params.CreateRepoParams{ + Owner: orgName, + Name: repoName, + CredentialsName: credentialsName, + WebhookSecret: repoWebhookSecret, + } + repo, err := createRepo(cli, authToken, createParams) + handleError(err) + printResponse(repo) + repoID = repo.ID +} + +func ListRepos() { + log.Println(">>> List repos") + repos, err := listRepos(cli, authToken) + handleError(err) + printResponse(repos) +} + +func UpdateRepo() { + log.Println(">>> Update repo") + updateParams := params.UpdateEntityParams{ + CredentialsName: fmt.Sprintf("%s-clone", credentialsName), + } + repo, err := updateRepo(cli, authToken, repoID, updateParams) + handleError(err) + printResponse(repo) +} + +func GetRepo() { + log.Println(">>> Get repo") + repo, err := getRepo(cli, authToken, repoID) + handleError(err) + printResponse(repo) +} + +func CreateRepoPool() { + pools, err := listRepoPools(cli, authToken, repoID) + handleError(err) + if len(pools) > 0 { + log.Println(">>> Repo pool already exists, skipping create") + repoPoolID = pools[0].ID + return + } + log.Println(">>> Create repo pool") + poolParams := params.CreatePoolParams{ + MaxRunners: 2, + MinIdleRunners: 0, + Flavor: "garm", + Image: "ubuntu:22.04", + OSType: commonParams.Linux, + OSArch: commonParams.Amd64, + ProviderName: "lxd_local", + Tags: []string{"ubuntu", "simple-runner"}, + Enabled: true, + } + repo, err := createRepoPool(cli, authToken, repoID, poolParams) + handleError(err) + printResponse(repo) + repoPoolID = repo.ID +} + +func ListRepoPools() { + log.Println(">>> List repo pools") + pools, err := listRepoPools(cli, authToken, repoID) + handleError(err) + printResponse(pools) +} + +func GetRepoPool() { + log.Println(">>> Get repo pool") + pool, err := getRepoPool(cli, authToken, repoID, repoPoolID) + handleError(err) + printResponse(pool) +} + +func UpdateRepoPool() { + log.Println(">>> Update repo pool") + var maxRunners uint = 5 + var idleRunners uint = 1 + poolParams := params.UpdatePoolParams{ + MinIdleRunners: &idleRunners, + MaxRunners: &maxRunners, + } + pool, err := updateRepoPool(cli, authToken, repoID, repoPoolID, poolParams) + handleError(err) + printResponse(pool) +} + +func DisableRepoPool() { + enabled := false + _, err := updateRepoPool(cli, authToken, repoID, repoPoolID, params.UpdatePoolParams{Enabled: &enabled}) + handleError(err) + log.Printf("repo pool %s disabled", repoPoolID) +} + +func WaitRepoPoolNoInstances() { + for { + log.Println(">>> Wait until repo pool has no instances") + pool, err := getRepoPool(cli, authToken, repoID, repoPoolID) + handleError(err) + if len(pool.Instances) == 0 { + break + } + time.Sleep(5 * time.Second) + } +} + +func WaitRepoInstance() { + log.Println(">>> Wait until repo instance is in running state") + for { + instances, err := listRepoInstances(cli, authToken, repoID) + handleError(err) + if len(instances) > 0 { + instance := instances[0] + log.Printf("instance %s status: %s", instance.Name, instance.Status) + if instance.Status == commonParams.InstanceRunning && instance.RunnerStatus == params.RunnerIdle { + repoInstanceName = instance.Name + break + } + } + time.Sleep(5 * time.Second) + } +} + +func ListRepoInstances() { + log.Println(">>> List repo instances") + instances, err := listRepoInstances(cli, authToken, repoID) + handleError(err) + printResponse(instances) +} + +func DeleteRepo() { + log.Println(">>> Delete repo") + err := deleteRepo(cli, authToken, repoID) + handleError(err) + log.Printf("repo %s deleted", repoID) +} + +func DeleteRepoPool() { + log.Println(">>> Delete repo pool") + err := deleteRepoPool(cli, authToken, repoID, repoPoolID) + handleError(err) + log.Printf("repo pool %s deleted", repoPoolID) +} + +// //////////////// +// Organizations // +// //////////////// +func CreateOrg() { + orgs, err := listOrgs(cli, authToken) + handleError(err) + if len(orgs) > 0 { + log.Println(">>> Org already exists, skipping create") + orgID = orgs[0].ID + return + } + log.Println(">>> Create org") + orgParams := params.CreateOrgParams{ + Name: orgName, + CredentialsName: credentialsName, + WebhookSecret: orgWebhookSecret, + } + org, err := createOrg(cli, authToken, orgParams) + handleError(err) + printResponse(org) + orgID = org.ID +} + +func ListOrgs() { + log.Println(">>> List orgs") + orgs, err := listOrgs(cli, authToken) + handleError(err) + printResponse(orgs) +} + +func UpdateOrg() { + log.Println(">>> Update org") + updateParams := params.UpdateEntityParams{ + CredentialsName: fmt.Sprintf("%s-clone", credentialsName), + } + org, err := updateOrg(cli, authToken, orgID, updateParams) + handleError(err) + printResponse(org) +} + +func GetOrg() { + log.Println(">>> Get org") + org, err := getOrg(cli, authToken, orgID) + handleError(err) + printResponse(org) +} + +func CreateOrgPool() { + pools, err := listOrgPools(cli, authToken, orgID) + handleError(err) + if len(pools) > 0 { + log.Println(">>> Org pool already exists, skipping create") + orgPoolID = pools[0].ID + return + } + log.Println(">>> Create org pool") + poolParams := params.CreatePoolParams{ + MaxRunners: 2, + MinIdleRunners: 0, + Flavor: "garm", + Image: "ubuntu:22.04", + OSType: commonParams.Linux, + OSArch: commonParams.Amd64, + ProviderName: "lxd_local", + Tags: []string{"ubuntu", "simple-runner"}, + Enabled: true, + } + org, err := createOrgPool(cli, authToken, orgID, poolParams) + handleError(err) + printResponse(org) + orgPoolID = org.ID +} + +func ListOrgPools() { + log.Println(">>> List org pools") + pools, err := listOrgPools(cli, authToken, orgID) + handleError(err) + printResponse(pools) +} + +func GetOrgPool() { + log.Println(">>> Get org pool") + pool, err := getOrgPool(cli, authToken, orgID, orgPoolID) + handleError(err) + printResponse(pool) +} + +func UpdateOrgPool() { + log.Println(">>> Update org pool") + var maxRunners uint = 5 + var idleRunners uint = 1 + poolParams := params.UpdatePoolParams{ + MinIdleRunners: &idleRunners, + MaxRunners: &maxRunners, + } + pool, err := updateOrgPool(cli, authToken, orgID, orgPoolID, poolParams) + handleError(err) + printResponse(pool) +} + +func DisableOrgPool() { + enabled := false + _, err := updateOrgPool(cli, authToken, orgID, orgPoolID, params.UpdatePoolParams{Enabled: &enabled}) + handleError(err) + log.Printf("org pool %s disabled", orgPoolID) +} + +func WaitOrgPoolNoInstances() { + for { + log.Println(">>> Wait until org pool has no instances") + pool, err := getOrgPool(cli, authToken, orgID, orgPoolID) + handleError(err) + if len(pool.Instances) == 0 { + break + } + time.Sleep(5 * time.Second) + } +} + +func WaitOrgInstance() { + log.Println(">>> Wait until org instance is in running state") + for { + instances, err := listOrgInstances(cli, authToken, orgID) + handleError(err) + if len(instances) > 0 { + instance := instances[0] + log.Printf("instance %s status: %s", instance.Name, instance.Status) + if instance.Status == commonParams.InstanceRunning && instance.RunnerStatus == params.RunnerIdle { + orgInstanceName = instance.Name + break + } + } + time.Sleep(5 * time.Second) + } +} + +func ListOrgInstances() { + log.Println(">>> List org instances") + instances, err := listOrgInstances(cli, authToken, orgID) + handleError(err) + printResponse(instances) +} + +func DeleteOrg() { + log.Println(">>> Delete org") + err := deleteOrg(cli, authToken, orgID) + handleError(err) + log.Printf("org %s deleted", orgID) +} + +func DeleteOrgPool() { + log.Println(">>> Delete org pool") + err := deleteOrgPool(cli, authToken, orgID, orgPoolID) + handleError(err) + log.Printf("org pool %s deleted", orgPoolID) +} + +// //////////// +// Instances // +// //////////// +func ListInstances() { + log.Println(">>> List instances") + instances, err := listInstances(cli, authToken) + handleError(err) + printResponse(instances) +} + +func GetInstance() { + log.Println(">>> Get instance") + instance, err := getInstance(cli, authToken, orgInstanceName) + handleError(err) + printResponse(instance) +} + +func DeleteInstance(name string) { + err := deleteInstance(cli, authToken, name) + for { + log.Printf(">>> Wait until instance %s is deleted", name) + instances, err := listInstances(cli, authToken) + handleError(err) + for _, instance := range instances { + if instance.Name == name { + time.Sleep(5 * time.Second) + continue + } + } + break + } + handleError(err) + log.Printf("instance %s deleted", name) +} + +// //////// +// Pools // +// //////// +func CreatePool() { + pools, err := listPools(cli, authToken) + handleError(err) + for _, pool := range pools { + if pool.Image == "ubuntu:20.04" { + // this is the extra pool to be deleted, later, via [DELETE] pools dedicated API. + poolID = pool.ID + return + } + } + log.Println(">>> Create pool") + poolParams := params.CreatePoolParams{ + MaxRunners: 2, + MinIdleRunners: 0, + Flavor: "garm", + Image: "ubuntu:20.04", + OSType: commonParams.Linux, + OSArch: commonParams.Amd64, + ProviderName: "lxd_local", + Tags: []string{"ubuntu", "simple-runner"}, + Enabled: true, + } + pool, err := createRepoPool(cli, authToken, repoID, poolParams) + handleError(err) + printResponse(pool) + poolID = pool.ID +} + +func ListPools() { + log.Println(">>> List pools") + pools, err := listPools(cli, authToken) + handleError(err) + printResponse(pools) +} + +func UpdatePool() { + log.Println(">>> Update pool") + var maxRunners uint = 5 + var idleRunners uint = 0 + poolParams := params.UpdatePoolParams{ + MinIdleRunners: &idleRunners, + MaxRunners: &maxRunners, + } + pool, err := updatePool(cli, authToken, poolID, poolParams) + handleError(err) + printResponse(pool) +} + +func GetPool() { + log.Println(">>> Get pool") + pool, err := getPool(cli, authToken, poolID) + handleError(err) + printResponse(pool) +} + +func DeletePool() { + log.Println(">>> Delete pool") + err := deletePool(cli, authToken, poolID) + handleError(err) + log.Printf("pool %s deleted", poolID) +} + +func ListPoolInstances() { + log.Println(">>> List pool instances") + instances, err := listPoolInstances(cli, authToken, repoPoolID) + handleError(err) + printResponse(instances) +} + +// /////////////// +// Enterprises // +// /////////////// +func CreateEnterprise() { + enterprises, err := listEnterprises(cli, authToken) + handleError(err) + if len(enterprises) > 0 { + log.Println(">>> Enterprise already exists, skipping create") + enterpriseID = enterprises[0].ID + return + } + log.Println(">>> Create enterprise") + createParams := params.CreateEnterpriseParams{ + Name: enterpriseName, + CredentialsName: credentialsName, + WebhookSecret: enterpriseWebhookSecret, + } + enterprise, err := createEnterprise(cli, authToken, createParams) + handleError(err) + printResponse(enterprise) + enterpriseID = enterprise.ID +} + +func ListEnterprises() { + log.Println(">>> List enterprises") + enterprises, err := listEnterprises(cli, authToken) + handleError(err) + printResponse(enterprises) +} + +func UpdateEnterprise() { + log.Println(">>> Update enterprise") + updateParams := params.UpdateEntityParams{ + CredentialsName: fmt.Sprintf("%s-clone", credentialsName), + } + enterprise, err := updateEnterprise(cli, authToken, enterpriseID, updateParams) + handleError(err) + printResponse(enterprise) +} + +func GetEnterprise() { + log.Println(">>> Get enterprise") + enterprise, err := getEnterprise(cli, authToken, enterpriseID) + handleError(err) + printResponse(enterprise) +} + +func CreateEnterprisePool() { + pools, err := listEnterprisesPools(cli, authToken, enterpriseID) + handleError(err) + if len(pools) > 0 { + log.Println(">>> Enterprise pool already exists, skipping create") + enterprisePoolID = pools[0].ID + return + } + log.Println(">>> Create enterprise pool") + poolParams := params.CreatePoolParams{ + MaxRunners: 2, + MinIdleRunners: 0, + Flavor: "garm", + Image: "ubuntu:22.04", + OSType: commonParams.Linux, + OSArch: commonParams.Amd64, + ProviderName: "lxd_local", + Tags: []string{"ubuntu", "simple-runner"}, + Enabled: true, + } + enterprise, err := createEnterprisePool(cli, authToken, enterpriseID, poolParams) + handleError(err) + printResponse(enterprise) + enterprisePoolID = enterprise.ID +} + +func ListEnterprisePools() { + log.Println(">>> List enterprise pools") + pools, err := listEnterprisesPools(cli, authToken, enterpriseID) + handleError(err) + printResponse(pools) +} + +func GetEnterprisePool() { + log.Println(">>> Get enterprise pool") + pool, err := getEnterprisePool(cli, authToken, enterpriseID, enterprisePoolID) + handleError(err) + printResponse(pool) +} + +func UpdateEnterprisePool() { + log.Println(">>> Update enterprise pool") + var maxRunners uint = 5 + var idleRunners uint = 1 + poolParams := params.UpdatePoolParams{ + MinIdleRunners: &idleRunners, + MaxRunners: &maxRunners, + } + pool, err := updateEnterprisePool(cli, authToken, enterpriseID, enterprisePoolID, poolParams) + handleError(err) + printResponse(pool) +} + +func DisableEnterprisePool() { + enabled := false + _, err := updateEnterprisePool(cli, authToken, enterpriseID, enterprisePoolID, params.UpdatePoolParams{Enabled: &enabled}) + handleError(err) + log.Printf("enterprise pool %s disabled", enterprisePoolID) +} + +func WaitEnterprisePoolNoInstances() { + for { + log.Println(">>> Wait until enterprise pool has no instances") + pool, err := getEnterprisePool(cli, authToken, enterpriseID, enterprisePoolID) + handleError(err) + if len(pool.Instances) == 0 { + break + } + time.Sleep(5 * time.Second) + } +} + +func WaitEnterpriseInstance() { + log.Println(">>> Wait until enterprise instance is in running state") + for { + instances, err := listEnterpriseInstances(cli, authToken, enterpriseID) + handleError(err) + if len(instances) > 0 { + instance := instances[0] + log.Printf("instance %s status: %s", instance.Name, instance.Status) + if instance.Status == commonParams.InstanceRunning && instance.RunnerStatus == params.RunnerIdle { + enterpriseInstanceName := instance.Name + log.Printf("enterprise instance %s is running", enterpriseInstanceName) + break + } + } + time.Sleep(5 * time.Second) + } +} + +func ListEnterpriseInstances() { + log.Println(">>> List enterprise instances") + instances, err := listEnterpriseInstances(cli, authToken, enterpriseID) + handleError(err) + printResponse(instances) +} + +func DeleteEnterprise() { + log.Println(">>> Delete enterprise") + err := deleteEnterprise(cli, authToken, enterpriseID) + handleError(err) + log.Printf("enterprise %s deleted", enterpriseID) +} + +func DeleteEnterprisePool() { + log.Println(">>> Delete enterprise pool") + err := deleteEnterprisePool(cli, authToken, enterpriseID, enterprisePoolID) + handleError(err) + log.Printf("enterprise pool %s deleted", enterprisePoolID) +} + +func main() { + ////////////////// + // initialize cli / + ////////////////// + garmUrl, err := url.Parse(baseURL) + handleError(err) + apiPath, err := url.JoinPath(garmUrl.Path, client.DefaultBasePath) + handleError(err) + transportCfg := client.DefaultTransportConfig(). + WithHost(garmUrl.Host). + WithBasePath(apiPath). + WithSchemes([]string{garmUrl.Scheme}) + cli = client.NewHTTPClientWithConfig(nil, transportCfg) + + ////////////////// + // garm init // + ////////////////// + FirstRun() + Login() + + // //////////////////////////// + // credentials and providers // + // //////////////////////////// + ListCredentials() + ListProviders() + + ////////// + // jobs // + ////////// + ListJobs() + + //////////////////// + /// metrics token // + //////////////////// + GetMetricsToken() + + ////////////////// + // repositories // + ////////////////// + CreateRepo() + ListRepos() + UpdateRepo() + GetRepo() + + CreateRepoPool() + ListRepoPools() + GetRepoPool() + UpdateRepoPool() + + ////////////////// + // organizations // + ////////////////// + CreateOrg() + ListOrgs() + UpdateOrg() + GetOrg() + + CreateOrgPool() + ListOrgPools() + GetOrgPool() + UpdateOrgPool() + + /////////////// + // instances // + /////////////// + WaitRepoInstance() + ListRepoInstances() + + WaitOrgInstance() + ListOrgInstances() + + ListInstances() + GetInstance() + + /////////////// + // pools // + /////////////// + CreatePool() + ListPools() + UpdatePool() + GetPool() + ListPoolInstances() + + /////////////// + // enterprise / + /////////////// + // CreateEnterprise() + // ListEnterprises() + // UpdateEnterprise() + // GetEnterprise() + + // CreateEnterprisePool() + // ListEnterprisePools() + // GetEnterprisePool() + // UpdateEnterprisePool() + + // WaitEnterpriseInstance() + // ListEnterpriseInstances() + + // DisableEnterprisePool() + // DeleteInstance(enterpriseInstanceName) + // WaitEnterprisePoolNoInstances() + // DeleteEnterprisePool() + // DeleteEnterprise() + + ///////////// + // Cleanup // + ///////////// + DisableRepoPool() + DisableOrgPool() + + DeleteInstance(repoInstanceName) + DeleteInstance(orgInstanceName) + + WaitRepoPoolNoInstances() + WaitOrgPoolNoInstances() + + DeleteRepoPool() + DeleteOrgPool() + DeletePool() + + DeleteRepo() + DeleteOrg() +}