Adding new client interface in Swarm

Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
This commit is contained in:
Nishant Totla 2016-07-19 10:14:55 -07:00
parent 936f2f7914
commit 62b0b29aa6
No known key found for this signature in database
GPG Key ID: 7EA5781C9B3D0C19
8 changed files with 47 additions and 30 deletions

View File

@ -2,6 +2,7 @@ package mockclient
import ( import (
"io" "io"
"time"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container" "github.com/docker/engine-api/types/container"
@ -161,7 +162,7 @@ func (client *MockClient) ContainerResize(ctx context.Context, container string,
} }
// ContainerRestart stops and starts a container again // ContainerRestart stops and starts a container again
func (client *MockClient) ContainerRestart(ctx context.Context, container string, timeout int) error { func (client *MockClient) ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error {
args := client.Mock.Called(ctx, container, timeout) args := client.Mock.Called(ctx, container, timeout)
return args.Error(0) return args.Error(0)
} }
@ -179,13 +180,13 @@ func (client *MockClient) ContainerStats(ctx context.Context, container string,
} }
// ContainerStart sends a request to the docker daemon to start a container // ContainerStart sends a request to the docker daemon to start a container
func (client *MockClient) ContainerStart(ctx context.Context, container string, checkpointID string) error { func (client *MockClient) ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error {
args := client.Mock.Called(ctx, container, checkpointID) args := client.Mock.Called(ctx, container, options)
return args.Error(0) return args.Error(0)
} }
// ContainerStop stops a container without terminating the process // ContainerStop stops a container without terminating the process
func (client *MockClient) ContainerStop(ctx context.Context, container string, timeout int) error { func (client *MockClient) ContainerStop(ctx context.Context, container string, timeout *time.Duration) error {
args := client.Mock.Called(ctx, container, timeout) args := client.Mock.Called(ctx, container, timeout)
return args.Error(0) return args.Error(0)
} }
@ -305,8 +306,8 @@ func (client *MockClient) ImageSave(ctx context.Context, images []string) (io.Re
} }
// ImageTag tags an image in the docker host // ImageTag tags an image in the docker host
func (client *MockClient) ImageTag(ctx context.Context, image, ref string, options types.ImageTagOptions) error { func (client *MockClient) ImageTag(ctx context.Context, image, ref string) error {
args := client.Mock.Called(ctx, image, ref, options) args := client.Mock.Called(ctx, image, ref)
return args.Error(0) return args.Error(0)
} }

View File

@ -6,8 +6,8 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/swarm/swarmclient"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
) )
@ -27,10 +27,10 @@ func TestMock(t *testing.T) {
} }
func TestMockInterface(t *testing.T) { func TestMockInterface(t *testing.T) {
iface := reflect.TypeOf((*client.APIClient)(nil)).Elem() iface := reflect.TypeOf((*swarmclient.SwarmAPIClient)(nil)).Elem()
mockClient := NewMockClient() mockClient := NewMockClient()
if !reflect.TypeOf(mockClient).Implements(iface) { if !reflect.TypeOf(mockClient).Implements(iface) {
t.Fatalf("Mock does not implement the APIClient interface") t.Fatalf("Mock does not implement the SwarmAPIClient interface")
} }
} }

View File

@ -3,6 +3,7 @@ package nopclient
import ( import (
"errors" "errors"
"io" "io"
"time"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -142,7 +143,7 @@ func (client *NopClient) ContainerResize(ctx context.Context, container string,
} }
// ContainerRestart stops and starts a container again // ContainerRestart stops and starts a container again
func (client *NopClient) ContainerRestart(ctx context.Context, container string, timeout int) error { func (client *NopClient) ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error {
return errNoEngine return errNoEngine
} }
@ -157,12 +158,12 @@ func (client *NopClient) ContainerStats(ctx context.Context, container string, s
} }
// ContainerStart sends a request to the docker daemon to start a container // ContainerStart sends a request to the docker daemon to start a container
func (client *NopClient) ContainerStart(ctx context.Context, container string, checkpointID string) error { func (client *NopClient) ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error {
return errNoEngine return errNoEngine
} }
// ContainerStop stops a container without terminating the process // ContainerStop stops a container without terminating the process
func (client *NopClient) ContainerStop(ctx context.Context, container string, timeout int) error { func (client *NopClient) ContainerStop(ctx context.Context, container string, timeout *time.Duration) error {
return errNoEngine return errNoEngine
} }
@ -262,7 +263,7 @@ func (client *NopClient) ImageSave(ctx context.Context, images []string) (io.Rea
} }
// ImageTag tags an image in the docker host // ImageTag tags an image in the docker host
func (client *NopClient) ImageTag(ctx context.Context, image, ref string, options types.ImageTagOptions) error { func (client *NopClient) ImageTag(ctx context.Context, image, ref string) error {
return errNoEngine return errNoEngine
} }

View File

