Skip to content

Commit

Permalink
Merge pull request #13 from fabi200123/unit-tests
Browse files Browse the repository at this point in the history
Adding unit tests
  • Loading branch information
gabriel-samfira authored Mar 11, 2024
2 parents 9733b4a + 37e695f commit 0a2ba2f
Show file tree
Hide file tree
Showing 61 changed files with 18,511 additions and 13 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/go-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Go Tests

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
go-tests:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Golang
uses: actions/setup-go@v3
with:
go-version-file: go.mod

- run: go version

- name: Run GARM Go Tests
run: make go-test
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SHELL := bash

.PHONY: go-test

go-test:
go test -v ./... $(TEST_ARGS) -timeout=15m -parallel=4
143 changes: 143 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 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.

package config

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/require"
)

func TestConfig_Validate(t *testing.T) {
tests := []struct {
name string
config *Config
errString error
}{
{
name: "ValidConfig",
config: &Config{
Zone: "europe-west1-d",
ProjectId: "my-project",
NetworkID: "my-network",
SubnetworkID: "my-subnetwork",
CredentialsFile: "path/to/credentials.json",
ExternalIPAccess: true,
},
errString: nil,
},
{
name: "MissingRegion",
config: &Config{
ProjectId: "my-project",
NetworkID: "my-network",
SubnetworkID: "my-subnetwork",
CredentialsFile: "path/to/credentials.json",
ExternalIPAccess: true,
},
errString: fmt.Errorf("missing region"),
},
{
name: "MissingProjectID",
config: &Config{
Zone: "europe-west1-d",
NetworkID: "my-network",
SubnetworkID: "my-subnetwork",
CredentialsFile: "path/to/credentials.json",
},
errString: fmt.Errorf("missing project_id"),
},
{
name: "MissingNetworkID",
config: &Config{
Zone: "europe-west1-d",
ProjectId: "my-project",
SubnetworkID: "my-subnetwork",
CredentialsFile: "path/to/credentials.json",
ExternalIPAccess: true,
},
errString: fmt.Errorf("missing network_id"),
},
{
name: "MissingSubnetworkID",
config: &Config{
Zone: "europe-west1-d",
ProjectId: "my-project",
NetworkID: "my-network",
CredentialsFile: "path/to/credentials.json",
ExternalIPAccess: true,
},
errString: fmt.Errorf("missing subnetwork_id"),
},
{
name: "MissingCredentialsFile",
config: &Config{
Zone: "europe-west1-d",
ProjectId: "my-project",
NetworkID: "my-network",
SubnetworkID: "my-subnetwork",
ExternalIPAccess: true,
},
errString: fmt.Errorf("missing credentials_file"),
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.config.Validate()
if tc.errString == nil {
require.Nil(t, err)
} else {
require.Equal(t, tc.errString, err)
}

})
}
}

