diff --git a/README.md b/README.md index eddc86c..8e80ca3 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,11 @@ Here's a quick view of what `tfautomv` does: `tfautomv` uses the Terraform CLI command under the hood. This allows it to work with any Terraform version reliably. -You will need Terraform v1.1 or above to generate `moved` blocks. Or Terraform -v0.13 or above to generate `terraform state mv` commands. +Certain features require specific versions of Terraform: + +- `moved` blocks require Terraform v1.1 or above +- cross-module `terraform state mv` commands require Terraform v0.14 or above +- single-module `terraform state mv` commands require Terraform v0.13 or above ## Installation diff --git a/go.mod b/go.mod index 3335679..7d2f052 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/busser/tfautomv -go 1.22 +go 1.22.0 require ( github.com/google/go-cmp v0.6.0 diff --git a/go.sum b/go.sum index e750e55..f19a920 100644 --- a/go.sum +++ b/go.sum @@ -1,64 +1,76 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs= -github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= -github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= +github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.6.0 h1:fDHnU7JNFNSQebVKYhHZ0va1bC6SrPQ8fpebsvNr2w4= -github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= -github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= +github.com/hashicorp/hc-install v0.6.2 h1:V1k+Vraqz4olgZ9UzKiAcbman9i9scg9GgSt/U3mw/M= +github.com/hashicorp/hc-install v0.6.2/go.mod h1:2JBpd+NCFKiHiu/yYCGaPyPHhZLxXTpz8oreHa/a3Ps= github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo= github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw= -github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA= -github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o= -github.com/hashicorp/terraform-json v0.19.0 h1:e9DBKC5sxDfiJT7Zoi+yRIwqLVtFur/fwK/FuE6AWsA= -github.com/hashicorp/terraform-json v0.19.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= github.com/hashicorp/terraform-json v0.21.0 h1:9NQxbLNqPbEMze+S6+YluEdXgJmhQykRyRNd+zTI05U= github.com/hashicorp/terraform-json v0.21.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/zclconf/go-cty v1.14.0 h1:/Xrd39K7DXbHzlisFP9c4pHao4yyf+/Ug9LEz+Y/yhc= -github.com/zclconf/go-cty v1.14.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA= github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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/main.go b/main.go index b2459ff..48c511d 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,11 @@ var tfautomvVersion string func run() error { parseFlags() + workdirs := flag.Args() + if len(workdirs) == 0 { + workdirs = []string{"."} + } + if noColor { pretty.DisableColors() } @@ -66,6 +71,11 @@ func run() error { return fmt.Errorf("Terraform version %s does not support moved blocks", tfVersion) } + crossModuleMovesSupported := tfVersion.GreaterThanOrEqual(version.Must(version.NewSemver("0.14.0"))) + if len(workdirs) > 1 && !crossModuleMovesSupported { + return fmt.Errorf("Terraform version %s does not support moves across modules", tfVersion) + } + /* * Step 1: Parse user-provided rules * @@ -89,11 +99,6 @@ func run() error { * Run `terraform plan` for each working directory provided by the user. */ - workdirs := flag.Args() - if len(workdirs) == 0 { - workdirs = []string{"."} - } - planOptions := []terraform.Option{ terraform.WithTerraformBin(terraformBin), terraform.WithSkipInit(skipInit), @@ -290,19 +295,26 @@ func writeMovedBlocks(moves []terraform.Move) error { return nil } - movesFilePath := filepath.Join(moves[0].FromWorkdir, "moves.tf") - movesFile, err := os.OpenFile(movesFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return fmt.Errorf("failed to open %q: %w", movesFilePath, err) + movesByWorkdir := make(map[string][]terraform.Move) + for _, m := range moves { + movesByWorkdir[m.FromWorkdir] = append(movesByWorkdir[m.FromWorkdir], m) } - err = terraform.WriteMovedBlocks(movesFile, moves) - if err != nil { - return fmt.Errorf("failed to write moved blocks: %w", err) - } + for workdir, moves := range movesByWorkdir { + movesFilePath := filepath.Join(workdir, "moves.tf") + movesFile, err := os.OpenFile(movesFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("failed to open %q: %w", movesFilePath, err) + } - os.Stderr.WriteString(pretty.Colorf("%s written to [bold][green]%s", pretty.StyledNumMoves(len(moves)), movesFilePath)) - os.Stderr.WriteString("\n") + err = terraform.WriteMovedBlocks(movesFile, moves) + if err != nil { + return fmt.Errorf("failed to write moved blocks: %w", err) + } + + os.Stderr.WriteString(pretty.Colorf("%s written to [bold][green]%s", pretty.StyledNumMoves(len(moves)), movesFilePath)) + os.Stderr.WriteString("\n") + } return nil } diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index b2004a6..913060c 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -37,9 +37,9 @@ resource "random_pet" "refactored_third" { writeCode(t, codePath, originalCode) terraformInitAndApply(t, workdir) writeCode(t, codePath, refactoredCode) - runTfautomv(t, workdir) + runTfautomv(t, workdir, nil) changeCount := countPlannedChanges(terraformPlan(t, workdir)) - assert.Equal(t, changeCount, 0) + assert.Equal(t, 0, changeCount) } func TestE2E_DependencyAnalysis(t *testing.T) { @@ -99,9 +99,9 @@ resource "random_pet" "second" { writeCode(t, codePath, originalCode) terraformInitAndApply(t, workdir) writeCode(t, codePath, refactoredCode) - runTfautomv(t, workdir) + runTfautomv(t, workdir, nil) changeCount := countPlannedChanges(terraformPlan(t, workdir)) - assert.Equal(t, changeCount, 0) + assert.Equal(t, 0, changeCount) } func TestE2E_MultipleTypes(t *testing.T) { @@ -119,9 +119,9 @@ resource "random_uuid" "refactored" {}` writeCode(t, codePath, originalCode) terraformInitAndApply(t, workdir) writeCode(t, codePath, refactoredCode) - runTfautomv(t, workdir) + runTfautomv(t, workdir, nil) changeCount := countPlannedChanges(terraformPlan(t, workdir)) - assert.Equal(t, changeCount, 0) + assert.Equal(t, 0, changeCount) } func TestE2E_DifferentAttributes(t *testing.T) { @@ -142,13 +142,13 @@ resource "random_pet" "refactored" { terraformInitAndApply(t, workdir) writeCode(t, codePath, refactoredCode) - runTfautomv(t, workdir) + runTfautomv(t, workdir, nil) changeCount := countPlannedChanges(terraformPlan(t, workdir)) - assert.Equal(t, changeCount, 2) + assert.Equal(t, 2, changeCount) - runTfautomv(t, workdir, "--ignore=everything:random_pet:length") + runTfautomv(t, workdir, []string{"--ignore=everything:random_pet:length"}) changeCount = countPlannedChanges(terraformPlan(t, workdir)) - assert.Equal(t, changeCount, 1) + assert.Equal(t, 1, changeCount) } func TestE2E_Terragrunt(t *testing.T) { @@ -199,9 +199,9 @@ inputs = { writeCode(t, terragruntConfigPath, terragruntConfig) terragruntInitAndApply(t, workdir) writeCode(t, codePath, refactoredCode) - runTfautomv(t, workdir, "--terraform-bin=terragrunt") + runTfautomv(t, workdir, []string{"--terraform-bin=terragrunt"}) changeCount := countPlannedChanges(terragruntPlan(t, workdir)) - assert.Equal(t, changeCount, 0) + assert.Equal(t, 0, changeCount) } func TestE2E_TerraformCloud(t *testing.T) { @@ -259,7 +259,95 @@ resource "random_pet" "refactored_third" { writeCode(t, codePath, originalCode) terraformInit(t, workdir) writeCode(t, codePath, refactoredCode) - runTfautomv(t, workdir) + runTfautomv(t, workdir, nil) changeCount := countPlannedChanges(terraformPlan(t, workdir)) - assert.Equal(t, changeCount, 0) + assert.Equal(t, 0, changeCount) +} + +func TestE2E_MultipleModules(t *testing.T) { + tfVersion := terraformVersion(t) + if tfVersion.LessThan(version.Must(version.NewVersion("0.14"))) { + t.Skip("tfautomv requires Terraform 0.14 or later to run this test") + } + + workdirA := t.TempDir() + codePathA := filepath.Join(workdirA, "main.tf") + + workdirB := t.TempDir() + codePathB := filepath.Join(workdirB, "main.tf") + + workdirC := t.TempDir() + codePathC := filepath.Join(workdirC, "main.tf") + + originalCodeA := ` +resource "random_pet" "original_first" { + length = 1 +} +resource "random_pet" "original_second" { + length = 2 +} +` + originalCodeB := ` +resource "random_pet" "original_third" { + length = 3 +} +resource "random_pet" "original_fourth" { + length = 4 +} +` + originalCodeC := ` +resource "random_pet" "original_fifth" { + length = 5 +} +resource "random_pet" "original_sixth" { + length = 6 +} +` + + refactoredCodeA := ` +resource "random_pet" "refactored_first" { + length = 1 +} +resource "random_pet" "refactored_fourth" { + length = 4 +} +` + refactoredCodeB := ` +resource "random_pet" "refactored_third" { + length = 3 +} +resource "random_pet" "refactored_sixth" { + length = 6 +} +` + refactoredCodeC := ` +resource "random_pet" "refactored_fifth" { + length = 5 +} +resource "random_pet" "refactored_second" { + length = 2 +} +` + + writeCode(t, codePathA, originalCodeA) + writeCode(t, codePathB, originalCodeB) + writeCode(t, codePathC, originalCodeC) + + terraformInitAndApply(t, workdirA) + terraformInitAndApply(t, workdirB) + terraformInitAndApply(t, workdirC) + + writeCode(t, codePathA, refactoredCodeA) + writeCode(t, codePathB, refactoredCodeB) + writeCode(t, codePathC, refactoredCodeC) + + // We don't care where we run tfautomv from, since we explicitly pass the + // workdirs as arguments. + runTfautomv(t, t.TempDir(), []string{workdirA, workdirB, workdirC}) + + changeCount := 0 + changeCount += countPlannedChanges(terraformPlan(t, workdirA)) + changeCount += countPlannedChanges(terraformPlan(t, workdirB)) + changeCount += countPlannedChanges(terraformPlan(t, workdirC)) + assert.Equal(t, 0, changeCount) } diff --git a/test/e2e/test_utils.go b/test/e2e/test_utils.go index 978b754..9ac0fb6 100644 --- a/test/e2e/test_utils.go +++ b/test/e2e/test_utils.go @@ -143,7 +143,7 @@ func terragruntPlan(t *testing.T, workdir string) *tfjson.Plan { return runPlan(t, workdir, terragruntBin) } -func runTfautomv(t *testing.T, workdir string, args ...string) { +func runTfautomv(t *testing.T, workdir string, args []string) { t.Helper() tfautomvBinAbsPath, err := filepath.Abs(tfautomvBin)