Terraform
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
with an instance of the mux server, instead of declaring the provider with other TestCase
fields such as ProviderFactories
.
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.