From dd8973b7f72e4b153f7f135e4af8e89c66d3666d Mon Sep 17 00:00:00 2001 From: cojenco Date: Fri, 29 Apr 2022 15:27:50 -0700 Subject: [PATCH] chore(storage): implement ListBucketACLs and ListDefaultObjectACLs (#5965) Adds HTTP and gRPC implementations for ListBucketACLs and ListDefaultObjectACL. gRPC methods use bucket.Get under the hood because the ACL methods are not supported. Co-authored-by: Chris Cotter --- storage/client_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++ storage/grpc_client.go | 12 ++++++++++-- storage/http_client.go | 42 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/storage/client_test.go b/storage/client_test.go index 6d0f4df503a..b86d876342d 100644 --- a/storage/client_test.go +++ b/storage/client_test.go @@ -373,6 +373,50 @@ func TestListBucketsEmulated(t *testing.T) { }) } +func TestListBucketACLsEmulated(t *testing.T) { + transportClientTest(t, func(t *testing.T, project, bucket string, client storageClient) { + ctx := context.Background() + attrs := &BucketAttrs{ + Name: bucket, + PredefinedACL: "publicRead", + } + // Create the bucket that will be retrieved. + if _, err := client.CreateBucket(ctx, project, attrs); err != nil { + t.Fatalf("client.CreateBucket: %v", err) + } + + acls, err := client.ListBucketACLs(ctx, bucket) + if err != nil { + t.Fatalf("client.ListBucketACLs: %v", err) + } + if want, got := len(acls), 2; want != got { + t.Errorf("ListBucketACLs: got %v, want %v items", acls, want) + } + }) +} + +func TestListDefaultObjectACLsEmulated(t *testing.T) { + transportClientTest(t, func(t *testing.T, project, bucket string, client storageClient) { + ctx := context.Background() + attrs := &BucketAttrs{ + Name: bucket, + PredefinedDefaultObjectACL: "publicRead", + } + // Create the bucket that will be retrieved. + if _, err := client.CreateBucket(ctx, project, attrs); err != nil { + t.Fatalf("client.CreateBucket: %v", err) + } + + acls, err := client.ListDefaultObjectACLs(ctx, bucket) + if err != nil { + t.Fatalf("client.ListDefaultObjectACLs: %v", err) + } + if want, got := len(acls), 2; want != got { + t.Errorf("ListDefaultObjectACLs: got %v, want %v items", acls, want) + } + }) +} + func initEmulatorClients() func() error { noopCloser := func() error { return nil } if !isEmulatorEnvironmentSet() { diff --git a/storage/grpc_client.go b/storage/grpc_client.go index 7952f0c5e0e..ef84e2ba6e7 100644 --- a/storage/grpc_client.go +++ b/storage/grpc_client.go @@ -403,7 +403,11 @@ func (c *grpcStorageClient) DeleteDefaultObjectACL(ctx context.Context, bucket s return errMethodNotSupported } func (c *grpcStorageClient) ListDefaultObjectACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error) { - return nil, errMethodNotSupported + attrs, err := c.GetBucket(ctx, bucket, nil, opts...) + if err != nil { + return nil, err + } + return attrs.DefaultObjectACL, nil } func (c *grpcStorageClient) UpdateDefaultObjectACL(ctx context.Context, opts ...storageOption) (*ACLRule, error) { return nil, errMethodNotSupported @@ -415,7 +419,11 @@ func (c *grpcStorageClient) DeleteBucketACL(ctx context.Context, bucket string, return errMethodNotSupported } func (c *grpcStorageClient) ListBucketACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error) { - return nil, errMethodNotSupported + attrs, err := c.GetBucket(ctx, bucket, nil, opts...) + if err != nil { + return nil, err + } + return attrs.ACL, nil } func (c *grpcStorageClient) UpdateBucketACL(ctx context.Context, bucket string, entity ACLEntity, role ACLRole, opts ...storageOption) (*ACLRule, error) { return nil, errMethodNotSupported diff --git a/storage/http_client.go b/storage/http_client.go index 8ab5f0314f2..be4e9b3c752 100644 --- a/storage/http_client.go +++ b/storage/http_client.go @@ -21,6 +21,7 @@ import ( "net/http" "net/url" "os" + "reflect" "strings" "golang.org/x/oauth2/google" @@ -381,8 +382,21 @@ func (c *httpStorageClient) UpdateObject(ctx context.Context, bucket, object str func (c *httpStorageClient) DeleteDefaultObjectACL(ctx context.Context, bucket string, entity ACLEntity, opts ...storageOption) error { return errMethodNotSupported } + func (c *httpStorageClient) ListDefaultObjectACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error) { - return nil, errMethodNotSupported + s := callSettings(c.settings, opts...) + var acls *raw.ObjectAccessControls + var err error + err = run(ctx, func() error { + req := c.raw.DefaultObjectAccessControls.List(bucket) + configureACLCall(ctx, s.userProject, req) + acls, err = req.Do() + return err + }, s.retry, true) + if err != nil { + return nil, err + } + return toObjectACLRules(acls.Items), nil } func (c *httpStorageClient) UpdateDefaultObjectACL(ctx context.Context, opts ...storageOption) (*ACLRule, error) { return nil, errMethodNotSupported @@ -394,8 +408,32 @@ func (c *httpStorageClient) DeleteBucketACL(ctx context.Context, bucket string, return errMethodNotSupported } func (c *httpStorageClient) ListBucketACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error) { - return nil, errMethodNotSupported + s := callSettings(c.settings, opts...) + var acls *raw.BucketAccessControls + var err error + err = run(ctx, func() error { + req := c.raw.BucketAccessControls.List(bucket) + configureACLCall(ctx, s.userProject, req) + acls, err = req.Do() + return err + }, s.retry, true) + if err != nil { + return nil, err + } + return toBucketACLRules(acls.Items), nil } + +// configureACLCall sets the context, user project and headers on the apiary library call. +// This will panic if the call does not have the correct methods. +func configureACLCall(ctx context.Context, userProject string, call interface{ Header() http.Header }) { + vc := reflect.ValueOf(call) + vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)}) + if userProject != "" { + vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(userProject)}) + } + setClientHeader(call.Header()) +} + func (c *httpStorageClient) UpdateBucketACL(ctx context.Context, bucket string, entity ACLEntity, role ACLRole, opts ...storageOption) (*ACLRule, error) { return nil, errMethodNotSupported }