github.com/opentofu/opentofu@v1.7.1/internal/plugin/serve.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package plugin
     7  
     8  import (
     9  	"github.com/hashicorp/go-plugin"
    10  	proto "github.com/opentofu/opentofu/internal/tfplugin5"
    11  )
    12  
    13  const (
    14  	// The constants below are the names of the plugins that can be dispensed
    15  	// from the plugin server.
    16  	ProviderPluginName    = "provider"
    17  	ProvisionerPluginName = "provisioner"
    18  
    19  	// DefaultProtocolVersion is the protocol version assumed for legacy clients that don't specify
    20  	// a particular version during their handshake. This is the version used when Terraform 0.10
    21  	// and 0.11 launch plugins that were built with support for both versions 4 and 5, and must
    22  	// stay unchanged at 4 until we intentionally build plugins that are not compatible with 0.10 and
    23  	// 0.11.
    24  	DefaultProtocolVersion = 4
    25  )
    26  
    27  // Handshake is the HandshakeConfig used to configure clients and servers.
    28  var Handshake = plugin.HandshakeConfig{
    29  	// The ProtocolVersion is the version that must match between TF core
    30  	// and TF plugins. This should be bumped whenever a change happens in
    31  	// one or the other that makes it so that they can't safely communicate.
    32  	// This could be adding a new interface value, it could be how
    33  	// helper/schema computes diffs, etc.
    34  	ProtocolVersion: DefaultProtocolVersion,
    35  
    36  	// The magic cookie values should NEVER be changed.
    37  	MagicCookieKey:   "TF_PLUGIN_MAGIC_COOKIE",
    38  	MagicCookieValue: "d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d6991ca9872b2",
    39  }
    40  
    41  type GRPCProviderFunc func() proto.ProviderServer
    42  type GRPCProvisionerFunc func() proto.ProvisionerServer
    43  
    44  // ServeOpts are the configurations to serve a plugin.
    45  type ServeOpts struct {
    46  	// Wrapped versions of the above plugins will automatically shimmed and
    47  	// added to the GRPC functions when possible.
    48  	GRPCProviderFunc    GRPCProviderFunc
    49  	GRPCProvisionerFunc GRPCProvisionerFunc
    50  }
    51  
    52  // Serve serves a plugin. This function never returns and should be the final
    53  // function called in the main function of the plugin.
    54  func Serve(opts *ServeOpts) {
    55  	plugin.Serve(&plugin.ServeConfig{
    56  		HandshakeConfig:  Handshake,
    57  		VersionedPlugins: pluginSet(opts),
    58  		GRPCServer:       plugin.DefaultGRPCServer,
    59  	})
    60  }
    61  
    62  func pluginSet(opts *ServeOpts) map[int]plugin.PluginSet {
    63  	plugins := map[int]plugin.PluginSet{}
    64  
    65  	// add the new protocol versions if they're configured
    66  	if opts.GRPCProviderFunc != nil || opts.GRPCProvisionerFunc != nil {
    67  		plugins[5] = plugin.PluginSet{}
    68  		if opts.GRPCProviderFunc != nil {
    69  			plugins[5]["provider"] = &GRPCProviderPlugin{
    70  				GRPCProvider: opts.GRPCProviderFunc,
    71  			}
    72  		}
    73  		if opts.GRPCProvisionerFunc != nil {
    74  			plugins[5]["provisioner"] = &GRPCProvisionerPlugin{
    75  				GRPCProvisioner: opts.GRPCProvisionerFunc,
    76  			}
    77  		}
    78  	}
    79  	return plugins
    80  }