Description
Module version
N/A
Use-cases
This feature is a follow-up to #1022 once that work is completed.
Once Framework providers are able to generate metadata that is defined by the schema (similar data to the terraform providers schema -json
command today), we should consider allowing provider developers to define arbitrary data related to a resource/data source/provider that can be generated and included in the metadata JSON produced for downstream tools, an implementation that should be covered by #1022. For the specification of the metadata, we should explicitly declare where this arbitrary data will live, so downstream tools know where to expect it, similar to this idea for the code generation spec: hashicorp/terraform-plugin-codegen-spec#75
Once included in the metadata JSON output, this could be consumed by existing ecosystem tooling like terraform-plugin-docs
or by provider-specific tooling.
A concrete example of where this could be useful can be found in the awscc
provider: hashicorp/terraform-provider-awscc#2038
Proposal
As a lot of this relies on #1022, which hasn't been completely designed/implemented, this proposal is speculative
Since this would be at the schema level, we could leverage the Metadata
response to provide this (ex. resource.MetadataResponse
).
To put a straw-man proposal out there, one way to approach this could be accepting any type that implements the json.Marshaler
interface:
type MetadataResponse struct {
// .. other existing fields
// CustomMetadata will generate provider-defined JSON data when creating Provider Metadata documents
CustomMetadata json.Marshaler
}
With that, you could make a simple static metadata JSON marshaler from the map
type (this could also be provided out of the box by terraform-plugin-framework
):
func (r *thingResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_thing"
resp.CustomMetadata = StaticMetadata(
map[string]any{
"create": map[string][]string{
"permissions": {
"access-analyzer:CreateAnalyzer",
"access-analyzer:TagResource",
"iam:CreateServiceLinkedRole",
// etc.
},
},
},
)
}
func StaticMetadata(data map[string]any) staticMetadata {
return staticMetadata{data: data}
}
type staticMetadata struct {
data map[string]any
}
func (s staticMetadata) MarshalJSON() ([]byte, error) {
return json.Marshal(s.data)
}
You could also write a more complex marshaler if defining the data statically isn't preferred, like the case of awscc
, where a lot of the information is already defined in a separate JSON file: https://github.com/hashicorp/terraform-provider-awscc/blob/0c1486c2663aca8d80b347f260f1d140553c939a/internal/service/cloudformation/schemas/AWS_AccessAnalyzer_Analyzer.json#L171-L178