Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tfsdk: Introduce new ProviderServer functions, deprecate existing #294

Merged
merged 2 commits into from Apr 21, 2022

Conversation

bflad
Copy link
Member

@bflad bflad commented Apr 19, 2022

Closes #22 (its technically solved already, this is just cherry on top)

Provider developers have a few reasons to directly need a tfprotov6.ProviderServer implementation:

  • When implementing acceptance testing with terraform-plugin-sdk helper/resource.
  • When using terraform-plugin-mux tf6muxserver.NewMuxServer().
  • When using terraform-plugin-mux tf6to5server.DowngradeServer().

The current NewProtocol6Server(Provider) function enables these use cases, however the implementation is less than ergonomic for provider developers as a wrapping function is required in all cases:

// helper/resource acceptance testing

resource.TestCase{
	ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
		"example": func() (tfprotov6.ProviderServer, error) {
			return tfsdk.NewProtocol6Server(New()), nil
		},
	},
 // ...
}

// tf6muxserver.NewMuxServer()

providers := []func() tfprotov6.ProviderServer{
	func() tfprotov6.ProviderServer {
		return tfsdk.NewProtocol6Server(provider1.New())
	},
	func() tfprotov6.ProviderServer {
		return tfsdk.NewProtocol6Server(provider2.New())
	},
}

muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)

// tf6to5server.DowngradeServer()

downgradeServer, err := tf6to5server.DowngradeServer(ctx, func() tfprotov6.ProviderServer {
	return tfsdk.NewProtocol6Server(provider.New())
})

The new functions simplify these implementations and get provider developers closer to not directly importing terraform-plugin-go (with a few other targeted changes in other projects, such as type aliases), e.g.

// helper/resource acceptance testing

resource.TestCase{
	ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
		"example": tfsdk.NewProtocol6ProviderServerWithError(New()),
	},
 // ...
}

// tf6muxserver.NewMuxServer()

providers := []func() tfprotov6.ProviderServer{
	tfsdk.NewProtocol6ProviderServer(provider1.New()),
  tfsdk.NewProtocol6ProviderServer(provider2.New()),
}

muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)

// tf6to5server.DowngradeServer()

downgradeServer, err := tf6to5server.DowngradeServer(ctx, tfsdk.NewProtocol6ProviderServer(provider.New()))

This change prefers deprecation over straight replacement to give some lead time for various documentation updates across multiple projects.

The naming is less than ideal, however it feels necessary to remain generic instead of picking any particular details related to their current usage (e.g. "NewTestServer") as this can/will change over time. The "Protocol6" naming is important should a new major protocol version 7 be released, which this framework must support.

Reference: #22

Provider developers have a few reasons to directly need a tfprotov6.ProviderServer implementation:

- When implementing acceptance testing with terraform-plugin-sdk helper/resource.
- When using terraform-plugin-mux tf6muxserver.NewMuxServer().
- When using terraform-plugin-mux tf6to5server.DowngradeServer().

The current `NewProtocol6Server(Provider)` function enables these use cases, however the implementation is less than ergonomic for provider developers as a wrapping function is required in all cases:

```go
// helper/resource acceptance testing

resource.TestCase{
	ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
		"example": func() (tfprotov6.ProviderServer, error) {
			return tfsdk.NewProtocol6Server(New()), nil
		},
	},
 // ...
}

// tf6muxserver.NewMuxServer()

providers := []func() tfprotov6.ProviderServer{
	func() tfprotov6.ProviderServer {
		return tfsdk.NewProtocol6Server(provider1.New())
	},
	func() tfprotov6.ProviderServer {
		return tfsdk.NewProtocol6Server(provider2.New())
	},
}

muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)

// tf6to5server.DowngradeServer()

downgradeServer, err := tf6to5server.DowngradeServer(ctx, func() tfprotov6.ProviderServer {
	return tfsdk.NewProtocol6Server(provider.New())
})
```

The new functions simplify these implementations and get provider developers closer to not directly importing terraform-plugin-go (with a few other targeted changes, such as type aliases), e.g.

```go
// helper/resource acceptance testing

resource.TestCase{
	ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
		"example": tfsdk.NewProtocol6ProviderServerWithError(New()),
	},
 // ...
}

// tf6muxserver.NewMuxServer()

providers := []func() tfprotov6.ProviderServer{
	tfsdk.NewProtocol6ProviderServer(provider1.New()),
  tfsdk.NewProtocol6ProviderServer(provider2.New()),
}

muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)

// tf6to5server.DowngradeServer()

downgradeServer, err := tf6to5server.DowngradeServer(ctx, tfsdk.NewProtocol6ProviderServer(provider.New()))
```

This change prefers deprecation over straight replacement to give some lead time for various documentation updates across multiple projects.

The naming is less than ideal, however it feels necessary to remain generic instead of picking any particular details related to their current usage (e.g. "NewTestServer") as this can/will change over time. The "Protocol6" naming is important should a new major protocol version 7 be released, which this framework must support.
@bflad bflad added the enhancement New feature or request label Apr 19, 2022
@bflad bflad added this to the v0.7.0 milestone Apr 19, 2022
@bflad bflad requested a review from a team as a code owner April 19, 2022 16:14
Copy link
Contributor

@detro detro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines +42 to +43
// Deprecated: Use NewProtocol6ProviderServer instead. This will be removed
// in an upcoming minor version before v1.0.0.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to ask if we really need to do this deprecation phase, but I did a quick GitHub global code search, and while it's in the order of ~70 usages, and it includes the HashiCorp repos, it's still 70 usages.

Yep, deprecation first it is.

@bflad bflad merged commit c8d1dc3 into main Apr 21, 2022
@bflad bflad deleted the bflad-ProviderServer-func-implementations branch April 21, 2022 13:45
bflad added a commit that referenced this pull request Apr 21, 2022
bflad added a commit to hashicorp/terraform-website that referenced this pull request Apr 21, 2022
@bflad
Copy link
Member Author

bflad commented Apr 21, 2022

Associated terraform.io update: hashicorp/terraform-website#2256

bflad added a commit that referenced this pull request Apr 21, 2022
bflad added a commit that referenced this pull request Apr 27, 2022
Reference: #215
Reference: #294
Reference: #296

This change represents the first half of the work necessary to extract the `tfprotov6.ProviderServer` implementation and helper functions out of the `tfsdk` package and into separate packages. The `providerserver` package will be the provider developer facing functionality, while the next iteration of this refactoring will move the actual server implementation into a separate internal package. Once in that separate internal package, efforts can be made to make that code handle terraform-plugin-go type conversions "at the edge" better.
bflad added a commit that referenced this pull request Apr 28, 2022
#308)

Reference: #215
Reference: #294
Reference: #296

This change represents the first half of the work necessary to extract the `tfprotov6.ProviderServer` implementation and helper functions out of the `tfsdk` package and into separate packages. The `providerserver` package will be the provider developer facing functionality, while the next iteration of this refactoring will move the actual server implementation into a separate internal package. Once in that separate internal package, efforts can be made to make that code handle terraform-plugin-go type conversions "at the edge" better.
bflad added a commit to hashicorp/terraform-website that referenced this pull request Apr 28, 2022
@github-actions
Copy link

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support muxing with SDKv2
2 participants