@ -4,9 +4,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/docker/swarm/swarmclient"
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/docker/engine-api/client"
) )
func TestNop(t *testing.T) { func TestNop(t *testing.T) {
@ -18,10 +17,10 @@ func TestNop(t *testing.T) {
} }
func TestNopInterface(t *testing.T) { func TestNopInterface(t *testing.T) {
iface := reflect.TypeOf((*client.APIClient)(nil)).Elem() iface := reflect.TypeOf((*swarmclient.SwarmAPIClient)(nil)).Elem()
nop := NewNopClient() nop := NewNopClient()
if !reflect.TypeOf(nop).Implements(iface) { if !reflect.TypeOf(nop).Implements(iface) {
t.Fatalf("Nop does not implement the APIClient interface") t.Fatalf("Nop does not implement the SwarmAPIClient interface")
} }
} }

View File

@ -25,6 +25,7 @@ import (
"github.com/docker/engine-api/types/filters" "github.com/docker/engine-api/types/filters"
networktypes "github.com/docker/engine-api/types/network" networktypes "github.com/docker/engine-api/types/network"
engineapinop "github.com/docker/swarm/api/nopclient" engineapinop "github.com/docker/swarm/api/nopclient"
"github.com/docker/swarm/swarmclient"
"github.com/samalba/dockerclient" "github.com/samalba/dockerclient"
"github.com/samalba/dockerclient/nopclient" "github.com/samalba/dockerclient/nopclient"
) )
@ -123,7 +124,7 @@ type Engine struct {
networks map[string]*Network networks map[string]*Network
volumes map[string]*Volume volumes map[string]*Volume
client dockerclient.Client client dockerclient.Client
apiClient engineapi.APIClient apiClient swarmclient.SwarmAPIClient
eventHandler EventHandler eventHandler EventHandler
state engineState state engineState
lastError string lastError string
@ -209,7 +210,7 @@ func (e *Engine) StartMonitorEvents() {
} }
// ConnectWithClient is exported // ConnectWithClient is exported
func (e *Engine) ConnectWithClient(client dockerclient.Client, apiClient engineapi.APIClient) error { func (e *Engine) ConnectWithClient(client dockerclient.Client, apiClient swarmclient.SwarmAPIClient) error {
e.client = client e.client = client
e.apiClient = apiClient e.apiClient = apiClient
e.eventsMonitor = NewEventsMonitor(e.apiClient, e.handler) e.eventsMonitor = NewEventsMonitor(e.apiClient, e.handler)
@ -1335,8 +1336,8 @@ func (e *Engine) StartContainer(id string, hostConfig *dockerclient.HostConfig)
if hostConfig != nil { if hostConfig != nil {
err = e.client.StartContainer(id, hostConfig) err = e.client.StartContainer(id, hostConfig)
} else { } else {
// TODO(nishanttotla): Figure out what the checkpoint id (second string argument) should be // TODO(nishanttotla): Should ContainerStartOptions be provided?
err = e.apiClient.ContainerStart(context.Background(), id, "") err = e.apiClient.ContainerStart(context.Background(), id, types.ContainerStartOptions{})
} }
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
@ -1375,11 +1376,7 @@ func (e *Engine) BuildImage(buildContext io.Reader, buildImage *types.ImageBuild
// TagImage tags an image // TagImage tags an image
func (e *Engine) TagImage(IDOrName string, ref string, force bool) error { func (e *Engine) TagImage(IDOrName string, ref string, force bool) error {
// send tag request to docker engine // send tag request to docker engine
opts := types.ImageTagOptions{ err := e.apiClient.ImageTag(context.Background(), IDOrName, ref)
Force: force,
}
err := e.apiClient.ImageTag(context.Background(), IDOrName, ref, opts)
e.CheckConnectionErr(err) e.CheckConnectionErr(err)
if err != nil { if err != nil {
return err return err

View File

@ -4,16 +4,16 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types" "github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/events" "github.com/docker/engine-api/types/events"
"github.com/docker/swarm/swarmclient"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
//EventsMonitor monitors events //EventsMonitor monitors events
type EventsMonitor struct { type EventsMonitor struct {
stopChan chan struct{} stopChan chan struct{}
cli client.APIClient cli swarmclient.SwarmAPIClient
handler func(msg events.Message) error handler func(msg events.Message) error
} }
@ -23,7 +23,7 @@ type decodingResult struct {
} }
// NewEventsMonitor returns an EventsMonitor // NewEventsMonitor returns an EventsMonitor
func NewEventsMonitor(cli client.APIClient, handler func(msg events.Message) error) *EventsMonitor { func NewEventsMonitor(cli swarmclient.SwarmAPIClient, handler func(msg events.Message) error) *EventsMonitor {
return &EventsMonitor{ return &EventsMonitor{
cli: cli, cli: cli,
handler: handler, handler: handler,

View File

@ -264,7 +264,7 @@ func TestTagImage(t *testing.T) {
c.engines[engine.ID] = engine c.engines[engine.ID] = engine
// tag image // tag image
apiClient.On("ImageTag", mock.Anything, mock.Anything, mock.Anything, mock.AnythingOfType("types.ImageTagOptions")).Return(nil).Once() apiClient.On("ImageTag", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
assert.Nil(t, c.TagImage("busybox", "test_busybox:latest", false)) assert.Nil(t, c.TagImage("busybox", "test_busybox:latest", false))
assert.NotNil(t, c.TagImage("busybox_not_exists", "test_busybox:latest", false)) assert.NotNil(t, c.TagImage("busybox_not_exists", "test_busybox:latest", false))
} }

19
swarmclient/interface.go Normal file
View File

@ -0,0 +1,19 @@
package swarmclient
import (
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// SwarmAPIClient contains the subset of the engine-api interface relevant to Docker Swarm
type SwarmAPIClient interface {
client.ContainerAPIClient
client.ImageAPIClient
client.NetworkAPIClient
client.SystemAPIClient
client.VolumeAPIClient
ClientVersion() string
ServerVersion(ctx context.Context) (types.Version, error)
UpdateClientVersion(v string)
}