go.temporal.io/server@v1.23.0/common/archiver/gcloud/connector/client_delegate.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 //go:generate mockgen -copyright_file ../../../../LICENSE -package $GOPACKAGE -source $GOFILE -destination client_delegate_mock.go 26 27 package connector 28 29 import ( 30 "context" 31 "os" 32 33 "cloud.google.com/go/storage" 34 "golang.org/x/oauth2/google" 35 "google.golang.org/api/option" 36 ) 37 38 type ( 39 // GcloudStorageClient is an interface that expose some methods from gcloud storage client 40 GcloudStorageClient interface { 41 Bucket(URI string) BucketHandleWrapper 42 } 43 44 clientDelegate struct { 45 nativeClient *storage.Client 46 } 47 ) 48 49 type ( 50 // BucketHandleWrapper is an interface that expose some methods from gcloud storage bucket 51 BucketHandleWrapper interface { 52 Object(name string) ObjectHandleWrapper 53 Objects(ctx context.Context, q *storage.Query) ObjectIteratorWrapper 54 Attrs(ctx context.Context) (*storage.BucketAttrs, error) 55 } 56 57 bucketDelegate struct { 58 bucket *storage.BucketHandle 59 } 60 ) 61 62 type ( 63 // ObjectHandleWrapper is an interface that expose some methods from gcloud storage object 64 ObjectHandleWrapper interface { 65 NewWriter(ctx context.Context) WriterWrapper 66 NewReader(ctx context.Context) (ReaderWrapper, error) 67 Attrs(ctx context.Context) (*storage.ObjectAttrs, error) 68 } 69 70 objectDelegate struct { 71 object *storage.ObjectHandle 72 } 73 ) 74 75 type ( 76 // WriterWrapper is an interface that expose some methods from gcloud storage writer 77 WriterWrapper interface { 78 Close() error 79 Write(p []byte) (n int, err error) 80 CloseWithError(err error) error 81 } 82 83 writerDelegate struct { 84 writer *storage.Writer 85 } 86 ) 87 88 type ( 89 // ReaderWrapper is an interface that expose some methods from gcloud storage reader 90 ReaderWrapper interface { 91 Close() error 92 Read(p []byte) (int, error) 93 } 94 95 readerDelegate struct { 96 reader *storage.Reader 97 } 98 ) 99 100 type ( 101 // ObjectIteratorWrapper is an interface that expose some methods from gcloud storage objectIterator 102 ObjectIteratorWrapper interface { 103 Next() (*storage.ObjectAttrs, error) 104 } 105 ) 106 107 func newDefaultClientDelegate(ctx context.Context) (*clientDelegate, error) { 108 nativeClient, err := storage.NewClient(ctx) 109 return &clientDelegate{nativeClient: nativeClient}, err 110 } 111 112 func newClientDelegateWithCredentials(ctx context.Context, credentialsPath string) (*clientDelegate, error) { 113 114 jsonKey, err := os.ReadFile(credentialsPath) 115 if err != nil { 116 return newDefaultClientDelegate(ctx) 117 } 118 119 conf, err := google.JWTConfigFromJSON(jsonKey, storage.ScopeFullControl) 120 if err != nil { 121 return newDefaultClientDelegate(ctx) 122 } 123 124 nativeClient, err := storage.NewClient(ctx, option.WithTokenSource(conf.TokenSource(ctx))) 125 return &clientDelegate{nativeClient: nativeClient}, err 126 } 127 128 // Bucket returns a BucketHandle, which provides operations on the named bucket. 129 // This call does not perform any network operations. 130 // 131 // The supplied name must contain only lowercase letters, numbers, dashes, 132 // underscores, and dots. The full specification for valid bucket names can be 133 // found at: 134 // 135 // https://cloud.google.com/storage/docs/bucket-naming 136 func (c *clientDelegate) Bucket(bucketName string) BucketHandleWrapper { 137 return &bucketDelegate{bucket: c.nativeClient.Bucket(bucketName)} 138 } 139 140 // Object returns an ObjectHandle, which provides operations on the named object. 141 // This call does not perform any network operations. 142 // 143 // name must consist entirely of valid UTF-8-encoded runes. The full specification 144 // for valid object names can be found at: 145 // 146 // https://cloud.google.com/storage/docs/bucket-naming 147 func (b *bucketDelegate) Object(name string) ObjectHandleWrapper { 148 return &objectDelegate{object: b.bucket.Object(name)} 149 } 150 151 // Objects returns an iterator over the objects in the bucket that match the Query q. 152 // If q is nil, no filtering is done. 153 func (b *bucketDelegate) Objects(ctx context.Context, q *storage.Query) ObjectIteratorWrapper { 154 return b.bucket.Objects(ctx, q) 155 } 156 157 // Attrs returns the metadata for the bucket. 158 func (b *bucketDelegate) Attrs(ctx context.Context) (*storage.BucketAttrs, error) { 159 return b.bucket.Attrs(ctx) 160 } 161 162 // NewWriter returns a storage Writer that writes to the GCS object 163 // associated with this ObjectHandle. 164 // 165 // A new object will be created unless an object with this name already exists. 166 // Otherwise any previous object with the same name will be replaced. 167 // The object will not be available (and any previous object will remain) 168 // until Close has been called. 169 // 170 // Attributes can be set on the object by modifying the returned Writer's 171 // ObjectAttrs field before the first call to Write. If no ContentType 172 // attribute is specified, the content type will be automatically sniffed 173 // using net/http.DetectContentType. 174 // 175 // It is the caller's responsibility to call Close when writing is done. To 176 // stop writing without saving the data, cancel the context. 177 func (o *objectDelegate) NewWriter(ctx context.Context) WriterWrapper { 178 return &writerDelegate{writer: o.object.NewWriter(ctx)} 179 } 180 181 // NewReader creates a new Reader to read the contents of the 182 // object. 183 // ErrObjectNotExist will be returned if the object is not found. 184 // 185 // The caller must call Close on the returned Reader when done reading. 186 func (o *objectDelegate) NewReader(ctx context.Context) (ReaderWrapper, error) { 187 r, err := o.object.NewReader(ctx) 188 return &readerDelegate{reader: r}, err 189 } 190 191 func (o *objectDelegate) Attrs(ctx context.Context) (attrs *storage.ObjectAttrs, err error) { 192 return o.object.Attrs(ctx) 193 } 194 195 // Close completes the write operation and flushes any buffered data. 196 // If Close doesn't return an error, metadata about the written object 197 // can be retrieved by calling Attrs. 198 func (w *writerDelegate) Close() error { 199 return w.writer.Close() 200 } 201 202 // Write appends to w. It implements the io.Writer interface. 203 // 204 // Since writes happen asynchronously, Write may return a nil 205 // error even though the write failed (or will fail). Always 206 // use the error returned from Writer.Close to determine if 207 // the upload was successful. 208 func (w *writerDelegate) Write(p []byte) (int, error) { 209 return w.writer.Write(p) 210 } 211 212 // CloseWithError aborts the write operation with the provided error. 213 // CloseWithError always returns nil. 214 // 215 // Deprecated: cancel the context passed to NewWriter instead. 216 func (w *writerDelegate) CloseWithError(err error) error { 217 return w.writer.CloseWithError(err) 218 } 219 220 // Close closes the Reader. It must be called when done reading. 221 func (r *readerDelegate) Close() error { 222 return r.reader.Close() 223 } 224 225 func (r *readerDelegate) Read(p []byte) (int, error) { 226 return r.reader.Read(p) 227 228 }