functional-test.sh 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #!/bin/bash
  2. ETCD_IMG="${ETCD_IMG:-quay.io/coreos/etcd:v3.2.7}"
  3. ETCD_LOCATION="${ETCD_LOCATION:-etcd}"
  4. FLANNEL_NET="${FLANNEL_NET:-10.10.0.0/16}"
  5. TAG=`git describe --tags --dirty`
  6. FLANNEL_DOCKER_IMAGE="${FLANNEL_DOCKER_IMAGE:-quay.io/coreos/flannel:$TAG}"
  7. setup_suite() {
  8. # Run etcd, killing any existing one that was running
  9. docker_ip=$(ip -o -f inet addr show docker0 | grep -Po 'inet \K[\d.]+')
  10. etcd_endpt="http://$docker_ip:2379"
  11. # Start etcd
  12. docker rm -f flannel-e2e-test-etcd >/dev/null 2>/dev/null
  13. docker run --name=flannel-e2e-test-etcd -d -p 2379:2379 $ETCD_IMG $ETCD_LOCATION --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls $etcd_endpt >/dev/null
  14. }
  15. teardown_suite() {
  16. # Teardown the etcd server
  17. docker rm -f flannel-e2e-test-etcd >/dev/null
  18. }
  19. setup() {
  20. # rm any old flannel container that maybe running, ignore error as it might not exist
  21. docker rm -f flannel-e2e-test-flannel1 >/dev/null 2>/dev/null
  22. assert "docker run --name=flannel-e2e-test-flannel1 -d --privileged $FLANNEL_DOCKER_IMAGE --etcd-endpoints=$etcd_endpt -v 10 >/dev/null"
  23. # rm any old flannel container that maybe running, ignore error as it might not exist
  24. docker rm -f flannel-e2e-test-flannel2 >/dev/null 2>/dev/null
  25. assert "docker run --name=flannel-e2e-test-flannel2 -d --privileged $FLANNEL_DOCKER_IMAGE --etcd-endpoints=$etcd_endpt -v 10 >/dev/null"
  26. }
  27. teardown() {
  28. docker rm -f flannel-e2e-test-flannel1 >/dev/null 2>/dev/null
  29. docker rm -f flannel-e2e-test-flannel2 >/dev/null 2>/dev/null
  30. }
  31. write_config_etcd() {
  32. local backend=$1
  33. if [ -e "$backend" ]; then
  34. echo "Reading custom conf from $backend"
  35. flannel_conf=`cat "$backend"`
  36. else
  37. flannel_conf="{ \"Network\": \"$FLANNEL_NET\", \"Backend\": { \"Type\": \"${backend}\" } }"
  38. fi
  39. # etcd might take a bit to come up - use a known etcd version so we know we have etcdctl available
  40. while ! docker run --rm -it quay.io/coreos/etcd:v3.2.7 etcdctl --endpoints=$etcd_endpt set /coreos.com/network/config "$flannel_conf" >/dev/null
  41. do
  42. sleep 0.1
  43. done
  44. }
  45. create_ping_dest() {
  46. # add a dummy interface with $FLANNEL_SUBNET so we have a known working IP to ping
  47. for host_num in 1 2; do
  48. while ! docker exec flannel-e2e-test-flannel$host_num ls /run/flannel/subnet.env >/dev/null 2>&1; do
  49. sleep 0.1
  50. done
  51. # Use declare to allow the host_num variable to be part of the ping_dest variable name. -g is needed to make it global
  52. declare -g ping_dest$host_num=$(docker "exec" --privileged flannel-e2e-test-flannel$host_num /bin/sh -c '\
  53. source /run/flannel/subnet.env && \
  54. ip link add name dummy0 type dummy && \
  55. ip addr add $FLANNEL_SUBNET dev dummy0 && ip link set dummy0 up && \
  56. echo $FLANNEL_SUBNET | cut -f 1 -d "/" ')
  57. done
  58. }
  59. test_vxlan_ping() {
  60. write_config_etcd vxlan
  61. create_ping_dest # creates ping_dest1 and ping_dest2 variables
  62. pings
  63. }
  64. test_udp_ping() {
  65. write_config_etcd udp
  66. create_ping_dest # creates ping_dest1 and ping_dest2 variables
  67. pings
  68. }
  69. test_host-gw_ping() {
  70. write_config_etcd host-gw
  71. create_ping_dest # creates ping_dest1 and ping_dest2 variables
  72. pings
  73. }
  74. pings() {
  75. # ping in both directions
  76. assert "docker exec -it --privileged flannel-e2e-test-flannel1 /bin/ping -c 3 $ping_dest2" "Host 1 cannot ping host 2"
  77. assert "docker exec -it --privileged flannel-e2e-test-flannel2 /bin/ping -c 3 $ping_dest1" "Host 2 cannot ping host 1"
  78. }
  79. # These perf tests don't actually assert on anything
  80. test_host-gw-perf() {
  81. write_config_etcd host-gw
  82. create_ping_dest
  83. perf
  84. }
  85. test_vxlan_perf() {
  86. write_config_etcd vxlan
  87. create_ping_dest
  88. perf
  89. }
  90. test_udp_perf() {
  91. write_config_etcd udp
  92. create_ping_dest
  93. perf
  94. }
  95. perf() {
  96. # Perf test - run iperf server on flannel1 and client on flannel2
  97. docker rm -f flannel-e2e-test-flannel1-iperf 2>/dev/null
  98. docker run -d --name flannel-e2e-test-flannel1-iperf --net=container:flannel-e2e-test-flannel1 mlabbe/iperf3
  99. docker run --rm --net=container:flannel-e2e-test-flannel2 mlabbe/iperf3 -c $ping_dest1
  100. }
  101. test_multi() {
  102. flannel_conf_vxlan='{"Network": "10.11.0.0/16", "Backend": {"Type": "vxlan"}}'
  103. flannel_conf_host_gw='{"Network": "10.12.0.0/16", "Backend": {"Type": "host-gw"}}'
  104. while ! docker run --rm -it $ETCD_IMG etcdctl --endpoints=$etcd_endpt set /vxlan/network/config "$flannel_conf_vxlan" >/dev/null
  105. do
  106. sleep 0.1
  107. done
  108. while ! docker run --rm -it $ETCD_IMG etcdctl --endpoints=$etcd_endpt set /hostgw/network/config "$flannel_conf_host_gw" >/dev/null
  109. do
  110. sleep 0.1
  111. done
  112. for host in 1 2; do
  113. # rm any old flannel container, ignore error as it might not exist
  114. docker rm -f flannel-host$host 2>/dev/null >/dev/null
  115. # Start the hosts
  116. docker run --name=flannel-host$host -d -it --privileged --entrypoint /bin/sh $FLANNEL_DOCKER_IMAGE >/dev/null
  117. # Start two flanneld instances
  118. docker exec -d flannel-host$host sh -c "/opt/bin/flanneld -v 10 -subnet-file /vxlan.env -etcd-prefix=/vxlan/network --etcd-endpoints=$etcd_endpt 2>vxlan.log"
  119. docker exec -d flannel-host$host sh -c "/opt/bin/flanneld -v 10 -subnet-file /hostgw.env -etcd-prefix=/hostgw/network --etcd-endpoints=$etcd_endpt 2>hostgw.log"
  120. done
  121. for host in 1 2; do
  122. for backend_type in vxlan hostgw; do
  123. while ! docker exec flannel-host$host ls /$backend_type.env >/dev/null 2>&1; do
  124. sleep 0.1
  125. done
  126. done
  127. done
  128. # add dummy interface on host1 only so we have a known working IP to ping then ping it from host2
  129. vxlan_ping_dest=$(docker exec flannel-host1 /bin/sh -c '\
  130. source /vxlan.env &&
  131. ip link add name dummy_vxlan type dummy && \
  132. ip addr add $FLANNEL_SUBNET dev dummy_vxlan && \
  133. ip link set dummy_vxlan up && \
  134. echo $FLANNEL_SUBNET | cut -f 1 -d "/" ')
  135. hostgw_ping_dest=$(docker exec flannel-host1 /bin/sh -c '\
  136. source /hostgw.env &&
  137. ip link add name dummy_hostgw type dummy && \
  138. ip addr add $FLANNEL_SUBNET dev dummy_hostgw && \
  139. ip link set dummy_hostgw up && \
  140. echo $FLANNEL_SUBNET | cut -f 1 -d "/" ')
  141. # Send some pings from host2. Make sure we can send traffic over vxlan or directly.
  142. # If a particular (wrong) interface is forced then pings should fail
  143. assert "docker exec -it flannel-host2 ping -c 3 $hostgw_ping_dest"
  144. assert "docker exec -it flannel-host2 ping -c 3 $vxlan_ping_dest"
  145. assert_fails "docker exec -it flannel-host2 ping -W 1 -c 1 -I flannel.1 $hostgw_ping_dest"
  146. assert_fails "docker exec -it flannel-host2 ping -W 1 -c 1 -I eth0 $vxlan_ping_dest"
  147. }