diff options
author | appilon <apilon@hashicorp.com> | 2019-02-27 16:43:31 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-27 16:43:31 -0500 |
commit | 844b5a68d8af4791755b8f0ad293cc99f5959183 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/hashicorp/go-plugin/client.go | |
parent | 303b299eeb6b06e939e35905e4b34cb410dd9dc3 (diff) | |
parent | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (diff) | |
download | terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.tar.gz terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.tar.zst terraform-provider-statuscake-844b5a68d8af4791755b8f0ad293cc99f5959183.zip |
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[MODULES] Switch to Go Modules
Diffstat (limited to 'vendor/github.com/hashicorp/go-plugin/client.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-plugin/client.go | 293 |
1 files changed, 253 insertions, 40 deletions
diff --git a/vendor/github.com/hashicorp/go-plugin/client.go b/vendor/github.com/hashicorp/go-plugin/client.go index 9f8a0f2..b3e3b78 100644 --- a/vendor/github.com/hashicorp/go-plugin/client.go +++ b/vendor/github.com/hashicorp/go-plugin/client.go | |||
@@ -2,8 +2,12 @@ package plugin | |||
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bufio" | 4 | "bufio" |
5 | "context" | ||
6 | "crypto/subtle" | ||
7 | "crypto/tls" | ||
5 | "errors" | 8 | "errors" |
6 | "fmt" | 9 | "fmt" |
10 | "hash" | ||
7 | "io" | 11 | "io" |
8 | "io/ioutil" | 12 | "io/ioutil" |
9 | "log" | 13 | "log" |
@@ -17,6 +21,8 @@ import ( | |||
17 | "sync/atomic" | 21 | "sync/atomic" |
18 | "time" | 22 | "time" |
19 | "unicode" | 23 | "unicode" |
24 | |||
25 | hclog "github.com/hashicorp/go-hclog" | ||
20 | ) | 26 | ) |
21 | 27 | ||
22 | // If this is 1, then we've called CleanupClients. This can be used | 28 | // If this is 1, then we've called CleanupClients. This can be used |
@@ -35,6 +41,22 @@ var ( | |||
35 | // ErrProcessNotFound is returned when a client is instantiated to | 41 | // ErrProcessNotFound is returned when a client is instantiated to |
36 | // reattach to an existing process and it isn't found. | 42 | // reattach to an existing process and it isn't found. |
37 | ErrProcessNotFound = errors.New("Reattachment process not found") | 43 | ErrProcessNotFound = errors.New("Reattachment process not found") |
44 | |||
45 | // ErrChecksumsDoNotMatch is returned when binary's checksum doesn't match | ||
46 | // the one provided in the SecureConfig. | ||
47 | ErrChecksumsDoNotMatch = errors.New("checksums did not match") | ||
48 | |||
49 | // ErrSecureNoChecksum is returned when an empty checksum is provided to the | ||
50 | // SecureConfig. | ||
51 | ErrSecureConfigNoChecksum = errors.New("no checksum provided") | ||
52 | |||
53 | // ErrSecureNoHash is returned when a nil Hash object is provided to the | ||
54 | // SecureConfig. | ||
55 | ErrSecureConfigNoHash = errors.New("no hash implementation provided") | ||
56 | |||
57 | // ErrSecureConfigAndReattach is returned when both Reattach and | ||
58 | // SecureConfig are set. | ||
59 | ErrSecureConfigAndReattach = errors.New("only one of Reattach or SecureConfig can be set") | ||
38 | ) | 60 | ) |
39 | 61 | ||
40 | // Client handles the lifecycle of a plugin application. It launches | 62 | // Client handles the lifecycle of a plugin application. It launches |
@@ -55,7 +77,10 @@ type Client struct { | |||
55 | l sync.Mutex | 77 | l sync.Mutex |
56 | address net.Addr | 78 | address net.Addr |
57 | process *os.Process | 79 | process *os.Process |
58 | client *RPCClient | 80 | client ClientProtocol |
81 | protocol Protocol | ||
82 | logger hclog.Logger | ||
83 | doneCtx context.Context | ||
59 | } | 84 | } |
60 | 85 | ||
61 | // ClientConfig is the configuration used to initialize a new | 86 | // ClientConfig is the configuration used to initialize a new |
@@ -79,6 +104,13 @@ type ClientConfig struct { | |||
79 | Cmd *exec.Cmd | 104 | Cmd *exec.Cmd |
80 | Reattach *ReattachConfig | 105 | Reattach *ReattachConfig |
81 | 106 | ||
107 | // SecureConfig is configuration for verifying the integrity of the | ||
108 | // executable. It can not be used with Reattach. | ||
109 | SecureConfig *SecureConfig | ||
110 | |||
111 | // TLSConfig is used to enable TLS on the RPC client. | ||
112 | TLSConfig *tls.Config | ||
113 | |||
82 | // Managed represents if the client should be managed by the | 114 | // Managed represents if the client should be managed by the |
83 | // plugin package or not. If true, then by calling CleanupClients, | 115 | // plugin package or not. If true, then by calling CleanupClients, |
84 | // it will automatically be cleaned up. Otherwise, the client | 116 | // it will automatically be cleaned up. Otherwise, the client |
@@ -109,14 +141,74 @@ type ClientConfig struct { | |||
109 | // sync any of these streams. | 141 | // sync any of these streams. |
110 | SyncStdout io.Writer | 142 | SyncStdout io.Writer |
111 | SyncStderr io.Writer | 143 | SyncStderr io.Writer |
144 | |||
145 | // AllowedProtocols is a list of allowed protocols. If this isn't set, | ||
146 | // then only netrpc is allowed. This is so that older go-plugin systems | ||
147 | // can show friendly errors if they see a plugin with an unknown | ||
148 | // protocol. | ||
149 | // | ||
150 | // By setting this, you can cause an error immediately on plugin start | ||
151 | // if an unsupported protocol is used with a good error message. | ||
152 | // | ||
153 | // If this isn't set at all (nil value), then only net/rpc is accepted. | ||
154 | // This is done for legacy reasons. You must explicitly opt-in to | ||
155 | // new protocols. | ||
156 | AllowedProtocols []Protocol | ||
157 | |||
158 | // Logger is the logger that the client will used. If none is provided, | ||
159 | // it will default to hclog's default logger. | ||
160 | Logger hclog.Logger | ||
112 | } | 161 | } |
113 | 162 | ||
114 | // ReattachConfig is used to configure a client to reattach to an | 163 | // ReattachConfig is used to configure a client to reattach to an |
115 | // already-running plugin process. You can retrieve this information by | 164 | // already-running plugin process. You can retrieve this information by |
116 | // calling ReattachConfig on Client. | 165 | // calling ReattachConfig on Client. |
117 | type ReattachConfig struct { | 166 | type ReattachConfig struct { |
118 | Addr net.Addr | 167 | Protocol Protocol |
119 | Pid int | 168 | Addr net.Addr |
169 | Pid int | ||
170 | } | ||
171 | |||
172 | // SecureConfig is used to configure a client to verify the integrity of an | ||
173 | // executable before running. It does this by verifying the checksum is | ||
174 | // expected. Hash is used to specify the hashing method to use when checksumming | ||
175 | // the file. The configuration is verified by the client by calling the | ||
176 | // SecureConfig.Check() function. | ||
177 | // | ||
178 | // The host process should ensure the checksum was provided by a trusted and | ||
179 | // authoritative source. The binary should be installed in such a way that it | ||
180 | // can not be modified by an unauthorized user between the time of this check | ||
181 | // and the time of execution. | ||
182 | type SecureConfig struct { | ||
183 | Checksum []byte | ||
184 | Hash hash.Hash | ||
185 | } | ||
186 | |||
187 | // Check takes the filepath to an executable and returns true if the checksum of | ||
188 | // the file matches the checksum provided in the SecureConfig. | ||
189 | func (s *SecureConfig) Check(filePath string) (bool, error) { | ||
190 | if len(s.Checksum) == 0 { | ||
191 | return false, ErrSecureConfigNoChecksum | ||
192 | } | ||
193 | |||
194 | if s.Hash == nil { | ||
195 | return false, ErrSecureConfigNoHash | ||
196 | } | ||
197 | |||
198 | file, err := os.Open(filePath) | ||
199 | if err != nil { | ||
200 | return false, err | ||
201 | } | ||
202 | defer file.Close() | ||
203 | |||
204 | _, err = io.Copy(s.Hash, file) | ||
205 | if err != nil { | ||
206 | return false, err | ||
207 | } | ||
208 | |||
209 | sum := s.Hash.Sum(nil) | ||
210 | |||
211 | return subtle.ConstantTimeCompare(sum, s.Checksum) == 1, nil | ||
120 | } | 212 | } |
121 | 213 | ||
122 | // This makes sure all the managed subprocesses are killed and properly | 214 | // This makes sure all the managed subprocesses are killed and properly |
@@ -174,7 +266,22 @@ func NewClient(config *ClientConfig) (c *Client) { | |||
174 | config.SyncStderr = ioutil.Discard | 266 | config.SyncStderr = ioutil.Discard |
175 | } | 267 | } |
176 | 268 | ||
177 | c = &Client{config: config} | 269 | if config.AllowedProtocols == nil { |
270 | config.AllowedProtocols = []Protocol{ProtocolNetRPC} | ||
271 | } | ||
272 | |||
273 | if config.Logger == nil { | ||
274 | config.Logger = hclog.New(&hclog.LoggerOptions{ | ||
275 | Output: hclog.DefaultOutput, | ||
276 | Level: hclog.Trace, | ||
277 | Name: "plugin", | ||
278 | }) | ||
279 | } | ||
280 | |||
281 | c = &Client{ | ||
282 | config: config, | ||
283 | logger: config.Logger, | ||
284 | } | ||
178 | if config.Managed { | 285 | if config.Managed { |
179 | managedClientsLock.Lock() | 286 | managedClientsLock.Lock() |
180 | managedClients = append(managedClients, c) | 287 | managedClients = append(managedClients, c) |
@@ -184,11 +291,11 @@ func NewClient(config *ClientConfig) (c *Client) { | |||
184 | return | 291 | return |
185 | } | 292 | } |
186 | 293 | ||
187 | // Client returns an RPC client for the plugin. | 294 | // Client returns the protocol client for this connection. |
188 | // | 295 | // |
189 | // Subsequent calls to this will return the same RPC client. | 296 | // Subsequent calls to this will return the same client. |
190 | func (c *Client) Client() (*RPCClient, error) { | 297 | func (c *Client) Client() (ClientProtocol, error) { |
191 | addr, err := c.Start() | 298 | _, err := c.Start() |
192 | if err != nil { | 299 | if err != nil { |
193 | return nil, err | 300 | return nil, err |
194 | } | 301 | } |
@@ -200,29 +307,18 @@ func (c *Client) Client() (*RPCClient, error) { | |||
200 | return c.client, nil | 307 | return c.client, nil |
201 | } | 308 | } |
202 | 309 | ||
203 | // Connect to the client | 310 | switch c.protocol { |
204 | conn, err := net.Dial(addr.Network(), addr.String()) | 311 | case ProtocolNetRPC: |
205 | if err != nil { | 312 | c.client, err = newRPCClient(c) |
206 | return nil, err | ||
207 | } | ||
208 | if tcpConn, ok := conn.(*net.TCPConn); ok { | ||
209 | // Make sure to set keep alive so that the connection doesn't die | ||
210 | tcpConn.SetKeepAlive(true) | ||
211 | } | ||
212 | 313 | ||
213 | // Create the actual RPC client | 314 | case ProtocolGRPC: |
214 | c.client, err = NewRPCClient(conn, c.config.Plugins) | 315 | c.client, err = newGRPCClient(c.doneCtx, c) |
215 | if err != nil { | 316 | |
216 | conn.Close() | 317 | default: |
217 | return nil, err | 318 | return nil, fmt.Errorf("unknown server protocol: %s", c.protocol) |
218 | } | 319 | } |
219 | 320 | ||
220 | // Begin the stream syncing so that stdin, out, err work properly | ||
221 | err = c.client.SyncStreams( | ||
222 | c.config.SyncStdout, | ||
223 | c.config.SyncStderr) | ||
224 | if err != nil { | 321 | if err != nil { |
225 | c.client.Close() | ||
226 | c.client = nil | 322 | c.client = nil |
227 | return nil, err | 323 | return nil, err |
228 | } | 324 | } |
@@ -274,8 +370,7 @@ func (c *Client) Kill() { | |||
274 | if err != nil { | 370 | if err != nil { |
275 | // If there was an error just log it. We're going to force | 371 | // If there was an error just log it. We're going to force |
276 | // kill in a moment anyways. | 372 | // kill in a moment anyways. |
277 | log.Printf( | 373 | c.logger.Warn("error closing client during Kill", "err", err) |
278 | "[WARN] plugin: error closing client during Kill: %s", err) | ||
279 | } | 374 | } |
280 | } | 375 | } |
281 | } | 376 | } |
@@ -318,13 +413,21 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
318 | { | 413 | { |
319 | cmdSet := c.config.Cmd != nil | 414 | cmdSet := c.config.Cmd != nil |
320 | attachSet := c.config.Reattach != nil | 415 | attachSet := c.config.Reattach != nil |
416 | secureSet := c.config.SecureConfig != nil | ||
321 | if cmdSet == attachSet { | 417 | if cmdSet == attachSet { |
322 | return nil, fmt.Errorf("Only one of Cmd or Reattach must be set") | 418 | return nil, fmt.Errorf("Only one of Cmd or Reattach must be set") |
323 | } | 419 | } |
420 | |||
421 | if secureSet && attachSet { | ||
422 | return nil, ErrSecureConfigAndReattach | ||
423 | } | ||
324 | } | 424 | } |
325 | 425 | ||
326 | // Create the logging channel for when we kill | 426 | // Create the logging channel for when we kill |
327 | c.doneLogging = make(chan struct{}) | 427 | c.doneLogging = make(chan struct{}) |
428 | // Create a context for when we kill | ||
429 | var ctxCancel context.CancelFunc | ||
430 | c.doneCtx, ctxCancel = context.WithCancel(context.Background()) | ||
328 | 431 | ||
329 | if c.config.Reattach != nil { | 432 | if c.config.Reattach != nil { |
330 | // Verify the process still exists. If not, then it is an error | 433 | // Verify the process still exists. If not, then it is an error |
@@ -350,7 +453,7 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
350 | pidWait(pid) | 453 | pidWait(pid) |
351 | 454 | ||
352 | // Log so we can see it | 455 | // Log so we can see it |
353 | log.Printf("[DEBUG] plugin: reattached plugin process exited\n") | 456 | c.logger.Debug("reattached plugin process exited") |
354 | 457 | ||
355 | // Mark it | 458 | // Mark it |
356 | c.l.Lock() | 459 | c.l.Lock() |
@@ -359,11 +462,19 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
359 | 462 | ||
360 | // Close the logging channel since that doesn't work on reattach | 463 | // Close the logging channel since that doesn't work on reattach |
361 | close(c.doneLogging) | 464 | close(c.doneLogging) |
465 | |||
466 | // Cancel the context | ||
467 | ctxCancel() | ||
362 | }(p.Pid) | 468 | }(p.Pid) |
363 | 469 | ||
364 | // Set the address and process | 470 | // Set the address and process |
365 | c.address = c.config.Reattach.Addr | 471 | c.address = c.config.Reattach.Addr |
366 | c.process = p | 472 | c.process = p |
473 | c.protocol = c.config.Reattach.Protocol | ||
474 | if c.protocol == "" { | ||
475 | // Default the protocol to net/rpc for backwards compatibility | ||
476 | c.protocol = ProtocolNetRPC | ||
477 | } | ||
367 | 478 | ||
368 | return c.address, nil | 479 | return c.address, nil |
369 | } | 480 | } |
@@ -384,7 +495,15 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
384 | cmd.Stderr = stderr_w | 495 | cmd.Stderr = stderr_w |
385 | cmd.Stdout = stdout_w | 496 | cmd.Stdout = stdout_w |
386 | 497 | ||
387 | log.Printf("[DEBUG] plugin: starting plugin: %s %#v", cmd.Path, cmd.Args) | 498 | if c.config.SecureConfig != nil { |
499 | if ok, err := c.config.SecureConfig.Check(cmd.Path); err != nil { | ||
500 | return nil, fmt.Errorf("error verifying checksum: %s", err) | ||
501 | } else if !ok { | ||
502 | return nil, ErrChecksumsDoNotMatch | ||
503 | } | ||
504 | } | ||
505 | |||
506 | c.logger.Debug("starting plugin", "path", cmd.Path, "args", cmd.Args) | ||
388 | err = cmd.Start() | 507 | err = cmd.Start() |
389 | if err != nil { | 508 | if err != nil { |
390 | return | 509 | return |
@@ -418,12 +537,15 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
418 | cmd.Wait() | 537 | cmd.Wait() |
419 | 538 | ||
420 | // Log and make sure to flush the logs write away | 539 | // Log and make sure to flush the logs write away |
421 | log.Printf("[DEBUG] plugin: %s: plugin process exited\n", cmd.Path) | 540 | c.logger.Debug("plugin process exited", "path", cmd.Path) |
422 | os.Stderr.Sync() | 541 | os.Stderr.Sync() |
423 | 542 | ||
424 | // Mark that we exited | 543 | // Mark that we exited |
425 | close(exitCh) | 544 | close(exitCh) |
426 | 545 | ||
546 | // Cancel the context, marking that we exited | ||
547 | ctxCancel() | ||
548 | |||
427 | // Set that we exited, which takes a lock | 549 | // Set that we exited, which takes a lock |
428 | c.l.Lock() | 550 | c.l.Lock() |
429 | defer c.l.Unlock() | 551 | defer c.l.Unlock() |
@@ -465,7 +587,7 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
465 | timeout := time.After(c.config.StartTimeout) | 587 | timeout := time.After(c.config.StartTimeout) |
466 | 588 | ||
467 | // Start looking for the address | 589 | // Start looking for the address |
468 | log.Printf("[DEBUG] plugin: waiting for RPC address for: %s", cmd.Path) | 590 | c.logger.Debug("waiting for RPC address", "path", cmd.Path) |
469 | select { | 591 | select { |
470 | case <-timeout: | 592 | case <-timeout: |
471 | err = errors.New("timeout while waiting for plugin to start") | 593 | err = errors.New("timeout while waiting for plugin to start") |
@@ -475,7 +597,7 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
475 | // Trim the line and split by "|" in order to get the parts of | 597 | // Trim the line and split by "|" in order to get the parts of |
476 | // the output. | 598 | // the output. |
477 | line := strings.TrimSpace(string(lineBytes)) | 599 | line := strings.TrimSpace(string(lineBytes)) |
478 | parts := strings.SplitN(line, "|", 4) | 600 | parts := strings.SplitN(line, "|", 6) |
479 | if len(parts) < 4 { | 601 | if len(parts) < 4 { |
480 | err = fmt.Errorf( | 602 | err = fmt.Errorf( |
481 | "Unrecognized remote plugin message: %s\n\n"+ | 603 | "Unrecognized remote plugin message: %s\n\n"+ |
@@ -495,7 +617,7 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
495 | 617 | ||
496 | if int(coreProtocol) != CoreProtocolVersion { | 618 | if int(coreProtocol) != CoreProtocolVersion { |
497 | err = fmt.Errorf("Incompatible core API version with plugin. "+ | 619 | err = fmt.Errorf("Incompatible core API version with plugin. "+ |
498 | "Plugin version: %s, Ours: %d\n\n"+ | 620 | "Plugin version: %s, Core version: %d\n\n"+ |
499 | "To fix this, the plugin usually only needs to be recompiled.\n"+ | 621 | "To fix this, the plugin usually only needs to be recompiled.\n"+ |
500 | "Please report this to the plugin author.", parts[0], CoreProtocolVersion) | 622 | "Please report this to the plugin author.", parts[0], CoreProtocolVersion) |
501 | return | 623 | return |
@@ -513,7 +635,7 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
513 | // Test the API version | 635 | // Test the API version |
514 | if uint(protocol) != c.config.ProtocolVersion { | 636 | if uint(protocol) != c.config.ProtocolVersion { |
515 | err = fmt.Errorf("Incompatible API version with plugin. "+ | 637 | err = fmt.Errorf("Incompatible API version with plugin. "+ |
516 | "Plugin version: %s, Ours: %d", parts[1], c.config.ProtocolVersion) | 638 | "Plugin version: %s, Core version: %d", parts[1], c.config.ProtocolVersion) |
517 | return | 639 | return |
518 | } | 640 | } |
519 | 641 | ||
@@ -525,6 +647,27 @@ func (c *Client) Start() (addr net.Addr, err error) { | |||
525 | default: | 647 | default: |
526 | err = fmt.Errorf("Unknown address type: %s", parts[3]) | 648 | err = fmt.Errorf("Unknown address type: %s", parts[3]) |
527 | } | 649 | } |
650 | |||
651 | // If we have a server type, then record that. We default to net/rpc | ||
652 | // for backwards compatibility. | ||
653 | c.protocol = ProtocolNetRPC | ||
654 | if len(parts) >= 5 { | ||
655 | c.protocol = Protocol(parts[4]) | ||
656 | } | ||
657 | |||
658 | found := false | ||
659 | for _, p := range c.config.AllowedProtocols { | ||
660 | if p == c.protocol { | ||
661 | found = true | ||
662 | break | ||
663 | } | ||
664 | } | ||
665 | if !found { | ||
666 | err = fmt.Errorf("Unsupported plugin protocol %q. Supported: %v", | ||
667 | c.protocol, c.config.AllowedProtocols) | ||
668 | return | ||
669 | } | ||
670 | |||
528 | } | 671 | } |
529 | 672 | ||
530 | c.address = addr | 673 | c.address = addr |
@@ -555,9 +698,57 @@ func (c *Client) ReattachConfig() *ReattachConfig { | |||
555 | } | 698 | } |
556 | 699 | ||
557 | return &ReattachConfig{ | 700 | return &ReattachConfig{ |
558 | Addr: c.address, | 701 | Protocol: c.protocol, |
559 | Pid: c.config.Cmd.Process.Pid, | 702 | Addr: c.address, |
703 | Pid: c.config.Cmd.Process.Pid, | ||
704 | } | ||
705 | } | ||
706 | |||
707 | // Protocol returns the protocol of server on the remote end. This will | ||
708 | // start the plugin process if it isn't already started. Errors from | ||
709 | // starting the plugin are surpressed and ProtocolInvalid is returned. It | ||
710 | // is recommended you call Start explicitly before calling Protocol to ensure | ||
711 | // no errors occur. | ||
712 | func (c *Client) Protocol() Protocol { | ||
713 | _, err := c.Start() | ||
714 | if err != nil { | ||
715 | return ProtocolInvalid | ||
716 | } | ||
717 | |||
718 | return c.protocol | ||
719 | } | ||
720 | |||
721 | func netAddrDialer(addr net.Addr) func(string, time.Duration) (net.Conn, error) { | ||
722 | return func(_ string, _ time.Duration) (net.Conn, error) { | ||
723 | // Connect to the client | ||
724 | conn, err := net.Dial(addr.Network(), addr.String()) | ||
725 | if err != nil { | ||
726 | return nil, err | ||
727 | } | ||
728 | if tcpConn, ok := conn.(*net.TCPConn); ok { | ||
729 | // Make sure to set keep alive so that the connection doesn't die | ||
730 | tcpConn.SetKeepAlive(true) | ||
731 | } | ||
732 | |||
733 | return conn, nil | ||
734 | } | ||
735 | } | ||
736 | |||
737 | // dialer is compatible with grpc.WithDialer and creates the connection | ||
738 | // to the plugin. | ||
739 | func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) { | ||
740 | conn, err := netAddrDialer(c.address)("", timeout) | ||
741 | if err != nil { | ||
742 | return nil, err | ||
560 | } | 743 | } |
744 | |||
745 | // If we have a TLS config we wrap our connection. We only do this | ||
746 | // for net/rpc since gRPC uses its own mechanism for TLS. | ||
747 | if c.protocol == ProtocolNetRPC && c.config.TLSConfig != nil { | ||
748 | conn = tls.Client(conn, c.config.TLSConfig) | ||
749 | } | ||
750 | |||
751 | return conn, nil | ||
561 | } | 752 | } |
562 | 753 | ||
563 | func (c *Client) logStderr(r io.Reader) { | 754 | func (c *Client) logStderr(r io.Reader) { |
@@ -566,9 +757,31 @@ func (c *Client) logStderr(r io.Reader) { | |||
566 | line, err := bufR.ReadString('\n') | 757 | line, err := bufR.ReadString('\n') |
567 | if line != "" { | 758 | if line != "" { |
568 | c.config.Stderr.Write([]byte(line)) | 759 | c.config.Stderr.Write([]byte(line)) |
569 | |||
570 | line = strings.TrimRightFunc(line, unicode.IsSpace) | 760 | line = strings.TrimRightFunc(line, unicode.IsSpace) |
571 | log.Printf("[DEBUG] plugin: %s: %s", filepath.Base(c.config.Cmd.Path), line) | 761 | |
762 | l := c.logger.Named(filepath.Base(c.config.Cmd.Path)) | ||
763 | |||
764 | entry, err := parseJSON(line) | ||
765 | // If output is not JSON format, print directly to Debug | ||
766 | if err != nil { | ||
767 | l.Debug(line) | ||
768 | } else { | ||
769 | out := flattenKVPairs(entry.KVPairs) | ||
770 | |||
771 | l = l.With("timestamp", entry.Timestamp.Format(hclog.TimeFormat)) | ||
772 | switch hclog.LevelFromString(entry.Level) { | ||
773 | case hclog.Trace: | ||
774 | l.Trace(entry.Message, out...) | ||
775 | case hclog.Debug: | ||
776 | l.Debug(entry.Message, out...) | ||
777 | case hclog.Info: | ||
778 | l.Info(entry.Message, out...) | ||
779 | case hclog.Warn: | ||
780 | l.Warn(entry.Message, out...) | ||
781 | case hclog.Error: | ||
782 | l.Error(entry.Message, out...) | ||
783 | } | ||
784 | } | ||
572 | } | 785 | } |
573 | 786 | ||
574 | if err == io.EOF { | 787 | if err == io.EOF { |