Terraspace all down not building dependent stacks?

Hi Tung and Boltops Community,

In a parallel universe, terraspace all down used to work for me when I had multiple dependent stacks. However, I’m using now using terraspace 1.1.3 and doing a terraspace all down is giving me errors, which I suspect is due to Terraspace not building the dependent stacks (admittedly, the number of stacks in the project have grown since I last used terraspace all down).

So, I think that… When we have dependent stacks, terraspace all down still works out the dependent stacks correctly. But I think it doesn’t build/create the dependent folder/stack in the cache, and therefore the current won’t destroy properly (because it will fail to resolve the variables that references the dependent stacks).

Here is an output of doing a terraspace all graph --format text of our project

Building graph...
.
├── appstream
│   ├── network
│   ├── s3
│   └── securitygroups
│       └── network
├── asg
│   ├── compute
│   │   ├── network
│   │   ├── s3
│   │   └── securitygroups
│   │       └── network
│   ├── securitygroups
│   │   └── network
│   ├── network
│   └── loadbalancer
│       ├── network
│       ├── s3
│       ├── compute
│       │   ├── network
│       │   ├── s3
│       │   └── securitygroups
│       │       └── network
│       └── securitygroups
│           └── network
├── cloudfront
│   ├── s3
│   ├── loadbalancer
│   │   ├── network
│   │   ├── s3
│   │   ├── compute
│   │   │   ├── network
│   │   │   ├── s3
│   │   │   └── securitygroups
│   │   │       └── network
│   │   └── securitygroups
│   │       └── network
│   ├── acm
│   │   └── route53
│   │       ├── network
│   │       ├── compute
│   │       │   ├── network
│   │       │   ├── s3
│   │       │   └── securitygroups
│   │       │       └── network
│   │       └── loadbalancer
│   │           ├── network
│   │           ├── s3
│   │           ├── compute
│   │           │   ├── network
│   │           │   ├── s3
│   │           │   └── securitygroups
│   │           │       └── network
│   │           └── securitygroups
│   │               └── network
│   └── lambda
│       └── s3
├── efs
│   ├── network
│   └── securitygroups
│       └── network
├── iam_role
└── waf

Below is the output of running terraspace all down --yes, including the error messages (I’ve omitted the output of batch 3 onwards as they are very similar to the output of batch 1 and batch 2)

Running:
    terraspace down cloudfront     # batch 1
    terraspace down acm            # batch 2
    terraspace down asg            # batch 3
    terraspace down route53        # batch 3
    terraspace down loadbalancer   # batch 4
    terraspace down appstream      # batch 5
    terraspace down compute        # batch 5
    terraspace down efs            # batch 5
    terraspace down securitygroups # batch 6
    terraspace down lambda         # batch 6
    terraspace down iam_role       # batch 7
    terraspace down network        # batch 7
    terraspace down s3             # batch 7
    terraspace down waf            # batch 7
Batch Run 1:
Errno::ENOENT: No such file or directory - /tmp/SITSv3/.terraspace-cache/ap-southeast-2/dev/stacks/s3
Error evaluating ERB template around line 6 of: /tmp/SITSv3/app/stacks/cloudfront/tfvars/base.tfvars:
 1 
 2 
 3 
 4 
 5 
 6   bucket_testing_bucket_only_jalam = <%= output("s3.bucket_testing_bucket_only_jalam") %>
 7 
 8 
 9 
10 
11 

Original backtrace (last 8 lines):
/usr/lib/ruby/2.7.0/open3.rb:213:in `spawn'
/usr/lib/ruby/2.7.0/open3.rb:213:in `popen_run'
/usr/lib/ruby/2.7.0/open3.rb:101:in `popen3'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/shell.rb:36:in `popen3'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/shell.rb:26:in `shell'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/shell.rb:17:in `run'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/terraform/runner.rb:51:in `block in terraform'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/hooks/builder.rb:25:in `run_hooks'

Re-run with FULL_BACKTRACE=1 to see all lines
Error running: terraspace down cloudfront. Fix the error above or check logs for the error.
Batch Run 2:
Errno::ENOENT: No such file or directory - /tmp/SITSv3/.terraspace-cache/ap-southeast-2/dev/stacks/route53
Error evaluating ERB template around line 6 of: /tmp/SITSv3/app/stacks/acm/tfvars/base.tfvars:
 1 
 2 
 3 
 4 
 5 
 6   zone_mydomain = <%= output("route53.zone_mydomain") %>
 7 
 8 
 9 
