Skip to content

Commit

Permalink
Migrate to aws-sdk-go-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
robertvolkmann committed Mar 13, 2024
1 parent 6d09f42 commit 5e6e03a
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 106 deletions.
150 changes: 53 additions & 97 deletions cmd/internal/backup/providers/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ import (
"path/filepath"
"strings"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/metal-stack/backup-restore-sidecar/cmd/internal/backup/providers"
"github.com/metal-stack/backup-restore-sidecar/pkg/constants"
"github.com/spf13/afero"

awsv1 "github.com/aws/aws-sdk-go/aws"
awserrv1 "github.com/aws/aws-sdk-go/aws/awserr"
credentialsv1 "github.com/aws/aws-sdk-go/aws/credentials"
sessionv1 "github.com/aws/aws-sdk-go/aws/session"
s3v1 "github.com/aws/aws-sdk-go/service/s3"
s3managerv1 "github.com/aws/aws-sdk-go/service/s3/s3manager"
)

const (
Expand All @@ -28,8 +27,7 @@ const (
type BackupProviderS3 struct {
fs afero.Fs
log *slog.Logger
c *s3v1.S3
sess *sessionv1.Session
c *s3.Client
config *BackupProviderConfigS3
}

Expand All @@ -42,7 +40,7 @@ type BackupProviderConfigS3 struct {
SecretKey string
BackupName string
ObjectPrefix string
ObjectsToKeep int64
ObjectsToKeep int32
FS afero.Fs
}

Expand Down Expand Up @@ -83,24 +81,21 @@ func New(log *slog.Logger, cfg *BackupProviderConfigS3) (*BackupProviderS3, erro
if err != nil {
return nil, err
}
s3Config := &awsv1.Config{
Credentials: credentialsv1.NewStaticCredentials(cfg.AccessKey, cfg.SecretKey, ""),
Endpoint: awsv1.String(cfg.Endpoint),
Region: awsv1.String(cfg.Region),
S3ForcePathStyle: awsv1.Bool(true),
}
newSession, err := sessionv1.NewSession(s3Config)
if err != nil {
return nil, err
}
client := s3v1.New(newSession)

s3Cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(cfg.AccessKey, cfg.SecretKey, "")),
config.WithRegion(cfg.Region),
)
if err != nil {
return nil, err
}
client := s3.NewFromConfig(s3Cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String(cfg.Endpoint)
o.UsePathStyle = true
})

