github.com/AbhinandanKurakure/podman/v3@v3.4.10/test/system/500-networking.bats (about)

     1  #!/usr/bin/env bats   -*- bats -*-
     2  #
     3  # Test podman local networking
     4  #
     5  
     6  load helpers
     7  
     8  @test "podman network - basic tests" {
     9      heading="*NETWORK*ID*NAME*VERSION*PLUGINS*"
    10      run_podman network ls
    11      if  [[ ${output} != ${heading} ]]; then
    12         die "network ls expected heading is not available"
    13      fi
    14  
    15      run_podman network ls --noheading
    16      if  [[ ${output} = ${heading} ]]; then
    17         die "network ls --noheading did not remove heading: $output"
    18      fi
    19  }
    20  
    21  # Copied from tsweeney's https://github.com/containers/podman/issues/4827
    22  @test "podman networking: port on localhost" {
    23      random_1=$(random_string 30)
    24      random_2=$(random_string 30)
    25  
    26      HOST_PORT=$(random_free_port)
    27      SERVER=http://127.0.0.1:$HOST_PORT
    28  
    29      # Create a test file with random content
    30      INDEX1=$PODMAN_TMPDIR/hello.txt
    31      echo $random_1 > $INDEX1
    32  
    33      # Bind-mount this file with a different name to a container running httpd
    34      run_podman run -d --name myweb -p "$HOST_PORT:80" \
    35              -v $INDEX1:/var/www/index.txt:Z \
    36              -w /var/www \
    37              $IMAGE /bin/busybox-extras httpd -f -p 80
    38      cid=$output
    39  
    40      # In that container, create a second file, using exec and redirection
    41      run_podman exec -i myweb sh -c "cat > index2.txt" <<<"$random_2"
    42      # ...verify its contents as seen from container.
    43      run_podman exec -i myweb cat /var/www/index2.txt
    44      is "$output" "$random_2" "exec cat index2.txt"
    45  
    46      # Verify http contents: curl from localhost
    47      run curl -s $SERVER/index.txt
    48      is "$output" "$random_1" "curl 127.0.0.1:/index.txt"
    49      run curl -s $SERVER/index2.txt
    50      is "$output" "$random_2" "curl 127.0.0.1:/index2.txt"
    51  
    52      # Verify http contents: wget from a second container
    53      run_podman run --rm --net=host $IMAGE wget -qO - $SERVER/index.txt
    54      is "$output" "$random_1" "podman wget /index.txt"
    55      run_podman run --rm --net=host $IMAGE wget -qO - $SERVER/index2.txt
    56      is "$output" "$random_2" "podman wget /index2.txt"
    57  
    58      # Tests #4889 - two-argument form of "podman ports" was broken
    59      run_podman port myweb
    60      is "$output" "80/tcp -> 0.0.0.0:$HOST_PORT" "port <cid>"
    61      run_podman port myweb 80
    62      is "$output" "0.0.0.0:$HOST_PORT"  "port <cid> 80"
    63      run_podman port myweb 80/tcp
    64      is "$output" "0.0.0.0:$HOST_PORT"  "port <cid> 80/tcp"
    65  
    66      run_podman 125 port myweb 99/tcp
    67      is "$output" 'Error: failed to find published port "99/tcp"'
    68  
    69      # Clean up
    70      run_podman stop -t 1 myweb
    71      run_podman rm myweb
    72  }
    73  
    74  # Issue #5466 - port-forwarding doesn't work with this option and -d
    75  @test "podman networking: port with --userns=keep-id" {
    76      for cidr in "" "$(random_rfc1918_subnet).0/24"; do
    77          myport=$(random_free_port 52000-52999)
    78          if [[ -z $cidr ]]; then
    79              # regex to match that we are in 10.X subnet
    80              match="10\..*"
    81          else
    82              # Issue #9828 make sure a custom slir4netns cidr also works
    83              network_arg="--network slirp4netns:cidr=$cidr"
    84              # slirp4netns interface ip is always .100
    85              match="${cidr%.*}.100"
    86          fi
    87  
    88          # Container will exit as soon as 'nc' receives input
    89          # We use '-n -v' to give us log messages showing an incoming connection
    90          # and its IP address; the purpose of that is guaranteeing that the
    91          # remote IP is not 127.0.0.1 (podman PR #9052).
    92          # We could get more parseable output by using $NCAT_REMOTE_ADDR,
    93          # but busybox nc doesn't support that.
    94          run_podman run -d --userns=keep-id $network_arg -p 127.0.0.1:$myport:$myport \
    95                     $IMAGE nc -l -n -v -p $myport
    96          cid="$output"
    97  
    98          wait_for_output "listening on .*:$myport .*" $cid
    99  
   100          # emit random string, and check it
   101          teststring=$(random_string 30)
   102          echo "$teststring" | nc 127.0.0.1 $myport
   103  
   104          run_podman logs $cid
   105          # Sigh. We can't check line-by-line, because 'nc' output order is
   106          # unreliable. We usually get the 'connect to' line before the random
   107          # string, but sometimes we get it after. So, just do substring checks.
   108          is "$output" ".*listening on \[::\]:$myport .*" "nc -v shows right port"
   109  
   110          # This is the truly important check: make sure the remote IP is not 127.X.
   111          is "$output" \
   112             ".*connect to \[::ffff:$match*\]:$myport from \[::ffff:$match\]:.*" \
   113             "nc -v shows remote IP address is not 127.0.0.1"
   114          is "$output" ".*${teststring}.*" "test string received on container"
   115  
   116          # Clean up
   117          run_podman wait $cid
   118          run_podman rm $cid
   119      done
   120  }
   121  
   122  @test "podman run with slirp4ns assigns correct addresses to /etc/hosts" {
   123      CIDR="$(random_rfc1918_subnet)"
   124      local conname=con-$(random_string 10)
   125      run_podman run --rm --network slirp4netns:cidr="${CIDR}.0/24" \
   126                  --name $conname --hostname $conname $IMAGE cat /etc/hosts
   127      is "$output"   ".*${CIDR}.2 host.containers.internal"   "host.containers.internal should be the cidr+2 address"
   128      is "$output"   ".*${CIDR}.100	$conname $conname"   "$conname should be the cidr+100 address"
   129  }
   130  
   131  @test "podman run with slirp4ns adds correct dns address to resolv.conf" {
   132      CIDR="$(random_rfc1918_subnet)"
   133      run_podman run --rm --network slirp4netns:cidr="${CIDR}.0/24" \
   134                  $IMAGE grep "${CIDR}" /etc/resolv.conf
   135      is "$output"   "nameserver ${CIDR}.3"   "resolv.conf should have slirp4netns cidr+3 as a nameserver"
   136  }
   137  
   138  @test "podman run with slirp4ns assigns correct ip address container" {
   139      CIDR="$(random_rfc1918_subnet)"
   140      run_podman run --rm --network slirp4netns:cidr="${CIDR}.0/24" \
   141                  $IMAGE sh -c "ip address | grep ${CIDR}"
   142      is "$output"   ".*inet ${CIDR}.100/24 \+"   "container should have slirp4netns cidr+100 assigned to interface"
   143  }
   144  
   145  # "network create" now works rootless, with the help of a special container
   146  @test "podman network create" {
   147      # Deliberately use a fixed port, not random_open_port, because of #10806
   148      myport=54322
   149  
   150      local mynetname=testnet-$(random_string 10)
   151      local mysubnet=$(random_rfc1918_subnet)
   152  
   153      run_podman network create --subnet "${mysubnet}.0/24" $mynetname
   154      is "$output" ".*/cni/net.d/$mynetname.conflist" "output of 'network create'"
   155  
   156      # (Assert that output is formatted, not a one-line blob: #8011)
   157      run_podman network inspect $mynetname
   158      if [[ "${#lines[*]}" -lt 5 ]]; then
   159  	die "Output from 'pod inspect' is only ${#lines[*]} lines; see #8011"
   160      fi
   161  
   162      run_podman run --rm --network $mynetname $IMAGE ip a
   163      is "$output" ".* inet ${mysubnet}\.2/24 brd ${mysubnet}\.255 " \
   164         "sdfsdf"
   165  
   166      run_podman run -d --network $mynetname -p 127.0.0.1:$myport:$myport \
   167  	       $IMAGE nc -l -n -v -p $myport
   168      cid="$output"
   169  
   170      # FIXME: debugging for #11871
   171      run_podman exec $cid cat /etc/resolv.conf
   172      if is_rootless && ! is_remote; then
   173          run_podman unshare --rootless-cni cat /etc/resolv.conf
   174      fi
   175      ps uxww
   176  
   177      # check that dns is working inside the container
   178      run_podman exec $cid nslookup google.com
   179  
   180      # emit random string, and check it
   181      teststring=$(random_string 30)
   182      echo "$teststring" | nc 127.0.0.1 $myport
   183  
   184      run_podman logs $cid
   185      # Sigh. We can't check line-by-line, because 'nc' output order is
   186      # unreliable. We usually get the 'connect to' line before the random
   187      # string, but sometimes we get it after. So, just do substring checks.
   188      is "$output" ".*listening on \[::\]:$myport .*" "nc -v shows right port"
   189  
   190      # This is the truly important check: make sure the remote IP is
   191      # in the 172.X range, not 127.X.
   192      is "$output" \
   193         ".*connect to \[::ffff:172\..*\]:$myport from \[::ffff:172\..*\]:.*" \
   194         "nc -v shows remote IP address in 172.X space (not 127.0.0.1)"
   195      is "$output" ".*${teststring}.*" "test string received on container"
   196  
   197      # Cannot create network with the same name
   198      run_podman 125 network create $mynetname
   199      is "$output" "Error: the network name $mynetname is already used" \
   200         "Trying to create an already-existing network"
   201  
   202      run_podman rm $cid
   203      run_podman network rm $mynetname
   204      run_podman 1 network rm $mynetname
   205  }
   206  
   207  @test "podman network reload" {
   208      skip_if_remote "podman network reload does not have remote support"
   209  
   210      random_1=$(random_string 30)
   211      HOST_PORT=$(random_free_port)
   212      SERVER=http://127.0.0.1:$HOST_PORT
   213  
   214      # Create a test file with random content
   215      INDEX1=$PODMAN_TMPDIR/hello.txt
   216      echo $random_1 > $INDEX1
   217  
   218      # use default network for root
   219      local netname=podman
   220      # for rootless we have to create a custom network since there is no default network
   221      if is_rootless; then
   222          netname=testnet-$(random_string 10)
   223          run_podman network create $netname
   224          is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'"
   225      fi
   226  
   227      # Bind-mount this file with a different name to a container running httpd
   228      run_podman run -d --name myweb -p "$HOST_PORT:80" \
   229              --network $netname \
   230              -v $INDEX1:/var/www/index.txt:Z \
   231              -w /var/www \
   232              $IMAGE /bin/busybox-extras httpd -f -p 80
   233      cid=$output
   234  
   235      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").IPAddress}}"
   236      ip="$output"
   237      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}"
   238      mac="$output"
   239  
   240      # Verify http contents: curl from localhost
   241      run curl -s $SERVER/index.txt
   242      is "$output" "$random_1" "curl 127.0.0.1:/index.txt"
   243  
   244      # rootless cannot modify iptables
   245      if ! is_rootless; then
   246          # flush the CNI iptables here
   247          run iptables -t nat -F CNI-HOSTPORT-DNAT
   248  
   249          # check that we cannot curl (timeout after 5 sec)
   250          run timeout 5 curl -s $SERVER/index.txt
   251          if [ "$status" -ne 124 ]; then
   252  	        die "curl did not timeout, status code: $status"
   253          fi
   254      fi
   255  
   256      # reload the network to recreate the iptables rules
   257      run_podman network reload $cid
   258      is "$output" "$cid" "Output does not match container ID"
   259  
   260      # check that we still have the same mac and ip
   261      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").IPAddress}}"
   262      is "$output" "$ip" "IP address changed after podman network reload"
   263      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}"
   264      is "$output" "$mac" "MAC address changed after podman network reload"
   265  
   266      # check that we can still curl
   267      run curl -s $SERVER/index.txt
   268      is "$output" "$random_1" "curl 127.0.0.1:/index.txt"
   269  
   270      # make sure --all is working and that this
   271      # cmd also works if the iptables still exists
   272      run_podman network reload --all
   273      is "$output" "$cid" "Output does not match container ID"
   274  
   275      # check that we can still curl
   276      run curl -s $SERVER/index.txt
   277      is "$output" "$random_1" "curl 127.0.0.1:/index.txt"
   278  
   279      # cleanup the container
   280      run_podman rm -f $cid
   281  
   282      if is_rootless; then
   283          run_podman network rm -f $netname
   284      fi
   285  }
   286  
   287  @test "podman rootless cni adds /usr/sbin to PATH" {
   288      is_rootless || skip "only meaningful for rootless"
   289  
   290      local mynetname=testnet-$(random_string 10)
   291      run_podman network create $mynetname
   292  
   293      # Test that rootless cni adds /usr/sbin to $PATH
   294      # iptables is located under /usr/sbin and is needed for the CNI plugins.
   295      # Debian doesn't add /usr/sbin to $PATH for rootless users so we have to add it.
   296      PATH=/usr/local/bin:/usr/bin run_podman run --rm --network $mynetname $IMAGE ip addr
   297      is "$output" ".*eth0.*" "Interface eth0 not found in ip addr output"
   298  
   299      run_podman network rm -f $mynetname
   300  }
   301  
   302  @test "podman ipv6 in /etc/resolv.conf" {
   303      ipv6_regex='([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})(%\w+)?'
   304  
   305      # Make sure to read the correct /etc/resolv.conf file in case of systemd-resolved.
   306      resolve_file=$(readlink -f /etc/resolv.conf)
   307      if [[ "$resolve_file" == "/run/systemd/resolve/stub-resolv.conf" ]]; then
   308          resolve_file="/run/systemd/resolve/resolv.conf"
   309      fi
   310  
   311      # If the host doesn't have an ipv6 in resolv.conf skip this test.
   312      # We should never modify resolv.conf on the host.
   313      if ! grep -E "$ipv6_regex" "$resolve_file"; then
   314          skip "This test needs an ipv6 nameserver in $resolve_file"
   315      fi
   316  
   317      # ipv4 slirp
   318      run_podman run --rm --network slirp4netns:enable_ipv6=false $IMAGE cat /etc/resolv.conf
   319      if grep -E "$ipv6_regex" <<< $output; then
   320          die "resolv.conf contains a ipv6 nameserver"
   321      fi
   322  
   323      # ipv6 slirp
   324      run_podman run --rm --network slirp4netns:enable_ipv6=true $IMAGE cat /etc/resolv.conf
   325      # "is" does not like the ipv6 regex
   326      if ! grep -E "$ipv6_regex" <<< $output; then
   327          die "resolv.conf does not contain a ipv6 nameserver"
   328      fi
   329  
   330      # ipv4 cni
   331      local mysubnet=$(random_rfc1918_subnet)
   332      local netname=testnet-$(random_string 10)
   333  
   334      run_podman network create --subnet $mysubnet.0/24 $netname
   335      is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'"
   336  
   337      run_podman run --rm --network $netname $IMAGE cat /etc/resolv.conf
   338      if grep -E "$ipv6_regex" <<< $output; then
   339          die "resolv.conf contains a ipv6 nameserver"
   340      fi
   341  
   342      run_podman network rm -f $netname
   343  
   344      # ipv6 cni
   345      mysubnet=fd00:4:4:4:4::/64
   346      netname=testnet-$(random_string 10)
   347  
   348      run_podman network create --subnet $mysubnet $netname
   349      is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'"
   350  
   351      run_podman run --rm --network $netname $IMAGE cat /etc/resolv.conf
   352      # "is" does not like the ipv6 regex
   353      if ! grep -E "$ipv6_regex" <<< $output; then
   354          die "resolv.conf does not contain a ipv6 nameserver"
   355      fi
   356  
   357      run_podman network rm -f $netname
   358  }
   359  
   360  # Test for https://github.com/containers/podman/issues/10052
   361  @test "podman network connect/disconnect with port forwarding" {
   362      random_1=$(random_string 30)
   363      HOST_PORT=$(random_free_port)
   364      SERVER=http://127.0.0.1:$HOST_PORT
   365  
   366      # Create a test file with random content
   367      INDEX1=$PODMAN_TMPDIR/hello.txt
   368      echo $random_1 > $INDEX1
   369  
   370      local netname=testnet-$(random_string 10)
   371      run_podman network create $netname
   372      is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'"
   373  
   374      local netname2=testnet2-$(random_string 10)
   375      run_podman network create $netname2
   376      is "$output" ".*/cni/net.d/$netname2.conflist" "output of 'network create'"
   377  
   378      # First, run a container in background to ensure that the rootless cni ns
   379      # is not destroyed after network disconnect.
   380      run_podman run -d --network $netname $IMAGE top
   381      background_cid=$output
   382  
   383      # Run a httpd container on first network with exposed port
   384      run_podman run -d -p "$HOST_PORT:80" \
   385              --network $netname \
   386              -v $INDEX1:/var/www/index.txt:Z \
   387              -w /var/www \
   388              $IMAGE /bin/busybox-extras httpd -f -p 80
   389      cid=$output
   390  
   391      # Verify http contents: curl from localhost
   392      run curl --max-time 3 -s $SERVER/index.txt
   393      is "$output" "$random_1" "curl 127.0.0.1:/index.txt"
   394  
   395      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").IPAddress}}"
   396      ip="$output"
   397      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}"
   398      mac="$output"
   399  
   400      run_podman network disconnect $netname $cid
   401      is "$output" "" "Output should be empty (no errors)"
   402  
   403      # check that we cannot curl (timeout after 3 sec)
   404      run curl --max-time 3 -s $SERVER/index.txt
   405      if [ "$status" -eq 0 ]; then
   406  	    die "curl did not fail, it should have timed out or failed with non zero exit code"
   407      fi
   408  
   409      run_podman network connect $netname $cid
   410      is "$output" "" "Output should be empty (no errors)"
   411  
   412      # curl should work again
   413      run curl --max-time 3 -s $SERVER/index.txt
   414      is "$output" "$random_1" "curl 127.0.0.1:/index.txt should work again"
   415  
   416      # check that we have a new ip and mac
   417      # if the ip is still the same this whole test turns into a nop
   418      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").IPAddress}}"
   419      if [[ "$output" == "$ip" ]]; then
   420          die "IP address did not change after podman network disconnect/connect"
   421      fi
   422      run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}"
   423      if [[ "$output" == "$mac" ]]; then
   424          die "MAC address did not change after podman network disconnect/connect"
   425      fi
   426  
   427      # Disconnect/reconnect of a container *with no ports* should succeed quietly
   428      run_podman network disconnect $netname $background_cid
   429      is "$output" "" "disconnect of container with no open ports"
   430      run_podman network connect $netname $background_cid
   431      is "$output" "" "(re)connect of container with no open ports"
   432  
   433      # connect a second network
   434      run_podman network connect $netname2 $cid
   435      is "$output" "" "Output should be empty (no errors)"
   436  
   437      # curl should work
   438      run curl --max-time 3 -s $SERVER/index.txt
   439      is "$output" "$random_1" "curl 127.0.0.1:/index.txt should work"
   440  
   441      # disconnect the first network
   442      run_podman network disconnect $netname $cid
   443  
   444      # curl should still work
   445      run curl --max-time 3 -s $SERVER/index.txt
   446      is "$output" "$random_1" "curl 127.0.0.1:/index.txt should still work"
   447  
   448      # cleanup
   449      run_podman stop -t 0 $cid $background_cid
   450      run_podman rm -f $cid $background_cid
   451      run_podman network rm -f $netname $netname2
   452  }
   453  
   454  @test "podman network after restart" {
   455      random_1=$(random_string 30)
   456  
   457      HOST_PORT=$(random_free_port)
   458      SERVER=http://127.0.0.1:$HOST_PORT
   459  
   460      # Create a test file with random content
   461      INDEX1=$PODMAN_TMPDIR/hello.txt
   462      echo $random_1 > $INDEX1
   463  
   464      local netname=testnet-$(random_string 10)
   465      run_podman network create $netname
   466      is "$output" ".*/cni/net.d/$netname.conflist" "output of 'network create'"
   467  
   468      for network in "slirp4netns" "$netname"; do
   469          # Start container with the restart always policy
   470          run_podman run -d --name myweb -p "$HOST_PORT:80" \
   471                  --restart always \
   472                  --network $network \
   473                  -v $INDEX1:/var/www/index.txt:Z \
   474                  -w /var/www \
   475                  $IMAGE /bin/busybox-extras httpd -f -p 80
   476          cid=$output
   477  
   478          # Tests #10310: podman will restart slirp4netns on container restart
   479          run_podman container inspect --format "{{.State.Pid}}" $cid
   480          pid=$output
   481  
   482          # Kill the process; podman restart policy will bring up a new container.
   483          # -9 is crucial: busybox httpd ignores all other signals.
   484          kill -9 $pid
   485          # Wait for process to exit
   486          retries=30
   487          while kill -0 $pid; do
   488              sleep 0.5
   489              retries=$((retries - 1))
   490              if [[ $retries -eq 0 ]]; then
   491                  die "Process $pid (container $cid) refused to die"
   492              fi
   493          done
   494  
   495          # Wait for container to restart
   496          retries=20
   497          while :;do
   498              run_podman container inspect --format "{{.State.Pid}}" $cid
   499              # pid is 0 as long as the container is not running
   500              if [[ $output -ne 0 ]]; then
   501                  if [[ $output == $pid ]]; then
   502                      die "This should never happen! Restarted container has same PID ($output) as killed one!"
   503                  fi
   504                  break
   505              fi
   506              sleep 0.5
   507              retries=$((retries - 1))
   508              if [[ $retries -eq 0 ]]; then
   509                  die "Timed out waiting for container to restart"
   510              fi
   511          done
   512  
   513          # Verify http contents again: curl from localhost
   514          # Use retry since it can take a moment until the new container is ready
   515          run curl --retry 2 -s $SERVER/index.txt
   516          is "$output" "$random_1" "curl 127.0.0.1:/index.txt after auto restart"
   517  
   518          run_podman restart $cid
   519          # Verify http contents again: curl from localhost
   520          # Use retry since it can take a moment until the new container is ready
   521          run curl --retry 2 -s $SERVER/index.txt
   522          is "$output" "$random_1" "curl 127.0.0.1:/index.txt after podman restart"
   523  
   524          run_podman stop -t 0 $cid
   525          run_podman rm -f $cid
   526      done
   527  
   528      # Cleanup network
   529      run_podman network rm $netname
   530  }
   531  
   532  # vim: filetype=sh