Terraform
resource block reference
The resource block defines a piece of infrastructure and specifies the settings for Terraform to create it with. The arguments that an individual resource supports are determined by the provider. Refer to the provider documentation for more information about specific resource configuration.
Configuration model
The resource block supports the following arguments:
- resource "<TYPE>" "<LABEL>"block- PROVIDER ARGUMENTSblock | refer to your provider documentation
- countnumber | mutually exclusive with- for_each
- depends_onlist of references
- for_eachmap or set of strings | mutually exclusive with- count
- providerreference
- lifecycleblock- action_triggerblock
- create_before_destroyboolean
- prevent_destroyboolean
- ignore_changeslist of attributes
- replace_triggered_bylist of references
- preconditionblock- conditionstring
- error_messagestring
 
- postconditionblock- conditionstring
- error_messagestring
 
 
- connectionblock- typestring
- userstring
- passwordstring
- hoststring
- portstring
- timeoutstring
- script_pathstring
- private_keystring
- certificatestring
- agentstring
- agent_identitystring
- host_keystring
- target_platformstring
- script_pathstring
- httpsstring
- insecurestring
- use_ntlmstring
- cacertstring
- bastion_hoststring
- bastion_host_keystring
- bastion_portstring
- bastion_userstring
- bastion_passwordstring
- bastion_private_keystring
- bastion_certificatestring
- proxy_schemestring
- proxy_portstring
- proxy_user_namestring
- proxy_user_passwordstring
 
