Merge pull request #31710 from sanimej/drillerrr

Add verbose flag to network inspect to show all services & tasks in swarm mode
This commit is contained in:
Madhu Venugopal 2017-03-13 21:12:32 -07:00 коммит произвёл GitHub
Родитель bba7d8adda 14f76a21db
Коммит cdf66ba715
37 изменённых файлов: 697 добавлений и 93 удалений

Просмотреть файл

@ -4,10 +4,12 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv"
"strings" "strings"
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/docker/docker/api/errors"
"github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
@ -65,7 +67,7 @@ SKIP:
// run across all the networks. Starting API version 1.27, this detailed // run across all the networks. Starting API version 1.27, this detailed
// info is available for network specific GET API (equivalent to inspect) // info is available for network specific GET API (equivalent to inspect)
if versions.LessThan(httputils.VersionFromContext(ctx), "1.27") { if versions.LessThan(httputils.VersionFromContext(ctx), "1.27") {
nr = n.buildDetailedNetworkResources(nw) nr = n.buildDetailedNetworkResources(nw, false)
} else { } else {
nr = n.buildNetworkResource(nw) nr = n.buildNetworkResource(nw)
} }
@ -85,6 +87,16 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
} }
term := vars["id"] term := vars["id"]
var (
verbose bool
err error
)
if v := r.URL.Query().Get("verbose"); v != "" {
if verbose, err = strconv.ParseBool(v); err != nil {
err = fmt.Errorf("invalid value for verbose: %s", v)
return errors.NewBadRequestError(err)
}
}
// In case multiple networks have duplicate names, return error. // In case multiple networks have duplicate names, return error.
// TODO (yongtang): should we wrap with version here for backward compatibility? // TODO (yongtang): should we wrap with version here for backward compatibility?
@ -100,17 +112,17 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
nw := n.backend.GetNetworks() nw := n.backend.GetNetworks()
for _, network := range nw { for _, network := range nw {
if network.ID() == term { if network.ID() == term {
return httputils.WriteJSON(w, http.StatusOK, *n.buildDetailedNetworkResources(network)) return httputils.WriteJSON(w, http.StatusOK, *n.buildDetailedNetworkResources(network, verbose))
} }
if network.Name() == term { if network.Name() == term {
// No need to check the ID collision here as we are still in // No need to check the ID collision here as we are still in
// local scope and the network ID is unique in this scope. // local scope and the network ID is unique in this scope.
listByFullName[network.ID()] = *n.buildDetailedNetworkResources(network) listByFullName[network.ID()] = *n.buildDetailedNetworkResources(network, verbose)
} }
if strings.HasPrefix(network.ID(), term) { if strings.HasPrefix(network.ID(), term) {
// No need to check the ID collision here as we are still in // No need to check the ID collision here as we are still in
// local scope and the network ID is unique in this scope. // local scope and the network ID is unique in this scope.
listByPartialID[network.ID()] = *n.buildDetailedNetworkResources(network) listByPartialID[network.ID()] = *n.buildDetailedNetworkResources(network, verbose)
} }
} }
@ -294,7 +306,7 @@ func (n *networkRouter) buildNetworkResource(nw libnetwork.Network) *types.Netwo
return r return r
} }
func (n *networkRouter) buildDetailedNetworkResources(nw libnetwork.Network) *types.NetworkResource { func (n *networkRouter) buildDetailedNetworkResources(nw libnetwork.Network, verbose bool) *types.NetworkResource {
if nw == nil { if nw == nil {
return &types.NetworkResource{} return &types.NetworkResource{}
} }
@ -315,6 +327,28 @@ func (n *networkRouter) buildDetailedNetworkResources(nw libnetwork.Network) *ty
r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei) r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei)
} }
if !verbose {
return r
}
services := nw.Info().Services()
r.Services = make(map[string]network.ServiceInfo)
for name, service := range services {
tasks := []network.Task{}
for _, t := range service.Tasks {
tasks = append(tasks, network.Task{
Name: t.Name,
EndpointID: t.EndpointID,
EndpointIP: t.EndpointIP,
Info: t.Info,
})
}
r.Services[name] = network.ServiceInfo{
VIP: service.VIP,
Ports: service.Ports,
Tasks: tasks,
LocalLBIndex: service.LocalLBIndex,
}
}
return r return r
} }

Просмотреть файл

@ -6271,6 +6271,11 @@ paths:
description: "Network ID or name" description: "Network ID or name"
required: true required: true
type: "string" type: "string"
- name: "verbose"
in: "query"
description: "Detailed inspect output for troubleshooting"
type: "boolean"
default: false
tags: ["Network"] tags: ["Network"]
delete: delete:

Просмотреть файл

@ -60,6 +60,22 @@ type EndpointSettings struct {
MacAddress string MacAddress string
} }
// Task carries the information about one backend task
type Task struct {
Name string
EndpointID string
EndpointIP string
Info map[string]string
}
// ServiceInfo represents service parameters with the list of service's tasks
type ServiceInfo struct {
VIP string
Ports []string
LocalLBIndex int
Tasks []Task
}
// Copy makes a deep copy of `EndpointSettings` // Copy makes a deep copy of `EndpointSettings`
func (es *EndpointSettings) Copy() *EndpointSettings { func (es *EndpointSettings) Copy() *EndpointSettings {
epCopy := *es epCopy := *es

Просмотреть файл

@ -391,19 +391,20 @@ type MountPoint struct {
// NetworkResource is the body of the "get network" http response message // NetworkResource is the body of the "get network" http response message
type NetworkResource struct { type NetworkResource struct {
Name string // Name is the requested name of the network Name string // Name is the requested name of the network
ID string `json:"Id"` // ID uniquely identifies a network on a single machine ID string `json:"Id"` // ID uniquely identifies a network on a single machine
Created time.Time // Created is the time the network created Created time.Time // Created is the time the network created
Scope string // Scope describes the level at which the network exists (e.g. `global` for cluster-wide or `local` for machine level) Scope string // Scope describes the level at which the network exists (e.g. `global` for cluster-wide or `local` for machine level)
Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`) Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`)
EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6 EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6
IPAM network.IPAM // IPAM is the network's IP Address Management IPAM network.IPAM // IPAM is the network's IP Address Management
Internal bool // Internal represents if the network is used internal only Internal bool // Internal represents if the network is used internal only
Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode.
Containers map[string]EndpointResource // Containers contains endpoints belonging to the network Containers map[string]EndpointResource // Containers contains endpoints belonging to the network
Options map[string]string // Options holds the network specific options to use for when creating the network Options map[string]string // Options holds the network specific options to use for when creating the network
Labels map[string]string // Labels holds metadata specific to the network being created Labels map[string]string // Labels holds metadata specific to the network being created
Peers []network.PeerInfo `json:",omitempty"` // List of peer nodes for an overlay network Peers []network.PeerInfo `json:",omitempty"` // List of peer nodes for an overlay network
Services map[string]network.ServiceInfo `json:",omitempty"`
} }
// EndpointResource contains network resources allocated and used for a container in a network // EndpointResource contains network resources allocated and used for a container in a network

Просмотреть файл

@ -10,8 +10,9 @@ import (
) )
type inspectOptions struct { type inspectOptions struct {
format string format string
names []string names []string
verbose bool
} }
func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
@ -28,6 +29,7 @@ func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
} }
cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
cmd.Flags().BoolVarP(&opts.verbose, "verbose", "v", false, "Verbose output for diagnostics")
return cmd return cmd
} }
@ -38,7 +40,7 @@ func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
ctx := context.Background() ctx := context.Background()
getNetFunc := func(name string) (interface{}, []byte, error) { getNetFunc := func(name string) (interface{}, []byte, error) {
return client.NetworkInspectWithRaw(ctx, name) return client.NetworkInspectWithRaw(ctx, name, opts.verbose)
} }
return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getNetFunc) return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getNetFunc)

