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>
| ... | ... |
@@ -11,6 +11,9 @@ import ( |
| 11 | 11 |
// ConfigCreate creates a new Config. |
| 12 | 12 |
func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
| 13 | 13 |
var response types.ConfigCreateResponse |
| 14 |
+ if err := cli.NewVersionError("1.30", "config create"); err != nil {
|
|
| 15 |
+ return response, err |
|
| 16 |
+ } |
|
| 14 | 17 |
resp, err := cli.post(ctx, "/configs/create", nil, config, nil) |
| 15 | 18 |
if err != nil {
|
| 16 | 19 |
return response, err |
| ... | ... |
@@ -11,12 +11,23 @@ import ( |
| 11 | 11 |
|
| 12 | 12 |
"github.com/docker/docker/api/types" |
| 13 | 13 |
"github.com/docker/docker/api/types/swarm" |
| 14 |
+ "github.com/stretchr/testify/assert" |
|
| 14 | 15 |
"golang.org/x/net/context" |
| 15 | 16 |
) |
| 16 | 17 |
|
| 18 |
+func TestConfigCreateUnsupported(t *testing.T) {
|
|
| 19 |
+ client := &Client{
|
|
| 20 |
+ version: "1.29", |
|
| 21 |
+ client: &http.Client{},
|
|
| 22 |
+ } |
|
| 23 |
+ _, err := client.ConfigCreate(context.Background(), swarm.ConfigSpec{})
|
|
| 24 |
+ assert.EqualError(t, err, `"config create" requires API version 1.30, but the Docker daemon API version is 1.29`) |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 17 | 27 |
func TestConfigCreateError(t *testing.T) {
|
| 18 | 28 |
client := &Client{
|
| 19 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 29 |
+ version: "1.30", |
|
| 30 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 20 | 31 |
} |
| 21 | 32 |
_, err := client.ConfigCreate(context.Background(), swarm.ConfigSpec{})
|
| 22 | 33 |
if err == nil || err.Error() != "Error response from daemon: Server error" {
|
| ... | ... |
@@ -25,8 +36,9 @@ func TestConfigCreateError(t *testing.T) {
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
func TestConfigCreate(t *testing.T) {
|
| 28 |
- expectedURL := "/configs/create" |
|
| 28 |
+ expectedURL := "/v1.30/configs/create" |
|
| 29 | 29 |
client := &Client{
|
| 30 |
+ version: "1.30", |
|
| 30 | 31 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 31 | 32 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 32 | 33 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -12,6 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// ConfigInspectWithRaw returns the config information with raw data |
| 14 | 14 |
func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
|
| 15 |
+ if err := cli.NewVersionError("1.30", "config inspect"); err != nil {
|
|
| 16 |
+ return swarm.Config{}, nil, err
|
|
| 17 |
+ } |
|
| 15 | 18 |
resp, err := cli.get(ctx, "/configs/"+id, nil, nil) |
| 16 | 19 |
if err != nil {
|
| 17 | 20 |
if resp.statusCode == http.StatusNotFound {
|
| ... | ... |
@@ -10,12 +10,23 @@ import ( |
| 10 | 10 |
"testing" |
| 11 | 11 |
|
| 12 | 12 |
"github.com/docker/docker/api/types/swarm" |
| 13 |
+ "github.com/stretchr/testify/assert" |
|
| 13 | 14 |
"golang.org/x/net/context" |
| 14 | 15 |
) |
| 15 | 16 |
|
| 17 |
+func TestConfigInspectUnsupported(t *testing.T) {
|
|
| 18 |
+ client := &Client{
|
|
| 19 |
+ version: "1.29", |
|
| 20 |
+ client: &http.Client{},
|
|
| 21 |
+ } |
|
| 22 |
+ _, _, err := client.ConfigInspectWithRaw(context.Background(), "nothing") |
|
| 23 |
+ assert.EqualError(t, err, `"config inspect" requires API version 1.30, but the Docker daemon API version is 1.29`) |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 16 | 26 |
func TestConfigInspectError(t *testing.T) {
|
| 17 | 27 |
client := &Client{
|
| 18 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 28 |
+ version: "1.30", |
|
| 29 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 19 | 30 |
} |
| 20 | 31 |
|
| 21 | 32 |
_, _, err := client.ConfigInspectWithRaw(context.Background(), "nothing") |
| ... | ... |
@@ -26,7 +37,8 @@ func TestConfigInspectError(t *testing.T) {
|
| 26 | 26 |
|
| 27 | 27 |
func TestConfigInspectConfigNotFound(t *testing.T) {
|
| 28 | 28 |
client := &Client{
|
| 29 |
- client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 29 |
+ version: "1.30", |
|
| 30 |
+ client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 30 | 31 |
} |
| 31 | 32 |
|
| 32 | 33 |
_, _, err := client.ConfigInspectWithRaw(context.Background(), "unknown") |
| ... | ... |
@@ -36,8 +48,9 @@ func TestConfigInspectConfigNotFound(t *testing.T) {
|
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 | 38 |
func TestConfigInspect(t *testing.T) {
|
| 39 |
- expectedURL := "/configs/config_id" |
|
| 39 |
+ expectedURL := "/v1.30/configs/config_id" |
|
| 40 | 40 |
client := &Client{
|
| 41 |
+ version: "1.30", |
|
| 41 | 42 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 42 | 43 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 43 | 44 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -12,6 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// ConfigList returns the list of configs. |
| 14 | 14 |
func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
| 15 |
+ if err := cli.NewVersionError("1.30", "config list"); err != nil {
|
|
| 16 |
+ return nil, err |
|
| 17 |
+ } |
|
| 15 | 18 |
query := url.Values{}
|
| 16 | 19 |
|
| 17 | 20 |
if options.Filters.Len() > 0 {
|
| ... | ... |
@@ -12,12 +12,23 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/api/types" |
| 13 | 13 |
"github.com/docker/docker/api/types/filters" |
| 14 | 14 |
"github.com/docker/docker/api/types/swarm" |
| 15 |
+ "github.com/stretchr/testify/assert" |
|
| 15 | 16 |
"golang.org/x/net/context" |
| 16 | 17 |
) |
| 17 | 18 |
|
| 19 |
+func TestConfigListUnsupported(t *testing.T) {
|
|
| 20 |
+ client := &Client{
|
|
| 21 |
+ version: "1.29", |
|
| 22 |
+ client: &http.Client{},
|
|
| 23 |
+ } |
|
| 24 |
+ _, err := client.ConfigList(context.Background(), types.ConfigListOptions{})
|
|
| 25 |
+ assert.EqualError(t, err, `"config list" requires API version 1.30, but the Docker daemon API version is 1.29`) |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 18 | 28 |
func TestConfigListError(t *testing.T) {
|
| 19 | 29 |
client := &Client{
|
| 20 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 30 |
+ version: "1.30", |
|
| 31 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 21 | 32 |
} |
| 22 | 33 |
|
| 23 | 34 |
_, err := client.ConfigList(context.Background(), types.ConfigListOptions{})
|
| ... | ... |
@@ -27,7 +38,7 @@ func TestConfigListError(t *testing.T) {
|
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 | 29 |
func TestConfigList(t *testing.T) {
|
| 30 |
- expectedURL := "/configs" |
|
| 30 |
+ expectedURL := "/v1.30/configs" |
|
| 31 | 31 |
|
| 32 | 32 |
filters := filters.NewArgs() |
| 33 | 33 |
filters.Add("label", "label1")
|
| ... | ... |
@@ -54,6 +65,7 @@ func TestConfigList(t *testing.T) {
|
| 54 | 54 |
} |
| 55 | 55 |
for _, listCase := range listCases {
|
| 56 | 56 |
client := &Client{
|
| 57 |
+ version: "1.30", |
|
| 57 | 58 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 58 | 59 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 59 | 60 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -4,6 +4,9 @@ import "golang.org/x/net/context" |
| 4 | 4 |
|
| 5 | 5 |
// ConfigRemove removes a Config. |
| 6 | 6 |
func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
|
| 7 |
+ if err := cli.NewVersionError("1.30", "config remove"); err != nil {
|
|
| 8 |
+ return err |
|
| 9 |
+ } |
|
| 7 | 10 |
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) |
| 8 | 11 |
ensureReaderClosed(resp) |
| 9 | 12 |
return err |
| ... | ... |
@@ -8,12 +8,23 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 |
+ "github.com/stretchr/testify/assert" |
|
| 11 | 12 |
"golang.org/x/net/context" |
| 12 | 13 |
) |
| 13 | 14 |
|
| 15 |
+func TestConfigRemoveUnsupported(t *testing.T) {
|
|
| 16 |
+ client := &Client{
|
|
| 17 |
+ version: "1.29", |
|
| 18 |
+ client: &http.Client{},
|
|
| 19 |
+ } |
|
| 20 |
+ err := client.ConfigRemove(context.Background(), "config_id") |
|
| 21 |
+ assert.EqualError(t, err, `"config remove" requires API version 1.30, but the Docker daemon API version is 1.29`) |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 14 | 24 |
func TestConfigRemoveError(t *testing.T) {
|
| 15 | 25 |
client := &Client{
|
| 16 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 26 |
+ version: "1.30", |
|
| 27 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 17 | 28 |
} |
| 18 | 29 |
|
| 19 | 30 |
err := client.ConfigRemove(context.Background(), "config_id") |
| ... | ... |
@@ -23,9 +34,10 @@ func TestConfigRemoveError(t *testing.T) {
|
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
func TestConfigRemove(t *testing.T) {
|
| 26 |
- expectedURL := "/configs/config_id" |
|
| 26 |
+ expectedURL := "/v1.30/configs/config_id" |
|
| 27 | 27 |
|
| 28 | 28 |
client := &Client{
|
| 29 |
+ version: "1.30", |
|
| 29 | 30 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 30 | 31 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 31 | 32 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -10,6 +10,9 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
// ConfigUpdate attempts to update a Config |
| 12 | 12 |
func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error {
|
| 13 |
+ if err := cli.NewVersionError("1.30", "config update"); err != nil {
|
|
| 14 |
+ return err |
|
| 15 |
+ } |
|
| 13 | 16 |
query := url.Values{}
|
| 14 | 17 |
query.Set("version", strconv.FormatUint(version.Index, 10))
|
| 15 | 18 |
resp, err := cli.post(ctx, "/configs/"+id+"/update", query, config, nil) |
| ... | ... |
@@ -8,14 +8,24 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 |
- "golang.org/x/net/context" |
|
| 12 |
- |
|
| 13 | 11 |
"github.com/docker/docker/api/types/swarm" |
| 12 |
+ "github.com/stretchr/testify/assert" |
|
| 13 |
+ "golang.org/x/net/context" |
|
| 14 | 14 |
) |
| 15 | 15 |
|
| 16 |
+func TestConfigUpdateUnsupported(t *testing.T) {
|
|
| 17 |
+ client := &Client{
|
|
| 18 |
+ version: "1.29", |
|
| 19 |
+ client: &http.Client{},
|
|
| 20 |
+ } |
|
| 21 |
+ err := client.ConfigUpdate(context.Background(), "config_id", swarm.Version{}, swarm.ConfigSpec{})
|
|
| 22 |
+ assert.EqualError(t, err, `"config update" requires API version 1.30, but the Docker daemon API version is 1.29`) |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 16 | 25 |
func TestConfigUpdateError(t *testing.T) {
|
| 17 | 26 |
client := &Client{
|
| 18 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 27 |
+ version: "1.30", |
|
| 28 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 19 | 29 |
} |
| 20 | 30 |
|
| 21 | 31 |
err := client.ConfigUpdate(context.Background(), "config_id", swarm.Version{}, swarm.ConfigSpec{})
|
| ... | ... |
@@ -25,9 +35,10 @@ func TestConfigUpdateError(t *testing.T) {
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
func TestConfigUpdate(t *testing.T) {
|
| 28 |
- expectedURL := "/configs/config_id/update" |
|
| 28 |
+ expectedURL := "/v1.30/configs/config_id/update" |
|
| 29 | 29 |
|
| 30 | 30 |
client := &Client{
|
| 31 |
+ version: "1.30", |
|
| 31 | 32 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 32 | 33 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 33 | 34 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -10,6 +10,12 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
// DistributionInspect returns the image digest with full Manifest |
| 12 | 12 |
func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) {
|
| 13 |
+ // Contact the registry to retrieve digest and platform information |
|
| 14 |
+ var distributionInspect registrytypes.DistributionInspect |
|
| 15 |
+ |
|
| 16 |
+ if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil {
|
|
| 17 |
+ return distributionInspect, err |
|
| 18 |
+ } |
|
| 13 | 19 |
var headers map[string][]string |
| 14 | 20 |
|
| 15 | 21 |
if encodedRegistryAuth != "" {
|
| ... | ... |
@@ -18,8 +24,6 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist |
| 18 | 18 |
} |
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 |
- // Contact the registry to retrieve digest and platform information |
|
| 22 |
- var distributionInspect registrytypes.DistributionInspect |
|
| 23 | 21 |
resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
|
| 24 | 22 |
if err != nil {
|
| 25 | 23 |
return distributionInspect, err |
| 26 | 24 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+package client |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net/http" |
|
| 4 |
+ "testing" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/stretchr/testify/assert" |
|
| 7 |
+ "golang.org/x/net/context" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+func TestDistributionInspectUnsupported(t *testing.T) {
|
|
| 11 |
+ client := &Client{
|
|
| 12 |
+ version: "1.29", |
|
| 13 |
+ client: &http.Client{},
|
|
| 14 |
+ } |
|
| 15 |
+ _, err := client.DistributionInspect(context.Background(), "foobar:1.0", "") |
|
| 16 |
+ assert.EqualError(t, err, `"distribution inspect" requires API version 1.30, but the Docker daemon API version is 1.29`) |
|
| 17 |
+} |
| ... | ... |
@@ -12,6 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// PluginUpgrade upgrades a plugin |
| 14 | 14 |
func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
|
| 15 |
+ if err := cli.NewVersionError("1.26", "plugin upgrade"); err != nil {
|
|
| 16 |
+ return nil, err |
|
| 17 |
+ } |
|
| 15 | 18 |
query := url.Values{}
|
| 16 | 19 |
if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil {
|
| 17 | 20 |
return nil, errors.Wrap(err, "invalid remote reference") |
| ... | ... |
@@ -11,6 +11,9 @@ import ( |
| 11 | 11 |
// SecretCreate creates a new Secret. |
| 12 | 12 |
func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
| 13 | 13 |
var response types.SecretCreateResponse |
| 14 |
+ if err := cli.NewVersionError("1.25", "secret create"); err != nil {
|
|
| 15 |
+ return response, err |
|
| 16 |
+ } |
|
| 14 | 17 |
resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) |
| 15 | 18 |
if err != nil {
|
| 16 | 19 |
return response, err |
| ... | ... |
@@ -11,12 +11,23 @@ import ( |
| 11 | 11 |
|
| 12 | 12 |
"github.com/docker/docker/api/types" |
| 13 | 13 |
"github.com/docker/docker/api/types/swarm" |
| 14 |
+ "github.com/stretchr/testify/assert" |
|
| 14 | 15 |
"golang.org/x/net/context" |
| 15 | 16 |
) |
| 16 | 17 |
|
| 18 |
+func TestSecretCreateUnsupported(t *testing.T) {
|
|
| 19 |
+ client := &Client{
|
|
| 20 |
+ version: "1.24", |
|
| 21 |
+ client: &http.Client{},
|
|
| 22 |
+ } |
|
| 23 |
+ _, err := client.SecretCreate(context.Background(), swarm.SecretSpec{})
|
|
| 24 |
+ assert.EqualError(t, err, `"secret create" requires API version 1.25, but the Docker daemon API version is 1.24`) |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 17 | 27 |
func TestSecretCreateError(t *testing.T) {
|
| 18 | 28 |
client := &Client{
|
| 19 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 29 |
+ version: "1.25", |
|
| 30 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 20 | 31 |
} |
| 21 | 32 |
_, err := client.SecretCreate(context.Background(), swarm.SecretSpec{})
|
| 22 | 33 |
if err == nil || err.Error() != "Error response from daemon: Server error" {
|
| ... | ... |
@@ -25,8 +36,9 @@ func TestSecretCreateError(t *testing.T) {
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
func TestSecretCreate(t *testing.T) {
|
| 28 |
- expectedURL := "/secrets/create" |
|
| 28 |
+ expectedURL := "/v1.25/secrets/create" |
|
| 29 | 29 |
client := &Client{
|
| 30 |
+ version: "1.25", |
|
| 30 | 31 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 31 | 32 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 32 | 33 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -12,6 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// SecretInspectWithRaw returns the secret information with raw data |
| 14 | 14 |
func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) {
|
| 15 |
+ if err := cli.NewVersionError("1.25", "secret inspect"); err != nil {
|
|
| 16 |
+ return swarm.Secret{}, nil, err
|
|
| 17 |
+ } |
|
| 15 | 18 |
resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) |
| 16 | 19 |
if err != nil {
|
| 17 | 20 |
if resp.statusCode == http.StatusNotFound {
|
| ... | ... |
@@ -10,12 +10,23 @@ import ( |
| 10 | 10 |
"testing" |
| 11 | 11 |
|
| 12 | 12 |
"github.com/docker/docker/api/types/swarm" |
| 13 |
+ "github.com/stretchr/testify/assert" |
|
| 13 | 14 |
"golang.org/x/net/context" |
| 14 | 15 |
) |
| 15 | 16 |
|
| 17 |
+func TestSecretInspectUnsupported(t *testing.T) {
|
|
| 18 |
+ client := &Client{
|
|
| 19 |
+ version: "1.24", |
|
| 20 |
+ client: &http.Client{},
|
|
| 21 |
+ } |
|
| 22 |
+ _, _, err := client.SecretInspectWithRaw(context.Background(), "nothing") |
|
| 23 |
+ assert.EqualError(t, err, `"secret inspect" requires API version 1.25, but the Docker daemon API version is 1.24`) |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 16 | 26 |
func TestSecretInspectError(t *testing.T) {
|
| 17 | 27 |
client := &Client{
|
| 18 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 28 |
+ version: "1.25", |
|
| 29 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 19 | 30 |
} |
| 20 | 31 |
|
| 21 | 32 |
_, _, err := client.SecretInspectWithRaw(context.Background(), "nothing") |
| ... | ... |
@@ -26,7 +37,8 @@ func TestSecretInspectError(t *testing.T) {
|
| 26 | 26 |
|
| 27 | 27 |
func TestSecretInspectSecretNotFound(t *testing.T) {
|
| 28 | 28 |
client := &Client{
|
| 29 |
- client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 29 |
+ version: "1.25", |
|
| 30 |
+ client: newMockClient(errorMock(http.StatusNotFound, "Server error")), |
|
| 30 | 31 |
} |
| 31 | 32 |
|
| 32 | 33 |
_, _, err := client.SecretInspectWithRaw(context.Background(), "unknown") |
| ... | ... |
@@ -36,8 +48,9 @@ func TestSecretInspectSecretNotFound(t *testing.T) {
|
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 | 38 |
func TestSecretInspect(t *testing.T) {
|
| 39 |
- expectedURL := "/secrets/secret_id" |
|
| 39 |
+ expectedURL := "/v1.25/secrets/secret_id" |
|
| 40 | 40 |
client := &Client{
|
| 41 |
+ version: "1.25", |
|
| 41 | 42 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 42 | 43 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 43 | 44 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -12,6 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
// SecretList returns the list of secrets. |
| 14 | 14 |
func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
| 15 |
+ if err := cli.NewVersionError("1.25", "secret list"); err != nil {
|
|
| 16 |
+ return nil, err |
|
| 17 |
+ } |
|
| 15 | 18 |
query := url.Values{}
|
| 16 | 19 |
|
| 17 | 20 |
if options.Filters.Len() > 0 {
|
| ... | ... |
@@ -12,12 +12,23 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/api/types" |
| 13 | 13 |
"github.com/docker/docker/api/types/filters" |
| 14 | 14 |
"github.com/docker/docker/api/types/swarm" |
| 15 |
+ "github.com/stretchr/testify/assert" |
|
| 15 | 16 |
"golang.org/x/net/context" |
| 16 | 17 |
) |
| 17 | 18 |
|
| 19 |
+func TestSecretListUnsupported(t *testing.T) {
|
|
| 20 |
+ client := &Client{
|
|
| 21 |
+ version: "1.24", |
|
| 22 |
+ client: &http.Client{},
|
|
| 23 |
+ } |
|
| 24 |
+ _, err := client.SecretList(context.Background(), types.SecretListOptions{})
|
|
| 25 |
+ assert.EqualError(t, err, `"secret list" requires API version 1.25, but the Docker daemon API version is 1.24`) |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 18 | 28 |
func TestSecretListError(t *testing.T) {
|
| 19 | 29 |
client := &Client{
|
| 20 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 30 |
+ version: "1.25", |
|
| 31 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 21 | 32 |
} |
| 22 | 33 |
|
| 23 | 34 |
_, err := client.SecretList(context.Background(), types.SecretListOptions{})
|
| ... | ... |
@@ -27,7 +38,7 @@ func TestSecretListError(t *testing.T) {
|
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 | 29 |
func TestSecretList(t *testing.T) {
|
| 30 |
- expectedURL := "/secrets" |
|
| 30 |
+ expectedURL := "/v1.25/secrets" |
|
| 31 | 31 |
|
| 32 | 32 |
filters := filters.NewArgs() |
| 33 | 33 |
filters.Add("label", "label1")
|
| ... | ... |
@@ -54,6 +65,7 @@ func TestSecretList(t *testing.T) {
|
| 54 | 54 |
} |
| 55 | 55 |
for _, listCase := range listCases {
|
| 56 | 56 |
client := &Client{
|
| 57 |
+ version: "1.25", |
|
| 57 | 58 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 58 | 59 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 59 | 60 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -4,6 +4,9 @@ import "golang.org/x/net/context" |
| 4 | 4 |
|
| 5 | 5 |
// SecretRemove removes a Secret. |
| 6 | 6 |
func (cli *Client) SecretRemove(ctx context.Context, id string) error {
|
| 7 |
+ if err := cli.NewVersionError("1.25", "secret remove"); err != nil {
|
|
| 8 |
+ return err |
|
| 9 |
+ } |
|
| 7 | 10 |
resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil) |
| 8 | 11 |
ensureReaderClosed(resp) |
| 9 | 12 |
return err |
| ... | ... |
@@ -8,12 +8,23 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 |
+ "github.com/stretchr/testify/assert" |
|
| 11 | 12 |
"golang.org/x/net/context" |
| 12 | 13 |
) |
| 13 | 14 |
|
| 15 |
+func TestSecretRemoveUnsupported(t *testing.T) {
|
|
| 16 |
+ client := &Client{
|
|
| 17 |
+ version: "1.24", |
|
| 18 |
+ client: &http.Client{},
|
|
| 19 |
+ } |
|
| 20 |
+ err := client.SecretRemove(context.Background(), "secret_id") |
|
| 21 |
+ assert.EqualError(t, err, `"secret remove" requires API version 1.25, but the Docker daemon API version is 1.24`) |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 14 | 24 |
func TestSecretRemoveError(t *testing.T) {
|
| 15 | 25 |
client := &Client{
|
| 16 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 26 |
+ version: "1.25", |
|
| 27 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 17 | 28 |
} |
| 18 | 29 |
|
| 19 | 30 |
err := client.SecretRemove(context.Background(), "secret_id") |
| ... | ... |
@@ -23,9 +34,10 @@ func TestSecretRemoveError(t *testing.T) {
|
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
func TestSecretRemove(t *testing.T) {
|
| 26 |
- expectedURL := "/secrets/secret_id" |
|
| 26 |
+ expectedURL := "/v1.25/secrets/secret_id" |
|
| 27 | 27 |
|
| 28 | 28 |
client := &Client{
|
| 29 |
+ version: "1.25", |
|
| 29 | 30 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 30 | 31 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 31 | 32 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -10,6 +10,9 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
// SecretUpdate attempts to update a Secret |
| 12 | 12 |
func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error {
|
| 13 |
+ if err := cli.NewVersionError("1.25", "secret update"); err != nil {
|
|
| 14 |
+ return err |
|
| 15 |
+ } |
|
| 13 | 16 |
query := url.Values{}
|
| 14 | 17 |
query.Set("version", strconv.FormatUint(version.Index, 10))
|
| 15 | 18 |
resp, err := cli.post(ctx, "/secrets/"+id+"/update", query, secret, nil) |
| ... | ... |
@@ -8,14 +8,24 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"testing" |
| 10 | 10 |
|
| 11 |
- "golang.org/x/net/context" |
|
| 12 |
- |
|
| 13 | 11 |
"github.com/docker/docker/api/types/swarm" |
| 12 |
+ "github.com/stretchr/testify/assert" |
|
| 13 |
+ "golang.org/x/net/context" |
|
| 14 | 14 |
) |
| 15 | 15 |
|
| 16 |
+func TestSecretUpdateUnsupported(t *testing.T) {
|
|
| 17 |
+ client := &Client{
|
|
| 18 |
+ version: "1.24", |
|
| 19 |
+ client: &http.Client{},
|
|
| 20 |
+ } |
|
| 21 |
+ err := client.SecretUpdate(context.Background(), "secret_id", swarm.Version{}, swarm.SecretSpec{})
|
|
| 22 |
+ assert.EqualError(t, err, `"secret update" requires API version 1.25, but the Docker daemon API version is 1.24`) |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 16 | 25 |
func TestSecretUpdateError(t *testing.T) {
|
| 17 | 26 |
client := &Client{
|
| 18 |
- client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 27 |
+ version: "1.25", |
|
| 28 |
+ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), |
|
| 19 | 29 |
} |
| 20 | 30 |
|
| 21 | 31 |
err := client.SecretUpdate(context.Background(), "secret_id", swarm.Version{}, swarm.SecretSpec{})
|
| ... | ... |
@@ -25,9 +35,10 @@ func TestSecretUpdateError(t *testing.T) {
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
func TestSecretUpdate(t *testing.T) {
|
| 28 |
- expectedURL := "/secrets/secret_id/update" |
|
| 28 |
+ expectedURL := "/v1.25/secrets/secret_id/update" |
|
| 29 | 29 |
|
| 30 | 30 |
client := &Client{
|
| 31 |
+ version: "1.25", |
|
| 31 | 32 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 32 | 33 |
if !strings.HasPrefix(req.URL.Path, expectedURL) {
|
| 33 | 34 |
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
| ... | ... |
@@ -68,8 +68,9 @@ func TestServiceCreateCompatiblePlatforms(t *testing.T) {
|
| 68 | 68 |
) |
| 69 | 69 |
|
| 70 | 70 |
client := &Client{
|
| 71 |
+ version: "1.30", |
|
| 71 | 72 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 72 |
- if strings.HasPrefix(req.URL.Path, "/services/create") {
|
|
| 73 |
+ if strings.HasPrefix(req.URL.Path, "/v1.30/services/create") {
|
|
| 73 | 74 |
// check if the /distribution endpoint returned correct output |
| 74 | 75 |
err := json.NewDecoder(distributionInspectBody).Decode(&distributionInspect) |
| 75 | 76 |
if err != nil {
|
| ... | ... |
@@ -89,7 +90,7 @@ func TestServiceCreateCompatiblePlatforms(t *testing.T) {
|
| 89 | 89 |
StatusCode: http.StatusOK, |
| 90 | 90 |
Body: ioutil.NopCloser(bytes.NewReader(b)), |
| 91 | 91 |
}, nil |
| 92 |
- } else if strings.HasPrefix(req.URL.Path, "/distribution/") {
|
|
| 92 |
+ } else if strings.HasPrefix(req.URL.Path, "/v1.30/distribution/") {
|
|
| 93 | 93 |
platforms = []v1.Platform{
|
| 94 | 94 |
{
|
| 95 | 95 |
Architecture: "amd64", |
| ... | ... |
@@ -146,8 +147,9 @@ func TestServiceCreateDigestPinning(t *testing.T) {
|
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 | 148 |
client := &Client{
|
| 149 |
+ version: "1.30", |
|
| 149 | 150 |
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
| 150 |
- if strings.HasPrefix(req.URL.Path, "/services/create") {
|
|
| 151 |
+ if strings.HasPrefix(req.URL.Path, "/v1.30/services/create") {
|
|
| 151 | 152 |
// reset and set image received by the service create endpoint |
| 152 | 153 |
serviceCreateImage = "" |
| 153 | 154 |
var service swarm.ServiceSpec |
| ... | ... |
@@ -166,10 +168,10 @@ func TestServiceCreateDigestPinning(t *testing.T) {
|
| 166 | 166 |
StatusCode: http.StatusOK, |
| 167 | 167 |
Body: ioutil.NopCloser(bytes.NewReader(b)), |
| 168 | 168 |
}, nil |
| 169 |
- } else if strings.HasPrefix(req.URL.Path, "/distribution/cannotresolve") {
|
|
| 169 |
+ } else if strings.HasPrefix(req.URL.Path, "/v1.30/distribution/cannotresolve") {
|
|
| 170 | 170 |
// unresolvable image |
| 171 | 171 |
return nil, fmt.Errorf("cannot resolve image")
|
| 172 |
- } else if strings.HasPrefix(req.URL.Path, "/distribution/") {
|
|
| 172 |
+ } else if strings.HasPrefix(req.URL.Path, "/v1.30/distribution/") {
|
|
| 173 | 173 |
// resolvable images |
| 174 | 174 |
b, err := json.Marshal(registrytypes.DistributionInspect{
|
| 175 | 175 |
Descriptor: v1.Descriptor{
|