aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/fsouza/go-dockerclient/volume.go
blob: 9f8a435c91f1648522c353fe8d16313599e3f634 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// Copyright 2015 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"context"
	"encoding/json"
	"errors"
	"net/http"
	"time"
)

var (
	// ErrNoSuchVolume is the error returned when the volume does not exist.
	ErrNoSuchVolume = errors.New("no such volume")

	// ErrVolumeInUse is the error returned when the volume requested to be removed is still in use.
	ErrVolumeInUse = errors.New("volume in use and cannot be removed")
)

// Volume represents a volume.
//
// See https://goo.gl/3wgTsd for more details.
type Volume struct {
	Name       string            `json:"Name" yaml:"Name" toml:"Name"`
	Driver     string            `json:"Driver,omitempty" yaml:"Driver,omitempty" toml:"Driver,omitempty"`
	Mountpoint string            `json:"Mountpoint,omitempty" yaml:"Mountpoint,omitempty" toml:"Mountpoint,omitempty"`
	Labels     map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty" toml:"Labels,omitempty"`
	Options    map[string]string `json:"Options,omitempty" yaml:"Options,omitempty" toml:"Options,omitempty"`
	CreatedAt  time.Time         `json:"CreatedAt,omitempty" yaml:"CreatedAt,omitempty" toml:"CreatedAt,omitempty"`
}

// ListVolumesOptions specify parameters to the ListVolumes function.
//
// See https://goo.gl/3wgTsd for more details.
type ListVolumesOptions struct {
	Filters map[string][]string
	Context context.Context
}

// ListVolumes returns a list of available volumes in the server.
//
// See https://goo.gl/3wgTsd for more details.
func (c *Client) ListVolumes(opts ListVolumesOptions) ([]Volume, error) {
	resp, err := c.do(http.MethodGet, "/volumes?"+queryString(opts), doOptions{
		context: opts.Context,
	})
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	m := make(map[string]interface{})
	if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return nil, err
	}
	var volumes []Volume
	volumesJSON, ok := m["Volumes"]
	if !ok {
		return volumes, nil
	}
	data, err := json.Marshal(volumesJSON)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(data, &volumes); err != nil {
		return nil, err
	}
	return volumes, nil
}

// CreateVolumeOptions specify parameters to the CreateVolume function.
//
// See https://goo.gl/qEhmEC for more details.
type CreateVolumeOptions struct {
	Name       string
	Driver     string
	DriverOpts map[string]string
	Context    context.Context `json:"-"`
	Labels     map[string]string
}

// CreateVolume creates a volume on the server.
//
// See https://goo.gl/qEhmEC for more details.
func (c *Client) CreateVolume(opts CreateVolumeOptions) (*Volume, error) {
	resp, err := c.do(http.MethodPost, "/volumes/create", doOptions{
		data:    opts,
		context: opts.Context,
	})
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	var volume Volume
	if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
		return nil, err
	}
	return &volume, nil
}

// InspectVolume returns a volume by its name.
//
// See https://goo.gl/GMjsMc for more details.
func (c *Client) InspectVolume(name string) (*Volume, error) {
	resp, err := c.do(http.MethodGet, "/volumes/"+name, doOptions{})
	if err != nil {
		var e *Error
		if errors.As(err, &e) && e.Status == http.StatusNotFound {
			return nil, ErrNoSuchVolume
		}
		return nil, err
	}
	defer resp.Body.Close()
	var volume Volume
	if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
		return nil, err
	}
	return &volume, nil
}

// RemoveVolume removes a volume by its name.
//
// Deprecated: Use RemoveVolumeWithOptions instead.
func (c *Client) RemoveVolume(name string) error {
	return c.RemoveVolumeWithOptions(RemoveVolumeOptions{Name: name})
}

// RemoveVolumeOptions specify parameters to the RemoveVolumeWithOptions
// function.
//
// See https://goo.gl/nvd6qj for more details.
type RemoveVolumeOptions struct {
	Context context.Context
	Name    string `qs:"-"`
	Force   bool
}

// RemoveVolumeWithOptions removes a volume by its name and takes extra
// parameters.
//
// See https://goo.gl/nvd6qj for more details.
func (c *Client) RemoveVolumeWithOptions(opts RemoveVolumeOptions) error {
	path := "/volumes/" + opts.Name
	resp, err := c.do(http.MethodDelete, path+"?"+queryString(opts), doOptions{context: opts.Context})
	if err != nil {
		var e *Error
		if errors.As(err, &e) {
			if e.Status == http.StatusNotFound {
				return ErrNoSuchVolume
			}
			if e.Status == http.StatusConflict {
				return ErrVolumeInUse
			}
		}
		return err
	}
	defer resp.Body.Close()
	return nil
}

// PruneVolumesOptions specify parameters to the PruneVolumes function.
//
// See https://goo.gl/f9XDem for more details.
type PruneVolumesOptions struct {
	Filters map[string][]string
	Context context.Context
}

// PruneVolumesResults specify results from the PruneVolumes function.
//
// See https://goo.gl/f9XDem for more details.
type PruneVolumesResults struct {
	VolumesDeleted []string
	SpaceReclaimed int64
}

// PruneVolumes deletes volumes which are unused.
//
// See https://goo.gl/f9XDem for more details.
func (c *Client) PruneVolumes(opts PruneVolumesOptions) (*PruneVolumesResults, error) {
	path := "/volumes/prune?" + queryString(opts)
	resp, err := c.do(http.MethodPost, path, doOptions{context: opts.Context})
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	var results PruneVolumesResults
	if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
		return nil, err
	}
	return &results, nil
}