@@ -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"
@@ -1007,75 +1008,81 @@ func getAliases(s types.ServiceConfig, c *types.ServiceNetworkConfig) []string {
10071008}
10081009
10091010func (s * composeService ) ensureNetwork (ctx context.Context , n types.NetworkConfig ) error {
1010- _ , err := s .apiClient ().NetworkInspect (ctx , n .Name , moby.NetworkInspectOptions {})
1011+ // NetworkInspect will match on ID prefix, so NetworkList with a name
1012+ // filter is used to look for an exact match to prevent e.g. a network
1013+ // named `db` from getting erroneously matched to a network with an ID
1014+ // like `db9086999caf`
1015+ networks , err := s .apiClient ().NetworkList (ctx , moby.NetworkListOptions {
1016+ Filters : filters .NewArgs (filters .Arg ("name" , n .Name )),
1017+ })
10111018 if err != nil {
1012- if errdefs . IsNotFound ( err ) {
1013- if n . External . External {
1014- if n . Driver == "overlay" {
1015- // Swarm nodes do not register overlay networks that were
1016- // created on a different node unless they're in use.
1017- // Here we assume `driver` is relevant for a network we don't manage
1018- // which is a non-sense, but this is our legacy ¯\(ツ)/¯
1019- // networkAttach will later fail anyway if network actually doesn 't exists
1020- return nil
1021- }
1022- return fmt . Errorf ( "network %s declared as external, but could not be found" , n . Name )
1019+ return err
1020+ }
1021+ if len ( networks ) == 0 {
1022+ if n . External . External {
1023+ if n . Driver == "overlay" {
1024+ // Swarm nodes do not register overlay networks that were
1025+ // created on a different node unless they're in use.
1026+ // Here we assume `driver` is relevant for a network we don 't manage
1027+ // which is a non-sense, but this is our legacy ¯\(ツ)/¯
1028+ // networkAttach will later fail anyway if network actually doesn't exists
1029+ return nil
10231030 }
1024- var ipam * network.IPAM
1025- if n .Ipam .Config != nil {
1026- var config []network.IPAMConfig
1027- for _ , pool := range n .Ipam .Config {
1028- config = append (config , network.IPAMConfig {
1029- Subnet : pool .Subnet ,
1030- IPRange : pool .IPRange ,
1031- Gateway : pool .Gateway ,
1032- AuxAddress : pool .AuxiliaryAddresses ,
1033- })
1034- }
1035- ipam = & network.IPAM {
1036- Driver : n .Ipam .Driver ,
1037- Config : config ,
1038- }
1031+ return fmt .Errorf ("network %s declared as external, but could not be found" , n .Name )
1032+ }
1033+ var ipam * network.IPAM
1034+ if n .Ipam .Config != nil {
1035+ var config []network.IPAMConfig
1036+ for _ , pool := range n .Ipam .Config {
1037+ config = append (config , network.IPAMConfig {
1038+ Subnet : pool .Subnet ,
1039+ IPRange : pool .IPRange ,
1040+ Gateway : pool .Gateway ,
1041+ AuxAddress : pool .AuxiliaryAddresses ,
1042+ })
10391043 }
1040- createOpts := moby.NetworkCreate {
1041- // TODO NameSpace Labels
1042- Labels : n .Labels ,
1043- Driver : n .Driver ,
1044- Options : n .DriverOpts ,
1045- Internal : n .Internal ,
1046- Attachable : n .Attachable ,
1047- IPAM : ipam ,
1048- EnableIPv6 : n .EnableIPv6 ,
1044+ ipam = & network.IPAM {
1045+ Driver : n .Ipam .Driver ,
1046+ Config : config ,
10491047 }
1048+ }
1049+ createOpts := moby.NetworkCreate {
1050+ // TODO NameSpace Labels
1051+ Labels : n .Labels ,
1052+ Driver : n .Driver ,
1053+ Options : n .DriverOpts ,
1054+ Internal : n .Internal ,
1055+ Attachable : n .Attachable ,
1056+ IPAM : ipam ,
1057+ EnableIPv6 : n .EnableIPv6 ,
1058+ }
10501059
1051- if n .Ipam .Driver != "" || len (n .Ipam .Config ) > 0 {
1052- createOpts .IPAM = & network.IPAM {}
1053- }
1060+ if n .Ipam .Driver != "" || len (n .Ipam .Config ) > 0 {
1061+ createOpts .IPAM = & network.IPAM {}
1062+ }
10541063
1055- if n .Ipam .Driver != "" {
1056- createOpts .IPAM .Driver = n .Ipam .Driver
1057- }
1064+ if n .Ipam .Driver != "" {
1065+ createOpts .IPAM .Driver = n .Ipam .Driver
1066+ }
10581067
1059- for _ , ipamConfig := range n .Ipam .Config {
1060- config := network.IPAMConfig {
1061- Subnet : ipamConfig .Subnet ,
1062- IPRange : ipamConfig .IPRange ,
1063- Gateway : ipamConfig .Gateway ,
1064- AuxAddress : ipamConfig .AuxiliaryAddresses ,
1065- }
1066- createOpts .IPAM .Config = append (createOpts .IPAM .Config , config )
1068+ for _ , ipamConfig := range n .Ipam .Config {
1069+ config := network.IPAMConfig {
1070+ Subnet : ipamConfig .Subnet ,
1071+ IPRange : ipamConfig .IPRange ,
1072+ Gateway : ipamConfig .Gateway ,
1073+ AuxAddress : ipamConfig .AuxiliaryAddresses ,
10671074 }
1068- networkEventName := fmt .Sprintf ("Network %s" , n .Name )
1069- w := progress .ContextWriter (ctx )
1070- w .Event (progress .CreatingEvent (networkEventName ))
1071- if _ , err := s .apiClient ().NetworkCreate (ctx , n .Name , createOpts ); err != nil {
1072- w .Event (progress .ErrorEvent (networkEventName ))
1073- return errors .Wrapf (err , "failed to create network %s" , n .Name )
1074- }
1075- w .Event (progress .CreatedEvent (networkEventName ))
1076- return nil
1075+ createOpts .IPAM .Config = append (createOpts .IPAM .Config , config )
10771076 }
1078- return err
1077+ networkEventName := fmt .Sprintf ("Network %s" , n .Name )
1078+ w := progress .ContextWriter (ctx )
1079+ w .Event (progress .CreatingEvent (networkEventName ))
1080+ if _ , err := s .apiClient ().NetworkCreate (ctx , n .Name , createOpts ); err != nil {
1081+ w .Event (progress .ErrorEvent (networkEventName ))
1082+ return errors .Wrapf (err , "failed to create network %s" , n .Name )
1083+ }
1084+ w .Event (progress .CreatedEvent (networkEventName ))
1085+ return nil
10791086 }
10801087 return nil
10811088}
0 commit comments