Просмотреть файл

@ -140,7 +140,7 @@ func validateExternalNetworks(
client := dockerCli.Client() client := dockerCli.Client()
for _, networkName := range externalNetworks { for _, networkName := range externalNetworks {
network, err := client.NetworkInspect(ctx, networkName) network, err := client.NetworkInspect(ctx, networkName, false)
if err != nil { if err != nil {
if dockerclient.IsErrNetworkNotFound(err) { if dockerclient.IsErrNetworkNotFound(err) {
return fmt.Errorf("network %q is declared as external, but could not be found. You need to create the network before the stack is deployed (with overlay driver)", networkName) return fmt.Errorf("network %q is declared as external, but could not be found. You need to create the network before the stack is deployed (with overlay driver)", networkName)

Просмотреть файл

@ -67,7 +67,7 @@ func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.Ge
func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
return func(ref string) (interface{}, []byte, error) { return func(ref string) (interface{}, []byte, error) {
return dockerCli.Client().NetworkInspectWithRaw(ctx, ref) return dockerCli.Client().NetworkInspectWithRaw(ctx, ref, false)
} }
} }

Просмотреть файл

@ -91,8 +91,8 @@ type NetworkAPIClient interface {
NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error
NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) NetworkInspect(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, error)
NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error) NetworkInspectWithRaw(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, []byte, error)
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
NetworkRemove(ctx context.Context, networkID string) error NetworkRemove(ctx context.Context, networkID string) error
NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error)

Просмотреть файл

@ -5,21 +5,30 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
// NetworkInspect returns the information for a specific network configured in the docker host. // NetworkInspect returns the information for a specific network configured in the docker host.
func (cli *Client) NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) { func (cli *Client) NetworkInspect(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, error) {
networkResource, _, err := cli.NetworkInspectWithRaw(ctx, networkID) networkResource, _, err := cli.NetworkInspectWithRaw(ctx, networkID, verbose)
return networkResource, err return networkResource, err
} }
// NetworkInspectWithRaw returns the information for a specific network configured in the docker host and its raw representation. // NetworkInspectWithRaw returns the information for a specific network configured in the docker host and its raw representation.
func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error) { func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, []byte, error) {
var networkResource types.NetworkResource var (
resp, err := cli.get(ctx, "/networks/"+networkID, nil, nil) networkResource types.NetworkResource
resp serverResponse
err error
)
query := url.Values{}
if verbose {
query.Set("verbose", "true")
}
resp, err = cli.get(ctx, "/networks/"+networkID, query, nil)
if err != nil { if err != nil {
if resp.statusCode == http.StatusNotFound { if resp.statusCode == http.StatusNotFound {
return networkResource, nil, networkNotFoundError{networkID} return networkResource, nil, networkNotFoundError{networkID}

Просмотреть файл

@ -10,6 +10,7 @@ import (
"testing" "testing"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/network"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -18,7 +19,7 @@ func TestNetworkInspectError(t *testing.T) {
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
} }
_, err := client.NetworkInspect(context.Background(), "nothing") _, err := client.NetworkInspect(context.Background(), "nothing", false)
if err == nil || err.Error() != "Error response from daemon: Server error" { if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err) t.Fatalf("expected a Server Error, got %v", err)
} }
@ -29,7 +30,7 @@ func TestNetworkInspectContainerNotFound(t *testing.T) {
client: newMockClient(errorMock(http.StatusNotFound, "Server error")), client: newMockClient(errorMock(http.StatusNotFound, "Server error")),
} }
_, err := client.NetworkInspect(context.Background(), "unknown") _, err := client.NetworkInspect(context.Background(), "unknown", false)
if err == nil || !IsErrNetworkNotFound(err) { if err == nil || !IsErrNetworkNotFound(err) {
t.Fatalf("expected a networkNotFound error, got %v", err) t.Fatalf("expected a networkNotFound error, got %v", err)
} }
@ -46,9 +47,23 @@ func TestNetworkInspect(t *testing.T) {
return nil, fmt.Errorf("expected GET method, got %s", req.Method) return nil, fmt.Errorf("expected GET method, got %s", req.Method)
} }
content, err := json.Marshal(types.NetworkResource{ var (
Name: "mynetwork", content []byte
}) err error
)
if strings.HasPrefix(req.URL.RawQuery, "verbose=true") {
s := map[string]network.ServiceInfo{
"web": {},
}
content, err = json.Marshal(types.NetworkResource{
Name: "mynetwork",
Services: s,
})
} else {
content, err = json.Marshal(types.NetworkResource{
Name: "mynetwork",
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -59,11 +74,23 @@ func TestNetworkInspect(t *testing.T) {
}), }),
} }
r, err := client.NetworkInspect(context.Background(), "network_id") r, err := client.NetworkInspect(context.Background(), "network_id", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Name != "mynetwork" { if r.Name != "mynetwork" {
t.Fatalf("expected `mynetwork`, got %s", r.Name) t.Fatalf("expected `mynetwork`, got %s", r.Name)
} }
r, err = client.NetworkInspect(context.Background(), "network_id", true)
if err != nil {
t.Fatal(err)
}
if r.Name != "mynetwork" {
t.Fatalf("expected `mynetwork`, got %s", r.Name)
}
_, ok := r.Services["web"]
if !ok {
t.Fatalf("expected service `web` missing in the verbose output")
}
} }

