Преглед на файлове

Add API version checks to client

The Docker CLI already performs version-checks when
running commands, but other clients consuming the API
client may not do so.

This patch adds a version check to various
client functions.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn преди 8 години
родител
ревизия
1401342f46

+ 3 - 0
client/config_create.go

@@ -11,6 +11,9 @@ import (
 // ConfigCreate creates a new Config.
 func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
 	var response types.ConfigCreateResponse
+	if err := cli.NewVersionError("1.30", "config create"); err != nil {
+		return response, err
+	}
 	resp, err := cli.post(ctx, "/configs/create", nil, config, nil)
 	if err != nil {
 		return response, err

+ 14 - 2
client/config_create_test.go

@@ -11,12 +11,23 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestConfigCreateUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.29",
+		client:  &http.Client{},
+	}
+	_, err := client.ConfigCreate(context.Background(), swarm.ConfigSpec{})
+	assert.EqualError(t, err, `"config create" requires API version 1.30, but the Docker daemon API version is 1.29`)
+}
+
 func TestConfigCreateError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.30",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 	_, err := client.ConfigCreate(context.Background(), swarm.ConfigSpec{})
 	if err == nil || err.Error() != "Error response from daemon: Server error" {
@@ -25,8 +36,9 @@ func TestConfigCreateError(t *testing.T) {
 }
 
 func TestConfigCreate(t *testing.T) {
-	expectedURL := "/configs/create"
+	expectedURL := "/v1.30/configs/create"
 	client := &Client{
+		version: "1.30",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/config_inspect.go

@@ -12,6 +12,9 @@ import (
 
 // ConfigInspectWithRaw returns the config information with raw data
 func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
+	if err := cli.NewVersionError("1.30", "config inspect"); err != nil {
+		return swarm.Config{}, nil, err
+	}
 	resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
 	if err != nil {
 		if resp.statusCode == http.StatusNotFound {

+ 16 - 3
client/config_inspect_test.go

@@ -10,12 +10,23 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestConfigInspectUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.29",
+		client:  &http.Client{},
+	}
+	_, _, err := client.ConfigInspectWithRaw(context.Background(), "nothing")
+	assert.EqualError(t, err, `"config inspect" requires API version 1.30, but the Docker daemon API version is 1.29`)
+}
+
 func TestConfigInspectError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.30",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	_, _, err := client.ConfigInspectWithRaw(context.Background(), "nothing")
@@ -26,7 +37,8 @@ func TestConfigInspectError(t *testing.T) {
 
 func TestConfigInspectConfigNotFound(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusNotFound, "Server error")),
+		version: "1.30",
+		client:  newMockClient(errorMock(http.StatusNotFound, "Server error")),
 	}
 
 	_, _, err := client.ConfigInspectWithRaw(context.Background(), "unknown")
@@ -36,8 +48,9 @@ func TestConfigInspectConfigNotFound(t *testing.T) {
 }
 
 func TestConfigInspect(t *testing.T) {
-	expectedURL := "/configs/config_id"
+	expectedURL := "/v1.30/configs/config_id"
 	client := &Client{
+		version: "1.30",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/config_list.go

@@ -12,6 +12,9 @@ import (
 
 // ConfigList returns the list of configs.
 func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
+	if err := cli.NewVersionError("1.30", "config list"); err != nil {
+		return nil, err
+	}
 	query := url.Values{}
 
 	if options.Filters.Len() > 0 {

+ 14 - 2
client/config_list_test.go

@@ -12,12 +12,23 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestConfigListUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.29",
+		client:  &http.Client{},
+	}
+	_, err := client.ConfigList(context.Background(), types.ConfigListOptions{})
+	assert.EqualError(t, err, `"config list" requires API version 1.30, but the Docker daemon API version is 1.29`)
+}
+
 func TestConfigListError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.30",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	_, err := client.ConfigList(context.Background(), types.ConfigListOptions{})
@@ -27,7 +38,7 @@ func TestConfigListError(t *testing.T) {
 }
 
 func TestConfigList(t *testing.T) {
-	expectedURL := "/configs"
+	expectedURL := "/v1.30/configs"
 
 	filters := filters.NewArgs()
 	filters.Add("label", "label1")
@@ -54,6 +65,7 @@ func TestConfigList(t *testing.T) {
 	}
 	for _, listCase := range listCases {
 		client := &Client{
+			version: "1.30",
 			client: newMockClient(func(req *http.Request) (*http.Response, error) {
 				if !strings.HasPrefix(req.URL.Path, expectedURL) {
 					return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/config_remove.go

@@ -4,6 +4,9 @@ import "golang.org/x/net/context"
 
 // ConfigRemove removes a Config.
 func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
+	if err := cli.NewVersionError("1.30", "config remove"); err != nil {
+		return err
+	}
 	resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
 	ensureReaderClosed(resp)
 	return err

+ 14 - 2
client/config_remove_test.go

@@ -8,12 +8,23 @@ import (
 	"strings"
 	"testing"
 
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestConfigRemoveUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.29",
+		client:  &http.Client{},
+	}
+	err := client.ConfigRemove(context.Background(), "config_id")
+	assert.EqualError(t, err, `"config remove" requires API version 1.30, but the Docker daemon API version is 1.29`)
+}
+
 func TestConfigRemoveError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.30",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	err := client.ConfigRemove(context.Background(), "config_id")
@@ -23,9 +34,10 @@ func TestConfigRemoveError(t *testing.T) {
 }
 
 func TestConfigRemove(t *testing.T) {
-	expectedURL := "/configs/config_id"
+	expectedURL := "/v1.30/configs/config_id"
 
 	client := &Client{
+		version: "1.30",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/config_update.go

@@ -10,6 +10,9 @@ import (
 
 // ConfigUpdate attempts to update a Config
 func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error {
+	if err := cli.NewVersionError("1.30", "config update"); err != nil {
+		return err
+	}
 	query := url.Values{}
 	query.Set("version", strconv.FormatUint(version.Index, 10))
 	resp, err := cli.post(ctx, "/configs/"+id+"/update", query, config, nil)

+ 15 - 4
client/config_update_test.go

@@ -8,14 +8,24 @@ import (
 	"strings"
 	"testing"
 
-	"golang.org/x/net/context"
-
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
+	"golang.org/x/net/context"
 )
 
+func TestConfigUpdateUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.29",
+		client:  &http.Client{},
+	}
+	err := client.ConfigUpdate(context.Background(), "config_id", swarm.Version{}, swarm.ConfigSpec{})
+	assert.EqualError(t, err, `"config update" requires API version 1.30, but the Docker daemon API version is 1.29`)
+}
+
 func TestConfigUpdateError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.30",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	err := client.ConfigUpdate(context.Background(), "config_id", swarm.Version{}, swarm.ConfigSpec{})
@@ -25,9 +35,10 @@ func TestConfigUpdateError(t *testing.T) {
 }
 
 func TestConfigUpdate(t *testing.T) {
-	expectedURL := "/configs/config_id/update"
+	expectedURL := "/v1.30/configs/config_id/update"
 
 	client := &Client{
+		version: "1.30",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 6 - 2
client/distribution_inspect.go

@@ -10,6 +10,12 @@ import (
 
 // DistributionInspect returns the image digest with full Manifest
 func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) {
+	// Contact the registry to retrieve digest and platform information
+	var distributionInspect registrytypes.DistributionInspect
+
+	if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil {
+		return distributionInspect, err
+	}
 	var headers map[string][]string
 
 	if encodedRegistryAuth != "" {
@@ -18,8 +24,6 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
 		}
 	}
 
-	// Contact the registry to retrieve digest and platform information
-	var distributionInspect registrytypes.DistributionInspect
 	resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
 	if err != nil {
 		return distributionInspect, err

+ 18 - 0
client/distribution_inspect_test.go

@@ -0,0 +1,18 @@
+package client
+
+import (
+	"net/http"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"golang.org/x/net/context"
+)
+
+func TestDistributionInspectUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.29",
+		client:  &http.Client{},
+	}
+	_, err := client.DistributionInspect(context.Background(), "foobar:1.0", "")
+	assert.EqualError(t, err, `"distribution inspect" requires API version 1.30, but the Docker daemon API version is 1.29`)
+}

+ 3 - 0
client/plugin_upgrade.go

@@ -12,6 +12,9 @@ import (
 
 // PluginUpgrade upgrades a plugin
 func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
+	if err := cli.NewVersionError("1.26", "plugin upgrade"); err != nil {
+		return nil, err
+	}
 	query := url.Values{}
 	if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil {
 		return nil, errors.Wrap(err, "invalid remote reference")

+ 3 - 0
client/secret_create.go

@@ -11,6 +11,9 @@ import (
 // SecretCreate creates a new Secret.
 func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) {
 	var response types.SecretCreateResponse
+	if err := cli.NewVersionError("1.25", "secret create"); err != nil {
+		return response, err
+	}
 	resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil)
 	if err != nil {
 		return response, err

+ 14 - 2
client/secret_create_test.go

@@ -11,12 +11,23 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestSecretCreateUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.24",
+		client:  &http.Client{},
+	}
+	_, err := client.SecretCreate(context.Background(), swarm.SecretSpec{})
+	assert.EqualError(t, err, `"secret create" requires API version 1.25, but the Docker daemon API version is 1.24`)
+}
+
 func TestSecretCreateError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.25",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 	_, err := client.SecretCreate(context.Background(), swarm.SecretSpec{})
 	if err == nil || err.Error() != "Error response from daemon: Server error" {
@@ -25,8 +36,9 @@ func TestSecretCreateError(t *testing.T) {
 }
 
 func TestSecretCreate(t *testing.T) {
-	expectedURL := "/secrets/create"
+	expectedURL := "/v1.25/secrets/create"
 	client := &Client{
+		version: "1.25",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/secret_inspect.go

@@ -12,6 +12,9 @@ import (
 
 // SecretInspectWithRaw returns the secret information with raw data
 func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) {
+	if err := cli.NewVersionError("1.25", "secret inspect"); err != nil {
+		return swarm.Secret{}, nil, err
+	}
 	resp, err := cli.get(ctx, "/secrets/"+id, nil, nil)
 	if err != nil {
 		if resp.statusCode == http.StatusNotFound {

+ 16 - 3
client/secret_inspect_test.go

@@ -10,12 +10,23 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestSecretInspectUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.24",
+		client:  &http.Client{},
+	}
+	_, _, err := client.SecretInspectWithRaw(context.Background(), "nothing")
+	assert.EqualError(t, err, `"secret inspect" requires API version 1.25, but the Docker daemon API version is 1.24`)
+}
+
 func TestSecretInspectError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.25",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	_, _, err := client.SecretInspectWithRaw(context.Background(), "nothing")
@@ -26,7 +37,8 @@ func TestSecretInspectError(t *testing.T) {
 
 func TestSecretInspectSecretNotFound(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusNotFound, "Server error")),
+		version: "1.25",
+		client:  newMockClient(errorMock(http.StatusNotFound, "Server error")),
 	}
 
 	_, _, err := client.SecretInspectWithRaw(context.Background(), "unknown")
@@ -36,8 +48,9 @@ func TestSecretInspectSecretNotFound(t *testing.T) {
 }
 
 func TestSecretInspect(t *testing.T) {
-	expectedURL := "/secrets/secret_id"
+	expectedURL := "/v1.25/secrets/secret_id"
 	client := &Client{
+		version: "1.25",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/secret_list.go

@@ -12,6 +12,9 @@ import (
 
 // SecretList returns the list of secrets.
 func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
+	if err := cli.NewVersionError("1.25", "secret list"); err != nil {
+		return nil, err
+	}
 	query := url.Values{}
 
 	if options.Filters.Len() > 0 {

+ 14 - 2
client/secret_list_test.go

@@ -12,12 +12,23 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestSecretListUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.24",
+		client:  &http.Client{},
+	}
+	_, err := client.SecretList(context.Background(), types.SecretListOptions{})
+	assert.EqualError(t, err, `"secret list" requires API version 1.25, but the Docker daemon API version is 1.24`)
+}
+
 func TestSecretListError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.25",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	_, err := client.SecretList(context.Background(), types.SecretListOptions{})
@@ -27,7 +38,7 @@ func TestSecretListError(t *testing.T) {
 }
 
 func TestSecretList(t *testing.T) {
-	expectedURL := "/secrets"
+	expectedURL := "/v1.25/secrets"
 
 	filters := filters.NewArgs()
 	filters.Add("label", "label1")
@@ -54,6 +65,7 @@ func TestSecretList(t *testing.T) {
 	}
 	for _, listCase := range listCases {
 		client := &Client{
+			version: "1.25",
 			client: newMockClient(func(req *http.Request) (*http.Response, error) {
 				if !strings.HasPrefix(req.URL.Path, expectedURL) {
 					return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/secret_remove.go

@@ -4,6 +4,9 @@ import "golang.org/x/net/context"
 
 // SecretRemove removes a Secret.
 func (cli *Client) SecretRemove(ctx context.Context, id string) error {
+	if err := cli.NewVersionError("1.25", "secret remove"); err != nil {
+		return err
+	}
 	resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil)
 	ensureReaderClosed(resp)
 	return err

+ 14 - 2
client/secret_remove_test.go

@@ -8,12 +8,23 @@ import (
 	"strings"
 	"testing"
 
+	"github.com/stretchr/testify/assert"
 	"golang.org/x/net/context"
 )
 
+func TestSecretRemoveUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.24",
+		client:  &http.Client{},
+	}
+	err := client.SecretRemove(context.Background(), "secret_id")
+	assert.EqualError(t, err, `"secret remove" requires API version 1.25, but the Docker daemon API version is 1.24`)
+}
+
 func TestSecretRemoveError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.25",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	err := client.SecretRemove(context.Background(), "secret_id")
@@ -23,9 +34,10 @@ func TestSecretRemoveError(t *testing.T) {
 }
 
 func TestSecretRemove(t *testing.T) {
-	expectedURL := "/secrets/secret_id"
+	expectedURL := "/v1.25/secrets/secret_id"
 
 	client := &Client{
+		version: "1.25",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 3 - 0
client/secret_update.go

@@ -10,6 +10,9 @@ import (
 
 // SecretUpdate attempts to update a Secret
 func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error {
+	if err := cli.NewVersionError("1.25", "secret update"); err != nil {
+		return err
+	}
 	query := url.Values{}
 	query.Set("version", strconv.FormatUint(version.Index, 10))
 	resp, err := cli.post(ctx, "/secrets/"+id+"/update", query, secret, nil)

+ 15 - 4
client/secret_update_test.go

@@ -8,14 +8,24 @@ import (
 	"strings"
 	"testing"
 
-	"golang.org/x/net/context"
-
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/stretchr/testify/assert"
+	"golang.org/x/net/context"
 )
 
+func TestSecretUpdateUnsupported(t *testing.T) {
+	client := &Client{
+		version: "1.24",
+		client:  &http.Client{},
+	}
+	err := client.SecretUpdate(context.Background(), "secret_id", swarm.Version{}, swarm.SecretSpec{})
+	assert.EqualError(t, err, `"secret update" requires API version 1.25, but the Docker daemon API version is 1.24`)
+}
+
 func TestSecretUpdateError(t *testing.T) {
 	client := &Client{
-		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
+		version: "1.25",
+		client:  newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
 	err := client.SecretUpdate(context.Background(), "secret_id", swarm.Version{}, swarm.SecretSpec{})
@@ -25,9 +35,10 @@ func TestSecretUpdateError(t *testing.T) {
 }
 
 func TestSecretUpdate(t *testing.T) {
-	expectedURL := "/secrets/secret_id/update"
+	expectedURL := "/v1.25/secrets/secret_id/update"
 
 	client := &Client{
+		version: "1.25",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
 			if !strings.HasPrefix(req.URL.Path, expectedURL) {
 				return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)

+ 7 - 5
client/service_create_test.go

@@ -68,8 +68,9 @@ func TestServiceCreateCompatiblePlatforms(t *testing.T) {
 	)
 
 	client := &Client{
+		version: "1.30",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
-			if strings.HasPrefix(req.URL.Path, "/services/create") {
+			if strings.HasPrefix(req.URL.Path, "/v1.30/services/create") {
 				// check if the /distribution endpoint returned correct output
 				err := json.NewDecoder(distributionInspectBody).Decode(&distributionInspect)
 				if err != nil {
@@ -89,7 +90,7 @@ func TestServiceCreateCompatiblePlatforms(t *testing.T) {
 					StatusCode: http.StatusOK,
 					Body:       ioutil.NopCloser(bytes.NewReader(b)),
 				}, nil
-			} else if strings.HasPrefix(req.URL.Path, "/distribution/") {
+			} else if strings.HasPrefix(req.URL.Path, "/v1.30/distribution/") {
 				platforms = []v1.Platform{
 					{
 						Architecture: "amd64",
@@ -146,8 +147,9 @@ func TestServiceCreateDigestPinning(t *testing.T) {
 	}
 
 	client := &Client{
+		version: "1.30",
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
-			if strings.HasPrefix(req.URL.Path, "/services/create") {
+			if strings.HasPrefix(req.URL.Path, "/v1.30/services/create") {
 				// reset and set image received by the service create endpoint
 				serviceCreateImage = ""
 				var service swarm.ServiceSpec
@@ -166,10 +168,10 @@ func TestServiceCreateDigestPinning(t *testing.T) {
 					StatusCode: http.StatusOK,
 					Body:       ioutil.NopCloser(bytes.NewReader(b)),
 				}, nil
-			} else if strings.HasPrefix(req.URL.Path, "/distribution/cannotresolve") {
+			} else if strings.HasPrefix(req.URL.Path, "/v1.30/distribution/cannotresolve") {
 				// unresolvable image
 				return nil, fmt.Errorf("cannot resolve image")
-			} else if strings.HasPrefix(req.URL.Path, "/distribution/") {
+			} else if strings.HasPrefix(req.URL.Path, "/v1.30/distribution/") {
 				// resolvable images
 				b, err := json.Marshal(registrytypes.DistributionInspect{
 					Descriptor: v1.Descriptor{