From 81be222c2454652a55001f5a63ecbef01012d147 Mon Sep 17 00:00:00 2001 From: sboy99 Date: Thu, 9 Jan 2025 08:56:33 +0530 Subject: [PATCH 1/5] chore: cloud storage skeleton added --- config/config.go | 15 +++++++++++++-- internal/storage/cloud_storage.go | 21 +++++++++++++++++++++ internal/storage/local_storage.go | 7 +++++-- internal/storage/storage.go | 4 ++-- 4 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 internal/storage/cloud_storage.go diff --git a/config/config.go b/config/config.go index ae5bd00..313ec71 100644 --- a/config/config.go +++ b/config/config.go @@ -29,8 +29,14 @@ type database struct { type StorageEnum string type storage struct { - Type StorageEnum - Dest string + Type StorageEnum + Dest string //TODO: Move Dest to LocalStorage struct + Cloud CloudStorage +} + +type CloudEnum string +type CloudStorage struct { + Type CloudEnum } const ( @@ -44,6 +50,11 @@ const ( CLOUD StorageEnum = "cloud" ) +const ( + GCP CloudEnum = "gcp" + AWS CloudEnum = "aws" +) + func init() { viper.SetConfigName("config") viper.AddConfigPath(".") diff --git a/internal/storage/cloud_storage.go b/internal/storage/cloud_storage.go new file mode 100644 index 0000000..17649d4 --- /dev/null +++ b/internal/storage/cloud_storage.go @@ -0,0 +1,21 @@ +package storage + +type CloudStorage struct { + // TODO: Add creds and other cloud storage specific fields +} + +func NewCloudStorage() *CloudStorage { + return &CloudStorage{} +} + +func (c *CloudStorage) Save(filename string, data []byte) error { + return nil +} + +func (c *CloudStorage) Load(filename string) ([]byte, error) { + return nil, nil +} + +func (c *CloudStorage) Delete(filename string) error { + return nil +} diff --git a/internal/storage/local_storage.go b/internal/storage/local_storage.go index 5b828c8..f488b78 100644 --- a/internal/storage/local_storage.go +++ b/internal/storage/local_storage.go @@ -2,14 +2,17 @@ package storage import ( "os" + + "github.com/sboy99/go-vault/config" ) type LocalStorage struct { BasePath string } -func NewLocalStorage(basePath string) *LocalStorage { - return &LocalStorage{BasePath: basePath} +func NewLocalStorage() *LocalStorage { + cfg := config.GetConfig() + return &LocalStorage{BasePath: cfg.Storage.Dest} } func (ls *LocalStorage) Save(filename string, data []byte) error { diff --git a/internal/storage/storage.go b/internal/storage/storage.go index a1d5f39..37d92b1 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -16,8 +16,8 @@ type Storage struct { func NewStorage() *Storage { return &Storage{ storageMap: map[config.StorageEnum]IStorage{ - config.LOCAL: NewLocalStorage(config.GetConfig().Storage.Dest), - config.CLOUD: nil, + config.LOCAL: NewLocalStorage(), + config.CLOUD: NewCloudStorage(), }, } } From 5f4bd19b9815e5adbd9823751e7e06c7672921a2 Mon Sep 17 00:00:00 2001 From: sboy99 Date: Thu, 9 Jan 2025 23:12:29 +0530 Subject: [PATCH 2/5] feat: added aws cloud storage and config --- config/config.go | 11 +++++ go.mod | 2 + go.sum | 6 +++ internal/config/service.go | 48 ++++++++++++++---- internal/storage/aws_cloud_storage.go | 69 ++++++++++++++++++++++++++ internal/storage/cloud_storage.go | 26 ++++++++-- internal/ui/ui.go | 71 +++++++++++++++++++++++++++ pkg/utils/time.go | 8 +++ 8 files changed, 229 insertions(+), 12 deletions(-) create mode 100644 internal/storage/aws_cloud_storage.go diff --git a/config/config.go b/config/config.go index 313ec71..c623131 100644 --- a/config/config.go +++ b/config/config.go @@ -37,6 +37,12 @@ type storage struct { type CloudEnum string type CloudStorage struct { Type CloudEnum + AWS AWSCloudStorage +} + +type AWSCloudStorage struct { + Region string + BucketName string } const ( @@ -86,6 +92,11 @@ func Save(config *Config) error { // Storage // viper.Set("storage.type", config.Storage.Type) viper.Set("storage.dest", config.Storage.Dest) + // Cloud Storage // + viper.Set("storage.cloud.type", config.Storage.Cloud.Type) + // AWS Cloud Storage // + viper.Set("storage.cloud.aws.region", config.Storage.Cloud.AWS.Region) + viper.Set("storage.cloud.aws.bucket_name", config.Storage.Cloud.AWS.BucketName) if err := viper.WriteConfig(); err != nil { return err diff --git a/go.mod b/go.mod index 54a3636..dec2bc4 100644 --- a/go.mod +++ b/go.mod @@ -11,10 +11,12 @@ require ( ) require ( + github.com/aws/aws-sdk-go v1.55.5 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect diff --git a/go.sum b/go.sum index a595fbf..8d9a2a7 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -21,6 +23,9 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -85,6 +90,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/config/service.go b/internal/config/service.go index b26a83d..e8ab2f0 100644 --- a/internal/config/service.go +++ b/internal/config/service.go @@ -12,55 +12,85 @@ func NewConfigService() *ConfigService { return &ConfigService{} } +// TODO: Return error func (c *ConfigService) SetupConfig() { + // Config // + cfg := config.GetConfig() + // Promt input // dbType, err := ui.DisplaySelectDatabaseTypePrompt() if err != nil { logger.Error("Failed to display select db prompt\nDetails: %v", err) return } + cfg.DB.Type = dbType + dbHost, err := ui.DisplayInputDatabaseHostPrompt() if err != nil { logger.Error("Failed to display input db host prompt\nDetails: %v", err) return } + cfg.DB.Host = dbHost + dbPort, err := ui.DisplayInputDatabasePortPrompt(dbType) if err != nil { logger.Error("Failed to display input db port prompt\nDetails: %v", err) return } + cfg.DB.Port = dbPort + dbName, err := ui.DisplayInputDatabaseNamePrompt(dbType) if err != nil { logger.Error("Failed to display input db name prompt\nDetails: %v", err) return } + cfg.DB.Name = dbName + dbUser, err := ui.DisplayInputDatabaseUsernamePrompt(dbType) if err != nil { logger.Error("Failed to display input db username prompt\nDetails: %v", err) return } + cfg.DB.Username = dbUser + dbPass, err := ui.DisplayInputDatabasePasswordPrompt() if err != nil { logger.Error("Failed to display input db password prompt\nDetails: %v", err) return } + cfg.DB.Password = dbPass storageType, err := ui.DisplaySelectStorageTypePrompt() if err != nil { logger.Error("Failed to display select storage prompt\nDetails: %v", err) return } + cfg.Storage.Type = storageType - // Save config // - cfg := config.GetConfig() - cfg.DB.Type = dbType - cfg.DB.Host = dbHost - cfg.DB.Port = dbPort - cfg.DB.Name = dbName - cfg.DB.Username = dbUser - cfg.DB.Password = dbPass + if storageType == config.CLOUD { + cloudType, err := ui.DisplaySelectCloudTypePrompt() + if err != nil { + logger.Error("Failed to display select cloud prompt\nDetails: %v", err) + return + } + cfg.Storage.Cloud.Type = cloudType - cfg.Storage.Type = storageType + if cloudType == config.AWS { + awsRegion, err := ui.DisplaySelectAWSRegionPrompt() + if err != nil { + logger.Error("Failed to display input aws region prompt\nDetails: %v", err) + return + } + cfg.Storage.Cloud.AWS.Region = awsRegion + + awsBucketName, err := ui.DisplayInputAWSBucketNamePrompt() + if err != nil { + logger.Error("Failed to display input aws bucket name prompt\nDetails: %v", err) + return + } + cfg.Storage.Cloud.AWS.BucketName = awsBucketName + } + } if err = config.Save(cfg); err != nil { logger.Error("Failed to save config\nDetails: %v", err) diff --git a/internal/storage/aws_cloud_storage.go b/internal/storage/aws_cloud_storage.go new file mode 100644 index 0000000..6637d88 --- /dev/null +++ b/internal/storage/aws_cloud_storage.go @@ -0,0 +1,69 @@ +package storage + +import ( + "bytes" + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/sboy99/go-vault/config" + "github.com/sboy99/go-vault/pkg/utils" +) + +type AWSCloudStorage struct { + Region string + BucketName string +} + +func NewAWSCloudStorage() *AWSCloudStorage { + cfg := config.GetConfig() + return &AWSCloudStorage{ + Region: cfg.Storage.Cloud.AWS.Region, + BucketName: cfg.Storage.Cloud.AWS.BucketName, + } +} + +func (a *AWSCloudStorage) Upload(filename string, data []byte) error { + svc, err := a.getSvc() + if err != nil { + return err + } + key := a.buildKey(filename) + if _, err = svc.PutObject(a.createPutObjectInput(key, data)); err != nil { + return err + } + return nil +} + +func (a *AWSCloudStorage) Download(filename string) ([]byte, error) { + return nil, fmt.Errorf("Not Impl") +} + +func (a *AWSCloudStorage) Delete(filename string) error { + return fmt.Errorf("Not Impl") +} + +func (a *AWSCloudStorage) getSvc() (*s3.S3, error) { + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(a.Region), + Credentials: &credentials.Credentials{}, + }) + if err != nil { + return nil, err + } + return s3.New(sess), nil +} + +func (a *AWSCloudStorage) createPutObjectInput(key string, data []byte) *s3.PutObjectInput { + return &s3.PutObjectInput{ + Key: aws.String(key), + Bucket: aws.String(a.BucketName), + Body: bytes.NewReader(data), + } +} + +func (a *AWSCloudStorage) buildKey(filename string) string { + return filename + "_" + utils.GetUnixTimeStamp() +} diff --git a/internal/storage/cloud_storage.go b/internal/storage/cloud_storage.go index 17649d4..d8545d8 100644 --- a/internal/storage/cloud_storage.go +++ b/internal/storage/cloud_storage.go @@ -1,15 +1,31 @@ package storage +import "github.com/sboy99/go-vault/config" + +type ICloudStorage interface { + Upload(filename string, data []byte) error + Download(filename string) ([]byte, error) + Delete(filename string) error +} + type CloudStorage struct { - // TODO: Add creds and other cloud storage specific fields + Type config.CloudEnum + storageMap map[config.CloudEnum]ICloudStorage } func NewCloudStorage() *CloudStorage { - return &CloudStorage{} + cfg := config.GetConfig() + return &CloudStorage{ + Type: cfg.Storage.Cloud.Type, + storageMap: map[config.CloudEnum]ICloudStorage{ + config.AWS: NewAWSCloudStorage(), + config.GCP: nil, + }, + } } func (c *CloudStorage) Save(filename string, data []byte) error { - return nil + return c.getCloudStorage().Upload(filename, data) } func (c *CloudStorage) Load(filename string) ([]byte, error) { @@ -19,3 +35,7 @@ func (c *CloudStorage) Load(filename string) ([]byte, error) { func (c *CloudStorage) Delete(filename string) error { return nil } + +func (c *CloudStorage) getCloudStorage() ICloudStorage { + return c.storageMap[c.Type] +} diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 1c4138a..f9e8253 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -107,3 +107,74 @@ func DisplaySelectStorageTypePrompt() (config.StorageEnum, error) { } return config.StorageEnum(result), nil } + +func DisplaySelectCloudTypePrompt() (config.CloudEnum, error) { + // Prompt for Cloud selection // + prompt := promptui.Select{ + Label: "Select Cloud", + Items: []config.CloudEnum{config.AWS, config.GCP}, + } + // Run the prompt // + _, result, err := prompt.Run() + if err != nil { + return "", err + } + return config.CloudEnum(result), nil +} + +func DisplaySelectAWSRegionPrompt() (string, error) { + // Prompt for AWS region // + prompt := promptui.Select{ + Label: "Enter AWS Region", + Items: []string{ + "us-east-1", // US East (N. Virginia) + "us-east-2", // US East (Ohio) + "us-west-1", // US West (N. California) + "us-west-2", // US West (Oregon) + "ca-central-1", // Canada (Central) + "sa-east-1", // South America (São Paulo) + "eu-west-1", // Europe (Ireland) + "eu-west-2", // Europe (London) + "eu-west-3", // Europe (Paris) + "eu-central-1", // Europe (Frankfurt) + "eu-central-2", // Europe (Zurich) + "eu-north-1", // Europe (Stockholm) + "eu-south-1", // Europe (Milan) + "eu-south-2", // Europe (Spain) + "me-south-1", // Middle East (Bahrain) + "me-central-1", // Middle East (UAE) + "il-central-1", // Middle East (Israel) + "af-south-1", // Africa (Cape Town) + "ap-southeast-1", // Asia Pacific (Singapore) + "ap-southeast-2", // Asia Pacific (Sydney) + "ap-southeast-3", // Asia Pacific (Jakarta) + "ap-southeast-4", // Asia Pacific (Bangkok) + "ap-northeast-1", // Asia Pacific (Tokyo) + "ap-northeast-2", // Asia Pacific (Seoul) + "ap-northeast-3", // Asia Pacific (Osaka) + "ap-south-1", // Asia Pacific (Mumbai) + "ap-south-2", // Asia Pacific (Hyderabad) + "ap-east-1", // Asia Pacific (Hong Kong) + "ap-southeast-5", // Asia Pacific (Melbourne) + }, + } + // Run the prompt // + _, result, err := prompt.Run() + if err != nil { + return "", err + } + return result, nil +} + +func DisplayInputAWSBucketNamePrompt() (string, error) { + // Prompt for AWS bucket name // + prompt := promptui.Prompt{ + Label: "Enter AWS Bucket Name", + } + // Run the prompt // + result, err := prompt.Run() + if err != nil { + return "", err + } + return result, nil +} diff --git a/pkg/utils/time.go b/pkg/utils/time.go index e7dec10..8c82065 100644 --- a/pkg/utils/time.go +++ b/pkg/utils/time.go @@ -8,3 +8,11 @@ import ( func GetUnixTimeStamp() string { return fmt.Sprintf("%d", time.Now().Unix()) } + +func GetNow() time.Time { + return time.Now() +} + +func GetNowInString() string { + return GetNow().Format("2006-01-02 15:04:05") +} From bb143fefdb44b4acb3857e9a7e682bb877d99291 Mon Sep 17 00:00:00 2001 From: sboy99 Date: Sun, 12 Jan 2025 23:07:16 +0530 Subject: [PATCH 3/5] feat: upload to cloud, aws strategy impl --- .gitignore | 3 ++ config/config.go | 28 ++++++++++++---- config/validator.go | 7 ++++ internal/cmd/cmd.go | 2 ++ internal/config/service.go | 21 ++++++++++++ internal/storage/aws_cloud_storage.go | 46 ++++++++++++++++++++------- internal/storage/cloud_storage.go | 8 ++--- internal/ui/ui.go | 41 ++++++++++++++++++++++++ 8 files changed, 134 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 2be51e7..afd18bc 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ generated/ # Config config.json config.yml + +# Secrets +.env diff --git a/config/config.go b/config/config.go index c623131..558df58 100644 --- a/config/config.go +++ b/config/config.go @@ -31,18 +31,21 @@ type StorageEnum string type storage struct { Type StorageEnum Dest string //TODO: Move Dest to LocalStorage struct - Cloud CloudStorage + Cloud cloudStorage } type CloudEnum string -type CloudStorage struct { +type cloudStorage struct { Type CloudEnum - AWS AWSCloudStorage + AWS _AWSCloudStorage } -type AWSCloudStorage struct { - Region string - BucketName string +type _AWSCloudStorage struct { + Region string + BucketName string + AccessKeyId string + AccessKeySecret string + Endpoint string } const ( @@ -97,6 +100,9 @@ func Save(config *Config) error { // AWS Cloud Storage // viper.Set("storage.cloud.aws.region", config.Storage.Cloud.AWS.Region) viper.Set("storage.cloud.aws.bucket_name", config.Storage.Cloud.AWS.BucketName) + viper.Set("storage.cloud.aws.access_key_id", config.Storage.Cloud.AWS.AccessKeyId) + viper.Set("storage.cloud.aws.access_key_secret", config.Storage.Cloud.AWS.AccessKeySecret) + viper.Set("storage.cloud.aws.endpoint", config.Storage.Cloud.AWS.Endpoint) if err := viper.WriteConfig(); err != nil { return err @@ -121,6 +127,16 @@ func GetConfig() *Config { Storage: storage{ Type: StorageEnum(viper.GetString("storage.type")), Dest: viper.GetString("storage.dest"), + Cloud: cloudStorage{ + Type: CloudEnum(viper.GetString("storage.cloud.type")), + AWS: _AWSCloudStorage{ + Region: viper.GetString("storage.cloud.aws.region"), + BucketName: viper.GetString("storage.cloud.aws.bucket_name"), + AccessKeyId: viper.GetString("storage.cloud.aws.access_key_id"), + AccessKeySecret: viper.GetString("storage.cloud.aws.access_key_secret"), + Endpoint: viper.GetString("storage.cloud.aws.endpoint"), + }, + }, }, } } diff --git a/config/validator.go b/config/validator.go index a11cfca..33f33b0 100644 --- a/config/validator.go +++ b/config/validator.go @@ -8,11 +8,18 @@ import ( ) func setDefaults() { + // App viper.SetDefault("app.name", "go-vault") viper.SetDefault("app.version", "0.0.1") + // Storage viper.SetDefault("storage.type", "local") viper.SetDefault("storage.dest", "./generated") + + // Storage Cloud + // AWS + viper.SetDefault("storage.cloud.aws.endpoint", "default") + } func validateConfig() error { diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 7cb8ea9..e8cdbf3 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/sboy99/go-vault/internal/config" "github.com/sboy99/go-vault/internal/database" + "github.com/sboy99/go-vault/pkg/logger" "github.com/spf13/cobra" ) @@ -35,6 +36,7 @@ var backupCmd = &cobra.Command{ Short: "Create a backup of your database.", Run: func(cmd *cobra.Command, args []string) { dbService := database.NewDatabaseService() + logger.Info("%v", dbService) dbService.Backup() }, } diff --git a/internal/config/service.go b/internal/config/service.go index e8ab2f0..773dec8 100644 --- a/internal/config/service.go +++ b/internal/config/service.go @@ -89,6 +89,27 @@ func (c *ConfigService) SetupConfig() { return } cfg.Storage.Cloud.AWS.BucketName = awsBucketName + + awsAccessKeyId, err := ui.DisplayInputAWSAccessKeyIdPrompt() + if err != nil { + logger.Error("Failed to display input aws access key id prompt\nDetails: %v", err) + return + } + cfg.Storage.Cloud.AWS.AccessKeyId = awsAccessKeyId + + awsAccessKeySecret, err := ui.DisplayInputAWSAccessKeySecretPrompt() + if err != nil { + logger.Error("Failed to display input aws access key secret prompt\nDetails: %v", err) + return + } + cfg.Storage.Cloud.AWS.AccessKeySecret = awsAccessKeySecret + + awsEndpoint, err := ui.DisplayInputAWSEndpointPrompt() + if err != nil { + logger.Error("Failed to display input aws endpoint prompt\nDetails: %v", err) + return + } + cfg.Storage.Cloud.AWS.Endpoint = awsEndpoint } } diff --git a/internal/storage/aws_cloud_storage.go b/internal/storage/aws_cloud_storage.go index 6637d88..4be8997 100644 --- a/internal/storage/aws_cloud_storage.go +++ b/internal/storage/aws_cloud_storage.go @@ -13,25 +13,34 @@ import ( ) type AWSCloudStorage struct { - Region string - BucketName string + Region string + BucketName string + AccessKeyId string + AccessKeySecret string + Endpoint string + Token string } func NewAWSCloudStorage() *AWSCloudStorage { cfg := config.GetConfig() return &AWSCloudStorage{ - Region: cfg.Storage.Cloud.AWS.Region, - BucketName: cfg.Storage.Cloud.AWS.BucketName, + Region: cfg.Storage.Cloud.AWS.Region, + BucketName: cfg.Storage.Cloud.AWS.BucketName, + AccessKeyId: cfg.Storage.Cloud.AWS.AccessKeyId, + AccessKeySecret: cfg.Storage.Cloud.AWS.AccessKeySecret, + Endpoint: cfg.Storage.Cloud.AWS.Endpoint, + Token: "", // TODO: Add token but not required for now } } func (a *AWSCloudStorage) Upload(filename string, data []byte) error { - svc, err := a.getSvc() + s3, err := a.getS3() if err != nil { return err } key := a.buildKey(filename) - if _, err = svc.PutObject(a.createPutObjectInput(key, data)); err != nil { + s3Object := a.createPutObjectInput(key, data) + if _, err = s3.PutObject(s3Object); err != nil { return err } return nil @@ -45,17 +54,30 @@ func (a *AWSCloudStorage) Delete(filename string) error { return fmt.Errorf("Not Impl") } -func (a *AWSCloudStorage) getSvc() (*s3.S3, error) { - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(a.Region), - Credentials: &credentials.Credentials{}, - }) +func (a *AWSCloudStorage) getS3() (*s3.S3, error) { + sess, err := a.getSession() if err != nil { return nil, err } return s3.New(sess), nil } +func (a *AWSCloudStorage) getSession() (*session.Session, error) { + creds := credentials.NewStaticCredentials(a.AccessKeyId, a.AccessKeySecret, a.Token) + if a.Endpoint == "default" { + return session.NewSession(&aws.Config{ + Region: aws.String(a.Region), + Credentials: creds, + }) + } + return session.NewSession(&aws.Config{ + Region: aws.String(a.Region), + Endpoint: aws.String(a.Endpoint), + S3ForcePathStyle: aws.Bool(true), + Credentials: creds, + }) +} + func (a *AWSCloudStorage) createPutObjectInput(key string, data []byte) *s3.PutObjectInput { return &s3.PutObjectInput{ Key: aws.String(key), @@ -65,5 +87,5 @@ func (a *AWSCloudStorage) createPutObjectInput(key string, data []byte) *s3.PutO } func (a *AWSCloudStorage) buildKey(filename string) string { - return filename + "_" + utils.GetUnixTimeStamp() + return utils.GetUnixTimeStamp() + "_" + filename } diff --git a/internal/storage/cloud_storage.go b/internal/storage/cloud_storage.go index d8545d8..6ab81b4 100644 --- a/internal/storage/cloud_storage.go +++ b/internal/storage/cloud_storage.go @@ -9,15 +9,15 @@ type ICloudStorage interface { } type CloudStorage struct { - Type config.CloudEnum - storageMap map[config.CloudEnum]ICloudStorage + Type config.CloudEnum + cloudStorageMap map[config.CloudEnum]ICloudStorage } func NewCloudStorage() *CloudStorage { cfg := config.GetConfig() return &CloudStorage{ Type: cfg.Storage.Cloud.Type, - storageMap: map[config.CloudEnum]ICloudStorage{ + cloudStorageMap: map[config.CloudEnum]ICloudStorage{ config.AWS: NewAWSCloudStorage(), config.GCP: nil, }, @@ -37,5 +37,5 @@ func (c *CloudStorage) Delete(filename string) error { } func (c *CloudStorage) getCloudStorage() ICloudStorage { - return c.storageMap[c.Type] + return c.cloudStorageMap[c.Type] } diff --git a/internal/ui/ui.go b/internal/ui/ui.go index f9e8253..81407d2 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -178,3 +178,44 @@ func DisplayInputAWSBucketNamePrompt() (string, error) { } return result, nil } + +func DisplayInputAWSAccessKeyIdPrompt() (string, error) { + // Prompt for AWS access key id // + prompt := promptui.Prompt{ + Label: "Enter AWS Access Key ID", + } + // Run the prompt // + result, err := prompt.Run() + if err != nil { + return "", err + } + return result, nil +} + +func DisplayInputAWSAccessKeySecretPrompt() (string, error) { + // Prompt for AWS access key secret // + prompt := promptui.Prompt{ + Label: "Enter AWS Access Key Secret", + Mask: '*', + } + // Run the prompt // + result, err := prompt.Run() + if err != nil { + return "", err + } + return result, nil +} + +func DisplayInputAWSEndpointPrompt() (string, error) { + // Prompt for AWS endpoint // + prompt := promptui.Prompt{ + Label: "Enter AWS Endpoint", + Default: "default", + } + // Run the prompt // + result, err := prompt.Run() + if err != nil { + return "", err + } + return result, nil +} From bc843ae2f5a00438fa3f67cc12f6a944c66b0c02 Mon Sep 17 00:00:00 2001 From: sboy99 Date: Sun, 12 Jan 2025 23:13:58 +0530 Subject: [PATCH 4/5] refactor: update enum values --- config/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/config.go b/config/config.go index 558df58..97836da 100644 --- a/config/config.go +++ b/config/config.go @@ -55,13 +55,13 @@ const ( ) const ( - LOCAL StorageEnum = "local" - CLOUD StorageEnum = "cloud" + LOCAL StorageEnum = "LOCAL" + CLOUD StorageEnum = "CLOUD" ) const ( - GCP CloudEnum = "gcp" - AWS CloudEnum = "aws" + GCP CloudEnum = "GCP" + AWS CloudEnum = "AWS" ) func init() { From 16b3b4eb822a2fe63828df509e8f17041facaea4 Mon Sep 17 00:00:00 2001 From: sboy99 Date: Fri, 17 Jan 2025 00:17:40 +0530 Subject: [PATCH 5/5] chore: cmd func alligned --- internal/cmd/cmd.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index e8cdbf3..15191aa 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -17,11 +17,6 @@ var rootCmd = &cobra.Command{ }, } -// Execute runs the root command -func Execute() error { - return rootCmd.Execute() -} - var setupCmd = &cobra.Command{ Use: "setup", Short: "Setup config of your database.", @@ -45,3 +40,8 @@ func init() { rootCmd.AddCommand(setupCmd) rootCmd.AddCommand(backupCmd) } + +// Execute runs the root command +func Execute() error { + return rootCmd.Execute() +}