--- name: review-helpers description: "Review Terraform AWS Provider helper code: finders, status functions, waiters, sweepers, data sources, and list resources. Use when reviewing a PR that changes non-test internal/service/**/*.go code for resource lookup, retry.StateChangeConf waiters, NewSweepResource sweepers, DataSourceWithModel data sources, or Framework/SDKv2 list resources." --- # Review: Helpers, Sweepers, Data Sources, List Resources Assume the `@maintainer` persona. Scope: finders, status, waiters, sweepers, data sources, list resources. Loaded from `review-pr`. ## Finders, status, waiters - Finder signature: `findByID(ctx context.Context, conn *.Client, id string) (*awstypes., error)`. Variants by ARN/Name use the same shape. - On `*awstypes.ResourceNotFoundException`, return `smarterr.NewError(&retry.NotFoundError{LastError: err})`. - Status function reuses the finder and returns `retry.StateRefreshFunc`. Design status so one function powers create, update, and delete waiters. - Waiters use `retry.StateChangeConf`. Created/updated waiters typically set `NotFoundChecks: 20` and `ContinuousTargetOccurence: 2`. Deleted waiters use empty `Target` with `Pending` covering deletion-in-progress states. - Prefer SDK-provided status constants (e.g. `awstypes.StatusInProgress`) over package-level string consts. - Finders and `ResName` constants referenced in tests must be re-exported via `exports_test.go`. Flag finders that return raw errors (must wrap with `smarterr.NewError`), status that duplicates finder logic, or hand-rolled polling loops in place of `retry.StateChangeConf`. ## Sweepers Each new resource needs a sweeper. Iterate the SDK paginator, build via `framework.NewSweepResource(newResource, client, framework.NewAttribute(names.AttrID, aws.ToString(v.Id)))` (where `framework` is `internal/sweep/framework`), and register in the package's `sweep.go` with `awsv2.Register("aws__", sweeps, ...optionalDeps)`. Pass multiple `framework.NewAttribute(...)` arguments for composite identity. Flag new resources without a sweeper, sweepers that don't propagate paginator errors via `smarterr.NewError`, and sweepers using import aliases other than `framework` for `internal/sweep/framework`. ## Data sources Data sources have only a `Read` method. - Use `framework.DataSourceWithModel[T]`. - Schema attributes are `Required` or `Optional` for search criteria; everything else is `Computed`. - Attributes that are `Required` on the corresponding resource are typically `Computed` on the data source unless they form lookup criteria. - No configurable timeouts. - Tagged data sources expose a single computed `tags` attribute (no `tags_all`). ## List resources Framework path embeds the corresponding underlying resource. SDKv2 path uses `framework.ListResourceWithSDKv2Resource`. The `List` method: 1. Get the client. 2. Fetch the config (only when the list takes query attributes such as a parent ID). 3. Stream results from a paginated AWS List API. 4. Set logging fields per item (typically the ARN) via `tflog.SetField(ctx, logging.ResourceAttributeKey(...), ...)`. 5. Set identifying attributes for each result. 6. Set `result.DisplayName` to a human-readable identifier (typically the resource name). The listing helper uses an iterator over the SDK paginator: ```go func lists(ctx context.Context, conn *.Client, input *.ListsInput) iter.Seq2[awstypes., error] ``` The flatten function shared by Read and List lives in the resource file (`r.flatten` for Framework, `resourceFlatten` for SDKv2). Flag list resources that don't set `DisplayName`, that re-implement flatten logic instead of sharing with Read, or that omit the `tflog.SetField` per-item logging hook.