diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-plugin/grpc_server.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-plugin/grpc_server.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_server.go b/vendor/github.com/hashicorp/go-plugin/grpc_server.go new file mode 100644 index 0000000..3a72739 --- /dev/null +++ b/vendor/github.com/hashicorp/go-plugin/grpc_server.go | |||
@@ -0,0 +1,132 @@ | |||
1 | package plugin | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "crypto/tls" | ||
6 | "encoding/json" | ||
7 | "fmt" | ||
8 | "io" | ||
9 | "net" | ||
10 | |||
11 | "google.golang.org/grpc" | ||
12 | "google.golang.org/grpc/credentials" | ||
13 | "google.golang.org/grpc/health" | ||
14 | "google.golang.org/grpc/health/grpc_health_v1" | ||
15 | ) | ||
16 | |||
17 | // GRPCServiceName is the name of the service that the health check should | ||
18 | // return as passing. | ||
19 | const GRPCServiceName = "plugin" | ||
20 | |||
21 | // DefaultGRPCServer can be used with the "GRPCServer" field for Server | ||
22 | // as a default factory method to create a gRPC server with no extra options. | ||
23 | func DefaultGRPCServer(opts []grpc.ServerOption) *grpc.Server { | ||
24 | return grpc.NewServer(opts...) | ||
25 | } | ||
26 | |||
27 | // GRPCServer is a ServerType implementation that serves plugins over | ||
28 | // gRPC. This allows plugins to easily be written for other languages. | ||
29 | // | ||
30 | // The GRPCServer outputs a custom configuration as a base64-encoded | ||
31 | // JSON structure represented by the GRPCServerConfig config structure. | ||
32 | type GRPCServer struct { | ||
33 | // Plugins are the list of plugins to serve. | ||
34 | Plugins map[string]Plugin | ||
35 | |||
36 | // Server is the actual server that will accept connections. This | ||
37 | // will be used for plugin registration as well. | ||
38 | Server func([]grpc.ServerOption) *grpc.Server | ||
39 | |||
40 | // TLS should be the TLS configuration if available. If this is nil, | ||
41 | // the connection will not have transport security. | ||
42 | TLS *tls.Config | ||
43 | |||
44 | // DoneCh is the channel that is closed when this server has exited. | ||
45 | DoneCh chan struct{} | ||
46 | |||
47 | // Stdout/StderrLis are the readers for stdout/stderr that will be copied | ||
48 | // to the stdout/stderr connection that is output. | ||
49 | Stdout io.Reader | ||
50 | Stderr io.Reader | ||
51 | |||
52 | config GRPCServerConfig | ||
53 | server *grpc.Server | ||
54 | broker *GRPCBroker | ||
55 | } | ||
56 | |||
57 | // ServerProtocol impl. | ||
58 | func (s *GRPCServer) Init() error { | ||
59 | // Create our server | ||
60 | var opts []grpc.ServerOption | ||
61 | if s.TLS != nil { | ||
62 | opts = append(opts, grpc.Creds(credentials.NewTLS(s.TLS))) | ||
63 | } | ||
64 | s.server = s.Server(opts) | ||
65 | |||
66 | // Register the health service | ||
67 | healthCheck := health.NewServer() | ||
68 | healthCheck.SetServingStatus( | ||
69 | GRPCServiceName, grpc_health_v1.HealthCheckResponse_SERVING) | ||
70 | grpc_health_v1.RegisterHealthServer(s.server, healthCheck) | ||
71 | |||
72 | // Register the broker service | ||
73 | brokerServer := newGRPCBrokerServer() | ||
74 | RegisterGRPCBrokerServer(s.server, brokerServer) | ||
75 | s.broker = newGRPCBroker(brokerServer, s.TLS) | ||
76 | go s.broker.Run() | ||
77 | |||
78 | // Register all our plugins onto the gRPC server. | ||
79 | for k, raw := range s.Plugins { | ||
80 | p, ok := raw.(GRPCPlugin) | ||
81 | if !ok { | ||
82 | return fmt.Errorf("%q is not a GRPC-compatible plugin", k) | ||
83 | } | ||
84 | |||
85 | if err := p.GRPCServer(s.broker, s.server); err != nil { | ||
86 | return fmt.Errorf("error registring %q: %s", k, err) | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return nil | ||
91 | } | ||
92 | |||
93 | // Stop calls Stop on the underlying grpc.Server | ||
94 | func (s *GRPCServer) Stop() { | ||
95 | s.server.Stop() | ||
96 | } | ||
97 | |||
98 | // GracefulStop calls GracefulStop on the underlying grpc.Server | ||
99 | func (s *GRPCServer) GracefulStop() { | ||
100 | s.server.GracefulStop() | ||
101 | } | ||
102 | |||
103 | // Config is the GRPCServerConfig encoded as JSON then base64. | ||
104 | func (s *GRPCServer) Config() string { | ||
105 | // Create a buffer that will contain our final contents | ||
106 | var buf bytes.Buffer | ||
107 | |||
108 | // Wrap the base64 encoding with JSON encoding. | ||
109 | if err := json.NewEncoder(&buf).Encode(s.config); err != nil { | ||
110 | // We panic since ths shouldn't happen under any scenario. We | ||
111 | // carefully control the structure being encoded here and it should | ||
112 | // always be successful. | ||
113 | panic(err) | ||
114 | } | ||
115 | |||
116 | return buf.String() | ||
117 | } | ||
118 | |||
119 | func (s *GRPCServer) Serve(lis net.Listener) { | ||
120 | // Start serving in a goroutine | ||
121 | go s.server.Serve(lis) | ||
122 | |||
123 | // Wait until graceful completion | ||
124 | <-s.DoneCh | ||
125 | } | ||
126 | |||
127 | // GRPCServerConfig is the extra configuration passed along for consumers | ||
128 | // to facilitate using GRPC plugins. | ||
129 | type GRPCServerConfig struct { | ||
130 | StdoutAddr string `json:"stdout_addr"` | ||
131 | StderrAddr string `json:"stderr_addr"` | ||
132 | } | ||