| name | autogen-config |
| description | Authoring and reviewing `tools/codegen/config.yml` entries for autogenerated (serviceapi) resources. Use when creating the config.yml entry for a new autogen resource, adding or changing schema overrides (computability, sensitive, collection type, descriptions), configuring aliases, ignores, wait blocks, or version_header, or reviewing a generated schema for correctness after (re)generation. |
Autogen config.yml authoring and schema review
tools/codegen/config.yml tells the codegen pipeline which API endpoints map to each CRUD operation and how to shape the resulting Terraform schema. This skill holds all the judgment for writing an entry and for reviewing what the generator produced. Reference existing entries in config.yml for patterns matching your resource's shape.
Writing an entry
Search tools/codegen/atlasapispec/multi-version-api-spec.flattened.yml for the resource's path segment and map:
- GET (single item) →
read, POST → create, PATCH or PUT → update, DELETE → delete, GET (list) → datasources.list.
version_header: the application/vnd.atlas.<date>+json content type on those paths. Omitting it lets the pipeline derive the version from the read operation, so set it only when the resource must be pinned to a specific version.
- Naming: the config key must not use the
_api suffix, which is reserved for internal-only resources that are never registered in the provider. A user-facing mongodbatlas_<name> resource uses the plain name (e.g. metric_integration).
For the typical shape of a project-scoped entry — CRUD operations plus a datasources block with its own read/list and schema options — read a real entry such as log_integration or metric_integration in config.yml rather than working from a template.
aliases
- Any resource under
/groups/{groupId}/ must alias groupId: projectId, in both schema.aliases and datasources.schema.aliases, producing the standard project_id attribute.
- The resource's ID attribute name should match the API path parameter. If the path param and the response body disagree (path
{myResourceId}, body id), that is an API bug — report it to the owning API team, and alias to the more descriptive name (id: myResourceId) as a stopgap.
- Aliases match on the full camelCase API path, so the plural surface may need its own nested entries (e.g.
results.id: integrationId — see log_integration). When the list results embed the scope field, keep it and alias it (results.groupId: projectId — see ai_model_api_key) rather than ignoring it.
ignores
The generator already drops top-level links and pagination fields (total_count, envelope, items_per_page, page_num, pretty, include_count) everywhere — see commonIgnoredAttributes in tools/codegen/codespec/config.go. Do not re-list them. Ignore matching is exact-path, so the nested results.links on list data sources still needs an explicit entry, plus any other field that doesn't belong in the Terraform schema.
Secrets returned only in the create response (never populated on read or list) should be ignored on data sources, where the attribute would always be null (ignores: ["secret", "results.secret"] with a rationale comment — see service_account_secret or ai_model_api_key). On the resource itself the field stays, marked sensitive.
wait
Add wait blocks only when the API is async (the operation returns before completing). Look for state properties like stateName or status in the response schema. Follow the anchor/merge pattern in search_deployment_api in config.yml: define the wait once on create, reuse it on update (*anchor), and merge with overrides on delete (<<: *anchor), where DELETED is the special target state representing a 404/empty response.
Overrides
The Override struct in tools/codegen/config/config_model.go is the source of truth for the available set; config.yml has real examples of each. Overrides go under schema.overrides (resource) and datasources.schema.overrides (data sources), and an override can hit the same attribute on more than one surface.
Evaluate these two first — they are the easiest to miss and the most impactful when wrong:
-
computability → optional + computed: if the API returns a default when the attribute is omitted, mark it optional + computed so an absent config value does not produce a perpetual non-empty plan (see use_legacy_path_structure under log_integration). The "omitting the value" acceptance test in acceptance-test-patterns verifies exactly this.
overrides:
<attr>:
computability:
optional: true
computed: true
-
sensitive: if the field carries a secret (token, password, key, credential, connection string), mark it sensitive.
Then consider:
- Collection
type: decide list vs set from the array's semantics, per IPA-124 List vs Set. A list means order is meaningful and elements may repeat: the server returns a stable order and preserves the order the client provided (e.g. environments). A set means order is not meaningful and elements are unique: the server may return elements in any order and never returns duplicates (e.g. roles) — that needs type: set, since codegen defaults arrays to List absent an x-xgen-array-semantic: set declaration. Also align the same field across surfaces: the resource, singular data source, and plural data source are generated from different endpoints, so a field can come out as List on one and Set on another (see roles: type: set under service_account_project_assignment).
immutable_computed (generates UseStateForUnknown; resource schemas only): apply to server-generated fields that are stable after creation — IDs, created_at/created_by, masked secret variants — to reduce plan verbosity. On a one-time-returned secret it also preserves the stored value across updates (see ai_model_api_key, where secret carries it for exactly that reason).
description: each surface inherits wording from its own endpoint schema. Use the shared YAML anchors for standard fields (*project_id_description); otherwise prefer reporting wording inconsistencies upstream over local overrides.
Remaining override fields, one line each — read the struct comments in config_model.go before using them: request_body_usage (when a field must be sent or omitted differently on update), skip_state_list_merge, plan_modifiers, validators, ignore_validators. SchemaOptions.discriminator_types is a documented stopgap for oneOf/anyOf variants.
Overrides are stopgaps — pair each with an upstream flag
The codegen consumes spec annotations natively (tools/codegen/codespec/api_spec_schema.go), so the durable fix is the annotation, not the override. Whenever an override compensates for missing spec information, report to the owning API team that the spec should carry the annotation, and surface the report in the PR description. Once the spec is fixed, the override should be dropped on the next regeneration.
| Local override | Spec annotation to request | Reference |
|---|
type: set | x-xgen-array-semantic: set | IPA-131 |
computability optional+computed | x-xgen-server-computed-when-client-omitted: true (escape hatch for legacy APIs; not allowed on booleans) | IPA-131 |
immutable_computed | x-xgen-server-computed-immutable: true | IPA-131 |
sensitive: true | format: password | IPA-117 |
| ID alias for path/body mismatch | Consistent property naming (API bug) | — |
Post-generation schema review
The pipeline translates the spec faithfully, but the spec may not reflect how the API behaves or what Terraform users expect. After generating, read tools/codegen/models/<name>.yaml, internal/serviceapi/<package>/resource_schema.go, and the relevant spec paths, and check for:
- Should-be-updatable fields marked create-only (
create_only: true, which codegen derives from req_body_usage: omit_in_update_body or omit_always): often the PATCH body is narrower than POST in the spec even though the API accepts the field on update.
- Server-generated fields not computed:
id, created_at, state, status marked required/optional are likely wrong — response-required does not mean user-provided.
- User-configurable fields wrongly computed: the inverse — compare the field's presence in the POST/PATCH request bodies.
- Missing
sensitive markers on secret-looking fields.
- Discriminator scoping: a field required for one oneOf/anyOf variant must not be required for all variants.
Report findings with severity tags ([ERROR] wrong computed/required classification, [WARNING] likely-updatable or likely-sensitive, [INFO] cosmetic), fix what an override can fix, and flag the rest upstream as above.