- provisioner "<TYPE>"block- sourcestring
- destinationstring
- contentstring
- commandstring
- working_dirstring
- interpreterstring
- environmentstring
- whenkeyword
- quietboolean
- inlinelist of strings
- scriptstring
- scriptsstring
- on_failurekeyword
- connectionblock
 
 
Complete configuration
The following resource block defines all of the supported built-in arguments you can set on a resource:
resource "<TYPE>" "<LABEL>" {
  <PROVIDER_ARGUMENTS>
  count = <NUMBER>      # `for_each` and `count` are mutually exclusive
  depends_on = [ <RESOURCE.ADDRESS.EXPRESSION> ]
  for_each = {          # `for_each` and `count` are mutually exclusive
    <KEY> = <VALUE>
  }
  for_each = [       # `for_each` accepts a map or a set of strings
    "<VALUE>",
    "<VALUE>"
  ]
  provider = <REFERENCE.TO.ALIAS>
  lifecycle {
    action_trigger {
      events = [        # specify one or more lifecycle events as a list 
        before_create, 
        after_create,
        before_update,
        after_update
      ]
      condition = <EXPRESSSION>
      actions = [ action.<TYPE>.<LABEL> ]
    }
    create_before_destroy = <true || false>
    prevent_destroy = <true || false>
    ignore_changes = [ <ATTRIBUTE> ]
    replace_triggered_by = [ <RESOURCE.ADDRESS.EXPRESSION> ]
    precondition {
      condition = <EXPRESSION>
      error_message = "<STRING>"
    }
    postcondition {
      condition = <EXPRESSION>
      error_message = "<STRING>"
    }
  }
  connection {
    type = <"ssh" or "winrm">
    host = <EXPRESSION>
    <DEFAULT_CONNECTION_SETTINGS>
  }
  provisioner "<TYPE>" {
    source = "<PATH>"
    destination = "<PATH>"
    content = "<CONTENT TO COPY TO `destination`>"
    command = <COMMAND>
    working_dir = "<PATH TO DIR WHERE TERRAFORM EXECUTES `command`>"
    interpreter = [
      "<PATH TO INTERPRETER EXECUTABLE>",
      "<COMMAND> <ARGUMENTS>"
    ]
    environment {
      "<KEY>" = "<VALUE>"
    }
    when = <TERRAFORM COMMAND>
    quiet = <true || false>
    inline = [ "<COMMAND>" ]
    script = "<PATH>"
    scripts = [
      "<PATH>"
    ]
    on_failure = <continue || fail>
    connection {
      type = <"ssh" or "winrm">
      host = <EXPRESSION>
      <SPECIFIC_CONNECTION_SETTINGS>
    }
  }
}
Specification
A resource block supports the following configuration.
resource "<TYPE>" "<LABEL>"
You must set the following arguments for every resource block:
- TYPE: Specifies the type of resource to create. You can declare either a resource type determined by the provider or the built-in- terraform_dataresource type, which stores values and triggers Terraform operations without creating actual infrastructure. For information about provider resource types, refer to the provider documentation.
- LABEL: Specifies a name for the resource. Terraform uses this label to track the resource in your state file. The label does not affect settings on the actual infrastructure resource. Refer to References to Named Values and Resource naming for expression syntax and label recommendations.
To reference the resource in your configuration, you must refer to it using <TYPE>.<LABEL> syntax.
PROVIDER ARGUMENTS
The provider developer determines which arguments you can define for a resource. Refer to the provider documentation for details.
count
The count meta-argument instructs Terraform to provision multiple instances of the same resource with identical or similar configuration. You cannot use both a count and  for_each argument in the same block.
resource {
  count = <number>
}
count is a meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the count reference for details about how the argument works.
depends_on
The depends_on meta-argument specifies an upstream resource that the resource depends on. Terraform must complete all operations on the upstream resource before performing operations on the resource containing the depends_on argument.
resource {
  depends_on = [ <resource reference> ]
}
depends_on is a meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the depends_on reference for details about how the argument works.
for_each
The for_each meta-argument instructs Terraform to provision similar resources without requiring separate configuration blocks for each resource.
resource {
  for_each = [ "<VALUE>" ]
  # . . .
}
for_each is a meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the for_each reference for details about how the argument works.
provider
The provider argument instructs Terraform to use an alternate provider configuration to provision the resource.
resource {
  provider = <provider>.<alias>
}
provider is a meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the provider reference for details about how the argument works.
lifecycle
The lifecycle block defines lifecycle rules that instruct Terraform when and how to operate on your resource.
resource {
  lifecycle {
    <lifecycle>
  }
}
You can specify the following lifecycle rules to manage how Terraform performs operations on the resource:
- action_trigger: Specifies a set of arguments that determine which events trigger one or more provider actions, under which conditions the action runs, and which actions Terraform invokes.
- create_before_destroy: Terraform creates a replacement resource before destroying the current resource.
- prevent_destroy: Terraform rejects operations to destroy the resource and returns an error. This rule doesn't prevent Terraform from destroying the resource if you remove the resource configuration. For instructions on how to remove a resource from state without destroying the actual resource, refer to Remove a resource from state.
- ignore_changes: Specifies a list of resource attributes that Terraform ignores changes to. Otherwise, Terraform attempts to update the actual resource to match the configuration.
- replace_triggered_by: Terraform replaces the resource when any of the referenced resources or specified attributes change.
- precondition: Specifies a condition that Terraform evaluates before creating the resource. Refer to Validate your configuration for more information.
- postcondition: Specifies a condition that Terraform evaluates after creating the resource. Refer to Validate your configuration for more information.
Configurations defined in the lifecycle block affect how Terraform constructs and traverses the dependency graph. You can only use literal values in the lifecycle block because Terraform processes them before it evaluates arbitrary expressions for a run.
lifecycle is a meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
Summary
- Data type: Block.
- Default: None
action_trigger
The action_trigger block specifies a set of arguments that determine which events trigger one or more provider actions, under which conditions the action runs, and which actions Terraform invokes.
resource "<TYPE>" "<LABEL>" {
  lifecycle {
    action_trigger {
      events     = [ <EVENT> ]
      conditions = < true || false >
      actions    = [ action.<TYPE>.<LABEL> ]
    }
  }
}
action_trigger is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
create_before_destroy
The create_before_destroy argument instructs Terraform to create a replacement resource before destroying the resource it replaces.
resource {
  lifecycle {
    create_before_destroy = <boolean>
  }
}
create_before_destroy is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
prevent_destroy
The prevent_destroy argument instructs Terraform to reject plans to destroy the resource.
resource {
  lifecycle {
    prevent_destroy = <boolean>
  }
}
prevent_destroy is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
ignore_changes
The ignore_changes argument specifies a list of resource attributes for Terraform to ignore when planning updates to the resource.
resource {
  lifecycle {
    ignore_changes = [ <attribute> ]
  }
}
ignore_changes is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
replace_triggered_by
The replace_triggered_by argument instructs Terraform to replace the resource when any of the referenced items change.
resource {
  lifecycle {
    replace_triggered_by = [ <address.reference> ]
  }
}
replace_triggered_by is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
precondition
The precondition block specifies a condition that must return true before Terraform evaluates and performs operations on the resource. You can also specify an error message for Terraform to print when the condition returns false.
resource {
  lifecycle {
    precondition {
      condition = <expression>
      error_message = "<message>"
    }
  }
}
precondition is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
postcondition
The postcondition block specifies a condition that must return true after Terraform performs operations on the resource. You can also specify an error message for Terraform to print to the console when the condition returns false.
resource {
  lifecycle {
    postcondition {
      condition = <expression>
      error_message = "<message>"
    }
  }
}
postcondition is a directive available in the lifecycle meta-argument. Meta-arguments are built into the Terraform language and control how Terraform creates resources. Refer to the lifecycle reference for details about how the argument works.
connection
The connection block specifies settings that let provisioners connect to resources so that Terraform can perform operations on the resource after creating it.
Warning
We recommend using configuration management tools or other means to perform actions on the local or remote machine instead of using provisioners. Refer to Perform post-apply action for more information.
You can add the connection block to either the resource block or the provisioner block. When added to the resource block, the connection block sets default connection settings for all provisioners defined in the resource so that provisioners can connect to the remote resource after Terraform provisions it.
resource {
  # . . .
  connection {
    <settings for all provisioners in the resource>
  }
}
When added to a provisioner block, the connection block defines settings specific to the provisioner.
resource {
  # . . .
  provisioner {
    # . . .
    connection {
      <settings for all provisioners in the resource>
    }
  }
}
Terraform does not validate SSH host keys by default. You can establish a separate mechanism for key distribution and explicitly set the host_key argument to verify against a specific key or signing CA.
You can use ephemeral values for arguments in the connection block. Refer to Manage sensitive data for more information.
Expressions in connection blocks cannot refer to their parent resource by name. References create dependencies, and referring to a resource by name within its own block would create a dependency cycle. Instead, use the self object in expressions to refer to the connection block's parent block, including all of its attributes. For example, use self.public_ip to reference the public_ip attribute in an aws_instance.
Tip
You can provide multiple connections so that an initial provisioner can connect as the root user to set up user accounts and subsequent provisioners can connect as less-privileged users to perform more specific operations.
The following table describes the arguments you can use in the connection block:
| Argument | Description | Data type | Connection | Default | 
|---|---|---|---|---|
| type | Specifies the type of connection for sending and receiving data from the remote resource. You can specify sshorwinrm. When set towinrm, provisioners implement Windows-specific behaviors, even whentarget_platformis set tounix, unless otherwise specified. | string | ssh | |
| user | Specifies the user to use for the connection. | string | ssh
 | 
 
 | 
