Skip to content

Latest commit

 

History

History
217 lines (127 loc) · 23.5 KB

resource-behavior.md

File metadata and controls

217 lines (127 loc) · 23.5 KB

Terraform AWS Cloud Control Provider Resource Behavior

This document describes the behavior of resources implemented by the provider. In particular it describes in detail how AWS CloudFormation resource types are defined as Terraform resources.

We assume some familiarity with user-facing Terraform concepts like configuration, state, CLI workflow, etc. The Terraform website has documentation on these ideas.

Resources

Terraform Resources

Resources describe infrastructure objects such as virtual networks or compute instances. By declaring a Terraform resource block and applying that configuration, Terraform manages the lifecycle of the underlying infrastructure object so as to make its settings match the configuration.

Resource blocks declare a resource of a specific type with a specific local name. The local name is used solely to refer to that resource within its own module, having no meaning outside the module's scope. For example

resource "awscc_s3_bucket" "example" {
  bucket_name = "example-bucket"
}

declares a resource of type awscc_s3_bucket with its bucket_name argument set to "example-bucket". The resource's module-local name is example.

Resources are implemented in providers, plugins which interact with infrastructure providers such as AWS. A resource's implementation defines a schema which describes the resource's arguments, and methods (including CRUD methods) which define the resource's lifecycle management functionality.

Note that we will use the terms argument and attribute interchangeably from now on as Terraform plugins use attribute and Terraform CLI uses argument for the same concept.

Terraform Data Sources

Data sources are a variant of resource intended to allow Terraform to reference external data. Unlike managed resources, Terraform does not manage the underlying infrastructure object's lifecycle. Data sources are intended to have no side-effects.

For the purposes of this document we consider data sources to be similar to resources with only a Read method. We will call out differences where they are significant.

AWS CloudFormation Resources

CloudFormation resources are conceptually very similar to Terraform resources. However, there are some differences:

Interpretation Of CloudFormation Resource Schemas

During generation of the Terraform AWS Cloud Control Provider, all available CloudFormation resource schemas are downloaded from the CloudFormation registry and are cached in this GitHub repository (so as to have reproducible builds). Unless suppressed, each CloudFormation resource schema is then used to generate

  • A Terraform resource.
  • A Terraform singular data source. A singular data source returns attributes of a single AWS object. A unique identifier is used to specify for which AWS object information is returned.
  • A plural data source. A plural data source returns a list of the unique identifiers for every AWS object of the resource's type (in the configured AWS account and Region).

Resource Type Naming

CloudFormation resource type names consist of three parts; an organization, service and resource (for example AWS::EC2::Instance). Terraform type names are derived from the CloudFormation type name by lower casing the service part, snake casing the resource part and using awscc_ as a prefix. The resource part is pluralized for any plural data source type name.

For example, the AWS::EC2::Instance CloudFormation resource type leads to the generation of the awscc_ec2_instance resource and awscc_ec2_instance and awscc_ec2_instances data sources.

Resource Shape

The shape of a resource defines the names, types and behaviors of its fields. Every property in a CloudFormation resource schema corresponds to an argument in the Terraform schema.

Attribute Naming

A Terraform attribute's name is obtained by snake casing the corresponding CloudFormation property's name. For example a property named GlobalReplicationGroupDescription corresponds to an attribute named global_replication_group_description.

Note

If a top-level attribute's name is one of the Terraform meta-arguments count, depends_on, for_each, or lifecycle then generation of the Terraform resource (and data sources) is suppressed.

If a top-level attribute's name is provider it is renamed to provider_name.

Attribute Types

A Terraform attribute's type is derived from the corresponding CloudFormation property's type.

CloudFormation Type Terraform Type
boolean Bool
integer Int64
number Float64
string String1
array List or Set23
object Nested attribute or Map4
Array Types
insertionOrder uniqueItems Terraform Type
true false List
false false List custom type with semantic equality
true true List with UniqueValues validator
false true Set

Attribute Validation

Integer Validation

A JSON Schema integer property's minimum and maximum values correspond to Terraform AtLeast, AtMost and Between validators.

Any enum value corresponds to the Terraform OneOf validator.

Number Validation

A JSON Schema number property's minimum and maximum values correspond to Terraform AtLeast, AtMost and Between validators.

String Validation

A JSON Schema string property's minLength and maxLength values correspond to Terraform LengthAtLeast, LengthAtMost and LengthBetween validators.

Any enum value corresponds to the Terraform OneOf validator.

Any pattern value corresponds to the Terraform RegexMatches validator. If the pattern value is valid for ECMA-262 but not for Go then an empty pattern ("") is used in the validator, effectively allowing any string.

Array Validation

A JSON Schema array property's minItems and maxItems values correspond to Terraform SizeAtLeast, SizeAtMost and SizeBetween validators (or their equivalents for sets).

Attribute Behaviors

Default Values

A CloudFormation property's default value corresponds to a Terraform attribute plan modifier which tailors the plan so that if the planned value is null and there is a current value and the current value is the default then use the current value, else use the planned value.

Configurability

A Terraform attribute's configurability defines how Terraform expects data to be set, whether from configuration or in the provider's logic (such as an API response value). At least one of three schema attribute flags must be set to true:

  • Required: The attribute must be configured to a known, non-null value.
  • Optional: The attribute may be configured to a known value or its value is null.
  • Computed: The attribute's planned value is unknown and a known value must be set by provider logic.

