Combining Protocol Version 6 Providers
The tf6muxserver
package enables combining any number of protocol version 6 provider servers into a single server.
Use this package to:
- Support multiple development teams across separate codebases.
- Support multiple provider SDK implementations. For example, you could upgrade an existing terraform-plugin-sdk/v2 provider to protocol version 6 and then combine it with one or more providers built with terraform-plugin-framework.
Compatibility
Protocol version 6 provider servers are compatible with Terraform CLI 1.0 and later.
The following provider server implementations are supported:
- terraform-plugin-framework: A higher-level SDK that makes Terraform provider development easier by abstracting implementation details.
- terraform-plugin-go tf6server: A lower-level SDK to develop Terraform providers for more advanced use cases.
- tf5to6server: A package to translate protocol version 5 providers into protocol version 6.
Requirements
To be combined, provider servers must meet the following requirements:
- All provider schemas must match.
- All provider meta schemas must match.
- Only one provider may implement each resource and data source.
If publishing to the Terraform Registry, set metadata.protocol_versions
to ["6.0"]
in the Terraform Registry manifest file.
Code Implementation
Use the tf6muxserver.NewMuxServer()
function to create a combined provider server. Most providers implement this in the provider main()
function of the root directory main.go
file or within a shared internal package to enable testing for the combined provider. You can use tf6server.WithManagedDebug()
to enable debugger support.
The following example implements tf6muxserver.NewMuxServer()
in a main()
function.
package main
import (
"context"
"flag"
"log"
"github.com/example/terraform-provider-example/internal/provider1"
"github.com/example/terraform-provider-example/internal/provider2"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-go/tfprotov6/tf6server"
"github.com/hashicorp/terraform-plugin-mux/tf6muxserver"
)
var (
// Version can be updated by goreleaser on release
version string = "dev"
)
func main() {
debugFlag := flag.Bool("debug", false, "Start provider in debug mode.")
flag.Parse()
ctx := context.Background()
providers := []func() tfprotov6.ProviderServer{
// Example terraform-plugin-framework providers
providerserver.NewProtocol6(provider1.New("test")())
providerserver.NewProtocol6(provider2.New("test")())
}
muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)
if err != nil {
log.Fatal(err)
}
var serveOpts []tf6server.ServeOpt
if *debugFlag {
serveOpts = append(serveOpts, tf6server.WithManagedDebug())
}
err = tf6server.Serve(
"registry.terraform.io/example/example",
muxServer.ProviderServer,
serveOpts...,
)
if err != nil {
log.Fatal(err)
}
}
Testing Implementation
You can test individual providers using the same acceptance tests as before. Set the ProtoV6ProviderFactories
field of TestCase
to use the acceptance testing framework available in terraform-provider-sdk/v2/helper/resource.
The following example uses the acceptance testing framework to create a test for two providers.
resource.Test(t, resource.TestCase{
// ... other TestCase fields ...
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error) {
"example": func() (tfprotov6.ProviderServer, error) {
ctx := context.Background()
providers := []func() tfprotov6.ProviderServer{
// Example terraform-plugin-framework providers
providerserver.NewProtocol6(provider1.New("test")())
providerserver.NewProtocol6(provider2.New("test")())
}
muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...)
if err != nil {
return nil, err
}
return muxServer.ProviderServer(), nil
},
},
})
Refer to the acceptance tests documentation for more details.