Skip to content

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 Name Form AWS API Terraform
aws_alb_target_group_attachment One-to-many Plural Singular
aws_autoscaling_attachment (ELB) One-to-many Plural Singular
aws_autoscaling_attachment (Target Group ARN) One-to-many Plural Singular
aws_autoscaling_traffic_source_attachment One-to-many Plural Singular
aws_cognito_identity_pool_roles_attachment2 One-to-many Plural Plural
aws_ec2_transit_gateway_peering_attachment One-to-one Singular Singular
aws_ec2_transit_gateway_vpc_attachment One-to-one Singular Singular
aws_elb_attachment One-to-many Plural Singular
aws_iam_group_policy_attachment One-to-many Singular Singular
aws_iam_policy_attachment3 One-to-many Singular Plural
aws_iam_role_policy_attachment One-to-many Singular Singular
aws_iam_user_policy_attachment One-to-many Singular Singular
aws_internet_gateway_attachment One-to-one Singular Singular
aws_iot_policy_attachment One-to-many Singular Singular
aws_iot_thing_principal_attachment One-to-many Singular Singular
aws_lb_target_group_attachment One-to-many Plural Singular
aws_lightsail_disk_attachment One-to-many Singular Singular
aws_lightsail_lb_attachment One-to-many Plural Singular
aws_lightsail_lb_certificate_attachment One-to-one Singular Singular
aws_lightsail_static_ip_attachment One-to-one Singular Singular
aws_network_interface_attachment One-to-many Singular Singular
aws_network_interface_sg_attachment One-to-many Plural Singular
aws_networkmanager_connect_attachment One-to-one Singular Singular
aws_networkmanager_core_network_policy_attachment One-to-one Singular Singular
aws_networkmanager_site_to_site_vpn_attachment One-to-one Singular Singular
aws_networkmanager_transit_gateway_registration One-to-one Singular Singular
aws_networkmanager_transit_gateway_route_table_attachment One-to-one Singular Singular
aws_networkmanager_vpc_attachment One-to-one Singular Singular
aws_organizations_policy_attachment One-to-many Singular Singular
aws_quicksight_iam_policy_assignment One-to-many Plural Plural
aws_security_group (Egress)4 One-to-many Plural Plural
aws_security_group (Ingress)4 One-to-many Plural Plural
aws_security_group_rule (Egress) One-to-many Plural Singular
aws_security_group_rule (Ingress) One-to-many Plural Singular
aws_sesv2_dedicated_ip_assignment One-to-one Singular Singular
aws_ssoadmin_account_assignment One-to-one Singular Singular
aws_ssoadmin_customer_managed_policy_attachment One-to-many Singular Singular
aws_ssoadmin_managed_policy_attachment One-to-many Singular Singular
aws_ssoadmin_permissions_boundary_attachment One-to-one Singular Singular
aws_volume_attachment One-to-many Singular Singular
aws_vpc_security_group_egress_rule One-to-many Plural Singular
aws_vpc_security_group_ingress_rule One-to-many Plural Singular
aws_vpclattice_target_group_attachment One-to-many Plural Singular
aws_vpn_gateway_attachment One-to-one Singular Singular

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:

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#


  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.