Skip to content

Commit

Permalink
chore(storage): add Bucket Get & Delete implementations (#5775)
Browse files Browse the repository at this point in the history
* chore(storage): add Bucket Get & Delete implementations

* use errors instead of xerrors
  • Loading branch information
noahdietz authored Mar 23, 2022
1 parent 731705e commit dfda4d1
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 5 deletions.
26 changes: 26 additions & 0 deletions storage/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,32 @@ func applyBucketConds(method string, conds *BucketConditions, call interface{})
return nil
}

// applyBucketConds modifies the provided request message using the conditions
// in conds. msg is a protobuf Message that has fields if_metageneration_match
// and if_metageneration_not_match.
func applyBucketCondsProto(method string, conds *BucketConditions, msg proto.Message) error {
rmsg := msg.ProtoReflect()

if conds == nil {
return nil
}
if err := conds.validate(method); err != nil {
return err
}

switch {
case conds.MetagenerationMatch != 0:
if !setConditionProtoField(rmsg, "if_metageneration_match", conds.MetagenerationMatch) {
return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
}
case conds.MetagenerationNotMatch != 0:
if !setConditionProtoField(rmsg, "if_metageneration_not_match", conds.MetagenerationNotMatch) {
return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
}
}
return nil
}

func (rp *RetentionPolicy) toRawRetentionPolicy() *raw.BucketRetentionPolicy {
if rp == nil {
return nil
Expand Down
53 changes: 52 additions & 1 deletion storage/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestCreateBucketEmulated(t *testing.T) {
}
got, err := client.CreateBucket(context.Background(), project, want)
if err != nil {
t.Fatal(err)
t.Fatalf("%s, %v", transport, err)
}
want.Location = "US"
if diff := cmp.Diff(got.Name, want.Name); diff != "" {
Expand All @@ -49,6 +49,57 @@ func TestCreateBucketEmulated(t *testing.T) {
}
}

func TestDeleteBucketEmulated(t *testing.T) {
checkEmulatorEnvironment(t)

for transport, client := range emulatorClients {
project := fmt.Sprintf("%s-project", transport)
b := &BucketAttrs{
Name: fmt.Sprintf("%s-bucket-%d", transport, time.Now().Nanosecond()),
}
// Create the bucket that will be deleted.
_, err := client.CreateBucket(context.Background(), project, b)
if err != nil {
// Flag the error and continue so the Delete is skipped and the next
// transport can run its test.
t.Errorf("%s: %v", transport, err)
continue
}
// Delete the bucket that was just created.
err = client.DeleteBucket(context.Background(), b.Name, nil)
if err != nil {
t.Errorf("%s: %v", transport, err)
}
}
}

func TestGetBucketEmulated(t *testing.T) {
checkEmulatorEnvironment(t)

for transport, client := range emulatorClients {
project := fmt.Sprintf("%s-project", transport)
want := &BucketAttrs{
Name: fmt.Sprintf("%s-bucket-%d", transport, time.Now().Nanosecond()),
}
// Create the bucket that will be retrieved.
_, err := client.CreateBucket(context.Background(), project, want)
if err != nil {
// Flag the error and continue so the Get is skipped and the next
// transport can run its test.
t.Errorf("%s: %v", transport, err)
continue
}
got, err := client.GetBucket(context.Background(), want.Name, &BucketConditions{MetagenerationMatch: 1})
if err != nil {
t.Errorf("%s: %v", transport, err)
continue
}
if diff := cmp.Diff(got.Name, want.Name); diff != "" {
t.Errorf("%s: got(-),want(+):\n%s", transport, diff)
}
}
}

func initEmulatorClients() func() error {
noopCloser := func() error { return nil }
if !isEmulatorEnvironmentSet() {
Expand Down
48 changes: 46 additions & 2 deletions storage/grpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
iampb "google.golang.org/genproto/googleapis/iam/v1"
storagepb "google.golang.org/genproto/googleapis/storage/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

const (
Expand Down Expand Up @@ -144,10 +146,52 @@ func (c *grpcStorageClient) ListBuckets(ctx context.Context, project string, opt
// Bucket methods.

func (c *grpcStorageClient) DeleteBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error {
return errMethodNotSupported
s := callSettings(c.settings, opts...)
req := &storagepb.DeleteBucketRequest{
Name: bucketResourceName( /* project */ "_", bucket),
}
if err := applyBucketCondsProto("grpcStorageClient.DeleteBucket", conds, req); err != nil {
return err
}
if s.userProject != "" {
req.CommonRequestParams = &storagepb.CommonRequestParams{
UserProject: toProjectResource(s.userProject),
}
}

return run(ctx, func() error {
return c.raw.DeleteBucket(ctx, req, s.gax...)
}, s.retry, s.idempotent)
}

func (c *grpcStorageClient) GetBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) {
return nil, errMethodNotSupported
s := callSettings(c.settings, opts...)
req := &storagepb.GetBucketRequest{
Name: bucketResourceName( /* project */ "_", bucket),
}
if err := applyBucketCondsProto("grpcStorageClient.GetBucket", conds, req); err != nil {
return nil, err
}
if s.userProject != "" {
req.CommonRequestParams = &storagepb.CommonRequestParams{
UserProject: toProjectResource(s.userProject),
}
}

var battrs *BucketAttrs
err := run(ctx, func() error {
res, err := c.raw.GetBucket(ctx, req, s.gax...)

battrs = newBucketFromProto(res)

return err
}, s.retry, s.idempotent)

if s, ok := status.FromError(err); ok && s.Code() == codes.NotFound {
return nil, ErrBucketNotExist
}

return battrs, err
}
func (c *grpcStorageClient) UpdateBucket(ctx context.Context, uattrs *BucketAttrsToUpdate, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) {
return nil, errMethodNotSupported
Expand Down
41 changes: 39 additions & 2 deletions storage/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ package storage

import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"strings"

"golang.org/x/oauth2/google"
"google.golang.org/api/googleapi"
"google.golang.org/api/option"
"google.golang.org/api/option/internaloption"
raw "google.golang.org/api/storage/v1"
Expand Down Expand Up @@ -178,10 +180,45 @@ func (c *httpStorageClient) ListBuckets(ctx context.Context, project string, opt
// Bucket methods.

func (c *httpStorageClient) DeleteBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error {
return errMethodNotSupported
s := callSettings(c.settings, opts...)
req := c.raw.Buckets.Delete(bucket)
setClientHeader(req.Header())
if err := applyBucketConds("httpStorageClient.DeleteBucket", conds, req); err != nil {
return err
}
if s.userProject != "" {
req.UserProject(s.userProject)
}

return run(ctx, func() error { return req.Context(ctx).Do() }, s.retry, s.idempotent)
}

func (c *httpStorageClient) GetBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) {
return nil, errMethodNotSupported
s := callSettings(c.settings, opts...)
req := c.raw.Buckets.Get(bucket).Projection("full")
setClientHeader(req.Header())
err := applyBucketConds("httpStorageClient.GetBucket", conds, req)
if err != nil {
return nil, err
}
if s.userProject != "" {
req.UserProject(s.userProject)
}

var resp *raw.Bucket
err = run(ctx, func() error {
resp, err = req.Context(ctx).Do()
return err
}, s.retry, s.idempotent)

var e *googleapi.Error
if ok := errors.As(err, &e); ok && e.Code == http.StatusNotFound {
return nil, ErrBucketNotExist
}
if err != nil {
return nil, err
}
return newBucket(resp)
}
func (c *httpStorageClient) UpdateBucket(ctx context.Context, uattrs *BucketAttrsToUpdate, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) {
return nil, errMethodNotSupported
Expand Down

0 comments on commit dfda4d1

Please sign in to comment.