Просмотреть файл

@ -17,6 +17,7 @@ keywords: "API, Docker, rcli, REST, documentation"
[Docker Engine API v1.27](https://docs.docker.com/engine/api/v1.27/) documentation [Docker Engine API v1.27](https://docs.docker.com/engine/api/v1.27/) documentation
* Optional query parameter `verbose` for `GET /networks/(id or name)` will now list all services with all the tasks, including the non-local tasks on the given network.
* `GET /containers/(id or name)/attach/ws` now returns WebSocket in binary frame format for API version >= v1.27, and returns WebSocket in text frame format for API version< v1.27, for the purpose of backward-compatibility. * `GET /containers/(id or name)/attach/ws` now returns WebSocket in binary frame format for API version >= v1.27, and returns WebSocket in text frame format for API version< v1.27, for the purpose of backward-compatibility.
* `GET /networks` is optimised only to return list of all networks and network specific information. List of all containers attached to a specific network is removed from this API and is only available using the network specific `GET /networks/{network-id}. * `GET /networks` is optimised only to return list of all networks and network specific information. List of all containers attached to a specific network is removed from this API and is only available using the network specific `GET /networks/{network-id}.
* `GET /containers/json` now supports `publish` and `expose` filters to filter containers that expose or publish certain ports. * `GET /containers/json` now supports `publish` and `expose` filters to filter containers that expose or publish certain ports.

Просмотреть файл

@ -48,7 +48,7 @@ The `network inspect` command shows the containers, by id, in its
results. For networks backed by multi-host network driver, such as Overlay, results. For networks backed by multi-host network driver, such as Overlay,
this command also shows the container endpoints in other hosts in the this command also shows the container endpoints in other hosts in the
cluster. These endpoints are represented as "ep-{endpoint-id}" in the output. cluster. These endpoints are represented as "ep-{endpoint-id}" in the output.
However, for swarm-scoped networks, only the endpoints that are local to the However, for swarm mode networks, only the endpoints that are local to the
node are shown. node are shown.
You can specify an alternate format to execute a given You can specify an alternate format to execute a given
@ -201,6 +201,101 @@ $ docker network inspect ingress
] ]
``` ```
### Using `verbose` option for `network inspect`
`docker network inspect --verbose` for swarm mode overlay networks shows service-specific
details such as the service's VIP and port mappings. It also shows IPs of service tasks,
and the IPs of the nodes where the tasks are running.
Following is an example output for a overlay network `ov1` that has one service `s1`
attached to. service `s1` in this case has three replicas.
```bash
$ docker network inspect --verbose ov1
[
{
"Name": "ov1",
"Id": "ybmyjvao9vtzy3oorxbssj13b",
"Created": "2017-03-13T17:04:39.776106792Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"020403bd88a15f60747fd25d1ad5fa1272eb740e8a97fc547d8ad07b2f721c5e": {
"Name": "s1.1.pjn2ik0sfgkfzed3h0s00gs9o",
"EndpointID": "ad16946f416562d658f3bb30b9830d73ad91ccf6feae44411269cd0ff674714e",
"MacAddress": "02:42:0a:00:00:04",
"IPv4Address": "10.0.0.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": {},
"Peers": [
{
"Name": "net-3-5d3cfd30a58c",
"IP": "192.168.33.13"
},
{
"Name": "net-1-6ecbc0040a73",
"IP": "192.168.33.11"
},
{
"Name": "net-2-fb80208efd75",
"IP": "192.168.33.12"
}
],
"Services": {
"s1": {
"VIP": "10.0.0.2",
"Ports": [],
"LocalLBIndex": 257,
"Tasks": [
{
"Name": "s1.2.q4hcq2aiiml25ubtrtg4q1txt",
"EndpointID": "040879b027e55fb658e8b60ae3b87c6cdac7d291e86a190a3b5ac6567b26511a",
"EndpointIP": "10.0.0.5",
"Info": {
"Host IP": "192.168.33.11"
}
},
{
"Name": "s1.3.yawl4cgkp7imkfx469kn9j6lm",
"EndpointID": "106edff9f120efe44068b834e1cddb5b39dd4a3af70211378b2f7a9e562bbad8",
"EndpointIP": "10.0.0.3",
"Info": {
"Host IP": "192.168.33.12"
}
},
{
"Name": "s1.1.pjn2ik0sfgkfzed3h0s00gs9o",
"EndpointID": "ad16946f416562d658f3bb30b9830d73ad91ccf6feae44411269cd0ff674714e",
"EndpointIP": "10.0.0.4",
"Info": {
"Host IP": "192.168.33.13"
}
}
]
}
}
}
]
```
## Related commands ## Related commands
* [network disconnect ](network_disconnect.md) * [network disconnect ](network_disconnect.md)

Просмотреть файл

