| --- |
| page_title: Provisioners Without a Resource |
| description: >- |
| A terraform_data managed resource allows you to configure provisioners that |
| are not directly associated with a single existing resource. |
| --- |
| |
| # Provisioners Without a Resource |
| |
| If you need to run provisioners that aren't directly associated with a specific |
| resource, you can associate them with a `terraform_data`. |
| |
| Instances of [`terraform_data`](/terraform/language/resources/terraform-data) are treated |
| like normal resources, but they don't do anything. Like with any other resource |
| type, you can configure [provisioners](/terraform/language/resources/provisioners/syntax) |
| and [connection details](/terraform/language/resources/provisioners/connection) on a |
| `terraform_data` resource. You can also use its `input` argument, `triggers_replace` argument, and any |
| meta-arguments to control exactly where in the dependency graph its |
| provisioners will run. |
| |
| ~> **Important:** Use provisioners as a last resort. There are better alternatives for most situations. Refer to |
| [Declaring Provisioners](/terraform/language/resources/provisioners/syntax) for more details. |
| |
| ## Example usage |
| |
| ```hcl |
| resource "aws_instance" "cluster" { |
| count = 3 |
| |
| # ... |
| } |
| |
| resource "terraform_data" "cluster" { |
| # Replacement of any instance of the cluster requires re-provisioning |
| triggers_replace = aws_instance.cluster.[*].id |
| |
| # Bootstrap script can run on any instance of the cluster |
| # So we just choose the first in this case |
| connection { |
| host = aws_instance.cluster.[0].public_ip |
| } |
| |
| provisioner "remote-exec" { |
| # Bootstrap script called with private_ip of each node in the cluster |
| inline = [ |
| "bootstrap-cluster.sh ${join(" ", aws_instance.cluster.*.private_ip)}", |
| ] |
| } |
| } |
| ``` |