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