@ -86,3 +86,96 @@ $ docker network inspect simple-network
} }
] ]
``` ```
`docker network inspect --verbose` for swarm mode overlay networks shows service-specific
details such as the service's VIP and port mappings. It also shows IPs of service tasks,
and the IPs of the nodes where the tasks are running.
Following is an example output for a overlay network `ov1` that has one service `s1`
attached to. service `s1` in this case has three replicas.
```bash
$ docker network inspect --verbose ov1
[
{
"Name": "ov1",
"Id": "ybmyjvao9vtzy3oorxbssj13b",
"Created": "2017-03-13T17:04:39.776106792Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Containers": {
"020403bd88a15f60747fd25d1ad5fa1272eb740e8a97fc547d8ad07b2f721c5e": {
"Name": "s1.1.pjn2ik0sfgkfzed3h0s00gs9o",
"EndpointID": "ad16946f416562d658f3bb30b9830d73ad91ccf6feae44411269cd0ff674714e",
"MacAddress": "02:42:0a:00:00:04",
"IPv4Address": "10.0.0.4/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4097"
},
"Labels": {},
"Peers": [
{
"Name": "net-3-5d3cfd30a58c",
"IP": "192.168.33.13"
},
{
"Name": "net-1-6ecbc0040a73",
"IP": "192.168.33.11"
},
{
"Name": "net-2-fb80208efd75",
"IP": "192.168.33.12"
}
],
"Services": {
"s1": {
"VIP": "10.0.0.2",
"Ports": [],
"LocalLBIndex": 257,
"Tasks": [
{
"Name": "s1.2.q4hcq2aiiml25ubtrtg4q1txt",
"EndpointID": "040879b027e55fb658e8b60ae3b87c6cdac7d291e86a190a3b5ac6567b26511a",
"EndpointIP": "10.0.0.5",
"Info": {
"Host IP": "192.168.33.11"
}
},
{
"Name": "s1.3.yawl4cgkp7imkfx469kn9j6lm",
"EndpointID": "106edff9f120efe44068b834e1cddb5b39dd4a3af70211378b2f7a9e562bbad8",
"EndpointIP": "10.0.0.3",
"Info": {
"Host IP": "192.168.33.12"
}
},
{
"Name": "s1.1.pjn2ik0sfgkfzed3h0s00gs9o",
"EndpointID": "ad16946f416562d658f3bb30b9830d73ad91ccf6feae44411269cd0ff674714e",
"EndpointIP": "10.0.0.4",
"Info": {
"Host IP": "192.168.33.13"
}
}
]
}
}
}
]
```

Просмотреть файл

@ -23,7 +23,7 @@ github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5
github.com/imdario/mergo 0.2.1 github.com/imdario/mergo 0.2.1
#get libnetwork packages #get libnetwork packages
github.com/docker/libnetwork 1a019214c9cb80bd56219e5d6994a22caf302895 github.com/docker/libnetwork 4610dd67c7b9828bb4719d8aa2ac53a7f1f739d2
github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec

121
vendor/github.com/docker/libnetwork/agent.go сгенерированный поставляемый
Просмотреть файл

