hashicorp / hashicorp/terraform-plugin-framework

Allow arbitrary provider metadata to be generated for consumption by downstream tooling

Open
#1,047 0 comments 7 reactions 0 assignees View on GitHub
enhancement
Dominant language
Go
Stars
384
Forks
107
Avg merge
3m
Merged PRs (30d)
1

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: https://github.com/hashicorp/terraform-plugin-codegen-spec/issues/75

Once included in the metadata JSON output, this could be consumed by existing ecosystem tooling like [`terraform-plugin-docs`](https://github.com/hashicorp/terraform-plugin-docs) or by provider-specific tooling.

A concrete example of where this could be useful can be found in the `awscc` provider: https://github.com/hashicorp/terraform-provider-awscc/issues/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`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework@v1.12.0/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`](https://pkg.go.dev/encoding/json#Marshaler) interface:

```go
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`):
```go
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

### References
- https://github.com/hashicorp/terraform-provider-awscc/issues/2038
- https://github.com/hashicorp/terraform-provider-awscc/pull/2024

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.