aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/go-plugin
diff options
context:
space:
mode:
authorNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
committerNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
commit107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch)
treeca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/hashicorp/go-plugin
parent844b5a68d8af4791755b8f0ad293cc99f5959183 (diff)
downloadterraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/hashicorp/go-plugin')
-rw-r--r--vendor/github.com/hashicorp/go-plugin/README.md20
-rw-r--r--vendor/github.com/hashicorp/go-plugin/client.go523
-rw-r--r--vendor/github.com/hashicorp/go-plugin/go.mod17
-rw-r--r--vendor/github.com/hashicorp/go-plugin/go.sum31
-rw-r--r--vendor/github.com/hashicorp/go-plugin/grpc_broker.go38
-rw-r--r--vendor/github.com/hashicorp/go-plugin/grpc_client.go24
-rw-r--r--vendor/github.com/hashicorp/go-plugin/grpc_controller.go23
-rw-r--r--vendor/github.com/hashicorp/go-plugin/grpc_server.go24
-rw-r--r--vendor/github.com/hashicorp/go-plugin/internal/plugin/gen.go3
-rw-r--r--vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.pb.go (renamed from vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go)97
-rw-r--r--vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.proto (renamed from vendor/github.com/hashicorp/go-plugin/grpc_broker.proto)1
-rw-r--r--vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.pb.go143
-rw-r--r--vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.proto11
-rw-r--r--vendor/github.com/hashicorp/go-plugin/log_entry.go4
-rw-r--r--vendor/github.com/hashicorp/go-plugin/mtls.go73
-rw-r--r--vendor/github.com/hashicorp/go-plugin/server.go165
-rw-r--r--vendor/github.com/hashicorp/go-plugin/testing.go36
17 files changed, 963 insertions, 270 deletions
diff --git a/vendor/github.com/hashicorp/go-plugin/README.md b/vendor/github.com/hashicorp/go-plugin/README.md
index e4558db..fe305ad 100644
--- a/vendor/github.com/hashicorp/go-plugin/README.md
+++ b/vendor/github.com/hashicorp/go-plugin/README.md
@@ -109,7 +109,7 @@ high-level steps that must be done. Examples are available in the
109 1. Choose the interface(s) you want to expose for plugins. 109 1. Choose the interface(s) you want to expose for plugins.
110 110
111 2. For each interface, implement an implementation of that interface 111 2. For each interface, implement an implementation of that interface
112 that communicates over a `net/rpc` connection or other a 112 that communicates over a `net/rpc` connection or over a
113 [gRPC](http://www.grpc.io) connection or both. You'll have to implement 113 [gRPC](http://www.grpc.io) connection or both. You'll have to implement
114 both a client and server implementation. 114 both a client and server implementation.
115 115
@@ -150,19 +150,19 @@ user experience.
150 150
151When we started using plugins (late 2012, early 2013), plugins over RPC 151When we started using plugins (late 2012, early 2013), plugins over RPC
152were the only option since Go didn't support dynamic library loading. Today, 152were the only option since Go didn't support dynamic library loading. Today,
153Go still doesn't support dynamic library loading, but they do intend to. 153Go supports the [plugin](https://golang.org/pkg/plugin/) standard library with
154Since 2012, our plugin system has stabilized from millions of users using it, 154a number of limitations. Since 2012, our plugin system has stabilized
155and has many benefits we've come to value greatly. 155from tens of millions of users using it, and has many benefits we've come to
156 156value greatly.
157For example, we intend to use this plugin system in 157
158[Vault](https://www.vaultproject.io), and dynamic library loading will 158For example, we use this plugin system in
159simply never be acceptable in Vault for security reasons. That is an extreme 159[Vault](https://www.vaultproject.io) where dynamic library loading is
160not acceptable for security reasons. That is an extreme
160example, but we believe our library system has more upsides than downsides 161example, but we believe our library system has more upsides than downsides
161over dynamic library loading and since we've had it built and tested for years, 162over dynamic library loading and since we've had it built and tested for years,
162we'll likely continue to use it. 163we'll continue to use it.
163 164
164Shared libraries have one major advantage over our system which is much 165Shared libraries have one major advantage over our system which is much
165higher performance. In real world scenarios across our various tools, 166higher performance. In real world scenarios across our various tools,
166we've never required any more performance out of our plugin system and it 167we've never required any more performance out of our plugin system and it
167has seen very high throughput, so this isn't a concern for us at the moment. 168has seen very high throughput, so this isn't a concern for us at the moment.
168
diff --git a/vendor/github.com/hashicorp/go-plugin/client.go b/vendor/github.com/hashicorp/go-plugin/client.go
index b3e3b78..679e10a 100644
--- a/vendor/github.com/hashicorp/go-plugin/client.go
+++ b/vendor/github.com/hashicorp/go-plugin/client.go
@@ -5,12 +5,13 @@ import (
5 "context" 5 "context"
6 "crypto/subtle" 6 "crypto/subtle"
7 "crypto/tls" 7 "crypto/tls"
8 "crypto/x509"
9 "encoding/base64"
8 "errors" 10 "errors"
9 "fmt" 11 "fmt"
10 "hash" 12 "hash"
11 "io" 13 "io"
12 "io/ioutil" 14 "io/ioutil"
13 "log"
14 "net" 15 "net"
15 "os" 16 "os"
16 "os/exec" 17 "os/exec"
@@ -20,7 +21,6 @@ import (
20 "sync" 21 "sync"
21 "sync/atomic" 22 "sync/atomic"
22 "time" 23 "time"
23 "unicode"
24 24
25 hclog "github.com/hashicorp/go-hclog" 25 hclog "github.com/hashicorp/go-hclog"
26) 26)
@@ -71,16 +71,31 @@ var (
71// 71//
72// See NewClient and ClientConfig for using a Client. 72// See NewClient and ClientConfig for using a Client.
73type Client struct { 73type Client struct {
74 config *ClientConfig 74 config *ClientConfig
75 exited bool 75 exited bool
76 doneLogging chan struct{} 76 l sync.Mutex
77 l sync.Mutex 77 address net.Addr
78 address net.Addr 78 process *os.Process
79 process *os.Process 79 client ClientProtocol
80 client ClientProtocol 80 protocol Protocol
81 protocol Protocol 81 logger hclog.Logger
82 logger hclog.Logger 82 doneCtx context.Context
83 doneCtx context.Context 83 ctxCancel context.CancelFunc
84 negotiatedVersion int
85
86 // clientWaitGroup is used to manage the lifecycle of the plugin management
87 // goroutines.
88 clientWaitGroup sync.WaitGroup
89
90 // processKilled is used for testing only, to flag when the process was
91 // forcefully killed.
92 processKilled bool
93}
94
95// NegotiatedVersion returns the protocol version negotiated with the server.
96// This is only valid after Start() is called.
97func (c *Client) NegotiatedVersion() int {
98 return c.negotiatedVersion
84} 99}
85 100
86// ClientConfig is the configuration used to initialize a new 101// ClientConfig is the configuration used to initialize a new
@@ -91,7 +106,13 @@ type ClientConfig struct {
91 HandshakeConfig 106 HandshakeConfig
92 107
93 // Plugins are the plugins that can be consumed. 108 // Plugins are the plugins that can be consumed.
94 Plugins map[string]Plugin 109 // The implied version of this PluginSet is the Handshake.ProtocolVersion.
110 Plugins PluginSet
111
112 // VersionedPlugins is a map of PluginSets for specific protocol versions.
113 // These can be used to negotiate a compatible version between client and
114 // server. If this is set, Handshake.ProtocolVersion is not required.
115 VersionedPlugins map[int]PluginSet
95 116
96 // One of the following must be set, but not both. 117 // One of the following must be set, but not both.
97 // 118 //
@@ -158,6 +179,29 @@ type ClientConfig struct {
158 // Logger is the logger that the client will used. If none is provided, 179 // Logger is the logger that the client will used. If none is provided,
159 // it will default to hclog's default logger. 180 // it will default to hclog's default logger.
160 Logger hclog.Logger 181 Logger hclog.Logger
182
183 // AutoMTLS has the client and server automatically negotiate mTLS for
184 // transport authentication. This ensures that only the original client will
185 // be allowed to connect to the server, and all other connections will be
186 // rejected. The client will also refuse to connect to any server that isn't
187 // the original instance started by the client.
188 //
189 // In this mode of operation, the client generates a one-time use tls
190 // certificate, sends the public x.509 certificate to the new server, and
191 // the server generates a one-time use tls certificate, and sends the public
192 // x.509 certificate back to the client. These are used to authenticate all
193 // rpc connections between the client and server.
194 //
195 // Setting AutoMTLS to true implies that the server must support the
196 // protocol, and correctly negotiate the tls certificates, or a connection
197 // failure will result.
198 //
199 // The client should not set TLSConfig, nor should the server set a
200 // TLSProvider, because AutoMTLS implies that a new certificate and tls
201 // configuration will be generated at startup.
202 //
203 // You cannot Reattach to a server with this option enabled.
204 AutoMTLS bool
161} 205}
162 206
163// ReattachConfig is used to configure a client to reattach to an 207// ReattachConfig is used to configure a client to reattach to an
@@ -234,7 +278,6 @@ func CleanupClients() {
234 } 278 }
235 managedClientsLock.Unlock() 279 managedClientsLock.Unlock()
236 280
237 log.Println("[DEBUG] plugin: waiting for all plugin processes to complete...")
238 wg.Wait() 281 wg.Wait()
239} 282}
240 283
@@ -333,6 +376,14 @@ func (c *Client) Exited() bool {
333 return c.exited 376 return c.exited
334} 377}
335 378
379// killed is used in tests to check if a process failed to exit gracefully, and
380// needed to be killed.
381func (c *Client) killed() bool {
382 c.l.Lock()
383 defer c.l.Unlock()
384 return c.processKilled
385}
386
336// End the executing subprocess (if it is running) and perform any cleanup 387// End the executing subprocess (if it is running) and perform any cleanup
337// tasks necessary such as capturing any remaining logs and so on. 388// tasks necessary such as capturing any remaining logs and so on.
338// 389//
@@ -344,14 +395,24 @@ func (c *Client) Kill() {
344 c.l.Lock() 395 c.l.Lock()
345 process := c.process 396 process := c.process
346 addr := c.address 397 addr := c.address
347 doneCh := c.doneLogging
348 c.l.Unlock() 398 c.l.Unlock()
349 399
350 // If there is no process, we never started anything. Nothing to kill. 400 // If there is no process, there is nothing to kill.
351 if process == nil { 401 if process == nil {
352 return 402 return
353 } 403 }
354 404
405 defer func() {
406 // Wait for the all client goroutines to finish.
407 c.clientWaitGroup.Wait()
408
409 // Make sure there is no reference to the old process after it has been
410 // killed.
411 c.l.Lock()
412 c.process = nil
413 c.l.Unlock()
414 }()
415
355 // We need to check for address here. It is possible that the plugin 416 // We need to check for address here. It is possible that the plugin
356 // started (process != nil) but has no address (addr == nil) if the 417 // started (process != nil) but has no address (addr == nil) if the
357 // plugin failed at startup. If we do have an address, we need to close 418 // plugin failed at startup. If we do have an address, we need to close
@@ -372,6 +433,8 @@ func (c *Client) Kill() {
372 // kill in a moment anyways. 433 // kill in a moment anyways.
373 c.logger.Warn("error closing client during Kill", "err", err) 434 c.logger.Warn("error closing client during Kill", "err", err)
374 } 435 }
436 } else {
437 c.logger.Error("client", "error", err)
375 } 438 }
376 } 439 }
377 440
@@ -380,17 +443,20 @@ func (c *Client) Kill() {
380 // doneCh which would be closed if the process exits. 443 // doneCh which would be closed if the process exits.
381 if graceful { 444 if graceful {
382 select { 445 select {
383 case <-doneCh: 446 case <-c.doneCtx.Done():
447 c.logger.Debug("plugin exited")
384 return 448 return
385 case <-time.After(250 * time.Millisecond): 449 case <-time.After(2 * time.Second):
386 } 450 }
387 } 451 }
388 452
389 // If graceful exiting failed, just kill it 453 // If graceful exiting failed, just kill it
454 c.logger.Warn("plugin failed to exit gracefully")
390 process.Kill() 455 process.Kill()
391 456
392 // Wait for the client to finish logging so we have a complete log 457 c.l.Lock()
393 <-doneCh 458 c.processKilled = true
459 c.l.Unlock()
394} 460}
395 461
396// Starts the underlying subprocess, communicating with it to negotiate 462// Starts the underlying subprocess, communicating with it to negotiate
@@ -409,7 +475,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
409 475
410 // If one of cmd or reattach isn't set, then it is an error. We wrap 476 // If one of cmd or reattach isn't set, then it is an error. We wrap
411 // this in a {} for scoping reasons, and hopeful that the escape 477 // this in a {} for scoping reasons, and hopeful that the escape
412 // analysis will pop the stock here. 478 // analysis will pop the stack here.
413 { 479 {
414 cmdSet := c.config.Cmd != nil 480 cmdSet := c.config.Cmd != nil
415 attachSet := c.config.Reattach != nil 481 attachSet := c.config.Reattach != nil
@@ -423,77 +489,49 @@ func (c *Client) Start() (addr net.Addr, err error) {
423 } 489 }
424 } 490 }
425 491
426 // Create the logging channel for when we kill
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())
431
432 if c.config.Reattach != nil { 492 if c.config.Reattach != nil {
433 // Verify the process still exists. If not, then it is an error 493 return c.reattach()
434 p, err := os.FindProcess(c.config.Reattach.Pid) 494 }
435 if err != nil {
436 return nil, err
437 }
438 495
439 // Attempt to connect to the addr since on Unix systems FindProcess 496 if c.config.VersionedPlugins == nil {
440 // doesn't actually return an error if it can't find the process. 497 c.config.VersionedPlugins = make(map[int]PluginSet)
441 conn, err := net.Dial( 498 }
442 c.config.Reattach.Addr.Network(),
443 c.config.Reattach.Addr.String())
444 if err != nil {
445 p.Kill()
446 return nil, ErrProcessNotFound
447 }
448 conn.Close()
449
450 // Goroutine to mark exit status
451 go func(pid int) {
452 // Wait for the process to die
453 pidWait(pid)
454
455 // Log so we can see it
456 c.logger.Debug("reattached plugin process exited")
457
458 // Mark it
459 c.l.Lock()
460 defer c.l.Unlock()
461 c.exited = true
462
463 // Close the logging channel since that doesn't work on reattach
464 close(c.doneLogging)
465
466 // Cancel the context
467 ctxCancel()
468 }(p.Pid)
469
470 // Set the address and process
471 c.address = c.config.Reattach.Addr
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 }
478 499
479 return c.address, nil 500 // handle all plugins as versioned, using the handshake config as the default.
501 version := int(c.config.ProtocolVersion)
502
503 // Make sure we're not overwriting a real version 0. If ProtocolVersion was
504 // non-zero, then we have to just assume the user made sure that
505 // VersionedPlugins doesn't conflict.
506 if _, ok := c.config.VersionedPlugins[version]; !ok && c.config.Plugins != nil {
507 c.config.VersionedPlugins[version] = c.config.Plugins
508 }
509
510 var versionStrings []string
511 for v := range c.config.VersionedPlugins {
512 versionStrings = append(versionStrings, strconv.Itoa(v))
480 } 513 }
481 514
482 env := []string{ 515 env := []string{
483 fmt.Sprintf("%s=%s", c.config.MagicCookieKey, c.config.MagicCookieValue), 516 fmt.Sprintf("%s=%s", c.config.MagicCookieKey, c.config.MagicCookieValue),
484 fmt.Sprintf("PLUGIN_MIN_PORT=%d", c.config.MinPort), 517 fmt.Sprintf("PLUGIN_MIN_PORT=%d", c.config.MinPort),
485 fmt.Sprintf("PLUGIN_MAX_PORT=%d", c.config.MaxPort), 518 fmt.Sprintf("PLUGIN_MAX_PORT=%d", c.config.MaxPort),
519 fmt.Sprintf("PLUGIN_PROTOCOL_VERSIONS=%s", strings.Join(versionStrings, ",")),
486 } 520 }
487 521
488 stdout_r, stdout_w := io.Pipe()
489 stderr_r, stderr_w := io.Pipe()
490
491 cmd := c.config.Cmd 522 cmd := c.config.Cmd
492 cmd.Env = append(cmd.Env, os.Environ()...) 523 cmd.Env = append(cmd.Env, os.Environ()...)
493 cmd.Env = append(cmd.Env, env...) 524 cmd.Env = append(cmd.Env, env...)
494 cmd.Stdin = os.Stdin 525 cmd.Stdin = os.Stdin
495 cmd.Stderr = stderr_w 526
496 cmd.Stdout = stdout_w 527 cmdStdout, err := cmd.StdoutPipe()
528 if err != nil {
529 return nil, err
530 }
531 cmdStderr, err := cmd.StderrPipe()
532 if err != nil {
533 return nil, err
534 }
497 535
498 if c.config.SecureConfig != nil { 536 if c.config.SecureConfig != nil {
499 if ok, err := c.config.SecureConfig.Check(cmd.Path); err != nil { 537 if ok, err := c.config.SecureConfig.Check(cmd.Path); err != nil {
@@ -503,6 +541,29 @@ func (c *Client) Start() (addr net.Addr, err error) {
503 } 541 }
504 } 542 }
505 543
544 // Setup a temporary certificate for client/server mtls, and send the public
545 // certificate to the plugin.
546 if c.config.AutoMTLS {
547 c.logger.Info("configuring client automatic mTLS")
548 certPEM, keyPEM, err := generateCert()
549 if err != nil {
550 c.logger.Error("failed to generate client certificate", "error", err)
551 return nil, err
552 }
553 cert, err := tls.X509KeyPair(certPEM, keyPEM)
554 if err != nil {
555 c.logger.Error("failed to parse client certificate", "error", err)
556 return nil, err
557 }
558
559 cmd.Env = append(cmd.Env, fmt.Sprintf("PLUGIN_CLIENT_CERT=%s", certPEM))
560
561 c.config.TLSConfig = &tls.Config{
562 Certificates: []tls.Certificate{cert},
563 ServerName: "localhost",
564 }
565 }
566
506 c.logger.Debug("starting plugin", "path", cmd.Path, "args", cmd.Args) 567 c.logger.Debug("starting plugin", "path", cmd.Path, "args", cmd.Args)
507 err = cmd.Start() 568 err = cmd.Start()
508 if err != nil { 569 if err != nil {
@@ -511,6 +572,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
511 572
512 // Set the process 573 // Set the process
513 c.process = cmd.Process 574 c.process = cmd.Process
575 c.logger.Debug("plugin started", "path", cmd.Path, "pid", c.process.Pid)
514 576
515 // Make sure the command is properly cleaned up if there is an error 577 // Make sure the command is properly cleaned up if there is an error
516 defer func() { 578 defer func() {
@@ -525,27 +587,37 @@ func (c *Client) Start() (addr net.Addr, err error) {
525 } 587 }
526 }() 588 }()
527 589
528 // Start goroutine to wait for process to exit 590 // Create a context for when we kill
529 exitCh := make(chan struct{}) 591 c.doneCtx, c.ctxCancel = context.WithCancel(context.Background())
592
593 c.clientWaitGroup.Add(1)
530 go func() { 594 go func() {
531 // Make sure we close the write end of our stderr/stdout so 595 // ensure the context is cancelled when we're done
532 // that the readers send EOF properly. 596 defer c.ctxCancel()
533 defer stderr_w.Close() 597
534 defer stdout_w.Close() 598 defer c.clientWaitGroup.Done()
599
600 // get the cmd info early, since the process information will be removed
601 // in Kill.
602 pid := c.process.Pid
603 path := cmd.Path
535 604
536 // Wait for the command to end. 605 // Wait for the command to end.
537 cmd.Wait() 606 err := cmd.Wait()
607
608 debugMsgArgs := []interface{}{
609 "path", path,
610 "pid", pid,
611 }
612 if err != nil {
613 debugMsgArgs = append(debugMsgArgs,
614 []interface{}{"error", err.Error()}...)
615 }
538 616
539 // Log and make sure to flush the logs write away 617 // Log and make sure to flush the logs write away
540 c.logger.Debug("plugin process exited", "path", cmd.Path) 618 c.logger.Debug("plugin process exited", debugMsgArgs...)
541 os.Stderr.Sync() 619 os.Stderr.Sync()
542 620
543 // Mark that we exited
544 close(exitCh)
545
546 // Cancel the context, marking that we exited
547 ctxCancel()
548
549 // Set that we exited, which takes a lock 621 // Set that we exited, which takes a lock
550 c.l.Lock() 622 c.l.Lock()
551 defer c.l.Unlock() 623 defer c.l.Unlock()
@@ -553,32 +625,33 @@ func (c *Client) Start() (addr net.Addr, err error) {
553 }() 625 }()
554 626
555 // Start goroutine that logs the stderr 627 // Start goroutine that logs the stderr
556 go c.logStderr(stderr_r) 628 c.clientWaitGroup.Add(1)
629 // logStderr calls Done()
630 go c.logStderr(cmdStderr)
557 631
558 // Start a goroutine that is going to be reading the lines 632 // Start a goroutine that is going to be reading the lines
559 // out of stdout 633 // out of stdout
560 linesCh := make(chan []byte) 634 linesCh := make(chan string)
635 c.clientWaitGroup.Add(1)
561 go func() { 636 go func() {
637 defer c.clientWaitGroup.Done()
562 defer close(linesCh) 638 defer close(linesCh)
563 639
564 buf := bufio.NewReader(stdout_r) 640 scanner := bufio.NewScanner(cmdStdout)
565 for { 641 for scanner.Scan() {
566 line, err := buf.ReadBytes('\n') 642 linesCh <- scanner.Text()
567 if line != nil {
568 linesCh <- line
569 }
570
571 if err == io.EOF {
572 return
573 }
574 } 643 }
575 }() 644 }()
576 645
577 // Make sure after we exit we read the lines from stdout forever 646 // Make sure after we exit we read the lines from stdout forever
578 // so they don't block since it is an io.Pipe 647 // so they don't block since it is a pipe.
648 // The scanner goroutine above will close this, but track it with a wait
649 // group for completeness.
650 c.clientWaitGroup.Add(1)
579 defer func() { 651 defer func() {
580 go func() { 652 go func() {
581 for _ = range linesCh { 653 defer c.clientWaitGroup.Done()
654 for range linesCh {
582 } 655 }
583 }() 656 }()
584 }() 657 }()
@@ -591,12 +664,12 @@ func (c *Client) Start() (addr net.Addr, err error) {
591 select { 664 select {
592 case <-timeout: 665 case <-timeout:
593 err = errors.New("timeout while waiting for plugin to start") 666 err = errors.New("timeout while waiting for plugin to start")
594 case <-exitCh: 667 case <-c.doneCtx.Done():
595 err = errors.New("plugin exited before we could connect") 668 err = errors.New("plugin exited before we could connect")
596 case lineBytes := <-linesCh: 669 case line := <-linesCh:
597 // Trim the line and split by "|" in order to get the parts of 670 // Trim the line and split by "|" in order to get the parts of
598 // the output. 671 // the output.
599 line := strings.TrimSpace(string(lineBytes)) 672 line = strings.TrimSpace(line)
600 parts := strings.SplitN(line, "|", 6) 673 parts := strings.SplitN(line, "|", 6)
601 if len(parts) < 4 { 674 if len(parts) < 4 {
602 err = fmt.Errorf( 675 err = fmt.Errorf(
@@ -624,20 +697,18 @@ func (c *Client) Start() (addr net.Addr, err error) {
624 } 697 }
625 } 698 }
626 699
627 // Parse the protocol version 700 // Test the API version
628 var protocol int64 701 version, pluginSet, err := c.checkProtoVersion(parts[1])
629 protocol, err = strconv.ParseInt(parts[1], 10, 0)
630 if err != nil { 702 if err != nil {
631 err = fmt.Errorf("Error parsing protocol version: %s", err) 703 return addr, err
632 return
633 } 704 }
634 705
635 // Test the API version 706 // set the Plugins value to the compatible set, so the version
636 if uint(protocol) != c.config.ProtocolVersion { 707 // doesn't need to be passed through to the ClientProtocol
637 err = fmt.Errorf("Incompatible API version with plugin. "+ 708 // implementation.
638 "Plugin version: %s, Core version: %d", parts[1], c.config.ProtocolVersion) 709 c.config.Plugins = pluginSet
639 return 710 c.negotiatedVersion = version
640 } 711 c.logger.Debug("using plugin", "version", version)
641 712
642 switch parts[2] { 713 switch parts[2] {
643 case "tcp": 714 case "tcp":
@@ -665,15 +736,125 @@ func (c *Client) Start() (addr net.Addr, err error) {
665 if !found { 736 if !found {
666 err = fmt.Errorf("Unsupported plugin protocol %q. Supported: %v", 737 err = fmt.Errorf("Unsupported plugin protocol %q. Supported: %v",
667 c.protocol, c.config.AllowedProtocols) 738 c.protocol, c.config.AllowedProtocols)
668 return 739 return addr, err
669 } 740 }
670 741
742 // See if we have a TLS certificate from the server.
743 // Checking if the length is > 50 rules out catching the unused "extra"
744 // data returned from some older implementations.
745 if len(parts) >= 6 && len(parts[5]) > 50 {
746 err := c.loadServerCert(parts[5])
747 if err != nil {
748 return nil, fmt.Errorf("error parsing server cert: %s", err)
749 }
750 }
671 } 751 }
672 752
673 c.address = addr 753 c.address = addr
674 return 754 return
675} 755}
676 756
757// loadServerCert is used by AutoMTLS to read an x.509 cert returned by the
758// server, and load it as the RootCA for the client TLSConfig.
759func (c *Client) loadServerCert(cert string) error {
760 certPool := x509.NewCertPool()
761
762 asn1, err := base64.RawStdEncoding.DecodeString(cert)
763 if err != nil {
764 return err
765 }
766
767 x509Cert, err := x509.ParseCertificate([]byte(asn1))
768 if err != nil {
769 return err
770 }
771
772 certPool.AddCert(x509Cert)
773
774 c.config.TLSConfig.RootCAs = certPool
775 return nil
776}
777
778func (c *Client) reattach() (net.Addr, error) {
779 // Verify the process still exists. If not, then it is an error
780 p, err := os.FindProcess(c.config.Reattach.Pid)
781 if err != nil {
782 return nil, err
783 }
784
785 // Attempt to connect to the addr since on Unix systems FindProcess
786 // doesn't actually return an error if it can't find the process.
787 conn, err := net.Dial(
788 c.config.Reattach.Addr.Network(),
789 c.config.Reattach.Addr.String())
790 if err != nil {
791 p.Kill()
792 return nil, ErrProcessNotFound
793 }
794 conn.Close()
795
796 // Create a context for when we kill
797 c.doneCtx, c.ctxCancel = context.WithCancel(context.Background())
798
799 c.clientWaitGroup.Add(1)
800 // Goroutine to mark exit status
801 go func(pid int) {
802 defer c.clientWaitGroup.Done()
803
804 // ensure the context is cancelled when we're done
805 defer c.ctxCancel()
806
807 // Wait for the process to die
808 pidWait(pid)
809
810 // Log so we can see it
811 c.logger.Debug("reattached plugin process exited")
812
813 // Mark it
814 c.l.Lock()
815 defer c.l.Unlock()
816 c.exited = true
817 }(p.Pid)
818
819 // Set the address and process
820 c.address = c.config.Reattach.Addr
821 c.process = p
822 c.protocol = c.config.Reattach.Protocol
823 if c.protocol == "" {
824 // Default the protocol to net/rpc for backwards compatibility
825 c.protocol = ProtocolNetRPC
826 }
827
828 return c.address, nil
829}
830
831// checkProtoVersion returns the negotiated version and PluginSet.
832// This returns an error if the server returned an incompatible protocol
833// version, or an invalid handshake response.
834func (c *Client) checkProtoVersion(protoVersion string) (int, PluginSet, error) {
835 serverVersion, err := strconv.Atoi(protoVersion)
836 if err != nil {
837 return 0, nil, fmt.Errorf("Error parsing protocol version %q: %s", protoVersion, err)
838 }
839
840 // record these for the error message
841 var clientVersions []int
842
843 // all versions, including the legacy ProtocolVersion have been added to
844 // the versions set
845 for version, plugins := range c.config.VersionedPlugins {
846 clientVersions = append(clientVersions, version)
847
848 if serverVersion != version {
849 continue
850 }
851 return version, plugins, nil
852 }
853
854 return 0, nil, fmt.Errorf("Incompatible API version with plugin. "+
855 "Plugin version: %d, Client versions: %d", serverVersion, clientVersions)
856}
857
677// ReattachConfig returns the information that must be provided to NewClient 858// ReattachConfig returns the information that must be provided to NewClient
678// to reattach to the plugin process that this client started. This is 859// to reattach to the plugin process that this client started. This is
679// useful for plugins that detach from their parent process. 860// useful for plugins that detach from their parent process.
@@ -751,44 +932,84 @@ func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) {
751 return conn, nil 932 return conn, nil
752} 933}
753 934
935var stdErrBufferSize = 64 * 1024
936
754func (c *Client) logStderr(r io.Reader) { 937func (c *Client) logStderr(r io.Reader) {
755 bufR := bufio.NewReader(r) 938 defer c.clientWaitGroup.Done()
939 l := c.logger.Named(filepath.Base(c.config.Cmd.Path))
940
941 reader := bufio.NewReaderSize(r, stdErrBufferSize)
942 // continuation indicates the previous line was a prefix
943 continuation := false
944
756 for { 945 for {
757 line, err := bufR.ReadString('\n') 946 line, isPrefix, err := reader.ReadLine()
758 if line != "" { 947 switch {
759 c.config.Stderr.Write([]byte(line)) 948 case err == io.EOF:
760 line = strings.TrimRightFunc(line, unicode.IsSpace) 949 return
950 case err != nil:
951 l.Error("reading plugin stderr", "error", err)
952 return
953 }
761 954
762 l := c.logger.Named(filepath.Base(c.config.Cmd.Path)) 955 c.config.Stderr.Write(line)
763 956
764 entry, err := parseJSON(line) 957 // The line was longer than our max token size, so it's likely
765 // If output is not JSON format, print directly to Debug 958 // incomplete and won't unmarshal.
766 if err != nil { 959 if isPrefix || continuation {
767 l.Debug(line) 960 l.Debug(string(line))
768 } else { 961
769 out := flattenKVPairs(entry.KVPairs) 962 // if we're finishing a continued line, add the newline back in
770 963 if !isPrefix {
771 l = l.With("timestamp", entry.Timestamp.Format(hclog.TimeFormat)) 964 c.config.Stderr.Write([]byte{'\n'})
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 } 965 }
966
967 continuation = isPrefix
968 continue
785 } 969 }
786 970
787 if err == io.EOF { 971 c.config.Stderr.Write([]byte{'\n'})
788 break 972
973 entry, err := parseJSON(line)
974 // If output is not JSON format, print directly to Debug
975 if err != nil {
976 // Attempt to infer the desired log level from the commonly used
977 // string prefixes
978 switch line := string(line); {
979 case strings.HasPrefix(line, "[TRACE]"):
980 l.Trace(line)
981 case strings.HasPrefix(line, "[DEBUG]"):
982 l.Debug(line)
983 case strings.HasPrefix(line, "[INFO]"):
984 l.Info(line)
985 case strings.HasPrefix(line, "[WARN]"):
986 l.Warn(line)
987 case strings.HasPrefix(line, "[ERROR]"):
988 l.Error(line)
989 default:
990 l.Debug(line)
991 }
992 } else {
993 out := flattenKVPairs(entry.KVPairs)
994
995 out = append(out, "timestamp", entry.Timestamp.Format(hclog.TimeFormat))
996 switch hclog.LevelFromString(entry.Level) {
997 case hclog.Trace:
998 l.Trace(entry.Message, out...)
999 case hclog.Debug:
1000 l.Debug(entry.Message, out...)
1001 case hclog.Info:
1002 l.Info(entry.Message, out...)
1003 case hclog.Warn:
1004 l.Warn(entry.Message, out...)
1005 case hclog.Error:
1006 l.Error(entry.Message, out...)
1007 default:
1008 // if there was no log level, it's likely this is unexpected
1009 // json from something other than hclog, and we should output
1010 // it verbatim.
1011 l.Debug(string(line))
1012 }
789 } 1013 }
790 } 1014 }
791
792 // Flag that we've completed logging for others
793 close(c.doneLogging)
794} 1015}
diff --git a/vendor/github.com/hashicorp/go-plugin/go.mod b/vendor/github.com/hashicorp/go-plugin/go.mod
new file mode 100644
index 0000000..f3ddf44
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/go.mod
@@ -0,0 +1,17 @@
1module github.com/hashicorp/go-plugin
2
3require (
4 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
5 github.com/golang/protobuf v1.2.0
6 github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd
7 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb
8 github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77
9 github.com/oklog/run v1.0.0
10 github.com/stretchr/testify v1.3.0 // indirect
11 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
12 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
13 golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc // indirect
14 golang.org/x/text v0.3.0 // indirect
15 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 // indirect
16 google.golang.org/grpc v1.14.0
17)
diff --git a/vendor/github.com/hashicorp/go-plugin/go.sum b/vendor/github.com/hashicorp/go-plugin/go.sum
new file mode 100644
index 0000000..21b14e9
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/go.sum
@@ -0,0 +1,31 @@
1github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
4github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
5github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
6github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
7github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd h1:rNuUHR+CvK1IS89MMtcF0EpcVMZtjKfPRp4MEmt/aTs=
8github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
9github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
10github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
11github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
12github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
13github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
14github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
15github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
16github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
18github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
19github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
20golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
21golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
22golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
23golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
24golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ=
25golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
26golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
27golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
28google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
29google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
30google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo=
31google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go
index 49fd21c..daf142d 100644
--- a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go
+++ b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go
@@ -11,6 +11,8 @@ import (
11 "sync/atomic" 11 "sync/atomic"
12 "time" 12 "time"
13 13
14 "github.com/hashicorp/go-plugin/internal/plugin"
15
14 "github.com/oklog/run" 16 "github.com/oklog/run"
15 "google.golang.org/grpc" 17 "google.golang.org/grpc"
16 "google.golang.org/grpc/credentials" 18 "google.golang.org/grpc/credentials"
@@ -19,14 +21,14 @@ import (
19// streamer interface is used in the broker to send/receive connection 21// streamer interface is used in the broker to send/receive connection
20// information. 22// information.
21type streamer interface { 23type streamer interface {
22 Send(*ConnInfo) error 24 Send(*plugin.ConnInfo) error
23 Recv() (*ConnInfo, error) 25 Recv() (*plugin.ConnInfo, error)
24 Close() 26 Close()
25} 27}
26 28
27// sendErr is used to pass errors back during a send. 29// sendErr is used to pass errors back during a send.
28type sendErr struct { 30type sendErr struct {
29 i *ConnInfo 31 i *plugin.ConnInfo
30 ch chan error 32 ch chan error
31} 33}
32 34
@@ -38,7 +40,7 @@ type gRPCBrokerServer struct {
38 send chan *sendErr 40 send chan *sendErr
39 41
40 // recv is used to receive connection info from the gRPC stream. 42 // recv is used to receive connection info from the gRPC stream.
41 recv chan *ConnInfo 43 recv chan *plugin.ConnInfo
42 44
43 // quit closes down the stream. 45 // quit closes down the stream.
44 quit chan struct{} 46 quit chan struct{}
@@ -50,7 +52,7 @@ type gRPCBrokerServer struct {
50func newGRPCBrokerServer() *gRPCBrokerServer { 52func newGRPCBrokerServer() *gRPCBrokerServer {
51 return &gRPCBrokerServer{ 53 return &gRPCBrokerServer{
52 send: make(chan *sendErr), 54 send: make(chan *sendErr),
53 recv: make(chan *ConnInfo), 55 recv: make(chan *plugin.ConnInfo),
54 quit: make(chan struct{}), 56 quit: make(chan struct{}),
55 } 57 }
56} 58}
@@ -58,7 +60,7 @@ func newGRPCBrokerServer() *gRPCBrokerServer {
58// StartStream implements the GRPCBrokerServer interface and will block until 60// StartStream implements the GRPCBrokerServer interface and will block until
59// the quit channel is closed or the context reports Done. The stream will pass 61// the quit channel is closed or the context reports Done. The stream will pass
60// connection information to/from the client. 62// connection information to/from the client.
61func (s *gRPCBrokerServer) StartStream(stream GRPCBroker_StartStreamServer) error { 63func (s *gRPCBrokerServer) StartStream(stream plugin.GRPCBroker_StartStreamServer) error {
62 doneCh := stream.Context().Done() 64 doneCh := stream.Context().Done()
63 defer s.Close() 65 defer s.Close()
64 66
@@ -97,7 +99,7 @@ func (s *gRPCBrokerServer) StartStream(stream GRPCBroker_StartStreamServer) erro
97 99
98// Send is used by the GRPCBroker to pass connection information into the stream 100// Send is used by the GRPCBroker to pass connection information into the stream
99// to the client. 101// to the client.
100func (s *gRPCBrokerServer) Send(i *ConnInfo) error { 102func (s *gRPCBrokerServer) Send(i *plugin.ConnInfo) error {
101 ch := make(chan error) 103 ch := make(chan error)
102 defer close(ch) 104 defer close(ch)
103 105
@@ -115,7 +117,7 @@ func (s *gRPCBrokerServer) Send(i *ConnInfo) error {
115 117
116// Recv is used by the GRPCBroker to pass connection information that has been 118// Recv is used by the GRPCBroker to pass connection information that has been
117// sent from the client from the stream to the broker. 119// sent from the client from the stream to the broker.
118func (s *gRPCBrokerServer) Recv() (*ConnInfo, error) { 120func (s *gRPCBrokerServer) Recv() (*plugin.ConnInfo, error) {
119 select { 121 select {
120 case <-s.quit: 122 case <-s.quit:
121 return nil, errors.New("broker closed") 123 return nil, errors.New("broker closed")
@@ -136,13 +138,13 @@ func (s *gRPCBrokerServer) Close() {
136// streamer interfaces. 138// streamer interfaces.
137type gRPCBrokerClientImpl struct { 139type gRPCBrokerClientImpl struct {
138 // client is the underlying GRPC client used to make calls to the server. 140 // client is the underlying GRPC client used to make calls to the server.
139 client GRPCBrokerClient 141 client plugin.GRPCBrokerClient
140 142
141 // send is used to send connection info to the gRPC stream. 143 // send is used to send connection info to the gRPC stream.
142 send chan *sendErr 144 send chan *sendErr
143 145
144 // recv is used to receive connection info from the gRPC stream. 146 // recv is used to receive connection info from the gRPC stream.
145 recv chan *ConnInfo 147 recv chan *plugin.ConnInfo
146 148
147 // quit closes down the stream. 149 // quit closes down the stream.
148 quit chan struct{} 150 quit chan struct{}
@@ -153,9 +155,9 @@ type gRPCBrokerClientImpl struct {
153 155
154func newGRPCBrokerClient(conn *grpc.ClientConn) *gRPCBrokerClientImpl { 156func newGRPCBrokerClient(conn *grpc.ClientConn) *gRPCBrokerClientImpl {
155 return &gRPCBrokerClientImpl{ 157 return &gRPCBrokerClientImpl{
156 client: NewGRPCBrokerClient(conn), 158 client: plugin.NewGRPCBrokerClient(conn),
157 send: make(chan *sendErr), 159 send: make(chan *sendErr),
158 recv: make(chan *ConnInfo), 160 recv: make(chan *plugin.ConnInfo),
159 quit: make(chan struct{}), 161 quit: make(chan struct{}),
160 } 162 }
161} 163}
@@ -207,7 +209,7 @@ func (s *gRPCBrokerClientImpl) StartStream() error {
207 209
208// Send is used by the GRPCBroker to pass connection information into the stream 210// Send is used by the GRPCBroker to pass connection information into the stream
209// to the plugin. 211// to the plugin.
210func (s *gRPCBrokerClientImpl) Send(i *ConnInfo) error { 212func (s *gRPCBrokerClientImpl) Send(i *plugin.ConnInfo) error {
211 ch := make(chan error) 213 ch := make(chan error)
212 defer close(ch) 214 defer close(ch)
213 215
@@ -225,7 +227,7 @@ func (s *gRPCBrokerClientImpl) Send(i *ConnInfo) error {
225 227
226// Recv is used by the GRPCBroker to pass connection information that has been 228// Recv is used by the GRPCBroker to pass connection information that has been
227// sent from the plugin to the broker. 229// sent from the plugin to the broker.
228func (s *gRPCBrokerClientImpl) Recv() (*ConnInfo, error) { 230func (s *gRPCBrokerClientImpl) Recv() (*plugin.ConnInfo, error) {
229 select { 231 select {
230 case <-s.quit: 232 case <-s.quit:
231 return nil, errors.New("broker closed") 233 return nil, errors.New("broker closed")
@@ -266,7 +268,7 @@ type GRPCBroker struct {
266} 268}
267 269
268type gRPCBrokerPending struct { 270type gRPCBrokerPending struct {
269 ch chan *ConnInfo 271 ch chan *plugin.ConnInfo
270 doneCh chan struct{} 272 doneCh chan struct{}
271} 273}
272 274
@@ -288,7 +290,7 @@ func (b *GRPCBroker) Accept(id uint32) (net.Listener, error) {
288 return nil, err 290 return nil, err
289 } 291 }
290 292
291 err = b.streamer.Send(&ConnInfo{ 293 err = b.streamer.Send(&plugin.ConnInfo{
292 ServiceId: id, 294 ServiceId: id,
293 Network: listener.Addr().Network(), 295 Network: listener.Addr().Network(),
294 Address: listener.Addr().String(), 296 Address: listener.Addr().String(),
@@ -363,7 +365,7 @@ func (b *GRPCBroker) Close() error {
363 365
364// Dial opens a connection by ID. 366// Dial opens a connection by ID.
365func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { 367func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) {
366 var c *ConnInfo 368 var c *plugin.ConnInfo
367 369
368 // Open the stream 370 // Open the stream
369 p := b.getStream(id) 371 p := b.getStream(id)
@@ -433,7 +435,7 @@ func (m *GRPCBroker) getStream(id uint32) *gRPCBrokerPending {
433 } 435 }
434 436
435 m.streams[id] = &gRPCBrokerPending{ 437 m.streams[id] = &gRPCBrokerPending{
436 ch: make(chan *ConnInfo, 1), 438 ch: make(chan *plugin.ConnInfo, 1),
437 doneCh: make(chan struct{}), 439 doneCh: make(chan struct{}),
438 } 440 }
439 return m.streams[id] 441 return m.streams[id]
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_client.go b/vendor/github.com/hashicorp/go-plugin/grpc_client.go
index 44294d0..294518e 100644
--- a/vendor/github.com/hashicorp/go-plugin/grpc_client.go
+++ b/vendor/github.com/hashicorp/go-plugin/grpc_client.go
@@ -6,6 +6,7 @@ import (
6 "net" 6 "net"
7 "time" 7 "time"
8 8
9 "github.com/hashicorp/go-plugin/internal/plugin"
9 "golang.org/x/net/context" 10 "golang.org/x/net/context"
10 "google.golang.org/grpc" 11 "google.golang.org/grpc"
11 "google.golang.org/grpc/credentials" 12 "google.golang.org/grpc/credentials"
@@ -16,12 +17,9 @@ func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn,
16 // Build dialing options. 17 // Build dialing options.
17 opts := make([]grpc.DialOption, 0, 5) 18 opts := make([]grpc.DialOption, 0, 5)
18 19
19 // We use a custom dialer so that we can connect over unix domain sockets 20 // We use a custom dialer so that we can connect over unix domain sockets.
20 opts = append(opts, grpc.WithDialer(dialer)) 21 opts = append(opts, grpc.WithDialer(dialer))
21 22
22 // go-plugin expects to block the connection
23 opts = append(opts, grpc.WithBlock())
24
25 // Fail right away 23 // Fail right away
26 opts = append(opts, grpc.FailOnNonTempDialError(true)) 24 opts = append(opts, grpc.FailOnNonTempDialError(true))
27 25
@@ -58,12 +56,15 @@ func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) {
58 go broker.Run() 56 go broker.Run()
59 go brokerGRPCClient.StartStream() 57 go brokerGRPCClient.StartStream()
60 58
61 return &GRPCClient{ 59 cl := &GRPCClient{
62 Conn: conn, 60 Conn: conn,
63 Plugins: c.config.Plugins, 61 Plugins: c.config.Plugins,
64 doneCtx: doneCtx, 62 doneCtx: doneCtx,
65 broker: broker, 63 broker: broker,
66 }, nil 64 controller: plugin.NewGRPCControllerClient(conn),
65 }
66
67 return cl, nil
67} 68}
68 69
69// GRPCClient connects to a GRPCServer over gRPC to dispense plugin types. 70// GRPCClient connects to a GRPCServer over gRPC to dispense plugin types.
@@ -73,11 +74,14 @@ type GRPCClient struct {
73 74
74 doneCtx context.Context 75 doneCtx context.Context
75 broker *GRPCBroker 76 broker *GRPCBroker
77
78 controller plugin.GRPCControllerClient
76} 79}
77 80
78// ClientProtocol impl. 81// ClientProtocol impl.
79func (c *GRPCClient) Close() error { 82func (c *GRPCClient) Close() error {
80 c.broker.Close() 83 c.broker.Close()
84 c.controller.Shutdown(c.doneCtx, &plugin.Empty{})
81 return c.Conn.Close() 85 return c.Conn.Close()
82} 86}
83 87
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_controller.go b/vendor/github.com/hashicorp/go-plugin/grpc_controller.go
new file mode 100644
index 0000000..1a8a8e7
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/grpc_controller.go
@@ -0,0 +1,23 @@
1package plugin
2
3import (
4 "context"
5
6 "github.com/hashicorp/go-plugin/internal/plugin"
7)
8
9// GRPCControllerServer handles shutdown calls to terminate the server when the
10// plugin client is closed.
11type grpcControllerServer struct {
12 server *GRPCServer
13}
14
15// Shutdown stops the grpc server. It first will attempt a graceful stop, then a
16// full stop on the server.
17func (s *grpcControllerServer) Shutdown(ctx context.Context, _ *plugin.Empty) (*plugin.Empty, error) {
18 resp := &plugin.Empty{}
19
20 // TODO: figure out why GracefullStop doesn't work.
21 s.server.Stop()
22 return resp, nil
23}
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_server.go b/vendor/github.com/hashicorp/go-plugin/grpc_server.go
index 3a72739..d3dbf1c 100644
--- a/vendor/github.com/hashicorp/go-plugin/grpc_server.go
+++ b/vendor/github.com/hashicorp/go-plugin/grpc_server.go
@@ -8,6 +8,8 @@ import (
8 "io" 8 "io"
9 "net" 9 "net"
10 10
11 hclog "github.com/hashicorp/go-hclog"
12 "github.com/hashicorp/go-plugin/internal/plugin"
11 "google.golang.org/grpc" 13 "google.golang.org/grpc"
12 "google.golang.org/grpc/credentials" 14 "google.golang.org/grpc/credentials"
13 "google.golang.org/grpc/health" 15 "google.golang.org/grpc/health"
@@ -52,6 +54,8 @@ type GRPCServer struct {
52 config GRPCServerConfig 54 config GRPCServerConfig
53 server *grpc.Server 55 server *grpc.Server
54 broker *GRPCBroker 56 broker *GRPCBroker
57
58 logger hclog.Logger
55} 59}
56 60
57// ServerProtocol impl. 61// ServerProtocol impl.
@@ -71,10 +75,16 @@ func (s *GRPCServer) Init() error {
71 75
72 // Register the broker service 76 // Register the broker service
73 brokerServer := newGRPCBrokerServer() 77 brokerServer := newGRPCBrokerServer()
74 RegisterGRPCBrokerServer(s.server, brokerServer) 78 plugin.RegisterGRPCBrokerServer(s.server, brokerServer)
75 s.broker = newGRPCBroker(brokerServer, s.TLS) 79 s.broker = newGRPCBroker(brokerServer, s.TLS)
76 go s.broker.Run() 80 go s.broker.Run()
77 81
82 // Register the controller
83 controllerServer := &grpcControllerServer{
84 server: s,
85 }
86 plugin.RegisterGRPCControllerServer(s.server, controllerServer)
87
78 // Register all our plugins onto the gRPC server. 88 // Register all our plugins onto the gRPC server.
79 for k, raw := range s.Plugins { 89 for k, raw := range s.Plugins {
80 p, ok := raw.(GRPCPlugin) 90 p, ok := raw.(GRPCPlugin)
@@ -83,7 +93,7 @@ func (s *GRPCServer) Init() error {
83 } 93 }
84 94
85 if err := p.GRPCServer(s.broker, s.server); err != nil { 95 if err := p.GRPCServer(s.broker, s.server); err != nil {
86 return fmt.Errorf("error registring %q: %s", k, err) 96 return fmt.Errorf("error registering %q: %s", k, err)
87 } 97 }
88 } 98 }
89 99
@@ -117,11 +127,11 @@ func (s *GRPCServer) Config() string {
117} 127}
118 128
119func (s *GRPCServer) Serve(lis net.Listener) { 129func (s *GRPCServer) Serve(lis net.Listener) {
120 // Start serving in a goroutine 130 defer close(s.DoneCh)
121 go s.server.Serve(lis) 131 err := s.server.Serve(lis)
122 132 if err != nil {
123 // Wait until graceful completion 133 s.logger.Error("grpc server", "error", err)
124 <-s.DoneCh 134 }
125} 135}
126 136
127// GRPCServerConfig is the extra configuration passed along for consumers 137// GRPCServerConfig is the extra configuration passed along for consumers
diff --git a/vendor/github.com/hashicorp/go-plugin/internal/plugin/gen.go b/vendor/github.com/hashicorp/go-plugin/internal/plugin/gen.go
new file mode 100644
index 0000000..aa2fdc8
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/internal/plugin/gen.go
@@ -0,0 +1,3 @@
1//go:generate protoc -I ./ ./grpc_broker.proto ./grpc_controller.proto --go_out=plugins=grpc:.
2
3package plugin
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.pb.go
index d490daf..b6850aa 100644
--- a/vendor/github.com/hashicorp/go-plugin/grpc_broker.pb.go
+++ b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.pb.go
@@ -1,24 +1,14 @@
1// Code generated by protoc-gen-go. DO NOT EDIT. 1// Code generated by protoc-gen-go. DO NOT EDIT.
2// source: grpc_broker.proto 2// source: grpc_broker.proto
3 3
4/*
5Package plugin is a generated protocol buffer package.
6
7It is generated from these files:
8 grpc_broker.proto
9
10It has these top-level messages:
11 ConnInfo
12*/
13package plugin 4package plugin
14 5
15import proto "github.com/golang/protobuf/proto"
16import fmt "fmt"
17import math "math"
18
19import ( 6import (
7 fmt "fmt"
8 proto "github.com/golang/protobuf/proto"
20 context "golang.org/x/net/context" 9 context "golang.org/x/net/context"
21 grpc "google.golang.org/grpc" 10 grpc "google.golang.org/grpc"
11 math "math"
22) 12)
23 13
24// Reference imports to suppress errors if they are not otherwise used. 14// Reference imports to suppress errors if they are not otherwise used.
@@ -33,15 +23,38 @@ var _ = math.Inf
33const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 23const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
34 24
35type ConnInfo struct { 25type ConnInfo struct {
36 ServiceId uint32 `protobuf:"varint,1,opt,name=service_id,json=serviceId" json:"service_id,omitempty"` 26 ServiceId uint32 `protobuf:"varint,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
37 Network string `protobuf:"bytes,2,opt,name=network" json:"network,omitempty"` 27 Network string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
38 Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` 28 Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
29 XXX_NoUnkeyedLiteral struct{} `json:"-"`
30 XXX_unrecognized []byte `json:"-"`
31 XXX_sizecache int32 `json:"-"`
32}
33
34func (m *ConnInfo) Reset() { *m = ConnInfo{} }
35func (m *ConnInfo) String() string { return proto.CompactTextString(m) }
36func (*ConnInfo) ProtoMessage() {}
37func (*ConnInfo) Descriptor() ([]byte, []int) {
38 return fileDescriptor_802e9beed3ec3b28, []int{0}
39} 39}
40 40
41func (m *ConnInfo) Reset() { *m = ConnInfo{} } 41func (m *ConnInfo) XXX_Unmarshal(b []byte) error {
42func (m *ConnInfo) String() string { return proto.CompactTextString(m) } 42 return xxx_messageInfo_ConnInfo.Unmarshal(m, b)
43func (*ConnInfo) ProtoMessage() {} 43}
44func (*ConnInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 44func (m *ConnInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
45 return xxx_messageInfo_ConnInfo.Marshal(b, m, deterministic)
46}
47func (m *ConnInfo) XXX_Merge(src proto.Message) {
48 xxx_messageInfo_ConnInfo.Merge(m, src)
49}
50func (m *ConnInfo) XXX_Size() int {
51 return xxx_messageInfo_ConnInfo.Size(m)
52}
53func (m *ConnInfo) XXX_DiscardUnknown() {
54 xxx_messageInfo_ConnInfo.DiscardUnknown(m)
55}
56
57var xxx_messageInfo_ConnInfo proto.InternalMessageInfo
45 58
46func (m *ConnInfo) GetServiceId() uint32 { 59func (m *ConnInfo) GetServiceId() uint32 {
47 if m != nil { 60 if m != nil {
@@ -68,6 +81,23 @@ func init() {
68 proto.RegisterType((*ConnInfo)(nil), "plugin.ConnInfo") 81 proto.RegisterType((*ConnInfo)(nil), "plugin.ConnInfo")
69} 82}
70 83
84func init() { proto.RegisterFile("grpc_broker.proto", fileDescriptor_802e9beed3ec3b28) }
85
86var fileDescriptor_802e9beed3ec3b28 = []byte{
87 // 175 bytes of a gzipped FileDescriptorProto
88 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0x2f, 0x2a, 0x48,
89 0x8e, 0x4f, 0x2a, 0xca, 0xcf, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2b,
90 0xc8, 0x29, 0x4d, 0xcf, 0xcc, 0x53, 0x8a, 0xe5, 0xe2, 0x70, 0xce, 0xcf, 0xcb, 0xf3, 0xcc, 0x4b,
91 0xcb, 0x17, 0x92, 0xe5, 0xe2, 0x2a, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x8d, 0xcf, 0x4c, 0x91,
92 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0d, 0xe2, 0x84, 0x8a, 0x78, 0xa6, 0x08, 0x49, 0x70, 0xb1, 0xe7,
93 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x4b, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x20,
94 0x99, 0xc4, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0x62, 0x09, 0x66, 0x88, 0x0c, 0x94, 0x6b, 0xe4, 0xcc,
95 0xc5, 0xe5, 0x1e, 0x14, 0xe0, 0xec, 0x04, 0xb6, 0x5a, 0xc8, 0x94, 0x8b, 0x3b, 0xb8, 0x24, 0xb1,
96 0xa8, 0x24, 0xb8, 0xa4, 0x28, 0x35, 0x31, 0x57, 0x48, 0x40, 0x0f, 0xe2, 0x08, 0x3d, 0x98, 0x0b,
97 0xa4, 0x30, 0x44, 0x34, 0x18, 0x0d, 0x18, 0x9d, 0x38, 0xa2, 0xa0, 0xae, 0x4d, 0x62, 0x03, 0x3b,
98 0xde, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x10, 0x15, 0x39, 0x47, 0xd1, 0x00, 0x00, 0x00,
99}
100
71// Reference imports to suppress errors if they are not otherwise used. 101// Reference imports to suppress errors if they are not otherwise used.
72var _ context.Context 102var _ context.Context
73var _ grpc.ClientConn 103var _ grpc.ClientConn
@@ -76,8 +106,9 @@ var _ grpc.ClientConn
76// is compatible with the grpc package it is being compiled against. 106// is compatible with the grpc package it is being compiled against.
77const _ = grpc.SupportPackageIsVersion4 107const _ = grpc.SupportPackageIsVersion4
78 108
79// Client API for GRPCBroker service 109// GRPCBrokerClient is the client API for GRPCBroker service.
80 110//
111// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
81type GRPCBrokerClient interface { 112type GRPCBrokerClient interface {
82 StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) 113 StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error)
83} 114}
@@ -91,7 +122,7 @@ func NewGRPCBrokerClient(cc *grpc.ClientConn) GRPCBrokerClient {
91} 122}
92 123
93func (c *gRPCBrokerClient) StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) { 124func (c *gRPCBrokerClient) StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) {
94 stream, err := grpc.NewClientStream(ctx, &_GRPCBroker_serviceDesc.Streams[0], c.cc, "/plugin.GRPCBroker/StartStream", opts...) 125 stream, err := c.cc.NewStream(ctx, &_GRPCBroker_serviceDesc.Streams[0], "/plugin.GRPCBroker/StartStream", opts...)
95 if err != nil { 126 if err != nil {
96 return nil, err 127 return nil, err
97 } 128 }
@@ -121,8 +152,7 @@ func (x *gRPCBrokerStartStreamClient) Recv() (*ConnInfo, error) {
121 return m, nil 152 return m, nil
122} 153}
123 154
124// Server API for GRPCBroker service 155// GRPCBrokerServer is the server API for GRPCBroker service.
125
126type GRPCBrokerServer interface { 156type GRPCBrokerServer interface {
127 StartStream(GRPCBroker_StartStreamServer) error 157 StartStream(GRPCBroker_StartStreamServer) error
128} 158}
@@ -171,20 +201,3 @@ var _GRPCBroker_serviceDesc = grpc.ServiceDesc{
171 }, 201 },
172 Metadata: "grpc_broker.proto", 202 Metadata: "grpc_broker.proto",
173} 203}
174
175func init() { proto.RegisterFile("grpc_broker.proto", fileDescriptor0) }
176
177var fileDescriptor0 = []byte{
178 // 170 bytes of a gzipped FileDescriptorProto
179 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0x2f, 0x2a, 0x48,
180 0x8e, 0x4f, 0x2a, 0xca, 0xcf, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2b,
181 0xc8, 0x29, 0x4d, 0xcf, 0xcc, 0x53, 0x8a, 0xe5, 0xe2, 0x70, 0xce, 0xcf, 0xcb, 0xf3, 0xcc, 0x4b,
182 0xcb, 0x17, 0x92, 0xe5, 0xe2, 0x2a, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x8d, 0xcf, 0x4c, 0x91,
183 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0d, 0xe2, 0x84, 0x8a, 0x78, 0xa6, 0x08, 0x49, 0x70, 0xb1, 0xe7,
184 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x4b, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xb8, 0x20,
185 0x99, 0xc4, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0x62, 0x09, 0x66, 0x88, 0x0c, 0x94, 0x6b, 0xe4, 0xcc,
186 0xc5, 0xe5, 0x1e, 0x14, 0xe0, 0xec, 0x04, 0xb6, 0x5a, 0xc8, 0x94, 0x8b, 0x3b, 0xb8, 0x24, 0xb1,
187 0xa8, 0x24, 0xb8, 0xa4, 0x28, 0x35, 0x31, 0x57, 0x48, 0x40, 0x0f, 0xe2, 0x08, 0x3d, 0x98, 0x0b,
188 0xa4, 0x30, 0x44, 0x34, 0x18, 0x0d, 0x18, 0x93, 0xd8, 0xc0, 0x4e, 0x36, 0x06, 0x04, 0x00, 0x00,
189 0xff, 0xff, 0x7b, 0x5d, 0xfb, 0xe1, 0xc7, 0x00, 0x00, 0x00,
190}
diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.proto b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.proto
index f578348..3fa79e8 100644
--- a/vendor/github.com/hashicorp/go-plugin/grpc_broker.proto
+++ b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.proto
@@ -1,5 +1,6 @@
1syntax = "proto3"; 1syntax = "proto3";
2package plugin; 2package plugin;
3option go_package = "plugin";
3 4
4message ConnInfo { 5message ConnInfo {
5 uint32 service_id = 1; 6 uint32 service_id = 1;
diff --git a/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.pb.go b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.pb.go
new file mode 100644
index 0000000..38b4204
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.pb.go
@@ -0,0 +1,143 @@
1// Code generated by protoc-gen-go. DO NOT EDIT.
2// source: grpc_controller.proto
3
4package plugin
5
6import (
7 fmt "fmt"
8 proto "github.com/golang/protobuf/proto"
9 context "golang.org/x/net/context"
10 grpc "google.golang.org/grpc"
11 math "math"
12)
13
14// Reference imports to suppress errors if they are not otherwise used.
15var _ = proto.Marshal
16var _ = fmt.Errorf
17var _ = math.Inf
18
19// This is a compile-time assertion to ensure that this generated file
20// is compatible with the proto package it is being compiled against.
21// A compilation error at this line likely means your copy of the
22// proto package needs to be updated.
23const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
24
25type Empty struct {
26 XXX_NoUnkeyedLiteral struct{} `json:"-"`
27 XXX_unrecognized []byte `json:"-"`
28 XXX_sizecache int32 `json:"-"`
29}
30
31func (m *Empty) Reset() { *m = Empty{} }
32func (m *Empty) String() string { return proto.CompactTextString(m) }
33func (*Empty) ProtoMessage() {}
34func (*Empty) Descriptor() ([]byte, []int) {
35 return fileDescriptor_23c2c7e42feab570, []int{0}
36}
37
38func (m *Empty) XXX_Unmarshal(b []byte) error {
39 return xxx_messageInfo_Empty.Unmarshal(m, b)
40}
41func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
42 return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
43}
44func (m *Empty) XXX_Merge(src proto.Message) {
45 xxx_messageInfo_Empty.Merge(m, src)
46}
47func (m *Empty) XXX_Size() int {
48 return xxx_messageInfo_Empty.Size(m)
49}
50func (m *Empty) XXX_DiscardUnknown() {
51 xxx_messageInfo_Empty.DiscardUnknown(m)
52}
53
54var xxx_messageInfo_Empty proto.InternalMessageInfo
55
56func init() {
57 proto.RegisterType((*Empty)(nil), "plugin.Empty")
58}
59
60func init() { proto.RegisterFile("grpc_controller.proto", fileDescriptor_23c2c7e42feab570) }
61
62var fileDescriptor_23c2c7e42feab570 = []byte{
63 // 108 bytes of a gzipped FileDescriptorProto
64 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0x2f, 0x2a, 0x48,
65 0x8e, 0x4f, 0xce, 0xcf, 0x2b, 0x29, 0xca, 0xcf, 0xc9, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f,
66 0xc9, 0x17, 0x62, 0x2b, 0xc8, 0x29, 0x4d, 0xcf, 0xcc, 0x53, 0x62, 0xe7, 0x62, 0x75, 0xcd, 0x2d,
67 0x28, 0xa9, 0x34, 0xb2, 0xe2, 0xe2, 0x73, 0x0f, 0x0a, 0x70, 0x76, 0x86, 0x2b, 0x14, 0xd2, 0xe0,
68 0xe2, 0x08, 0xce, 0x28, 0x2d, 0x49, 0xc9, 0x2f, 0xcf, 0x13, 0xe2, 0xd5, 0x83, 0xa8, 0xd7, 0x03,
69 0x2b, 0x96, 0x42, 0xe5, 0x3a, 0x71, 0x44, 0x41, 0x8d, 0x4b, 0x62, 0x03, 0x9b, 0x6e, 0x0c, 0x08,
70 0x00, 0x00, 0xff, 0xff, 0xab, 0x7c, 0x27, 0xe5, 0x76, 0x00, 0x00, 0x00,
71}
72
73// Reference imports to suppress errors if they are not otherwise used.
74var _ context.Context
75var _ grpc.ClientConn
76
77// This is a compile-time assertion to ensure that this generated file
78// is compatible with the grpc package it is being compiled against.
79const _ = grpc.SupportPackageIsVersion4
80
81// GRPCControllerClient is the client API for GRPCController service.
82//
83// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
84type GRPCControllerClient interface {
85 Shutdown(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
86}
87
88type gRPCControllerClient struct {
89 cc *grpc.ClientConn
90}
91
92func NewGRPCControllerClient(cc *grpc.ClientConn) GRPCControllerClient {
93 return &gRPCControllerClient{cc}
94}
95
96func (c *gRPCControllerClient) Shutdown(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
97 out := new(Empty)
98 err := c.cc.Invoke(ctx, "/plugin.GRPCController/Shutdown", in, out, opts...)
99 if err != nil {
100 return nil, err
101 }
102 return out, nil
103}
104
105// GRPCControllerServer is the server API for GRPCController service.
106type GRPCControllerServer interface {
107 Shutdown(context.Context, *Empty) (*Empty, error)
108}
109
110func RegisterGRPCControllerServer(s *grpc.Server, srv GRPCControllerServer) {
111 s.RegisterService(&_GRPCController_serviceDesc, srv)
112}
113
114func _GRPCController_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
115 in := new(Empty)
116 if err := dec(in); err != nil {
117 return nil, err
118 }
119 if interceptor == nil {
120 return srv.(GRPCControllerServer).Shutdown(ctx, in)
121 }
122 info := &grpc.UnaryServerInfo{
123 Server: srv,
124 FullMethod: "/plugin.GRPCController/Shutdown",
125 }
126 handler := func(ctx context.Context, req interface{}) (interface{}, error) {
127 return srv.(GRPCControllerServer).Shutdown(ctx, req.(*Empty))
128 }
129 return interceptor(ctx, in, info, handler)
130}
131
132var _GRPCController_serviceDesc = grpc.ServiceDesc{
133 ServiceName: "plugin.GRPCController",
134 HandlerType: (*GRPCControllerServer)(nil),
135 Methods: []grpc.MethodDesc{
136 {
137 MethodName: "Shutdown",
138 Handler: _GRPCController_Shutdown_Handler,
139 },
140 },
141 Streams: []grpc.StreamDesc{},
142 Metadata: "grpc_controller.proto",
143}
diff --git a/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.proto b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.proto
new file mode 100644
index 0000000..345d0a1
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.proto
@@ -0,0 +1,11 @@
1syntax = "proto3";
2package plugin;
3option go_package = "plugin";
4
5message Empty {
6}
7
8// The GRPCController is responsible for telling the plugin server to shutdown.
9service GRPCController {
10 rpc Shutdown(Empty) returns (Empty);
11}
diff --git a/vendor/github.com/hashicorp/go-plugin/log_entry.go b/vendor/github.com/hashicorp/go-plugin/log_entry.go
index 2996c14..fb2ef93 100644
--- a/vendor/github.com/hashicorp/go-plugin/log_entry.go
+++ b/vendor/github.com/hashicorp/go-plugin/log_entry.go
@@ -32,11 +32,11 @@ func flattenKVPairs(kvs []*logEntryKV) []interface{} {
32} 32}
33 33
34// parseJSON handles parsing JSON output 34// parseJSON handles parsing JSON output
35func parseJSON(input string) (*logEntry, error) { 35func parseJSON(input []byte) (*logEntry, error) {
36 var raw map[string]interface{} 36 var raw map[string]interface{}
37 entry := &logEntry{} 37 entry := &logEntry{}
38 38
39 err := json.Unmarshal([]byte(input), &raw) 39 err := json.Unmarshal(input, &raw)
40 if err != nil { 40 if err != nil {
41 return nil, err 41 return nil, err
42 } 42 }
diff --git a/vendor/github.com/hashicorp/go-plugin/mtls.go b/vendor/github.com/hashicorp/go-plugin/mtls.go
new file mode 100644
index 0000000..8895524
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-plugin/mtls.go
@@ -0,0 +1,73 @@
1package plugin
2
3import (
4 "bytes"
5 "crypto/ecdsa"
6 "crypto/elliptic"
7 "crypto/rand"
8 "crypto/x509"
9 "crypto/x509/pkix"
10 "encoding/pem"
11 "math/big"
12 "time"
13)
14
15// generateCert generates a temporary certificate for plugin authentication. The
16// certificate and private key are returns in PEM format.
17func generateCert() (cert []byte, privateKey []byte, err error) {
18 key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
19 if err != nil {
20 return nil, nil, err
21 }
22
23 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
24 sn, err := rand.Int(rand.Reader, serialNumberLimit)
25 if err != nil {
26 return nil, nil, err
27 }
28
29 host := "localhost"
30
31 template := &x509.Certificate{
32 Subject: pkix.Name{
33 CommonName: host,
34 Organization: []string{"HashiCorp"},
35 },
36 DNSNames: []string{host},
37 ExtKeyUsage: []x509.ExtKeyUsage{
38 x509.ExtKeyUsageClientAuth,
39 x509.ExtKeyUsageServerAuth,
40 },
41 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement | x509.KeyUsageCertSign,
42 BasicConstraintsValid: true,
43 SerialNumber: sn,
44 NotBefore: time.Now().Add(-30 * time.Second),
45 NotAfter: time.Now().Add(262980 * time.Hour),
46 IsCA: true,
47 }
48
49 der, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key)
50 if err != nil {
51 return nil, nil, err
52 }
53
54 var certOut bytes.Buffer
55 if err := pem.Encode(&certOut, &pem.Block{Type: "CERTIFICATE", Bytes: der}); err != nil {
56 return nil, nil, err
57 }
58
59 keyBytes, err := x509.MarshalECPrivateKey(key)
60 if err != nil {
61 return nil, nil, err
62 }
63
64 var keyOut bytes.Buffer
65 if err := pem.Encode(&keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}); err != nil {
66 return nil, nil, err
67 }
68
69 cert = certOut.Bytes()
70 privateKey = keyOut.Bytes()
71
72 return cert, privateKey, nil
73}
diff --git a/vendor/github.com/hashicorp/go-plugin/server.go b/vendor/github.com/hashicorp/go-plugin/server.go
index 1e808b9..fc9f05a 100644
--- a/vendor/github.com/hashicorp/go-plugin/server.go
+++ b/vendor/github.com/hashicorp/go-plugin/server.go
@@ -2,6 +2,7 @@ package plugin
2 2
3import ( 3import (
4 "crypto/tls" 4 "crypto/tls"
5 "crypto/x509"
5 "encoding/base64" 6 "encoding/base64"
6 "errors" 7 "errors"
7 "fmt" 8 "fmt"
@@ -11,7 +12,9 @@ import (
11 "os" 12 "os"
12 "os/signal" 13 "os/signal"
13 "runtime" 14 "runtime"
15 "sort"
14 "strconv" 16 "strconv"
17 "strings"
15 "sync/atomic" 18 "sync/atomic"
16 19
17 "github.com/hashicorp/go-hclog" 20 "github.com/hashicorp/go-hclog"
@@ -36,6 +39,8 @@ type HandshakeConfig struct {
36 // ProtocolVersion is the version that clients must match on to 39 // ProtocolVersion is the version that clients must match on to
37 // agree they can communicate. This should match the ProtocolVersion 40 // agree they can communicate. This should match the ProtocolVersion
38 // set on ClientConfig when using a plugin. 41 // set on ClientConfig when using a plugin.
42 // This field is not required if VersionedPlugins are being used in the
43 // Client or Server configurations.
39 ProtocolVersion uint 44 ProtocolVersion uint
40 45
41 // MagicCookieKey and value are used as a very basic verification 46 // MagicCookieKey and value are used as a very basic verification
@@ -46,6 +51,10 @@ type HandshakeConfig struct {
46 MagicCookieValue string 51 MagicCookieValue string
47} 52}
48 53
54// PluginSet is a set of plugins provided to be registered in the plugin
55// server.
56type PluginSet map[string]Plugin
57
49// ServeConfig configures what sorts of plugins are served. 58// ServeConfig configures what sorts of plugins are served.
50type ServeConfig struct { 59type ServeConfig struct {
51 // HandshakeConfig is the configuration that must match clients. 60 // HandshakeConfig is the configuration that must match clients.
@@ -55,7 +64,13 @@ type ServeConfig struct {
55 TLSProvider func() (*tls.Config, error) 64 TLSProvider func() (*tls.Config, error)
56 65
57 // Plugins are the plugins that are served. 66 // Plugins are the plugins that are served.
58 Plugins map[string]Plugin 67 // The implied version of this PluginSet is the Handshake.ProtocolVersion.
68 Plugins PluginSet
69
70 // VersionedPlugins is a map of PluginSets for specific protocol versions.
71 // These can be used to negotiate a compatible version between client and
72 // server. If this is set, Handshake.ProtocolVersion is not required.
73 VersionedPlugins map[int]PluginSet
59 74
60 // GRPCServer should be non-nil to enable serving the plugins over 75 // 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 76 // gRPC. This is a function to create the server when needed with the
@@ -72,14 +87,83 @@ type ServeConfig struct {
72 Logger hclog.Logger 87 Logger hclog.Logger
73} 88}
74 89
75// Protocol returns the protocol that this server should speak. 90// protocolVersion determines the protocol version and plugin set to be used by
76func (c *ServeConfig) Protocol() Protocol { 91// the server. In the event that there is no suitable version, the last version
77 result := ProtocolNetRPC 92// in the config is returned leaving the client to report the incompatibility.
78 if c.GRPCServer != nil { 93func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
79 result = ProtocolGRPC 94 protoVersion := int(opts.ProtocolVersion)
95 pluginSet := opts.Plugins
96 protoType := ProtocolNetRPC
97 // Check if the client sent a list of acceptable versions
98 var clientVersions []int
99 if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" {
100 for _, s := range strings.Split(vs, ",") {
101 v, err := strconv.Atoi(s)
102 if err != nil {
103 fmt.Fprintf(os.Stderr, "server sent invalid plugin version %q", s)
104 continue
105 }
106 clientVersions = append(clientVersions, v)
107 }
108 }
109
110 // We want to iterate in reverse order, to ensure we match the newest
111 // compatible plugin version.
112 sort.Sort(sort.Reverse(sort.IntSlice(clientVersions)))
113
114 // set the old un-versioned fields as if they were versioned plugins
115 if opts.VersionedPlugins == nil {
116 opts.VersionedPlugins = make(map[int]PluginSet)
117 }
118
119 if pluginSet != nil {
120 opts.VersionedPlugins[protoVersion] = pluginSet
80 } 121 }
81 122
82 return result 123 // Sort the version to make sure we match the latest first
124 var versions []int
125 for v := range opts.VersionedPlugins {
126 versions = append(versions, v)
127 }
128
129 sort.Sort(sort.Reverse(sort.IntSlice(versions)))
130
131 // See if we have multiple versions of Plugins to choose from
132 for _, version := range versions {
133 // Record each version, since we guarantee that this returns valid
134 // values even if they are not a protocol match.
135 protoVersion = version
136 pluginSet = opts.VersionedPlugins[version]
137
138 // If we have a configured gRPC server we should select a protocol
139 if opts.GRPCServer != nil {
140 // All plugins in a set must use the same transport, so check the first
141 // for the protocol type
142 for _, p := range pluginSet {
143 switch p.(type) {
144 case GRPCPlugin:
145 protoType = ProtocolGRPC
146 default:
147 protoType = ProtocolNetRPC
148 }
149 break
150 }
151 }
152
153 for _, clientVersion := range clientVersions {
154 if clientVersion == protoVersion {
155 return protoVersion, protoType, pluginSet
156 }
157 }
158 }
159
160 // Return the lowest version as the fallback.
161 // Since we iterated over all the versions in reverse order above, these
162 // values are from the lowest version number plugins (which may be from
163 // a combination of the Handshake.ProtocolVersion and ServeConfig.Plugins
164 // fields). This allows serving the oldest version of our plugins to a
165 // legacy client that did not send a PLUGIN_PROTOCOL_VERSIONS list.
166 return protoVersion, protoType, pluginSet
83} 167}
84 168
85// Serve serves the plugins given by ServeConfig. 169// Serve serves the plugins given by ServeConfig.
@@ -107,6 +191,10 @@ func Serve(opts *ServeConfig) {
107 os.Exit(1) 191 os.Exit(1)
108 } 192 }
109 193
194 // negotiate the version and plugins
195 // start with default version in the handshake config
196 protoVersion, protoType, pluginSet := protocolVersion(opts)
197
110 // Logging goes to the original stderr 198 // Logging goes to the original stderr
111 log.SetOutput(os.Stderr) 199 log.SetOutput(os.Stderr)
112 200
@@ -155,12 +243,47 @@ func Serve(opts *ServeConfig) {
155 } 243 }
156 } 244 }
157 245
246 var serverCert string
247 clientCert := os.Getenv("PLUGIN_CLIENT_CERT")
248 // If the client is configured using AutoMTLS, the certificate will be here,
249 // and we need to generate our own in response.
250 if tlsConfig == nil && clientCert != "" {
251 logger.Info("configuring server automatic mTLS")
252 clientCertPool := x509.NewCertPool()
253 if !clientCertPool.AppendCertsFromPEM([]byte(clientCert)) {
254 logger.Error("client cert provided but failed to parse", "cert", clientCert)
255 }
256
257 certPEM, keyPEM, err := generateCert()
258 if err != nil {
259 logger.Error("failed to generate client certificate", "error", err)
260 panic(err)
261 }
262
263 cert, err := tls.X509KeyPair(certPEM, keyPEM)
264 if err != nil {
265 logger.Error("failed to parse client certificate", "error", err)
266 panic(err)
267 }
268
269 tlsConfig = &tls.Config{
270 Certificates: []tls.Certificate{cert},
271 ClientAuth: tls.RequireAndVerifyClientCert,
272 ClientCAs: clientCertPool,
273 MinVersion: tls.VersionTLS12,
274 }
275
276 // We send back the raw leaf cert data for the client rather than the
277 // PEM, since the protocol can't handle newlines.
278 serverCert = base64.RawStdEncoding.EncodeToString(cert.Certificate[0])
279 }
280
158 // Create the channel to tell us when we're done 281 // Create the channel to tell us when we're done
159 doneCh := make(chan struct{}) 282 doneCh := make(chan struct{})
160 283
161 // Build the server type 284 // Build the server type
162 var server ServerProtocol 285 var server ServerProtocol
163 switch opts.Protocol() { 286 switch protoType {
164 case ProtocolNetRPC: 287 case ProtocolNetRPC:
165 // If we have a TLS configuration then we wrap the listener 288 // If we have a TLS configuration then we wrap the listener
166 // ourselves and do it at that level. 289 // ourselves and do it at that level.
@@ -170,7 +293,7 @@ func Serve(opts *ServeConfig) {
170 293
171 // Create the RPC server to dispense 294 // Create the RPC server to dispense
172 server = &RPCServer{ 295 server = &RPCServer{
173 Plugins: opts.Plugins, 296 Plugins: pluginSet,
174 Stdout: stdout_r, 297 Stdout: stdout_r,
175 Stderr: stderr_r, 298 Stderr: stderr_r,
176 DoneCh: doneCh, 299 DoneCh: doneCh,
@@ -179,16 +302,17 @@ func Serve(opts *ServeConfig) {
179 case ProtocolGRPC: 302 case ProtocolGRPC:
180 // Create the gRPC server 303 // Create the gRPC server
181 server = &GRPCServer{ 304 server = &GRPCServer{
182 Plugins: opts.Plugins, 305 Plugins: pluginSet,
183 Server: opts.GRPCServer, 306 Server: opts.GRPCServer,
184 TLS: tlsConfig, 307 TLS: tlsConfig,
185 Stdout: stdout_r, 308 Stdout: stdout_r,
186 Stderr: stderr_r, 309 Stderr: stderr_r,
187 DoneCh: doneCh, 310 DoneCh: doneCh,
311 logger: logger,
188 } 312 }
189 313
190 default: 314 default:
191 panic("unknown server protocol: " + opts.Protocol()) 315 panic("unknown server protocol: " + protoType)
192 } 316 }
193 317
194 // Initialize the servers 318 // Initialize the servers
@@ -197,25 +321,16 @@ func Serve(opts *ServeConfig) {
197 return 321 return
198 } 322 }
199 323
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()) 324 logger.Debug("plugin address", "network", listener.Addr().Network(), "address", listener.Addr().String())
210 325
211 // Output the address and service name to stdout so that core can bring it up. 326 // Output the address and service name to stdout so that the client can bring it up.
212 fmt.Printf("%d|%d|%s|%s|%s%s\n", 327 fmt.Printf("%d|%d|%s|%s|%s|%s\n",
213 CoreProtocolVersion, 328 CoreProtocolVersion,
214 opts.ProtocolVersion, 329 protoVersion,
215 listener.Addr().Network(), 330 listener.Addr().Network(),
216 listener.Addr().String(), 331 listener.Addr().String(),
217 opts.Protocol(), 332 protoType,
218 extra) 333 serverCert)
219 os.Stdout.Sync() 334 os.Stdout.Sync()
220 335
221 // Eat the interrupts 336 // Eat the interrupts
diff --git a/vendor/github.com/hashicorp/go-plugin/testing.go b/vendor/github.com/hashicorp/go-plugin/testing.go
index df29593..2cf2c26 100644
--- a/vendor/github.com/hashicorp/go-plugin/testing.go
+++ b/vendor/github.com/hashicorp/go-plugin/testing.go
@@ -3,13 +3,28 @@ package plugin
3import ( 3import (
4 "bytes" 4 "bytes"
5 "context" 5 "context"
6 "io"
6 "net" 7 "net"
7 "net/rpc" 8 "net/rpc"
8 9
9 "github.com/mitchellh/go-testing-interface" 10 "github.com/mitchellh/go-testing-interface"
11 hclog "github.com/hashicorp/go-hclog"
12 "github.com/hashicorp/go-plugin/internal/plugin"
10 "google.golang.org/grpc" 13 "google.golang.org/grpc"
11) 14)
12 15
16// TestOptions allows specifying options that can affect the behavior of the
17// test functions
18type TestOptions struct {
19 //ServerStdout causes the given value to be used in place of a blank buffer
20 //for RPCServer's Stdout
21 ServerStdout io.ReadCloser
22
23 //ServerStderr causes the given value to be used in place of a blank buffer
24 //for RPCServer's Stderr
25 ServerStderr io.ReadCloser
26}
27
13// The testing file contains test helpers that you can use outside of 28// The testing file contains test helpers that you can use outside of
14// this package for making it easier to test plugins themselves. 29// this package for making it easier to test plugins themselves.
15 30
@@ -61,12 +76,20 @@ func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) {
61 76
62// TestPluginRPCConn returns a plugin RPC client and server that are connected 77// TestPluginRPCConn returns a plugin RPC client and server that are connected
63// together and configured. 78// together and configured.
64func TestPluginRPCConn(t testing.T, ps map[string]Plugin) (*RPCClient, *RPCServer) { 79func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) {
65 // Create two net.Conns we can use to shuttle our control connection 80 // Create two net.Conns we can use to shuttle our control connection
66 clientConn, serverConn := TestConn(t) 81 clientConn, serverConn := TestConn(t)
67 82
68 // Start up the server 83 // Start up the server
69 server := &RPCServer{Plugins: ps, Stdout: new(bytes.Buffer), Stderr: new(bytes.Buffer)} 84 server := &RPCServer{Plugins: ps, Stdout: new(bytes.Buffer), Stderr: new(bytes.Buffer)}
85 if opts != nil {
86 if opts.ServerStdout != nil {
87 server.Stdout = opts.ServerStdout
88 }
89 if opts.ServerStderr != nil {
90 server.Stderr = opts.ServerStderr
91 }
92 }
70 go server.ServeConn(serverConn) 93 go server.ServeConn(serverConn)
71 94
72 // Connect the client to the server 95 // Connect the client to the server
@@ -119,9 +142,11 @@ func TestPluginGRPCConn(t testing.T, ps map[string]Plugin) (*GRPCClient, *GRPCSe
119 // Start up the server 142 // Start up the server
120 server := &GRPCServer{ 143 server := &GRPCServer{
121 Plugins: ps, 144 Plugins: ps,
145 DoneCh: make(chan struct{}),
122 Server: DefaultGRPCServer, 146 Server: DefaultGRPCServer,
123 Stdout: new(bytes.Buffer), 147 Stdout: new(bytes.Buffer),
124 Stderr: new(bytes.Buffer), 148 Stderr: new(bytes.Buffer),
149 logger: hclog.Default(),
125 } 150 }
126 if err := server.Init(); err != nil { 151 if err := server.Init(); err != nil {
127 t.Fatalf("err: %s", err) 152 t.Fatalf("err: %s", err)
@@ -144,10 +169,11 @@ func TestPluginGRPCConn(t testing.T, ps map[string]Plugin) (*GRPCClient, *GRPCSe
144 169
145 // Create the client 170 // Create the client
146 client := &GRPCClient{ 171 client := &GRPCClient{
147 Conn: conn, 172 Conn: conn,
148 Plugins: ps, 173 Plugins: ps,
149 broker: broker, 174 broker: broker,
150 doneCtx: context.Background(), 175 doneCtx: context.Background(),
176 controller: plugin.NewGRPCControllerClient(conn),
151 } 177 }
152 178
153 return client, server 179 return client, server