@ -44,6 +44,8 @@ type agent struct {
sync.Mutex sync.Mutex
} }
const libnetworkEPTable = "endpoint_table"
func getBindAddr(ifaceName string) (string, error) { func getBindAddr(ifaceName string) (string, error) {
iface, err := net.InterfaceByName(ifaceName) iface, err := net.InterfaceByName(ifaceName)
if err != nil { if err != nil {
@ -285,7 +287,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st
return err return err
} }
ch, cancel := nDB.Watch("endpoint_table", "", "") ch, cancel := nDB.Watch(libnetworkEPTable, "", "")
nodeCh, cancel := nDB.Watch(networkdb.NodeTable, "", "") nodeCh, cancel := nDB.Watch(networkdb.NodeTable, "", "")
c.Lock() c.Lock()
@ -385,6 +387,111 @@ func (c *controller) agentClose() {
agent.networkDB.Close() agent.networkDB.Close()
} }
// Task has the backend container details
type Task struct {
Name string
EndpointID string
EndpointIP string
Info map[string]string
}
// ServiceInfo has service specific details along with the list of backend tasks
type ServiceInfo struct {
VIP string
LocalLBIndex int
Tasks []Task
Ports []string
}
type epRecord struct {
ep EndpointRecord
info map[string]string
lbIndex int
}
func (n *network) Services() map[string]ServiceInfo {
eps := make(map[string]epRecord)
if !n.isClusterEligible() {
return nil
}
agent := n.getController().getAgent()
if agent == nil {
return nil
}
// Walk through libnetworkEPTable and fetch the driver agnostic endpoint info
entries := agent.networkDB.GetTableByNetwork(libnetworkEPTable, n.id)
for eid, value := range entries {
var epRec EndpointRecord
nid := n.ID()
if err := proto.Unmarshal(value.([]byte), &epRec); err != nil {
logrus.Errorf("Unmarshal of libnetworkEPTable failed for endpoint %s in network %s, %v", eid, nid, err)
continue
}
i := n.getController().getLBIndex(epRec.ServiceID, nid, epRec.IngressPorts)
eps[eid] = epRecord{
ep: epRec,
lbIndex: i,
}
}
// Walk through the driver's tables, have the driver decode the entries
// and return the tuple {ep ID, value}. value is a string that coveys
// relevant info about the endpoint.
d, err := n.driver(true)
if err != nil {
logrus.Errorf("Could not resolve driver for network %s/%s while fetching services: %v", n.networkType, n.ID(), err)
return nil
}
for _, table := range n.driverTables {
if table.objType != driverapi.EndpointObject {
continue
}
entries := agent.networkDB.GetTableByNetwork(table.name, n.id)
for key, value := range entries {
epID, info := d.DecodeTableEntry(table.name, key, value.([]byte))
if ep, ok := eps[epID]; !ok {
logrus.Errorf("Inconsistent driver and libnetwork state for endpoint %s", epID)
} else {
ep.info = info
eps[epID] = ep
}
}
}
// group the endpoints into a map keyed by the service name
sinfo := make(map[string]ServiceInfo)
for ep, epr := range eps {
var (
s ServiceInfo
ok bool
)
if s, ok = sinfo[epr.ep.ServiceName]; !ok {
s = ServiceInfo{
VIP: epr.ep.VirtualIP,
LocalLBIndex: epr.lbIndex,
}
}
ports := []string{}
if s.Ports == nil {
for _, port := range epr.ep.IngressPorts {
p := fmt.Sprintf("Target: %d, Publish: %d", port.TargetPort, port.PublishedPort)
ports = append(ports, p)
}
s.Ports = ports
}
s.Tasks = append(s.Tasks, Task{
Name: epr.ep.Name,
EndpointID: ep,
EndpointIP: epr.ep.EndpointIP,
Info: epr.info,
})
sinfo[epr.ep.ServiceName] = s
}
return sinfo
}
func (n *network) isClusterEligible() bool { func (n *network) isClusterEligible() bool {
if n.driverScope() != datastore.GlobalScope { if n.driverScope() != datastore.GlobalScope {
return false return false
@ -508,7 +615,7 @@ func (ep *endpoint) addServiceInfoToCluster() error {
} }
if agent != nil { if agent != nil {
if err := agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil { if err := agent.networkDB.CreateEntry(libnetworkEPTable, n.ID(), ep.ID(), buf); err != nil {
return err return err
} }
} }
@ -541,7 +648,7 @@ func (ep *endpoint) deleteServiceInfoFromCluster() error {
} }
if agent != nil { if agent != nil {
if err := agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil { if err := agent.networkDB.DeleteEntry(libnetworkEPTable, n.ID(), ep.ID()); err != nil {
return err return err
} }
} }
@ -559,8 +666,8 @@ func (n *network) addDriverWatches() {
if agent == nil { if agent == nil {
return return
} }
for _, tableName := range n.driverTables { for _, table := range n.driverTables {
ch, cancel := agent.networkDB.Watch(tableName, n.ID(), "") ch, cancel := agent.networkDB.Watch(table.name, n.ID(), "")
agent.Lock() agent.Lock()
agent.driverCancelFuncs[n.ID()] = append(agent.driverCancelFuncs[n.ID()], cancel) agent.driverCancelFuncs[n.ID()] = append(agent.driverCancelFuncs[n.ID()], cancel)
agent.Unlock() agent.Unlock()
@ -571,9 +678,9 @@ func (n *network) addDriverWatches() {
return return
} }
agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool { agent.networkDB.WalkTable(table.name, func(nid, key string, value []byte) bool {
if nid == n.ID() { if nid == n.ID() {
d.EventNotify(driverapi.Create, nid, tableName, key, value) d.EventNotify(driverapi.Create, nid, table.name, key, value)
} }
return false return false

37
vendor/github.com/docker/libnetwork/driverapi/driverapi.go сгенерированный поставляемый
Просмотреть файл

@ -72,6 +72,16 @@ type Driver interface {
// only invoked for the global scope driver. // only invoked for the global scope driver.
EventNotify(event EventType, nid string, tableName string, key string, value []byte) EventNotify(event EventType, nid string, tableName string, key string, value []byte)
// DecodeTableEntry passes the driver a key, value pair from table it registered
// with libnetwork. Driver should return {object ID, map[string]string} tuple.
// If DecodeTableEntry is called for a table associated with NetworkObject or
// EndpointObject the return object ID should be the network id or endppoint id
// associated with that entry. map should have information about the object that
// can be presented to the user.
// For exampe: overlay driver returns the VTEP IP of the host that has the endpoint
// which is shown in 'network inspect --verbose'
DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string)
// Type returns the type of this driver, the network type this driver manages // Type returns the type of this driver, the network type this driver manages
Type() string Type() string
@ -84,7 +94,7 @@ type Driver interface {
type NetworkInfo interface { type NetworkInfo interface {
// TableEventRegister registers driver interest in a given // TableEventRegister registers driver interest in a given
// table name. // table name.
TableEventRegister(tableName string) error TableEventRegister(tableName string, objType ObjectType) error
} }
// InterfaceInfo provides a go interface for drivers to retrive // InterfaceInfo provides a go interface for drivers to retrive
@ -175,3 +185,28 @@ const (
// Delete event is generated when a table entry is deleted. // Delete event is generated when a table entry is deleted.
Delete Delete
) )
// ObjectType represents the type of object driver wants to store in libnetwork's networkDB
type ObjectType int
const (
// EndpointObject should be set for libnetwork endpoint object related data
EndpointObject ObjectType = 1 + iota
// NetworkObject should be set for libnetwork network object related data
NetworkObject
// OpaqueObject is for driver specific data with no corresponding libnetwork object
OpaqueObject
)
// IsValidType validates the passed in type against the valid object types
func IsValidType(objType ObjectType) bool {
switch objType {
case EndpointObject:
fallthrough
case NetworkObject:
fallthrough
case OpaqueObject:
return true
}
return false
}

4
vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go сгенерированный поставляемый
Просмотреть файл

@ -575,6 +575,10 @@ func (d *driver) NetworkFree(id string) error {
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
// Create a new network using bridge plugin // Create a new network using bridge plugin
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {

6
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go сгенерированный поставляемый
Просмотреть файл

@ -140,7 +140,6 @@ func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, hairp
hpNatRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", bridgeIface, "-j", "MASQUERADE"}} hpNatRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", bridgeIface, "-j", "MASQUERADE"}}
skipDNAT = iptRule{table: iptables.Nat, chain: DockerChain, preArgs: []string{"-t", "nat"}, args: []string{"-i", bridgeIface, "-j", "RETURN"}} skipDNAT = iptRule{table: iptables.Nat, chain: DockerChain, preArgs: []string{"-t", "nat"}, args: []string{"-i", bridgeIface, "-j", "RETURN"}}
outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}} outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}}
inRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}
) )
// Set NAT. // Set NAT.
@ -173,11 +172,6 @@ func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, hairp
return err return err
} }
// Set Accept on incoming packets for existing connections.
if err := programChainRule(inRule, "ACCEPT INCOMING", enable); err != nil {
return err
}
return nil return nil
} }

4
vendor/github.com/docker/libnetwork/drivers/host/host.go сгенерированный поставляемый
Просмотреть файл

@ -35,6 +35,10 @@ func (d *driver) NetworkFree(id string) error {
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
d.Lock() d.Lock()
defer d.Unlock() defer d.Unlock()

4
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan.go сгенерированный поставляемый
Просмотреть файл

@ -108,3 +108,7 @@ func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}

4
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan.go сгенерированный поставляемый
Просмотреть файл

@ -110,3 +110,7 @@ func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}

4
vendor/github.com/docker/libnetwork/drivers/null/null.go сгенерированный поставляемый
Просмотреть файл

