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 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.