serve the new version 5 grpc plugins
Use the new go-plugin version negotiation to server th appropriate plugin type when the client requests protocol version 5.
This commit is contained in:
parent
ff7d51a9b4
commit
b403023841
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/terraform/plugin/proto"
|
"github.com/hashicorp/terraform/plugin/proto"
|
||||||
"github.com/hashicorp/terraform/providers"
|
"github.com/hashicorp/terraform/providers"
|
||||||
"github.com/hashicorp/terraform/version"
|
"github.com/hashicorp/terraform/version"
|
||||||
|
@ -12,6 +13,25 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GRPCProviderPlugin implements plugin.GRPCPlugin for the go-plugin package.
|
||||||
|
type GRPCProviderPlugin struct {
|
||||||
|
plugin.Plugin
|
||||||
|
GRPCProvider func() proto.ProviderServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GRPCProviderPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
|
return &GRPCProvider{
|
||||||
|
conn: c,
|
||||||
|
client: proto.NewProviderClient(c),
|
||||||
|
ctx: ctx,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GRPCProviderPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
proto.RegisterProviderServer(s, p.GRPCProvider())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GRPCProvider handles the client, or core side of the plugin rpc connection.
|
// GRPCProvider handles the client, or core side of the plugin rpc connection.
|
||||||
// The GRPCProvider methods are mostly a translation layer between the
|
// The GRPCProvider methods are mostly a translation layer between the
|
||||||
// terraform provioders types and the grpc proto types, directly converting
|
// terraform provioders types and the grpc proto types, directly converting
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/terraform/configs/configschema"
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/plugin/proto"
|
"github.com/hashicorp/terraform/plugin/proto"
|
||||||
"github.com/hashicorp/terraform/provisioners"
|
"github.com/hashicorp/terraform/provisioners"
|
||||||
|
@ -14,6 +15,25 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GRPCProvisionerPlugin is the plugin.GRPCPlugin implementation.
|
||||||
|
type GRPCProvisionerPlugin struct {
|
||||||
|
plugin.Plugin
|
||||||
|
GRPCProvisioner func() proto.ProvisionerServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GRPCProvisionerPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
|
return &GRPCProvisioner{
|
||||||
|
conn: c,
|
||||||
|
client: proto.NewProvisionerClient(c),
|
||||||
|
ctx: ctx,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GRPCProvisionerPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
proto.RegisterProvisionerServer(s, p.GRPCProvisioner())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// provisioners.Interface grpc implementation
|
// provisioners.Interface grpc implementation
|
||||||
type GRPCProvisioner struct {
|
type GRPCProvisioner struct {
|
||||||
conn *grpc.ClientConn
|
conn *grpc.ClientConn
|
||||||
|
|
|
@ -9,11 +9,14 @@ import (
|
||||||
|
|
||||||
// ResourceProviderPlugin is the plugin.Plugin implementation.
|
// ResourceProviderPlugin is the plugin.Plugin implementation.
|
||||||
type ResourceProviderPlugin struct {
|
type ResourceProviderPlugin struct {
|
||||||
F func() terraform.ResourceProvider
|
ResourceProvider func() terraform.ResourceProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
|
func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
|
||||||
return &ResourceProviderServer{Broker: b, Provider: p.F()}, nil
|
return &ResourceProviderServer{
|
||||||
|
Broker: b,
|
||||||
|
Provider: p.ResourceProvider(),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ResourceProviderPlugin) Client(
|
func (p *ResourceProviderPlugin) Client(
|
||||||
|
|
|
@ -10,11 +10,14 @@ import (
|
||||||
|
|
||||||
// ResourceProvisionerPlugin is the plugin.Plugin implementation.
|
// ResourceProvisionerPlugin is the plugin.Plugin implementation.
|
||||||
type ResourceProvisionerPlugin struct {
|
type ResourceProvisionerPlugin struct {
|
||||||
F func() terraform.ResourceProvisioner
|
ResourceProvisioner func() terraform.ResourceProvisioner
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
|
func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
|
||||||
return &ResourceProvisionerServer{Broker: b, Provisioner: p.F()}, nil
|
return &ResourceProvisionerServer{
|
||||||
|
Broker: b,
|
||||||
|
Provisioner: p.ResourceProvisioner(),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ResourceProvisionerPlugin) Client(
|
func (p *ResourceProvisionerPlugin) Client(
|
||||||
|
|
|
@ -2,6 +2,8 @@ package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
|
grpcplugin "github.com/hashicorp/terraform/helper/plugin"
|
||||||
|
"github.com/hashicorp/terraform/plugin/proto"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,27 +30,82 @@ var Handshake = plugin.HandshakeConfig{
|
||||||
|
|
||||||
type ProviderFunc func() terraform.ResourceProvider
|
type ProviderFunc func() terraform.ResourceProvider
|
||||||
type ProvisionerFunc func() terraform.ResourceProvisioner
|
type ProvisionerFunc func() terraform.ResourceProvisioner
|
||||||
|
type GRPCProviderFunc func() proto.ProviderServer
|
||||||
|
type GRPCProvisionerFunc func() proto.ProvisionerServer
|
||||||
|
|
||||||
// ServeOpts are the configurations to serve a plugin.
|
// ServeOpts are the configurations to serve a plugin.
|
||||||
type ServeOpts struct {
|
type ServeOpts struct {
|
||||||
ProviderFunc ProviderFunc
|
ProviderFunc ProviderFunc
|
||||||
ProvisionerFunc ProvisionerFunc
|
ProvisionerFunc ProvisionerFunc
|
||||||
|
|
||||||
|
// 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
|
// Serve serves a plugin. This function never returns and should be the final
|
||||||
// function called in the main function of the plugin.
|
// function called in the main function of the plugin.
|
||||||
func Serve(opts *ServeOpts) {
|
func Serve(opts *ServeOpts) {
|
||||||
|
// since the plugins may not yet be aware of the new protocol, we
|
||||||
|
// automatically wrap the plugins in the grpc shims.
|
||||||
|
if opts.GRPCProviderFunc == nil && opts.ProviderFunc != nil {
|
||||||
|
provider := grpcplugin.NewGRPCProviderServerShim(opts.ProviderFunc())
|
||||||
|
// this is almost always going to be a *schema.Provider, but check that
|
||||||
|
// we got back a valid provider just in case.
|
||||||
|
if provider != nil {
|
||||||
|
opts.GRPCProviderFunc = func() proto.ProviderServer {
|
||||||
|
return provider
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opts.GRPCProvisionerFunc == nil && opts.ProvisionerFunc != nil {
|
||||||
|
provider := grpcplugin.NewGRPCProvisionerServerShim(opts.ProvisionerFunc())
|
||||||
|
if provider != nil {
|
||||||
|
opts.GRPCProvisionerFunc = func() proto.ProvisionerServer {
|
||||||
|
return provider
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugin.Serve(&plugin.ServeConfig{
|
plugin.Serve(&plugin.ServeConfig{
|
||||||
HandshakeConfig: Handshake,
|
HandshakeConfig: Handshake,
|
||||||
Plugins: pluginMap(opts),
|
VersionedPlugins: pluginSet(opts),
|
||||||
|
GRPCServer: plugin.DefaultGRPCServer,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// pluginMap returns the map[string]plugin.Plugin to use for configuring a plugin
|
// pluginMap returns the legacy map[string]plugin.Plugin to use for configuring
|
||||||
// server or client.
|
// a plugin server or client.
|
||||||
func pluginMap(opts *ServeOpts) map[string]plugin.Plugin {
|
func pluginMap(opts *ServeOpts) map[string]plugin.Plugin {
|
||||||
return map[string]plugin.Plugin{
|
return map[string]plugin.Plugin{
|
||||||
"provider": &ResourceProviderPlugin{F: opts.ProviderFunc},
|
"provider": &ResourceProviderPlugin{
|
||||||
"provisioner": &ResourceProvisionerPlugin{F: opts.ProvisionerFunc},
|
ResourceProvider: opts.ProviderFunc,
|
||||||
|
},
|
||||||
|
"provisioner": &ResourceProvisionerPlugin{
|
||||||
|
ResourceProvisioner: opts.ProvisionerFunc,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pluginSet(opts *ServeOpts) map[int]plugin.PluginSet {
|
||||||
|
// Set the legacy netrpc plugins at version 4.
|
||||||
|
// The oldest version is returned in when executed by a legacy go-plugin
|
||||||
|
// client.
|
||||||
|
plugins := map[int]plugin.PluginSet{
|
||||||
|
4: pluginMap(opts),
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the new protocol versions if they're configured
|
||||||
|
if opts.GRPCProviderFunc != nil || opts.GRPCProvisionerFunc != nil {
|
||||||
|
plugins[5] = plugin.PluginSet{
|
||||||
|
"provider": &GRPCProviderPlugin{
|
||||||
|
GRPCProvider: opts.GRPCProviderFunc,
|
||||||
|
},
|
||||||
|
"provisioner": &GRPCProvisionerPlugin{
|
||||||
|
GRPCProvisioner: opts.GRPCProvisionerFunc,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return plugins
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue