Skip to content
This repository has been archived by the owner on Jul 27, 2023. It is now read-only.

feat(storagezone): add the ability to add, get, list, and remove stor… #19

Merged
merged 4 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18

- name: build
run: go build -v ./...
Expand All @@ -30,7 +30,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18

- name: Test
run: go test -v -race ./...
Expand All @@ -41,4 +41,4 @@ jobs:
- uses: actions/checkout@v2

- name: golangci-lint
run: docker run -v $GITHUB_WORKSPACE:/repo -w /repo golangci/golangci-lint:v1.42 golangci-lint run
run: docker run -v $GITHUB_WORKSPACE:/repo -w /repo golangci/golangci-lint:v1.46 golangci-lint run
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ Endpoints](https://docs.bunny.net/reference/bunnynet-api-overview) are supported
- [ ] Remove Blocked IP
- [ ] Purge
- [ ] Statistics
- [ ] Storage Zone
- [ ] [Storage Zone](https://docs.bunny.net/reference/storagezonepublic_index)
- [x] List Storage Zones
- [x] Add Storage Zone
- [x] Get Storage Zone
- [x] Update Storage Zone
- [x] Delete Storage Zone
- [ ] Reset Password
- [ ] Reset Read-Only Password
- [ ] User
- [ ] Edge Storage API
- [ ] Stream API
Expand Down
12 changes: 10 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"reflect"

"github.com/google/go-querystring/query"
"github.com/google/uuid"
Expand Down Expand Up @@ -44,9 +45,13 @@ type Client struct {
logf Logf
userAgent string

PullZone *PullZoneService
PullZone *PullZoneService
StorageZone *StorageZoneService
}

// NoContentResponse is a special struct that should be used for requests that return a 204 response
type NoContentResponse struct{}

var discardLogF = func(string, ...interface{}) {}

// NewClient returns a new bunny.net API client.
Expand All @@ -65,6 +70,7 @@ func NewClient(APIKey string, opts ...Option) *Client {
}

clt.PullZone = &PullZoneService{client: &clt}
clt.StorageZone = &StorageZoneService{client: &clt}

for _, opt := range opts {
opt(&clt)
Expand Down Expand Up @@ -301,7 +307,9 @@ func (c *Client) unmarshalHTTPJSONBody(resp *http.Response, reqURL string, resul
}

if len(body) == 0 {
if result != nil {
var nc *NoContentResponse
isNoContent := reflect.TypeOf(result) == reflect.TypeOf(nc)
if result != nil && !isNoContent {
return &HTTPError{
RequestURL: reqURL,
StatusCode: resp.StatusCode,
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/simplesurance/bunny-go

go 1.17
go 1.18

require (
github.com/google/go-querystring v1.1.0
Expand Down
36 changes: 35 additions & 1 deletion integrationtest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const envVarApiKeyName = "BUNNY_API_KEY"
// pullzoneNamePrefix is the prefix for all pullzones created by the integrationtests.
const pullzoneNamePrefix = "bunny-go-test-"

// pullzoneNamePrefix is the prefix for all pullzones created by the integrationtests.
const storagezoneNamePrefix = "bunny-go-test-storage-"

func newClient(t *testing.T) *bunny.Client {
t.Helper()

Expand All @@ -34,6 +37,10 @@ func randomPullZoneName() string {
return pullzoneNamePrefix + uuid.New().String()
}

func randomStorageZoneName() string {
return storagezoneNamePrefix + uuid.New().String()
}

// createPullZone creates a Pull Zone via the bunny client and registers a
// testing cleanup function to remove it when the test terminates.
// If creating the Pull Zone fails, t.Fatal is called.
Expand All @@ -50,7 +57,7 @@ func createPullZone(t *testing.T, clt *bunny.Client, opts *bunny.PullZoneAddOpti
t.Cleanup(func() {
err := clt.PullZone.Delete(context.Background(), *pz.ID)
if err != nil {
t.Errorf("coult not delete pull zone (id: %d, name: %q) on test cleanup: %s", *pz.ID, *pz.Name, err)
t.Errorf("could not delete pull zone (id: %d, name: %q) on test cleanup: %s", *pz.ID, *pz.Name, err)
return

}
Expand All @@ -59,3 +66,30 @@ func createPullZone(t *testing.T, clt *bunny.Client, opts *bunny.PullZoneAddOpti

return pz
}


// createStorageZone creates a Storage Zone via the bunny client and registers a
// testing cleanup function to remove it when the test terminates.
// If creating the Storage Zone fails, t.Fatal is called.
func createStorageZone(t *testing.T, clt *bunny.Client, opts *bunny.StorageZoneAddOptions) *bunny.StorageZone {
t.Helper()

pz, err := clt.StorageZone.Add(context.Background(), opts)
require.NoError(t, err, "creating storage zone failed")
require.NotNil(t, pz.ID, "add returned storage zone with nil id")
require.NotNil(t, pz.Name, "add returned storage zone with nil name")

t.Logf("created storage zone: %q, id: %d", *pz.Name, *pz.ID)

t.Cleanup(func() {
err := clt.StorageZone.Delete(context.Background(), *pz.ID)
if err != nil {
t.Errorf("could not delete storage zone (id: %d, name: %q) on test cleanup: %s", *pz.ID, *pz.Name, err)
return

}
t.Logf("cleanup: deleted storage zone: %q, id: %d", *pz.Name, *pz.ID)
})

return pz
}
18 changes: 6 additions & 12 deletions pullzone_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,10 @@ type PullZoneAddOptions struct {
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_add
func (s *PullZoneService) Add(ctx context.Context, opts *PullZoneAddOptions) (*PullZone, error) {
var res PullZone

req, err := s.client.newPostRequest("/pullzone", opts)
if err != nil {
return nil, err
}

if err := s.client.sendRequest(ctx, req, &res); err != nil {
return nil, err
}

return &res, nil
return resourcePost[PullZone](
ctx,
s.client,
"/pullzone",
opts,
)
}
10 changes: 3 additions & 7 deletions pullzone_add_custom_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ type PullZoneAddCustomCertificateOptions struct {
// AddCustomCertificate represents the Add Custom Certificate API Endpoint.
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_addcertificate
func (s *PullZoneService) AddCustomCertificate(ctx context.Context, pullZoneID int64, options *PullZoneAddCustomCertificateOptions) error {
req, err := s.client.newPostRequest(fmt.Sprintf("/pullzone/%d/addCertificate", pullZoneID), options)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
func (s *PullZoneService) AddCustomCertificate(ctx context.Context, pullZoneID int64, opts *PullZoneAddCustomCertificateOptions) error {
path := fmt.Sprintf("/pullzone/%d/addCertificate", pullZoneID)
return resourcePostWith204Response(ctx, s.client, path, opts)
}
8 changes: 2 additions & 6 deletions pullzone_add_custom_hostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ type AddCustomHostnameOptions struct {
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_addhostname
func (s *PullZoneService) AddCustomHostname(ctx context.Context, pullZoneID int64, opts *AddCustomHostnameOptions) error {
req, err := s.client.newPostRequest(fmt.Sprintf("pullzone/%d/addHostname", pullZoneID), opts)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
path := fmt.Sprintf("pullzone/%d/addHostname", pullZoneID)
return resourcePostWith204Response(ctx, s.client, path, opts)
}
8 changes: 2 additions & 6 deletions pullzone_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import (
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_delete
func (s *PullZoneService) Delete(ctx context.Context, id int64) error {
req, err := s.client.newDeleteRequest(fmt.Sprintf("pullzone/%d", id), nil)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
path := fmt.Sprintf("pullzone/%d", id)
return resourceDelete(ctx, s.client, path, nil)
}
8 changes: 2 additions & 6 deletions pullzone_edgerule_add_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ type AddOrUpdateEdgeRuleOptions struct {
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_addedgerule
func (s *PullZoneService) AddOrUpdateEdgeRule(ctx context.Context, pullZoneID int64, opts *AddOrUpdateEdgeRuleOptions) error {
req, err := s.client.newPostRequest(fmt.Sprintf("pullzone/%d/edgerules/addOrUpdate", pullZoneID), opts)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
path := fmt.Sprintf("pullzone/%d/edgerules/addOrUpdate", pullZoneID)
return resourcePostWith204Response(ctx, s.client, path, opts)
}
8 changes: 2 additions & 6 deletions pullzone_edgerule_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import (
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_deleteedgerule
func (s *PullZoneService) DeleteEdgeRule(ctx context.Context, pullZoneID int64, edgeRuleGUID string) error {
req, err := s.client.newDeleteRequest(fmt.Sprintf("pullzone/%d/edgerules/%s", pullZoneID, edgeRuleGUID), nil)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
path := fmt.Sprintf("pullzone/%d/edgerules/%s", pullZoneID, edgeRuleGUID)
return resourceDelete(ctx, s.client, path, nil)
}
8 changes: 2 additions & 6 deletions pullzone_edgerule_set_enabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ func (s *PullZoneService) SetEdgeRuleEnabled(ctx context.Context, pullZoneID int
}
}

req, err := s.client.newPostRequest(fmt.Sprintf("pullzone/%d/edgerules/%s/setEdgeRuleEnabled", pullZoneID, edgeRuleGUID), opts)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
path := fmt.Sprintf("pullzone/%d/edgerules/%s/setEdgeRuleEnabled", pullZoneID, edgeRuleGUID)
return resourcePostWith204Response(ctx, s.client, path, opts)
}
14 changes: 2 additions & 12 deletions pullzone_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,6 @@ type EdgeRule struct {
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_index2
func (s *PullZoneService) Get(ctx context.Context, id int64) (*PullZone, error) {
var res PullZone

req, err := s.client.newGetRequest(fmt.Sprintf("pullzone/%d", id), nil)
if err != nil {
return nil, err
}

if err := s.client.sendRequest(ctx, req, &res); err != nil {
return nil, err
}

return &res, err
path := fmt.Sprintf("pullzone/%d", id)
return resourceGet[PullZone](ctx, s.client, path)
}
74 changes: 6 additions & 68 deletions pullzone_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,19 @@ package bunny

import "context"

const (
// DefaultPaginationPage is the default value that is used for
// PullZonePaginationOptions.Page if it is unset.
DefaultPaginationPage = 1
// DefaultPaginationPerPage is the default value that is used for
// PullZonePaginationOptions.PerPage if it is unset.
DefaultPaginationPerPage = 1000
)

// PullZones represents the response of the List Pull Zone API endpoint.
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_index
type PullZones struct {
Items []*PullZone `json:"Items,omitempty"`
PullZonePaginationReply
}

// PullZonePaginationReply represents the pagination information contained in a
// Pull Zone List API endpoint response.
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_index
type PullZonePaginationReply struct {
CurrentPage *int32 `json:"CurrentPage"`
TotalItems *int32 `json:"TotalItems"`
HasMoreItems *bool `json:"HasMoreItems"`
}

// PullZonePaginationOptions specifies optional parameters for List APIs.
type PullZonePaginationOptions struct {
// Page the page to return
Page int32 `url:"page,omitempty"`
// PerPage how many entries to return per page
PerPage int32 `url:"per_page,omitempty"`
}
type PullZones PaginationReply[PullZone]

// List retrieves the Pull Zones.
// If opts is nil, DefaultPaginationPerPage and DefaultPaginationPage will be used.
// if opts.Page or or opts.PerPage is < 1, the related DefaultPagination values are used.
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_index
func (s *PullZoneService) List(ctx context.Context, opts *PullZonePaginationOptions) (*PullZones, error) {
var res PullZones

// Ensure that opts.Page is >=1, if it isn't bunny.net will send a
// different response JSON object, that contains only a single
// PullZone, without items and paginations fields.
// Enforcing opts.page =>1 ensures that we always unmarshal into the
// same struct.
if opts == nil {
opts = &PullZonePaginationOptions{
Page: DefaultPaginationPage,
PerPage: DefaultPaginationPerPage,
}
} else {
opts.ensureConstraints()
}

req, err := s.client.newGetRequest("/pullzone", opts)
if err != nil {
return nil, err
}

if err := s.client.sendRequest(ctx, req, &res); err != nil {
return nil, err
}

return &res, nil
}

func (p *PullZonePaginationOptions) ensureConstraints() {
if p.Page < 1 {
p.Page = DefaultPaginationPage
}

if p.PerPage < 1 {
p.PerPage = DefaultPaginationPerPage
}
func (s *PullZoneService) List(
ctx context.Context,
opts *PaginationOptions,
) (*PullZones, error) {
return resourceList[PullZones](ctx, s.client, "/pullzone", opts)
}
10 changes: 3 additions & 7 deletions pullzone_remove_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ type RemoveCertificateOptions struct {
// RemoveCertificate represents the Remove Certificate API Endpoint.
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_removecertificate
func (s *PullZoneService) RemoveCertificate(ctx context.Context, pullZoneID int64, options *RemoveCertificateOptions) error {
req, err := s.client.newDeleteRequest(fmt.Sprintf("/pullzone/%d/removeCertificate", pullZoneID), options)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
func (s *PullZoneService) RemoveCertificate(ctx context.Context, pullZoneID int64, opts *RemoveCertificateOptions) error {
path := fmt.Sprintf("/pullzone/%d/removeCertificate", pullZoneID)
return resourceDelete(ctx, s.client, path, opts)
}
8 changes: 2 additions & 6 deletions pullzone_remove_custom_hostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ type RemoveCustomHostnameOptions struct {
//
// Bunny.net API docs: https://docs.bunny.net/reference/pullzonepublic_removehostname
func (s *PullZoneService) RemoveCustomHostname(ctx context.Context, pullZoneID int64, opts *RemoveCustomHostnameOptions) error {
req, err := s.client.newDeleteRequest(fmt.Sprintf("pullzone/%d/removeHostname", pullZoneID), opts)
if err != nil {
return err
}

return s.client.sendRequest(ctx, req, nil)
path := fmt.Sprintf("pullzone/%d/removeHostname", pullZoneID)
return resourceDelete(ctx, s.client, path, opts)
}
Loading