From b58a973b1820673b328e89514b26df2bb358f016 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Mon, 14 Nov 2016 18:08:24 -0800 Subject: [PATCH] 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 --- interface.go | 2 +- service_update.go | 11 +++++++++-- service_update_test.go | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/interface.go b/interface.go index 7a3ebe8b4c..d46720e6c7 100644 --- a/interface.go +++ b/interface.go @@ -124,7 +124,7 @@ type ServiceAPIClient interface { ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, 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) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) diff --git a/service_update.go b/service_update.go index 8e03f7f483..afa94d47e2 100644 --- a/service_update.go +++ b/service_update.go @@ -1,6 +1,7 @@ package client import ( + "encoding/json" "net/url" "strconv" @@ -10,7 +11,7 @@ import ( ) // 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 ( headers map[string][]string 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)) + var response types.ServiceUpdateResponse 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) - return err + return response, err } diff --git a/service_update_test.go b/service_update_test.go index 081649f492..76bea176bf 100644 --- a/service_update_test.go +++ b/service_update_test.go @@ -19,7 +19,7 @@ func TestServiceUpdateError(t *testing.T) { 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" { t.Fatalf("expected a Server Error, got %v", err) } @@ -64,12 +64,12 @@ func TestServiceUpdate(t *testing.T) { } return &http.Response{ StatusCode: http.StatusOK, - Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))), + Body: ioutil.NopCloser(bytes.NewReader([]byte("{}"))), }, 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 { t.Fatal(err) }