@ -35,6 +35,10 @@ func (d *driver) NetworkFree(id string) error {
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
d.Lock() d.Lock()
defer d.Unlock() defer d.Unlock()

70
vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go сгенерированный поставляемый
Просмотреть файл

@ -20,7 +20,7 @@ import (
) )
const ( const (
mark = uint32(0xD0C4E3) r = 0xD0C4E3
timeout = 30 timeout = 30
pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8) pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8)
) )
@ -31,6 +31,8 @@ const (
bidir bidir
) )
var spMark = netlink.XfrmMark{Value: uint32(r), Mask: 0xffffffff}
type key struct { type key struct {
value []byte value []byte
tag uint32 tag uint32
@ -201,7 +203,7 @@ func programMangle(vni uint32, add bool) (err error) {
var ( var (
p = strconv.FormatUint(uint64(vxlanPort), 10) p = strconv.FormatUint(uint64(vxlanPort), 10)
c = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8) c = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8)
m = strconv.FormatUint(uint64(mark), 10) m = strconv.FormatUint(uint64(r), 10)
chain = "OUTPUT" chain = "OUTPUT"
rule = []string{"-p", "udp", "--dport", p, "-m", "u32", "--u32", c, "-j", "MARK", "--set-mark", m} rule = []string{"-p", "udp", "--dport", p, "-m", "u32", "--u32", c, "-j", "MARK", "--set-mark", m}
a = "-A" a = "-A"
@ -271,6 +273,7 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
Proto: netlink.XFRM_PROTO_ESP, Proto: netlink.XFRM_PROTO_ESP,
Spi: spi.reverse, Spi: spi.reverse,
Mode: netlink.XFRM_MODE_TRANSPORT, Mode: netlink.XFRM_MODE_TRANSPORT,
Reqid: r,
} }
if add { if add {
rSA.Aead = buildAeadAlgo(k, spi.reverse) rSA.Aead = buildAeadAlgo(k, spi.reverse)
@ -296,6 +299,7 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
Proto: netlink.XFRM_PROTO_ESP, Proto: netlink.XFRM_PROTO_ESP,
Spi: spi.forward, Spi: spi.forward,
Mode: netlink.XFRM_MODE_TRANSPORT, Mode: netlink.XFRM_MODE_TRANSPORT,
Reqid: r,
} }
if add { if add {
fSA.Aead = buildAeadAlgo(k, spi.forward) fSA.Aead = buildAeadAlgo(k, spi.forward)
@ -325,17 +329,18 @@ func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
xfrmProgram = ns.NlHandle().XfrmPolicyAdd xfrmProgram = ns.NlHandle().XfrmPolicyAdd
} }
fullMask := net.CIDRMask(8*len(fSA.Src), 8*len(fSA.Src)) // Create a congruent cidr
s := types.GetMinimalIP(fSA.Src)
d := types.GetMinimalIP(fSA.Dst)
fullMask := net.CIDRMask(8*len(s), 8*len(s))
fPol := &netlink.XfrmPolicy{ fPol := &netlink.XfrmPolicy{
Src: &net.IPNet{IP: fSA.Src, Mask: fullMask}, Src: &net.IPNet{IP: s, Mask: fullMask},
Dst: &net.IPNet{IP: fSA.Dst, Mask: fullMask}, Dst: &net.IPNet{IP: d, Mask: fullMask},
Dir: netlink.XFRM_DIR_OUT, Dir: netlink.XFRM_DIR_OUT,
Proto: 17, Proto: 17,
DstPort: 4789, DstPort: 4789,
Mark: &netlink.XfrmMark{ Mark: &spMark,
Value: mark,
},
Tmpls: []netlink.XfrmPolicyTmpl{ Tmpls: []netlink.XfrmPolicyTmpl{
{ {
Src: fSA.Src, Src: fSA.Src,
@ -343,6 +348,7 @@ func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
Proto: netlink.XFRM_PROTO_ESP, Proto: netlink.XFRM_PROTO_ESP,
Mode: netlink.XFRM_MODE_TRANSPORT, Mode: netlink.XFRM_MODE_TRANSPORT,
Spi: fSA.Spi, Spi: fSA.Spi,
Reqid: r,
}, },
}, },
} }
@ -426,6 +432,8 @@ func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
} }
func (d *driver) setKeys(keys []*key) error { func (d *driver) setKeys(keys []*key) error {
// Remove any stale policy, state
clearEncryptionStates()
// Accept the encryption keys and clear any stale encryption map // Accept the encryption keys and clear any stale encryption map
d.Lock() d.Lock()
d.keys = keys d.keys = keys
@ -526,7 +534,7 @@ func updateNodeKey(lIP, aIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, pr
} }
if newIdx > -1 { if newIdx > -1 {
// +RSA2 // +rSA2
programSA(lIP, rIP, spis[newIdx], curKeys[newIdx], reverse, true) programSA(lIP, rIP, spis[newIdx], curKeys[newIdx], reverse, true)
} }
@ -535,16 +543,17 @@ func updateNodeKey(lIP, aIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, pr
fSA2, _, _ := programSA(lIP, rIP, spis[priIdx], curKeys[priIdx], forward, true) fSA2, _, _ := programSA(lIP, rIP, spis[priIdx], curKeys[priIdx], forward, true)
// +fSP2, -fSP1 // +fSP2, -fSP1
fullMask := net.CIDRMask(8*len(fSA2.Src), 8*len(fSA2.Src)) s := types.GetMinimalIP(fSA2.Src)
d := types.GetMinimalIP(fSA2.Dst)
fullMask := net.CIDRMask(8*len(s), 8*len(s))
fSP1 := &netlink.XfrmPolicy{ fSP1 := &netlink.XfrmPolicy{
Src: &net.IPNet{IP: fSA2.Src, Mask: fullMask}, Src: &net.IPNet{IP: s, Mask: fullMask},
Dst: &net.IPNet{IP: fSA2.Dst, Mask: fullMask}, Dst: &net.IPNet{IP: d, Mask: fullMask},
Dir: netlink.XFRM_DIR_OUT, Dir: netlink.XFRM_DIR_OUT,
Proto: 17, Proto: 17,
DstPort: 4789, DstPort: 4789,
Mark: &netlink.XfrmMark{ Mark: &spMark,
Value: mark,
},
Tmpls: []netlink.XfrmPolicyTmpl{ Tmpls: []netlink.XfrmPolicyTmpl{
{ {
Src: fSA2.Src, Src: fSA2.Src,
@ -552,6 +561,7 @@ func updateNodeKey(lIP, aIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, pr
Proto: netlink.XFRM_PROTO_ESP, Proto: netlink.XFRM_PROTO_ESP,
Mode: netlink.XFRM_MODE_TRANSPORT, Mode: netlink.XFRM_MODE_TRANSPORT,
Spi: fSA2.Spi, Spi: fSA2.Spi,
Reqid: r,
}, },
}, },
} }
@ -597,3 +607,33 @@ func (n *network) maxMTU() int {
} }
return mtu return mtu
} }
func clearEncryptionStates() {
nlh := ns.NlHandle()
spList, err := nlh.XfrmPolicyList(netlink.FAMILY_ALL)
if err != nil {
logrus.Warnf("Failed to retrieve SP list for cleanup: %v", err)
}
saList, err := nlh.XfrmStateList(netlink.FAMILY_ALL)
if err != nil {
logrus.Warnf("Failed to retrieve SA list for cleanup: %v", err)
}
for _, sp := range spList {
if sp.Mark != nil && sp.Mark.Value == spMark.Value {
if err := nlh.XfrmPolicyDel(&sp); err != nil {
logrus.Warnf("Failed to delete stale SP %s: %v", sp, err)
continue
}
logrus.Debugf("Removed stale SP: %s", sp)
}
}
for _, sa := range saList {
if sa.Reqid == r {
if err := nlh.XfrmStateDel(&sa); err != nil {
logrus.Warnf("Failed to delete stale SA %s: %v", sa, err)
continue
}
logrus.Debugf("Removed stale SA: %s", sa)
}
}
}

