1// Copyright 2015 go-dockerclient authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package docker 6 7import ( 8 "context" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "net/http" 13 "net/url" 14) 15 16// ErrNetworkAlreadyExists is the error returned by CreateNetwork when the 17// network already exists. 18var ErrNetworkAlreadyExists = errors.New("network already exists") 19 20// Network represents a network. 21// 22// See https://goo.gl/6GugX3 for more details. 23type Network struct { 24 Name string 25 ID string `json:"Id"` 26 Scope string 27 Driver string 28 IPAM IPAMOptions 29 Containers map[string]Endpoint 30 Options map[string]string 31 Internal bool 32 EnableIPv6 bool `json:"EnableIPv6"` 33 Labels map[string]string 34} 35 36// Endpoint contains network resources allocated and used for a container in a network 37// 38// See https://goo.gl/6GugX3 for more details. 39type Endpoint struct { 40 Name string 41 ID string `json:"EndpointID"` 42 MacAddress string 43 IPv4Address string 44 IPv6Address string 45} 46 47// ListNetworks returns all networks. 48// 49// See https://goo.gl/6GugX3 for more details. 50func (c *Client) ListNetworks() ([]Network, error) { 51 resp, err := c.do("GET", "/networks", doOptions{}) 52 if err != nil { 53 return nil, err 54 } 55 defer resp.Body.Close() 56 var networks []Network 57 if err := json.NewDecoder(resp.Body).Decode(&networks); err != nil { 58 return nil, err 59 } 60 return networks, nil 61} 62 63// NetworkFilterOpts is an aggregation of key=value that Docker 64// uses to filter networks 65type NetworkFilterOpts map[string]map[string]bool 66 67// FilteredListNetworks returns all networks with the filters applied 68// 69// See goo.gl/zd2mx4 for more details. 70func (c *Client) FilteredListNetworks(opts NetworkFilterOpts) ([]Network, error) { 71 params, err := json.Marshal(opts) 72 if err != nil { 73 return nil, err 74 } 75 qs := make(url.Values) 76 qs.Add("filters", string(params)) 77 path := "/networks?" + qs.Encode() 78 resp, err := c.do("GET", path, doOptions{}) 79 if err != nil { 80 return nil, err 81 } 82 defer resp.Body.Close() 83 var networks []Network 84 if err := json.NewDecoder(resp.Body).Decode(&networks); err != nil { 85 return nil, err 86 } 87 return networks, nil 88} 89 90// NetworkInfo returns information about a network by its ID. 91// 92// See https://goo.gl/6GugX3 for more details. 93func (c *Client) NetworkInfo(id string) (*Network, error) { 94 path := "/networks/" + id 95 resp, err := c.do("GET", path, doOptions{}) 96 if err != nil { 97 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 98 return nil, &NoSuchNetwork{ID: id} 99 } 100 return nil, err 101 } 102 defer resp.Body.Close() 103 var network Network 104 if err := json.NewDecoder(resp.Body).Decode(&network); err != nil { 105 return nil, err 106 } 107 return &network, nil 108} 109 110// CreateNetworkOptions specify parameters to the CreateNetwork function and 111// (for now) is the expected body of the "create network" http request message 112// 113// See https://goo.gl/6GugX3 for more details. 114type CreateNetworkOptions struct { 115 Name string `json:"Name" yaml:"Name" toml:"Name"` 116 Driver string `json:"Driver" yaml:"Driver" toml:"Driver"` 117 IPAM *IPAMOptions `json:"IPAM,omitempty" yaml:"IPAM" toml:"IPAM"` 118 Options map[string]interface{} `json:"Options" yaml:"Options" toml:"Options"` 119 Labels map[string]string `json:"Labels" yaml:"Labels" toml:"Labels"` 120 CheckDuplicate bool `json:"CheckDuplicate" yaml:"CheckDuplicate" toml:"CheckDuplicate"` 121 Internal bool `json:"Internal" yaml:"Internal" toml:"Internal"` 122 EnableIPv6 bool `json:"EnableIPv6" yaml:"EnableIPv6" toml:"EnableIPv6"` 123 Context context.Context `json:"-"` 124} 125 126// IPAMOptions controls IP Address Management when creating a network 127// 128// See https://goo.gl/T8kRVH for more details. 129type IPAMOptions struct { 130 Driver string `json:"Driver" yaml:"Driver" toml:"Driver"` 131 Config []IPAMConfig `json:"Config" yaml:"Config" toml:"Config"` 132 Options map[string]string `json:"Options" yaml:"Options" toml:"Options"` 133} 134 135// IPAMConfig represents IPAM configurations 136// 137// See https://goo.gl/T8kRVH for more details. 138type IPAMConfig struct { 139 Subnet string `json:",omitempty"` 140 IPRange string `json:",omitempty"` 141 Gateway string `json:",omitempty"` 142 AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"` 143} 144 145// CreateNetwork creates a new network, returning the network instance, 146// or an error in case of failure. 147// 148// See https://goo.gl/6GugX3 for more details. 149func (c *Client) CreateNetwork(opts CreateNetworkOptions) (*Network, error) { 150 resp, err := c.do( 151 "POST", 152 "/networks/create", 153 doOptions{ 154 data: opts, 155 context: opts.Context, 156 }, 157 ) 158 if err != nil { 159 return nil, err 160 } 161 defer resp.Body.Close() 162 163 type createNetworkResponse struct { 164 ID string 165 } 166 var ( 167 network Network 168 cnr createNetworkResponse 169 ) 170 if err := json.NewDecoder(resp.Body).Decode(&cnr); err != nil { 171 return nil, err 172 } 173 174 network.Name = opts.Name 175 network.ID = cnr.ID 176 network.Driver = opts.Driver 177 178 return &network, nil 179} 180 181// RemoveNetwork removes a network or returns an error in case of failure. 182// 183// See https://goo.gl/6GugX3 for more details. 184func (c *Client) RemoveNetwork(id string) error { 185 resp, err := c.do("DELETE", "/networks/"+id, doOptions{}) 186 if err != nil { 187 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 188 return &NoSuchNetwork{ID: id} 189 } 190 return err 191 } 192 resp.Body.Close() 193 return nil 194} 195 196// NetworkConnectionOptions specify parameters to the ConnectNetwork and 197// DisconnectNetwork function. 198// 199// See https://goo.gl/RV7BJU for more details. 200type NetworkConnectionOptions struct { 201 Container string 202 203 // EndpointConfig is only applicable to the ConnectNetwork call 204 EndpointConfig *EndpointConfig `json:"EndpointConfig,omitempty"` 205 206 // Force is only applicable to the DisconnectNetwork call 207 Force bool 208 209 Context context.Context `json:"-"` 210} 211 212// EndpointConfig stores network endpoint details 213// 214// See https://goo.gl/RV7BJU for more details. 215type EndpointConfig struct { 216 IPAMConfig *EndpointIPAMConfig `json:"IPAMConfig,omitempty" yaml:"IPAMConfig,omitempty" toml:"IPAMConfig,omitempty"` 217 Links []string `json:"Links,omitempty" yaml:"Links,omitempty" toml:"Links,omitempty"` 218 Aliases []string `json:"Aliases,omitempty" yaml:"Aliases,omitempty" toml:"Aliases,omitempty"` 219 NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty" toml:"NetworkID,omitempty"` 220 EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty" toml:"EndpointID,omitempty"` 221 Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty" toml:"Gateway,omitempty"` 222 IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty" toml:"IPAddress,omitempty"` 223 IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty" toml:"IPPrefixLen,omitempty"` 224 IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty" toml:"IPv6Gateway,omitempty"` 225 GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty" toml:"GlobalIPv6Address,omitempty"` 226 GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty" toml:"GlobalIPv6PrefixLen,omitempty"` 227 MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty" toml:"MacAddress,omitempty"` 228} 229 230// EndpointIPAMConfig represents IPAM configurations for an 231// endpoint 232// 233// See https://goo.gl/RV7BJU for more details. 234type EndpointIPAMConfig struct { 235 IPv4Address string `json:",omitempty"` 236 IPv6Address string `json:",omitempty"` 237} 238 239// ConnectNetwork adds a container to a network or returns an error in case of 240// failure. 241// 242// See https://goo.gl/6GugX3 for more details. 243func (c *Client) ConnectNetwork(id string, opts NetworkConnectionOptions) error { 244 resp, err := c.do("POST", "/networks/"+id+"/connect", doOptions{ 245 data: opts, 246 context: opts.Context, 247 }) 248 if err != nil { 249 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 250 return &NoSuchNetworkOrContainer{NetworkID: id, ContainerID: opts.Container} 251 } 252 return err 253 } 254 resp.Body.Close() 255 return nil 256} 257 258// DisconnectNetwork removes a container from a network or returns an error in 259// case of failure. 260// 261// See https://goo.gl/6GugX3 for more details. 262func (c *Client) DisconnectNetwork(id string, opts NetworkConnectionOptions) error { 263 resp, err := c.do("POST", "/networks/"+id+"/disconnect", doOptions{data: opts}) 264 if err != nil { 265 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { 266 return &NoSuchNetworkOrContainer{NetworkID: id, ContainerID: opts.Container} 267 } 268 return err 269 } 270 resp.Body.Close() 271 return nil 272} 273 274// PruneNetworksOptions specify parameters to the PruneNetworks function. 275// 276// See https://goo.gl/kX0S9h for more details. 277type PruneNetworksOptions struct { 278 Filters map[string][]string 279 Context context.Context 280} 281 282// PruneNetworksResults specify results from the PruneNetworks function. 283// 284// See https://goo.gl/kX0S9h for more details. 285type PruneNetworksResults struct { 286 NetworksDeleted []string 287} 288 289// PruneNetworks deletes networks which are unused. 290// 291// See https://goo.gl/kX0S9h for more details. 292func (c *Client) PruneNetworks(opts PruneNetworksOptions) (*PruneNetworksResults, error) { 293 path := "/networks/prune?" + queryString(opts) 294 resp, err := c.do("POST", path, doOptions{context: opts.Context}) 295 if err != nil { 296 return nil, err 297 } 298 defer resp.Body.Close() 299 var results PruneNetworksResults 300 if err := json.NewDecoder(resp.Body).Decode(&results); err != nil { 301 return nil, err 302 } 303 return &results, nil 304} 305 306// NoSuchNetwork is the error returned when a given network does not exist. 307type NoSuchNetwork struct { 308 ID string 309} 310 311func (err *NoSuchNetwork) Error() string { 312 return fmt.Sprintf("No such network: %s", err.ID) 313} 314 315// NoSuchNetworkOrContainer is the error returned when a given network or 316// container does not exist. 317type NoSuchNetworkOrContainer struct { 318 NetworkID string 319 ContainerID string 320} 321 322func (err *NoSuchNetworkOrContainer) Error() string { 323 return fmt.Sprintf("No such network (%s) or container (%s)", err.NetworkID, err.ContainerID) 324} 325