OSDN Git Service

add package
[bytom/vapor.git] / vendor / github.com / hashicorp / go-plugin / grpc_client.go
1 package plugin
2
3 import (
4         "crypto/tls"
5         "fmt"
6         "net"
7         "time"
8
9         "golang.org/x/net/context"
10         "google.golang.org/grpc"
11         "google.golang.org/grpc/credentials"
12         "google.golang.org/grpc/health/grpc_health_v1"
13 )
14
15 func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn, error)) (*grpc.ClientConn, error) {
16         // Build dialing options.
17         opts := make([]grpc.DialOption, 0, 5)
18
19         // We use a custom dialer so that we can connect over unix domain sockets
20         opts = append(opts, grpc.WithDialer(dialer))
21
22         // go-plugin expects to block the connection
23         opts = append(opts, grpc.WithBlock())
24
25         // Fail right away
26         opts = append(opts, grpc.FailOnNonTempDialError(true))
27
28         // If we have no TLS configuration set, we need to explicitly tell grpc
29         // that we're connecting with an insecure connection.
30         if tls == nil {
31                 opts = append(opts, grpc.WithInsecure())
32         } else {
33                 opts = append(opts, grpc.WithTransportCredentials(
34                         credentials.NewTLS(tls)))
35         }
36
37         // Connect. Note the first parameter is unused because we use a custom
38         // dialer that has the state to see the address.
39         conn, err := grpc.Dial("unused", opts...)
40         if err != nil {
41                 return nil, err
42         }
43
44         return conn, nil
45 }
46
47 // newGRPCClient creates a new GRPCClient. The Client argument is expected
48 // to be successfully started already with a lock held.
49 func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) {
50         conn, err := dialGRPCConn(c.config.TLSConfig, c.dialer)
51         if err != nil {
52                 return nil, err
53         }
54
55         // Start the broker.
56         brokerGRPCClient := newGRPCBrokerClient(conn)
57         broker := newGRPCBroker(brokerGRPCClient, c.config.TLSConfig)
58         go broker.Run()
59         go brokerGRPCClient.StartStream()
60
61         return &GRPCClient{
62                 Conn:    conn,
63                 Plugins: c.config.Plugins,
64                 doneCtx: doneCtx,
65                 broker:  broker,
66         }, nil
67 }
68
69 // GRPCClient connects to a GRPCServer over gRPC to dispense plugin types.
70 type GRPCClient struct {
71         Conn    *grpc.ClientConn
72         Plugins map[string]Plugin
73
74         doneCtx context.Context
75         broker  *GRPCBroker
76 }
77
78 // ClientProtocol impl.
79 func (c *GRPCClient) Close() error {
80         c.broker.Close()
81         return c.Conn.Close()
82 }
83
84 // ClientProtocol impl.
85 func (c *GRPCClient) Dispense(name string) (interface{}, error) {
86         raw, ok := c.Plugins[name]
87         if !ok {
88                 return nil, fmt.Errorf("unknown plugin type: %s", name)
89         }
90
91         p, ok := raw.(GRPCPlugin)
92         if !ok {
93                 return nil, fmt.Errorf("plugin %q doesn't support gRPC", name)
94         }
95
96         return p.GRPCClient(c.doneCtx, c.broker, c.Conn)
97 }
98
99 // ClientProtocol impl.
100 func (c *GRPCClient) Ping() error {
101         client := grpc_health_v1.NewHealthClient(c.Conn)
102         _, err := client.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{
103                 Service: GRPCServiceName,
104         })
105
106         return err
107 }