17
vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go сгенерированный поставляемый
Просмотреть файл

@ -145,6 +145,23 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
return nil return nil
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
if tablename != ovPeerTable {
logrus.Errorf("DecodeTableEntry: unexpected table name %s", tablename)
return "", nil
}
var peer PeerRecord
if err := proto.Unmarshal(value, &peer); err != nil {
logrus.Errorf("DecodeTableEntry: failed to unmarshal peer record for key %s: %v", key, err)
return "", nil
}
return key, map[string]string{
"Host IP": peer.TunnelEndpointIP,
}
}
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
if tableName != ovPeerTable { if tableName != ovPeerTable {
logrus.Errorf("Unexpected table notification for table %s received", tableName) logrus.Errorf("Unexpected table notification for table %s received", tableName)

2
vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go сгенерированный поставляемый
Просмотреть файл

@ -159,7 +159,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
} }
if nInfo != nil { if nInfo != nil {
if err := nInfo.TableEventRegister(ovPeerTable); err != nil { if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
return err return err
} }
} }

4
vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go сгенерированный поставляемый
Просмотреть файл

@ -199,6 +199,10 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
func (d *driver) DeleteNetwork(nid string) error { func (d *driver) DeleteNetwork(nid string) error {
return types.NotImplementedErrorf("not implemented") return types.NotImplementedErrorf("not implemented")
} }

4
vendor/github.com/docker/libnetwork/drivers/remote/driver.go сгенерированный поставляемый
Просмотреть файл

