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
81 changes: 81 additions & 0 deletions storage/bucket.go
Expand Up @@ -444,6 +444,11 @@ type BucketAttrs struct {
// See https://cloud.google.com/storage/docs/managing-turbo-replication for
// more information.
RPO RPO

// Autoclass holds the bucket's autoclass configuration. If enabled,
// allows for the automatic selection of the best storage class
// based on object access patterns.
Autoclass *Autoclass
}

// BucketPolicyOnly is an alias for UniformBucketLevelAccess.
Expand Down Expand Up @@ -710,6 +715,20 @@ type CustomPlacementConfig struct {
DataLocations []string
}

// Autoclass holds the bucket's autoclass configuration. If enabled,
// allows for the automatic selection of the best storage class
// based on object access patterns. See
// https://cloud.google.com/storage/docs/using-autoclass for more information.
type Autoclass struct {
// Enabled specifies whether the autoclass feature is enabled
// on the bucket.
Enabled bool
// ToggleTime is the time from which Autoclass was last toggled.
// If Autoclass is enabled when the bucket is created, the ToggleTime
// is set to the bucket creation time. This field is read-only.
ToggleTime time.Time
}

func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
if b == nil {
return nil, nil
Expand Down Expand Up @@ -744,6 +763,7 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
ProjectNumber: b.ProjectNumber,
RPO: toRPO(b),
CustomPlacementConfig: customPlacementFromRaw(b.CustomPlacementConfig),
Autoclass: toAutoclassFromRaw(b.Autoclass),
}, nil
}

Expand Down Expand Up @@ -776,6 +796,7 @@ func newBucketFromProto(b *storagepb.Bucket) *BucketAttrs {
RPO: toRPOFromProto(b),
CustomPlacementConfig: customPlacementFromProto(b.GetCustomPlacementConfig()),
ProjectNumber: parseProjectNumber(b.GetProject()), // this can return 0 the project resource name is ID based
Autoclass: toAutoclassFromProto(b.GetAutoclass()),
}
}

Expand Down Expand Up @@ -830,6 +851,7 @@ func (b *BucketAttrs) toRawBucket() *raw.Bucket {
IamConfiguration: bktIAM,
Rpo: b.RPO.String(),
CustomPlacementConfig: b.CustomPlacementConfig.toRawCustomPlacement(),
Autoclass: b.Autoclass.toRawAutoclass(),
}
}

Expand Down Expand Up @@ -889,6 +911,7 @@ func (b *BucketAttrs) toProtoBucket() *storagepb.Bucket {
IamConfig: bktIAM,
Rpo: b.RPO.String(),
CustomPlacementConfig: b.CustomPlacementConfig.toProtoCustomPlacement(),
Autoclass: b.Autoclass.toProtoAutoclass(),
}
}

Expand Down Expand Up @@ -971,6 +994,7 @@ func (ua *BucketAttrsToUpdate) toProtoBucket() *storagepb.Bucket {
Website: ua.Website.toProtoBucketWebsite(),
IamConfig: bktIAM,
Rpo: ua.RPO.String(),
Autoclass: ua.Autoclass.toProtoAutoclass(),
}
}

Expand Down Expand Up @@ -1086,6 +1110,10 @@ type BucketAttrsToUpdate struct {
// more information.
RPO RPO

// If set, updates the autoclass configuration of the bucket.
// See https://cloud.google.com/storage/docs/using-autoclass for more information.
Autoclass *Autoclass

// acl is the list of access control rules on the bucket.
// It is unexported and only used internally by the gRPC client.
// Library users should use ACLHandle methods directly.
Expand Down Expand Up @@ -1199,6 +1227,12 @@ func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
rb.Website = ua.Website.toRawBucketWebsite()
}
}
if ua.Autoclass != nil {
rb.Autoclass = &raw.BucketAutoclass{
Enabled: ua.Autoclass.Enabled,
ForceSendFields: []string{"Enabled"},
}
}
if ua.PredefinedACL != "" {
// Clear ACL or the call will fail.
rb.Acl = nil
Expand Down Expand Up @@ -1899,6 +1933,53 @@ func customPlacementFromProto(c *storagepb.Bucket_CustomPlacementConfig) *Custom
return &CustomPlacementConfig{DataLocations: c.GetDataLocations()}
}

func (a *Autoclass) toRawAutoclass() *raw.BucketAutoclass {
if a == nil {
return nil
}
// Excluding read only field ToggleTime.
return &raw.BucketAutoclass{
Enabled: a.Enabled,
}
}

func (a *Autoclass) toProtoAutoclass() *storagepb.Bucket_Autoclass {
if a == nil {
return nil
}
// Excluding read only field ToggleTime.
return &storagepb.Bucket_Autoclass{
Enabled: a.Enabled,
}
}

func toAutoclassFromRaw(a *raw.BucketAutoclass) *Autoclass {
if a == nil || a.ToggleTime == "" {
return nil
}
// 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 &Autoclass{
Enabled: a.Enabled,
}
}
return &Autoclass{
Enabled: a.Enabled,
ToggleTime: t,
}
}

func toAutoclassFromProto(a *storagepb.Bucket_Autoclass) *Autoclass {
if a == nil || a.GetToggleTime().AsTime().Unix() == 0 {
return nil
}
return &Autoclass{
Enabled: a.GetEnabled(),
ToggleTime: a.GetToggleTime().AsTime(),
}
}

// Objects returns an iterator over the objects in the bucket that match the
// Query q. If q is nil, no filtering is done. Objects will be iterated over
// lexicographically by name.
Expand Down