mirror of https://github.com/docker/cli.git
Return warnings from service create and service update when digest pinning fails
Modify the service update and create APIs to return optional warning messages as part of the response. Populate these messages with an informative reason when digest resolution fails. This is a small API change, but significantly improves the UX. The user can now get immediate feedback when they've specified a nonexistent image or unreachable registry. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
e360a30a41
commit
b58a973b18
|
@ -124,7 +124,7 @@ type ServiceAPIClient interface {
|
||||||
ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error)
|
ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error)
|
||||||
ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
|
ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
|
||||||
ServiceRemove(ctx context.Context, serviceID string) error
|
ServiceRemove(ctx context.Context, serviceID string) error
|
||||||
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error
|
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
|
||||||
ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
|
ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
|
||||||
TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
|
TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
|
||||||
TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
|
TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServiceUpdate updates a Service.
|
// ServiceUpdate updates a Service.
|
||||||
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error {
|
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
||||||
var (
|
var (
|
||||||
headers map[string][]string
|
headers map[string][]string
|
||||||
query = url.Values{}
|
query = url.Values{}
|
||||||
|
@ -28,7 +29,13 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
|
||||||
|
|
||||||
query.Set("version", strconv.FormatUint(version.Index, 10))
|
query.Set("version", strconv.FormatUint(version.Index, 10))
|
||||||
|
|
||||||
|
var response types.ServiceUpdateResponse
|
||||||
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
|
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewDecoder(resp.body).Decode(&response)
|
||||||
ensureReaderClosed(resp)
|
ensureReaderClosed(resp)
|
||||||
return err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ func TestServiceUpdateError(t *testing.T) {
|
||||||
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
|
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := client.ServiceUpdate(context.Background(), "service_id", swarm.Version{}, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
|
_, err := client.ServiceUpdate(context.Background(), "service_id", swarm.Version{}, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
|
||||||
if err == nil || err.Error() != "Error response from daemon: Server error" {
|
if err == nil || err.Error() != "Error response from daemon: Server error" {
|
||||||
t.Fatalf("expected a Server Error, got %v", err)
|
t.Fatalf("expected a Server Error, got %v", err)
|
||||||
}
|
}
|
||||||
|
@ -64,12 +64,12 @@ func TestServiceUpdate(t *testing.T) {
|
||||||
}
|
}
|
||||||
return &http.Response{
|
return &http.Response{
|
||||||
StatusCode: http.StatusOK,
|
StatusCode: http.StatusOK,
|
||||||
Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
|
Body: ioutil.NopCloser(bytes.NewReader([]byte("{}"))),
|
||||||
}, nil
|
}, nil
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := client.ServiceUpdate(context.Background(), "service_id", updateCase.swarmVersion, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
|
_, err := client.ServiceUpdate(context.Background(), "service_id", updateCase.swarmVersion, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue