Back to Terraform Provider Aws

Relationship Resource Design Standards

docs/design-decisions/relationship-resource-design-standards.md

6.43.023.2 KB
Original Source
<!-- Copyright IBM Corp. 2014, 2026 --> <!-- SPDX-License-Identifier: MPL-2.0 -->

Relationship Resource Design Standards

Summary: Align on design standards for relationship management resources in the Terraform AWS Provider.
Created: 2022-07-11


The goal of this document is to assess the design of existing "relationship" resources in the Terraform AWS Provider and determine if a consistent set of rules can be defined for implementing them. For the purpose of this document, a "relationship" resource is defined as a resource which manages either a direct relationship between two standalone resources ("one-to-one", ie. aws_ssoadmin_permission_boundary_attachment), or a variable number of child relationships to a parent resource ("one-to-many", ie. aws_iam_role_policy_attachment). Resources and AWS APIs with this function will often contain suffixes like "attachment", "assignment", "registration", or "rule".

A documented standard for implementing relationship-styled resources will inform how new resources are written, and provide guidelines to refer back to when the community requests features which may not align with internal best practices.

Background

The first form of relationship resources ("one-to-one") typically have a straightforward, singular API design and provider implementation given only a single relationship exists. The second form of resources ("one-to-many") often has to balance two provider design principles:

In these cases, the smallest possible piece of infrastructure may be a single parent-child relationship, while the AWS APIs may accept and return lists of parent-child relationships. The first principle would favor a resource representing a single relationship, while the second principle suggests a resource should manage a variable number of relationships. Additionally, practitioners coming from the AWS CLI or SDK might also have expectations about how resource schemas should be shaped compared to CLI flags or SDK inputs.

An analysis of existing resources can inform which of these principles maintainers have given precedence to up to this point. The table below documents existing relationship resources in the AWS provider. This table should not be considered exhaustive1, but covers a large majority of the resources implementing the patterns discussed above.

Resource NameFormAWS APITerraform
aws_alb_target_group_attachmentOne-to-manyPluralSingular
aws_autoscaling_attachment (ELB)One-to-manyPluralSingular
aws_autoscaling_attachment (Target Group ARN)One-to-manyPluralSingular
aws_autoscaling_traffic_source_attachmentOne-to-manyPluralSingular
aws_cognito_identity_pool_roles_attachment2One-to-manyPluralPlural
aws_ec2_transit_gateway_peering_attachmentOne-to-oneSingularSingular
aws_ec2_transit_gateway_vpc_attachmentOne-to-oneSingularSingular
aws_elb_attachmentOne-to-manyPluralSingular
aws_iam_group_policy_attachmentOne-to-manySingularSingular
aws_iam_policy_attachment3One-to-manySingularPlural
aws_iam_role_policy_attachmentOne-to-manySingularSingular
aws_iam_user_policy_attachmentOne-to-manySingularSingular
aws_internet_gateway_attachmentOne-to-oneSingularSingular
aws_iot_policy_attachmentOne-to-manySingularSingular
aws_iot_thing_principal_attachmentOne-to-manySingularSingular
aws_lb_target_group_attachmentOne-to-manyPluralSingular
aws_lightsail_disk_attachmentOne-to-manySingularSingular
aws_lightsail_lb_attachmentOne-to-manyPluralSingular
aws_lightsail_lb_certificate_attachmentOne-to-oneSingularSingular
aws_lightsail_static_ip_attachmentOne-to-oneSingularSingular
aws_network_interface_attachmentOne-to-manySingularSingular
aws_network_interface_sg_attachmentOne-to-manyPluralSingular
aws_networkmanager_connect_attachmentOne-to-oneSingularSingular
aws_networkmanager_core_network_policy_attachmentOne-to-oneSingularSingular
aws_networkmanager_site_to_site_vpn_attachmentOne-to-oneSingularSingular
aws_networkmanager_transit_gateway_registrationOne-to-oneSingularSingular
aws_networkmanager_transit_gateway_route_table_attachmentOne-to-oneSingularSingular
aws_networkmanager_vpc_attachmentOne-to-oneSingularSingular
aws_organizations_policy_attachmentOne-to-manySingularSingular
aws_quicksight_iam_policy_assignmentOne-to-manyPluralPlural
aws_security_group (Egress)4One-to-manyPluralPlural
aws_security_group (Ingress)4One-to-manyPluralPlural
aws_security_group_rule (Egress)One-to-manyPluralSingular
aws_security_group_rule (Ingress)One-to-manyPluralSingular
aws_sesv2_dedicated_ip_assignmentOne-to-oneSingularSingular
aws_ssoadmin_account_assignmentOne-to-oneSingularSingular
aws_ssoadmin_customer_managed_policy_attachmentOne-to-manySingularSingular
aws_ssoadmin_managed_policy_attachmentOne-to-manySingularSingular
aws_ssoadmin_permissions_boundary_attachmentOne-to-oneSingularSingular
aws_volume_attachmentOne-to-manySingularSingular
aws_vpc_security_group_egress_ruleOne-to-manyPluralSingular
aws_vpc_security_group_ingress_ruleOne-to-manyPluralSingular
aws_vpclattice_target_group_attachmentOne-to-manyPluralSingular
aws_vpn_gateway_attachmentOne-to-oneSingularSingular

Of the 44 resources documented above, 29 are of the "one-to-many" form and 17 have "plural" AWS APIs (ie. accept a list of child resources to be attached to a single parent). Of these 17, 13 resources (76%) use a "singular" Terraform implementation, where a list with one item is sent to the Create/Read/Update API, rather than allowing a single resource to manage multiple relationships. Of the remaining 4 with "plural" Terraform implementations, 2 do so to exclusively manage child relationships (aws_security_group Ingress/Egress variants), and one requires a "plural" implementation simply because of API limitations.

These metrics indicate a strong historical preference for representing a single API object over aligning the schema to the underlying AWS API. The primary exceptions to this are when exclusive management of all child resources is desired, such as security group ingress/egress rules, or IAM policy attachments.

Proposal

The best practice for net-new "one-to-many" relationship resources should be to implement singular versions. Feature requests related to changing the singular nature of an existing relationship resource should be avoided unless necessary for the underlying API to function properly.

Variation from this pattern should only be done when:

  1. There is a valid use case for a single resource to retain exclusive management of all parent/child relationships.
  2. Manipulating the underlying AWS APIs to work with singular relationships is not possible or introduces unnecessary complexity.

"One-to-many" Design Example

Given a fictional "plural" API AttachChildren with a request body like:

{
  "ParentId": "string",
  "Children": [
    {
      "ChildId: "string"
    }
  ]
}

The corresponding Terraform resource would only represent a single parent/child relationship with a configuration like:

terraform
resource "aws_parent" "example" {
  name = "foo"
}

resource "aws_child" "example" {
  name = "bar"
}

resource "aws_child_attachment" "example" {
  parent_id = aws_parent.example.id
  child_id  = aws_child.example.id
}

References

Footnotes

  1. Due to the volume of resources with "rule" in the name (~70), only the prominent security group rule resources were included in the analysis above. While "rule" resources often follow the same relationship-style design, the ~40 examples above provided enough initial data to inform design standards.

  2. The structure of this API precludes it from being implemented in a singular fashion.

  3. Creates exclusive attachments.

  4. Creates exclusive rules. 2