Files
linuxkit/vendor/github.com/docker/infrakit/pkg/rpc/client/handshake.go
Rolf Neugebauer 6a29d153f5 infrakit: Move the hyperkit instance plugin into the source directory
- The tools directory ideally should not contain source code
- Removes double vendoring of packagages
- Makes it easer to hook the build into the top-level Makefile

Eventually, the plugin should be moved to the infrakit repo.

Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
2017-03-25 13:02:45 +01:00

89 lines
1.9 KiB
Go

package client
import (
"fmt"
"github.com/docker/infrakit/pkg/rpc"
"github.com/docker/infrakit/pkg/spi"
"sync"
)
type handshakingClient struct {
client Client
iface spi.InterfaceSpec
// handshakeResult handles the tri-state outcome of handshake state:
// - handshake has not yet completed (nil)
// - handshake completed successfully (non-nil result, nil error)
// - handshake failed (non-nil result, non-nil error)
handshakeResult *handshakeResult
// lock guards handshakeResult
lock *sync.Mutex
}
type handshakeResult struct {
err error
}
type errVersionMismatch string
// Error implements error interface
func (e errVersionMismatch) Error() string {
return string(e)
}
// IsErrVersionMismatch return true if the error is from mismatched api versions.
func IsErrVersionMismatch(e error) bool {
_, is := e.(errVersionMismatch)
return is
}
func (c *handshakingClient) handshake() error {
c.lock.Lock()
defer c.lock.Unlock()
if c.handshakeResult == nil {
req := rpc.ImplementsRequest{}
resp := rpc.ImplementsResponse{}
if err := c.client.Call("Handshake.Implements", req, &resp); err != nil {
return err
}
err := fmt.Errorf("Plugin does not support interface %v", c.iface)
if resp.APIs != nil {
for _, iface := range resp.APIs {
if iface.Name == c.iface.Name {
if iface.Version == c.iface.Version {
err = nil
break
} else {
err = errVersionMismatch(fmt.Sprintf(
"Plugin supports %s interface version %s, client requires %s",
iface.Name,
iface.Version,
c.iface.Version))
}
}
}
}
c.handshakeResult = &handshakeResult{err: err}
}
return c.handshakeResult.err
}
func (c *handshakingClient) Addr() string {
return c.client.Addr()
}
func (c *handshakingClient) Call(method string, arg interface{}, result interface{}) error {
if err := c.handshake(); err != nil {
return err
}
return c.client.Call(method, arg, result)
}