mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #28876 from vdemeester/28835-better-handling-of-external-networks
stack deploy: handle external network when deploying
This commit is contained in:
commit
b8dac5dc99
3 changed files with 57 additions and 13 deletions
|
@ -37,7 +37,7 @@ func getServices(
|
||||||
types.ServiceListOptions{Filters: getStackFilter(namespace)})
|
types.ServiceListOptions{Filters: getStackFilter(namespace)})
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNetworks(
|
func getStackNetworks(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
apiclient client.APIClient,
|
apiclient client.APIClient,
|
||||||
namespace string,
|
namespace string,
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/docker/docker/cli"
|
"github.com/docker/docker/cli"
|
||||||
"github.com/docker/docker/cli/command"
|
"github.com/docker/docker/cli/command"
|
||||||
servicecmd "github.com/docker/docker/cli/command/service"
|
servicecmd "github.com/docker/docker/cli/command/service"
|
||||||
|
dockerclient "github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/opts"
|
"github.com/docker/docker/opts"
|
||||||
runconfigopts "github.com/docker/docker/runconfig/opts"
|
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
|
@ -123,7 +124,10 @@ func deployCompose(ctx context.Context, dockerCli *command.DockerCli, opts deplo
|
||||||
|
|
||||||
namespace := namespace{name: opts.namespace}
|
namespace := namespace{name: opts.namespace}
|
||||||
|
|
||||||
networks := convertNetworks(namespace, config.Networks)
|
networks, externalNetworks := convertNetworks(namespace, config.Networks)
|
||||||
|
if err := validateExternalNetworks(ctx, dockerCli, externalNetworks); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
|
if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -179,7 +183,7 @@ func getConfigFile(filename string) (*composetypes.ConfigFile, error) {
|
||||||
func convertNetworks(
|
func convertNetworks(
|
||||||
namespace namespace,
|
namespace namespace,
|
||||||
networks map[string]composetypes.NetworkConfig,
|
networks map[string]composetypes.NetworkConfig,
|
||||||
) map[string]types.NetworkCreate {
|
) (map[string]types.NetworkCreate, []string) {
|
||||||
if networks == nil {
|
if networks == nil {
|
||||||
networks = make(map[string]composetypes.NetworkConfig)
|
networks = make(map[string]composetypes.NetworkConfig)
|
||||||
}
|
}
|
||||||
|
@ -187,10 +191,12 @@ func convertNetworks(
|
||||||
// TODO: only add default network if it's used
|
// TODO: only add default network if it's used
|
||||||
networks["default"] = composetypes.NetworkConfig{}
|
networks["default"] = composetypes.NetworkConfig{}
|
||||||
|
|
||||||
|
externalNetworks := []string{}
|
||||||
result := make(map[string]types.NetworkCreate)
|
result := make(map[string]types.NetworkCreate)
|
||||||
|
|
||||||
for internalName, network := range networks {
|
for internalName, network := range networks {
|
||||||
if network.External.Name != "" {
|
if network.External.External {
|
||||||
|
externalNetworks = append(externalNetworks, network.External.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +222,29 @@ func convertNetworks(
|
||||||
result[internalName] = createOpts
|
result[internalName] = createOpts
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result, externalNetworks
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateExternalNetworks(
|
||||||
|
ctx context.Context,
|
||||||
|
dockerCli *command.DockerCli,
|
||||||
|
externalNetworks []string) error {
|
||||||
|
client := dockerCli.Client()
|
||||||
|
|
||||||
|
for _, networkName := range externalNetworks {
|
||||||
|
network, err := client.NetworkInspect(ctx, networkName)
|
||||||
|
if err != nil {
|
||||||
|
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 err
|
||||||
|
}
|
||||||
|
if network.Scope != "swarm" {
|
||||||
|
return fmt.Errorf("network %q is declared as external, but it is not in the right scope: %q instead of %q", networkName, network.Scope, "swarm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNetworks(
|
func createNetworks(
|
||||||
|
@ -227,7 +255,7 @@ func createNetworks(
|
||||||
) error {
|
) error {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
|
|
||||||
existingNetworks, err := getNetworks(ctx, client, namespace.name)
|
existingNetworks, err := getStackNetworks(ctx, client, namespace.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -258,30 +286,39 @@ func createNetworks(
|
||||||
|
|
||||||
func convertServiceNetworks(
|
func convertServiceNetworks(
|
||||||
networks map[string]*composetypes.ServiceNetworkConfig,
|
networks map[string]*composetypes.ServiceNetworkConfig,
|
||||||
|
networkConfigs map[string]composetypes.NetworkConfig,
|
||||||
namespace namespace,
|
namespace namespace,
|
||||||
name string,
|
name string,
|
||||||
) []swarm.NetworkAttachmentConfig {
|
) ([]swarm.NetworkAttachmentConfig, error) {
|
||||||
if len(networks) == 0 {
|
if len(networks) == 0 {
|
||||||
return []swarm.NetworkAttachmentConfig{
|
return []swarm.NetworkAttachmentConfig{
|
||||||
{
|
{
|
||||||
Target: namespace.scope("default"),
|
Target: namespace.scope("default"),
|
||||||
Aliases: []string{name},
|
Aliases: []string{name},
|
||||||
},
|
},
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nets := []swarm.NetworkAttachmentConfig{}
|
nets := []swarm.NetworkAttachmentConfig{}
|
||||||
for networkName, network := range networks {
|
for networkName, network := range networks {
|
||||||
|
networkConfig, ok := networkConfigs[networkName]
|
||||||
|
if !ok {
|
||||||
|
return []swarm.NetworkAttachmentConfig{}, fmt.Errorf("invalid network: %s", networkName)
|
||||||
|
}
|
||||||
var aliases []string
|
var aliases []string
|
||||||
if network != nil {
|
if network != nil {
|
||||||
aliases = network.Aliases
|
aliases = network.Aliases
|
||||||
}
|
}
|
||||||
|
target := namespace.scope(networkName)
|
||||||
|
if networkConfig.External.External {
|
||||||
|
target = networkName
|
||||||
|
}
|
||||||
nets = append(nets, swarm.NetworkAttachmentConfig{
|
nets = append(nets, swarm.NetworkAttachmentConfig{
|
||||||
Target: namespace.scope(networkName),
|
Target: target,
|
||||||
Aliases: append(aliases, name),
|
Aliases: append(aliases, name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nets
|
return nets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertVolumes(
|
func convertVolumes(
|
||||||
|
@ -472,9 +509,10 @@ func convertServices(
|
||||||
|
|
||||||
services := config.Services
|
services := config.Services
|
||||||
volumes := config.Volumes
|
volumes := config.Volumes
|
||||||
|
networks := config.Networks
|
||||||
|
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
serviceSpec, err := convertService(namespace, service, volumes)
|
serviceSpec, err := convertService(namespace, service, networks, volumes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -487,6 +525,7 @@ func convertServices(
|
||||||
func convertService(
|
func convertService(
|
||||||
namespace namespace,
|
namespace namespace,
|
||||||
service composetypes.ServiceConfig,
|
service composetypes.ServiceConfig,
|
||||||
|
networkConfigs map[string]composetypes.NetworkConfig,
|
||||||
volumes map[string]composetypes.VolumeConfig,
|
volumes map[string]composetypes.VolumeConfig,
|
||||||
) (swarm.ServiceSpec, error) {
|
) (swarm.ServiceSpec, error) {
|
||||||
name := namespace.scope(service.Name)
|
name := namespace.scope(service.Name)
|
||||||
|
@ -523,6 +562,11 @@ func convertService(
|
||||||
return swarm.ServiceSpec{}, err
|
return swarm.ServiceSpec{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
networks, err := convertServiceNetworks(service.Networks, networkConfigs, namespace, service.Name)
|
||||||
|
if err != nil {
|
||||||
|
return swarm.ServiceSpec{}, err
|
||||||
|
}
|
||||||
|
|
||||||
serviceSpec := swarm.ServiceSpec{
|
serviceSpec := swarm.ServiceSpec{
|
||||||
Annotations: swarm.Annotations{
|
Annotations: swarm.Annotations{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -553,7 +597,7 @@ func convertService(
|
||||||
},
|
},
|
||||||
EndpointSpec: endpoint,
|
EndpointSpec: endpoint,
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Networks: convertServiceNetworks(service.Networks, namespace, service.Name),
|
Networks: networks,
|
||||||
UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig),
|
UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ func runRemove(dockerCli *command.DockerCli, opts removeOptions) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
networks, err := getNetworks(ctx, client, namespace)
|
networks, err := getStackNetworks(ctx, client, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue