Skip to content

Commit

Permalink
feat: separate state per cloud (#395)
Browse files Browse the repository at this point in the history
  • Loading branch information
goncalo-rodrigues authored Aug 5, 2022
1 parent b033aab commit 3e55ab1
Show file tree
Hide file tree
Showing 23 changed files with 247 additions and 129 deletions.
12 changes: 6 additions & 6 deletions api/aws/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ func newLocalClient() (*LocalClient, error) {
return &LocalClient{}, nil
}

func (c LocalClient) SaveFile(userId string, fileName string, content string) error {
filePath, err := c.getFilePath(userId, fileName)
func (c LocalClient) SaveFile(configPrefix string, fileName string, content string) error {
filePath, err := c.getFilePath(configPrefix, fileName)
if err != nil {
return err
}
Expand All @@ -26,8 +26,8 @@ func (c LocalClient) SaveFile(userId string, fileName string, content string) er
return nil
}

func (c LocalClient) ReadFile(userId string, fileName string) (string, error) {
filePath, err := c.getFilePath(userId, fileName)
func (c LocalClient) ReadFile(configPrefix string, fileName string) (string, error) {
filePath, err := c.getFilePath(configPrefix, fileName)
if err != nil {
return "", err
}
Expand All @@ -42,8 +42,8 @@ func (c LocalClient) ReadFile(userId string, fileName string) (string, error) {
return string(file), nil
}

func (c LocalClient) getFilePath(userId string, fileName string) (string, error) {
tmpDir := path.Join(os.TempDir(), "multy", userId, "local")
func (c LocalClient) getFilePath(configPrefix string, fileName string) (string, error) {
tmpDir := path.Join(os.TempDir(), "multy", configPrefix, "local")
err := os.MkdirAll(tmpDir, os.ModeDir|(os.ModePerm&0775))
if err != nil {
return "", err
Expand Down
40 changes: 20 additions & 20 deletions api/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ func NewDeploymentExecutor() DeploymentExecutor {
return DeploymentExecutor{TfCmd: terraformCmd{}}
}

func (d DeploymentExecutor) Deploy(ctx context.Context, c *resources.MultyConfig, prev resources.Resource, curr resources.Resource) (rollbackFn func(), err error) {
tmpDir := GetTempDirForUser(c.GetUserId())
encoded, err := d.EncodeAndStoreTfFile(ctx, c, prev, curr)
func (d DeploymentExecutor) Deploy(ctx context.Context, c *resources.MultyConfig, prev resources.Resource, curr resources.Resource, configPrefix string) (rollbackFn func(), err error) {
tmpDir := GetTempDirForUser(configPrefix)
encoded, err := d.EncodeAndStoreTfFile(ctx, c, prev, curr, configPrefix)
if err != nil {
return
}

err = d.MaybeInit(ctx, c.GetUserId())
err = d.MaybeInit(ctx, configPrefix)
if err != nil {
return
}
Expand All @@ -68,7 +68,7 @@ func (d DeploymentExecutor) Deploy(ctx context.Context, c *resources.MultyConfig
log.Printf("[ERROR] Rollback unsuccessful: %s\n", err2)
return
}
_, err2 = d.EncodeAndStoreTfFile(ctx, originalC, curr, prev)
_, err2 = d.EncodeAndStoreTfFile(ctx, originalC, curr, prev, configPrefix)
if err2 != nil {
log.Printf("[ERROR] Rollback unsuccessful: %s\n", err2)
return
Expand Down Expand Up @@ -96,7 +96,7 @@ func (d DeploymentExecutor) Deploy(ctx context.Context, c *resources.MultyConfig
return
}

func (d DeploymentExecutor) EncodeAndStoreTfFile(ctx context.Context, c *resources.MultyConfig, prev resources.Resource, curr resources.Resource) (EncodedResources, error) {
func (d DeploymentExecutor) EncodeAndStoreTfFile(ctx context.Context, c *resources.MultyConfig, prev resources.Resource, curr resources.Resource, configPrefix string) (EncodedResources, error) {
credentials, err := util.ExtractCloudCredentials(ctx)
if err != nil {
return EncodedResources{}, err
Expand All @@ -106,15 +106,15 @@ func (d DeploymentExecutor) EncodeAndStoreTfFile(ctx context.Context, c *resourc
return encoded, err
}

tfBlock, err := GetTerraformBlock(c.GetUserId())
tfBlock, err := GetTerraformBlock(configPrefix)
if err != nil {
return encoded, err
}

// TODO: move this to a proper place
hclOutput := tfBlock + encoded.HclString

tmpDir := GetTempDirForUser(c.GetUserId())
tmpDir := GetTempDirForUser(configPrefix)
err = os.MkdirAll(tmpDir, os.ModeDir|(os.ModePerm&0775))
if err != nil {
return EncodedResources{}, err
Expand All @@ -123,8 +123,8 @@ func (d DeploymentExecutor) EncodeAndStoreTfFile(ctx context.Context, c *resourc
return encoded, err
}

func (d DeploymentExecutor) MaybeInit(ctx context.Context, userId string) error {
tmpDir := GetTempDirForUser(userId)
func (d DeploymentExecutor) MaybeInit(ctx context.Context, configPrefix string) error {
tmpDir := GetTempDirForUser(configPrefix)
_, err := os.Stat(filepath.Join(tmpDir, tfDir))
if os.IsNotExist(err) {
start := time.Now()
Expand All @@ -147,17 +147,17 @@ func (d DeploymentExecutor) MaybeInit(ctx context.Context, userId string) error
return nil
}

func (d DeploymentExecutor) GetState(ctx context.Context, userId string, client db.TfStateReader) (*output.TfState, error) {
return d.TfCmd.GetState(ctx, userId, client)
func (d DeploymentExecutor) GetState(ctx context.Context, configPrefix string, client db.TfStateReader) (*output.TfState, error) {
return d.TfCmd.GetState(ctx, configPrefix, client)
}

func (d DeploymentExecutor) RefreshState(ctx context.Context, userId string, c *resources.MultyConfig) error {
_, err := d.EncodeAndStoreTfFile(ctx, c, nil, nil)
func (d DeploymentExecutor) RefreshState(ctx context.Context, configPrefix string, c *resources.MultyConfig) error {
_, err := d.EncodeAndStoreTfFile(ctx, c, nil, nil, configPrefix)
if err != nil {
return err
}

err = d.MaybeInit(ctx, userId)
err = d.MaybeInit(ctx, configPrefix)
if err != nil {
return err
}
Expand All @@ -167,21 +167,21 @@ func (d DeploymentExecutor) RefreshState(ctx context.Context, userId string, c *
log.Printf("[DEBUG] refresh finished in %s", time.Since(start))
}()

return d.refresh(ctx, userId)
return d.refresh(ctx, configPrefix)
}

func (d DeploymentExecutor) refresh(ctx context.Context, userId string) error {
func (d DeploymentExecutor) refresh(ctx context.Context, configPrefix string) error {
start := time.Now()
defer func() {
log.Printf("[DEBUG] refresh finished in %s", time.Since(start))
}()

tmpDir := GetTempDirForUser(userId)
tmpDir := GetTempDirForUser(configPrefix)
return d.TfCmd.Refresh(ctx, tmpDir)
}

func GetTempDirForUser(userId string) string {
tmpDir := filepath.Join(os.TempDir(), "multy", userId)
func GetTempDirForUser(configPrefix string) string {
tmpDir := filepath.Join(os.TempDir(), "multy", configPrefix)

if flags.Environment == flags.Local {
tmpDir = filepath.Join(tmpDir, "local")
Expand Down
47 changes: 28 additions & 19 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,13 +373,14 @@ func (s *Server) refresh(ctx context.Context, _ *commonpb.Empty) (*commonpb.Empt
return nil, err
}

lock, err := s.Database.LockConfig(ctx, userId)
lock, err := s.Database.LockConfig(ctx, userId, userId)
if err != nil {
return nil, err
}
defer s.Database.UnlockConfig(ctx, lock)

c, err := s.Database.LoadUserConfig(ctx, userId, lock)
// TODO: ask for cloud in request
c, err := s.Database.LoadUserConfig(ctx, userId, userId, lock)
if err != nil {
return nil, err
}
Expand All @@ -393,7 +394,7 @@ func (s *Server) refresh(ctx context.Context, _ *commonpb.Empty) (*commonpb.Empt
return nil, err
}

err = s.Database.StoreUserConfig(ctx, c, lock)
err = s.Database.StoreUserConfig(ctx, c, userId, lock)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -422,20 +423,27 @@ func (s *Server) list(ctx context.Context, _ *commonpb.Empty) (*commonpb.ListRes
return nil, err
}

c, err := s.Database.LoadUserConfig(ctx, userId, nil)
if err != nil {
return nil, err
}

resp := &commonpb.ListResourcesResponse{}
for _, r := range c.Resources {
name := string(r.ResourceArgs.ResourceArgs.MessageName().Name())
name = strings.TrimSuffix(name, "Args")

resp.Resources = append(resp.Resources, &commonpb.ListResourcesResponse_ResourceMetadata{
ResourceId: r.ResourceId,
ResourceType: name,
})

for cloudValue := range commonpb.CloudProvider_name {
cloud := commonpb.CloudProvider(cloudValue)
if cloud == commonpb.CloudProvider_UNKNOWN_PROVIDER {
continue
}
c, err := s.Database.LoadUserConfig(ctx, userId, services.GetConfigPrefixForCloud(userId, cloud), nil)
if err != nil {
return nil, err
}

for _, r := range c.Resources {
name := string(r.ResourceArgs.ResourceArgs.MessageName().Name())
name = strings.TrimSuffix(name, "Args")

resp.Resources = append(resp.Resources, &commonpb.ListResourcesResponse_ResourceMetadata{
ResourceId: r.ResourceId,
ResourceType: name,
})
}
}

return resp, nil
Expand All @@ -461,13 +469,14 @@ func (s *Server) deleteResource(ctx context.Context, req *proto.DeleteResourceRe
if err != nil {
return nil, err
}
configPrefix := services.GetConfigPrefix(req, userId)

lock, err := s.Database.LockConfig(ctx, userId)
lock, err := s.Database.LockConfig(ctx, userId, configPrefix)
if err != nil {
return nil, err
}
defer s.Database.UnlockConfig(ctx, lock)
c, err := s.Database.LoadUserConfig(ctx, userId, lock)
c, err := s.Database.LoadUserConfig(ctx, userId, configPrefix, lock)
if err != nil {
return nil, err
}
Expand All @@ -477,7 +486,7 @@ func (s *Server) deleteResource(ctx context.Context, req *proto.DeleteResourceRe
return nil, err
}

err = s.Database.StoreUserConfig(ctx, c, lock)
err = s.Database.StoreUserConfig(ctx, c, configPrefix, lock)
if err != nil {
return nil, err
}
Expand Down
37 changes: 37 additions & 0 deletions api/services/config_prefix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package services

import (
"fmt"
"github.com/multycloud/multy/api/proto/commonpb"
"github.com/multycloud/multy/resources"
"github.com/multycloud/multy/resources/common"
"github.com/multycloud/multy/resources/types/metadata"
"google.golang.org/protobuf/proto"
"strings"
)

func GetConfigPrefixForCloud(userId string, cloud commonpb.CloudProvider) string {
return fmt.Sprintf("%s/%s", userId, strings.ToLower(cloud.String()))
}

func GetConfigPrefix(req WithResourceId, userId string) string {
cloud := common.ParseCloudFromResourceId(req.GetResourceId())
if cloud == commonpb.CloudProvider_UNKNOWN_PROVIDER {
return userId
}

return GetConfigPrefixForCloud(userId, cloud)
}

func getConfigPrefixForCreateReq(r proto.Message, userId string) string {
converter, err := resources.ResourceMetadatas(metadata.Metadatas).GetConverter(proto.MessageName(r))
if err != nil {
return ""
}
cloud := converter.ParseCloud(r)
if cloud == commonpb.CloudProvider_UNKNOWN_PROVIDER {
return userId
}

return GetConfigPrefixForCloud(userId, cloud)
}
Loading

0 comments on commit 3e55ab1

Please sign in to comment.