The allowed combinations of these flags are Required-only, Optional-only, Computed-only (no value is allowed to be configured), and Optional+Computed (a value may be configured; if the configured value is null, a value may be set by provider logic).

A Terraform attribute's configurability is derived from the CloudFormation resource's semantic properties.

  • If a CloudFormation property is required, the attribute is Required.
  • If a CloudFormation property is not required and not in the readOnlyProperties list, the attribute is Optional.
  • If a CloudFormation property is in the readOnlyProperties list, the attribute is Computed.
  • If a CloudFormation property has a default value, the attribute is Computed. A required property with a default value is switches the attribute to Optional.
  • All Optional attributes are marked as Computed. This is because CloudFormation only determines drift for property values that are explicitly set, whereas Terraform expects the value of an unset, non-Computed attribute to always be null (not present). AWS services will often return values that have not been specified as default values in the CloudFormation resource type schema for properties that are unset in configuration.
Immutability

If a CloudFormation property is in the createOnlyProperties list, the corresponding Terraform attribute is immutable. If the value of the attribute changes, in-place update is not possible and instead the resource is replaced for the change to occur. The Terraform RequiresReplace plan modified is used for this behavior.

The id Attribute

Every Terraform schema generated from a CloudFormation resource schema includes a top-level attribute named id. This attribute's value uniquely identifies the underlying AWS resource in the configured AWS account and Region and is used for Cloud Control API operations and in acceptance tests. The id attribute is added during the Terraform resource generation process.

Note

If the CloudFormation resource schema does define a top-level Id property then that property is mapped to a Terraform attribute named <type>_id (e.g. flow_log_id for the awscc_ec2_flow_log resource).

Interaction With The Cloud Control API

The AWS Cloud Control API provides a standardized set of operations to create, read, update, delete, and list (CRUD-L) supported resources in an AWS account.

A resource type represents an infrastructure artifact whose lifecycle can be managed through the API. Each resource type is defined by its resource type schema, a JSON Schema-compliant document published to the AWS CloudFormation registry.

To create or update a resource using the Cloud Control API a program must specify a JSON document representing the resource's properties and their values. When the resource is being created, these values are the resource's desired state. When the resource is being updated, the values are a list of patches between the resource's current state and its desired state.

Reading a resource returns a JSON document representing its current state.

The Terraform AWS Cloud Control Provider maps Terraform data to and from these JSON documents and call Cloud Control API methods.

Create

The provider's Create method is called from terraform apply when Terraform determines during planning that no resource with the configured module-local name exists or that an existing resource must be recreated. The provider converts the Terraform plan, which describes the expected values of the resource's attributes, into the Cloud Control desired state JSON document -- in the process reversing the snake casing described above.

The resource's desired state document and the CloudFormation resource type name are passed to the CreateResource API and the provider then polls for completion of the operation.

If the operation fails, the error is returned to the Terraform CLI.

If the operation succeeds, the resource's current state document is used to populate unknown attribute values, including the id attribute, and all attribute values are saved in Terraform state.

Read

The provider's Read method is called from terraform plan, terraform apply and terraform refresh to obtain the current state of the resource. The provider uses the value of the id attribute, stored in the resource's prior state, and the CloudFormation resource type name to call the GetResource API.

If the operation fails, the error is returned to the Terraform CLI.

If the operation succeeds, the resource's current state document is used to populate the Terraform current state. The values of attributes corresponding to properties in the writeOnlyProperties list are copied from prior state to current state.

Update

The provider's Update method is called from terraform apply when Terraform determines during planning that an existing resource must be updated in-place. The provider converts the resource's prior state and planned new state into JSON documents and generates a JSON Patch document listing the operations required to reach the desired state from the current state of the resource.

The patch document and the CloudFormation resource type name are passed to the UpdateResource API and the provider then polls for completion of the operation.

If the operation fails, the error is returned.

If the operation succeeds, the resource's current state document is used to populate unknown attribute values and all attribute values are saved in Terraform state.

Delete

The provider's Delete method is called from terraform apply when Terraform determines during planning that an existing resource has been removed from configuration or that an existing resource must be recreated. The provider uses the value of the id attribute and the CloudFormation resource type name to call the DeleteResource API and then polls for completion of the operation.

If the operation fails, the error is returned to the Terraform CLI and Terraform keeps the resource under management.

If the operation succeeds, the resource is removed from state.

List

The provider has no List method. Instead when a plural data source's Read method is called the provider uses the CloudFormation resource type name to call the ListResources API.

If the operation fails, the error is returned to the Terraform CLI.

If the operation succeeds, a list of primary identifiers for all resources is returned and stored in state as the value of the ids attribute.

Footnotes

  1. JSON Schema string properties with a format value of "date-time" correspond to the Terraform RFC3339 custom type.

  2. JSON Schema array properties correspond to either Terraform lists or sets depending on the values of uniqueItems and insertionOrder.

  3. An array's item type determines the Terraform list or set element type. See Array Types.

  4. JSON Schema object properties with pattern properties correspond to Terraform maps. Only the first pattern is considered.