Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: multycloud/multy
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.1.55
Choose a base ref
...
head repository: multycloud/multy
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref

Commits on Aug 3, 2022

  1. Copy the full SHA
    86e7ec7 View commit details

Commits on Aug 4, 2022

  1. Copy the full SHA
    b033aab View commit details

Commits on Aug 5, 2022

  1. Copy the full SHA
    3e55ab1 View commit details

Commits on Aug 8, 2022

  1. Copy the full SHA
    a28e8d1 View commit details

Commits on Aug 10, 2022

  1. Copy the full SHA
    b36d851 View commit details
  2. Update README.md

    JCoelhoo authored Aug 10, 2022
    Copy the full SHA
    a2877ba View commit details
  3. Copy the full SHA
    e94cbbd View commit details
  4. Copy the full SHA
    d88f2bd View commit details
  5. Copy the full SHA
    ce1a0c7 View commit details

Commits on Aug 11, 2022

  1. Copy the full SHA
    a498905 View commit details
  2. Copy the full SHA
    8ee2c4f View commit details
  3. Copy the full SHA
    9ae4257 View commit details

Commits on Aug 12, 2022

  1. Copy the full SHA
    7694c55 View commit details
  2. Copy the full SHA
    a4068f8 View commit details

Commits on Aug 15, 2022

  1. Copy the full SHA
    73a95fc View commit details

Commits on Aug 16, 2022

  1. Copy the full SHA
    d3541de View commit details
  2. Copy the full SHA
    9d941f8 View commit details

Commits on Aug 17, 2022

  1. Copy the full SHA
    a35a1fe View commit details

