Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 13 additions & 17 deletions cli/command/stack/deploy_composefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -75,15 +76,15 @@ 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
}

configs, err := convert.Configs(namespace, config.Configs)
if err != nil {
return err
}
if err := createConfigs(ctx, dockerCli, namespace, configs); err != nil {
if err := createConfigs(ctx, dockerCli, configs); err != nil {
return err
}

Expand Down Expand Up @@ -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()
Expand All @@ -219,7 +216,6 @@ func createSecrets(
func createConfigs(
ctx context.Context,
dockerCli command.Cli,
namespace convert.Namespace,
configs []swarm.ConfigSpec,
) error {
client := dockerCli.Client()
Expand Down
57 changes: 57 additions & 0 deletions cli/command/stack/deploy_composefile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
}
}
}
12 changes: 9 additions & 3 deletions cli/compose/convert/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,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))
Expand Down
56 changes: 56 additions & 0 deletions cli/internal/test/network/client.go
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 1 addition & 1 deletion scripts/test/watch
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

filewatcher \
-L 5 \
-L 6 \
-x '**/*.swp' \
-x .git \
-x build \
Expand Down