diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-plugin/server.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-plugin/server.go | 135 |
1 files changed, 115 insertions, 20 deletions
diff --git a/vendor/github.com/hashicorp/go-plugin/server.go b/vendor/github.com/hashicorp/go-plugin/server.go index b5c5270..1e808b9 100644 --- a/vendor/github.com/hashicorp/go-plugin/server.go +++ b/vendor/github.com/hashicorp/go-plugin/server.go | |||
@@ -1,6 +1,8 @@ | |||
1 | package plugin | 1 | package plugin |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "crypto/tls" | ||
5 | "encoding/base64" | ||
4 | "errors" | 6 | "errors" |
5 | "fmt" | 7 | "fmt" |
6 | "io/ioutil" | 8 | "io/ioutil" |
@@ -11,6 +13,10 @@ import ( | |||
11 | "runtime" | 13 | "runtime" |
12 | "strconv" | 14 | "strconv" |
13 | "sync/atomic" | 15 | "sync/atomic" |
16 | |||
17 | "github.com/hashicorp/go-hclog" | ||
18 | |||
19 | "google.golang.org/grpc" | ||
14 | ) | 20 | ) |
15 | 21 | ||
16 | // CoreProtocolVersion is the ProtocolVersion of the plugin system itself. | 22 | // CoreProtocolVersion is the ProtocolVersion of the plugin system itself. |
@@ -45,14 +51,41 @@ type ServeConfig struct { | |||
45 | // HandshakeConfig is the configuration that must match clients. | 51 | // HandshakeConfig is the configuration that must match clients. |
46 | HandshakeConfig | 52 | HandshakeConfig |
47 | 53 | ||
54 | // TLSProvider is a function that returns a configured tls.Config. | ||
55 | TLSProvider func() (*tls.Config, error) | ||
56 | |||
48 | // Plugins are the plugins that are served. | 57 | // Plugins are the plugins that are served. |
49 | Plugins map[string]Plugin | 58 | Plugins map[string]Plugin |
59 | |||
60 | // GRPCServer should be non-nil to enable serving the plugins over | ||
61 | // gRPC. This is a function to create the server when needed with the | ||
62 | // given server options. The server options populated by go-plugin will | ||
63 | // be for TLS if set. You may modify the input slice. | ||
64 | // | ||
65 | // Note that the grpc.Server will automatically be registered with | ||
66 | // the gRPC health checking service. This is not optional since go-plugin | ||
67 | // relies on this to implement Ping(). | ||
68 | GRPCServer func([]grpc.ServerOption) *grpc.Server | ||
69 | |||
70 | // Logger is used to pass a logger into the server. If none is provided the | ||
71 | // server will create a default logger. | ||
72 | Logger hclog.Logger | ||
73 | } | ||
74 | |||
75 | // Protocol returns the protocol that this server should speak. | ||
76 | func (c *ServeConfig) Protocol() Protocol { | ||
77 | result := ProtocolNetRPC | ||
78 | if c.GRPCServer != nil { | ||
79 | result = ProtocolGRPC | ||
80 | } | ||
81 | |||
82 | return result | ||
50 | } | 83 | } |
51 | 84 | ||
52 | // Serve serves the plugins given by ServeConfig. | 85 | // Serve serves the plugins given by ServeConfig. |
53 | // | 86 | // |
54 | // Serve doesn't return until the plugin is done being executed. Any | 87 | // Serve doesn't return until the plugin is done being executed. Any |
55 | // errors will be outputted to the log. | 88 | // errors will be outputted to os.Stderr. |
56 | // | 89 | // |
57 | // This is the method that plugins should call in their main() functions. | 90 | // This is the method that plugins should call in their main() functions. |
58 | func Serve(opts *ServeConfig) { | 91 | func Serve(opts *ServeConfig) { |
@@ -77,6 +110,16 @@ func Serve(opts *ServeConfig) { | |||
77 | // Logging goes to the original stderr | 110 | // Logging goes to the original stderr |
78 | log.SetOutput(os.Stderr) | 111 | log.SetOutput(os.Stderr) |
79 | 112 | ||
113 | logger := opts.Logger | ||
114 | if logger == nil { | ||
115 | // internal logger to os.Stderr | ||
116 | logger = hclog.New(&hclog.LoggerOptions{ | ||
117 | Level: hclog.Trace, | ||
118 | Output: os.Stderr, | ||
119 | JSONFormat: true, | ||
120 | }) | ||
121 | } | ||
122 | |||
80 | // Create our new stdout, stderr files. These will override our built-in | 123 | // Create our new stdout, stderr files. These will override our built-in |
81 | // stdout/stderr so that it works across the stream boundary. | 124 | // stdout/stderr so that it works across the stream boundary. |
82 | stdout_r, stdout_w, err := os.Pipe() | 125 | stdout_r, stdout_w, err := os.Pipe() |
@@ -93,30 +136,86 @@ func Serve(opts *ServeConfig) { | |||
93 | // Register a listener so we can accept a connection | 136 | // Register a listener so we can accept a connection |
94 | listener, err := serverListener() | 137 | listener, err := serverListener() |
95 | if err != nil { | 138 | if err != nil { |
96 | log.Printf("[ERR] plugin: plugin init: %s", err) | 139 | logger.Error("plugin init error", "error", err) |
97 | return | 140 | return |
98 | } | 141 | } |
99 | defer listener.Close() | 142 | |
143 | // Close the listener on return. We wrap this in a func() on purpose | ||
144 | // because the "listener" reference may change to TLS. | ||
145 | defer func() { | ||
146 | listener.Close() | ||
147 | }() | ||
148 | |||
149 | var tlsConfig *tls.Config | ||
150 | if opts.TLSProvider != nil { | ||
151 | tlsConfig, err = opts.TLSProvider() | ||
152 | if err != nil { | ||
153 | logger.Error("plugin tls init", "error", err) | ||
154 | return | ||
155 | } | ||
156 | } | ||
100 | 157 | ||
101 | // Create the channel to tell us when we're done | 158 | // Create the channel to tell us when we're done |
102 | doneCh := make(chan struct{}) | 159 | doneCh := make(chan struct{}) |
103 | 160 | ||
104 | // Create the RPC server to dispense | 161 | // Build the server type |
105 | server := &RPCServer{ | 162 | var server ServerProtocol |
106 | Plugins: opts.Plugins, | 163 | switch opts.Protocol() { |
107 | Stdout: stdout_r, | 164 | case ProtocolNetRPC: |
108 | Stderr: stderr_r, | 165 | // If we have a TLS configuration then we wrap the listener |
109 | DoneCh: doneCh, | 166 | // ourselves and do it at that level. |
167 | if tlsConfig != nil { | ||
168 | listener = tls.NewListener(listener, tlsConfig) | ||
169 | } | ||
170 | |||
171 | // Create the RPC server to dispense | ||
172 | server = &RPCServer{ | ||
173 | Plugins: opts.Plugins, | ||
174 | Stdout: stdout_r, | ||
175 | Stderr: stderr_r, | ||
176 | DoneCh: doneCh, | ||
177 | } | ||
178 | |||
179 | case ProtocolGRPC: | ||
180 | // Create the gRPC server | ||
181 | server = &GRPCServer{ | ||
182 | Plugins: opts.Plugins, | ||
183 | Server: opts.GRPCServer, | ||
184 | TLS: tlsConfig, | ||
185 | Stdout: stdout_r, | ||
186 | Stderr: stderr_r, | ||
187 | DoneCh: doneCh, | ||
188 | } | ||
189 | |||
190 | default: | ||
191 | panic("unknown server protocol: " + opts.Protocol()) | ||
110 | } | 192 | } |
111 | 193 | ||
194 | // Initialize the servers | ||
195 | if err := server.Init(); err != nil { | ||
196 | logger.Error("protocol init", "error", err) | ||
197 | return | ||
198 | } | ||
199 | |||
200 | // Build the extra configuration | ||
201 | extra := "" | ||
202 | if v := server.Config(); v != "" { | ||
203 | extra = base64.StdEncoding.EncodeToString([]byte(v)) | ||
204 | } | ||
205 | if extra != "" { | ||
206 | extra = "|" + extra | ||
207 | } | ||
208 | |||
209 | logger.Debug("plugin address", "network", listener.Addr().Network(), "address", listener.Addr().String()) | ||
210 | |||
112 | // Output the address and service name to stdout so that core can bring it up. | 211 | // Output the address and service name to stdout so that core can bring it up. |
113 | log.Printf("[DEBUG] plugin: plugin address: %s %s\n", | 212 | fmt.Printf("%d|%d|%s|%s|%s%s\n", |
114 | listener.Addr().Network(), listener.Addr().String()) | ||
115 | fmt.Printf("%d|%d|%s|%s\n", | ||
116 | CoreProtocolVersion, | 213 | CoreProtocolVersion, |
117 | opts.ProtocolVersion, | 214 | opts.ProtocolVersion, |
118 | listener.Addr().Network(), | 215 | listener.Addr().Network(), |
119 | listener.Addr().String()) | 216 | listener.Addr().String(), |
217 | opts.Protocol(), | ||
218 | extra) | ||
120 | os.Stdout.Sync() | 219 | os.Stdout.Sync() |
121 | 220 | ||
122 | // Eat the interrupts | 221 | // Eat the interrupts |
@@ -127,9 +226,7 @@ func Serve(opts *ServeConfig) { | |||
127 | for { | 226 | for { |
128 | <-ch | 227 | <-ch |
129 | newCount := atomic.AddInt32(&count, 1) | 228 | newCount := atomic.AddInt32(&count, 1) |
130 | log.Printf( | 229 | logger.Debug("plugin received interrupt signal, ignoring", "count", newCount) |
131 | "[DEBUG] plugin: received interrupt signal (count: %d). Ignoring.", | ||
132 | newCount) | ||
133 | } | 230 | } |
134 | }() | 231 | }() |
135 | 232 | ||
@@ -137,10 +234,8 @@ func Serve(opts *ServeConfig) { | |||
137 | os.Stdout = stdout_w | 234 | os.Stdout = stdout_w |
138 | os.Stderr = stderr_w | 235 | os.Stderr = stderr_w |
139 | 236 | ||
140 | // Serve | 237 | // Accept connections and wait for completion |
141 | go server.Accept(listener) | 238 | go server.Serve(listener) |
142 | |||
143 | // Wait for the graceful exit | ||
144 | <-doneCh | 239 | <-doneCh |
145 | } | 240 | } |
146 | 241 | ||