@ -116,6 +116,10 @@ func (d *driver) NetworkFree(id string) error {
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
func (d *driver) CreateNetwork(id string, options map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { func (d *driver) CreateNetwork(id string, options map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
create := &api.CreateNetworkRequest{ create := &api.CreateNetworkRequest{
NetworkID: id, NetworkID: id,

4
vendor/github.com/docker/libnetwork/drivers/solaris/bridge/bridge.go сгенерированный поставляемый
Просмотреть файл

@ -175,6 +175,10 @@ func (d *driver) NetworkFree(id string) error {
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
return types.BadRequestErrorf("ipv4 pool is empty") return types.BadRequestErrorf("ipv4 pool is empty")

4
vendor/github.com/docker/libnetwork/drivers/solaris/overlay/joinleave.go сгенерированный поставляемый
Просмотреть файл

@ -149,6 +149,10 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri
d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true) d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true)
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
// Leave method is invoked when a Sandbox detaches from an endpoint. // Leave method is invoked when a Sandbox detaches from an endpoint.
func (d *driver) Leave(nid, eid string) error { func (d *driver) Leave(nid, eid string) error {
if err := validateID(nid, eid); err != nil { if err := validateID(nid, eid); err != nil {

2
vendor/github.com/docker/libnetwork/drivers/solaris/overlay/ov_network.go сгенерированный поставляемый
Просмотреть файл

@ -153,7 +153,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
} }
if nInfo != nil { if nInfo != nil {
if err := nInfo.TableEventRegister(ovPeerTable); err != nil { if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
return err return err
} }
} }

4
vendor/github.com/docker/libnetwork/drivers/windows/overlay/joinleave_windows.go сгенерированный поставляемый
Просмотреть файл

@ -93,6 +93,10 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri
d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true) d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true)
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
// Leave method is invoked when a Sandbox detaches from an endpoint. // Leave method is invoked when a Sandbox detaches from an endpoint.
func (d *driver) Leave(nid, eid string) error { func (d *driver) Leave(nid, eid string) error {
if err := validateID(nid, eid); err != nil { if err := validateID(nid, eid); err != nil {

2
vendor/github.com/docker/libnetwork/drivers/windows/overlay/ov_network_windows.go сгенерированный поставляемый
Просмотреть файл

@ -169,7 +169,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
n.interfaceName = interfaceName n.interfaceName = interfaceName
if nInfo != nil { if nInfo != nil {
if err := nInfo.TableEventRegister(ovPeerTable); err != nil { if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
return err return err
} }
} }

4
vendor/github.com/docker/libnetwork/drivers/windows/windows.go сгенерированный поставляемый
Просмотреть файл

@ -183,6 +183,10 @@ func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []d
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
} }
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
return "", nil
}
// Create a new network // Create a new network
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
if _, err := d.getNetwork(id); err == nil { if _, err := d.getNetwork(id); err == nil {

71
vendor/github.com/docker/libnetwork/iptables/iptables.go сгенерированный поставляемый
Просмотреть файл

@ -50,8 +50,7 @@ var (
bestEffortLock sync.Mutex bestEffortLock sync.Mutex
// ErrIptablesNotFound is returned when the rule is not found. // ErrIptablesNotFound is returned when the rule is not found.
ErrIptablesNotFound = errors.New("Iptables not found") ErrIptablesNotFound = errors.New("Iptables not found")
probeOnce sync.Once initOnce sync.Once
firewalldOnce sync.Once
) )
// ChainInfo defines the iptables chain. // ChainInfo defines the iptables chain.
@ -86,22 +85,32 @@ func initFirewalld() {
} }
} }
func detectIptables() {
path, err := exec.LookPath("iptables")
if err != nil {
return
}
iptablesPath = path
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil
mj, mn, mc, err := GetVersion()
if err != nil {
logrus.Warnf("Failed to read iptables version: %v", err)
return
}
supportsCOpt = supportsCOption(mj, mn, mc)
}
func initIptables() {
probe()
initFirewalld()
detectIptables()
}
func initCheck() error { func initCheck() error {
initOnce.Do(initIptables)
if iptablesPath == "" { if iptablesPath == "" {
probeOnce.Do(probe) return ErrIptablesNotFound
firewalldOnce.Do(initFirewalld)
path, err := exec.LookPath("iptables")
if err != nil {
return ErrIptablesNotFound
}
iptablesPath = path
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil
mj, mn, mc, err := GetVersion()
if err != nil {
logrus.Warnf("Failed to read iptables version: %v", err)
return nil
}
supportsCOpt = supportsCOption(mj, mn, mc)
} }
return nil return nil
} }
@ -189,6 +198,26 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err
} }
} }
establish := []string{
"-o", bridgeName,
"-m", "conntrack",
"--ctstate", "RELATED,ESTABLISHED",
"-j", "ACCEPT"}
if !Exists(Filter, "FORWARD", establish...) && enable {
insert := append([]string{string(Insert), "FORWARD"}, establish...)
if output, err := Raw(insert...); err != nil {
return err
} else if len(output) != 0 {
return fmt.Errorf("Could not create establish rule to %s: %s", c.Table, output)
}
} else if Exists(Filter, "FORWARD", establish...) && !enable {
del := append([]string{string(Delete), "FORWARD"}, establish...)
if output, err := Raw(del...); err != nil {
return err
} else if len(output) != 0 {
return fmt.Errorf("Could not delete establish rule from %s: %s", c.Table, output)
}
}
} }
return nil return nil
} }
@ -353,7 +382,11 @@ func exists(native bool, table Table, chain string, rule ...string) bool {
table = Filter table = Filter
} }
initCheck() if err := initCheck(); err != nil {
// The exists() signature does not allow us to return an error, but at least
// we can skip the (likely invalid) exec invocation.
return false
}
if supportsCOpt { if supportsCOpt {
// if exit status is 0 then return true, the rule exists // if exit status is 0 then return true, the rule exists
@ -436,9 +469,9 @@ func ExistChain(chain string, table Table) bool {
return false return false
} }
// GetVersion reads the iptables version numbers // GetVersion reads the iptables version numbers during initialization
func GetVersion() (major, minor, micro int, err error) { func GetVersion() (major, minor, micro int, err error) {
out, err := Raw("--version") out, err := exec.Command(iptablesPath, "--version").CombinedOutput()
if err == nil { if err == nil {
major, minor, micro = parseVersionNumbers(string(out)) major, minor, micro = parseVersionNumbers(string(out))
} }

23
vendor/github.com/docker/libnetwork/network.go сгенерированный поставляемый
Просмотреть файл

@ -74,6 +74,9 @@ type NetworkInfo interface {
// gossip cluster. For non-dynamic overlay networks and bridge networks it returns an // gossip cluster. For non-dynamic overlay networks and bridge networks it returns an
// empty slice // empty slice
Peers() []networkdb.PeerInfo Peers() []networkdb.PeerInfo
//Services returns a map of services keyed by the service name with the details
//of all the tasks that belong to the service. Applicable only in swarm mode.
Services() map[string]ServiceInfo
} }
// EndpointWalker is a client provided function which will be used to walk the Endpoints. // EndpointWalker is a client provided function which will be used to walk the Endpoints.
@ -108,6 +111,11 @@ type servicePorts struct {
target []serviceTarget target []serviceTarget
} }
type networkDBTable struct {
name string
objType driverapi.ObjectType
}
// IpamConf contains all the ipam related configurations for a network // IpamConf contains all the ipam related configurations for a network
type IpamConf struct { type IpamConf struct {
// The master address pool for containers and network interfaces // The master address pool for containers and network interfaces
@ -208,7 +216,7 @@ type network struct {
attachable bool attachable bool
inDelete bool inDelete bool
ingress bool ingress bool
driverTables []string driverTables []networkDBTable
dynamic bool dynamic bool
sync.Mutex sync.Mutex
} }
@ -1607,11 +1615,18 @@ func (n *network) Labels() map[string]string {
return lbls return lbls
} }
func (n *network) TableEventRegister(tableName string) error { func (n *network) TableEventRegister(tableName string, objType driverapi.ObjectType) error {
if !driverapi.IsValidType(objType) {
return fmt.Errorf("invalid object type %v in registering table, %s", objType, tableName)
}
t := networkDBTable{
name: tableName,
objType: objType,
}
n.Lock() n.Lock()
defer n.Unlock() defer n.Unlock()
n.driverTables = append(n.driverTables, t)
n.driverTables = append(n.driverTables, tableName)
return nil return nil
} }

16
vendor/github.com/docker/libnetwork/networkdb/networkdb.go сгенерированный поставляемый
Просмотреть файл

@ -307,6 +307,22 @@ func (nDB *NetworkDB) UpdateEntry(tname, nid, key string, value []byte) error {
return nil return nil
} }
// GetTableByNetwork walks the networkdb by the give table and network id and
// returns a map of keys and values
func (nDB *NetworkDB) GetTableByNetwork(tname, nid string) map[string]interface{} {
entries := make(map[string]interface{})
nDB.indexes[byTable].WalkPrefix(fmt.Sprintf("/%s/%s", tname, nid), func(k string, v interface{}) bool {
entry := v.(*entry)
if entry.deleting {
return false
}
key := k[strings.LastIndex(k, "/")+1:]
entries[key] = entry.value
return false
})
return entries
}
// DeleteEntry deletes a table entry in NetworkDB for given (network, // DeleteEntry deletes a table entry in NetworkDB for given (network,
// table, key) tuple and if the NetworkDB is part of the cluster // table, key) tuple and if the NetworkDB is part of the cluster
// propagates this event to the cluster. // propagates this event to the cluster.

20
vendor/github.com/docker/libnetwork/service_common.go сгенерированный поставляемый
Просмотреть файл

@ -18,6 +18,26 @@ func newService(name string, id string, ingressPorts []*PortConfig, aliases []st
} }
} }
func (c *controller) getLBIndex(sid, nid string, ingressPorts []*PortConfig) int {
skey := serviceKey{
id: sid,
ports: portConfigs(ingressPorts).String(),
}
c.Lock()
s, ok := c.serviceBindings[skey]
c.Unlock()
if !ok {
return 0
}
s.Lock()
lb := s.loadBalancers[nid]
s.Unlock()
return int(lb.fwMark)
}
func (c *controller) cleanupServiceBindings(cleanupNID string) { func (c *controller) cleanupServiceBindings(cleanupNID string) {
var cleanupFuncs []func() var cleanupFuncs []func()