Commits on Aug 18, 2022

  1. Copy the full SHA
    bf1f3a7 View commit details
  2. test: assert that read resources after deploy are correct for k8s, vm…

    …s and objs (#411)
    
    test: assert that read resources after deploy are correct for k8s, vms and obj
    goncalo-rodrigues authored Aug 18, 2022
    Copy the full SHA
    30a3818 View commit details
  3. Copy the full SHA
    16de6ac View commit details

Commits on Aug 23, 2022

  1. feat: use tf plan to detect drift in umapped fields (#413)

    * feat: use tf plan to detect drift in umapped fields
    
    * aws drift
    
    * azure drift
    
    * gcp drift
    
    * nil plan for update and create
    goncalo-rodrigues authored Aug 23, 2022
    Copy the full SHA
    54b1870 View commit details
  2. Copy the full SHA
    30d0426 View commit details

Commits on Aug 31, 2022

  1. Copy the full SHA
    16d5ae5 View commit details

Commits on Sep 1, 2022

  1. Copy the full SHA
    ee9106e View commit details

Commits on Sep 2, 2022

  1. Copy the full SHA
    ac25163 View commit details

Commits on Sep 5, 2022

  1. Copy the full SHA
    4f51049 View commit details

Commits on Sep 6, 2022

  1. Copy the full SHA
    2dab6a3 View commit details

Commits on Sep 8, 2022

  1. fix: random suffix in vault e2e test as azure sometimes doesn't free … (

    #423)
    
    fix: random suffix in vault e2e test as azure sometimes doesn't free up names right away
    goncalo-rodrigues authored Sep 8, 2022
    Copy the full SHA
    9fd4fd9 View commit details

Commits on Oct 21, 2022

  1. feat: add overrides for VMs images (#424)

    * feat: add overrides for VM's images (AWS)
    
    * feat: add overrides for VM's images (Azure)
    
    * feat: add overrides for VM's images (GCP)
    
    * feat: add overrides for VM's images
    renaming and a comment
    syanukov authored Oct 21, 2022
    Copy the full SHA
    fb68ed1 View commit details

Commits on Dec 1, 2022

  1. Copy the full SHA
    0c8780b View commit details

Commits on Dec 6, 2022

  1. Copy the full SHA
    5c5e0ea View commit details
  2. Copy the full SHA
    28c84ed View commit details
  3. Copy the full SHA
    be5d961 View commit details
  4. Copy the full SHA
    9ce6fff View commit details

Commits on Dec 14, 2022

  1. fix: fixed k8 default disk size & tf init (#425)

    fixed default disk size; fixed tf init
    
    Co-authored-by: Joao Coelho <joao.coelho@ori.co>
    JCoelhoo and JCoelhoo authored Dec 14, 2022
    Copy the full SHA
    07b8174 View commit details

Commits on Feb 1, 2023

  1. fix: kubeconfig name

    JCoelhoo committed Feb 1, 2023
    Copy the full SHA
    6be746f View commit details
Showing with 4,867 additions and 2,175 deletions.
  1. +1 −1 .github/workflows/e2e.yml
  2. +1 −1 .github/workflows/pr-e2e.yml
  3. +3 −2 README.md
  4. +6 −6 api/aws/local.go
  5. +25 −25 api/deploy/deploy.go
  6. +1 −1 api/deploy/provider_versions.go
  7. +34 −11 api/deploy/terraform_command.go
  8. +282 −114 api/proto/commonpb/common.pb.go
  9. +16 −0 api/proto/commonpb/common.proto
  10. +780 −713 api/proto/multy_service.pb.go
  11. +5 −1 api/proto/multy_service.proto
  12. +6 −6 api/proto/multy_service_grpc.pb.go
  13. +103 −83 api/proto/resourcespb/kubernetes_cluster.pb.go
  14. +3 −0 api/proto/resourcespb/kubernetes_cluster.proto
  15. +322 −196 api/proto/resourcespb/virtual_machine.pb.go
  16. +13 −3 api/proto/resourcespb/virtual_machine.proto
  17. +42 −23 api/server.go
  18. +37 −0 api/services/config_prefix.go
  19. +60 −31 api/services/service.go
  20. +24 −14 db/database.go
  21. +6 −3 db/interface.go
  22. +19 −9 db/local_database.go
  23. +4 −3 db/local_lock_db.go
  24. +8 −8 db/lock_db.go
  25. +6 −6 db/user_config_storage.go
  26. +1 −1 resources/common/cloud_provider.go
  27. +23 −0 resources/common/resource_id.go
  28. +10 −0 resources/common/vm_size.go
  29. +15 −15 resources/output/database/aws_database.go
  30. +43 −45 resources/output/database/azure_databases.go
  31. +2 −7 resources/output/database/azure_mariadb_database.go
  32. +1 −6 resources/output/database/azure_mysql_database.go
  33. +1 −6 resources/output/database/azure_postgresql_database.go
  34. +10 −10 resources/output/database/gcp_database.go
  35. +5 −5 resources/output/iam/aws_iam_role.go
  36. +13 −12 resources/output/kubernetes_node_pool/aws_eks_node_group.go
  37. +11 −10 resources/output/kubernetes_node_pool/azure_aks_node_pool.go
  38. +19 −19 resources/output/kubernetes_node_pool/gcp_gke_node_pool.go
  39. +7 −6 resources/output/kubernetes_service/aws_eks.go
  40. +13 −11 resources/output/kubernetes_service/azure_aks.go
  41. +17 −10 resources/output/kubernetes_service/gcp_gke.go
  42. +12 −5 resources/output/network_security_group/aws_network_security_group.go
  43. +10 −12 resources/output/network_security_group/azure_network_security_group.go
  44. +40 −12 resources/output/network_security_group/gcp_firewall.go
  45. +5 −5 resources/output/object_storage/aws_object_storage.go
  46. +5 −5 resources/output/object_storage/azure_object_storage.go
  47. +5 −4 resources/output/object_storage/gcp_storage_bucket.go
  48. +6 −6 resources/output/object_storage_object/aws_object_storage_object.go
  49. +6 −6 resources/output/object_storage_object/azure_object_storage_object.go
  50. +7 −7 resources/output/object_storage_object/gcp_storage_object.go
  51. +0 −6 resources/output/route_table/azurerm_route_table.go
  52. +2 −2 resources/output/route_table/gcp_route_table.go
  53. +104 −0 resources/output/terraform_plan.go
  54. +1 −25 resources/output/terraform_state.go
  55. +1 −1 resources/output/vault/azurerm_key_vault.go
  56. +2 −2 resources/output/vault_access_policy/gcp_secret_iam_member.go
  57. +1 −1 resources/output/vault_secret/aws_ssm_parameter.go
  58. +1 −1 resources/output/vault_secret/azurerm_key_vault_secret.go
  59. +2 −2 resources/output/vault_secret/gcp_secret_manager_secret.go
  60. +12 −12 resources/output/virtual_machine/aws_virtual_machine.go
  61. +17 −17 resources/output/virtual_machine/azure_virtual_machine.go
  62. +10 −10 resources/output/virtual_machine/gcp_virtual_machine.go
  63. +20 −12 resources/resource_metadata.go
  64. +6 −2 resources/resource_with_id.go
  65. +32 −8 resources/types/aws/database.go
  66. +40 −20 resources/types/aws/kubernetes_cluster.go
  67. +42 −9 resources/types/aws/kubernetes_node_pool.go
  68. +19 −5 resources/types/aws/network_interface.go
  69. +19 −3 resources/types/aws/network_interface_security_group_association.go
  70. +141 −55 resources/types/aws/network_security_group.go
  71. +30 −6 resources/types/aws/object_storage.go
  72. +38 −19 resources/types/aws/object_storage_object.go
  73. +17 −8 resources/types/aws/public_ip.go
  74. +1 −1 resources/types/aws/resource_group.go
  75. +30 −15 resources/types/aws/route_table.go
  76. +13 −5 resources/types/aws/route_table_association.go
  77. +20 −6 resources/types/aws/subnet.go
  78. +1 −1 resources/types/aws/vault.go
  79. +25 −6 resources/types/aws/vault_access_policy.go
  80. +16 −5 resources/types/aws/vault_secret.go
  81. +68 −26 resources/types/aws/virtual_machine.go
  82. +25 −10 resources/types/aws/virtual_network.go
  83. +23 −9 resources/types/azure/database.go
  84. +41 −18 resources/types/azure/kubernetes_cluster.go
  85. +36 −7 resources/types/azure/kubernetes_node_pool.go
  86. +20 −5 resources/types/azure/network_interface.go
  87. +19 −3 resources/types/azure/network_interface_security_group_association.go
  88. +138 −21 resources/types/azure/network_security_group.go
  89. +36 −16 resources/types/azure/object_storage.go
  90. +30 −23 resources/types/azure/object_storage_object.go
  91. +17 −8 resources/types/azure/public_ip.go
  92. +2 −2 resources/types/azure/resource_group.go
  93. +31 −15 resources/types/azure/route_table.go
  94. +24 −7 resources/types/azure/route_table_association.go
  95. +19 −9 resources/types/azure/subnet.go
  96. +14 −6 resources/types/azure/vault.go
  97. +16 −6 resources/types/azure/vault_access_policy.go
  98. +15 −5 resources/types/azure/vault_secret.go
  99. +57 −24 resources/types/azure/virtual_machine.go
  100. +21 −10 resources/types/azure/virtual_network.go
  101. +50 −7 resources/types/gcp/database.go
  102. +56 −21 resources/types/gcp/kubernetes_cluster.go
  103. +49 −11 resources/types/gcp/kubernetes_node_pool.go
  104. +126 −5 resources/types/gcp/network_security_group.go
  105. +19 −6 resources/types/gcp/object_storage.go
  106. +31 −19 resources/types/gcp/object_storage_object.go
  107. +16 −9 resources/types/gcp/public_ip.go
  108. +1 −1 resources/types/gcp/resource_group.go
  109. +29 −6 resources/types/gcp/route_table.go
  110. +1 −1 resources/types/gcp/route_table_association.go
  111. +16 −5 resources/types/gcp/subnet.go
  112. +1 −1 resources/types/gcp/vault.go
  113. +38 −5 resources/types/gcp/vault_access_policy.go
  114. +24 −10 resources/types/gcp/vault_secret.go
  115. +61 −23 resources/types/gcp/virtual_machine.go
  116. +19 −7 resources/types/gcp/virtual_network.go
  117. +5 −0 resources/types/kubernetes_node_pool.go
  118. +6 −0 resources/types/network_interface_security_group_association.go
  119. +6 −0 resources/types/object_storage_object.go
  120. +6 −0 resources/types/route_table.go
  121. +6 −0 resources/types/route_table_association.go
  122. +6 −0 resources/types/subnet.go
  123. +6 −0 resources/types/vault_access_policy.go
  124. +6 −0 resources/types/vault_secret.go
  125. +3 −0 test/_configs/kubernetes/kubernetes/main.tf
  126. +3 −0 test/_configs/kubernetes/kubernetes_size_override/main.tf
  127. +3 −0 test/_configs/kubernetes/kubernetes_zones/main.tf
  128. +4 −4 ...network_interface_security_group_association/network_interface_security_group_association/main.tf
  129. +6 −6 test/_configs/network_security_group/network_security_group/main.tf
  130. +3 −3 test/_configs/object_storage/object_storage/config.textproto
  131. +5 −4 test/_configs/object_storage/object_storage/main.tf
  132. +3 −3 test/_configs/object_storage_object/object_storage_object/config.textproto
  133. +5 −14 test/_configs/object_storage_object/object_storage_object/main.tf
  134. +6 −6 test/_configs/subnet/subnet_public_private/main.tf
  135. +233 −0 test/_configs/virtual_machine/virtual_machine_image_override/config_gen.textproto
  136. +289 −0 test/_configs/virtual_machine/virtual_machine_image_override/main.tf
  137. +2 −2 test/_configs/virtual_machine/virtual_machine_images/config_gen.textproto
  138. +2 −2 test/_configs/virtual_machine/virtual_machine_images/main.tf
  139. +5 −5 test/deploy/deploy_test.go
  140. +5 −0 test/deploy/terraform_command_mock.go
  141. +45 −1 test/e2e/common.go
  142. +18 −0 test/e2e/database_test.go
  143. +82 −0 test/e2e/drift_test.go
  144. +60 −1 test/e2e/kubernetes_test.go
  145. +20 −1 test/e2e/nsg_test.go
  146. +17 −4 test/e2e/object_storage_object_test.go
  147. +7 −0 test/e2e/public_ip_test.go
  148. +24 −1 test/e2e/vault_secret_test.go
  149. +24 −1 test/e2e/virtual_machine_test.go
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ jobs:
run: gcloud components install gke-gcloud-auth-plugin

- name: Test
run: go test ./test/e2e -tags=e2e -timeout=180m -parallel 10
run: go test ./test/e2e -tags=e2e -timeout=180m -parallel 20
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_E2E }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_E2E }}
2 changes: 1 addition & 1 deletion .github/workflows/pr-e2e.yml
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ jobs:
run: gcloud components install gke-gcloud-auth-plugin

- name: Test
run: go test ./test/e2e -tags=e2e -timeout=180m -parallel 10
run: go test ./test/e2e -tags=e2e -timeout=180m -parallel 20
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_E2E }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_E2E }}
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<br>
<p align="center">
<a href="https://multy.dev?utm_source=github.com">
<img src="https://multy.dev/assets/multy_logo_horizontal.jpg" width="250">
<img src="https://multy.dev/logo_dark_mode.svg" width="250">
</a>
</p>

