diff --git a/website/data/language-nav-data.json b/website/data/language-nav-data.json index 35f869ea92..22f3999d28 100644 --- a/website/data/language-nav-data.json +++ b/website/data/language-nav-data.json @@ -94,6 +94,10 @@ "path": "resources/provisioners/remote-exec" } ] + }, + { + "title": "The terraform_data Resource Type", + "path": "resources/terraform-data" } ] }, diff --git a/website/docs/language/meta-arguments/lifecycle.mdx b/website/docs/language/meta-arguments/lifecycle.mdx index cd38ffeb09..300654528e 100644 --- a/website/docs/language/meta-arguments/lifecycle.mdx +++ b/website/docs/language/meta-arguments/lifecycle.mdx @@ -144,6 +144,8 @@ The arguments available within a `lifecycle` block are `create_before_destroy`, } ``` + `replace_triggered_by` allows only resource addresses because the decision is based on the planned actions for all of the given resources. Plain values such as local values or input variables do not have planned actions of their own, but you can treat them with a resource-like lifecycle by using them with [the `terraform_data` resource type](/language/resources/terraform-data). + ## Custom Condition Checks You can add `precondition` and `postcondition` blocks with a `lifecycle` block to specify assumptions and guarantees about how resources and data sources operate. The following examples creates a precondition that checks whether the AMI is properly configured. diff --git a/website/docs/language/resources/provisioners/local-exec.mdx b/website/docs/language/resources/provisioners/local-exec.mdx index 952c131aa4..83241ffa43 100644 --- a/website/docs/language/resources/provisioners/local-exec.mdx +++ b/website/docs/language/resources/provisioners/local-exec.mdx @@ -67,7 +67,7 @@ The following arguments are supported: ### Interpreter Examples ```hcl -resource "null_resource" "example1" { +resource "terraform_data" "example1" { provisioner "local-exec" { command = "open WFH, '>completed.txt' and print WFH scalar localtime" interpreter = ["perl", "-e"] @@ -76,7 +76,7 @@ resource "null_resource" "example1" { ``` ```hcl -resource "null_resource" "example2" { +resource "terraform_data" "example2" { provisioner "local-exec" { command = "Get-Date > completed.txt" interpreter = ["PowerShell", "-Command"] diff --git a/website/docs/language/resources/provisioners/null_resource.mdx b/website/docs/language/resources/provisioners/null_resource.mdx index fc270e364c..8722938bec 100644 --- a/website/docs/language/resources/provisioners/null_resource.mdx +++ b/website/docs/language/resources/provisioners/null_resource.mdx @@ -1,23 +1,22 @@ --- page_title: Provisioners Without a Resource description: >- - A null_resource allows you to configure provisioners that are not directly - associated with a single existing resource. + A terraform_data managed resource allows you to configure provisioners that + are not directly associated with a single existing resource. --- # Provisioners Without a Resource -[null]: https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource - If you need to run provisioners that aren't directly associated with a specific resource, you can associate them with a `null_resource`. -Instances of [`null_resource`][null] are treated like normal resources, but they -don't do anything. Like with any other resource, you can configure -[provisioners](/language/resources/provisioners/syntax) and [connection -details](/language/resources/provisioners/connection) on a `null_resource`. You can also -use its `triggers` argument and any meta-arguments to control exactly where in -the dependency graph its provisioners will run. +Instances of [`terraform_data`](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](/language/resources/provisioners/syntax) +and [connection details](/language/resources/provisioners/connection) on a +`terraform_data` resource. You can also use its `triggers` 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](/language/resources/provisioners/syntax) for more details. @@ -31,16 +30,14 @@ resource "aws_instance" "cluster" { # ... } -resource "null_resource" "cluster" { - # Changes to any instance of the cluster requires re-provisioning - triggers = { - cluster_instance_ids = "${join(",", aws_instance.cluster.*.id)}" - } +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 = "${element(aws_instance.cluster.*.public_ip, 0)}" + host = aws_instance.cluster.[0].public_ip } provisioner "remote-exec" { @@ -51,12 +48,3 @@ resource "null_resource" "cluster" { } } ``` - -## Argument Reference - -In addition to meta-arguments supported by all resources, `null_resource` -supports the following specific arguments: - -- `triggers` - A map of values which should cause this set of provisioners to - re-run. Values are meant to be interpolated references to variables or - attributes of other resources. diff --git a/website/docs/language/resources/terraform-data.mdx b/website/docs/language/resources/terraform-data.mdx new file mode 100644 index 0000000000..4e03d3d80b --- /dev/null +++ b/website/docs/language/resources/terraform-data.mdx @@ -0,0 +1,82 @@ +--- +page_title: The terraform_data Managed Resource Type +description: >- + Retrieves the root module output values from a Terraform state snapshot stored + in a remote backend. +--- + +# The `terraform_data` Managed Resource Type + +The `terraform_data` implements the standard resource lifecycle, but does not directly take any other actions. +You can use the `terraform_data` resource without requiring or configuring a provider. It is always available through a built-in provider with the [source address](/language/providers/requirements#source-addresses) `terraform.io/builtin/terraform`. + +The `terraform_data` resource is useful for storing values which need to follow a manage resource lifecycle, and for triggering provisioners when there is no other logical managed resource in which to place them. + + +## Example Usage (data for `replace_triggered_by`) + + +[The `replace_triggered_by` lifecycle argument](/language/meta-arguments/lifecycle#replace_triggered_by) requires all of the given addresses to be for resources, because the decision to force replacement is based on the planned actions for all of the mentioned resources. + +Plain data values such as [Local Values](/language/values/locals) and [Input Variables](/language/values/variables) don't have any side-effects to plan against and so they aren't valid in `replace_triggered_by`. You can use `terraform_data`'s behavior of planning an action each time `input` changes to _indirectly_ use a plain value to trigger replacement. + + +```hcl +variable "revision" { + default = 1 +} + +resource "terraform_data" "replacement" { + input = var.revision +} + +# This resource has no convenient attribute which forces replacement, +# but can now be replaced by any change to the revision variable value. +resource "example_database" "test" { + lifecycle { + replace_triggered_by = [terraform_data.replacement] + } +} +``` + +## Example Usage (`null_resource` replacement) + +```hcl +resource "aws_instance" "web" { + # ... +} + +resource "aws_instance" "database" { + # ... +} + +# A use-case for terraform_data is as a do-nothing container +# for arbitrary actions taken by a provisioner. +resource "terraform_data" "bootstrap" { + triggers_replace = [ + aws_instance.web.id, + aws_instance.database.id + ] + + provisioner "local-exec" { + command = "bootstrap-hosts.sh" + } +} +``` + + +## Argument Reference + +The following arguments are supported: + +* `input` - (Optional) A value which will be stored in the instance state, and reflected in the `output` attribute after apply. + +* `triggers_replace` - (Optional) A value which is stored in the instance state, and will force replacement when the value changes. + +## Attributes Reference + +In addition to the above, the following attributes are exported: + +* `id` - A string value unique to the resource instance. + +* `output` - The computed value derived from the `input` argument. During a plan where `output` is unknown, it will still be of the same type as `input`. diff --git a/website/layouts/language.erb b/website/layouts/language.erb index 0d5c25e8c4..56e5884f4e 100644 --- a/website/layouts/language.erb +++ b/website/layouts/language.erb @@ -142,6 +142,10 @@ +
  • + Terraform Data Resource Type +
  • +