| // Copyright IBM Corp. 2014, 2026 | |
| // SPDX-License-Identifier: BUSL-1.1 | |
| package plugin | |
| import ( | |
| "github.com/hashicorp/go-plugin" | |
| proto "github.com/hashicorp/terraform/internal/tfplugin5" | |
| ) | |
| const ( | |
| // The constants below are the names of the plugins that can be dispensed | |
| // from the plugin server. | |
| ProviderPluginName = "provider" | |
| ProvisionerPluginName = "provisioner" | |
| // DefaultProtocolVersion is the protocol version assumed for legacy clients that don't specify | |
| // a particular version during their handshake. This is the version used when Terraform 0.10 | |
| // and 0.11 launch plugins that were built with support for both versions 4 and 5, and must | |
| // stay unchanged at 4 until we intentionally build plugins that are not compatible with 0.10 and | |
| // 0.11. | |
| DefaultProtocolVersion = 4 | |
| ) | |
| // Handshake is the HandshakeConfig used to configure clients and servers. | |
| var Handshake = plugin.HandshakeConfig{ | |
| // The ProtocolVersion is the version that must match between TF core | |
| // and TF plugins. This should be bumped whenever a change happens in | |
| // one or the other that makes it so that they can't safely communicate. | |
| // This could be adding a new interface value, it could be how | |
| // helper/schema computes diffs, etc. | |
| ProtocolVersion: DefaultProtocolVersion, | |
| // The magic cookie values should NEVER be changed. | |
| MagicCookieKey: "TF_PLUGIN_MAGIC_COOKIE", | |
| MagicCookieValue: "d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d6991ca9872b2", | |
| } | |
| type GRPCProviderFunc func() proto.ProviderServer | |
| type GRPCProvisionerFunc func() proto.ProvisionerServer | |
| // ServeOpts are the configurations to serve a plugin. | |
| type ServeOpts struct { | |
| // Wrapped versions of the above plugins will automatically shimmed and | |
| // added to the GRPC functions when possible. | |
| GRPCProviderFunc GRPCProviderFunc | |
| GRPCProvisionerFunc GRPCProvisionerFunc | |
| } | |
| // Serve serves a plugin. This function never returns and should be the final | |
| // function called in the main function of the plugin. | |
| func Serve(opts *ServeOpts) { | |
| plugin.Serve(&plugin.ServeConfig{ | |
| HandshakeConfig: Handshake, | |
| VersionedPlugins: pluginSet(opts), | |
| GRPCServer: plugin.DefaultGRPCServer, | |
| }) | |
| } | |
| func pluginSet(opts *ServeOpts) map[int]plugin.PluginSet { | |
| plugins := map[int]plugin.PluginSet{} | |
| // add the new protocol versions if they're configured | |
| if opts.GRPCProviderFunc != nil || opts.GRPCProvisionerFunc != nil { | |
| plugins[5] = plugin.PluginSet{} | |
| if opts.GRPCProviderFunc != nil { | |
| plugins[5]["provider"] = &GRPCProviderPlugin{ | |
| GRPCProvider: opts.GRPCProviderFunc, | |
| } | |
| } | |
| if opts.GRPCProvisionerFunc != nil { | |
| plugins[5]["provisioner"] = &GRPCProvisionerPlugin{ | |
| GRPCProvisioner: opts.GRPCProvisionerFunc, | |
| } | |
| } | |
| } | |
| return plugins | |
| } |