hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.72k stars 9.55k forks source link

Terraform init should detect module cycles #22648

Open VladRassokhin opened 5 years ago

VladRassokhin commented 5 years ago

Current Terraform Version

0.12.7

Use-cases

It may happen that two or more modules depends on each other. Instead of producing cyptinc error terraform could detect that. Given project structure:

main.tf
a/a.tf

with content of main.tf as module "a" { source = "./a"} and a/a.tf as module "p" { source = "./../"} terraform init outputs some not easy to understand messages, like:

Error: Failed to remove local module cache

Terraform tried to remove
.terraform/modules/a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a.p.a
in order to reinstall this module, but encountered an error: unlinkat

Full log in gist

Proposal

Ensure that modules graph is acyclic before trying to create module directories under .terraform/modules

References

15276

VladRassokhin commented 5 years ago

It can be even simplified to just one file with content module "r" { source = "./"}

saiaman commented 4 years ago

any solution ?

qiuxin commented 2 years ago

any solution ?

vjmanda commented 2 years ago

Any thoughts on achieving this? I've got a similar issue with recursive modules.

https://discuss.hashicorp.com/t/are-recursive-modules-even-a-possibility-in-terraform/42745

bhargavpanth commented 1 year ago

I was running into this issue and realized that the issue was being caused by having my TF module inside a parent directory. Ex:

|
-- ec2/
      |
      --- key_pair/
      - main.tf
      - variables.tf
      - outputs.tf

And I was trying to reference key_pair it in my Terratests like so


func generateEC2KeyPair(t *testing.T, target string, keyName string) *terraform.Options {
    return terraform.WithDefaultRetryableErrors(t, &terraform.Options{
        TerraformDir: "./modules/ec2/key_pair",
        Vars: map[string]interface{}{
            "key_name": keyName,
        },
        Targets: []string{target},
    })
}

All I had to do was remove the parent ec2 directory