10 
11 

Original backtrace (last 8 lines):
/usr/lib/ruby/2.7.0/open3.rb:213:in `spawn'
/usr/lib/ruby/2.7.0/open3.rb:213:in `popen_run'
/usr/lib/ruby/2.7.0/open3.rb:101:in `popen3'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/shell.rb:36:in `popen3'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/shell.rb:26:in `shell'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/shell.rb:17:in `run'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/terraform/runner.rb:51:in `block in terraform'
/var/lib/gems/2.7.0/gems/terraspace-1.1.3/lib/terraspace/hooks/builder.rb:25:in `run_hooks'

Re-run with FULL_BACKTRACE=1 to see all lines
Error running: terraspace down acm. Fix the error above or check logs for the error.
....
....
....

From the dependency graph, we can see that the s3 stack is a dependency of the cloudfront stack (executed at batch 1). But looking at the message for batch run 1, it says: Errno::ENOENT: No such file or directory - /tmp/SITSv3/.terraspace-cache/ap-southeast-2/dev/stacks/s3, which leads me to think that the directory isn’t there because it isn’t built when terraspace all down --yes is run (the cache folder is not build/present before running terraspace all down).

FYI, I also have the following set in config/app.rb (if it makes any difference)

Terraspace.configure do |config|
  config.logger.level = :info
  config.test_framework = "rspec"
  config.all.exit_on_fail.down = false
  config.all.exit_on_fail.up = false
end

Many thanks,
James

Hi again,

Sorry, it turns out that the error messages about the (dependent) folders not being in the cache because I’ve accidentally commented out the terraspace all init line before doing terraspace all down --yes in my scipt.

I have now restored the terraspace all init line and it is no longer complaining about the file/folder not found. However, it is complaining about unsupported attribute now. E.g.

Running:
    terraspace down cloudfront     # batch 1
    terraspace down acm            # batch 2
    terraspace down asg            # batch 3
    terraspace down route53        # batch 3
    terraspace down loadbalancer   # batch 4
    terraspace down appstream      # batch 5
    terraspace down compute        # batch 5
    terraspace down efs            # batch 5
    terraspace down securitygroups # batch 6
    terraspace down lambda         # batch 6
    terraspace down iam_role       # batch 7
    terraspace down network        # batch 7
    terraspace down s3             # batch 7
    terraspace down waf            # batch 7
Batch Run 1:
Running: terraspace down cloudfront Logs: log/down/cloudfront.log
terraspace down cloudfront:  Error: WAFv2 WebACL not found for name: my-waf
Error running: terraspace down cloudfront. Fix the error above or check logs for the error.
Batch Run 2:
Running: terraspace down acm Logs: log/down/acm.log
terraspace down acm:  Error: Unsupported attribute
terraspace down acm:  Error: Unsupported attribute
terraspace down acm:  Error: Unsupported attribute
terraspace down acm:  Error: Unsupported attribute
Error running: terraspace down acm. Fix the error above or check logs for the error.
Batch Run 3:
Running: terraspace down route53 Logs: log/down/route53.log
Running: terraspace down asg Logs: log/down/asg.log
terraspace down asg:  Error: Unsupported attribute
terraspace down asg:  Error: Unsupported attribute
terraspace down asg:  Error: Unsupported attribute
terraspace down asg:  Error: Unsupported attribute
terraspace down asg:  Error: Unsupported attribute
terraspace down asg:  Error: Unsupported attribute
terraspace down route53:  Changes to Outputs:
terraspace down route53:  Changes to Outputs:
terraspace down route53:  Destroy complete! Resources: 0 destroyed.
Error running: terraspace down asg. Fix the error above or check logs for the error.
Batch Run 4:
Running: terraspace down loadbalancer Logs: log/down/loadbalancer.log
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
terraspace down loadbalancer:  Error: Unsupported attribute
Error running: terraspace down loadbalancer. Fix the error above or check logs for the error.
Batch Run 5:
Running: terraspace down efs Logs: log/down/efs.log
Running: terraspace down appstream Logs: log/down/appstream.log
Running: terraspace down compute Logs: log/down/compute.log
terraspace down appstream:  Error: Unsupported attribute
terraspace down appstream:  Error: Unsupported attribute
terraspace down compute:  Error: Unsupported attribute
terraspace down compute:  Error: Unsupported attribute
terraspace down compute:  Error: Unsupported attribute
terraspace down compute:  Error: Unsupported attribute
terraspace down compute:  Error: Unsupported attribute
terraspace down compute:  Error: Unsupported attribute
terraspace down efs:  Error: Unsupported attribute
terraspace down efs:  Error: Unsupported attribute
Error running: terraspace down appstream. Fix the error above or check logs for the error.
Error running: terraspace down compute. Fix the error above or check logs for the error.
Error running: terraspace down efs. Fix the error above or check logs for the error.
Batch Run 6:
Running: terraspace down lambda Logs: log/down/lambda.log
Running: terraspace down securitygroups Logs: log/down/securitygroups.log
terraspace down lambda:  Error: Unsupported attribute
terraspace down lambda:  Error: Unsupported attribute
terraspace down securitygroups:  Error: Unsupported attribute
terraspace down securitygroups:  Error: Unsupported attribute
terraspace down securitygroups:  Error: Unsupported attribute
terraspace down securitygroups:  Error: Unsupported attribute
terraspace down securitygroups:  Error: Unsupported attribute
terraspace down securitygroups:  Error: Unsupported attribute
Error running: terraspace down lambda. Fix the error above or check logs for the error.
Error running: terraspace down securitygroups. Fix the error above or check logs for the error.
Batch Run 7:
Running: terraspace down iam_role Logs: log/down/iam_role.log
Running: terraspace down waf Logs: log/down/waf.log
Running: terraspace down network Logs: log/down/network.log
Running: terraspace down s3 Logs: log/down/s3.log
terraspace down iam_role:  Changes to Outputs:
terraspace down iam_role:  Changes to Outputs:
terraspace down iam_role:  Destroy complete! Resources: 0 destroyed.
terraspace down network:  Changes to Outputs:
terraspace down network:  Changes to Outputs:
terraspace down network:  Error: error deleting EC2 Subnet (subnet-xxxxxxxxxx): DependencyViolation: The subnet 'subnet-xxxxxxxxxx' has dependencies and cannot be deleted.
terraspace down network:  Error: error deleting EC2 Subnet (subnet-xxxxxxxxxx): DependencyViolation: The subnet 'subnet-xxxxxxxxxx' has dependencies and cannot be deleted.
terraspace down network:  Error: error detaching EC2 Internet Gateway (igw-xxxxxxxxxx) from VPC (vpc-xxxxxxxxxx): DependencyViolation: Network vpc-xxxxxxxxxx has some mapped public address(es). Please unmap those public address(es) before detaching the gateway.
terraspace down network:  Error: error deleting EC2 Subnet (subnet-xxxxxxxxxx): DependencyViolation: The subnet 'subnet-xxxxxxxxxx' has dependencies and cannot be deleted.
terraspace down network:  Error: error deleting EC2 Subnet (subnet-xxxxxxxxxx): DependencyViolation: The subnet 'subnet-xxxxxxxxxx' has dependencies and cannot be deleted.
terraspace down network:  Error: error deleting EC2 Subnet (subnet-xxxxxxxxxx): DependencyViolation: The subnet 'subnet-xxxxxxxxxx' has dependencies and cannot be deleted.
terraspace down network:  Error: error deleting EC2 Subnet (subnet-xxxxxxxxxx): DependencyViolation: The subnet 'subnet-xxxxxxxxxx' has dependencies and cannot be deleted.
terraspace down s3:  Changes to Outputs:
terraspace down s3:  Changes to Outputs:
terraspace down s3:  Destroy complete! Resources: 0 destroyed.
terraspace down waf:  Error: error waiting for CloudFormation Stack deletion: failed to delete CloudFormation stack (DELETE_FAILED): ["The following resource(s) failed to delete: [WebACLStack]. " "Embedded stack arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxx:stack/WebACLStack/xxxxxxxxxx was not successfully deleted: The following resource(s) failed to delete: [WAFReputationListsSetV6, WAFWhitelistSetV6, WAFReputationListsSetV4, WAFWebACL, WAFScannersProbesSetV6, WAFWhitelistSetV4, WAFScannersProbesSetV4, WAFBadBotSetV4, WAFBlacklistSetV4, WAFBlacklistSetV6, WAFBadBotSetV6]. "]
Error running: terraspace down network. Fix the error above or check logs for the error.
Error running: terraspace down waf. Fix the error above or check logs for the error.
Time took: 25m 29s
##[section]Finishing: Terraspace : down

I’ve previously seen this “Unsupported attribute” error previously, mainly when the helper output file isn’t able to correctly resolve the value from the remote state file of the dependent stacks. E.g. Saying that the stack isn’t deployed/built (although it might actually be deployed/built). So, could it be that it is complaining about unsupported attribute because the helper output file doesn’t correctly resolve the values from the remote state file of the dependent stacks (especially when my project, in particular, has many nested dependencies)?

Or… it could’ve messed up the dependencies because of the previous failed attempts at terraspace all down (which might’ve destroyed some dependencies)…

I’ll try doing a terraspace all up and then another terraspace all down

Many thanks,
James

OK,

Another update… Done a terraspace all up to restore the resources/state, and did another terraspace all down, and it’s destroyed all resources as expected :slight_smile:

So, in summary, there wasn’t a problem to begin with… It was just me being silly by commenting out the terraspace all init command, and panicking for nothing :crazy_face:

Cheers,
James

Hello again,

I am encountering another challenge which is related to doing terraspace all down, and thought I’d revive the thread (instead of opening a new one) as it is somewhat related to how terraspace all down deals with nested stacks.

So, as with the above example with multiple stacks and batch runs… If I now set
(so that it doesn’t proceed to delete the next stack sets)

Terraspace.configure do |config|
  config.all.exit_on_fail.down = true
end

If let’s say it successfully do terraspace down for batch 1, 2 and 3, but failed at batch 4. When I try to re-run terraspace all down, it would now fail at batch 1, and I think I do understand why it’s doing that (because the dependent stacks e.g. stacks in batch 2 and batch 3 no longer exists - so the command will fail at batch 1 due to the unsupported attribute error because it can no longer resolve the tfvars). e.g.

Building graph...
.
├── appstream
│   ├── network
│   ├── s3
│   └── securitygroups
│       └── network
├── asg
│   ├── compute
│   │   ├── network
│   │   ├── s3
│   │   └── securitygroups
│   │       └── network
│   ├── securitygroups
│   │   └── network
│   ├── network
│   └── loadbalancer
│       ├── network
│       ├── s3
│       ├── compute
│       │   ├── network
│       │   ├── s3
│       │   └── securitygroups
│       │       └── network
│       └── securitygroups
│           └── network
├── cloudfront
│   ├── s3
│   ├── loadbalancer
│   │   ├── network
│   │   ├── s3
│   │   ├── compute
│   │   │   ├── network
│   │   │   ├── s3
│   │   │   └── securitygroups
│   │   │       └── network
│   │   └── securitygroups
│   │       └── network
│   ├── acm
│   │   └── route53
│   │       ├── network
│   │       ├── compute
│   │       │   ├── network
│   │       │   ├── s3
│   │       │   └── securitygroups
│   │       │       └── network
│   │       └── loadbalancer
│   │           ├── network
│   │           ├── s3
│   │           ├── compute
│   │           │   ├── network
│   │           │   ├── s3
│   │           │   └── securitygroups
│   │           │       └── network
│   │           └── securitygroups
│   │               └── network
│   └── lambda
│       └── s3
├── efs
│   ├── network
│   └── securitygroups
│       └── network
├── iam_role
└── waf


Running:
    terraspace down cloudfront     # batch 1
    terraspace down acm            # batch 2
    terraspace down asg            # batch 3
    terraspace down route53        # batch 3
    terraspace down loadbalancer   # batch 4
    terraspace down appstream      # batch 5
    terraspace down compute        # batch 5
    terraspace down efs            # batch 5
    terraspace down securitygroups # batch 6
    terraspace down lambda         # batch 6
    terraspace down iam_role       # batch 7
    terraspace down network        # batch 7
    terraspace down s3             # batch 7
    terraspace down waf            # batch 7
Batch Run 1:
Running: terraspace down cloudfront Logs: log/down/cloudfront.log
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
terraspace down cloudfront:  Error: Unsupported attribute
Error running: terraspace down cloudfront. Fix the error above or check logs for the error.
##[error]Bash exited with code '2'.
##[section]Finishing: Terraspace : down

I am wondering what would be best way to deal with re-running a terraspace all down which has a failure mid-process?

Many thanks,
James

Thanks for report. This was a bug introduced in 1.1.0. Fixed. Details:

Also, added a codebuild project for terraspace all and improve acceptance testing. Details: https://github.com/boltops-tools/terraspace/pull/216

1 Like

Thanks Tung,

I think 1.1.7 fixed the issue with the building of the stacks in the cache folder.

But, I think the challenge with “continuing” terraspace all down from the last successful batch is still there… As in, as long as terraspace all down finish destroying batch 2, but fails without destroying all of the batches, when you re-run terraspace all down, it would fail at the batch 1… This is because batch 1 is dependent on the output from batch 2 (but batch 2 would’ve been destroyed, and therefore the tfvars in batch 1 cannot be evaluated properly - and will error with and unsupported attribute message).

I might be under-thinking this, but I wonder if… during a terraspace destroy all, when the state (in the dependent stack) does not contain the output required by the current stack, then the destroy of the current stack gets ignored (and move onto the next stack/batch) :thinking:? E.g. using the above example where terraspace all destroy has 7 batches in total, and failed at batch 4 (i.e. completed batch 1, batch 2 and batch 3), then the next time it gets re-run, it would

  • skip batch 1 (because batch 2’s state will not contain the output needed for batch 1 - because batch 2 is destroyed)
  • skip batch 2 (because batch 3’s state will not contain the output needed for batch 2 - because batch 3 is destroyed)
  • retry batch 3 (because batch 4’s state will still contain the output needed for batch 3 - because batch 4 has not been destroyed) - but there might be nothing left to destroy because batch 3 has been destroyed successfully in previous run
  • proceed destroying batch 4 and onwards

Many thanks,
James

I see. One possible approach is to save the state of where terraspace all down failed, IE: The batch number. Then continue from there with that info. Will consider PRs. Thanks.

1 Like

Hi Tung,

Just had a thought/feedback about your suggestion of saving the state of terraspace all down, and selfishly/specifically for our use case, where we always run the pipeline/process on a fresh instance (and the instance terminated after the run), the state would be lost unless we can store the state in a persistent location. e.g. commiting back to the repo or store it in Azure Artifacts (and this is may not necessarily be something we’d like to do if we can avoid it)

Many thanks,
James

Would save state remotely to available backend like AWS s3, Azure Storage Account, GCS bucket, etc.

Maybe it’s avoidable. Unsure about assuming to skip based on unavailable outputs. Maybe :face_with_monocle: Will consider and review experimental PR. Note: Unsure on approach though and whether or not would take it. :ok_hand: It’ll probably help provide clarity though

1 Like

Hi Tung,

Actually, that’s good point. :+1:

I’ve only considered the storage on the machine running the process, but not backends like s3 buckets (or equivalent), or dynamodb (or equivalent). Also agree that this would likely be a better approach to the making assumptions about the outputs being unavailable (as it takes the guess work away) :slightly_smiling_face:

Many thanks,
James

Hi Tung,

Me again… Another thought… Let’s say we’re storing the state externally somewhere… How would terraspace know if doing another terraform all destroy is a retry of a previous failed terraform all destroy? For example, when I have encounter a failure midway a terraform all destroy at the moment, I either do another terraform all up, or redeploy the destroyed stacks - then have another go a terraform all destroy… If it only relies on the saved state and resume only from the last unsuccessful batch (e.g. batch 4), then the re-deployed batches (batch 1, 2 and 3) would not get evaluated/destroyed (and subsequent batches would possibly fail due to resources from batch 1, 2, 3 being present due to the re-deploy)?

Perhaps… recording something like a previous_operation value might also be useful in the state - so that it can be used in the evaluation… E.g. something like

if previous_operation=terraspace all destroy and status=error_midway; then
  if current_operation==previous_operation; then
     do terraspace all destroy from last_successful_batch+1
  fi
fi

Just throwing ideas out, in case it might be useful to consider (or not…) :slight_smile:

Many thanks,
James