@@ -31,6 +31,7 @@ import (
3131 moby "github.com/docker/docker/api/types"
3232 "github.com/docker/docker/api/types/blkiodev"
3333 "github.com/docker/docker/api/types/container"
34+ "github.com/docker/docker/api/types/filters"
3435 "github.com/docker/docker/api/types/mount"
3536 "github.com/docker/docker/api/types/network"
3637 "github.com/docker/docker/api/types/strslice"
@@ -1001,75 +1002,81 @@ func getAliases(s types.ServiceConfig, c *types.ServiceNetworkConfig) []string {
10011002}
10021003
10031004func (s * composeService ) ensureNetwork (ctx context.Context , n types.NetworkConfig ) error {
1004- _ , err := s .apiClient ().NetworkInspect (ctx , n .Name , moby.NetworkInspectOptions {})
1005+ // NetworkInspect will match on ID prefix, so NetworkList with a name
1006+ // filter is used to look for an exact match to prevent e.g. a network
1007+ // named `db` from getting erroneously matched to a network with an ID
1008+ // like `db9086999caf`
1009+ networks , err := s .apiClient ().NetworkList (ctx , moby.NetworkListOptions {
1010+ Filters : filters .NewArgs (filters .Arg ("name" , n .Name )),
1011+ })
10051012 if err != nil {
1006- if errdefs . IsNotFound ( err ) {
1007- if n . External . External {
1008- if n . Driver == "overlay" {
1009- // Swarm nodes do not register overlay networks that were
1010- // created on a different node unless they're in use.
1011- // Here we assume `driver` is relevant for a network we don't manage
1012- // which is a non-sense, but this is our legacy ¯\(ツ)/¯
1013- // networkAttach will later fail anyway if network actually doesn 't exists
1014- return nil
1015- }
1016- return fmt . Errorf ( "network %s declared as external, but could not be found" , n . Name )
1013+ return err
1014+ }
1015+ if len ( networks ) == 0 {
1016+ if n . External . External {
1017+ if n . Driver == "overlay" {
1018+ // Swarm nodes do not register overlay networks that were
1019+ // created on a different node unless they're in use.
1020+ // Here we assume `driver` is relevant for a network we don 't manage
1021+ // which is a non-sense, but this is our legacy ¯\(ツ)/¯
1022+ // networkAttach will later fail anyway if network actually doesn't exists
1023+ return nil
10171024 }
1018- var ipam * network.IPAM
1019- if n .Ipam .Config != nil {
1020- var config []network.IPAMConfig
1021- for _ , pool := range n .Ipam .Config {
1022- config = append (config , network.IPAMConfig {
1023- Subnet : pool .Subnet ,
1024- IPRange : pool .IPRange ,
1025- Gateway : pool .Gateway ,
1026- AuxAddress : pool .AuxiliaryAddresses ,
1027- })
1028- }
1029- ipam = & network.IPAM {
1030- Driver : n .Ipam .Driver ,
1031- Config : config ,
1032- }
1025+ return fmt .Errorf ("network %s declared as external, but could not be found" , n .Name )
1026+ }
1027+ var ipam * network.IPAM
1028+ if n .Ipam .Config != nil {
1029+ var config []network.IPAMConfig
1030+ for _ , pool := range n .Ipam .Config {
1031+ config = append (config , network.IPAMConfig {
1032+ Subnet : pool .Subnet ,
1033+ IPRange : pool .IPRange ,
1034+ Gateway : pool .Gateway ,
1035+ AuxAddress : pool .AuxiliaryAddresses ,
1036+ })
10331037 }
1034- createOpts := moby.NetworkCreate {
1035- // TODO NameSpace Labels
1036- Labels : n .Labels ,
1037- Driver : n .Driver ,
1038- Options : n .DriverOpts ,
1039- Internal : n .Internal ,
1040- Attachable : n .Attachable ,
1041- IPAM : ipam ,
1042- EnableIPv6 : n .EnableIPv6 ,
1038+ ipam = & network.IPAM {
1039+ Driver : n .Ipam .Driver ,
1040+ Config : config ,
10431041 }
1042+ }
1043+ createOpts := moby.NetworkCreate {
1044+ // TODO NameSpace Labels
1045+ Labels : n .Labels ,
1046+ Driver : n .Driver ,
1047+ Options : n .DriverOpts ,
1048+ Internal : n .Internal ,
1049+ Attachable : n .Attachable ,
1050+ IPAM : ipam ,
1051+ EnableIPv6 : n .EnableIPv6 ,
1052+ }
10441053
1045- if n .Ipam .Driver != "" || len (n .Ipam .Config ) > 0 {
1046- createOpts .IPAM = & network.IPAM {}
1047- }
1054+ if n .Ipam .Driver != "" || len (n .Ipam .Config ) > 0 {
1055+ createOpts .IPAM = & network.IPAM {}
1056+ }
10481057
1049- if n .Ipam .Driver != "" {
1050- createOpts .IPAM .Driver = n .Ipam .Driver
1051- }
1058+ if n .Ipam .Driver != "" {
1059+ createOpts .IPAM .Driver = n .Ipam .Driver
1060+ }
10521061
1053- for _ , ipamConfig := range n .Ipam .Config {
1054- config := network.IPAMConfig {
1055- Subnet : ipamConfig .Subnet ,
1056- IPRange : ipamConfig .IPRange ,
1057- Gateway : ipamConfig .Gateway ,
1058- AuxAddress : ipamConfig .AuxiliaryAddresses ,
1059- }
1060- createOpts .IPAM .Config = append (createOpts .IPAM .Config , config )
1062+ for _ , ipamConfig := range n .Ipam .Config {
1063+ config := network.IPAMConfig {
1064+ Subnet : ipamConfig .Subnet ,
1065+ IPRange : ipamConfig .IPRange ,
1066+ Gateway : ipamConfig .Gateway ,
1067+ AuxAddress : ipamConfig .AuxiliaryAddresses ,
10611068 }
1062- networkEventName := fmt .Sprintf ("Network %s" , n .Name )
1063- w := progress .ContextWriter (ctx )
1064- w .Event (progress .CreatingEvent (networkEventName ))
1065- if _ , err := s .apiClient ().NetworkCreate (ctx , n .Name , createOpts ); err != nil {
1066- w .Event (progress .ErrorEvent (networkEventName ))
1067- return errors .Wrapf (err , "failed to create network %s" , n .Name )
1068- }
1069- w .Event (progress .CreatedEvent (networkEventName ))
1070- return nil
1069+ createOpts .IPAM .Config = append (createOpts .IPAM .Config , config )
10711070 }
1072- return err
1071+ networkEventName := fmt .Sprintf ("Network %s" , n .Name )
1072+ w := progress .ContextWriter (ctx )
1073+ w .Event (progress .CreatingEvent (networkEventName ))
1074+ if _ , err := s .apiClient ().NetworkCreate (ctx , n .Name , createOpts ); err != nil {
1075+ w .Event (progress .ErrorEvent (networkEventName ))
1076+ return errors .Wrapf (err , "failed to create network %s" , n .Name )
1077+ }
1078+ w .Event (progress .CreatedEvent (networkEventName ))
1079+ return nil
10731080 }
10741081 return nil
10751082}
0 commit comments