summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/go-plugin/grpc_client.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-plugin/grpc_client.go')
-rw-r--r--vendor/github.com/hashicorp/go-plugin/grpc_client.go107
1 files changed, 107 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_client.go b/vendor/github.com/hashicorp/go-plugin/grpc_client.go
new file mode 100644
index 000000000..44294d0d3
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/grpc_client.go
@@ -0,0 +1,107 @@
+package plugin
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net"
+ "time"
+
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/health/grpc_health_v1"
+)
+
+func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn, error)) (*grpc.ClientConn, error) {
+ // Build dialing options.
+ opts := make([]grpc.DialOption, 0, 5)
+
+ // We use a custom dialer so that we can connect over unix domain sockets
+ opts = append(opts, grpc.WithDialer(dialer))
+
+ // go-plugin expects to block the connection
+ opts = append(opts, grpc.WithBlock())
+
+ // Fail right away
+ opts = append(opts, grpc.FailOnNonTempDialError(true))
+
+ // If we have no TLS configuration set, we need to explicitly tell grpc
+ // that we're connecting with an insecure connection.
+ if tls == nil {
+ opts = append(opts, grpc.WithInsecure())
+ } else {
+ opts = append(opts, grpc.WithTransportCredentials(
+ credentials.NewTLS(tls)))
+ }
+
+ // Connect. Note the first parameter is unused because we use a custom
+ // dialer that has the state to see the address.
+ conn, err := grpc.Dial("unused", opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ return conn, nil
+}
+
+// newGRPCClient creates a new GRPCClient. The Client argument is expected
+// to be successfully started already with a lock held.
+func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) {
+ conn, err := dialGRPCConn(c.config.TLSConfig, c.dialer)
+ if err != nil {
+ return nil, err
+ }
+
+ // Start the broker.
+ brokerGRPCClient := newGRPCBrokerClient(conn)
+ broker := newGRPCBroker(brokerGRPCClient, c.config.TLSConfig)
+ go broker.Run()
+ go brokerGRPCClient.StartStream()
+
+ return &GRPCClient{
+ Conn: conn,
+ Plugins: c.config.Plugins,
+ doneCtx: doneCtx,
+ broker: broker,
+ }, nil
+}
+
+// GRPCClient connects to a GRPCServer over gRPC to dispense plugin types.
+type GRPCClient struct {
+ Conn *grpc.ClientConn
+ Plugins map[string]Plugin
+
+ doneCtx context.Context
+ broker *GRPCBroker
+}
+
+// ClientProtocol impl.
+func (c *GRPCClient) Close() error {
+ c.broker.Close()
+ return c.Conn.Close()
+}
+
+// ClientProtocol impl.
+func (c *GRPCClient) Dispense(name string) (interface{}, error) {
+ raw, ok := c.Plugins[name]
+ if !ok {
+ return nil, fmt.Errorf("unknown plugin type: %s", name)
+ }
+
+ p, ok := raw.(GRPCPlugin)
+ if !ok {
+ return nil, fmt.Errorf("plugin %q doesn't support gRPC", name)
+ }
+
+ return p.GRPCClient(c.doneCtx, c.broker, c.Conn)
+}
+
+// ClientProtocol impl.
+func (c *GRPCClient) Ping() error {
+ client := grpc_health_v1.NewHealthClient(c.Conn)
+ _, err := client.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{
+ Service: GRPCServiceName,
+ })
+
+ return err
+}