Skip to content

Commit

Permalink
include expire time in options
Browse files Browse the repository at this point in the history
  • Loading branch information
bhshkh committed Dec 25, 2024
1 parent bb7e0c5 commit fd3ba83
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 34 deletions.
74 changes: 43 additions & 31 deletions bigtable/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import (
const adminAddr = "bigtableadmin.googleapis.com:443"
const mtlsAdminAddr = "bigtableadmin.mtls.googleapis.com:443"

var errExpiryMissing = errors.New("WithExpiry is a required option")

// ErrPartiallyUnavailable is returned when some locations (clusters) are
// unavailable. Both partial results (retrieved from available locations)
// and the error are returned when this exception occurred.
Expand Down Expand Up @@ -2153,54 +2155,69 @@ func (ac *AdminClient) RestoreTableFrom(ctx context.Context, sourceInstance, tab
type backupOptions struct {
backupType *BackupType
hotToStandardTime *time.Time
expireTime *time.Time
}

// BackupOption can be used to specify parameters for backup operations.
type BackupOption interface {
apply(o *backupOptions)
}

type hotBackupOption struct {
htsTime *time.Time
}

func (hbo hotBackupOption) apply(o *backupOptions) {
o.hotToStandardTime = hbo.htsTime
btHot := BackupTypeHot
o.backupType = &btHot
}
type BackupOption func(*backupOptions)

// HotToStandardBackup option can be used to create backup with
// WithHotToStandardBackup option can be used to create backup with
// type [BackupTypeHot] and specify time at which the hot backup will be
// converted to a standard backup. Once the `hot_to_standard_time` has passed,
// converted to a standard backup. Once the 'hotToStandardTime' has passed,
// Cloud Bigtable will convert the hot backup to a standard backup.
// This value must be greater than the backup creation time by at least 24 hours
func HotToStandardBackup(hotToStandardTime time.Time) BackupOption {
return hotBackupOption{htsTime: &hotToStandardTime}
func WithHotToStandardBackup(hotToStandardTime time.Time) BackupOption {
return func(bo *backupOptions) {
btHot := BackupTypeHot
bo.backupType = &btHot
bo.hotToStandardTime = &hotToStandardTime
}
}

// WithExpiry option can be used to create backup
// that expires after time 'expireTime'.
// Once the 'expireTime' has passed, Cloud Bigtable will delete the backup.
func WithExpiry(expireTime time.Time) BackupOption {
return func(bo *backupOptions) {
bo.expireTime = &expireTime
}
}

// HotBackup option can be used to create backup
// WithHotBackup option can be used to create backup
// with type [BackupTypeHot]
func HotBackup() BackupOption {
return hotBackupOption{}
func WithHotBackup() BackupOption {
return func(bo *backupOptions) {
btHot := BackupTypeHot
bo.backupType = &btHot
}
}

// CreateBackup creates a new backup in the specified cluster from the
// specified source table with the user-provided expire time.
func (ac *AdminClient) CreateBackup(ctx context.Context, table, cluster, backup string, expireTime time.Time) error {
return ac.createBackup(ctx, table, cluster, backup, expireTime, nil)
return ac.createBackup(ctx, table, cluster, backup, WithExpiry(expireTime))
}

// CreateBackupWithOptions is similar to CreateBackup but lets the user specify additional options.
func (ac *AdminClient) CreateBackupWithOptions(ctx context.Context, table, cluster, backup string, expireTime time.Time, opts ...BackupOption) error {
return ac.createBackup(ctx, table, cluster, backup, expireTime, opts...)
func (ac *AdminClient) CreateBackupWithOptions(ctx context.Context, table, cluster, backup string, opts ...BackupOption) error {
return ac.createBackup(ctx, table, cluster, backup, opts...)
}

func (ac *AdminClient) createBackup(ctx context.Context, table, cluster, backup string, expireTime time.Time, opts ...BackupOption) error {
func (ac *AdminClient) createBackup(ctx context.Context, table, cluster, backup string, opts ...BackupOption) error {
ctx = mergeOutgoingMetadata(ctx, ac.md)
prefix := ac.instancePrefix()

parsedExpireTime := timestamppb.New(expireTime)
o := backupOptions{}
for _, opt := range opts {
if opt != nil {
opt(&o)
}
}

if o.expireTime == nil {
return errExpiryMissing
}
parsedExpireTime := timestamppb.New(*o.expireTime)

req := &btapb.CreateBackupRequest{
Parent: prefix + "/clusters/" + cluster,
Expand All @@ -2210,12 +2227,7 @@ func (ac *AdminClient) createBackup(ctx context.Context, table, cluster, backup
SourceTable: prefix + "/tables/" + table,
},
}
o := backupOptions{}
for _, opt := range opts {
if opt != nil {
opt.apply(&o)
}
}

if o.backupType != nil {
req.Backup.BackupType = btapb.Backup_BackupType(*o.backupType)
}
Expand Down
10 changes: 10 additions & 0 deletions bigtable/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ func TestTableAdmin_CreateTableFromConf_AutomatedBackupPolicy_Valid(t *testing.T
}
}

func TestTableAdmin_CreateBackupWithOptions_NoExpiryTime(t *testing.T) {
mock := &mockTableAdminClock{}
c := setupTableClient(t, mock)

err := c.CreateBackupWithOptions(context.Background(), "table", "cluster", "backup-01")
if err == nil || !errors.Is(err, errExpiryMissing) {
t.Errorf("CreateBackupWithOptions got: %v, want: %v error", err, errExpiryMissing)
}
}

func TestTableAdmin_CopyBackup_ErrorFromClient(t *testing.T) {
mock := &mockTableAdminClock{}
c := setupTableClient(t, mock)
Expand Down
6 changes: 3 additions & 3 deletions bigtable/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3757,15 +3757,15 @@ func TestIntegration_AdminBackup(t *testing.T) {
defer adminClient.DeleteBackup(ctx, sourceCluster, hotBkpName1)
wantHtsTime := time.Now().Truncate(time.Second).Add(48 * time.Hour)
if err = adminClient.CreateBackupWithOptions(ctx, tblConf.TableID, sourceCluster, hotBkpName1,
time.Now().Add(8*time.Hour), HotToStandardBackup(wantHtsTime)); err != nil {
WithExpiry(time.Now().Add(8*time.Hour)), WithHotToStandardBackup(wantHtsTime)); err != nil {
t.Fatalf("Creating backup: %v", err)
}

// Create hot backup without hot_to_standard_time
hotBkpName2 := backupUID.New()
defer adminClient.DeleteBackup(ctx, sourceCluster, hotBkpName2)
if err = adminClient.CreateBackupWithOptions(ctx, tblConf.TableID, sourceCluster, hotBkpName2,
time.Now().Add(8*time.Hour), HotBackup()); err != nil {
WithExpiry(time.Now().Add(8*time.Hour)), WithHotBackup()); err != nil {
t.Fatalf("Creating backup: %v", err)
}

Expand Down Expand Up @@ -3946,7 +3946,7 @@ func TestIntegration_AdminUpdateBackupHotToStandardTime(t *testing.T) {
bkpName := backupUID.New()
defer adminClient.DeleteBackup(ctx, testEnv.Config().Cluster, bkpName)
if err = adminClient.CreateBackupWithOptions(ctx, tblConf.TableID, testEnv.Config().Cluster, bkpName,
time.Now().Add(8*time.Hour), HotToStandardBackup(time.Now().Truncate(time.Second).Add(2*24*time.Hour))); err != nil {
WithExpiry(time.Now().Add(8*time.Hour)), WithHotToStandardBackup(time.Now().Truncate(time.Second).Add(2*24*time.Hour))); err != nil {
t.Fatalf("Creating backup: %v", err)
}

Expand Down

0 comments on commit fd3ba83

Please sign in to comment.