2018-07-11 10:31:27 -04:00
package network // import "github.com/docker/docker/integration/network"
import (
"bytes"
"context"
2020-11-30 06:34:24 -05:00
"encoding/json"
2018-11-05 08:50:33 -05:00
"net/http"
2018-07-11 10:31:27 -04:00
"os/exec"
"strings"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/integration/internal/container"
2020-03-04 17:44:08 -05:00
"github.com/docker/docker/integration/internal/network"
2019-08-29 16:52:40 -04:00
"github.com/docker/docker/testutil/daemon"
"github.com/docker/docker/testutil/request"
2020-02-07 08:39:24 -05:00
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
2020-03-04 17:44:08 -05:00
"gotest.tools/v3/icmd"
2020-02-07 08:39:24 -05:00
"gotest.tools/v3/skip"
2018-07-11 10:31:27 -04:00
)
func TestRunContainerWithBridgeNone ( t * testing . T ) {
skip . If ( t , testEnv . IsRemoteDaemon , "cannot start daemon on remote test run" )
skip . If ( t , testEnv . DaemonInfo . OSType != "linux" )
2021-08-12 03:12:04 -04:00
skip . If ( t , testEnv . IsUserNamespace )
2020-03-13 09:37:09 -04:00
skip . If ( t , testEnv . IsRootless , "rootless mode has different view of network" )
2018-07-11 10:31:27 -04:00
d := daemon . New ( t )
d . StartWithBusybox ( t , "-b" , "none" )
defer d . Stop ( t )
2018-12-22 09:53:02 -05:00
c := d . NewClientT ( t )
2018-07-11 10:31:27 -04:00
ctx := context . Background ( )
2019-06-06 07:15:31 -04:00
id1 := container . Run ( ctx , t , c )
2018-12-22 09:53:02 -05:00
defer c . ContainerRemove ( ctx , id1 , types . ContainerRemoveOptions { Force : true } )
result , err := container . Exec ( ctx , c , id1 , [ ] string { "ip" , "l" } )
2018-07-11 10:31:27 -04:00
assert . NilError ( t , err )
assert . Check ( t , is . Equal ( false , strings . Contains ( result . Combined ( ) , "eth0" ) ) , "There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled" )
2019-06-06 07:15:31 -04:00
id2 := container . Run ( ctx , t , c , container . WithNetworkMode ( "bridge" ) )
2018-12-22 09:53:02 -05:00
defer c . ContainerRemove ( ctx , id2 , types . ContainerRemoveOptions { Force : true } )
2018-07-11 10:31:27 -04:00
2018-12-22 09:53:02 -05:00
result , err = container . Exec ( ctx , c , id2 , [ ] string { "ip" , "l" } )
2018-07-11 10:31:27 -04:00
assert . NilError ( t , err )
assert . Check ( t , is . Equal ( false , strings . Contains ( result . Combined ( ) , "eth0" ) ) , "There shouldn't be eth0 in container in bridge mode when bridge network is disabled" )
nsCommand := "ls -l /proc/self/ns/net | awk -F '->' '{print $2}'"
cmd := exec . Command ( "sh" , "-c" , nsCommand )
stdout := bytes . NewBuffer ( nil )
cmd . Stdout = stdout
err = cmd . Run ( )
assert . NilError ( t , err , "Failed to get current process network namespace: %+v" , err )
2019-06-06 07:15:31 -04:00
id3 := container . Run ( ctx , t , c , container . WithNetworkMode ( "host" ) )
2018-12-22 09:53:02 -05:00
defer c . ContainerRemove ( ctx , id3 , types . ContainerRemoveOptions { Force : true } )
2018-07-11 10:31:27 -04:00
2018-12-22 09:53:02 -05:00
result , err = container . Exec ( ctx , c , id3 , [ ] string { "sh" , "-c" , nsCommand } )
2018-07-11 10:31:27 -04:00
assert . NilError ( t , err )
2018-11-11 10:07:43 -05:00
assert . Check ( t , is . Equal ( stdout . String ( ) , result . Combined ( ) ) , "The network namespace of container should be the same with host when --net=host and bridge network is disabled" )
2018-07-11 10:31:27 -04:00
}
2018-11-05 08:50:33 -05:00
2022-04-05 05:43:06 -04:00
// TestNetworkInvalidJSON tests that POST endpoints that expect a body return
// the correct error when sending invalid JSON requests.
2018-11-05 08:50:33 -05:00
func TestNetworkInvalidJSON ( t * testing . T ) {
defer setupTest ( t ) ( )
2022-04-05 05:43:06 -04:00
// POST endpoints that accept / expect a JSON body;
2018-11-05 08:50:33 -05:00
endpoints := [ ] string {
"/networks/create" ,
"/networks/bridge/connect" ,
"/networks/bridge/disconnect" ,
}
for _ , ep := range endpoints {
2021-07-22 16:41:01 -04:00
ep := ep
2022-04-05 05:43:06 -04:00
t . Run ( ep [ 1 : ] , func ( t * testing . T ) {
2018-11-05 08:50:33 -05:00
t . Parallel ( )
2022-04-05 05:43:06 -04:00
t . Run ( "invalid content type" , func ( t * testing . T ) {
res , body , err := request . Post ( ep , request . RawString ( "{}" ) , request . ContentType ( "text/plain" ) )
assert . NilError ( t , err )
assert . Check ( t , is . Equal ( res . StatusCode , http . StatusBadRequest ) )
buf , err := request . ReadBody ( body )
assert . NilError ( t , err )
assert . Check ( t , is . Contains ( string ( buf ) , "unsupported Content-Type header (text/plain): must be 'application/json'" ) )
} )
t . Run ( "invalid JSON" , func ( t * testing . T ) {
res , body , err := request . Post ( ep , request . RawString ( "{invalid json" ) , request . JSON )
assert . NilError ( t , err )
assert . Check ( t , is . Equal ( res . StatusCode , http . StatusBadRequest ) )
buf , err := request . ReadBody ( body )
assert . NilError ( t , err )
assert . Check ( t , is . Contains ( string ( buf ) , "invalid JSON: invalid character 'i' looking for beginning of object key string" ) )
} )
t . Run ( "extra content after JSON" , func ( t * testing . T ) {
res , body , err := request . Post ( ep , request . RawString ( ` { } trailing content ` ) , request . JSON )
assert . NilError ( t , err )
assert . Check ( t , is . Equal ( res . StatusCode , http . StatusBadRequest ) )
buf , err := request . ReadBody ( body )
assert . NilError ( t , err )
assert . Check ( t , is . Contains ( string ( buf ) , "unexpected content after JSON" ) )
} )
t . Run ( "empty body" , func ( t * testing . T ) {
// empty body should not produce an 500 internal server error, or
// any 5XX error (this is assuming the request does not produce
// an internal server error for another reason, but it shouldn't)
res , _ , err := request . Post ( ep , request . RawString ( ` ` ) , request . JSON )
assert . NilError ( t , err )
assert . Check ( t , res . StatusCode < http . StatusInternalServerError )
} )
2018-11-05 08:50:33 -05:00
} )
}
}
2020-03-04 17:44:08 -05:00
2020-11-30 06:34:24 -05:00
// TestNetworkList verifies that /networks returns a list of networks either
// with, or without a trailing slash (/networks/). Regression test for https://github.com/moby/moby/issues/24595
func TestNetworkList ( t * testing . T ) {
defer setupTest ( t ) ( )
endpoints := [ ] string {
"/networks" ,
"/networks/" ,
}
for _ , ep := range endpoints {
2021-07-22 16:41:01 -04:00
ep := ep
2020-11-30 06:34:24 -05:00
t . Run ( ep , func ( t * testing . T ) {
t . Parallel ( )
res , body , err := request . Get ( ep , request . JSON )
assert . NilError ( t , err )
assert . Equal ( t , res . StatusCode , http . StatusOK )
buf , err := request . ReadBody ( body )
assert . NilError ( t , err )
var nws [ ] types . NetworkResource
err = json . Unmarshal ( buf , & nws )
assert . NilError ( t , err )
assert . Assert ( t , len ( nws ) > 0 )
} )
}
}
2020-03-04 17:44:08 -05:00
func TestHostIPv4BridgeLabel ( t * testing . T ) {
skip . If ( t , testEnv . OSType == "windows" )
skip . If ( t , testEnv . IsRemoteDaemon )
2020-03-13 09:37:09 -04:00
skip . If ( t , testEnv . IsRootless , "rootless mode has different view of network" )
2020-03-04 17:44:08 -05:00
d := daemon . New ( t )
d . Start ( t )
defer d . Stop ( t )
c := d . NewClientT ( t )
defer c . Close ( )
ctx := context . Background ( )
ipv4SNATAddr := "172.0.0.172"
// Create a bridge network with --opt com.docker.network.host_ipv4=172.0.0.172
bridgeName := "hostIPv4Bridge"
network . CreateNoError ( ctx , t , c , bridgeName ,
network . WithDriver ( "bridge" ) ,
network . WithOption ( "com.docker.network.host_ipv4" , ipv4SNATAddr ) ,
network . WithOption ( "com.docker.network.bridge.name" , bridgeName ) ,
)
out , err := c . NetworkInspect ( ctx , bridgeName , types . NetworkInspectOptions { Verbose : true } )
assert . NilError ( t , err )
assert . Assert ( t , len ( out . IPAM . Config ) > 0 )
// Make sure the SNAT rule exists
icmd . RunCommand ( "iptables" , "-t" , "nat" , "-C" , "POSTROUTING" , "-s" , out . IPAM . Config [ 0 ] . Subnet , "!" , "-o" , bridgeName , "-j" , "SNAT" , "--to-source" , ipv4SNATAddr ) . Assert ( t , icmd . Success )
}