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
|
// 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 {
if e, ok := err.(*Error); ok && 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 {
if e, ok := err.(*Error); ok {
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
}
|