From c4d94361f250719ab14dca3e6507e4d0e1953177 Mon Sep 17 00:00:00 2001 From: Dane Elwell Date: Tue, 12 Nov 2024 16:35:51 +0000 Subject: [PATCH] Add support for backup gateways, agent-level props --- pkg/service/ecloud/error.go | 18 + pkg/service/ecloud/model.go | 25 + pkg/service/ecloud/request.go | 11 + pkg/service/ecloud/service.go | 15 + pkg/service/ecloud/service_backupgateway.go | 168 +++++++ .../ecloud/service_backupgateway_specs.go | 57 +++ .../service_backupgateway_specs_test.go | 140 ++++++ .../ecloud/service_backupgateway_test.go | 440 ++++++++++++++++++ 8 files changed, 874 insertions(+) create mode 100644 pkg/service/ecloud/service_backupgateway.go create mode 100644 pkg/service/ecloud/service_backupgateway_specs.go create mode 100644 pkg/service/ecloud/service_backupgateway_specs_test.go create mode 100644 pkg/service/ecloud/service_backupgateway_test.go diff --git a/pkg/service/ecloud/error.go b/pkg/service/ecloud/error.go index 5d05fd4..2517938 100644 --- a/pkg/service/ecloud/error.go +++ b/pkg/service/ecloud/error.go @@ -496,3 +496,21 @@ type VPNGatewayUserNotFoundError struct { func (e *VPNGatewayUserNotFoundError) Error() string { return fmt.Sprintf("VPN gateway user not found with ID [%s]", e.ID) } + +// BackupGatewaySpecificationNotFoundError represents a VPN gateway specification not found error +type BackupGatewaySpecificationNotFoundError struct { + ID string +} + +func (e *BackupGatewaySpecificationNotFoundError) Error() string { + return fmt.Sprintf("Backup gateway specification not found with ID [%s]", e.ID) +} + +// BackupGatewayNotFoundError represents a backup gateway not found error +type BackupGatewayNotFoundError struct { + ID string +} + +func (e *BackupGatewayNotFoundError) Error() string { + return fmt.Sprintf("Backup gateway not found with ID [%s]", e.ID) +} diff --git a/pkg/service/ecloud/model.go b/pkg/service/ecloud/model.go index ad45cd7..53f66c9 100644 --- a/pkg/service/ecloud/model.go +++ b/pkg/service/ecloud/model.go @@ -1065,3 +1065,28 @@ type VPNGatewayUser struct { CreatedAt connection.DateTime `json:"created_at"` UpdatedAt connection.DateTime `json:"updated_at"` } + +// BackupGatewaySpecification represents a Backup Gateway specification +type BackupGatewaySpecification struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + CPU int `json:"cpu"` + RAM int `json:"ram"` + IopsID string `json:"iops_id"` + VolumeCapacity int `json:"volume_capacity"` + ImageID string `json:"image_id"` +} + +// BackupGateway represents a Backup Gateway +type BackupGateway struct { + ID string `json:"id"` + VPCID string `json:"vpc_id"` + Name string `json:"name"` + AvailabilityZoneID string `json:"availability_zone_id"` + GatewaySpecID string `json:"gateway_spec_id"` + Sync ResourceSync `json:"sync"` + Task ResourceTask `json:"task"` + CreatedAt connection.DateTime `json:"created_at"` + UpdatedAt connection.DateTime `json:"updated_at"` +} diff --git a/pkg/service/ecloud/request.go b/pkg/service/ecloud/request.go index 87799dc..7f36bfa 100644 --- a/pkg/service/ecloud/request.go +++ b/pkg/service/ecloud/request.go @@ -664,3 +664,14 @@ type PatchVPNGatewayUserRequest struct { Name string `json:"name,omitempty"` Password string `json:"password,omitempty"` } + +type CreateBackupGatewayRequest struct { + Name string `json:"name,omitempty"` + VPCID string `json:"vpc_id"` + RouterID string `json:"router_id"` + GatewaySpecID string `json:"gateway_spec_id"` +} + +type PatchBackupGatewayRequest struct { + Name string `json:"name"` +} diff --git a/pkg/service/ecloud/service.go b/pkg/service/ecloud/service.go index 3323370..f3044c3 100644 --- a/pkg/service/ecloud/service.go +++ b/pkg/service/ecloud/service.go @@ -485,6 +485,21 @@ type ECloudService interface { GetIOPSTiers(parameters connection.APIRequestParameters) ([]IOPSTier, error) GetIOPSTiersPaginated(parameters connection.APIRequestParameters) (*connection.Paginated[IOPSTier], error) GetIOPSTier(iopsID string) (IOPSTier, error) + + // Backup Gateway Specifications + GetBackupGatewaySpecifications(parameters connection.APIRequestParameters) ([]BackupGatewaySpecification, error) + GetBackupGatewaySpecificationsPaginated(parameters connection.APIRequestParameters) (*connection.Paginated[BackupGatewaySpecification], error) + GetBackupGatewaySpecification(specificationID string) (BackupGatewaySpecification, error) + + // Backup Gateways + GetBackupGateways(parameters connection.APIRequestParameters) ([]BackupGateway, error) + GetBackupGatewaysPaginated(parameters connection.APIRequestParameters) (*connection.Paginated[BackupGateway], error) + GetBackupGateway(gatewayID string) (BackupGateway, error) + CreateBackupGateway(req CreateBackupGatewayRequest) (TaskReference, error) + PatchBackupGateway(gatewayID string, req PatchBackupGatewayRequest) (TaskReference, error) + DeleteBackupGateway(gatewayID string) (string, error) + GetBackupGatewayTasks(gatewayID string, parameters connection.APIRequestParameters) ([]Task, error) + GetBackupGatewayTasksPaginated(gatewayID string, parameters connection.APIRequestParameters) (*connection.Paginated[Task], error) } // Service implements ECloudService for managing diff --git a/pkg/service/ecloud/service_backupgateway.go b/pkg/service/ecloud/service_backupgateway.go new file mode 100644 index 0000000..1ae140b --- /dev/null +++ b/pkg/service/ecloud/service_backupgateway.go @@ -0,0 +1,168 @@ +package ecloud + +import ( + "fmt" + + "github.com/ans-group/sdk-go/pkg/connection" +) + +// GetBackupGateways retrieves a list of backup gateways +func (s *Service) GetBackupGateways(parameters connection.APIRequestParameters) ([]BackupGateway, error) { + return connection.InvokeRequestAll(s.GetBackupGatewaysPaginated, parameters) +} + +// GetBackupGatewaysPaginated retrieves a paginated list of backup gateways +func (s *Service) GetBackupGatewaysPaginated(parameters connection.APIRequestParameters) (*connection.Paginated[BackupGateway], error) { + body, err := s.getBackupGatewaysPaginatedResponseBody(parameters) + return connection.NewPaginated(body, parameters, s.GetBackupGatewaysPaginated), err +} + +func (s *Service) getBackupGatewaysPaginatedResponseBody(parameters connection.APIRequestParameters) (*connection.APIResponseBodyData[[]BackupGateway], error) { + body := &connection.APIResponseBodyData[[]BackupGateway]{} + + response, err := s.connection.Get("/ecloud/v2/backup-gateways", parameters) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, nil) +} + +// GetBackupGateway retrieves a single backup gateway by ID +func (s *Service) GetBackupGateway(gatewayID string) (BackupGateway, error) { + body, err := s.getBackupGatewayResponseBody(gatewayID) + + return body.Data, err +} + +func (s *Service) getBackupGatewayResponseBody(gatewayID string) (*connection.APIResponseBodyData[BackupGateway], error) { + body := &connection.APIResponseBodyData[BackupGateway]{} + + if gatewayID == "" { + return body, fmt.Errorf("invalid backup gateway id") + } + + response, err := s.connection.Get(fmt.Sprintf("/ecloud/v2/backup-gateways/%s", gatewayID), connection.APIRequestParameters{}) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, func(resp *connection.APIResponse) error { + if response.StatusCode == 404 { + return &BackupGatewayNotFoundError{ID: gatewayID} + } + + return nil + }) +} + +// CreateBackupGateway creates a new backup gateway +func (s *Service) CreateBackupGateway(req CreateBackupGatewayRequest) (TaskReference, error) { + body, err := s.createBackupGatewayResponseBody(req) + + return body.Data, err +} + +func (s *Service) createBackupGatewayResponseBody(req CreateBackupGatewayRequest) (*connection.APIResponseBodyData[TaskReference], error) { + body := &connection.APIResponseBodyData[TaskReference]{} + + response, err := s.connection.Post("/ecloud/v2/backup-gateways", &req) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, nil) +} + +// PatchBackupGateway patches a backup gateway +func (s *Service) PatchBackupGateway(gatewayID string, req PatchBackupGatewayRequest) (TaskReference, error) { + body, err := s.patchBackupGatewayResponseBody(gatewayID, req) + + return body.Data, err +} + +func (s *Service) patchBackupGatewayResponseBody(gatewayID string, req PatchBackupGatewayRequest) (*connection.APIResponseBodyData[TaskReference], error) { + body := &connection.APIResponseBodyData[TaskReference]{} + + if gatewayID == "" { + return body, fmt.Errorf("invalid gateway id") + } + + response, err := s.connection.Patch(fmt.Sprintf("/ecloud/v2/backup-gateways/%s", gatewayID), &req) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, func(resp *connection.APIResponse) error { + if response.StatusCode == 404 { + return &BackupGatewayNotFoundError{ID: gatewayID} + } + + return nil + }) +} + +// DeleteBackupGateway deletes a backup gateway +func (s *Service) DeleteBackupGateway(gatewayID string) (string, error) { + body, err := s.deleteBackupGatewayResponseBody(gatewayID) + + return body.Data.TaskID, err +} + +func (s *Service) deleteBackupGatewayResponseBody(gatewayID string) (*connection.APIResponseBodyData[TaskReference], error) { + body := &connection.APIResponseBodyData[TaskReference]{} + + if gatewayID == "" { + return body, fmt.Errorf("invalid gateway id") + } + + response, err := s.connection.Delete(fmt.Sprintf("/ecloud/v2/backup-gateways/%s", gatewayID), nil) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, func(resp *connection.APIResponse) error { + if response.StatusCode == 404 { + return &BackupGatewayNotFoundError{ID: gatewayID} + } + + return nil + }) +} + +// GetBackupGatewayTasks retrieves a list of backup gateway tasks +func (s *Service) GetBackupGatewayTasks(gatewayID string, parameters connection.APIRequestParameters) ([]Task, error) { + return connection.InvokeRequestAll(func(p connection.APIRequestParameters) (*connection.Paginated[Task], error) { + return s.GetBackupGatewayTasksPaginated(gatewayID, p) + }, parameters) +} + +// GetBackupGatewayTasksPaginated retrieves a paginated list of backup gateway tasks +func (s *Service) GetBackupGatewayTasksPaginated(gatewayID string, parameters connection.APIRequestParameters) (*connection.Paginated[Task], error) { + body, err := s.getBackupGatewayTasksPaginatedResponseBody(gatewayID, parameters) + + return connection.NewPaginated(body, parameters, func(p connection.APIRequestParameters) (*connection.Paginated[Task], error) { + return s.GetBackupGatewayTasksPaginated(gatewayID, p) + }), err +} + +func (s *Service) getBackupGatewayTasksPaginatedResponseBody(gatewayID string, parameters connection.APIRequestParameters) (*connection.APIResponseBodyData[[]Task], error) { + body := &connection.APIResponseBodyData[[]Task]{} + + if gatewayID == "" { + return body, fmt.Errorf("invalid backup gateway id") + } + + response, err := s.connection.Get(fmt.Sprintf("/ecloud/v2/backup-gateways/%s/tasks", gatewayID), parameters) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, func(resp *connection.APIResponse) error { + if response.StatusCode == 404 { + return &BackupGatewayNotFoundError{ID: gatewayID} + } + + return nil + }) +} diff --git a/pkg/service/ecloud/service_backupgateway_specs.go b/pkg/service/ecloud/service_backupgateway_specs.go new file mode 100644 index 0000000..b9b49da --- /dev/null +++ b/pkg/service/ecloud/service_backupgateway_specs.go @@ -0,0 +1,57 @@ +package ecloud + +import ( + "fmt" + + "github.com/ans-group/sdk-go/pkg/connection" +) + +// GetBackupGatewaySpecifications retrieves a list of Backup gateway specifications +func (s *Service) GetBackupGatewaySpecifications(parameters connection.APIRequestParameters) ([]BackupGatewaySpecification, error) { + return connection.InvokeRequestAll(s.GetBackupGatewaySpecificationsPaginated, parameters) +} + +// GetBackupGatewaySpecificationsPaginated retrieves a paginated list of Backup gateway specifications +func (s *Service) GetBackupGatewaySpecificationsPaginated(parameters connection.APIRequestParameters) (*connection.Paginated[BackupGatewaySpecification], error) { + body, err := s.getBackupGatewaySpecificationsPaginatedResponseBody(parameters) + return connection.NewPaginated(body, parameters, s.GetBackupGatewaySpecificationsPaginated), err +} + +func (s *Service) getBackupGatewaySpecificationsPaginatedResponseBody(parameters connection.APIRequestParameters) (*connection.APIResponseBodyData[[]BackupGatewaySpecification], error) { + body := &connection.APIResponseBodyData[[]BackupGatewaySpecification]{} + + response, err := s.connection.Get("/ecloud/v2/backup-gateway-specs", parameters) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, nil) +} + +// GetBackupGatewaySpecification retrieves a single Backup gateway specification by ID +func (s *Service) GetBackupGatewaySpecification(specificationID string) (BackupGatewaySpecification, error) { + body, err := s.getBackupGatewaySpecificationResponseBody(specificationID) + + return body.Data, err +} + +func (s *Service) getBackupGatewaySpecificationResponseBody(specificationID string) (*connection.APIResponseBodyData[BackupGatewaySpecification], error) { + body := &connection.APIResponseBodyData[BackupGatewaySpecification]{} + + if specificationID == "" { + return body, fmt.Errorf("invalid backup gateway specification id") + } + + response, err := s.connection.Get(fmt.Sprintf("/ecloud/v2/backup-gateway-specs/%s", specificationID), connection.APIRequestParameters{}) + if err != nil { + return body, err + } + + return body, response.HandleResponse(body, func(resp *connection.APIResponse) error { + if response.StatusCode == 404 { + return &BackupGatewaySpecificationNotFoundError{ID: specificationID} + } + + return nil + }) +} diff --git a/pkg/service/ecloud/service_backupgateway_specs_test.go b/pkg/service/ecloud/service_backupgateway_specs_test.go new file mode 100644 index 0000000..d3406c4 --- /dev/null +++ b/pkg/service/ecloud/service_backupgateway_specs_test.go @@ -0,0 +1,140 @@ +package ecloud + +import ( + "bytes" + "errors" + "io/ioutil" + "net/http" + "testing" + + "github.com/ans-group/sdk-go/pkg/connection" + "github.com/ans-group/sdk-go/test/mocks" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestGetBackupGatewaySpecifications(t *testing.T) { + t.Run("Single", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateway-specs", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":[{\"id\":\"bkupgs-abcdef12\"}],\"meta\":{\"pagination\":{\"total_pages\":1}}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + specs, err := s.GetBackupGatewaySpecifications(connection.APIRequestParameters{}) + + assert.Nil(t, err) + assert.Len(t, specs, 1) + assert.Equal(t, "bkupgs-abcdef12", specs[0].ID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateway-specs", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")) + + _, err := s.GetBackupGatewaySpecifications(connection.APIRequestParameters{}) + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) +} + +func TestGetBackupGatewaySpecification(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateway-specs/bkupgs-abcdef12", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":{\"id\":\"bkupgs-abcdef12\"}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + spec, err := s.GetBackupGatewaySpecification("bkupgs-abcdef12") + + assert.Nil(t, err) + assert.Equal(t, "bkupgs-abcdef12", spec.ID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateway-specs/bkupgs-abcdef12", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")).Times(1) + + _, err := s.GetBackupGatewaySpecification("bkupgs-abcdef12") + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) + + t.Run("InvalidBackupGatewaySpecificationID_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + _, err := s.GetBackupGatewaySpecification("") + + assert.NotNil(t, err) + assert.Equal(t, "invalid backup gateway specification id", err.Error()) + }) + + t.Run("404_ReturnsBackupGatewaySpecificationNotFoundError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateway-specs/bkupgs-abcdef12", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + StatusCode: 404, + }, + }, nil).Times(1) + + _, err := s.GetBackupGatewaySpecification("bkupgs-abcdef12") + + assert.NotNil(t, err) + assert.IsType(t, &BackupGatewaySpecificationNotFoundError{}, err) + }) +} diff --git a/pkg/service/ecloud/service_backupgateway_test.go b/pkg/service/ecloud/service_backupgateway_test.go new file mode 100644 index 0000000..079664a --- /dev/null +++ b/pkg/service/ecloud/service_backupgateway_test.go @@ -0,0 +1,440 @@ +package ecloud + +import ( + "bytes" + "errors" + "io/ioutil" + "net/http" + "testing" + + "github.com/ans-group/sdk-go/pkg/connection" + "github.com/ans-group/sdk-go/test/mocks" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestGetBackupGateways(t *testing.T) { + t.Run("Single", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":[{\"id\":\"bkupgw-abcdef12\"}],\"meta\":{\"pagination\":{\"total_pages\":1}}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + gateways, err := s.GetBackupGateways(connection.APIRequestParameters{}) + + assert.Nil(t, err) + assert.Len(t, gateways, 1) + assert.Equal(t, "bkupgw-abcdef12", gateways[0].ID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")) + + _, err := s.GetBackupGateways(connection.APIRequestParameters{}) + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) +} + +func TestGetBackupGateway(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways/bkupgw-abcdef12", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":{\"id\":\"bkupgw-abcdef12\"}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + gateway, err := s.GetBackupGateway("bkupgw-abcdef12") + + assert.Nil(t, err) + assert.Equal(t, "bkupgw-abcdef12", gateway.ID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways/bkupgw-abcdef12", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")).Times(1) + + _, err := s.GetBackupGateway("bkupgw-abcdef12") + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) + + t.Run("InvalidBackupGatewayID_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + _, err := s.GetBackupGateway("") + + assert.NotNil(t, err) + assert.Equal(t, "invalid backup gateway id", err.Error()) + }) + + t.Run("404_ReturnsBackupGatewayNotFoundError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways/bkupgw-abcdef12", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + StatusCode: 404, + }, + }, nil).Times(1) + + _, err := s.GetBackupGateway("bkupgw-abcdef12") + + assert.NotNil(t, err) + assert.IsType(t, &BackupGatewayNotFoundError{}, err) + }) +} + +func TestCreateBackupGateway(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + req := CreateBackupGatewayRequest{ + Name: "test", + } + + c.EXPECT().Post("/ecloud/v2/backup-gateways", &req).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":{\"id\":\"bkupgw-abcdef12\",\"task_id\":\"task-abcdef12\"}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + taskRef, err := s.CreateBackupGateway(req) + + assert.Nil(t, err) + assert.Equal(t, "bkupgw-abcdef12", taskRef.ResourceID) + assert.Equal(t, "task-abcdef12", taskRef.TaskID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Post("/ecloud/v2/backup-gateways", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")).Times(1) + + _, err := s.CreateBackupGateway(CreateBackupGatewayRequest{}) + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) +} + +func TestPatchBackupGateway(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + req := PatchBackupGatewayRequest{ + Name: "somegateway", + } + + c.EXPECT().Patch("/ecloud/v2/backup-gateways/bkupgw-abcdef12", &req).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":{\"id\":\"bkupgw-abcdef12\",\"task_id\":\"task-abcdef12\"}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + task, err := s.PatchBackupGateway("bkupgw-abcdef12", req) + + assert.Nil(t, err) + assert.Equal(t, "bkupgw-abcdef12", task.ResourceID) + assert.Equal(t, "task-abcdef12", task.TaskID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Patch("/ecloud/v2/backup-gateways/bkupgw-abcdef12", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")).Times(1) + + _, err := s.PatchBackupGateway("bkupgw-abcdef12", PatchBackupGatewayRequest{}) + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) + + t.Run("InvalidBackupGatewayID_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + _, err := s.PatchBackupGateway("", PatchBackupGatewayRequest{}) + + assert.NotNil(t, err) + assert.Equal(t, "invalid gateway id", err.Error()) + }) + + t.Run("404_ReturnsBackupGatewayNotFoundError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Patch("/ecloud/v2/backup-gateways/bkupgw-abcdef12", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + StatusCode: 404, + }, + }, nil).Times(1) + + _, err := s.PatchBackupGateway("bkupgw-abcdef12", PatchBackupGatewayRequest{}) + + assert.NotNil(t, err) + assert.IsType(t, &BackupGatewayNotFoundError{}, err) + }) +} + +func TestDeleteBackupGateway(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Delete("/ecloud/v2/backup-gateways/bkupgw-abcdef12", nil).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":{\"task_id\":\"task-abcdef12\"}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + taskID, err := s.DeleteBackupGateway("bkupgw-abcdef12") + + assert.Nil(t, err) + assert.Equal(t, "task-abcdef12", taskID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Delete("/ecloud/v2/backup-gateways/bkupgw-abcdef12", nil).Return(&connection.APIResponse{}, errors.New("test error 1")).Times(1) + + _, err := s.DeleteBackupGateway("bkupgw-abcdef12") + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) + + t.Run("InvalidBackupGatewayID_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + _, err := s.DeleteBackupGateway("") + + assert.NotNil(t, err) + assert.Equal(t, "invalid gateway id", err.Error()) + }) + + t.Run("404_ReturnsBackupGatewayNotFoundError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Delete("/ecloud/v2/backup-gateways/bkupgw-abcdef12", nil).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + StatusCode: 404, + }, + }, nil).Times(1) + + _, err := s.DeleteBackupGateway("bkupgw-abcdef12") + + assert.NotNil(t, err) + assert.IsType(t, &BackupGatewayNotFoundError{}, err) + }) +} + +func TestGetBackupGatewayTasks(t *testing.T) { + t.Run("Single", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways/bkupgw-abcdef12/tasks", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte("{\"data\":[{\"id\":\"task-abcdef12\"}],\"meta\":{\"pagination\":{\"total_pages\":1}}}"))), + StatusCode: 200, + }, + }, nil).Times(1) + + tasks, err := s.GetBackupGatewayTasks("bkupgw-abcdef12", connection.APIRequestParameters{}) + + assert.Nil(t, err) + assert.Len(t, tasks, 1) + assert.Equal(t, "task-abcdef12", tasks[0].ID) + }) + + t.Run("ConnectionError_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways/bkupgw-abcdef12/tasks", gomock.Any()).Return(&connection.APIResponse{}, errors.New("test error 1")) + + _, err := s.GetBackupGatewayTasks("bkupgw-abcdef12", connection.APIRequestParameters{}) + + assert.NotNil(t, err) + assert.Equal(t, "test error 1", err.Error()) + }) + + t.Run("InvalidBackupGatewayID_ReturnsError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + _, err := s.GetBackupGatewayTasks("", connection.APIRequestParameters{}) + + assert.NotNil(t, err) + assert.Equal(t, "invalid backup gateway id", err.Error()) + }) + + t.Run("404_ReturnsBackupGatewayNotFoundError", func(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + c := mocks.NewMockConnection(mockCtrl) + + s := Service{ + connection: c, + } + + c.EXPECT().Get("/ecloud/v2/backup-gateways/bkupgw-abcdef12/tasks", gomock.Any()).Return(&connection.APIResponse{ + Response: &http.Response{ + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + StatusCode: 404, + }, + }, nil).Times(1) + + _, err := s.GetBackupGatewayTasks("bkupgw-abcdef12", connection.APIRequestParameters{}) + + assert.NotNil(t, err) + assert.IsType(t, &BackupGatewayNotFoundError{}, err) + }) +}