mirror of https://github.com/docker/cli.git
Merge pull request #132 from mavenugo/stack-host
Host and Bridge network support in docker stack deploy
This commit is contained in:
commit
efaadcf465
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/docker/cli/cli/compose/loader"
|
||||
composetypes "github.com/docker/cli/cli/compose/types"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
apiclient "github.com/docker/docker/client"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
|
@ -64,7 +65,7 @@ func deployCompose(ctx context.Context, dockerCli command.Cli, opts deployOption
|
|||
|
||||
serviceNetworks := getServicesDeclaredNetworks(config.Services)
|
||||
networks, externalNetworks := convert.Networks(namespace, config.Networks, serviceNetworks)
|
||||
if err := validateExternalNetworks(ctx, dockerCli, externalNetworks); err != nil {
|
||||
if err := validateExternalNetworks(ctx, dockerCli.Client(), externalNetworks); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
|
||||
|
@ -75,7 +76,7 @@ func deployCompose(ctx context.Context, dockerCli command.Cli, opts deployOption
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createSecrets(ctx, dockerCli, namespace, secrets); err != nil {
|
||||
if err := createSecrets(ctx, dockerCli, secrets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,7 @@ func deployCompose(ctx context.Context, dockerCli command.Cli, opts deployOption
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := createConfigs(ctx, dockerCli, namespace, configs); err != nil {
|
||||
if err := createConfigs(ctx, dockerCli, configs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -169,30 +170,26 @@ func getConfigFile(filename string) (*composetypes.ConfigFile, error) {
|
|||
|
||||
func validateExternalNetworks(
|
||||
ctx context.Context,
|
||||
dockerCli command.Cli,
|
||||
externalNetworks []string) error {
|
||||
client := dockerCli.Client()
|
||||
|
||||
client dockerclient.NetworkAPIClient,
|
||||
externalNetworks []string,
|
||||
) error {
|
||||
for _, networkName := range externalNetworks {
|
||||
network, err := client.NetworkInspect(ctx, networkName, false)
|
||||
if err != nil {
|
||||
if dockerclient.IsErrNetworkNotFound(err) {
|
||||
return errors.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)
|
||||
}
|
||||
switch {
|
||||
case dockerclient.IsErrNotFound(err):
|
||||
return errors.Errorf("network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed", networkName)
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
if network.Scope != "swarm" {
|
||||
return errors.Errorf("network %q is declared as external, but it is not in the right scope: %q instead of %q", networkName, network.Scope, "swarm")
|
||||
case container.NetworkMode(networkName).IsUserDefined() && network.Scope != "swarm":
|
||||
return errors.Errorf("network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\"", networkName, network.Scope)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSecrets(
|
||||
ctx context.Context,
|
||||
dockerCli command.Cli,
|
||||
namespace convert.Namespace,
|
||||
secrets []swarm.SecretSpec,
|
||||
) error {
|
||||
client := dockerCli.Client()
|
||||
|
@ -219,7 +216,6 @@ func createSecrets(
|
|||
func createConfigs(
|
||||
ctx context.Context,
|
||||
dockerCli command.Cli,
|
||||
namespace convert.Namespace,
|
||||
configs []swarm.ConfigSpec,
|
||||
) error {
|
||||
client := dockerCli.Client()
|
||||
|
|
|
@ -5,9 +5,14 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/internal/test/network"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/pkg/testutil/tempfile"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestGetConfigDetails(t *testing.T) {
|
||||
|
@ -26,3 +31,55 @@ services:
|
|||
assert.Len(t, details.ConfigFiles, 1)
|
||||
assert.Len(t, details.Environment, len(os.Environ()))
|
||||
}
|
||||
|
||||
type notFound struct {
|
||||
error
|
||||
}
|
||||
|
||||
func (n notFound) NotFound() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func TestValidateExternalNetworks(t *testing.T) {
|
||||
var testcases = []struct {
|
||||
inspectResponse types.NetworkResource
|
||||
inspectError error
|
||||
expectedMsg string
|
||||
network string
|
||||
}{
|
||||
{
|
||||
inspectError: notFound{},
|
||||
expectedMsg: "could not be found. You need to create a swarm-scoped network",
|
||||
},
|
||||
{
|
||||
inspectError: errors.New("Unexpected"),
|
||||
expectedMsg: "Unexpected",
|
||||
},
|
||||
{
|
||||
network: "host",
|
||||
},
|
||||
{
|
||||
network: "user",
|
||||
expectedMsg: "is not in the right scope",
|
||||
},
|
||||
{
|
||||
network: "user",
|
||||
inspectResponse: types.NetworkResource{Scope: "swarm"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
fakeClient := &network.FakeClient{
|
||||
NetworkInspectFunc: func(_ context.Context, _ string, _ bool) (types.NetworkResource, error) {
|
||||
return testcase.inspectResponse, testcase.inspectError
|
||||
},
|
||||
}
|
||||
networks := []string{testcase.network}
|
||||
err := validateExternalNetworks(context.Background(), fakeClient, networks)
|
||||
if testcase.expectedMsg == "" {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
testutil.ErrorContains(t, err, testcase.expectedMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,10 +223,16 @@ func convertServiceNetworks(
|
|||
if networkConfig.External.External {
|
||||
target = networkConfig.External.Name
|
||||
}
|
||||
nets = append(nets, swarm.NetworkAttachmentConfig{
|
||||
netAttachConfig := swarm.NetworkAttachmentConfig{
|
||||
Target: target,
|
||||
Aliases: append(aliases, name),
|
||||
})
|
||||
Aliases: aliases,
|
||||
}
|
||||
// Only add default aliases to user defined networks. Other networks do
|
||||
// not support aliases.
|
||||
if container.NetworkMode(target).IsUserDefined() {
|
||||
netAttachConfig.Aliases = append(netAttachConfig.Aliases, name)
|
||||
}
|
||||
nets = append(nets, netAttachConfig)
|
||||
}
|
||||
|
||||
sort.Sort(byNetworkTarget(nets))
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// FakeClient is a fake NetworkAPIClient
|
||||
type FakeClient struct {
|
||||
NetworkInspectFunc func(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, error)
|
||||
}
|
||||
|
||||
// NetworkConnect fakes connecting to a network
|
||||
func (c *FakeClient) NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworkCreate fakes creating a network
|
||||
func (c *FakeClient) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
||||
return types.NetworkCreateResponse{}, nil
|
||||
}
|
||||
|
||||
// NetworkDisconnect fakes disconencting from a network
|
||||
func (c *FakeClient) NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworkInspect fakes inspecting a network
|
||||
func (c *FakeClient) NetworkInspect(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, error) {
|
||||
if c.NetworkInspectFunc != nil {
|
||||
return c.NetworkInspectFunc(ctx, networkID, verbose)
|
||||
}
|
||||
return types.NetworkResource{}, nil
|
||||
}
|
||||
|
||||
// NetworkInspectWithRaw fakes inspecting a network with a raw response
|
||||
func (c *FakeClient) NetworkInspectWithRaw(ctx context.Context, networkID string, verbose bool) (types.NetworkResource, []byte, error) {
|
||||
return types.NetworkResource{}, nil, nil
|
||||
}
|
||||
|
||||
// NetworkList fakes listing networks
|
||||
func (c *FakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NetworkRemove fakes removing networks
|
||||
func (c *FakeClient) NetworkRemove(ctx context.Context, networkID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworksPrune fakes pruning networks
|
||||
func (c *FakeClient) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error) {
|
||||
return types.NetworksPruneReport{}, nil
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
set -e
|
||||
|
||||
filewatcher \
|
||||
-L 5 \
|
||||
-L 6 \
|
||||
-x '**/*.swp' \
|
||||
-x .git \
|
||||
-x build \
|
||||
|
|
Loading…
Reference in New Issue