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.6k stars 9.54k forks source link

destroy provisioner not firing #24691

Closed simonB2020 closed 4 years ago

simonB2020 commented 4 years ago

I am trying to create Athena View via Terraform. The code below does create a view, but when destroyed, the destroy provisioner does not trigger.

resource "null_resource" "view116" {
        provisioner "local-exec" {
        command = <<-EOF
    aws athena start-query-execution --query-string file://${var.sql_files_dir}/query16.sql --output json --query-execution-context Database=${aws_athena_database.metadb.id} --result-configuration OutputLocation=s3://${module.meta_target_bucket.id}
        EOF
      }

      provisioner "local-exec" {
        when    = destroy
        command = <<EOF
aws athena start-query-execution --query-string file://${var.sql_drop_dir}/query16.sql --output json --query-execution-context Database=${aws_athena_database.metadb.id} --result-configuration OutputLocation=s3://${module.meta_target_bucket.id}
         EOF
      }
    }

In the above, the content of ${var.sql_files_dir}/query16.sql is a SQL 'create view' statement; and the content of ${var.sql_drop_dir}/query16.sql is a 'drop view' statement.

True enough, my view was created as a TF resource, and an Athena View object.

However, if I now remove the script for the resource, the output is thus :

Enter a value: yes

null_resource.view117: Destroying... [id=8539720183852187034] null_resource.view117: Destruction complete after 0s

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.

.. whilst the TF resource is destroyed, the Command Line in my destroy provisioner is not executed. The Athena database still contains the physical View 'query16'.

danieldreier commented 4 years ago

Hi @simonB2020!

If I'm reading your code correctly, this is code that will stop working in terraform 0.13 when external references from destroy provisioners are removed. As described there:

Destroy-time provisioners and their connection configurations may only
reference attributes of the related resource, via 'self', 'count.index', or
'each.key'.

References to other resources during the destroy phase can cause dependency
cycles and interact poorly with create_before_destroy.

If I'm understanding correctly, it sounds to me like you are using provisioners and destroy provisioners to work around the AWS provisioner not supporting Athena views. If I'm understanding this correctly, I think your best path forward is to file a feature request for supporting Athena views in the AWS provider, and then if you feel able, you could add that functionality in a PR.

simonB2020 commented 4 years ago

Daniel, Unfortunately AWS themselves do not provide a CLI command for this, so doubt TF will be able to do much about that - if I understand how TF interacts with AWS correctly ?

Is there a way to re-write my code to execute successfully ?

danieldreier commented 4 years ago

I think the Terraform AWS provider interacts with AWS via the AWS API. According to this blog post. It looks to me like the golang AWS SDK has a bunch of Athena-related operations. I don't know whether this fits into the Terraform AWS Provider's roadmap or whether they'd accept a PR to do what you need, but to my cursory assessment it looks like AWS does provide an API and SDK for doing these operations programatically.

If you're willing to write some golang, you could either try and contribute a resource to the official Terraform AWS provider, or write a very small custom provider for your own use here. You'd need to wrap the AWS SDK.

Provisioners, and destroy provisioners, are really intended as a way to start the next stage of the provisioning process on a VM that was just created, like starting Puppet or Chef on a VM that you just provisioned. It's common enough that people try to model resources with them, like you're doing, but it's not a very robust pattern and so I don't encourage it.

danieldreier commented 4 years ago

@simonB2020 James explained to me that what's happening here is that when you remove / comment out the code for the resource, the destroy provisioner no longer exists in the config, and so doesn't get called on destroy. If you want this to work, you'll need to leave the config in there. You could create those resources conditionally, like setting count = 0 to remove it, but you have to leave the config in or else the destroy provisioner won't run.

Destroy provisioners work differently from resources in that way, and it's an expected behavior. I think that explains the issue, so I'm going to resolve this. If that doesn't sound correct to you, feel free to say something and we can re-open and dig in further.

ghost commented 4 years ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.