functional-test.sh 7.8 KB

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