Unlike a plain `net/http/client.Do()`, requests made through client/request
use the `sendRequest` function, which parses the server response, and may
convert non-transport errors into errors (through `cli.checkResponseErr()`).
This means that we cannot assume that no reader was opened if an error is
returned.
This patch changes various locations where `ensureReaderClosed` was only
called in the non-error situation, and uses a `defer` to make sure it's
always called.
`ensureReaderClosed` itself already checks if the response's body was set,
so in situations where the error was due to a transport error, calling
`ensureReaderClosed` should be a no-op.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -11,10 +11,6 @@ func (cli *Client) BuildCancel(ctx context.Context, id string) error {
|
| 11 | 11 |
query.Set("id", id)
|
| 12 | 12 |
|
| 13 | 13 |
serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil) |
| 14 |
- if err != nil {
|
|
| 15 |
- return err |
|
| 16 |
- } |
|
| 17 |
- defer ensureReaderClosed(serverResp) |
|
| 18 |
- |
|
| 19 |
- return nil |
|
| 14 |
+ ensureReaderClosed(serverResp) |
|
| 15 |
+ return err |
|
| 20 | 16 |
} |
| ... | ... |
@@ -31,11 +31,11 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru |
| 31 | 31 |
query.Set("filters", filters)
|
| 32 | 32 |
|
| 33 | 33 |
serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil) |
| 34 |
+ defer ensureReaderClosed(serverResp) |
|
| 34 | 35 |
|
| 35 | 36 |
if err != nil {
|
| 36 | 37 |
return nil, err |
| 37 | 38 |
} |
| 38 |
- defer ensureReaderClosed(serverResp) |
|
| 39 | 39 |
|
| 40 | 40 |
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
| 41 | 41 |
return nil, fmt.Errorf("Error retrieving disk usage: %v", err)
|
| ... | ... |
@@ -18,11 +18,11 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options |
| 18 | 18 |
} |
| 19 | 19 |
|
| 20 | 20 |
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) |
| 21 |
+ defer ensureReaderClosed(resp) |
|
| 21 | 22 |
if err != nil {
|
| 22 | 23 |
return checkpoints, wrapResponseError(err, resp, "container", container) |
| 23 | 24 |
} |
| 24 | 25 |
|
| 25 | 26 |
err = json.NewDecoder(resp.body).Decode(&checkpoints) |
| 26 |
- ensureReaderClosed(resp) |
|
| 27 | 27 |
return checkpoints, err |
| 28 | 28 |
} |
| ... | ... |
@@ -15,11 +15,11 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t |
| 15 | 15 |
return response, err |
| 16 | 16 |
} |
| 17 | 17 |
resp, err := cli.post(ctx, "/configs/create", nil, config, nil) |
| 18 |
+ defer ensureReaderClosed(resp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return response, err |
| 20 | 21 |
} |
| 21 | 22 |
|
| 22 | 23 |
err = json.NewDecoder(resp.body).Decode(&response) |
| 23 |
- ensureReaderClosed(resp) |
|
| 24 | 24 |
return response, err |
| 25 | 25 |
} |
| ... | ... |
@@ -18,10 +18,10 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C |
| 18 | 18 |
return swarm.Config{}, nil, err
|
| 19 | 19 |
} |
| 20 | 20 |
resp, err := cli.get(ctx, "/configs/"+id, nil, nil) |
| 21 |
+ defer ensureReaderClosed(resp) |
|
| 21 | 22 |
if err != nil {
|
| 22 | 23 |
return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
|
| 23 | 24 |
} |
| 24 |
- defer ensureReaderClosed(resp) |
|
| 25 | 25 |
|
| 26 | 26 |
body, err := ioutil.ReadAll(resp.body) |
| 27 | 27 |
if err != nil {
|
| ... | ... |
@@ -27,12 +27,12 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio |
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 | 29 |
resp, err := cli.get(ctx, "/configs", query, nil) |
| 30 |
+ defer ensureReaderClosed(resp) |
|
| 30 | 31 |
if err != nil {
|
| 31 | 32 |
return nil, err |
| 32 | 33 |
} |
| 33 | 34 |
|
| 34 | 35 |
var configs []swarm.Config |
| 35 | 36 |
err = json.NewDecoder(resp.body).Decode(&configs) |
| 36 |
- ensureReaderClosed(resp) |
|
| 37 | 37 |
return configs, err |
| 38 | 38 |
} |
| ... | ... |
@@ -8,6 +8,6 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
|
| 8 | 8 |
return err |
| 9 | 9 |
} |
| 10 | 10 |
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) |
| 11 |
- ensureReaderClosed(resp) |
|
| 11 |
+ defer ensureReaderClosed(resp) |
|
| 12 | 12 |
return wrapResponseError(err, resp, "config", id) |
| 13 | 13 |
} |
| ... | ... |
@@ -45,11 +45,11 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option |
| 45 | 45 |
|
| 46 | 46 |
var response types.IDResponse |
| 47 | 47 |
resp, err := cli.post(ctx, "/commit", query, options.Config, nil) |
| 48 |
+ defer ensureReaderClosed(resp) |
|
| 48 | 49 |
if err != nil {
|
| 49 | 50 |
return response, err |
| 50 | 51 |
} |
| 51 | 52 |
|
| 52 | 53 |
err = json.NewDecoder(resp.body).Decode(&response) |
| 53 |
- ensureReaderClosed(resp) |
|
| 54 | 54 |
return response, err |
| 55 | 55 |
} |
| ... | ... |
@@ -21,10 +21,10 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri |
| 21 | 21 |
|
| 22 | 22 |
urlStr := "/containers/" + containerID + "/archive" |
| 23 | 23 |
response, err := cli.head(ctx, urlStr, query, nil) |
| 24 |
+ defer ensureReaderClosed(response) |
|
| 24 | 25 |
if err != nil {
|
| 25 | 26 |
return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path)
|
| 26 | 27 |
} |
| 27 |
- defer ensureReaderClosed(response) |
|
| 28 | 28 |
return getContainerPathStatFromHeader(response.header) |
| 29 | 29 |
} |
| 30 | 30 |
|
| ... | ... |
@@ -45,10 +45,10 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str |
| 45 | 45 |
apiPath := "/containers/" + containerID + "/archive" |
| 46 | 46 |
|
| 47 | 47 |
response, err := cli.putRaw(ctx, apiPath, query, content, nil) |
| 48 |
+ defer ensureReaderClosed(response) |
|
| 48 | 49 |
if err != nil {
|
| 49 | 50 |
return wrapResponseError(err, response, "container:path", containerID+":"+dstPath) |
| 50 | 51 |
} |
| 51 |
- defer ensureReaderClosed(response) |
|
| 52 | 52 |
|
| 53 | 53 |
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior |
| 54 | 54 |
if response.statusCode != http.StatusOK {
|
| ... | ... |
@@ -42,11 +42,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config |
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 | 44 |
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) |
| 45 |
+ defer ensureReaderClosed(serverResp) |
|
| 45 | 46 |
if err != nil {
|
| 46 | 47 |
return response, err |
| 47 | 48 |
} |
| 48 | 49 |
|
| 49 | 50 |
err = json.NewDecoder(serverResp.body).Decode(&response) |
| 50 |
- ensureReaderClosed(serverResp) |
|
| 51 | 51 |
return response, err |
| 52 | 52 |
} |
| ... | ... |
@@ -13,11 +13,11 @@ func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]con |
| 13 | 13 |
var changes []container.ContainerChangeResponseItem |
| 14 | 14 |
|
| 15 | 15 |
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
|
| 16 |
+ defer ensureReaderClosed(serverResp) |
|
| 16 | 17 |
if err != nil {
|
| 17 | 18 |
return changes, err |
| 18 | 19 |
} |
| 19 | 20 |
|
| 20 | 21 |
err = json.NewDecoder(serverResp.body).Decode(&changes) |
| 21 |
- ensureReaderClosed(serverResp) |
|
| 22 | 22 |
return changes, err |
| 23 | 23 |
} |
| ... | ... |
@@ -16,11 +16,11 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co |
| 16 | 16 |
} |
| 17 | 17 |
|
| 18 | 18 |
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) |
| 19 |
+ defer ensureReaderClosed(resp) |
|
| 19 | 20 |
if err != nil {
|
| 20 | 21 |
return response, err |
| 21 | 22 |
} |
| 22 | 23 |
err = json.NewDecoder(resp.body).Decode(&response) |
| 23 |
- ensureReaderClosed(resp) |
|
| 24 | 24 |
return response, err |
| 25 | 25 |
} |
| 26 | 26 |
|
| ... | ... |
@@ -16,10 +16,10 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty |
| 16 | 16 |
return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
|
| 17 | 17 |
} |
| 18 | 18 |
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) |
| 19 |
+ defer ensureReaderClosed(serverResp) |
|
| 19 | 20 |
if err != nil {
|
| 20 | 21 |
return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
|
| 21 | 22 |
} |
| 22 |
- defer ensureReaderClosed(serverResp) |
|
| 23 | 23 |
|
| 24 | 24 |
var response types.ContainerJSON |
| 25 | 25 |
err = json.NewDecoder(serverResp.body).Decode(&response) |
| ... | ... |
@@ -36,10 +36,10 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri |
| 36 | 36 |
query.Set("size", "1")
|
| 37 | 37 |
} |
| 38 | 38 |
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) |
| 39 |
+ defer ensureReaderClosed(serverResp) |
|
| 39 | 40 |
if err != nil {
|
| 40 | 41 |
return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
|
| 41 | 42 |
} |
| 42 |
- defer ensureReaderClosed(serverResp) |
|
| 43 | 43 |
|
| 44 | 44 |
body, err := ioutil.ReadAll(serverResp.body) |
| 45 | 45 |
if err != nil {
|
| ... | ... |
@@ -45,12 +45,12 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis |
| 45 | 45 |
} |
| 46 | 46 |
|
| 47 | 47 |
resp, err := cli.get(ctx, "/containers/json", query, nil) |
| 48 |
+ defer ensureReaderClosed(resp) |
|
| 48 | 49 |
if err != nil {
|
| 49 | 50 |
return nil, err |
| 50 | 51 |
} |
| 51 | 52 |
|
| 52 | 53 |
var containers []types.Container |
| 53 | 54 |
err = json.NewDecoder(resp.body).Decode(&containers) |
| 54 |
- ensureReaderClosed(resp) |
|
| 55 | 55 |
return containers, err |
| 56 | 56 |
} |
| ... | ... |
@@ -23,10 +23,10 @@ func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Arg |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) |
| 26 |
+ defer ensureReaderClosed(serverResp) |
|
| 26 | 27 |
if err != nil {
|
| 27 | 28 |
return report, err |
| 28 | 29 |
} |
| 29 |
- defer ensureReaderClosed(serverResp) |
|
| 30 | 30 |
|
| 31 | 31 |
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
| 32 | 32 |
return report, fmt.Errorf("Error retrieving disk usage: %v", err)
|
| ... | ... |
@@ -22,6 +22,6 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti |
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 | 24 |
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) |
| 25 |
- ensureReaderClosed(resp) |
|
| 25 |
+ defer ensureReaderClosed(resp) |
|
| 26 | 26 |
return wrapResponseError(err, resp, "container", containerID) |
| 27 | 27 |
} |
| ... | ... |
@@ -18,11 +18,11 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen |
| 18 | 18 |
} |
| 19 | 19 |
|
| 20 | 20 |
resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) |
| 21 |
+ defer ensureReaderClosed(resp) |
|
| 21 | 22 |
if err != nil {
|
| 22 | 23 |
return response, err |
| 23 | 24 |
} |
| 24 | 25 |
|
| 25 | 26 |
err = json.NewDecoder(resp.body).Decode(&response) |
| 26 |
- ensureReaderClosed(resp) |
|
| 27 | 27 |
return response, err |
| 28 | 28 |
} |
| ... | ... |
@@ -11,12 +11,11 @@ import ( |
| 11 | 11 |
func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) {
|
| 12 | 12 |
var response container.ContainerUpdateOKBody |
| 13 | 13 |
serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) |
| 14 |
+ defer ensureReaderClosed(serverResp) |
|
| 14 | 15 |
if err != nil {
|
| 15 | 16 |
return response, err |
| 16 | 17 |
} |
| 17 | 18 |
|
| 18 | 19 |
err = json.NewDecoder(serverResp.body).Decode(&response) |
| 19 |
- |
|
| 20 |
- ensureReaderClosed(serverResp) |
|
| 21 | 20 |
return response, err |
| 22 | 21 |
} |
| ... | ... |
@@ -13,10 +13,10 @@ func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) {
|
| 13 | 13 |
var du types.DiskUsage |
| 14 | 14 |
|
| 15 | 15 |
serverResp, err := cli.get(ctx, "/system/df", nil, nil) |
| 16 |
+ defer ensureReaderClosed(serverResp) |
|
| 16 | 17 |
if err != nil {
|
| 17 | 18 |
return du, err |
| 18 | 19 |
} |
| 19 |
- defer ensureReaderClosed(serverResp) |
|
| 20 | 20 |
|
| 21 | 21 |
if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil {
|
| 22 | 22 |
return du, fmt.Errorf("Error retrieving disk usage: %v", err)
|
| ... | ... |
@@ -28,11 +28,11 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist |
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 | 30 |
resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
|
| 31 |
+ defer ensureReaderClosed(resp) |
|
| 31 | 32 |
if err != nil {
|
| 32 | 33 |
return distributionInspect, err |
| 33 | 34 |
} |
| 34 | 35 |
|
| 35 | 36 |
err = json.NewDecoder(resp.body).Decode(&distributionInspect) |
| 36 |
- ensureReaderClosed(resp) |
|
| 37 | 37 |
return distributionInspect, err |
| 38 | 38 |
} |
| ... | ... |
@@ -12,11 +12,11 @@ import ( |
| 12 | 12 |
func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) {
|
| 13 | 13 |
var history []image.HistoryResponseItem |
| 14 | 14 |
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
|
| 15 |
+ defer ensureReaderClosed(serverResp) |
|
| 15 | 16 |
if err != nil {
|
| 16 | 17 |
return history, err |
| 17 | 18 |
} |
| 18 | 19 |
|
| 19 | 20 |
err = json.NewDecoder(serverResp.body).Decode(&history) |
| 20 |
- ensureReaderClosed(serverResp) |
|
| 21 | 21 |
return history, err |
| 22 | 22 |
} |
| ... | ... |
@@ -15,10 +15,10 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ |
| 15 | 15 |
return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID}
|
| 16 | 16 |
} |
| 17 | 17 |
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) |
| 18 |
+ defer ensureReaderClosed(serverResp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
|
| 20 | 21 |
} |
| 21 |
- defer ensureReaderClosed(serverResp) |
|
| 22 | 22 |
|
| 23 | 23 |
body, err := ioutil.ReadAll(serverResp.body) |
| 24 | 24 |
if err != nil {
|
| ... | ... |
@@ -35,11 +35,11 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions |
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
serverResp, err := cli.get(ctx, "/images/json", query, nil) |
| 38 |
+ defer ensureReaderClosed(serverResp) |
|
| 38 | 39 |
if err != nil {
|
| 39 | 40 |
return images, err |
| 40 | 41 |
} |
| 41 | 42 |
|
| 42 | 43 |
err = json.NewDecoder(serverResp.body).Decode(&images) |
| 43 |
- ensureReaderClosed(serverResp) |
|
| 44 | 44 |
return images, err |
| 45 | 45 |
} |
| ... | ... |
@@ -23,10 +23,10 @@ func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) ( |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) |
| 26 |
+ defer ensureReaderClosed(serverResp) |
|
| 26 | 27 |
if err != nil {
|
| 27 | 28 |
return report, err |
| 28 | 29 |
} |
| 29 |
- defer ensureReaderClosed(serverResp) |
|
| 30 | 30 |
|
| 31 | 31 |
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
| 32 | 32 |
return report, fmt.Errorf("Error retrieving disk usage: %v", err)
|
| ... | ... |
@@ -21,11 +21,11 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type |
| 21 | 21 |
|
| 22 | 22 |
var dels []types.ImageDeleteResponseItem |
| 23 | 23 |
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) |
| 24 |
+ defer ensureReaderClosed(resp) |
|
| 24 | 25 |
if err != nil {
|
| 25 | 26 |
return dels, wrapResponseError(err, resp, "image", imageID) |
| 26 | 27 |
} |
| 27 | 28 |
|
| 28 | 29 |
err = json.NewDecoder(resp.body).Decode(&dels) |
| 29 |
- ensureReaderClosed(resp) |
|
| 30 | 30 |
return dels, err |
| 31 | 31 |
} |
| ... | ... |
@@ -29,6 +29,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 | 31 |
resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth) |
| 32 |
+ defer ensureReaderClosed(resp) |
|
| 32 | 33 |
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
|
| 33 | 34 |
newAuthHeader, privilegeErr := options.PrivilegeFunc() |
| 34 | 35 |
if privilegeErr != nil {
|
| ... | ... |
@@ -41,7 +42,6 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I |
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 | 43 |
err = json.NewDecoder(resp.body).Decode(&results) |
| 44 |
- ensureReaderClosed(resp) |
|
| 45 | 44 |
return results, err |
| 46 | 45 |
} |
| 47 | 46 |
|
| ... | ... |
@@ -13,10 +13,10 @@ import ( |
| 13 | 13 |
func (cli *Client) Info(ctx context.Context) (types.Info, error) {
|
| 14 | 14 |
var info types.Info |
| 15 | 15 |
serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)
|
| 16 |
+ defer ensureReaderClosed(serverResp) |
|
| 16 | 17 |
if err != nil {
|
| 17 | 18 |
return info, err |
| 18 | 19 |
} |
| 19 |
- defer ensureReaderClosed(serverResp) |
|
| 20 | 20 |
|
| 21 | 21 |
if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil {
|
| 22 | 22 |
return info, fmt.Errorf("Error reading remote info: %v", err)
|
| ... | ... |
@@ -13,6 +13,7 @@ import ( |
| 13 | 13 |
// It returns unauthorizedError when the authentication fails. |
| 14 | 14 |
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) {
|
| 15 | 15 |
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
| 16 |
+ defer ensureReaderClosed(resp) |
|
| 16 | 17 |
|
| 17 | 18 |
if err != nil {
|
| 18 | 19 |
return registry.AuthenticateOKBody{}, err
|
| ... | ... |
@@ -20,6 +21,5 @@ func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (re |
| 20 | 20 |
|
| 21 | 21 |
var response registry.AuthenticateOKBody |
| 22 | 22 |
err = json.NewDecoder(resp.body).Decode(&response) |
| 23 |
- ensureReaderClosed(resp) |
|
| 24 | 23 |
return response, err |
| 25 | 24 |
} |
| ... | ... |
@@ -15,11 +15,11 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types |
| 15 | 15 |
} |
| 16 | 16 |
var response types.NetworkCreateResponse |
| 17 | 17 |
serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) |
| 18 |
+ defer ensureReaderClosed(serverResp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return response, err |
| 20 | 21 |
} |
| 21 | 22 |
|
| 22 |
- json.NewDecoder(serverResp.body).Decode(&response) |
|
| 23 |
- ensureReaderClosed(serverResp) |
|
| 23 |
+ err = json.NewDecoder(serverResp.body).Decode(&response) |
|
| 24 | 24 |
return response, err |
| 25 | 25 |
} |
| ... | ... |
@@ -34,10 +34,10 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, |
| 34 | 34 |
query.Set("scope", options.Scope)
|
| 35 | 35 |
} |
| 36 | 36 |
resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) |
| 37 |
+ defer ensureReaderClosed(resp) |
|
| 37 | 38 |
if err != nil {
|
| 38 | 39 |
return networkResource, nil, wrapResponseError(err, resp, "network", networkID) |
| 39 | 40 |
} |
| 40 |
- defer ensureReaderClosed(resp) |
|
| 41 | 41 |
|
| 42 | 42 |
body, err := ioutil.ReadAll(resp.body) |
| 43 | 43 |
if err != nil {
|
| ... | ... |
@@ -22,10 +22,10 @@ func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOpt |
| 22 | 22 |
} |
| 23 | 23 |
var networkResources []types.NetworkResource |
| 24 | 24 |
resp, err := cli.get(ctx, "/networks", query, nil) |
| 25 |
+ defer ensureReaderClosed(resp) |
|
| 25 | 26 |
if err != nil {
|
| 26 | 27 |
return networkResources, err |
| 27 | 28 |
} |
| 28 | 29 |
err = json.NewDecoder(resp.body).Decode(&networkResources) |
| 29 |
- ensureReaderClosed(resp) |
|
| 30 | 30 |
return networkResources, err |
| 31 | 31 |
} |
| ... | ... |
@@ -23,10 +23,10 @@ func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) |
| 26 |
+ defer ensureReaderClosed(serverResp) |
|
| 26 | 27 |
if err != nil {
|
| 27 | 28 |
return report, err |
| 28 | 29 |
} |
| 29 |
- defer ensureReaderClosed(serverResp) |
|
| 30 | 30 |
|
| 31 | 31 |
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
| 32 | 32 |
return report, fmt.Errorf("Error retrieving network prune report: %v", err)
|
| ... | ... |
@@ -5,6 +5,6 @@ import "context" |
| 5 | 5 |
// NetworkRemove removes an existent network from the docker host. |
| 6 | 6 |
func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
|
| 7 | 7 |
resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) |
| 8 |
- ensureReaderClosed(resp) |
|
| 8 |
+ defer ensureReaderClosed(resp) |
|
| 9 | 9 |
return wrapResponseError(err, resp, "network", networkID) |
| 10 | 10 |
} |
| ... | ... |
@@ -15,10 +15,10 @@ func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm |
| 15 | 15 |
return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID}
|
| 16 | 16 |
} |
| 17 | 17 |
serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) |
| 18 |
+ defer ensureReaderClosed(serverResp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID)
|
| 20 | 21 |
} |
| 21 |
- defer ensureReaderClosed(serverResp) |
|
| 22 | 22 |
|
| 23 | 23 |
body, err := ioutil.ReadAll(serverResp.body) |
| 24 | 24 |
if err != nil {
|
| ... | ... |
@@ -25,12 +25,12 @@ func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) |
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
resp, err := cli.get(ctx, "/nodes", query, nil) |
| 28 |
+ defer ensureReaderClosed(resp) |
|
| 28 | 29 |
if err != nil {
|
| 29 | 30 |
return nil, err |
| 30 | 31 |
} |
| 31 | 32 |
|
| 32 | 33 |
var nodes []swarm.Node |
| 33 | 34 |
err = json.NewDecoder(resp.body).Decode(&nodes) |
| 34 |
- ensureReaderClosed(resp) |
|
| 35 | 35 |
return nodes, err |
| 36 | 36 |
} |
| ... | ... |
@@ -15,6 +15,6 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types. |
| 15 | 15 |
} |
| 16 | 16 |
|
| 17 | 17 |
resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) |
| 18 |
- ensureReaderClosed(resp) |
|
| 18 |
+ defer ensureReaderClosed(resp) |
|
| 19 | 19 |
return wrapResponseError(err, resp, "node", nodeID) |
| 20 | 20 |
} |
| ... | ... |
@@ -38,10 +38,10 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
|
| 38 | 38 |
return ping, err |
| 39 | 39 |
} |
| 40 | 40 |
serverResp, err = cli.doRequest(ctx, req) |
| 41 |
+ defer ensureReaderClosed(serverResp) |
|
| 41 | 42 |
if err != nil {
|
| 42 | 43 |
return ping, err |
| 43 | 44 |
} |
| 44 |
- defer ensureReaderClosed(serverResp) |
|
| 45 | 45 |
return parsePingResponse(cli, serverResp) |
| 46 | 46 |
} |
| 47 | 47 |
|
| ... | ... |
@@ -18,9 +18,6 @@ func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, cr |
| 18 | 18 |
query.Set("name", createOptions.RepoName)
|
| 19 | 19 |
|
| 20 | 20 |
resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers) |
| 21 |
- if err != nil {
|
|
| 22 |
- return err |
|
| 23 |
- } |
|
| 24 | 21 |
ensureReaderClosed(resp) |
| 25 | 22 |
return err |
| 26 | 23 |
} |
| ... | ... |
@@ -15,11 +15,11 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type |
| 15 | 15 |
return nil, nil, objectNotFoundError{object: "plugin", id: name}
|
| 16 | 16 |
} |
| 17 | 17 |
resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) |
| 18 |
+ defer ensureReaderClosed(resp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return nil, nil, wrapResponseError(err, resp, "plugin", name) |
| 20 | 21 |
} |
| 21 | 22 |
|
| 22 |
- defer ensureReaderClosed(resp) |
|
| 23 | 23 |
body, err := ioutil.ReadAll(resp.body) |
| 24 | 24 |
if err != nil {
|
| 25 | 25 |
return nil, nil, err |
| ... | ... |
@@ -22,11 +22,11 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P |
| 22 | 22 |
query.Set("filters", filterJSON)
|
| 23 | 23 |
} |
| 24 | 24 |
resp, err := cli.get(ctx, "/plugins", query, nil) |
| 25 |
+ defer ensureReaderClosed(resp) |
|
| 25 | 26 |
if err != nil {
|
| 26 | 27 |
return plugins, wrapResponseError(err, resp, "plugin", "") |
| 27 | 28 |
} |
| 28 | 29 |
|
| 29 | 30 |
err = json.NewDecoder(resp.body).Decode(&plugins) |
| 30 |
- ensureReaderClosed(resp) |
|
| 31 | 31 |
return plugins, err |
| 32 | 32 |
} |
| ... | ... |
@@ -15,6 +15,6 @@ func (cli *Client) PluginRemove(ctx context.Context, name string, options types. |
| 15 | 15 |
} |
| 16 | 16 |
|
| 17 | 17 |
resp, err := cli.delete(ctx, "/plugins/"+name, query, nil) |
| 18 |
- ensureReaderClosed(resp) |
|
| 18 |
+ defer ensureReaderClosed(resp) |
|
| 19 | 19 |
return wrapResponseError(err, resp, "plugin", name) |
| 20 | 20 |
} |
| ... | ... |
@@ -15,11 +15,11 @@ func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (t |
| 15 | 15 |
return response, err |
| 16 | 16 |
} |
| 17 | 17 |
resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) |
| 18 |
+ defer ensureReaderClosed(resp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return response, err |
| 20 | 21 |
} |
| 21 | 22 |
|
| 22 | 23 |
err = json.NewDecoder(resp.body).Decode(&response) |
| 23 |
- ensureReaderClosed(resp) |
|
| 24 | 24 |
return response, err |
| 25 | 25 |
} |
| ... | ... |
@@ -18,10 +18,10 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S |
| 18 | 18 |
return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id}
|
| 19 | 19 |
} |
| 20 | 20 |
resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) |
| 21 |
+ defer ensureReaderClosed(resp) |
|
| 21 | 22 |
if err != nil {
|
| 22 | 23 |
return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id)
|
| 23 | 24 |
} |
| 24 |
- defer ensureReaderClosed(resp) |
|
| 25 | 25 |
|
| 26 | 26 |
body, err := ioutil.ReadAll(resp.body) |
| 27 | 27 |
if err != nil {
|
| ... | ... |
@@ -27,12 +27,12 @@ func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptio |
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 | 29 |
resp, err := cli.get(ctx, "/secrets", query, nil) |
| 30 |
+ defer ensureReaderClosed(resp) |
|
| 30 | 31 |
if err != nil {
|
| 31 | 32 |
return nil, err |
| 32 | 33 |
} |
| 33 | 34 |
|
| 34 | 35 |
var secrets []swarm.Secret |
| 35 | 36 |
err = json.NewDecoder(resp.body).Decode(&secrets) |
| 36 |
- ensureReaderClosed(resp) |
|
| 37 | 37 |
return secrets, err |
| 38 | 38 |
} |
| ... | ... |
@@ -8,6 +8,6 @@ func (cli *Client) SecretRemove(ctx context.Context, id string) error {
|
| 8 | 8 |
return err |
| 9 | 9 |
} |
| 10 | 10 |
resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil) |
| 11 |
- ensureReaderClosed(resp) |
|
| 11 |
+ defer ensureReaderClosed(resp) |
|
| 12 | 12 |
return wrapResponseError(err, resp, "secret", id) |
| 13 | 13 |
} |
| ... | ... |
@@ -72,6 +72,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, |
| 72 | 72 |
|
| 73 | 73 |
var response types.ServiceCreateResponse |
| 74 | 74 |
resp, err := cli.post(ctx, "/services/create", nil, service, headers) |
| 75 |
+ defer ensureReaderClosed(resp) |
|
| 75 | 76 |
if err != nil {
|
| 76 | 77 |
return response, err |
| 77 | 78 |
} |
| ... | ... |
@@ -82,7 +83,6 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, |
| 82 | 82 |
response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image)) |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 |
- ensureReaderClosed(resp) |
|
| 86 | 85 |
return response, err |
| 87 | 86 |
} |
| 88 | 87 |
|
| ... | ... |
@@ -20,10 +20,10 @@ func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, |
| 20 | 20 |
query := url.Values{}
|
| 21 | 21 |
query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults))
|
| 22 | 22 |
serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) |
| 23 |
+ defer ensureReaderClosed(serverResp) |
|
| 23 | 24 |
if err != nil {
|
| 24 | 25 |
return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID)
|
| 25 | 26 |
} |
| 26 |
- defer ensureReaderClosed(serverResp) |
|
| 27 | 27 |
|
| 28 | 28 |
body, err := ioutil.ReadAll(serverResp.body) |
| 29 | 29 |
if err != nil {
|
| ... | ... |
@@ -24,12 +24,12 @@ func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOpt |
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 | 26 |
resp, err := cli.get(ctx, "/services", query, nil) |
| 27 |
+ defer ensureReaderClosed(resp) |
|
| 27 | 28 |
if err != nil {
|
| 28 | 29 |
return nil, err |
| 29 | 30 |
} |
| 30 | 31 |
|
| 31 | 32 |
var services []swarm.Service |
| 32 | 33 |
err = json.NewDecoder(resp.body).Decode(&services) |
| 33 |
- ensureReaderClosed(resp) |
|
| 34 | 34 |
return services, err |
| 35 | 35 |
} |
| ... | ... |
@@ -5,6 +5,6 @@ import "context" |
| 5 | 5 |
// ServiceRemove kills and removes a service. |
| 6 | 6 |
func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error {
|
| 7 | 7 |
resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) |
| 8 |
- ensureReaderClosed(resp) |
|
| 8 |
+ defer ensureReaderClosed(resp) |
|
| 9 | 9 |
return wrapResponseError(err, resp, "service", serviceID) |
| 10 | 10 |
} |
| ... | ... |
@@ -79,6 +79,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version |
| 79 | 79 |
|
| 80 | 80 |
var response types.ServiceUpdateResponse |
| 81 | 81 |
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) |
| 82 |
+ defer ensureReaderClosed(resp) |
|
| 82 | 83 |
if err != nil {
|
| 83 | 84 |
return response, err |
| 84 | 85 |
} |
| ... | ... |
@@ -89,6 +90,5 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version |
| 89 | 89 |
response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image)) |
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 |
- ensureReaderClosed(resp) |
|
| 93 | 92 |
return response, err |
| 94 | 93 |
} |
| ... | ... |
@@ -10,12 +10,12 @@ import ( |
| 10 | 10 |
// SwarmGetUnlockKey retrieves the swarm's unlock key. |
| 11 | 11 |
func (cli *Client) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) {
|
| 12 | 12 |
serverResp, err := cli.get(ctx, "/swarm/unlockkey", nil, nil) |
| 13 |
+ defer ensureReaderClosed(serverResp) |
|
| 13 | 14 |
if err != nil {
|
| 14 | 15 |
return types.SwarmUnlockKeyResponse{}, err
|
| 15 | 16 |
} |
| 16 | 17 |
|
| 17 | 18 |
var response types.SwarmUnlockKeyResponse |
| 18 | 19 |
err = json.NewDecoder(serverResp.body).Decode(&response) |
| 19 |
- ensureReaderClosed(serverResp) |
|
| 20 | 20 |
return response, err |
| 21 | 21 |
} |
| ... | ... |
@@ -10,12 +10,12 @@ import ( |
| 10 | 10 |
// SwarmInit initializes the swarm. |
| 11 | 11 |
func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) {
|
| 12 | 12 |
serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil) |
| 13 |
+ defer ensureReaderClosed(serverResp) |
|
| 13 | 14 |
if err != nil {
|
| 14 | 15 |
return "", err |
| 15 | 16 |
} |
| 16 | 17 |
|
| 17 | 18 |
var response string |
| 18 | 19 |
err = json.NewDecoder(serverResp.body).Decode(&response) |
| 19 |
- ensureReaderClosed(serverResp) |
|
| 20 | 20 |
return response, err |
| 21 | 21 |
} |
| ... | ... |
@@ -10,12 +10,12 @@ import ( |
| 10 | 10 |
// SwarmInspect inspects the swarm. |
| 11 | 11 |
func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) {
|
| 12 | 12 |
serverResp, err := cli.get(ctx, "/swarm", nil, nil) |
| 13 |
+ defer ensureReaderClosed(serverResp) |
|
| 13 | 14 |
if err != nil {
|
| 14 | 15 |
return swarm.Swarm{}, err
|
| 15 | 16 |
} |
| 16 | 17 |
|
| 17 | 18 |
var response swarm.Swarm |
| 18 | 19 |
err = json.NewDecoder(serverResp.body).Decode(&response) |
| 19 |
- ensureReaderClosed(serverResp) |
|
| 20 | 20 |
return response, err |
| 21 | 21 |
} |
| ... | ... |
@@ -15,10 +15,10 @@ func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm |
| 15 | 15 |
return swarm.Task{}, nil, objectNotFoundError{object: "task", id: taskID}
|
| 16 | 16 |
} |
| 17 | 17 |
serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) |
| 18 |
+ defer ensureReaderClosed(serverResp) |
|
| 18 | 19 |
if err != nil {
|
| 19 | 20 |
return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID)
|
| 20 | 21 |
} |
| 21 |
- defer ensureReaderClosed(serverResp) |
|
| 22 | 22 |
|
| 23 | 23 |
body, err := ioutil.ReadAll(serverResp.body) |
| 24 | 24 |
if err != nil {
|
| ... | ... |
@@ -24,12 +24,12 @@ func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions) |
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 | 26 |
resp, err := cli.get(ctx, "/tasks", query, nil) |
| 27 |
+ defer ensureReaderClosed(resp) |
|
| 27 | 28 |
if err != nil {
|
| 28 | 29 |
return nil, err |
| 29 | 30 |
} |
| 30 | 31 |
|
| 31 | 32 |
var tasks []swarm.Task |
| 32 | 33 |
err = json.NewDecoder(resp.body).Decode(&tasks) |
| 33 |
- ensureReaderClosed(resp) |
|
| 34 | 34 |
return tasks, err |
| 35 | 35 |
} |
| ... | ... |
@@ -10,12 +10,12 @@ import ( |
| 10 | 10 |
// ServerVersion returns information of the docker client and server host. |
| 11 | 11 |
func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
|
| 12 | 12 |
resp, err := cli.get(ctx, "/version", nil, nil) |
| 13 |
+ defer ensureReaderClosed(resp) |
|
| 13 | 14 |
if err != nil {
|
| 14 | 15 |
return types.Version{}, err
|
| 15 | 16 |
} |
| 16 | 17 |
|
| 17 | 18 |
var server types.Version |
| 18 | 19 |
err = json.NewDecoder(resp.body).Decode(&server) |
| 19 |
- ensureReaderClosed(resp) |
|
| 20 | 20 |
return server, err |
| 21 | 21 |
} |
| ... | ... |
@@ -12,10 +12,10 @@ import ( |
| 12 | 12 |
func (cli *Client) VolumeCreate(ctx context.Context, options volumetypes.VolumeCreateBody) (types.Volume, error) {
|
| 13 | 13 |
var volume types.Volume |
| 14 | 14 |
resp, err := cli.post(ctx, "/volumes/create", nil, options, nil) |
| 15 |
+ defer ensureReaderClosed(resp) |
|
| 15 | 16 |
if err != nil {
|
| 16 | 17 |
return volume, err |
| 17 | 18 |
} |
| 18 | 19 |
err = json.NewDecoder(resp.body).Decode(&volume) |
| 19 |
- ensureReaderClosed(resp) |
|
| 20 | 20 |
return volume, err |
| 21 | 21 |
} |
| ... | ... |
@@ -23,10 +23,10 @@ func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (t |
| 23 | 23 |
|
| 24 | 24 |
var volume types.Volume |
| 25 | 25 |
resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil) |
| 26 |
+ defer ensureReaderClosed(resp) |
|
| 26 | 27 |
if err != nil {
|
| 27 | 28 |
return volume, nil, wrapResponseError(err, resp, "volume", volumeID) |
| 28 | 29 |
} |
| 29 |
- defer ensureReaderClosed(resp) |
|
| 30 | 30 |
|
| 31 | 31 |
body, err := ioutil.ReadAll(resp.body) |
| 32 | 32 |
if err != nil {
|
| ... | ... |
@@ -22,11 +22,11 @@ func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volumet |
| 22 | 22 |
query.Set("filters", filterJSON)
|
| 23 | 23 |
} |
| 24 | 24 |
resp, err := cli.get(ctx, "/volumes", query, nil) |
| 25 |
+ defer ensureReaderClosed(resp) |
|
| 25 | 26 |
if err != nil {
|
| 26 | 27 |
return volumes, err |
| 27 | 28 |
} |
| 28 | 29 |
|
| 29 | 30 |
err = json.NewDecoder(resp.body).Decode(&volumes) |
| 30 |
- ensureReaderClosed(resp) |
|
| 31 | 31 |
return volumes, err |
| 32 | 32 |
} |
| ... | ... |
@@ -23,10 +23,10 @@ func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) |
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) |
| 26 |
+ defer ensureReaderClosed(serverResp) |
|
| 26 | 27 |
if err != nil {
|
| 27 | 28 |
return report, err |
| 28 | 29 |
} |
| 29 |
- defer ensureReaderClosed(serverResp) |
|
| 30 | 30 |
|
| 31 | 31 |
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
| 32 | 32 |
return report, fmt.Errorf("Error retrieving volume prune report: %v", err)
|
| ... | ... |
@@ -16,6 +16,6 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool |
| 16 | 16 |
} |
| 17 | 17 |
} |
| 18 | 18 |
resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) |
| 19 |
- ensureReaderClosed(resp) |
|
| 19 |
+ defer ensureReaderClosed(resp) |
|
| 20 | 20 |
return wrapResponseError(err, resp, "volume", volumeID) |
| 21 | 21 |
} |