func TestNewConfig(t *testing.T) {
mockData := `
project_id = "garm-testing"
zone = "europe-west1-d"
network_id = "projects/garm-testing/global/networks/garm"
subnetwork_id = "projects/garm-testing/regions/europe-west1/subnetworks/garm"
credentials_file = "/home/ubuntu/service-account-key.json"
external_ip_access = true
`
// Create a temporary file
tmpFile, err := os.CreateTemp("", "config-*.toml")
require.NoError(t, err, "Failed to create temporary file")
defer os.Remove(tmpFile.Name())

_, err = tmpFile.WriteString(mockData)
require.NoError(t, err, "Failed to write to temporary file")
err = tmpFile.Close()
require.NoError(t, err, "Failed to close temporary file")

// Use the temporary file path as the argument to NewConfig
cfg, err := NewConfig(tmpFile.Name())
require.NoError(t, err, "NewConfig returned an error")

// Validate the content of the Config object
require.Equal(t, "garm-testing", cfg.ProjectId, "ProjectId value did not match expected")
require.Equal(t, "europe-west1-d", cfg.Zone, "Zone value did not match expected")
require.Equal(t, "projects/garm-testing/global/networks/garm", cfg.NetworkID, "NetworkId value did not match expected")
require.Equal(t, "projects/garm-testing/regions/europe-west1/subnetworks/garm", cfg.SubnetworkID, "SubnetworkId value did not match expected")
require.Equal(t, "/home/ubuntu/service-account-key.json", cfg.CredentialsFile, "CredentialsFile value did not match expected")
require.Equal(t, true, cfg.ExternalIPAccess, "ExternalIpAccess value did not match expected")
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/BurntSushi/toml v1.3.2
github.com/cloudbase/garm-provider-common v0.1.2-0.20240216125425-bbe4930a1ebf
github.com/googleapis/gax-go/v2 v2.12.0
github.com/stretchr/testify v1.9.0
github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/oauth2 v0.16.0
google.golang.org/api v0.156.0
Expand All @@ -15,6 +16,7 @@ require (

require (
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
Expand All @@ -27,6 +29,8 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/minio/sio v0.3.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI=
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
Expand Down
44 changes: 37 additions & 7 deletions internal/client/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/cloudbase/garm-provider-gcp/config"
"github.com/cloudbase/garm-provider-gcp/internal/spec"
"github.com/cloudbase/garm-provider-gcp/internal/util"
"github.com/googleapis/gax-go/v2"
"github.com/googleapis/gax-go/v2/apierror"
"golang.org/x/oauth2/google"
gcompute "google.golang.org/api/compute/v1"
Expand All @@ -39,6 +40,11 @@ const (
accessConfigType string = "ONE_TO_ONE_NAT"
)

var (
WaitOp = (*compute.Operation).Wait
NextIt = (*compute.InstanceIterator).Next
)

func NewGcpCli(ctx context.Context, cfg *config.Config) (*GcpCli, error) {
jsonKey, err := os.ReadFile(cfg.CredentialsFile)
if err != nil {
Expand All @@ -64,10 +70,34 @@ func NewGcpCli(ctx context.Context, cfg *config.Config) (*GcpCli, error) {
return gcpCli, nil
}

type ClientInterface interface {
Insert(ctx context.Context, req *computepb.InsertInstanceRequest, opts ...gax.CallOption) (*compute.Operation, error)
Start(ctx context.Context, req *computepb.StartInstanceRequest, opts ...gax.CallOption) (*compute.Operation, error)
Stop(ctx context.Context, req *computepb.StopInstanceRequest, opts ...gax.CallOption) (*compute.Operation, error)
Delete(ctx context.Context, req *computepb.DeleteInstanceRequest, opts ...gax.CallOption) (*compute.Operation, error)
List(ctx context.Context, req *computepb.ListInstancesRequest, opts ...gax.CallOption) *compute.InstanceIterator
Get(ctx context.Context, req *computepb.GetInstanceRequest, opts ...gax.CallOption) (*computepb.Instance, error)
}

type GcpCli struct {
cfg *config.Config
cfg *config.Config
client ClientInterface
}

func (g GcpCli) Config() *config.Config {
return g.cfg
}

func (g GcpCli) Client() ClientInterface {
return g.client
}

func (g *GcpCli) SetClient(client ClientInterface) {
g.client = client
}

client *compute.InstancesClient
func (g *GcpCli) SetConfig(cfg *config.Config) {
g.cfg = cfg
}

func (g *GcpCli) CreateInstance(ctx context.Context, spec *spec.RunnerSpec) (*computepb.Instance, error) {
Expand Down Expand Up @@ -128,7 +158,7 @@ func (g *GcpCli) CreateInstance(ctx context.Context, spec *spec.RunnerSpec) (*co
return nil, fmt.Errorf("failed to create instance %s: %w", insertReq, err)
}

if err = op.Wait(ctx); err != nil {
if err = WaitOp(op, ctx); err != nil {
return nil, fmt.Errorf("failed to wait for operation: %w", err)
}

Expand Down Expand Up @@ -161,7 +191,7 @@ func (g *GcpCli) ListDescribedInstances(ctx context.Context, poolID string) ([]*
it := g.client.List(ctx, req)
var instances []*computepb.Instance
for {
instance, _ := it.Next()
instance, _ := NextIt(it)
if instance == nil {
break
}
Expand All @@ -184,7 +214,7 @@ func (g *GcpCli) DeleteInstance(ctx context.Context, instance string) error {
return fmt.Errorf("unable to delete instance: %w", err)
}

if err = op.Wait(ctx); err != nil {
if err = WaitOp(op, ctx); err != nil {
return fmt.Errorf("unable to wait for the delete operation: %w", err)
}

Expand All @@ -203,7 +233,7 @@ func (g *GcpCli) StopInstance(ctx context.Context, instance string) error {
return fmt.Errorf("unable to stop instance: %w", err)
}

if err = op.Wait(ctx); err != nil {
if err = WaitOp(op, ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", err)
}

Expand All @@ -222,7 +252,7 @@ func (g *GcpCli) StartInstance(ctx context.Context, instance string) error {
return fmt.Errorf("unable to start instance: %w", err)
}

if err = op.Wait(ctx); err != nil {
if err = WaitOp(op, ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", err)
}

Expand Down
Loading

0 comments on commit 0a2ba2f

Please sign in to comment.