@@ -13,7 +14,7 @@ Multy is the easiest way to deploy multi cloud infrastructure
<br>
<br>
<p align="center">
<img src="https://multy.dev/assets/multy-diagram.png" width="500">
<img src="https://multy.dev/images/reusibility.svg" width="500">
</p>

<br>
12 changes: 6 additions & 6 deletions api/aws/local.go
Original file line number Diff line number Diff line change
@@ -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
}
@@ -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
}
@@ -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
50 changes: 25 additions & 25 deletions api/deploy/deploy.go
Original file line number Diff line number Diff line change
@@ -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
}
@@ -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
@@ -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
@@ -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
@@ -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()
@@ -147,17 +147,22 @@ 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) GetPlan(ctx context.Context, configPrefix string) (string, error) {
tmpDir := GetTempDirForUser(configPrefix)
return d.TfCmd.Plan(ctx, tmpDir)
}

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
}
@@ -167,21 +172,16 @@ 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 {
start := time.Now()
defer func() {
log.Printf("[DEBUG] refresh finished in %s", time.Since(start))
}()

tmpDir := GetTempDirForUser(userId)
func (d DeploymentExecutor) refresh(ctx context.Context, configPrefix string) error {
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")
2 changes: 1 addition & 1 deletion api/deploy/provider_versions.go
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ func GetTerraformBlock(userId string) (string, error) {
}

func getLocalStateBlock(userId string) string {
p := path.Join(os.TempDir(), "multy", userId, "local", db.TfState)
p := path.Join(db.TfState)
return fmt.Sprintf(
`backend "local" {
path = "%s"
45 changes: 34 additions & 11 deletions api/deploy/terraform_command.go
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ type TerraformCommand interface {
Init(ctx context.Context, dir string) error
Apply(ctx context.Context, dir string, resources []string) error
Refresh(ctx context.Context, dir string) error
Plan(ctx context.Context, dir string) (string, error)
GetState(ctx context.Context, userId string, dir db.TfStateReader) (*output.TfState, error)
}

@@ -78,7 +79,7 @@ func (c terraformCmd) Init(ctx context.Context, dir string) error {
region := trace.StartRegion(ctx, "tf init")
defer region.End()

cmd := exec.CommandContext(ctx, "terraform", "-chdir="+dir, "init", "-reconfigure", "-lock-timeout", "1m")
cmd := exec.CommandContext(ctx, "terraform", "-chdir="+dir, "init", "-migrate-state", "-force-copy", "-lock-timeout", "1m")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
@@ -110,6 +111,28 @@ func (c terraformCmd) Refresh(ctx context.Context, dir string) error {
return err
}

func (c terraformCmd) Plan(ctx context.Context, dir string) (string, error) {
region := trace.StartRegion(ctx, "tf plan")
defer region.End()

outputJson := new(bytes.Buffer)
cmd := exec.CommandContext(ctx, "terraform", "-chdir="+dir, "plan", "-json", "-refresh=false")
cmd.Stdout = outputJson
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
outputs, parseErr := parseTfOutputs(outputJson)
if parseErr != nil {
return "", errors.InternalServerErrorWithMessage("error querying resources for drift", parseErr)
}
if parseErr := getFirstError(outputs); parseErr != nil {
return "", errors.InternalServerErrorWithMessage("error querying resources for drift", parseErr)
}
return "", errors.InternalServerErrorWithMessage("error querying resources for drift", err)
}
return outputJson.String(), nil
}

func (c terraformCmd) GetState(ctx context.Context, userId string, client db.TfStateReader) (*output.TfState, error) {
region := trace.StartRegion(ctx, "tf show")
defer region.End()
@@ -123,7 +146,8 @@ func (c terraformCmd) GetState(ctx context.Context, userId string, client db.TfS

err = json.Unmarshal([]byte(terraformState), &state)
if err != nil {
return nil, err
log.Printf("[ERROR] Unable to parse terraform output (error: %s): %s\n", err, terraformState)
return nil, errors.InternalServerErrorWithMessage("unable to parse terraform get output", err)
}
return &state, err
}
@@ -143,19 +167,18 @@ func getFirstError(outputs []tfOutput) error {

func parseTfOutputs(outputJson *bytes.Buffer) ([]tfOutput, error) {
var out []tfOutput
line, err := outputJson.ReadString('\n')
for ; err == nil; line, err = outputJson.ReadString('\n') {
elem := tfOutput{}
err = json.Unmarshal([]byte(line), &elem)
if err != nil {
return nil, err
}
var err error
elem := tfOutput{}
dec := json.NewDecoder(outputJson)
for ; err == nil; err = dec.Decode(&elem) {
out = append(out, elem)
elem = tfOutput{}
}

if err == io.EOF {
return out, nil
} else {
log.Printf("[ERROR] Unable to parse terraform output (error: %s): %s\n", err, outputJson.String())
return nil, err
}

return nil, err
}
Loading