| password | Specifies the password to use for the connection. | string | ssh
 | none | 
| host | Specifies the address of the resource to connect to. This argument is required. | string | ssh
 | none | 
| port | Specifies the port number to connect to. | number | ssh
 | 
 
 | 
| timeout | Specifies how long to wait for the connection to become available. | string | ssh
 | "5m" | 
| script_path | Specifies the path on the remote resource where Terraform copies scripts to. Refer to the provisionerblock reference for more information. Terraform copies scripts to a path that contains random numbers depending on thetarget_platformconfiguration. | string | ssh
 | 
 
 | 
| private_key | Specifies the contents of an SSH key to use for the connection. private_keytakes precedence overpasswordwhen both are provided. | string Use a  | ssh | none | 
| certificate | Specifies the contents of a signed CA certificate. You must also configure a private_keyarugment. | string Use a  | ssh | none | 
| agent | Specifies an SSH agent for authentication. Set to falseto disable usingssh-agentto authenticate. On Windows, the only supported SSH authentication agent is Pageant. | string | ssh | false | 
| agent_identity | Specifies the preferred identity from the SSH agent to use for authentication. | string | ssh | none | 
| host_key | Specifies the public key from the remote host or the signing CA to verify the connection. | string | ssh | none | 
| target_platform | Specifies the target platform, which affects the default value for the script_pathargument. You can specify eitherwindowsorunix.
 
 | string | ssh | unix | 
