- Service Identifier
- Packages
- Resources and Data Sources
- Files
- MixedCaps
- Functions
- Variables and Constants
- Acceptance and Unit Tests
- Test Support Functions
- Acceptance Test Configurations
In the AWS Provider, a service identifier should consistently identify an AWS service from code to documentation to provider use by a practitioner. Prominent places you will see service identifiers:
- The package name (e.g.,
internal/service/<serviceidentifier>
) - In resource and data source names (e.g.,
aws_<serviceidentifier>_thing
) - Documentation file names (e.g.,
website/docs/r/<serviceidentifier>_thing
)
Typically, choosing the AWS Provider identifier for a service is simple. AWS consistently uses one name and we use that name as the identifier. However, some services are not simple. To provide consistency, and to help contributors and practitioners know what to expect, we provide this rule for defining a service identifier:
- Determine the service package name for AWS Go SDK v2.
- Determine the AWS CLI v2 command corresponding to the service (i.e., the word following
aws
in CLI commands; e.g., foraws sts get-caller-identity
,sts
is the command,get-caller-identity
is the subcommand). - If the SDK and CLI agree, use that. If the service only exists in one, use that.
- If they differ, use the shorter of the two.
- Use lowercase letters and do not include any underscores (
_
).
With 156+ services having some level of implementation, the following is a summary of how well this rule is currently followed.
For AWS provider service package names, only five packages violate this rule: appautoscaling
should be applicationautoscaling
, codedeploy
should be deploy
, elasticsearch
should be es
, cloudwatchlogs
should be logs
, and simpledb
should be sdb
.
For the service identifiers used in resource and data source configuration names (e.g., aws_acmpca_certificate_authority
), 32 wholly or partially violate the rule.
- EC2, ELB, ELBv2, and RDS have legacy but heavily used resources and data sources that do not or inconsistently use service identifiers.
- The remaining 28 services violate the rule in a consistent way:
appautoscaling
should beapplicationautoscaling
,codedeploy
should bedeploy
,elasticsearch
should bees
,cloudwatch_log
should belogs
,simpledb
should besdb
,prometheus
should beamp
,api_gateway
should beapigateway
,cloudcontrolapi
should becloudcontrol
,cognito_identity
should becognitoidentity
,cognito
should becognitoidp
,config
should beconfigservice
,dx
should bedirectconnect
,directory_service
should beds
,elastic_beanstalk
should beelasticbeanstalk
,cloudwatch_event
should beevents
,kinesis_firehose
should befirehose
,msk
should bekafka
,mskconnect
should bekafkaconnect
,kinesis_analytics
should bekinesisanalytics
,kinesis_video
should bekinesisvideo
,lex
should belexmodels
,media_convert
should bemediaconvert
,media_package
should bemediapackage
,media_store
should bemediastore
,route53_resolver
should beroute53resolver
, relevants3
should bes3control
,serverlessapplicationrepository
should beserverlessrepo
, andservice_discovery
should beservicediscovery
.
Package names are not seen or used by practitioners. However, they should still be carefully considered.
- For service packages (i.e., packages under
internal/service
), use the AWS Provider service identifier as the package name. - For other packages, use a short name for the package. Common Go lengths are 3-9 characters.
- Use a descriptive name. The name should capture the key purpose of the package.
- Use lowercase letters and do not include any underscores (
_
). - Avoid useless names like
helper
. These names convey zero information. Everything in the AWS Provider is helping something or someone do something so the namehelper
doesn't narrow down the purpose of the package within the codebase. - Use a name that is not too narrow or too broad as Go packages should not be too big or too small. Tiny packages can be combined using a broader name encompassing both. For example,
verify
is a good name because it tells you what the package does and allows a broad set of validation, comparison, and checking functionality.
When creating a new resource or data source, it is important to get names right. Once practitioners rely on names, we can only change them through breaking changes. If you are unsure about what to call a resource or data source, discuss it with the community and maintainers.
- Follow the AWS SDK for Go v2. Almost always, the API operations make determining the name simple. For example, the Amazon CloudWatch Evidently service includes
CreateExperiment
,GetExperiment
,UpdateExperiment
, andDeleteExperiment
. Thus, the resource (or data source) name is "Experiment." - Give a resource its Terraform configuration (i.e., HCL) name (e.g.,
aws_imagebuilder_image_pipeline
) by joining these three parts with underscores:aws
prefix- Service identifier (service identifiers do not include underscores), all lower case (e.g.,
imagebuilder
) - Resource (or data source) name in snake case (spaces replaced with underscores, if any), all lower case (e.g.,
image_pipeline
)
- Name the main resource function
Resource<ResourceName>()
, with the resource name in MixedCaps. Do not include the service name or identifier. For example, defineResourceImagePipeline()
in a file calledinternal/service/imagebuilder/image_pipeline.go
. - Similarly, name the main data source function
DataSource<ResourceName>()
, with the data source name in MixedCaps. Do not include the service name or identifier. For example, defineDataSourceImagePipeline()
in a file calledinternal/service/imagebuilder/image_pipeline_data_source.go
.
File names should follow Go and Markdown conventions with these additional points.
- Resource markdown goes in the
website/docs/r
directory. Data source markdown goes in thewebsite/docs/d
directory. - Use the service identifier and resource or data source name, separated by an underscore (
_
). - All letters are lowercase.
- Use
.html.markdown
as the extension. - Do not include "aws" in the name.
A correct example is accessanalyzer_analyzer.html.markdown
. An incorrect example is service_discovery_instance.html.markdown
because the service identifier should not include an underscore.
- Resource and data source files are in the
internal/service/<service>
directory. - Do not include the service as part of the file name.
- Data sources should include
_data_source
after the data source name (e.g.,application_data_source.go
). - Put unit and acceptance tests in a file ending with
_test.go
(e.g.,custom_domain_association_test.go
). - Use snake case for multiword names (i.e., all letters are lowercase, words separated by underscores).
- Use the
.go
extension. - Idiomatic names for common non-resource, non-data-source files include
consts.go
(service-wide constants),find.go
(finders),flex.go
(FLatteners and EXpanders),generate.go
(directives for code generation),id.go
(ID creators and parsers),status.go
(status functions),sweep.go
(sweepers),tags_gen.go
(generated tag code),validate.go
(validators), andwait.go
(waiters).
Write multiword names in Go using MixedCaps (or mixedCaps) rather than underscores.
For more details on capitalizations we enforce with CI Semgrep tests, see the Caps List.
Initialisms and other abbreviations are a key difference between many camel/Pascal case interpretations and mixedCaps. Abbreviations in mixedCaps should be the correct, human-readable case. After all, names in code are for humans. (The mixedCaps convention aligns with HashiCorp's emphasis on pragmatism and beauty.)
For example, an initialism such as "VPC" should either be all capitalized ("VPC") or all lower case ("vpc"), never "Vpc" or "vPC." Similarly, in mixedCaps, "DynamoDB" should either be "DynamoDB" or "dynamoDB", depending on whether an initial cap is needed or not, and never "dynamoDb" or "DynamoDb."
- Use mixedCaps for function, type, method, variable, and constant names in the Terraform AWS Provider Go code.
In general, follow Go best practices for good function naming. This rule is for functions defined outside of the test context (i.e., not in a file ending with _test.go
). For test functions, see Test Support Functions or Acceptance Test Configurations below.
- Only export functions (capitalize) when necessary, i.e., when the function is used outside the current package, including in the
_test
(.test
) package. - Use MixedCaps (exported) or mixedCaps (not exported). Do not use underscores for multiwords.
- Do not include the service name in the function name. (If functions are used outside the current package, the import package clarifies a function's origin. For example, the EC2 function
FindVPCEndpointByID()
is used outside theinternal/service/ec2
package but where it is used, the call istfec2.FindVPCEndpointByID()
.) - For CRUD functions for resources, use this format:
resource<ResourceName><CRUDFunction>
. For example,resourceImageRecipeUpdate()
,resourceBaiduChannelRead()
. - For data sources, for Read functions, use this format:
dataSource<DataSourceName>Read
. For example,dataSourceBrokerRead()
,dataSourceEngineVersionRead()
. - To improve readability, consider including the resource name in helper function names that pertain only to that resource. For example, for an expander function for an "App" resource and a "Campaign Hook" expander, use
expandAppCampaignHook()
. - Do not include "AWS" or "Aws" in the name.
In general, follow Go best practices for good variable and constant naming.
- Only export variables and constants (capitalize) when necessary, i.e., the variable or constant is used outside the current package, including in the
_test
(.test
) package. - Use MixedCaps (exported) or mixedCaps (not exported). Do not use underscores for multiwords.
- Do not include the service name in variable or constant names. (If variables or constants are used outside the current package, the import package clarifies its origin. For example, IAM's
PropagationTimeout
is widely used outside of IAM but each instance is through the package import alias,tfiam.PropagationTimeout
. "IAM" is unnecessary in the constant name.) - To improve readability, consider including the resource name in variable and constant names that pertain only to that resource. For example, for a string constant for a "Role" resource and a "not found" status, use
roleStatusNotFound
orRoleStatusNotFound
, if used outside the service's package. - Do not include "AWS" or "Aws" in the name.
NOTE: Give priority to using constants from the AWS SDK for Go rather than defining new constants for the same values.
With about 6000 acceptance and unit tests, following these naming conventions is essential to organization and (human) context switching between services.
There are three types of tests in the AWS Provider: (regular) acceptance tests, serialized acceptance tests, and unit tests. All are functions that take a variable of type *testing.T
. Acceptance tests and unit tests have exported (i.e., capitalized) names while serialized tests do not. Serialized tests are called by another exported acceptance test, often ending with _serial
. The majority of tests in the AWS provider are acceptance tests.
Acceptance test names have a minimum of two (e.g., TestAccBackupPlan_tags
) or a maximum of three (e.g., TestAccDynamoDBTable_Replica_multiple
) parts, joined with underscores:
- First part: All have a prefix (i.e.,
TestAcc
), service name (e.g.,Backup
,DynamoDB
), and resource name (e.g.,Plan
,Table
), MixedCaps without underscores between. Do not include "AWS" or "Aws" in the name. - Middle part (Optional): Test group (e.g.,
Replica
), uppercase, MixedCaps. Consider a metaphor where tests are chapters in a book. If it is helpful, tests can be grouped together like chapters in a book that are sometimes grouped into parts or sections of the book. - Last part: Test identifier (e.g.,
basic
,tags
, ormultiple
), lowercase, mixedCaps). The identifier should make the test's purpose clear but be concise. For example, the identifierconflictsWithCloudFrontDefaultCertificate
(41 characters) conveys no more information thanconflictDefaultCertificate
(26 characters), since "CloudFront" is implied and "with" is always implicit. Avoid words that convey no meaning or whose meaning is implied. For example, "with" (e.g.,_withTags
) is not needed because we imply the name is telling us what the test is with.withTags
can be simplified totags
.
The names of serialized acceptance tests follow the regular acceptance test name rule except serialized acceptance test names:
- Start with
testAcc
instead ofTestAcc
- Do not include the name of the service (e.g., a serialized acceptance test would be called
testAccApp_basic
nottestAccAmplifyApp_basic
).
Unit test names follow the same rule as acceptance test names except unit test names:
- Start with
Test
, notTestAcc
- Do not include the name of the service
- Usually do not have any underscores
- If they test a function, should include the function name (e.g., a unit test of
ExpandListener()
should be calledTestExpandListener()
)
This rule is for functions defined in the test context (i.e., in a file ending with _test.go
) that do not return a string with Terraform configuration. For non-test functions, see Functions above. Or, see Acceptance Test Configurations below.
- Only export functions (capitalize) when necessary, i.e., when the function is used outside the current package. This is very rare.
- Use MixedCaps (exported) or mixedCaps (not exported). Do not use underscores for multiwords.
- Do not include the service name in the function name. For example,
testAccCheckAMPWorkspaceExists()
should be namedtestAccCheckWorkspaceExists()
instead, dropping the service name. - Several types of support functions occur commonly and should follow these patterns:
- Destroy:
testAccCheck<Resource>Destroy
- Disappears:
testAccCheck<Resource>Disappears
- Exists:
testAccCheck<Resource>Exists
- Not Recreated:
testAccCheck<Resource>NotRecreated
- PreCheck:
testAccPreCheck
(often, only one PreCheck is needed per service so no resource name is needed) - Recreated:
testAccCheck<Resource>Recreated
- Destroy:
- Do not include "AWS" or "Aws" in the name.
This rule is for functions defined in the test context (i.e., in a file ending with _test.go
) that return a string with Terraform configuration. For test support functions, see Test Support Functions above. Or, for non-test functions, see Functions above.
NOTE: This rule is not widely used currently. However, new functions and functions you change should follow it.
- Only export functions (capitalize) when necessary, i.e., when the function is used outside the current package. This is very rare.
- Use MixedCaps (exported) or mixedCaps (not exported). Do not use underscores for multiwords.
- Do not include the service name in the function name.
- Follow this pattern:
testAccConfig<Resource>_<TestGroup>_<configDescription>
_<TestGroup>
is optional. Refer to the Acceptance Test Rule test group discussion.- Especially when an acceptance test only uses one configuration, the
<configDescription>
should be the same as the test identifier discussed in the Acceptance Test Rule.
- Do not include "AWS" or "Aws" in the name.