diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..b5f431e --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,42 @@ +name: Go + +on: + pull_request: + branches: [ "main" ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: read + +jobs: + build: + runs-on: tks-gha-runner + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: 'go.mod' + cache: true + + - name: Verify modules + run: | + go mod tidy && go mod verify + if [ -n "$(git status --porcelain go.mod go.sum)" ]; then + echo "go.mod or go.sum are not tidy. Run 'go mod tidy' and commit." + git status + exit 1 + fi + + - name: Build + run: go build ./... + + - name: Test + run: go test -v ./... diff --git a/go.mod b/go.mod index 27f9513..199c53d 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ -module github.com/spectrocloud/maas-client-go +module github.com/cloud104/maas-client-go go 1.24 require ( github.com/google/uuid v1.6.0 + github.com/jarcoal/httpmock v1.4.1 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 191ba16..9340fd0 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jarcoal/httpmock v1.4.1 h1:0Ju+VCFuARfFlhVXFc2HxlcQkfB+Xq12/EotHko+x2A= +github.com/jarcoal/httpmock v1.4.1/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0= +github.com/maxatome/go-testdeep v1.14.0 h1:rRlLv1+kI8eOI3OaBXZwb3O7xY3exRzdW5QyX48g9wI= +github.com/maxatome/go-testdeep v1.14.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/maasclient/bootresource_test.go b/maasclient/bootresource_test.go index 25760ca..500bbf5 100644 --- a/maasclient/bootresource_test.go +++ b/maasclient/bootresource_test.go @@ -18,33 +18,86 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" + "crypto/sha256" + "encoding/hex" + "net/http" "os" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestGetBootResources(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list-all", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/boot-resources/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/bootresources/list__all.json")), + ) + list, err := c.BootResources().List(ctx, nil) assert.Nil(t, err, "expecting nil error") assert.NotEmpty(t, list) }) - // + t.Run("list-by-id", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/boot-resources/7/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/bootresources/get__id-7.json")), + ) + res, err := c.BootResources().BootResource(7).Get(ctx) assert.Nil(t, err) assert.NotNil(t, res) }) t.Run("import image", func(t *testing.T) { + tmp, err := os.CreateTemp("", "maas-bootresource-*.tgz") + assert.NoError(t, err) + + defer func() { _ = os.Remove(tmp.Name()) }() + + content := []byte("dummy boot resource payload\n") + _, err = tmp.Write(content) + assert.NoError(t, err) + assert.NoError(t, tmp.Close()) + + size := len(content) + sum := sha256.Sum256(content) + sha := hex.EncodeToString(sum[:]) + + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/boot-resources/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/bootresources/import_response__id-99.json")), + ) + httpmock.RegisterResponder( + http.MethodPut, + "http://maas.test/api/2.0/boot-resources/99/upload/", + httpmock.NewBytesResponder(200, nil), + ) + res, err := c.BootResources().Builder("test-image", "amd64/generic", - "e9844638c7345d182c5d88e1eaeae74749d02beeca38587a530207fddc0a280a", - "/Users/deepak/maas/ubuntu.tar.gz", 1262032476).Create(ctx) + sha, + tmp.Name(), size).Create(ctx) assert.Nil(t, err) err = res.Upload(ctx) assert.Nil(t, err) diff --git a/maasclient/client.go b/maasclient/client.go index 8906e84..ef5bf6f 100644 --- a/maasclient/client.go +++ b/maasclient/client.go @@ -26,7 +26,7 @@ import ( "strings" "time" - "github.com/spectrocloud/maas-client-go/maasclient/oauth1" + "github.com/cloud104/maas-client-go/maasclient/oauth1" ) // authenticatedClient diff --git a/maasclient/dns_test.go b/maasclient/dns_test.go index 51f13fe..7c9a270 100644 --- a/maasclient/dns_test.go +++ b/maasclient/dns_test.go @@ -18,18 +18,32 @@ package maasclient import ( "context" - "os" + "net/http" "testing" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) func TestGetDNSResources(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("no-options", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/dnsresources/?all=true", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/dnsresources/list__all.json")), + ) + res, err := c.DNSResources().List(ctx, nil) assert.Nil(t, err, "expecting nil error") assert.NotNil(t, res, "expecting non-nil result") @@ -49,6 +63,12 @@ func TestGetDNSResources(t *testing.T) { }) t.Run("get maas-1.maas", func(t *testing.T) { + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/dnsresources/?fqdn=maas-1.maas.sc", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/dnsresources/list__fqdn-maas-1.maas.sc.json")), + ) + filters := ParamsBuilder().Add(FQDNKey, "maas-1.maas.sc") res, err := c.DNSResources().List(ctx, filters) assert.Nil(t, err, "expecting nil error") @@ -62,6 +82,20 @@ func TestGetDNSResources(t *testing.T) { }) t.Run("create test-unit-1.maas", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/dnsresources/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/dnsresources/create__id-201.json")), + ) + + httpmock.RegisterResponder( + http.MethodDelete, + "http://maas.test/api/2.0/dnsresources/201/", + httpmock.NewJsonResponderOrPanic(204, nil), + ) + res, err := c.DNSResources(). Builder(). WithFQDN("test-unit-1.maas.sc"). @@ -78,6 +112,31 @@ func TestGetDNSResources(t *testing.T) { }) t.Run("create test-unit-2.maas", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/dnsresources/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/dnsresources/create__id-202.json")), + ) + + httpmock.RegisterResponder( + http.MethodPut, + "http://maas.test/api/2.0/dnsresources/202/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/dnsresources/update__id-202.json")), + ) + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/dnsresources/202/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/dnsresources/update__id-202.json")), + ) + + httpmock.RegisterResponder( + http.MethodDelete, + "http://maas.test/api/2.0/dnsresources/202/", + httpmock.NewJsonResponderOrPanic(204, nil), + ) //err := c.DNSResources().DNSResource(148).Delete(ctx) //assert.Nil(t, err) diff --git a/maasclient/domain_test.go b/maasclient/domain_test.go index 72df07c..014093e 100644 --- a/maasclient/domain_test.go +++ b/maasclient/domain_test.go @@ -18,17 +18,30 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" - "os" + "net/http" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestDomain(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list domains", func(t *testing.T) { + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/domains/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/domains/list__all.json")), + ) + res, err := c.Domains().List(ctx) assert.Nil(t, err) assert.NotNil(t, res) diff --git a/maasclient/machine_test.go b/maasclient/machine_test.go index 3efc5af..85472e8 100644 --- a/maasclient/machine_test.go +++ b/maasclient/machine_test.go @@ -19,10 +19,12 @@ package maasclient import ( "context" "math/rand" + "net/http" "os" "testing" "time" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -33,7 +35,18 @@ func TestMain(m *testing.M) { } func TestClient_GetMachine(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/machines/e37xxm/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/get__systemid-e37xxm.json")), + ) ctx := context.Background() res := c.Machines().Machine("e37xxm") @@ -60,7 +73,12 @@ func TestClient_GetMachine(t *testing.T) { } func TestClient_AllocateMachine(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() @@ -75,6 +93,20 @@ func TestClient_AllocateMachine(t *testing.T) { } t.Run("no-options", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/machines/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/get__systemid-e37xxm.json")), + ) + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/machines/e37xxm/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/get__systemid-e37xxm.json")), + ) + res, err := c.Machines().Allocator().Allocate(ctx) assert.Nil(t, err, "expecting nil error") @@ -95,6 +127,20 @@ func TestClient_AllocateMachine(t *testing.T) { }) t.Run("with-az", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/machines/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/create__systemid-a12b3c.json")), + ) + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/machines/a12b3c/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/create__systemid-a12b3c.json")), + ) + res, err := c.Machines().Allocator().WithZone("az1").Allocate(ctx) assert.Nil(t, err, "expecting nil error") @@ -106,7 +152,12 @@ func TestClient_AllocateMachine(t *testing.T) { } func TestClient_DeployMachine(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() @@ -120,6 +171,26 @@ func TestClient_DeployMachine(t *testing.T) { } t.Run("simple", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/machines/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/create__systemid-a12b3c.json")), + ) + + httpmock.RegisterResponder( + http.MethodPut, + "http://maas.test/api/2.0/machines/a12b3c/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/update__systemid-a12b3c.json")), + ) + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/machines/a12b3c/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/deploy__systemid-a12b3c.json")), + ) + res, err := c.Machines().Allocator().Allocate(ctx) if err != nil { t.Fatal("Machine didn't allocate") @@ -148,7 +219,18 @@ func TestClient_DeployMachine(t *testing.T) { } func TestClient_UpdateMachine(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) + + httpmock.RegisterResponder( + http.MethodPut, + "http://maas.test/api/2.0/machines/e37xxm/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/machines/update__systemid-e37xxm.json")), + ) res, err := c.Machines().Machine("e37xxm"). Modifier(). diff --git a/maasclient/rackcontrollers_test.go b/maasclient/rackcontrollers_test.go index d3e4eff..0f01008 100644 --- a/maasclient/rackcontrollers_test.go +++ b/maasclient/rackcontrollers_test.go @@ -18,17 +18,32 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" - "os" + "net/http" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestRackControllers(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("begin rack import", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/rackcontrollers/", + httpmock.NewJsonResponderOrPanic(200, nil), + ) + err := c.RackControllers().ImportBootImages(ctx) assert.Nil(t, err, "expecting nil error") }) diff --git a/maasclient/resourcepool_test.go b/maasclient/resourcepool_test.go index e6153ff..404a9fa 100644 --- a/maasclient/resourcepool_test.go +++ b/maasclient/resourcepool_test.go @@ -18,17 +18,32 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" - "os" + "net/http" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestResourcePool(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list resourcepools", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/resourcepools/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/resourcepools/list__all.json")), + ) + res, err := c.ResourcePools().List(ctx, nil) assert.Nil(t, err) assert.NotNil(t, res) diff --git a/maasclient/space_test.go b/maasclient/space_test.go index def65a8..6b96b35 100644 --- a/maasclient/space_test.go +++ b/maasclient/space_test.go @@ -18,17 +18,32 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" - "os" + "net/http" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestSpaces(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("space list", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/spaces/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/spaces/list__all.json")), + ) + res, err := c.Spaces().List(ctx) assert.Nil(t, err) assert.NotNil(t, res) diff --git a/maasclient/sshkey_test.go b/maasclient/sshkey_test.go index df681c6..f2ba40e 100644 --- a/maasclient/sshkey_test.go +++ b/maasclient/sshkey_test.go @@ -18,18 +18,32 @@ package maasclient import ( "context" - "os" + "net/http" "testing" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) func TestSSHKeys(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list sshkeys", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/account/prefs/sshkeys/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/sshkeys/list__all.json")), + ) + sshKeys, err := c.SSHKeys().List(ctx) assert.Nil(t, err) assert.NotNil(t, sshKeys) diff --git a/maasclient/tags_test.go b/maasclient/tags_test.go index 9aae600..71086b8 100644 --- a/maasclient/tags_test.go +++ b/maasclient/tags_test.go @@ -29,26 +29,33 @@ package maasclient import ( "context" "fmt" - "os" + "net/http" "testing" "time" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) func TestTags(t *testing.T) { - endPoint := os.Getenv("MAAS_ENDPOINT") - apiKey := os.Getenv("MAAS_API_KEY") - c := NewAuthenticatedClientSet(endPoint, apiKey) + httpClient := &http.Client{} - // Uncomment below for Unit Testing purposes. - //os.Setenv("MAAS_ENDPOINT", "") - //os.Setenv("MAAS_API_KEY", "") - //c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list tags", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/tags/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/tags/list__all.json")), + ) + res, err := c.Tags().List(ctx) assert.Nil(t, err) assert.NotNil(t, res) @@ -58,6 +65,20 @@ func TestTags(t *testing.T) { }) t.Run("create tag", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/tags/", + httpmock.NewJsonResponderOrPanic(200, nil), + ) + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/tags/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/tags/list__all.json")), + ) + err := c.Tags().Create(ctx, "testCase-tag-1") assert.Nil(t, err) @@ -73,6 +94,14 @@ func TestTags(t *testing.T) { }) t.Run("assign tag to machines", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/tags/", + httpmock.NewJsonResponderOrPanic(200, nil), + ) + // First, create a test tag tagName := "test-assign-unassign-tag" err := c.Tags().Create(ctx, tagName) @@ -106,6 +135,14 @@ func TestTags(t *testing.T) { }) t.Run("unassign tag from machines", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodPost, + "http://maas.test/api/2.0/tags/", + httpmock.NewJsonResponderOrPanic(200, nil), + ) + // Create a test tag tagName := "test-assign-unassign-tag" err := c.Tags().Create(ctx, tagName) diff --git a/maasclient/testdata/bootresources/get__id-7.json b/maasclient/testdata/bootresources/get__id-7.json new file mode 100644 index 0000000..0f448f7 --- /dev/null +++ b/maasclient/testdata/bootresources/get__id-7.json @@ -0,0 +1,28 @@ +{ + "id": 7, + "name": "ubuntu/noble", + "type": "Synced", + "architecture": "amd64/generic", + "subarches": "generic", + "title": "Ubuntu 24.04 LTS (Noble Numbat)", + "sets": { + "20240115": { + "version": "20240115", + "label": "noble", + "size": 234567890, + "complete": true, + "progress": 1.0, + "files": { + "initrd": { + "filename": "initrd.gz", + "filetype": "initrd", + "sha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "size": 8765432, + "complete": true, + "progress": 1.0, + "upload_uri": "http://maas.test/upload/noble/initrd.gz" + } + } + } + } +} diff --git a/maasclient/testdata/bootresources/import_response__id-99.json b/maasclient/testdata/bootresources/import_response__id-99.json new file mode 100644 index 0000000..3f2eb2f --- /dev/null +++ b/maasclient/testdata/bootresources/import_response__id-99.json @@ -0,0 +1,27 @@ +{ + "id": 99, + "name": "test-image", + "type": "Synced", + "architecture": "amd64/generic", + "subarches": "generic", + "sets": { + "20251219": { + "version": "20251219", + "label": "stable", + "size": 28, + "complete": false, + "progress": 0, + "files": { + "root-tgz": { + "filename": "ubuntu.tar.gz", + "filetype": "tgz", + "sha256": "f3f0dca7ef3acf4c581232f996ff2df849b3d768c11ee1805e4fc78c8b5d2f40", + "size": 28, + "complete": false, + "progress": 0, + "upload_uri": "/boot-resources/99/upload/" + } + } + } + } +} diff --git a/maasclient/testdata/bootresources/list__all.json b/maasclient/testdata/bootresources/list__all.json new file mode 100644 index 0000000..b021b12 --- /dev/null +++ b/maasclient/testdata/bootresources/list__all.json @@ -0,0 +1,30 @@ +[ + { + "id": 1, + "name": "ubuntu/jammy", + "type": "Synced", + "architecture": "amd64/generic", + "subarches": "generic", + "title": "Ubuntu 22.04 LTS (Jammy Jellyfish)", + "sets": { + "20231201": { + "version": "20231201", + "label": "jammy", + "size": 123456789, + "complete": true, + "progress": 1.0, + "files": { + "root-tgz": { + "filename": "root.tgz", + "filetype": "tgz", + "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "size": 123456789, + "complete": true, + "progress": 1.0, + "upload_uri": "http://maas.test/upload/root.tgz" + } + } + } + } + } +] diff --git a/maasclient/testdata/dnsresources/create__id-201.json b/maasclient/testdata/dnsresources/create__id-201.json new file mode 100644 index 0000000..66663e7 --- /dev/null +++ b/maasclient/testdata/dnsresources/create__id-201.json @@ -0,0 +1,6 @@ +{ + "id": 201, + "fqdn": "test-unit-1.maas.sc", + "address_ttl": 10, + "ip_addresses": [] +} diff --git a/maasclient/testdata/dnsresources/create__id-202.json b/maasclient/testdata/dnsresources/create__id-202.json new file mode 100644 index 0000000..d74d1e0 --- /dev/null +++ b/maasclient/testdata/dnsresources/create__id-202.json @@ -0,0 +1,6 @@ +{ + "id": 202, + "fqdn": "test-unit-2.maas.sc", + "address_ttl": 10, + "ip_addresses": [] +} diff --git a/maasclient/testdata/dnsresources/list__all.json b/maasclient/testdata/dnsresources/list__all.json new file mode 100644 index 0000000..a2cb047 --- /dev/null +++ b/maasclient/testdata/dnsresources/list__all.json @@ -0,0 +1,55 @@ +[ + { + "id": 1, + "fqdn": "host1.maas.test", + "address_ttl": 300, + "ip_addresses": [ + { + "ip": "192.168.1.10", + "interface_set": [ + { + "system_id": "sys-abc123", + "interface_id": "if-1", + "id": 1, + "name": "eth0", + "type": "physical", + "enabled": true, + "mac_address": "52:54:00:12:34:56", + "links": [ + { + "id": "link-1", + "mode": "static", + "subnet": { + "id": 10, + "name": "subnet-10", + "space": "default", + "vlan": { + "id": 100, + "vid": 100, + "name": "vlan100", + "fabric_id": 1, + "fabric_name": "fabric-1", + "mtu": 1500, + "dhcp_on": true + }, + "cidr": "192.168.1.0/24" + }, + "ip_address": "192.168.1.10" + } + ], + "children": [], + "vlan": { + "id": 100, + "vid": 100, + "name": "vlan100", + "fabric_id": 1, + "fabric_name": "fabric-1", + "mtu": 1500, + "dhcp_on": true + } + } + ] + } + ] + } +] diff --git a/maasclient/testdata/dnsresources/list__fqdn-maas-1.maas.sc.json b/maasclient/testdata/dnsresources/list__fqdn-maas-1.maas.sc.json new file mode 100644 index 0000000..0de5b03 --- /dev/null +++ b/maasclient/testdata/dnsresources/list__fqdn-maas-1.maas.sc.json @@ -0,0 +1,55 @@ +[ + { + "id": 3, + "fqdn": "host1.maas.test", + "address_ttl": 300, + "ip_addresses": [ + { + "ip": "192.168.1.10", + "interface_set": [ + { + "system_id": "sys-abc123", + "interface_id": "if-1", + "id": 1, + "name": "eth0", + "type": "physical", + "enabled": true, + "mac_address": "52:54:00:12:34:56", + "links": [ + { + "id": "link-1", + "mode": "static", + "subnet": { + "id": 10, + "name": "subnet-10", + "space": "default", + "vlan": { + "id": 100, + "vid": 100, + "name": "vlan100", + "fabric_id": 1, + "fabric_name": "fabric-1", + "mtu": 1500, + "dhcp_on": true + }, + "cidr": "192.168.1.0/24" + }, + "ip_address": "192.168.1.10" + } + ], + "children": [], + "vlan": { + "id": 100, + "vid": 100, + "name": "vlan100", + "fabric_id": 1, + "fabric_name": "fabric-1", + "mtu": 1500, + "dhcp_on": true + } + } + ] + } + ] + } +] diff --git a/maasclient/testdata/dnsresources/update__id-202.json b/maasclient/testdata/dnsresources/update__id-202.json new file mode 100644 index 0000000..6d20c71 --- /dev/null +++ b/maasclient/testdata/dnsresources/update__id-202.json @@ -0,0 +1,13 @@ +{ + "id": 202, + "fqdn": "test-unit-2.maas.sc", + "address_ttl": 10, + "ip_addresses": [ + { + "ip": "1.2.3.4" + }, + { + "ip": "5.6.7.8" + } + ] +} diff --git a/maasclient/testdata/domains/list__all.json b/maasclient/testdata/domains/list__all.json new file mode 100644 index 0000000..359d661 --- /dev/null +++ b/maasclient/testdata/domains/list__all.json @@ -0,0 +1,18 @@ +[ + { + "id": 1, + "isAuthoritative": true, + "ttl": 300, + "isDefault": true, + "name": "maas.sc", + "resourceRecordCount": 12 + }, + { + "id": 2, + "isAuthoritative": false, + "ttl": 600, + "isDefault": false, + "name": "test.maas.sc", + "resourceRecordCount": 3 + } +] diff --git a/maasclient/testdata/machines/create__systemid-a12b3c.json b/maasclient/testdata/machines/create__systemid-a12b3c.json new file mode 100644 index 0000000..6edce3f --- /dev/null +++ b/maasclient/testdata/machines/create__systemid-a12b3c.json @@ -0,0 +1,37 @@ +{ + "system_id": "a12b3c", + "fqdn": "a12b3c.maas.sc", + "zone": { + "id": 1, + "name": "az1" + }, + "pool": { + "id": 1, + "name": "default" + }, + "power_state": "on", + "power_type": "ipmi", + "hostname": "a12b3c", + "ip_addresses": [ + "192.168.10.21" + ], + "status_name": "Deployed", + "osystem": "ubuntu", + "distro_series": "jammy", + "swap_size": 8192, + "memory": 16384, + "storage": 250059.35, + "boot_interface": { + "id": 3, + "type": "physical", + "name": "enp2s0", + "children": [] + }, + "parent": { + "system_id": "" + }, + "tags": [ + "az1", + "prod" + ] +} diff --git a/maasclient/testdata/machines/deploy__systemid-a12b3c.json b/maasclient/testdata/machines/deploy__systemid-a12b3c.json new file mode 100644 index 0000000..8f9baea --- /dev/null +++ b/maasclient/testdata/machines/deploy__systemid-a12b3c.json @@ -0,0 +1,37 @@ +{ + "system_id": "a12b3c", + "fqdn": "a12b3c.maas.sc", + "zone": { + "id": 1, + "name": "az1" + }, + "pool": { + "id": 1, + "name": "default" + }, + "power_state": "on", + "power_type": "ipmi", + "hostname": "a12b3c", + "ip_addresses": [ + "192.168.10.21" + ], + "status_name": "Deployed", + "osystem": "custom", + "distro_series": "u-1804-0-k-11915-0", + "swap_size": 0, + "memory": 16384, + "storage": 250059.35, + "boot_interface": { + "id": 3, + "type": "physical", + "name": "enp2s0", + "children": [] + }, + "parent": { + "system_id": "" + }, + "tags": [ + "az1", + "prod" + ] +} diff --git a/maasclient/testdata/machines/get__systemid-e37xxm.json b/maasclient/testdata/machines/get__systemid-e37xxm.json new file mode 100644 index 0000000..769f821 --- /dev/null +++ b/maasclient/testdata/machines/get__systemid-e37xxm.json @@ -0,0 +1,36 @@ +{ + "system_id": "e37xxm", + "fqdn": "e37xxm.maas.sc", + "zone": { + "id": 2, + "name": "az2" + }, + "pool": { + "id": 1, + "name": "default" + }, + "power_state": "on", + "power_type": "ipmi", + "hostname": "e37xxm", + "ip_addresses": [ + "192.168.20.15" + ], + "status_name": "Deployed", + "osystem": "ubuntu", + "distro_series": "jammy", + "swap_size": 0, + "memory": 16384, + "storage": 250059.35, + "boot_interface": { + "id": 1, + "type": "physical", + "name": "enp2s0", + "children": [] + }, + "parent": { + "system_id": "" + }, + "tags": [ + "prod" + ] +} diff --git a/maasclient/testdata/machines/update__systemid-a12b3c.json b/maasclient/testdata/machines/update__systemid-a12b3c.json new file mode 100644 index 0000000..8137e74 --- /dev/null +++ b/maasclient/testdata/machines/update__systemid-a12b3c.json @@ -0,0 +1,37 @@ +{ + "system_id": "a12b3c", + "fqdn": "a12b3c.maas.sc", + "zone": { + "id": 1, + "name": "az1" + }, + "pool": { + "id": 1, + "name": "default" + }, + "power_state": "on", + "power_type": "ipmi", + "hostname": "a12b3c", + "ip_addresses": [ + "192.168.10.21" + ], + "status_name": "Deployed", + "osystem": "ubuntu", + "distro_series": "jammy", + "swap_size": 0, + "memory": 16384, + "storage": 250059.35, + "boot_interface": { + "id": 3, + "type": "physical", + "name": "enp2s0", + "children": [] + }, + "parent": { + "system_id": "" + }, + "tags": [ + "az1", + "prod" + ] +} diff --git a/maasclient/testdata/machines/update__systemid-e37xxm.json b/maasclient/testdata/machines/update__systemid-e37xxm.json new file mode 100644 index 0000000..1ef412e --- /dev/null +++ b/maasclient/testdata/machines/update__systemid-e37xxm.json @@ -0,0 +1,36 @@ +{ + "system_id": "e37xxm", + "fqdn": "e37xxm.maas.sc", + "zone": { + "id": 2, + "name": "az2" + }, + "pool": { + "id": 1, + "name": "default" + }, + "power_state": "on", + "power_type": "ipmi", + "hostname": "e37xxm", + "ip_addresses": [ + "192.168.20.15" + ], + "status_name": "Deployed", + "osystem": "ubuntu", + "distro_series": "jammy", + "swap_size": 10, + "memory": 16384, + "storage": 250059.35, + "boot_interface": { + "id": 1, + "type": "physical", + "name": "enp2s0", + "children": [] + }, + "parent": { + "system_id": "" + }, + "tags": [ + "prod" + ] +} diff --git a/maasclient/testdata/resourcepools/list__all.json b/maasclient/testdata/resourcepools/list__all.json new file mode 100644 index 0000000..258934d --- /dev/null +++ b/maasclient/testdata/resourcepools/list__all.json @@ -0,0 +1,17 @@ +[ + { + "id": 1, + "name": "compute", + "description": "General-purpose compute nodes" + }, + { + "id": 2, + "name": "lxd", + "description": "LXD virtual machine hosts" + }, + { + "id": 3, + "name": "gpu", + "description": "GPU-enabled machines" + } +] diff --git a/maasclient/testdata/spaces/list__all.json b/maasclient/testdata/spaces/list__all.json new file mode 100644 index 0000000..1767471 --- /dev/null +++ b/maasclient/testdata/spaces/list__all.json @@ -0,0 +1,57 @@ +[ + { + "name": "default", + "subnets": [ + { + "id": 10, + "name": "subnet-10", + "space": "default", + "vlan": { + "id": 100, + "vid": 100, + "name": "vlan100", + "fabric": "fabric-1", + "fabric_id": 1, + "mtu": 1500, + "dhcp_on": true + }, + "cidr": "192.168.1.0/24" + } + ] + }, + { + "name": "az1", + "subnets": [ + { + "id": 11, + "name": "subnet-az1-1", + "space": "az1", + "vlan": { + "id": 101, + "vid": 101, + "name": "vlan101", + "fabric": "fabric-2", + "fabric_id": 2, + "mtu": 1500, + "dhcp_on": false + }, + "cidr": "10.10.0.0/16" + }, + { + "id": 12, + "name": "subnet-az1-2", + "space": "az1", + "vlan": { + "id": 102, + "vid": 102, + "name": "vlan102", + "fabric": "fabric-2", + "fabric_id": 2, + "mtu": 9000, + "dhcp_on": true + }, + "cidr": "172.16.10.0/24" + } + ] + } +] diff --git a/maasclient/testdata/sshkeys/list__all.json b/maasclient/testdata/sshkeys/list__all.json new file mode 100644 index 0000000..d8f15f6 --- /dev/null +++ b/maasclient/testdata/sshkeys/list__all.json @@ -0,0 +1,7 @@ +[ + { + "id": 1, + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtestkeymaterial test@example", + "keySource": "test@example" + } +] diff --git a/maasclient/testdata/tags/list__all.json b/maasclient/testdata/tags/list__all.json new file mode 100644 index 0000000..65ad924 --- /dev/null +++ b/maasclient/testdata/tags/list__all.json @@ -0,0 +1,16 @@ +[ + { + "resource_uri": "/MAAS/api/2.0/tags/testCase-tag-1/", + "name": "testCase-tag-1", + "definition": "tag:testCase-tag-1", + "comment": "Test case tag 1", + "kernel_opts": "" + }, + { + "resource_uri": "/MAAS/api/2.0/tags/testCase-tag-2/", + "name": "testCase-tag-2", + "definition": "tag:testCase-tag-2", + "comment": "Test case tag 2", + "kernel_opts": "intel_iommu=on" + } +] diff --git a/maasclient/testdata/users/get__whoami.json b/maasclient/testdata/users/get__whoami.json new file mode 100644 index 0000000..88d8812 --- /dev/null +++ b/maasclient/testdata/users/get__whoami.json @@ -0,0 +1,6 @@ +{ + "is_superuser": false, + "username": "dev", + "email": "dev@maas.test", + "is_local": true +} diff --git a/maasclient/testdata/users/list__all.json b/maasclient/testdata/users/list__all.json new file mode 100644 index 0000000..23b7f2c --- /dev/null +++ b/maasclient/testdata/users/list__all.json @@ -0,0 +1,20 @@ +[ + { + "is_superuser": true, + "username": "admin", + "email": "admin@maas.test", + "is_local": true + }, + { + "is_superuser": false, + "username": "dev", + "email": "dev@maas.test", + "is_local": true + }, + { + "is_superuser": false, + "username": "test-user-1", + "email": "test-user-1@maas.test", + "is_local": true + } +] diff --git a/maasclient/testdata/zones/list__all.json b/maasclient/testdata/zones/list__all.json new file mode 100644 index 0000000..0ff5239 --- /dev/null +++ b/maasclient/testdata/zones/list__all.json @@ -0,0 +1,17 @@ +[ + { + "id": 1, + "name": "default", + "description": "Default zone" + }, + { + "id": 2, + "name": "az1", + "description": "Availability zone 1" + }, + { + "id": 3, + "name": "az2", + "description": "Availability zone 2" + } +] diff --git a/maasclient/user_test.go b/maasclient/user_test.go index c64fb05..44859d7 100644 --- a/maasclient/user_test.go +++ b/maasclient/user_test.go @@ -18,17 +18,32 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" - "os" + "net/http" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestUsers(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list users", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/users/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/users/list__all.json")), + ) + res, err := c.Users().List(ctx) assert.Nil(t, err) assert.NotNil(t, res) @@ -36,6 +51,14 @@ func TestUsers(t *testing.T) { }) t.Run("whoami", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/users/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/users/get__whoami.json")), + ) + res, err := c.Users().WhoAmI(ctx) assert.Nil(t, err) assert.NotNil(t, res) diff --git a/maasclient/zone_test.go b/maasclient/zone_test.go index 5ceeb6b..bb3b4ab 100644 --- a/maasclient/zone_test.go +++ b/maasclient/zone_test.go @@ -18,17 +18,32 @@ package maasclient import ( "context" - "github.com/stretchr/testify/assert" - "os" + "net/http" "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) func TestZones(t *testing.T) { - c := NewAuthenticatedClientSet(os.Getenv("MAAS_ENDPOINT"), os.Getenv("MAAS_API_KEY")) + httpClient := &http.Client{} + + httpmock.ActivateNonDefault(httpClient) + t.Cleanup(httpmock.DeactivateAndReset) + + c := NewAuthenticatedClientSet("http://maas.test", "dummy-api-key", func(client *authenticatedClientSet) { client.WithHTTPClient(httpClient) }) ctx := context.Background() t.Run("list zones", func(t *testing.T) { + defer httpmock.Reset() + + httpmock.RegisterResponder( + http.MethodGet, + "http://maas.test/api/2.0/zones/", + httpmock.NewJsonResponderOrPanic(200, httpmock.File("testdata/zones/list__all.json")), + ) + zones, err := c.Zones().List(ctx) assert.Nil(t, err) assert.NotNil(t, zones)