| https | Set to trueto connect using HTTPS instead of HTTP. | boolean | winrm | false | 
| insecure | Set to trueto skip validating the HTTPS certificate chain. | boolean | winrm | false | 
| use_ntlm | Set to trueto use NTLM authentication instead of basic authentication. Using NTLM removes the requirement for basic authentication to be enabled within the target guest. Refer to Authentication for Remote Connections in the Windows App Development documentation for more details. | boolean | winrm | false | 
| cacert | Specifies the CA certificate to validate against. | string | winrm | none | 
| bastion_host | Specifies the address of the bastion host. The provisioner connects to bastion_hostbefore connecting tohost. | string | ssh | none | 
| bastion_host_key | Specifies the public key from the remote host or the signing CA to verify the host connection. | string | ssh | none | 
| bastion_port | Specifies the port number to use for the bastion host connection. | string | ssh | value of the portfield | 
| bastion_user | Specifies the user name for connecting to the bastion host. | string | ssh | value of the userfield | 
| bastion_password | Specifies the user password for connecting to the bastion host. | string | ssh | value of the passwordfield | 
| bastion_private_key | Specifies the contents of an SSH key file to use for the bastion host. | string Use a  | ssh | value of the private_keyfield | 
| bastion_certificate | Specifies the contents of a signed CA certificate. You must also configure the bastion_private_keyargument when providing the certificate for the bastion host. | string Use a  | ssh | value of the certificatefield | 
| proxy_scheme | Specifies the connection protocol. You can specify one of the following values: httphttpssocks5 | string | ssh | none | 
| proxy_host | Specifies the address of the proxy host. The provisioner connects to the proxy host first. When bastion_hostis configured, the provisioner connects to the bastion host next, otherwise the provisioner connects to the host specified in thehostargument. | string | ssh | none | 
| proxy_port | Specifies the port number to use for the proxy host connection. | number | ssh | none | 
| proxy_user_name | Specifies the user name for connecting to the proxy host. You should only configure this argument when the proxy server requires authentication. | string | ssh | none | 
| proxy_user_password | Specifies the user password for connecting to the proxy host. You should only configure this argument when the proxy server requires authentication. | string | ssh | none | 
Summary
- Data type: Block.
- Default: None.
- Example: Connect to remote resources
provisioner
The provisioner block defines actions to perform on the local machine or created resource, such as preparing servers or other infrastructure objects for service.
resource {
  provisioner "<TYPE>" {
    <arguments>
  }
}
Warning
We recommend using configuration management tools or other means to perform actions on the local or remote machine instead of using the provisioner block. Refer to Perform post-apply action for more information.
The provisioner block supports the following arguments:
- TYPE: Specifies the type of provisioner to use. You must specify one of the following types:- file: Copies files or directories from the machine where Terraform is running to the new resource. When the file provisioner communicates with a Windows system over SSH, you must configure OpenSSH to run the commands with- cmd.exeand not PowerShell. PowerShell causes file parsing errors because it is incompatible with both Unix shells and the Windows command interpreter.
- local-exec: Invokes an executable on the local machine after Terraform creates the resource.
- remote-exec: Invokes an executable on the remote resource after Terraform creates the resource.
 
