Skip to content

Commit 17cceeb

Browse files
authored
chore(storage): parse out project number if available (#6671)
The JSON API has a dedicated `ProjectNumber uint64` field used to populate the same field on `BucketAttrs`. The gRPC API has a `string project` field that can contain either a project *number* or a project *identifier* (alphanumeric). Parse out the *project number* if it is present in the returned `Bucket`, otherwise leave it as `0`.
1 parent feb7d7d commit 17cceeb

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

storage/bucket.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ func newBucketFromProto(b *storagepb.Bucket) *BucketAttrs {
775775
LocationType: b.GetLocationType(),
776776
RPO: toRPOFromProto(b),
777777
CustomPlacementConfig: customPlacementFromProto(b.GetCustomPlacementConfig()),
778+
ProjectNumber: parseProjectNumber(b.GetProject()), // this can return 0 the project resource name is ID based
778779
}
779780
}
780781

storage/storage.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"reflect"
3434
"regexp"
3535
"sort"
36+
"strconv"
3637
"strings"
3738
"time"
3839
"unicode/utf8"
@@ -2002,6 +2003,24 @@ func parseBucketName(b string) string {
20022003
return b[sep+1:]
20032004
}
20042005

2006+
// parseProjectNumber consume the given resource name and parses out the project
2007+
// number if one is present i.e. it is not a project ID.
2008+
func parseProjectNumber(r string) uint64 {
2009+
projectID := regexp.MustCompile(`projects\/([0-9]+)\/?`)
2010+
if matches := projectID.FindStringSubmatch(r); len(matches) > 0 {
2011+
// Capture group follows the matched segment. For example:
2012+
// input: projects/123/bars/456
2013+
// output: [projects/123/, 123]
2014+
number, err := strconv.ParseUint(matches[1], 10, 64)
2015+
if err != nil {
2016+
return 0
2017+
}
2018+
return number
2019+
}
2020+
2021+
return 0
2022+
}
2023+
20052024
// toProjectResource accepts a project ID and formats it as a Project resource
20062025
// name.
20072026
func toProjectResource(project string) string {

storage/storage_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,24 @@ func TestSignedURLOptionsClone(t *testing.T) {
23412341
}
23422342
}
23432343

2344+
func TestParseProjectNumber(t *testing.T) {
2345+
for _, tst := range []struct {
2346+
input string
2347+
want uint64
2348+
}{
2349+
{"projects/123", 123},
2350+
{"projects/123/foos/456", 123},
2351+
{"projects/abc-123/foos/456", 0},
2352+
{"projects/abc-123", 0},
2353+
{"projects/abc", 0},
2354+
{"projects/abc/foos", 0},
2355+
} {
2356+
if got := parseProjectNumber(tst.input); got != tst.want {
2357+
t.Errorf("For %q: got %v, expected %v", tst.input, got, tst.want)
2358+
}
2359+
}
2360+
}
2361+
23442362
// isZeroValue reports whether v is the zero value for its type
23452363
// It errors if the argument is unknown
23462364
func isZeroValue(v reflect.Value) (bool, error) {

0 commit comments

Comments
 (0)