diff --git a/.changes/unreleased/BREAKING CHANGES-20250613-135104.yaml b/.changes/unreleased/BREAKING CHANGES-20250613-135104.yaml index ddef526a..990825bc 100644 --- a/.changes/unreleased/BREAKING CHANGES-20250613-135104.yaml +++ b/.changes/unreleased/BREAKING CHANGES-20250613-135104.yaml @@ -1,6 +1,6 @@ kind: BREAKING CHANGES body: 'generate: The `.ProviderShortName` template function now uses the rendered provider name to derive the provider short name. Users that pass in the -`--rendered-provider-name` flag might see a different output for this function' + `--rendered-provider-name` flag might see a different output for this function' time: 2025-06-13T13:51:04.745115-04:00 custom: Issue: "492" diff --git a/.changes/unreleased/FEATURES-20250625-173710.yaml b/.changes/unreleased/FEATURES-20250625-173710.yaml new file mode 100644 index 00000000..1aed0b63 --- /dev/null +++ b/.changes/unreleased/FEATURES-20250625-173710.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'generate: Added support for defining import example file (`import-by-identity.tf`) using Terraform configuration + and the `identity` attribute (managed resource identity)' +time: 2025-06-25T17:37:10.853795-04:00 +custom: + Issue: "496" diff --git a/.changes/unreleased/NOTES-20250630-144026.yaml b/.changes/unreleased/NOTES-20250630-144026.yaml new file mode 100644 index 00000000..32b45a11 --- /dev/null +++ b/.changes/unreleased/NOTES-20250630-144026.yaml @@ -0,0 +1,6 @@ +kind: NOTES +body: 'generate: Generated import documentation will now contain more information about which methods are + supported by the provider (CLI command, config by ID, config by identity).' +time: 2025-06-30T14:40:26.94407-04:00 +custom: + Issue: "495" diff --git a/README.md b/README.md index 89a79d83..c72c187f 100644 --- a/README.md +++ b/README.md @@ -223,16 +223,17 @@ For examples: > **NOTE:** In the following conventional paths for examples, `` and `` include the provider prefix as well, but the provider prefix is **NOT** included in``. > For example, the data source [`caller_identity`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) in the `aws` provider would have an "example" conventional path of: `examples/data-sources/aws_caller_identity/data-source.tf` -| Path | Description | -|---------------------------------------------------------------------------|--------------------------------------| -| `examples/` | Root of examples | -| `examples/provider/provider.tf` | Provider example config | -| `examples/data-sources//data-source.tf` | Data source example config | -| `examples/ephemeral-resources//ephemeral-resource.tf` | Ephemeral resource example config | -| `examples/functions//function.tf` | Function example config | -| `examples/resources//resource.tf` | Resource example config | -| `examples/resources//import.sh` | Resource example import command | -| `examples/resources//import-by-string-id.tf` | Resource example import by id config | +| Path | Description | +|---------------------------------------------------------------------------|--------------------------------------------| +| `examples/` | Root of examples | +| `examples/provider/provider.tf` | Provider example config | +| `examples/data-sources//data-source.tf` | Data source example config | +| `examples/ephemeral-resources//ephemeral-resource.tf` | Ephemeral resource example config | +| `examples/functions//function.tf` | Function example config | +| `examples/resources//resource.tf` | Resource example config | +| `examples/resources//import.sh` | Resource example import command | +| `examples/resources//import-by-string-id.tf` | Resource example import by id config | +| `examples/resources//import-by-identity.tf` | Resource example import by identity config | #### Migration @@ -293,21 +294,24 @@ using the following data fields and functions: ##### Managed Resource / Ephemeral Resource / Data Source Fields -| Field | Type | Description | -|-------------------------|--------|-------------------------------------------------------------------------------------------| -| `.Name` | string | Name of the resource/data-source (ex. `tls_certificate`) | -| `.Type` | string | Either `Resource` or `Data Source` | -| `.Description` | string | Resource / Data Source description | -| `.HasExample` | bool | Is there an example file? | -| `.ExampleFile` | string | Path to the file with the terraform configuration example | -| `.HasImport` | bool | Is there an import shell file? (`terraform import` shell example) | -| `.ImportFile` | string | Path to the file with the command for importing the resource | -| `.HasImportIDConfig` | bool | Is there an import terraform config file? (`import` block example with `id`) | -| `.ImportIDConfigFile` | string | Path to the file with the Terraform configuration for importing the resource by `id` | -| `.ProviderName` | string | Canonical provider name (ex. `terraform-provider-random`) | -| `.ProviderShortName` | string | Short version of the rendered provider name (ex. `random`) | -| `.RenderedProviderName` | string | Value provided via argument `--rendered-provider-name`, otherwise same as `.ProviderName` | -| `.SchemaMarkdown` | string | a Markdown formatted Resource / Data Source Schema definition | +| Field | Type | Description | +|-----------------------------|--------|--------------------------------------------------------------------------------------------| +| `.Name` | string | Name of the resource/data-source (ex. `tls_certificate`) | +| `.Type` | string | Either `Resource` or `Data Source` | +| `.Description` | string | Resource / Data Source description | +| `.HasExample` | bool | Is there an example file? | +| `.ExampleFile` | string | Path to the file with the terraform configuration example | +| `.HasImport` | bool | Is there an import shell file? (`terraform import` shell example) | +| `.ImportFile` | string | Path to the file with the command for importing the resource | +| `.HasImportIDConfig` | bool | Is there an import terraform config file? (`import` block example with `id`) | +| `.ImportIDConfigFile` | string | Path to the file with the Terraform configuration for importing the resource by `id` | +| `.HasImportIdentityConfig` | bool | Is there an import terraform config file? (`import` block example with `identity`) | +| `.ImportIdentityConfigFile` | string | Path to the file with the Terraform configuration for importing the resource by `identity` | +| `.IdentitySchemaMarkdown` | string | a Markdown formatted Resource Identity Schema definition | +| `.ProviderName` | string | Canonical provider name (ex. `terraform-provider-random`) | +| `.ProviderShortName` | string | Short version of the rendered provider name (ex. `random`) | +| `.RenderedProviderName` | string | Value provided via argument `--rendered-provider-name`, otherwise same as `.ProviderName` | +| `.SchemaMarkdown` | string | a Markdown formatted Resource / Data Source Schema definition | ##### Provider-defined Function Fields @@ -360,16 +364,57 @@ This can be autogenerated by running `make generate` or running `go generate ./. ### Acceptance Tests This repo uses the `testscript` [package](https://pkg.go.dev/github.com/rogpeppe/go-internal/testscript) for acceptance testing. - There are two types of acceptance tests: full provider build tests in `tfplugindocs/testdata/scripts/provider-build` and provider schema json tests in `tfplugindocs/testdata/scripts/schema-json`. -Provider build tests run the default `tfplugindocs` command which builds the provider source code and runs Terraform to retrieve the schema. These tests require the full provider source code to build a valid provider binary. - -Schema json tests run the `tfplugindocs` command with the `--providers-schema=` flag to specify a provider schemas json file. This allows the test to skip the provider build and Terraform CLI call, instead using the specified file to generate docs. +Provider [build tests](./cmd/tfplugindocs/testdata/scripts/provider-build/) run the default `tfplugindocs` command which builds the provider source code and runs Terraform to retrieve the schema. These tests require the full provider source code to build a valid provider binary. +[Schema json](./cmd/tfplugindocs/testdata/scripts/schema-json/) tests run the `tfplugindocs` command with the `--providers-schema=` flag to specify a provider schemas json file. This allows the test to skip the provider build and Terraform CLI call, instead using the specified file to generate docs. You can run `make testacc` to run the full suite of acceptance tests. By default, the provider build acceptance tests will create a temporary directory in `/tmp/tftmp` for testing, but you can change this location in `cmd/tfplugindocs/main_test.go`. The schema json tests uses the `testscript` package's [default work directory](https://pkg.go.dev/github.com/rogpeppe/go-internal/testscript#Params.WorkdirRoot). The test scripts are defined in the `tfplugindocs/testdata/scripts` directory. Each script includes the test, golden files, and the provider source code or schema JSON file needed to run the test. +Each script is a [text archive](https://pkg.go.dev/golang.org/x/tools/txtar). You can install the `txtar` CLI locally by running `go install golang.org/x/exp/cmd/txtar@latest` to extract the files in the test script for debugging or to help with updating. + +For example, to unarchive all of the files from a test script: +```bash +# Assuming that your working directory is the root of the terraform-plugin-docs repo + +# Create a fresh directory to extract to +mkdir tmp && cd tmp + +# Extract this specific test script to the current working directory +txtar -x <../cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar +``` + +#### New test scripts + +Updates to existing tests are typically just made manually, but the `txtar` CLI can be used to create a new test quickly. + +A new text archive can be created from a folder with: +```bash +# Assuming that your working directory is the root of the terraform-plugin-docs repo + +# Create a fresh directory to make changes to +mkdir tmp && cd tmp + +# Update files in ./tmp that you want in the new .txtar + +# Archives all of the files in the current directory with a placeholder comment +echo "placeholder comment" | txtar . >../cmd/tfplugindocs/testdata/scripts/provider-build/generate/new.txtar +``` -Each script is a [text archive](https://pkg.go.dev/golang.org/x/tools/txtar). You can install the `txtar` CLI locally by running `go install golang.org/x/exp/cmd/txtar@latest` to extract the files in the test script for debugging. -You can also use `txtar` CLI archive files into the `.txtar` format to create new tests or modify existing ones. +Once a new text archive is created, the comment header can be replaced with [test script commands](https://pkg.go.dev/github.com/rogpeppe/go-internal/testscript) +like `env`, `cmp`, `exec`, etc. These commands control what actually is run during the test along with the assertions, for example: +```bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +# Successful run of tfplugindocs on a Framework provider with examples but no templates or pre-existing docs. +[!unix] skip +env GOCACHE=$WORK/gocache # sets an environment variable +env GOMODCACHE=$WORK/gomodcache # sets an environment variable +exec tfplugindocs --provider-name=terraform-provider-scaffolding # executes the Go binary for generating documentation +cmp stdout expected-output.txt # compares stdout from binary with the golden file in the text archive below +cmp docs/index.md expected-index.md # compares the generated docs with the golden file in the text archive below +cmp docs/data-sources/example.md expected-datasource.md # compares the generated docs with the golden file in the text archive below +cmp docs/resources/example.md expected-resource.md # compares the generated docs with the golden file in the text archive below +``` \ No newline at end of file diff --git a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar index e7a5ccbf..6cad31f7 100644 --- a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar @@ -146,6 +146,20 @@ HasImport: true ImportFile: $WORK/examples/resources/scaffolding_example/import.sh HasImportIDConfig: true ImportIDConfigFile: $WORK/examples/resources/scaffolding_example/import-by-string-id.tf +HasImportIdentityConfig: true +ImportIdentityConfigFile: $WORK/examples/resources/scaffolding_example/import-by-identity.tf +IdentitySchemaMarkdown: +### Identity Schema + +#### Required + +- `name` (String) Name of resource. + +#### Optional + +- `project` (String) Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable. +- `region` (String) Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable. + ProviderName: terraform-provider-scaffolding ProviderShortName: scaffolding RenderedProviderName: terraform-provider-scaffolding @@ -309,6 +323,9 @@ HasImport: {{.HasImport}} ImportFile: {{.ImportFile}} HasImportIDConfig: {{.HasImportIDConfig}} ImportIDConfigFile: {{.ImportIDConfigFile}} +HasImportIdentityConfig: {{.HasImportIdentityConfig}} +ImportIdentityConfigFile: {{.ImportIdentityConfigFile}} +IdentitySchemaMarkdown: {{.IdentitySchemaMarkdown}} ProviderName: {{.ProviderName}} ProviderShortName: {{.ProviderShortName}} RenderedProviderName: {{.RenderedProviderName}} @@ -381,6 +398,19 @@ import { id = "id-123" } +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} +-- examples/resources/scaffolding_example/import-by-identity.tf -- +import { + to = scaffolding_example.example + identity = { + name = "resource-abc" + project = "test-project-123" + region = "us-east-2" + } +} + resource "scaffolding_example" "example" { configurable_attribute = "some-value" } @@ -509,6 +539,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/identityschema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" @@ -520,6 +551,7 @@ import ( // Ensure provider defined types fully satisfy framework interfaces. var _ resource.Resource = &ExampleResource{} var _ resource.ResourceWithImportState = &ExampleResource{} +var _ resource.ResourceWithIdentity = &ExampleResource{} func NewExampleResource() resource.Resource { return &ExampleResource{} @@ -537,10 +569,36 @@ type ExampleResourceModel struct { Id types.String `tfsdk:"id"` } +// ExampleResourceIdentityModel describes the resource identity data model. +type ExampleResourceIdentityModel struct { + Name types.String `tfsdk:"name"` + Project types.String `tfsdk:"project"` + Region types.String `tfsdk:"region"` +} + func (r *ExampleResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_example" } +func (r *ExampleResource) IdentitySchema(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) { + resp.IdentitySchema = identityschema.Schema{ + Attributes: map[string]identityschema.Attribute{ + "name": identityschema.StringAttribute{ + RequiredForImport: true, + Description: "Name of resource.", + }, + "project": identityschema.StringAttribute{ + OptionalForImport: true, + Description: "Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable.", + }, + "region": identityschema.StringAttribute{ + OptionalForImport: true, + Description: "Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable.", + }, + }, + } +} + func (r *ExampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ // This description is used by the documentation generator and the language server. @@ -610,6 +668,13 @@ func (r *ExampleResource) Create(ctx context.Context, req resource.CreateRequest // save into the Terraform state. data.Id = types.StringValue("example-id") + // Create identity and store in Terraform state + resp.Diagnostics.Append(resp.Identity.Set(ctx, ExampleResourceIdentityModel{ + Name: types.StringValue("resource-abc"), + Project: types.StringValue("test-project-123"), + Region: types.StringValue("us-east-2"), + })...) + // Write logs using the tflog package // Documentation: https://terraform.io/plugin/log tflog.Trace(ctx, "created a resource") @@ -682,7 +747,7 @@ func (r *ExampleResource) Delete(ctx context.Context, req resource.DeleteRequest } func (r *ExampleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) + resource.ImportStatePassthroughWithIdentity(ctx, path.Root("id"), path.Root("name"), req, resp) } -- internal/provider/provider.go -- // Copyright (c) HashiCorp, Inc. @@ -824,75 +889,85 @@ testacc: -- go.mod -- module github.com/hashicorp/terraform-provider-scaffolding-framework -go 1.19 +go 1.23.0 + +toolchain go1.23.7 require ( - github.com/hashicorp/terraform-plugin-framework v1.4.2 + github.com/hashicorp/terraform-plugin-framework v1.15.0 github.com/hashicorp/terraform-plugin-log v0.9.0 ) require ( github.com/fatih/color v1.13.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect - github.com/hashicorp/go-plugin v1.5.1 // indirect + github.com/hashicorp/go-plugin v1.6.3 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/terraform-plugin-go v0.19.0 // indirect - github.com/hashicorp/terraform-registry-address v0.2.2 // indirect + github.com/hashicorp/terraform-plugin-go v0.27.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.5 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect - github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/oklog/run v1.0.0 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect - google.golang.org/grpc v1.57.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/grpc v1.72.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect ) -- go.sum -- github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-plugin v1.5.1 h1:oGm7cWBaYIp3lJpx1RUEfLWophprE2EV/KUeqBYo+6k= -github.com/hashicorp/go-plugin v1.5.1/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= +github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= +github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/terraform-plugin-framework v1.4.2 h1:P7a7VP1GZbjc4rv921Xy5OckzhoiO3ig6SGxwelD2sI= -github.com/hashicorp/terraform-plugin-framework v1.4.2/go.mod h1:GWl3InPFZi2wVQmdVnINPKys09s9mLmTZr95/ngLnbY= -github.com/hashicorp/terraform-plugin-go v0.19.0 h1:BuZx/6Cp+lkmiG0cOBk6Zps0Cb2tmqQpDM3iAtnhDQU= -github.com/hashicorp/terraform-plugin-go v0.19.0/go.mod h1:EhRSkEPNoylLQntYsk5KrDHTZJh9HQoumZXbOGOXmec= +github.com/hashicorp/terraform-plugin-framework v1.15.0 h1:LQ2rsOfmDLxcn5EeIwdXFtr03FVsNktbbBci8cOKdb4= +github.com/hashicorp/terraform-plugin-framework v1.15.0/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI= +github.com/hashicorp/terraform-plugin-go v0.27.0 h1:ujykws/fWIdsi6oTUT5Or4ukvEan4aN9lY+LOxVP8EE= +github.com/hashicorp/terraform-plugin-go v0.27.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-registry-address v0.2.2 h1:lPQBg403El8PPicg/qONZJDC6YlgCVbWDtNmmZKtBno= -github.com/hashicorp/terraform-registry-address v0.2.2/go.mod h1:LtwNbCihUoUZ3RYriyS2wF/lGPB6gF9ICLRtuDk7hSo= +github.com/hashicorp/terraform-registry-address v0.2.5 h1:2GTftHqmUhVOeuu9CW3kwDkRe4pcBDq0uuK5VJngU1M= +github.com/hashicorp/terraform-registry-address v0.2.5/go.mod h1:PpzXWINwB5kuVS5CA7m1+eO2f1jKb5ZDIxrOPfpnGkg= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= @@ -900,35 +975,43 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.57.1 h1:upNTNqv0ES+2ZOOqACwVtS3Il8M12/+Hz41RCPzAjQg= -google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar index 7c30ad2f..6a13f4c6 100644 --- a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar @@ -127,6 +127,35 @@ resource "scaffolding_example" "example" { Import is supported using the following syntax: +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute, for example: + +```terraform +import { + to = scaffolding_example.example + identity = { + name = "resource-abc" + project = "test-project-123" + region = "us-east-2" + } +} + +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} +``` + + +### Identity Schema + +#### Required + +- `name` (String) Name of resource. + +#### Optional + +- `project` (String) Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable. +- `region` (String) Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable. + In Terraform v1.5.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `id` attribute, for example: ```terraform @@ -163,6 +192,19 @@ data "scaffolding_example" "example" { provider "scaffolding" { # example configuration here } +-- examples/resources/scaffolding_example/import-by-identity.tf -- +import { + to = scaffolding_example.example + identity = { + name = "resource-abc" + project = "test-project-123" + region = "us-east-2" + } +} + +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} -- examples/resources/scaffolding_example/import-by-string-id.tf -- import { to = scaffolding_example.example @@ -297,6 +339,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/identityschema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" @@ -308,6 +351,7 @@ import ( // Ensure provider defined types fully satisfy framework interfaces. var _ resource.Resource = &ExampleResource{} var _ resource.ResourceWithImportState = &ExampleResource{} +var _ resource.ResourceWithIdentity = &ExampleResource{} func NewExampleResource() resource.Resource { return &ExampleResource{} @@ -325,10 +369,36 @@ type ExampleResourceModel struct { Id types.String `tfsdk:"id"` } +// ExampleResourceIdentityModel describes the resource identity data model. +type ExampleResourceIdentityModel struct { + Name types.String `tfsdk:"name"` + Project types.String `tfsdk:"project"` + Region types.String `tfsdk:"region"` +} + func (r *ExampleResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_example" } +func (r *ExampleResource) IdentitySchema(ctx context.Context, req resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) { + resp.IdentitySchema = identityschema.Schema{ + Attributes: map[string]identityschema.Attribute{ + "name": identityschema.StringAttribute{ + RequiredForImport: true, + Description: "Name of resource.", + }, + "project": identityschema.StringAttribute{ + OptionalForImport: true, + Description: "Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable.", + }, + "region": identityschema.StringAttribute{ + OptionalForImport: true, + Description: "Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable.", + }, + }, + } +} + func (r *ExampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ // This description is used by the documentation generator and the language server. @@ -398,6 +468,13 @@ func (r *ExampleResource) Create(ctx context.Context, req resource.CreateRequest // save into the Terraform state. data.Id = types.StringValue("example-id") + // Create identity and store in Terraform state + resp.Diagnostics.Append(resp.Identity.Set(ctx, ExampleResourceIdentityModel{ + Name: types.StringValue("resource-abc"), + Project: types.StringValue("test-project-123"), + Region: types.StringValue("us-east-2"), + })...) + // Write logs using the tflog package // Documentation: https://terraform.io/plugin/log tflog.Trace(ctx, "created a resource") @@ -470,7 +547,7 @@ func (r *ExampleResource) Delete(ctx context.Context, req resource.DeleteRequest } func (r *ExampleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) + resource.ImportStatePassthroughWithIdentity(ctx, path.Root("id"), path.Root("name"), req, resp) } -- internal/provider/provider.go -- // Copyright (c) HashiCorp, Inc. @@ -612,75 +689,85 @@ testacc: -- go.mod -- module github.com/hashicorp/terraform-provider-scaffolding-framework -go 1.19 +go 1.23.0 + +toolchain go1.23.7 require ( - github.com/hashicorp/terraform-plugin-framework v1.4.2 + github.com/hashicorp/terraform-plugin-framework v1.15.0 github.com/hashicorp/terraform-plugin-log v0.9.0 ) require ( github.com/fatih/color v1.13.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect - github.com/hashicorp/go-plugin v1.5.1 // indirect + github.com/hashicorp/go-plugin v1.6.3 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/terraform-plugin-go v0.19.0 // indirect - github.com/hashicorp/terraform-registry-address v0.2.2 // indirect + github.com/hashicorp/terraform-plugin-go v0.27.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.5 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect - github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/oklog/run v1.0.0 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect - google.golang.org/grpc v1.57.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/grpc v1.72.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect ) -- go.sum -- github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-plugin v1.5.1 h1:oGm7cWBaYIp3lJpx1RUEfLWophprE2EV/KUeqBYo+6k= -github.com/hashicorp/go-plugin v1.5.1/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= +github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= +github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/terraform-plugin-framework v1.4.2 h1:P7a7VP1GZbjc4rv921Xy5OckzhoiO3ig6SGxwelD2sI= -github.com/hashicorp/terraform-plugin-framework v1.4.2/go.mod h1:GWl3InPFZi2wVQmdVnINPKys09s9mLmTZr95/ngLnbY= -github.com/hashicorp/terraform-plugin-go v0.19.0 h1:BuZx/6Cp+lkmiG0cOBk6Zps0Cb2tmqQpDM3iAtnhDQU= -github.com/hashicorp/terraform-plugin-go v0.19.0/go.mod h1:EhRSkEPNoylLQntYsk5KrDHTZJh9HQoumZXbOGOXmec= +github.com/hashicorp/terraform-plugin-framework v1.15.0 h1:LQ2rsOfmDLxcn5EeIwdXFtr03FVsNktbbBci8cOKdb4= +github.com/hashicorp/terraform-plugin-framework v1.15.0/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI= +github.com/hashicorp/terraform-plugin-go v0.27.0 h1:ujykws/fWIdsi6oTUT5Or4ukvEan4aN9lY+LOxVP8EE= +github.com/hashicorp/terraform-plugin-go v0.27.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= -github.com/hashicorp/terraform-registry-address v0.2.2 h1:lPQBg403El8PPicg/qONZJDC6YlgCVbWDtNmmZKtBno= -github.com/hashicorp/terraform-registry-address v0.2.2/go.mod h1:LtwNbCihUoUZ3RYriyS2wF/lGPB6gF9ICLRtuDk7hSo= +github.com/hashicorp/terraform-registry-address v0.2.5 h1:2GTftHqmUhVOeuu9CW3kwDkRe4pcBDq0uuK5VJngU1M= +github.com/hashicorp/terraform-registry-address v0.2.5/go.mod h1:PpzXWINwB5kuVS5CA7m1+eO2f1jKb5ZDIxrOPfpnGkg= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= @@ -688,35 +775,43 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.57.1 h1:upNTNqv0ES+2ZOOqACwVtS3Il8M12/+Hz41RCPzAjQg= -google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar index 93dd75ab..c5cfe008 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar @@ -194,6 +194,20 @@ HasImport: true ImportFile: $WORK/examples/resources/scaffolding_example/import.sh HasImportIDConfig: true ImportIDConfigFile: $WORK/examples/resources/scaffolding_example/import-by-string-id.tf +HasImportIdentityConfig: true +ImportIdentityConfigFile: $WORK/examples/resources/scaffolding_example/import-by-identity.tf +IdentitySchemaMarkdown: +### Identity Schema + +#### Required + +- `name` (String) Name of resource. + +#### Optional + +- `project` (String) Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable. +- `region` (String) Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable. + ProviderName: terraform-provider-scaffolding ProviderShortName: Scaffolding RenderedProviderName: Scaffolding @@ -456,6 +470,9 @@ HasImport: {{.HasImport}} ImportFile: {{.ImportFile}} HasImportIDConfig: {{.HasImportIDConfig}} ImportIDConfigFile: {{.ImportIDConfigFile}} +HasImportIdentityConfig: {{.HasImportIdentityConfig}} +ImportIdentityConfigFile: {{.ImportIdentityConfigFile}} +IdentitySchemaMarkdown: {{.IdentitySchemaMarkdown}} ProviderName: {{.ProviderName}} ProviderShortName: {{.ProviderShortName}} RenderedProviderName: {{.RenderedProviderName}} @@ -597,6 +614,19 @@ import { id = "id-123" } +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} +-- examples/resources/scaffolding_example/import-by-identity.tf -- +import { + to = scaffolding_example.example + identity = { + name = "resource-abc" + project = "test-project-123" # can also be read via SCAFFOLDING_PROJECT environment variable + region = "us-east-2" # can also be read via SCAFFOLDING_REGION environment variable + } +} + resource "scaffolding_example" "example" { configurable_attribute = "some-value" } @@ -652,6 +682,28 @@ terraform import scaffolding_example.example "id-123" } } }, + "resource_identity_schemas": { + "scaffolding_example": { + "version": 0, + "attributes": { + "name": { + "type": "string", + "description": "Name of resource.", + "required_for_import": true + }, + "project": { + "type": "string", + "description": "Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable.", + "optional_for_import": true + }, + "region": { + "type": "string", + "description": "Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable.", + "optional_for_import": true + } + } + } + }, "ephemeral_resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar index 80251b8f..bb1e5961 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar @@ -197,6 +197,35 @@ resource "scaffolding_example" "example" { Import is supported using the following syntax: +In Terraform v1.12.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `identity` attribute, for example: + +```terraform +import { + to = scaffolding_example.example + identity = { + name = "resource-abc" + project = "test-project-123" # can also be read via SCAFFOLDING_PROJECT environment variable + region = "us-east-2" # can also be read via SCAFFOLDING_REGION environment variable + } +} + +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} +``` + + +### Identity Schema + +#### Required + +- `name` (String) Name of resource. + +#### Optional + +- `project` (String) Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable. +- `region` (String) Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable. + In Terraform v1.5.0 and later, the [`import` block](https://developer.hashicorp.com/terraform/language/import) can be used with the `id` attribute, for example: ```terraform @@ -273,6 +302,19 @@ import { id = "id-123" } +resource "scaffolding_example" "example" { + configurable_attribute = "some-value" +} +-- examples/resources/scaffolding_example/import-by-identity.tf -- +import { + to = scaffolding_example.example + identity = { + name = "resource-abc" + project = "test-project-123" # can also be read via SCAFFOLDING_PROJECT environment variable + region = "us-east-2" # can also be read via SCAFFOLDING_REGION environment variable + } +} + resource "scaffolding_example" "example" { configurable_attribute = "some-value" } @@ -335,6 +377,28 @@ resource "scaffolding_example" "example" { } } }, + "resource_identity_schemas": { + "scaffolding_example": { + "version": 0, + "attributes": { + "name": { + "type": "string", + "description": "Name of resource.", + "required_for_import": true + }, + "project": { + "type": "string", + "description": "Project of resource, can also be sourced via `SCAFFOLDING_PROJECT` environment variable.", + "optional_for_import": true + }, + "region": { + "type": "string", + "description": "Region of resource, can also be sourced via `SCAFFOLDING_REGION` environment variable.", + "optional_for_import": true + } + } + } + }, "ephemeral_resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/internal/provider/generate.go b/internal/provider/generate.go index 5fe68a4d..85370946 100644 --- a/internal/provider/generate.go +++ b/internal/provider/generate.go @@ -629,7 +629,7 @@ func (g *generator) renderStaticWebsite(providerSchema *tfjson.ProviderSchema) e if resSchema != nil { tmpl := resourceTemplate(tmplData) - render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Data Source", exampleFilePath, "", "", resSchema) + render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Data Source", exampleFilePath, "", "", "", resSchema, nil) if err != nil { return fmt.Errorf("unable to render data source template %q: %w", rel, err) } @@ -642,13 +642,15 @@ func (g *generator) renderStaticWebsite(providerSchema *tfjson.ProviderSchema) e g.warnf("data source entitled %q, or %q does not exist", shortName, resName) case "resources/": resSchema, resName := resourceSchema(providerSchema.ResourceSchemas, shortName, relFile) + resIdentitySchema := resourceIdentitySchema(providerSchema.ResourceIdentitySchemas, shortName, relFile) exampleFilePath := filepath.Join(g.ProviderExamplesDir(), "resources", resName, "resource.tf") importFilePath := filepath.Join(g.ProviderExamplesDir(), "resources", resName, "import.sh") importIDConfigFilePath := filepath.Join(g.ProviderExamplesDir(), "resources", resName, "import-by-string-id.tf") + importIdentityConfigFilePath := filepath.Join(g.ProviderExamplesDir(), "resources", resName, "import-by-identity.tf") if resSchema != nil { tmpl := resourceTemplate(tmplData) - render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Resource", exampleFilePath, importIDConfigFilePath, importFilePath, resSchema) + render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Resource", exampleFilePath, importIDConfigFilePath, importIdentityConfigFilePath, importFilePath, resSchema, resIdentitySchema) if err != nil { return fmt.Errorf("unable to render resource template %q: %w", rel, err) } @@ -683,7 +685,7 @@ func (g *generator) renderStaticWebsite(providerSchema *tfjson.ProviderSchema) e if resSchema != nil { tmpl := resourceTemplate(tmplData) - render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Ephemeral Resource", exampleFilePath, "", "", resSchema) + render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Ephemeral Resource", exampleFilePath, "", "", "", resSchema, nil) if err != nil { return fmt.Errorf("unable to render ephemeral resource template %q: %w", rel, err) } diff --git a/internal/provider/template.go b/internal/provider/template.go index e77792d1..5912ac7a 100644 --- a/internal/provider/template.go +++ b/internal/provider/template.go @@ -158,7 +158,7 @@ func (t providerTemplate) Render(providerDir, providerName, renderedProviderName }) } -func (t resourceTemplate) Render(providerDir, name, providerName, renderedProviderName, typeName, exampleFile, importIDConfigFile, importCmdFile string, schema *tfjson.Schema) (string, error) { +func (t resourceTemplate) Render(providerDir, name, providerName, renderedProviderName, typeName, exampleFile, importIDConfigFile, importIdentityConfigFile, importCmdFile string, schema *tfjson.Schema, identitySchema *tfjson.IdentitySchema) (string, error) { schemaBuffer := bytes.NewBuffer(nil) err := schemamd.Render(schema, schemaBuffer) if err != nil { @@ -170,6 +170,25 @@ func (t resourceTemplate) Render(providerDir, name, providerName, renderedProvid return "", nil } + hasImportIdentityConfig := importIdentityConfigFile != "" && fileExists(importIdentityConfigFile) + identitySchemaBuffer := bytes.NewBuffer(nil) + + // Always render the identity schema if we have one, so it can be used in custom templates. + if identitySchema != nil { + _, err := io.WriteString(identitySchemaBuffer, schemaComment+"\n") + if err != nil { + return "", fmt.Errorf("unable to render identity schema comment: %w", err) + } + + err = schemamd.RenderIdentitySchema(identitySchema, identitySchemaBuffer) + if err != nil { + return "", fmt.Errorf("unable to render identity schema: %w", err) + } + } else if hasImportIdentityConfig { + // If there is an identity example, but we don't have an identity schema, we should return an error to ensure the example file was intended. + return "", fmt.Errorf("unable to render: an identity import example (%q) was provided for a resource (%q) that does not support resource identity", importIdentityConfigFile, name) + } + return renderStringTemplate(providerDir, "resourceTemplate", s, struct { Type string Name string @@ -184,6 +203,10 @@ func (t resourceTemplate) Render(providerDir, name, providerName, renderedProvid HasImportIDConfig bool ImportIDConfigFile string + HasImportIdentityConfig bool + ImportIdentityConfigFile string + IdentitySchemaMarkdown string + ProviderName string ProviderShortName string @@ -204,6 +227,10 @@ func (t resourceTemplate) Render(providerDir, name, providerName, renderedProvid HasImportIDConfig: importIDConfigFile != "" && fileExists(importIDConfigFile), ImportIDConfigFile: importIDConfigFile, + HasImportIdentityConfig: hasImportIdentityConfig, + ImportIdentityConfigFile: importIdentityConfigFile, + IdentitySchemaMarkdown: identitySchemaBuffer.String(), + ProviderName: providerName, ProviderShortName: providerShortName(renderedProviderName), @@ -294,12 +321,20 @@ description: |- {{- end }} {{ .SchemaMarkdown | trimspace }} -{{- if or .HasImport .HasImportIDConfig }} +{{- if or .HasImport .HasImportIDConfig .HasImportIdentityConfig }} ## Import Import is supported using the following syntax: {{- end }} +{{- if .HasImportIdentityConfig }} + +In Terraform v1.12.0 and later, the [` + "`" + `import` + "`" + ` block](https://developer.hashicorp.com/terraform/language/import) can be used with the ` + "`" + `identity` + "`" + ` attribute, for example: + +{{tffile .ImportIdentityConfigFile }} + +{{ .IdentitySchemaMarkdown | trimspace }} +{{- end }} {{- if .HasImportIDConfig }} In Terraform v1.5.0 and later, the [` + "`" + `import` + "`" + ` block](https://developer.hashicorp.com/terraform/language/import) can be used with the ` + "`" + `id` + "`" + ` attribute, for example: diff --git a/internal/provider/template_test.go b/internal/provider/template_test.go index 3760b94d..d60e3992 100644 --- a/internal/provider/template_test.go +++ b/internal/provider/template_test.go @@ -93,7 +93,7 @@ provider "scaffolding" { }, } - result, err := tpl.Render("testdata/test-provider-dir", "testTemplate", "test-provider", "test-provider", "Resource", "provider.tf", "", "", &schema) + result, err := tpl.Render("testdata/test-provider-dir", "testTemplate", "test-provider", "test-provider", "Resource", "provider.tf", "", "", "", &schema, nil) if err != nil { t.Error(err) } diff --git a/internal/provider/util.go b/internal/provider/util.go index bcb8084d..8a879cfa 100644 --- a/internal/provider/util.go +++ b/internal/provider/util.go @@ -89,6 +89,19 @@ func resourceSchema(schemas map[string]*tfjson.Schema, providerShortName, templa return nil, resName } +func resourceIdentitySchema(schemas map[string]*tfjson.IdentitySchema, providerShortName, templateFileName string) *tfjson.IdentitySchema { + resName := providerShortName + "_" + removeAllExt(templateFileName) + if schema, ok := schemas[resName]; ok { + return schema + } + + if schema, ok := schemas[providerShortName]; ok { + return schema + } + + return nil +} + func writeFile(path string, data string) error { dir, _ := filepath.Split(path) diff --git a/internal/schemamd/render.go b/internal/schemamd/render.go index 5033c6ac..cc5cdc45 100644 --- a/internal/schemamd/render.go +++ b/internal/schemamd/render.go @@ -6,6 +6,7 @@ package schemamd import ( "fmt" "io" + "slices" "sort" "strings" @@ -35,6 +36,122 @@ func Render(schema *tfjson.Schema, w io.Writer) error { return nil } +func RenderIdentitySchema(identitySchema *tfjson.IdentitySchema, w io.Writer) error { + _, err := io.WriteString(w, "### Identity Schema\n\n") + if err != nil { + return err + } + + err = writeIdentitySchemaAttributes(w, identitySchema.Attributes) + if err != nil { + return fmt.Errorf("unable to render identity schema: %w", err) + } + + return nil +} + +func writeIdentitySchemaAttributes(w io.Writer, attrs map[string]*tfjson.IdentityAttribute) error { + attrNames := []string{} + for n := range attrs { + attrNames = append(attrNames, n) + } + + requiredForImportNames := []string{} + optionalForImportNames := []string{} + for _, name := range attrNames { + attr := attrs[name] + + if attr.RequiredForImport { + requiredForImportNames = append(requiredForImportNames, name) + continue + } + + if attr.OptionalForImport { + optionalForImportNames = append(optionalForImportNames, name) + continue + } + + return fmt.Errorf("invalid schema: for %q attribute, either RequiredForImport for OptionalForImport must be set to true", name) + } + + slices.Sort(requiredForImportNames) + slices.Sort(optionalForImportNames) + + for i, name := range requiredForImportNames { + requiredAttr := attrs[name] + if i == 0 { + _, err := io.WriteString(w, "#### Required\n\n") + if err != nil { + return err + } + } + + err := writeIdentityAttribute(w, name, requiredAttr) + if err != nil { + return fmt.Errorf("unable to render identity attribute %q: %w", name, err) + } + } + + _, err := io.WriteString(w, "\n") + if err != nil { + return err + } + + for i, name := range optionalForImportNames { + optionalAttr := attrs[name] + if i == 0 { + _, err := io.WriteString(w, "#### Optional\n\n") + if err != nil { + return err + } + } + + err := writeIdentityAttribute(w, name, optionalAttr) + if err != nil { + return fmt.Errorf("unable to render identity attribute %q: %w", name, err) + } + } + + return nil +} + +func writeIdentityAttribute(w io.Writer, name string, attr *tfjson.IdentityAttribute) error { + _, err := io.WriteString(w, "- `"+name+"` ") + if err != nil { + return err + } + + _, err = io.WriteString(w, "(") + if err != nil { + return err + } + + err = WriteType(w, attr.IdentityType) + if err != nil { + return err + } + + _, err = io.WriteString(w, ")") + if err != nil { + return err + } + + desc := strings.TrimSpace(attr.Description) + if desc != "" { + _, err = io.WriteString(w, " "+desc) + if err != nil { + return err + } + } + + _, err = io.WriteString(w, "\n") + if err != nil { + return err + } + + return nil +} + // Group by Attribute/Block characteristics. type groupFilter struct { topLevelTitle string diff --git a/internal/schemamd/render_test.go b/internal/schemamd/render_test.go index 2cf09eb1..f836d6d7 100644 --- a/internal/schemamd/render_test.go +++ b/internal/schemamd/render_test.go @@ -98,3 +98,56 @@ func TestRender(t *testing.T) { }) } } + +func TestRenderIdentitySchema(t *testing.T) { + t.Parallel() + + for _, c := range []struct { + name string + inputFile string + expectedFile string + }{ + { + "identity", + "testdata/identity.schema.json", + "testdata/identity.md", + }, + } { + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + input, err := os.ReadFile(c.inputFile) + if err != nil { + t.Fatal(err) + } + + expected, err := os.ReadFile(c.expectedFile) + if err != nil { + t.Fatal(err) + } + + var identitySchema tfjson.IdentitySchema + + err = json.Unmarshal(input, &identitySchema) + if err != nil { + t.Fatal(err) + } + + b := &strings.Builder{} + err = schemamd.RenderIdentitySchema(&identitySchema, b) + if err != nil { + t.Fatal(err) + } + + // Remove \r characters so tests don't fail on windows + expectedStr := strings.ReplaceAll(string(expected), "\r", "") + + // Remove trailing newlines before comparing (some text editors remove them). + expectedStr = strings.TrimRight(expectedStr, "\n") + actual := strings.TrimRight(b.String(), "\n") + if diff := cmp.Diff(expectedStr, actual); diff != "" { + t.Fatalf("Unexpected diff (-wanted, +got): %s", diff) + } + }) + } +} diff --git a/internal/schemamd/testdata/identity.md b/internal/schemamd/testdata/identity.md new file mode 100644 index 00000000..62c46778 --- /dev/null +++ b/internal/schemamd/testdata/identity.md @@ -0,0 +1,14 @@ +### Identity Schema + +#### Required + +- `bool_attribute` (Boolean) example bool attribute +- `list_of_bools_attribute` (List of Boolean) example list attribute with bool elements +- `list_of_strings_attribute` (List of String) example list attribute with string elements +- `string_attribute` (String) example string attribute + +#### Optional + +- `float64_attribute` (Number) example float64 attribute +- `int64_attribute` (Number) example int64 attribute +- `number_attribute` (Number) example number attribute diff --git a/internal/schemamd/testdata/identity.schema.json b/internal/schemamd/testdata/identity.schema.json new file mode 100644 index 00000000..02561fa4 --- /dev/null +++ b/internal/schemamd/testdata/identity.schema.json @@ -0,0 +1,46 @@ +{ + "version": 0, + "attributes": { + "float64_attribute": { + "type": "number", + "description": "example float64 attribute", + "optional_for_import": true + }, + "number_attribute": { + "type": "number", + "description": "example number attribute", + "optional_for_import": true + }, + "list_of_strings_attribute": { + "type": [ + "list", + "string" + ], + "description": "example list attribute with string elements", + "required_for_import": true + }, + "bool_attribute": { + "type": "bool", + "description": "example bool attribute", + "required_for_import": true + }, + "string_attribute": { + "type": "string", + "description": "example string attribute", + "required_for_import": true + }, + "int64_attribute": { + "type": "number", + "description": "example int64 attribute", + "optional_for_import": true + }, + "list_of_bools_attribute": { + "type": [ + "list", + "bool" + ], + "description": "example list attribute with bool elements", + "required_for_import": true + } + } +} \ No newline at end of file