feat(terraform): add terraform provider code generator - #268
Open
bhoomikarsnewrelic wants to merge 7 commits into
Open
feat(terraform): add terraform provider code generator#268bhoomikarsnewrelic wants to merge 7 commits into
bhoomikarsnewrelic wants to merge 7 commits into
Conversation
Adds a new `terraform` generator to tutone that produces the Go files
needed for each terraform-provider-newrelic resource from a NerdGraph
GraphQL schema, reducing new resource work from 1–3 weeks to same-day.
## What's generated per resource
- `resource_newrelic_<name>.go` — Schema declaration + full CRUD wiring
- `structures_newrelic_<name>.go` — expand/flatten scaffolds with TUTONE:MANUAL stubs
- `resource_newrelic_<name>_test.go` — acceptance test scaffold (written once)
- `provider_registration.txt` — single registration line for provider_newrelic.go
## Key design decisions
- Generator reads `pkgConfig.Terraform` config block; silently skips packages
that have no `terraform:` block — existing typegen/nerdgraphclient runs
are completely unaffected.
- Input type names are resolved directly from schema.json (not string
manipulation), guaranteeing 100% accuracy against the same schema that
produced the go-client types.
- `ClientService` defaults to TitleCase(last import path segment) with a
WARN log when not explicit, so authors are prompted to verify.
- SchemaFields sorted alphabetically for deterministic/idempotent output.
- All four read patterns supported via config flag:
direct | list_filter | list_search | entity_management
## Config fields added to PackageConfig
- `TerraformConfig` struct with 30+ fields covering all CRUD variants:
BatchCreate, ReadAfterCreate, NoUpdateMutation, ImmutableFields,
ConflictingFields, BatchDelete, RequiresOrgID, ReadRetry, etc.
## Files changed
- `internal/config/config.go` — TerraformConfig struct + embed in PackageConfig
- `pkg/lang/terraform.go` — TerraformGenerator, TerraformField, type-mapping
- `pkg/lang/terraform_test.go` — 14 unit tests (scalar/enum/nested/list mapping,
DeriveClientService, DeriveMethodName, etc.)
- `generators/terraform/generator.go` — full codegen.Generator implementation
- `generators/terraform/generator_test.go` — 10 unit tests covering all read_type paths,
field overrides, Execute file creation
- `generators/terraform/testdata/schema.json` — fixture schema for unit tests
- `templates/terraform/*.tmpl` — 4 templates (resource, structures, test, registration)
- `pkg/generate/generate.go` — registers "terraform" generator
- `.gitignore` — allow generators/terraform/testdata/schema.json
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Two bugs fixed: 1. Templates not found when tutone runs from a consuming repo (e.g. terraform-provider-newrelic, newrelic-client-go) that has no local templates/ directory. The binary now embeds all templates via go:embed so it is fully self-contained. Local files still take precedence, enabling per-repo overrides during development. 2. os.Create() was called before template parsing. A parse failure (missing template, syntax error) left a 0-byte file on disk that subsequent git add/commit would pick up silently. Reordered so the destination file is only created after the template parses successfully. Root cause of the 0-byte resource_newrelic_notification_destination.go in terraform-provider-newrelic PR #3146 was bug #2 triggered by bug #1. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…e path embed.FS in templates/tmpl.go is rooted at the templates/ directory, so embedded paths are terraform/resource.go.tmpl — not templates/terraform/resource.go.tmpl. ParseFS was failing with 'pattern matches no files' because the full path including the templates/ prefix was passed unchanged. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…nerated code
1. resource.go.tmpl: import the go-client namespace package so generated
code compiles. Qualify ReadFilterType and ReadEntityType with the
package name (e.g. notifications.AiNotificationsDestinationFilter).
2. structures.go.tmpl: replace interface{} stubs with concrete go-client
types so the resource.go function calls type-check at compile time.
expand funcs return PackageName.InputType; flatten accepts
*PackageName.ReturnType.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Two imports of the same path pkg/errors caused 'imported and not used'
compile errors. The bare errors alias was only used in entity_management
read type; all other read types used nrErrors. Unified to nrErrors only.
Also removed the {{ .ImportPath }} import added in the previous commit —
goimports strips it as unused since resource.go never references
packagename.TypeName directly (types flow from structures.go in the
same package).
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…fix test signature
1. TerraformField.GoTypeName: new field populated for KindInputObject
fields with the actual NerdGraph type name (e.g.
MaintenanceWindowScopedReferenceInput). Previously the template used
GoName (the field name, e.g. Scope) which does not exist in the
go-client package.
2. structures.go.tmpl: nested expand functions now return
PackageName.GoTypeName instead of PackageName.GoName.
3. resource_test.go.tmpl: testAccCheckDestroy now accepts
*terraform.State (not interface{}) and imports the terraform package.
Added //go:build integration build tag to exclude from unit builds.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…pass it The template was always passing accountID to go-client methods when requires_account_id=true, but some mutations (e.g. maintenanceWindowCreate) have no accountId argument in NerdGraph — so the go-client method doesn't accept it. This caused 'too many arguments' compile errors. Added MutationHasAccountIDArg helper that checks the mutation's argument list. Generator now sets CreateHasAccountIDArg / UpdateHasAccountIDArg / DeleteHasAccountIDArg from the live schema. Template uses these flags instead of RequiresAccountID for method call argument passing. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a new
terraformgenerator to tutone that produces the Go files needed for each terraform-provider-newrelic resource from a NerdGraph GraphQL schema, reducing new resource work from 1–3 weeks to same-day.What's generated per resource
resource_newrelic_<name>.go— Schema declaration + full CRUD wiringstructures_newrelic_<name>.go— expand/flatten scaffolds with TUTONE:MANUAL stubsresource_newrelic_<name>_test.go— acceptance test scaffold (written once)provider_registration.txt— single registration line for provider_newrelic.goKey design decisions
pkgConfig.Terraformconfig block; silently skips packages that have noterraform:block — existing typegen/nerdgraphclient runs are completely unaffected.ClientServicedefaults to TitleCase(last import path segment) with a WARN log when not explicit, so authors are prompted to verify.Config fields added to PackageConfig
TerraformConfigstruct with 30+ fields covering all CRUD variants: BatchCreate, ReadAfterCreate, NoUpdateMutation, ImmutableFields, ConflictingFields, BatchDelete, RequiresOrgID, ReadRetry, etc.Files changed
internal/config/config.go— TerraformConfig struct + embed in PackageConfigpkg/lang/terraform.go— TerraformGenerator, TerraformField, type-mappingpkg/lang/terraform_test.go— 14 unit tests (scalar/enum/nested/list mapping,DeriveClientService, DeriveMethodName, etc.)
generators/terraform/generator.go— full codegen.Generator implementationgenerators/terraform/generator_test.go— 10 unit tests covering all read_type paths,field overrides, Execute file creation
generators/terraform/testdata/schema.json— fixture schema for unit teststemplates/terraform/*.tmpl— 4 templates (resource, structures, test, registration)pkg/generate/generate.go— registers "terraform" generator.gitignore— allow generators/terraform/testdata/schema.json