mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-11-02 14:17:57 +00:00
- 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>
89 lines
1.9 KiB
Go
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)
|
|
}
|