-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(storage): internal client interface design (#5426)
- Loading branch information
Showing
1 changed file
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
// Copyright 2022 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package storage | ||
|
||
import ( | ||
"context" | ||
|
||
gax "github.com/googleapis/gax-go/v2" | ||
iampb "google.golang.org/genproto/googleapis/iam/v1" | ||
) | ||
|
||
// TODO(noahdietz): Move existing factory methods to this file. | ||
|
||
// storageClient is an internal-only interface designed to separate the | ||
// transport-specific logic of making Storage API calls from the logic of the | ||
// client library. | ||
// | ||
// Implementation requirements beyond implementing the interface include: | ||
// * factory method(s) must accept a `userProject string` param | ||
// * `settings` must be retained per instance | ||
// * `storageOption`s must be resolved in the order they are received | ||
// * all API errors must be wrapped in the gax-go APIError type | ||
// * any unimplemented interface methods must return a StorageUnimplementedErr | ||
// | ||
// TODO(noahdietz): This interface is currently not used in the production code | ||
// paths | ||
type storageClient interface { | ||
|
||
// Top-level methods. | ||
|
||
GetServiceAccount(ctx context.Context, project string, opts ...storageOption) (string, error) | ||
CreateBucket(ctx context.Context, project string, attrs *BucketAttrs, opts ...storageOption) (*BucketAttrs, error) | ||
ListBuckets(ctx context.Context, project string, opts ...storageOption) (BucketIterator, error) | ||
|
||
// Bucket methods. | ||
|
||
DeleteBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error | ||
GetBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) | ||
UpdateBucket(ctx context.Context, uattrs *BucketAttrsToUpdate, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) | ||
LockBucketRetentionPolicy(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error | ||
ListObjects(ctx context.Context, bucket string, q *Query, opts ...storageOption) (*ObjectIterator, error) | ||
|
||
// Object metadata methods. | ||
|
||
DeleteObject(ctx context.Context, bucket, object string, conds *Conditions, opts ...storageOption) error | ||
GetObject(ctx context.Context, bucket, object string, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error) | ||
UpdateObject(ctx context.Context, bucket, object string, uattrs *ObjectAttrsToUpdate, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error) | ||
|
||
// Default Object ACL methods. | ||
|
||
DeleteDefaultObjectACL(ctx context.Context, bucket string, entity ACLEntity, opts ...storageOption) error | ||
ListDefaultObjectACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error) | ||
UpdateDefaultObjectACL(ctx context.Context, opts ...storageOption) (ACLRule, error) | ||
|
||
// Bucket ACL methods. | ||
|
||
DeleteBucketACL(ctx context.Context, bucket string, entity ACLEntity, opts ...storageOption) error | ||
ListBucketACLs(ctx context.Context, bucket string, opts ...storageOption) ([]ACLRule, error) | ||
UpdateBucketACL(ctx context.Context, bucket string, entity ACLEntity, role ACLRole, opts ...storageOption) (ACLRule, error) | ||
|
||
// Object ACL methods. | ||
|
||
DeleteObjectACL(ctx context.Context, bucket, object string, entity ACLEntity, opts ...storageOption) error | ||
ListObjectACLs(ctx context.Context, bucket, object string, opts ...storageOption) ([]ACLRule, error) | ||
UpdateObjectACL(ctx context.Context, bucket, object string, entity ACLEntity, role ACLRole, opts ...storageOption) (ACLRule, error) | ||
|
||
// Media operations. | ||
|
||
ComposeObject(ctx context.Context, req *composeObjectRequest, opts ...storageOption) (*ObjectAttrs, error) | ||
RewriteObject(ctx context.Context, req *rewriteObjectRequest, opts ...storageOption) (*rewriteObjectResponse, error) | ||
|
||
OpenReader(ctx context.Context, r *Reader, opts ...storageOption) error | ||
OpenWriter(ctx context.Context, w *Writer, opts ...storageOption) error | ||
|
||
// IAM methods. | ||
|
||
GetIamPolicy(ctx context.Context, resource string, version int32, opts ...storageOption) (*iampb.Policy, error) | ||
SetIamPolicy(ctx context.Context, resource string, policy *iampb.Policy, opts ...storageOption) error | ||
TestIamPermissions(ctx context.Context, resource string, permissions []string, opts ...storageOption) ([]string, error) | ||
|
||
// HMAC Key methods. | ||
|
||
GetHMACKey(ctx context.Context, desc *hmacKeyDesc, opts ...storageOption) (*HMACKey, error) | ||
ListHMACKey(ctx context.Context, desc *hmacKeyDesc, opts ...storageOption) *HMACKeysIterator | ||
UpdateHMACKey(ctx context.Context, desc *hmacKeyDesc, attrs *HMACKeyAttrsToUpdate, opts ...storageOption) (*HMACKey, error) | ||
CreateHMACKey(ctx context.Context, desc *hmacKeyDesc, opts ...storageOption) (*HMACKey, error) | ||
DeleteHMACKey(ctx context.Context, desc *hmacKeyDesc, opts ...storageOption) error | ||
} | ||
|
||
// settings contains transport-agnostic configuration for API calls made via | ||
// the storageClient inteface. All implementations must utilize settings | ||
// and respect those that are applicable. | ||
type settings struct { | ||
// retry is the complete retry configuration to use when evaluating if an | ||
// API call should be retried. | ||
retry *retryConfig | ||
|
||
// gax is a set of gax.CallOption to be conveyed to gax.Invoke. | ||
// Note: Not all storageClient interfaces will must use gax.Invoke. | ||
gax []gax.CallOption | ||
|
||
// idempotent indicates if the call is idempotent or not when considering | ||
// if the call should be retired or not. | ||
idempotent bool | ||
} | ||
|
||
// storageOption is the transport-agnostic call option for the storageClient | ||
// interface. | ||
type storageOption interface { | ||
Apply(s *settings) | ||
} | ||
|
||
func withGAXOptions(opts ...gax.CallOption) storageOption { | ||
return &gaxOption{opts} | ||
} | ||
|
||
type gaxOption struct { | ||
opts []gax.CallOption | ||
} | ||
|
||
func (o *gaxOption) Apply(s *settings) { s.gax = o.opts } | ||
|
||
func withRetryConfig(rc *retryConfig) storageOption { | ||
return &retryOption{rc} | ||
} | ||
|
||
type retryOption struct { | ||
rc *retryConfig | ||
} | ||
|
||
func (o *retryOption) Apply(s *settings) { s.retry = o.rc } | ||
|
||
func idempotent(i bool) storageOption { | ||
return &idempotentOption{i} | ||
} | ||
|
||
type idempotentOption struct { | ||
idempotency bool | ||
} | ||
|
||
func (o *idempotentOption) Apply(s *settings) { s.idempotent = o.idempotency } | ||
|
||
type composeObjectRequest struct { | ||
dstBucket string | ||
dstObject string | ||
srcs []string | ||
gen int64 | ||
conds *Conditions | ||
predefinedACL string | ||
} | ||
|
||
type rewriteObjectRequest struct { | ||
srcBucket string | ||
srcObject string | ||
dstBucket string | ||
dstObject string | ||
dstKeyName string | ||
attrs *ObjectAttrs | ||
gen int64 | ||
conds *Conditions | ||
predefinedACL string | ||
token string | ||
} | ||
|
||
type rewriteObjectResponse struct { | ||
resource *ObjectAttrs | ||
done bool | ||
written int64 | ||
token string | ||
} |