Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(storage): add Autoclass support #6828

Merged
merged 13 commits into from Nov 1, 2022
18 changes: 8 additions & 10 deletions storage/bucket.go
Expand Up @@ -737,10 +737,6 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
if err != nil {
return nil, err
}
ac, err := toAutoclassFromRaw(b.Autoclass)
if err != nil {
return nil, err
}
return &BucketAttrs{
Name: b.Name,
Location: b.Location,
Expand All @@ -767,7 +763,7 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
ProjectNumber: b.ProjectNumber,
RPO: toRPO(b),
CustomPlacementConfig: customPlacementFromRaw(b.CustomPlacementConfig),
Autoclass: ac,
Autoclass: toAutoclassFromRaw(b.Autoclass),
}, nil
}

Expand Down Expand Up @@ -1957,19 +1953,21 @@ func (a *Autoclass) toProtoAutoclass() *storagepb.Bucket_Autoclass {
}
}

func toAutoclassFromRaw(a *raw.BucketAutoclass) (*Autoclass, error) {
func toAutoclassFromRaw(a *raw.BucketAutoclass) *Autoclass {
if a == nil || a.ToggleTime == "" {
return nil, nil
return nil
}
// Return Autoclass only if a valid ToggleTime is available.
// Return Autoclass.ToggleTime only if parsed with a valid value.
t, err := time.Parse(time.RFC3339, a.ToggleTime)
if err != nil {
cojenco marked this conversation as resolved.
Show resolved Hide resolved
return nil, err
return &Autoclass{
Enabled: a.Enabled,
}
}
return &Autoclass{
Enabled: a.Enabled,
ToggleTime: t,
}, nil
}
}

func toAutoclassFromProto(a *storagepb.Bucket_Autoclass) *Autoclass {
Expand Down
21 changes: 14 additions & 7 deletions storage/bucket_test.go
Expand Up @@ -722,6 +722,7 @@ func TestNewBucketFromProto(t *testing.T) {
{Entity: "allUsers", Role: "READER"},
},
Location: "loc",
LocationType: "region",
StorageClass: "class",
RetentionPolicy: &storagepb.Bucket_RetentionPolicy{
RetentionPeriod: proto.Int64(int64(3)),
Expand Down Expand Up @@ -766,6 +767,7 @@ func TestNewBucketFromProto(t *testing.T) {
ACL: []ACLRule{{Entity: "bob@example.com", Role: RoleOwner}},
DefaultObjectACL: []ACLRule{{Entity: AllUsers, Role: RoleReader}},
Location: "loc",
LocationType: "region",
StorageClass: "class",
RetentionPolicy: &RetentionPolicy{
RetentionPeriod: 3 * time.Second,
Expand Down Expand Up @@ -800,6 +802,11 @@ func TestNewBucketFromProto(t *testing.T) {
},
}},
},
// Populated with default values.
CustomPlacementConfig: nil,
cojenco marked this conversation as resolved.
Show resolved Hide resolved
VersioningEnabled: false,
RequesterPays: false,
ProjectNumber: 0,
}
got := newBucketFromProto(pb)
if diff := testutil.Diff(got, want); diff != "" {
Expand All @@ -814,7 +821,6 @@ func TestBucketAttrsToProtoBucket(t *testing.T) {
ACL: []ACLRule{{Entity: "bob@example.com", Role: RoleOwner, Domain: "d", Email: "e"}},
DefaultObjectACL: []ACLRule{{Entity: AllUsers, Role: RoleReader, EntityID: "eid",
ProjectTeam: &ProjectTeam{ProjectNumber: "17", Team: "t"}}},
Etag: "Zkyw9ACJZUvcYmlFaKGChzhmtnE/dt1zHSfweiWpwzdGsqXwuJZqiD0",
Location: "loc",
StorageClass: "class",
RetentionPolicy: &RetentionPolicy{
Expand All @@ -825,10 +831,8 @@ func TestBucketAttrsToProtoBucket(t *testing.T) {
PublicAccessPrevention: PublicAccessPreventionEnforced,
VersioningEnabled: false,
RPO: RPOAsyncTurbo,
// should be ignored:
MetaGeneration: 39,
Created: time.Now(),
Labels: map[string]string{"label": "value"},
Created: time.Now(),
Labels: map[string]string{"label": "value"},
CORS: []CORS{
{
MaxAge: time.Hour,
Expand All @@ -851,15 +855,18 @@ func TestBucketAttrsToProtoBucket(t *testing.T) {
},
}},
},
// Below fields should be ignored.
MetaGeneration: 39,
Etag: "Zkyw9ACJZUvcYmlFaKGChzhmtnE/dt1zHSfweiWpwzdGsqXwuJZqiD0",
}
got := attrs.toProtoBucket()
want := &storagepb.Bucket{
Name: "name",
Acl: []*storagepb.BucketAccessControl{
{Entity: "bob@example.com", Role: "OWNER"}, // other fields ignored on create/update
{Entity: "bob@example.com", Role: "OWNER"},
},
DefaultObjectAcl: []*storagepb.ObjectAccessControl{
{Entity: "allUsers", Role: "READER"}, // other fields ignored on create/update
{Entity: "allUsers", Role: "READER"},
},
Location: "loc",
StorageClass: "class",
Expand Down
10 changes: 5 additions & 5 deletions storage/integration_test.go
Expand Up @@ -874,25 +874,25 @@ func TestIntegration_Autoclass(t *testing.T) {
var toggleTime time.Time
if attrs != nil && attrs.Autoclass != nil {
if got, want := attrs.Autoclass.Enabled, true; got != want {
t.Fatalf("attr.Autoclass.Enabled = %v, want %v", got, want)
t.Errorf("attr.Autoclass.Enabled = %v, want %v", got, want)
}
if toggleTime = attrs.Autoclass.ToggleTime; toggleTime.IsZero() {
t.Fatal("got a zero time value, want a populated value")
t.Error("got a zero time value, want a populated value")
}
}

// Disable Autoclass on the bucket.
ua := BucketAttrsToUpdate{Autoclass: &Autoclass{Enabled: false}}
attrs = h.mustUpdateBucket(bkt, ua, attrs.MetaGeneration)
if got, want := attrs.Autoclass.Enabled, false; got != want {
t.Fatalf("attr.Autoclass.Enabled = %v, want %v", got, want)
t.Errorf("attr.Autoclass.Enabled = %v, want %v", got, want)
}
latestToggleTime := attrs.Autoclass.ToggleTime
if latestToggleTime.IsZero() {
t.Fatal("got a zero time value, want a populated value")
t.Error("got a zero time value, want a populated value")
}
if latestToggleTime.Before(toggleTime) {
t.Fatal("latestToggleTime should be newer than bucket creation toggleTime")
t.Error("latestToggleTime should be newer than bucket creation toggleTime")
}
}

Expand Down