hashicorp / hashicorp/terraform-plugin-framework
Consider Helper Method for User-Agent HTTP Header with Terraform Version and TF_APPEND_USER_AGENT
- Dominant language
- Go
- Stars
- 384
- Forks
- 107
- Avg merge
- 3m
- Merged PRs (30d)
- 1
Description
### Module version
```
v0.6.0
```
### Use-cases
APIs may wish to aggregate metrics on how many HTTP requests are coming from Terraform as compared to other sources. Conventionally, this is accomplished by providers adding Terraform product and version information to the `User-Agent` HTTP request header, then the APIs can perform analytics against that received header information.
Certain environments may also wish to include additional build/automation information in that data. There is an environment variable, `TF_APPEND_USER_AGENT`, that is conventionally implemented by Terraform CLI and terraform-plugin-sdk/v2's [`(helper/schema.Provider).UserAgent()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema#Provider.UserAgent) helper method.
Similar functionality should be made available to providers using this framework, so they can easily create `User-Agent` HTTP request headers in their vendor SDKs.
### Attempted Solutions
Providers using this framework today can manually inspect the `TF_APPEND_USER_AGENT` environment variable for any value. Providers can also access the Terraform CLI version via the [`tfsdk.ConfigureProviderRequest.TerraformVersion`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/tfsdk#ConfigureProviderRequest) field, although the provider would be responsible for passing that information in a format for `User-Agent` strings, such as prepending `Terraform/` before the version.
### Proposal
A first option would be to create a helper method similar to terraform-plugin-sdk/v2's, which takes in the Terraform version, provider name and version, and automatically adds `TF_APPEND_USER_AGENT` data if set, e.g.
```go
// Outputs: Terraform/{TERRAFORM_VERSION} (+https://www.terraform.io) {PROVIDER_NAME}/{PROVIDER_VERSION} {TF_APPEND_USER_AGENT}
func UserAgent(terraformVersion, providerName, providerVersion string) string
```
Another option may be to create a Terraform CLI and TF_APPEND_USER_AGENT specific helper function, such as:
```go
// Outputs: Terraform/{VERSION} (+https://www.terraform.io) {TF_APPEND_USER_AGENT}
func TerraformUserAgent(terraformVersion string) string
```
Which could be implemented in provider configure methods, such as:
```go
tfUserAgent := tfsdk.TerraformUserAgent(req.TerraformVersion)
// Use tfUserAgent with vendor SDK functionality to set User-Agent
```
And leave provider specific User-Agent strings as an exercise for the provider.
A third option may be to create a Terraform CLI and TF_APPEND_USER_AGENT specific helper _method_ on the `ConfigureProviderRequest` type, e.g.
```go
// Outputs: Terraform/{VERSION} (+https://www.terraform.io) {TF_APPEND_USER_AGENT}
func (req ConfigureProviderRequest) TerraformUserAgent() string
```
Where providers would call:
```go
tfUserAgent := req.TerraformUserAgent()
// Use tfUserAgent with vendor SDK functionality to set User-Agent
```
Personally the last option feels like the best solution to not further pollute the `tfsdk` package namespace where it really only can be determined during the provider configure function. If it was ever available in other requests, each of those could also implement this method.
### References
- https://github.com/hashicorp/terraform-plugin-sdk/issues/682
- https://github.com/hashicorp/terraform-plugin-sdk/pull/474
Contributor guide
Assessment
This issue has not been assessed yet.