- LABEL: Optional attribute for adding a unique name. Refer to Resource naming for label recommendations.
The type of provisioner determines which arguments you can add to the block. All types can use the connection argument. The following table lists each type's supported arguments:
| Provisioner type | Arguments | 
|---|---|
| file | sourcecontentdestination | 
| local-exec | commandworking_dirinterpreterenvironmentwhenquiet | 
| remote-exec | inlinescriptscripts | 
| All types | connectionon_failure | 
Summary
- Data type: Block.
- Default: None.
source
The source specifies the location of a file or directory to copy to the location specified in the destination argument.
resource {
  provisioner "file" {
    source = "<path>"
  }
}
You can specify a string value that contains an expression. You can't use the source argument and the content argument in the same provisioner "file" block.
When the source argument specifies a directory and the type argument in the provisioner connection settings is set to ssh, the corresponding directory specified in the destination argument must already exist. You can add a provisioner "remote-exec" block to your resource configuration to create the directory. If the directory does not already exist, Terraform creates it when the type argument in the provisioner connection settings is set to winrm.
Adding a trailing slash to the source argument path instructs Terraform to copy the contents of the directory to the destination directory. For example, when source = "/foo/" and destination = "/temp", Terraform uploads the contents of /foo directory into /tmp.
Without a trailing slash, Terraform creates the directory under the directory specified in the destination. For example, when source = "/foo" and destination = "/temp", Terraform uploads the /foo directory to /tmp/foo.
Summary
- Data type: String.
- Default: None.
- Example: Copy content to new resources.
content
The content argument specifies content to write directly to the location specified in the destination argument.
resource {
  provisioner "file" {
    content = "<content>"
  }
}
When destination points to a file, Terraform writes the value of the content argument to the file. When destination points to a directory, Terraform creates a file named tf-file-content inside the directory. We recommend setting the destination argument to a file when using content argument. Do not use the content argument and the source argument in the same provisioner "file" block.
You can specify a string value that contains an expression. You can't use the source argument and the content argument in the same provisioner "file" block.
Summary
- Data type: String.
- Default: None.
- Example: Copy content to new resources.
destination
The destination argument specifies a path on the remote resource that Terraform copies content to. You can use either source or content argument to provide content to the destination path.
resource {
  provisioner "file" {
    destination = "<path>"
  }
}
The remote system, not Terraform, evaluates the path you provide in the destination argument. As a result, valid values can vary depending on the operating system and remote access software running on the target.
When the type argument in the provisioner connection settings is set to ssh, the provisioner passes the destination path as-is to the scp program on the remote host. By default, the OpenSSH scp implementation runs in the remote user's home directory. As a result, you can specify a relative path to upload into the home directory or an absolute path to upload to a different location.
The remote scp process runs with the access level of the user specified in the provisioner connection settings, so permissions may prevent Terraform from writing directly to locations outside of the home directory.
When the type argument in the provisioner connection settings is set to winrm, Terraform uses PowerShell to interpret the destination path. As a result, you must not use meta-characters that PowerShell might interpret. You should specifically avoid including untrusted external input in your destination argument because doing so can let arbitrary PowerShell code execute on the remote system.
Terraform performs the following process over WinRM connections:
- Generates a temporary filename in the directory set in the remote system's TEMPenvironment variable.
- Generates a sequence of echocommands to gradually append base64-encoded chunks of the source file to the temporary file.
- Uses an uploaded PowerShell script to read the temporary file, base64-decode, and write the raw result into the destination file.
Modern Windows systems support running an OpenSSH server, so we strongly recommend choosing SSH over WinRM.
Summary
- Data type: String.
- Default: None.
- Example: Copy content to new resources.
command
The command argument specifies a command for a local executable to run. You can specify an absolute path or a relative path to the current working directory.
resource {
  provisioner "local-exec" {
    command = "<path>"
  }
}
Terraform evaluates the command in a local shell and can use environment variables for variable substitution. We do not recommend using Terraform variables for variable substitution because doing so can lead to shell injection vulnerabilities. Instead, use the environment parameter and environment variable substitution. Refer to the following OWASP article for more information about injection flaws: Code Injection.
Summary
- Data type: String.
- Default: None.
- This argument is required in the provisioner "local-exec"block.
- Example: Invoke executables.
working_dir
The working_dir block specifies the working directory where Terraform executes the command specified in the the command argument. You can specify a relative path to the current working directory or an absolute path. The directory must already exist.
resource {
  provisioner "local-exec" {
    working_dir = "<path>"
  }
}
Summary
- Data type: String.
- Default: None.
- Example: Invoke executables.
interpreter
The interpreter block specifies a list of interpreter arguments for running the executable specified in the command argument.
resource {
  provisioner "local-exec" {
    interpreter = [ "<path/to/interpreter>", "<command argument>" ]
  }
}
The first argument in the list is a path to the interpreter. You can specify a relative path to the current working directory or an absolute path. If you do not specify an interpreter, Terraform uses operating system defaults.
Summary
- Data type: List.
- Default: None.
- Example: Invoke executables.
environment
The environment block specifies a block of key value pairs that represent the environment for running the command specified in the command argument.
resource {
  provisioner "local-exec" {
    environment {
      <KEY> = <VALUE>
    }
  }
}
Summary
- Data type: Block.
- Default: None.
- Example: Invoke executables.
when
The when argument specifies a Terraform command that triggers actions specified in the provisioner.
resource {
  provisioner "local-exec" {
    when = <Terraform command>
  }
}
When you run the specified Terraform command, Terraform performs run the command specified in the command argument. Refer to Destroy-time provisioners for instructions on using the when argument.
Summary
- Data type: Terraform command.
- Default: None.
- Example: Invoke executables.
quiet
The quiet argument disables printing the command argument's output to stdout.
resource {
  provisioner "local-exec" {
    quiet = <boolean>
  }
}
When quiet is set to true, Terraform prints "Suppressed by quiet=true" to stdout. Terraform still prints the output of the command.
Summary
- Data type: Boolean.
- Default: None.
inline
Specifies a list of command strings to execute on the remote resource.
resource {
  # ...
  provisioner "remote-exec" {
    inline = [ "<command>" ]
  }
}
The provisioner uses the remote resource's default shell unless you specify a shell as the first command, for example #!/bin/bash. You cannot add an inline argument in the same provisioner with script or scripts.
Summary
- Data type: List.
- Default: None.
script
Specifies the relative or absolute path to a script on the local machine to copy and execute on the remote resource.
resource {
  # ...
  provisioner "remote-exec" {
    scripts = "<path-to-script>"
  }
}
You cannot add a script argument in the same provisioner with inline or scripts.
Summary
- Data type: String.
- Default: None.
scripts
Specifies a list of relative or absolute paths to script files on the local machine to copy and execute on the remote resource.
resource {
  # ...
  provisioner "remote-exec" {
    scripts = [ "<path-to-script>" ]
  }
}
You cannot add a scripts argument in the same provisioner with inline or script.
Summary
- Data type: List.
- Default: None.
Examples
The following examples show how to write configuration for common use cases.
Define an AWS instance
The following example defines an aws_instance resource named web.
resource "aws_instance" "web" {
  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
}
Create multiple instances of a resource
You can use either count or the for_each block to create multiple instances of a resource. The count argument is most suitable for creating multiple instances that are identical or nearly identical. The for_each argument is most suitable for creating multiple similar instances based on attributes defined in a map or set.
The following example creates one instance for each subnet provided in the input variable:
variable "subnet_ids" {
  type = list(string)
}
resource "aws_instance" "server" {
  count = length(var.subnet_ids)
  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
  subnet_id     = var.subnet_ids[count.index]
  tags = {
    Name = "Server ${count.index}"
  }
}
Specify a dependency
In the following example, the aws_iam_instance_profile resource references the aws_iam_role resource, instructing Terraform to create the upstream resource first. The aws_iam_role_policy resource configures an IAM policy that lets the EC2 instance access the S3 API.
Terraform infers that it must create the instance profile before the EC2 instance, but it cannot infer that the software running in the EC2 instance needs access to the S3 API in order to boot properly. As a result, the configuration explicitly instructs Terraform to create the aws_iam_role_policy first:
resource "aws_iam_role" "example" {
  name = "example"
  assume_role_policy = "..."
}
resource "aws_iam_instance_profile" "example" {
  role = aws_iam_role.example.name
}
resource "aws_iam_role_policy" "example" {
  name   = "example"
  role   = aws_iam_role.example.name
  policy = jsonencode({
    "Statement" = [{
      "Action" = "s3:*",
      "Effect" = "Allow",
    }],
  })
}
resource "aws_instance" "example" {
  ami           = "data.aws_ami.example.id"
  instance_type = "t2.micro"
  iam_instance_profile = aws_iam_instance_profile.example
  depends_on = [
    aws_iam_role_policy.example
  ]
}
data "aws_ami" "example" {
  # AMI configuration
}
Note that the aws_iam_role resource is partially defined. Refer to the AWS provider documentation for all configuration settings.
Select an alternate provider configuration
In the following example, the google_compute_instance resource selects the provider configuration with the europe alias.
provider "google" {
  region = "us-central1"
}
provider "google" {
  alias  = "europe"
  region = "europe-west1"
}
resource "google_compute_instance" "example" {
  provider = google.europe
  # ...
}
Ignore attribute changes
In the following example, Terraform ignores changes to the resource's tags:
resource "aws_instance" "example" {
   # ...
   lifecycle {
      ignore_changes = [tags]
   }
}
Specify triggers that replace resources
In the following example, Terraform replaces aws_appautoscaling_target each time this instance of aws_ecs_service is replaced:
resource "aws_appautoscaling_target" "ecs_target" {
   ...
   lifecycle {
   replace_triggered_by = [
      aws_ecs_service.svc.id
     ]
   }
}
Apply custom conditions
The following example includes several configurations that illustrate how to define precondition and postcondition arguments in the lifecycle meta-argument.
The following data block instructs Terraform to retrieve the ID of the ami-abc123 AMI:
data "aws_ami" "example" {
  owners = ["amazon"]
  filter {
    name   = "image-id"
    values = ["ami-abc123"]
  }
}
In the following code, the precondition block specifies that the AMI ID retrieved from the data block must include x86_64 as its architecture attribute. The postcondition block specifies that the EC2 instance must be allocated a public DNS hostname. When either condition is not met, Terraform returns the error_message for the failed condition:
resource "aws_instance" "example" {
  instance_type = "t3.micro"
  ami           = data.aws_ami.example.id
  lifecycle {
    precondition {
      condition     = data.aws_ami.example.architecture == "x86_64"
      error_message = "The selected AMI must be for the x86_64 architecture."
    }
    postcondition {
      condition     = self.public_dns != ""
      error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled."
    }
  }
}
The following data block retrieves the root storage volume connected to the aws_instance.example EC2 instance using the volume_id attribute. When a data resource verifies the result of a managed resource declared in the same configuration, you must define the check in a postcondition block in the resource so that Terraform waits for changes to the managed resource to complete before reading the data resource.
data "aws_ebs_volume" "example" {
  filter {
    name = "volume-id"
    values = [aws_instance.example.root_block_device[0].volume_id]
  }
  lifecycle {
    # The EC2 instance will have an encrypted root volume.
    postcondition {
      condition     = self.encrypted
      error_message = "The server's root volume is not encrypted."
    }
  }
}
output "api_base_url" {
  value = "https://${aws_instance.example.private_dns}:8433/"
}
Invoke an action
In the following example, Terraform invokes the action.ansible_playbook.provision action after Terraform creates the aws_instance.web resource:
resource "aws_instance" "web" {
  #...
  lifecycle {
    action_trigger {
      events    = [ after_create ]
      actions   = [action.ansible_playbook.provision]
    }
  }
}
action "ansible_playbook" "provision" {
  #...
}
Copy content to new resources
The following examples use the file provisioner type to copy artifacts from the machine where Terraform is running to the newly created resource.
resource "aws_instance" "web" {
  # ...
  # Copies the myapp.conf file to /etc/myapp.conf
  provisioner "file" {
    source      = "conf/myapp.conf"
    destination = "/etc/myapp.conf"
  }
  # Copies the string in content into /tmp/file.log
  provisioner "file" {
    content     = "ami used: ${self.ami}"
    destination = "/tmp/file.log"
  }
  # Copies the configs.d folder to /etc/configs.d
  provisioner "file" {
    source      = "conf/configs.d"
    destination = "/etc"
  }
  # Copies all files and folders in apps/app1 to D:/IIS/webapp1
  provisioner "file" {
    source      = "apps/app1/"
    destination = "D:/IIS/webapp1"
  }
}
Invoke executables
You can configure provisioners to perform remote operations, such as executing scripts or running commands.
In the following example, Terraform connects to the web instance using the connection settings so that the remote-exec provisioner can run the puppet apply and consul join commands on the resource:
resource "aws_instance" "web" {
  # ...
  connection {
    type     = "ssh"
    user     = "root"
    password = var.root_password
    host     = self.public_ip
  }
  provisioner "remote-exec" {
    inline = [
      "puppet apply",
      "consul join ${aws_instance.web.private_ip}",
    ]
  }
}
In the following example, Terraform uploads a script to the instance and provides inline commands to run the script:
resource "aws_instance" "web" {
  # ...
  provisioner "file" {
    source      = "script.sh"
    destination = "/tmp/script.sh"
  }
  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/script.sh",
      "/tmp/script.sh args",
    ]
  }
}
Connect to remote resources
The following example establishes a connection that all provisioners in the resource block can use to run commands on the remote resource:
resource "aws_instance" "web" {
  # ...
  connection {
    type     = "ssh"
    user     = "root"
    password = var.root_password
    host     = self.public_ip
  }
  provisioner "remote-exec" {
    inline = [
      "puppet apply",
      "consul join ${aws_instance.web.private_ip}",
    ]
  }
}
Define provisioner failure behaviors
In the following example, Terraform runs the echo command on the local machine after creating the web resource. Terraform continues with the operation if the command fails:
resource "aws_instance" "web" {
  # ...
  provisioner "local-exec" {
    command    = "echo The server's IP address is ${self.private_ip}"
    on_failure = continue
  }
}