Skip to content

Commit 12ba1df

Browse files
deka108dotslash
authored andcommitted
Change GCS Init to use List (kahing#81)
Co-authored-by: Sai Teja Suram <[email protected]>
1 parent db33ac2 commit 12ba1df

File tree

3 files changed

+37
-33
lines changed

3 files changed

+37
-33
lines changed

README-gcs.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55

66
Service Account credentials or user authentication. Ensure that either the service account or user has the proper permissions to the Bucket / Object under GCS.
77

8-
For example, read-only access should be granted the following permissions:
9-
```
10-
storage.objects.get
11-
storage.objects.list
12-
````
8+
To have a successful mount, we require users to have object listing (`storage.objects.list`) permission to the bucket.
139

1410
### Service Account credentials
1511

internal/backend_gcs.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"io"
1010
"net"
11+
"path"
1112
"strings"
1213
"syscall"
1314

@@ -78,16 +79,20 @@ func NewGCS(bucket string, config *common.GCSConfig) (*GCSBackend, error) {
7879

7980
// Init checks user's access to bucket.
8081
func (g *GCSBackend) Init(key string) error {
81-
g.logger.Debugf("INIT GCS: %s", key)
82-
_, err := g.bucket.Object(key).Attrs(context.Background())
83-
84-
// Currently we return successful mounts on 404 errors. However, GCS does not differentiate bucket not found and
85-
// object not found errors. So, even though we don't know that the bucket exists, we will still mount successfully.
86-
if err == storage.ErrObjectNotExist {
87-
err = nil
88-
}
89-
90-
return mapGCSError(err)
82+
// We will do a successful mount if the user can list on the bucket.
83+
// This is different other backends because GCS does not differentiate between object not found and
84+
// bucket not found.
85+
prefix, _ := path.Split(key)
86+
_, err := g.ListBlobs(&ListBlobsInput{
87+
MaxKeys: PUInt32(1),
88+
Prefix: PString(prefix),
89+
})
90+
g.logger.Debugf("INIT GCS: ListStatus = %s", getDebugResponseStatus(err))
91+
if err == syscall.ENXIO {
92+
return fmt.Errorf("bucket %v does not exist", g.bucketName)
93+
}
94+
// Errors can be returned directly since ListBlobs converts them to syscall errors.
95+
return err
9196
}
9297

9398
func (g *GCSBackend) Capabilities() *Capabilities {

internal/backend_gcs_test.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -187,19 +187,18 @@ func (s *GCSBackendTest) TearDownTest(c *C) {
187187
}
188188

189189
func (s *GCSBackendTest) TestGCSBackend_Init_Authenticated(c *C) {
190-
// on existing private bucket
190+
// No error when accessing existing private bucket.
191191
err := s.gcsBackend.Init(s.bucketName)
192192
c.Assert(err, IsNil)
193193

194-
// on nonexistent bucket
195-
gcsBackend, err := s.getGCSTestBackend(RandStringBytesMaskImprSrc(16))
194+
// Not Found error when accessing nonexistent bucket.
195+
randBktName := RandStringBytesMaskImprSrc(16)
196+
gcsBackend, err := s.getGCSTestBackend(randBktName)
196197
c.Assert(err, IsNil)
197198
err = gcsBackend.Init(RandStringBytesMaskImprSrc(16))
198-
// there is no error because we return not found errors as successful
199-
// bucket not found has the same 404 error code as object not found
200-
c.Assert(err, IsNil)
199+
c.Assert(err, ErrorMatches, fmt.Sprintf("bucket %s does not exist", randBktName))
201200

202-
// on public bucket
201+
// No error when accessing public bucket.
203202
gcsBackend, err = s.getGCSTestBackend("gcp-public-data-nexrad-l2")
204203
c.Assert(err, IsNil)
205204
err = gcsBackend.Init(RandStringBytesMaskImprSrc(16))
@@ -218,19 +217,20 @@ func (s *GCSBackendTest) TestGCSBackend_Init_Unauthenticated(c *C) {
218217
c.Skip("Skipping this test because credentials still exist in the environment.")
219218
}
220219

221-
// on existing private bucket
220+
// Access error on existing private bucket.
222221
gcsBackend, err := s.getGCSTestBackend(s.bucketName)
223222
c.Assert(err, IsNil)
224223
err = gcsBackend.Init(RandStringBytesMaskImprSrc(15))
225224
c.Assert(err, Equals, syscall.EACCES)
226225

227-
// on nonexistent bucket. there is no error because bucket not found is a 404 error
228-
gcsBackend, err = s.getGCSTestBackend(RandStringBytesMaskImprSrc(16))
226+
// Not Found error when accessing nonexistent bucket.
227+
randBktName := RandStringBytesMaskImprSrc(16)
228+
gcsBackend, err = s.getGCSTestBackend(randBktName)
229229
c.Assert(err, IsNil)
230230
err = gcsBackend.Init(RandStringBytesMaskImprSrc(16))
231-
c.Assert(err, IsNil)
231+
c.Assert(err, ErrorMatches, fmt.Sprintf("bucket %s does not exist", randBktName))
232232

233-
// on public bucket
233+
// No error when accessing public bucket.
234234
gcsBackend, err = s.getGCSTestBackend("gcp-public-data-nexrad-l2")
235235
c.Assert(err, IsNil)
236236
err = gcsBackend.Init(RandStringBytesMaskImprSrc(16))
@@ -249,21 +249,24 @@ func (s *GCSBackendTest) TestGCSBackend_Init_Authenticated_ReadOnlyAccess(c *C)
249249
}()
250250
os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", os.Getenv("READONLY_GOOGLE_APPLICATION_CREDENTIALS"))
251251

252-
// on existing private bucket
252+
// No error when accessing existing private bucket.
253253
gcsBackend, err := s.getGCSTestBackend(s.bucketName)
254254
c.Assert(err, IsNil)
255+
err = gcsBackend.Init(s.bucketName)
256+
c.Assert(err, IsNil)
255257

256-
// error when trying to modify object
258+
// Access error when trying to modify object.
257259
_, err = gcsBackend.DeleteBlob(&DeleteBlobInput{Key: s.testSpec.existingObjKey})
258260
c.Assert(err, Equals, syscall.EACCES)
259261

260-
// on nonexistent bucket. there is no error because bucket not found is a 404 error
261-
gcsBackend, err = s.getGCSTestBackend(RandStringBytesMaskImprSrc(16))
262+
// Not Found error when accessing nonexistent bucket.
263+
randBktName := RandStringBytesMaskImprSrc(16)
264+
gcsBackend, err = s.getGCSTestBackend(randBktName)
262265
c.Assert(err, IsNil)
263266
err = gcsBackend.Init(RandStringBytesMaskImprSrc(16))
264-
c.Assert(err, IsNil)
267+
c.Assert(err, ErrorMatches, fmt.Sprintf("bucket %s does not exist", randBktName))
265268

266-
// on public bucket
269+
// No error when accessing public bucket.
267270
gcsBackend, err = s.getGCSTestBackend("gcp-public-data-nexrad-l2")
268271
c.Assert(err, IsNil)
269272
err = gcsBackend.Init(RandStringBytesMaskImprSrc(16))

0 commit comments

Comments
 (0)