return &BackupProviderS3{
c: client,
sess: newSession,
config: cfg,
log: log,
fs: cfg.FS,
Expand All @@ -109,78 +104,49 @@ func New(log *slog.Logger, cfg *BackupProviderConfigS3) (*BackupProviderS3, erro

// EnsureBackupBucket ensures a backup bucket at the backup provider
func (b *BackupProviderS3) EnsureBackupBucket(ctx context.Context) error {
bucket := awsv1.String(b.config.BucketName)

// create bucket
cparams := &s3v1.CreateBucketInput{
Bucket: bucket,
}

_, err := b.c.CreateBucketWithContext(ctx, cparams)
_, err := b.c.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: aws.String(b.config.BucketName),
})
if err != nil {
// FIXME check how to migrate to errors.As
//nolint
if aerr, ok := err.(awserrv1.Error); ok {
switch aerr.Code() {
case s3v1.ErrCodeBucketAlreadyExists:
case s3v1.ErrCodeBucketAlreadyOwnedByYou:
default:
return err
}
} else {
var bucketAlreadyExists *types.BucketAlreadyExists
var bucketAlreadyOwnerByYou *types.BucketAlreadyOwnedByYou
if !errors.As(err, &bucketAlreadyExists) && !errors.As(err, &bucketAlreadyOwnerByYou) {
return err
}
}

// enable versioning
versioning := &s3v1.PutBucketVersioningInput{
Bucket: bucket,
VersioningConfiguration: &s3v1.VersioningConfiguration{
Status: awsv1.String("Enabled"),
_, err = b.c.PutBucketVersioning(ctx, &s3.PutBucketVersioningInput{
Bucket: aws.String(b.config.BucketName),
VersioningConfiguration: &types.VersioningConfiguration{
Status: types.BucketVersioningStatusEnabled,
},
}
_, err = b.c.PutBucketVersioningWithContext(ctx, versioning)
})
if err != nil {
// FIXME check how to migrate to errors.As
//nolint
if aerr, ok := err.(awserrv1.Error); ok {
switch aerr.Code() {
default:
return err
}
} else {
return err
}
return err
}

// add lifecyle policy
lifecycle := &s3v1.PutBucketLifecycleConfigurationInput{
Bucket: bucket,
LifecycleConfiguration: &s3v1.BucketLifecycleConfiguration{
Rules: []*s3v1.LifecycleRule{
_, err = b.c.PutBucketLifecycleConfiguration(ctx, &s3.PutBucketLifecycleConfigurationInput{
Bucket: aws.String(b.config.BucketName),
LifecycleConfiguration: &types.BucketLifecycleConfiguration{
Rules: []types.LifecycleRule{
{
NoncurrentVersionExpiration: &s3v1.NoncurrentVersionExpiration{
NoncurrentVersionExpiration: &types.NoncurrentVersionExpiration{
NoncurrentDays: &b.config.ObjectsToKeep,
},
Status: awsv1.String("Enabled"),
ID: awsv1.String("backup-restore-lifecycle"),
Prefix: &b.config.ObjectPrefix,
Status: types.ExpirationStatusEnabled,
ID: aws.String("backup-restore-lifecycle"),
Filter: &types.LifecycleRuleFilterMemberPrefix{
Value: b.config.ObjectPrefix,
},
},
},
},
}
_, err = b.c.PutBucketLifecycleConfigurationWithContext(ctx, lifecycle)
})
if err != nil {
// FIXME check how to migrate to errors.As
//nolint
if aerr, ok := err.(awserrv1.Error); ok {
switch aerr.Code() {
default:
return err
}
} else {
return err
}
return err
}
return nil
}
Expand All @@ -193,8 +159,6 @@ func (b *BackupProviderS3) CleanupBackups(_ context.Context) error {

// DownloadBackup downloads the given backup version to the restoration folder
func (b *BackupProviderS3) DownloadBackup(ctx context.Context, version *providers.BackupVersion) error {
bucket := awsv1.String(b.config.BucketName)

downloadFileName := version.Name
if strings.Contains(downloadFileName, "/") {
downloadFileName = filepath.Base(downloadFileName)
Expand All @@ -208,16 +172,12 @@ func (b *BackupProviderS3) DownloadBackup(ctx context.Context, version *provider
}
defer f.Close()

downloader := s3managerv1.NewDownloader(b.sess)

_, err = downloader.DownloadWithContext(
ctx,
f,
&s3v1.GetObjectInput{
Bucket: bucket,
Key: &version.Name,
VersionId: &version.Version,
})
downloader := manager.NewDownloader(b.c)
_, err = downloader.Download(ctx, f, &s3.GetObjectInput{
Bucket: aws.String(b.config.BucketName),
Key: &version.Name,
VersionId: &version.Version,
})
if err != nil {
return err
}
Expand All @@ -227,8 +187,6 @@ func (b *BackupProviderS3) DownloadBackup(ctx context.Context, version *provider

// UploadBackup uploads a backup to the backup provider
func (b *BackupProviderS3) UploadBackup(ctx context.Context, sourcePath string) error {
bucket := awsv1.String(b.config.BucketName)

r, err := b.fs.Open(sourcePath)
if err != nil {
return err
Expand All @@ -242,10 +200,10 @@ func (b *BackupProviderS3) UploadBackup(ctx context.Context, sourcePath string)

b.log.Debug("uploading object", "src", sourcePath, "dest", destination)

uploader := s3managerv1.NewUploader(b.sess)
_, err = uploader.UploadWithContext(ctx, &s3managerv1.UploadInput{
Bucket: bucket,
Key: awsv1.String(destination),
uploader := manager.NewUploader(b.c)
_, err = uploader.Upload(ctx, &s3.PutObjectInput{
Bucket: aws.String(b.config.BucketName),
Key: aws.String(destination),
Body: r,
})
if err != nil {
Expand All @@ -263,10 +221,8 @@ func (b *BackupProviderS3) GetNextBackupName(_ context.Context) string {

// ListBackups lists the available backups of the backup provider
func (b *BackupProviderS3) ListBackups(ctx context.Context) (providers.BackupVersions, error) {
bucket := awsv1.String(b.config.BucketName)

it, err := b.c.ListObjectVersionsWithContext(ctx, &s3v1.ListObjectVersionsInput{
Bucket: bucket,
it, err := b.c.ListObjectVersions(ctx, &s3.ListObjectVersionsInput{
Bucket: aws.String(b.config.BucketName),
Prefix: &b.config.ObjectPrefix,
})
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cmd/internal/backup/providers/s3/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import (
"fmt"
"sort"

"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/metal-stack/backup-restore-sidecar/cmd/internal/backup/providers"
)

// BackupVersionsS3 contains the list of available backup versions
type BackupVersionsS3 struct {
objectAttrs []*s3.ObjectVersion
objectAttrs []types.ObjectVersion
}

// Latest returns latest backup version
Expand Down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ func initBackupProvider() error {
logger.WithGroup("backup"),
&s3.BackupProviderConfigS3{
ObjectPrefix: viper.GetString(objectPrefixFlg),
ObjectsToKeep: viper.GetInt64(objectsToKeepFlg),
ObjectsToKeep: viper.GetInt32(objectsToKeepFlg),
Region: viper.GetString(s3RegionFlg),
BucketName: viper.GetString(s3BucketNameFlg),
Endpoint: viper.GetString(s3EndpointFlg),
Expand Down
20 changes: 19 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ require (
cloud.google.com/go/storage v1.35.1
github.com/Masterminds/semver/v3 v3.2.1
github.com/avast/retry-go/v4 v4.5.1
github.com/aws/aws-sdk-go v1.45.7
github.com/aws/aws-sdk-go-v2 v1.25.3
github.com/aws/aws-sdk-go-v2/config v1.27.7
github.com/aws/aws-sdk-go-v2/credentials v1.17.7
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4
github.com/docker/docker v25.0.2+incompatible
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/lib/pq v1.10.9
Expand Down Expand Up @@ -46,6 +50,20 @@ require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down
43 changes: 38 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,44 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/avast/retry-go/v4 v4.5.1 h1:AxIx0HGi4VZ3I02jr78j5lZ3M6x1E0Ivxa6b0pUUh7o=
github.com/avast/retry-go/v4 v4.5.1/go.mod h1:/sipNsvNB3RRuT5iNcb6h73nw3IBmXJ/H3XrCQYSOpc=
github.com/aws/aws-sdk-go v1.45.7 h1:k4QsvWZhm8409TYeRuTV1P6+j3lLKoe+giFA/j3VAps=
github.com/aws/aws-sdk-go v1.45.7/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go-v2 v1.25.3 h1:xYiLpZTQs1mzvz5PaI6uR0Wh57ippuEthxS4iK5v0n0=
github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
github.com/aws/aws-sdk-go-v2/config v1.27.7 h1:JSfb5nOQF01iOgxFI5OIKWwDiEXWTyTgg1Mm1mHi0A4=
github.com/aws/aws-sdk-go-v2/config v1.27.7/go.mod h1:PH0/cNpoMO+B04qET699o5W92Ca79fVtbUnvMIZro4I=
github.com/aws/aws-sdk-go-v2/credentials v1.17.7 h1:WJd+ubWKoBeRh7A5iNMnxEOs982SyVKOJD+K8HIezu4=
github.com/aws/aws-sdk-go-v2/credentials v1.17.7/go.mod h1:UQi7LMR0Vhvs+44w5ec8Q+VS+cd10cjwgHwiVkE0YGU=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 h1:p+y7FvkK2dxS+FEwRIDHDe//ZX+jDhP8HHE50ppj4iI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3/go.mod h1:/fYB+FZbDlwlAiynK9KDXlzZl3ANI9JkD0Uhz5FjNT4=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 h1:ifbIbHZyGl1alsAhPIYsHOg5MuApgqOvVeI8wIugXfs=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3/go.mod h1:oQZXg3c6SNeY6OZrDY+xHcF4VGIEoNotX2B4PrDeoJI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 h1:Qvodo9gHG9F3E8SfYOspPeBt0bjSbsevK8WhRAUHcoY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3/go.mod h1:vCKrdLXtybdf/uQd/YfVR2r5pcbNuEYKzMQpcxmeSJw=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3 h1:mDnFOE2sVkyphMWtTH+stv0eW3k0OTx94K63xpxHty4=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3/go.mod h1:V8MuRVcCRt5h1S+Fwu8KbC7l/gBGo3yBAyUbJM2IJOk=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5 h1:mbWNpfRUTT6bnacmvOTKXZjR/HycibdWzNpfbrbLDIs=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5/go.mod h1:FCOPWGjsshkkICJIn9hq9xr6dLKtyaWpuUojiN3W1/8=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 h1:K/NXvIftOlX+oGgWGIa3jDyYLDNsdVhsjHmsBH2GLAQ=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5/go.mod h1:cl9HGLV66EnCmMNzq4sYOti+/xo8w34CsgzVtm2GgsY=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3 h1:4t+QEX7BsXz98W8W1lNvMAG+NX8qHz2CjLBxQKku40g=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3/go.mod h1:oFcjjUq5Hm09N9rpxTdeMeLeQcxS7mIkBkL8qUKng+A=
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4 h1:lW5xUzOPGAMY7HPuNF4FdyBwRc3UJ/e8KsapbesVeNU=
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4/go.mod h1:MGTaf3x/+z7ZGugCGvepnx2DS6+caCYYqKhzVoLNYPk=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 h1:XOPfar83RIRPEzfihnp+U6udOveKZJvPQ76SKWrLRHc=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2/go.mod h1:Vv9Xyk1KMHXrR3vNQe8W5LMFdTjSeWk0gBZBzvf3Qa0=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 h1:pi0Skl6mNl2w8qWZXcdOyg197Zsf4G97U7Sso9JXGZE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2/go.mod h1:JYzLoEVeLXk+L4tn1+rrkfhkxl6mLDEVaDSvGq9og90=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 h1:Ppup1nVNAOWbBOrcoOxaxPeEnSFB2RnnQdguhXpmeQk=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4/go.mod h1:+K1rNPVyGxkRuv9NNiaZ4YhBFuyw2MMA9SlIJ1Zlpz8=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
Expand Down Expand Up @@ -463,7 +499,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down Expand Up @@ -503,15 +538,13 @@ golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
Expand Down

0 comments on commit 5e6e03a

Please sign in to comment.