helpers.bash 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. function get_docker_bridge_ip() {
  2. echo $(docker run --rm -it busybox ip route show | grep default | cut -d" " -f3)
  3. }
  4. function inst_id2port() {
  5. echo $((41000+${1}-1))
  6. }
  7. function dnet_container_name() {
  8. echo dnet-$1-$2
  9. }
  10. function get_sbox_id() {
  11. local line
  12. line=$(dnet_cmd $(inst_id2port ${1}) service ls | grep ${2})
  13. echo ${line} | cut -d" " -f5
  14. }
  15. function net_connect() {
  16. dnet_cmd $(inst_id2port ${1}) service publish ${2}.${3}
  17. dnet_cmd $(inst_id2port ${1}) service attach ${2} ${2}.${3}
  18. }
  19. function net_disconnect() {
  20. dnet_cmd $(inst_id2port ${1}) service detach ${2} ${2}.${3}
  21. dnet_cmd $(inst_id2port ${1}) service unpublish ${2}.${3}
  22. }
  23. function start_consul() {
  24. stop_consul
  25. docker run -d \
  26. --name=pr_consul \
  27. -p 8500:8500 \
  28. -p 8300-8302:8300-8302/tcp \
  29. -p 8300-8302:8300-8302/udp \
  30. -h consul \
  31. progrium/consul -server -bootstrap
  32. sleep 2
  33. }
  34. function stop_consul() {
  35. echo "consul started"
  36. docker stop pr_consul || true
  37. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  38. if [ -z "$CIRCLECI" ]; then
  39. docker rm -f pr_consul || true
  40. fi
  41. }
  42. hrun() {
  43. local e E T oldIFS
  44. [[ ! "$-" =~ e ]] || e=1
  45. [[ ! "$-" =~ E ]] || E=1
  46. [[ ! "$-" =~ T ]] || T=1
  47. set +e
  48. set +E
  49. set +T
  50. output="$("$@" 2>&1)"
  51. status="$?"
  52. oldIFS=$IFS
  53. IFS=$'\n' lines=($output)
  54. [ -z "$e" ] || set -e
  55. [ -z "$E" ] || set -E
  56. [ -z "$T" ] || set -T
  57. IFS=$oldIFS
  58. }
  59. function wait_for_dnet() {
  60. local hport
  61. hport=$1
  62. echo "waiting on dnet to come up ..."
  63. for i in `seq 1 10`;
  64. do
  65. hrun ./bin/dnet -H tcp://127.0.0.1:${hport} network ls
  66. echo ${output}
  67. if [ "$status" -eq 0 ]; then
  68. return
  69. fi
  70. if [[ "${lines[1]}" =~ .*EOF.* ]]
  71. then
  72. docker logs ${2}
  73. fi
  74. echo "still waiting after ${i} seconds"
  75. sleep 1
  76. done
  77. }
  78. function parse_discovery_str() {
  79. local d provider address
  80. discovery=$1
  81. provider=$(echo ${discovery} | cut -d":" -f1)
  82. address=$(echo ${discovery} | cut -d":" -f2):$(echo ${discovery} | cut -d":" -f3)
  83. address=${address:2}
  84. echo "${discovery} ${provider} ${address}"
  85. }
  86. function start_dnet() {
  87. local inst suffix name hport cport hopt store bridge_ip labels tomlfile
  88. local discovery provider address
  89. inst=$1
  90. shift
  91. suffix=$1
  92. shift
  93. stop_dnet ${inst} ${suffix}
  94. name=$(dnet_container_name ${inst} ${suffix})
  95. hport=$((41000+${inst}-1))
  96. cport=2385
  97. hopt=""
  98. store=${suffix}
  99. while [ -n "$1" ]
  100. do
  101. if [[ "$1" =~ ^[0-9]+$ ]]
  102. then
  103. hport=$1
  104. cport=$1
  105. hopt="-H tcp://0.0.0.0:${cport}"
  106. else
  107. store=$1
  108. fi
  109. shift
  110. done
  111. bridge_ip=$(get_docker_bridge_ip)
  112. echo "start_dnet parsed values: " ${inst} ${suffix} ${name} ${hport} ${cport} ${hopt} ${store} ${labels}
  113. mkdir -p /tmp/dnet/${name}
  114. tomlfile="/tmp/dnet/${name}/libnetwork.toml"
  115. # Try discovery URLs with or without path
  116. if [ "$store" = "zookeeper" ]; then
  117. read discovery provider address < <(parse_discovery_str zk://${bridge_ip}:2182)
  118. elif [ "$store" = "etcd" ]; then
  119. read discovery provider address < <(parse_discovery_str etcd://${bridge_ip}:42000/custom_prefix)
  120. else
  121. read discovery provider address < <(parse_discovery_str consul://${bridge_ip}:8500/custom_prefix)
  122. fi
  123. cat > ${tomlfile} <<EOF
  124. title = "LibNetwork Configuration file for ${name}"
  125. [daemon]
  126. debug = false
  127. [cluster]
  128. discovery = "${discovery}"
  129. Heartbeat = 10
  130. [scopes]
  131. [scopes.global]
  132. [scopes.global.client]
  133. provider = "${provider}"
  134. address = "${address}"
  135. EOF
  136. cat ${tomlfile}
  137. docker run \
  138. -d \
  139. --name=${name} \
  140. --privileged \
  141. -p ${hport}:${cport} \
  142. -e _OVERLAY_HOST_MODE \
  143. -v $(pwd)/:/go/src/github.com/docker/libnetwork \
  144. -v /tmp:/tmp \
  145. -v $(pwd)/${TMPC_ROOT}:/scratch \
  146. -v /usr/local/bin/runc:/usr/local/bin/runc \
  147. -w /go/src/github.com/docker/libnetwork \
  148. mrjana/golang ./bin/dnet -d -D ${hopt} -c ${tomlfile}
  149. wait_for_dnet $(inst_id2port ${inst}) ${name}
  150. }
  151. function skip_for_circleci() {
  152. if [ -n "$CIRCLECI" ]; then
  153. skip
  154. fi
  155. }
  156. function stop_dnet() {
  157. local name
  158. name=$(dnet_container_name $1 $2)
  159. rm -rf /tmp/dnet/${name} || true
  160. docker stop ${name} || true
  161. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  162. if [ -z "$CIRCLECI" ]; then
  163. docker rm -f ${name} || true
  164. fi
  165. }
  166. function dnet_cmd() {
  167. local hport
  168. hport=$1
  169. shift
  170. ./bin/dnet -H tcp://127.0.0.1:${hport} $*
  171. }
  172. function dnet_exec() {
  173. docker exec -it ${1} bash -c "$2"
  174. }
  175. function runc() {
  176. local dnet
  177. dnet=${1}
  178. shift
  179. dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
  180. dnet_exec ${dnet} "mkdir -p /var/run/netns"
  181. dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
  182. dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
  183. dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
  184. }
  185. function runc_nofail() {
  186. local dnet
  187. dnet=${1}
  188. shift
  189. dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
  190. dnet_exec ${dnet} "mkdir -p /var/run/netns"
  191. dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
  192. set +e
  193. dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
  194. status="$?"
  195. set -e
  196. dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
  197. }
  198. function start_etcd() {
  199. local bridge_ip
  200. stop_etcd
  201. bridge_ip=$(get_docker_bridge_ip)
  202. docker run -d \
  203. --net=host \
  204. --name=dn_etcd \
  205. mrjana/etcd --listen-client-urls http://0.0.0.0:42000 \
  206. --advertise-client-urls http://${bridge_ip}:42000
  207. sleep 2
  208. }
  209. function stop_etcd() {
  210. docker stop dn_etcd || true
  211. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  212. if [ -z "$CIRCLECI" ]; then
  213. docker rm -f dn_etcd || true
  214. fi
  215. }
  216. function start_zookeeper() {
  217. stop_zookeeper
  218. docker run -d \
  219. --name=zookeeper_server \
  220. -p 2182:2181 \
  221. -h zookeeper \
  222. dnephin/docker-zookeeper:3.4.6
  223. sleep 2
  224. }
  225. function stop_zookeeper() {
  226. echo "zookeeper started"
  227. docker stop zookeeper_server || true
  228. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  229. if [ -z "$CIRCLECI" ]; then
  230. docker rm -f zookeeper_server || true
  231. fi
  232. }
  233. function test_overlay() {
  234. dnet_suffix=$1
  235. echo $(docker ps)
  236. start=1
  237. end=3
  238. # Setup overlay network and connect containers ot it
  239. if [ -z "${2}" -o "${2}" != "skip_add" ]; then
  240. if [ -z "${2}" -o "${2}" != "internal" ]; then
  241. dnet_cmd $(inst_id2port 1) network create -d overlay multihost
  242. else
  243. dnet_cmd $(inst_id2port 1) network create -d overlay --internal multihost
  244. fi
  245. fi
  246. for i in `seq ${start} ${end}`;
  247. do
  248. dnet_cmd $(inst_id2port $i) container create container_${i}
  249. net_connect ${i} container_${i} multihost
  250. done
  251. # Now test connectivity between all the containers using service names
  252. for i in `seq ${start} ${end}`;
  253. do
  254. if [ -z "${2}" -o "${2}" != "internal" ]; then
  255. runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) \
  256. "ping -c 1 www.google.com"
  257. else
  258. default_route=`runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) "ip route | grep default"`
  259. [ "$default_route" = "" ]
  260. fi
  261. for j in `seq ${start} ${end}`;
  262. do
  263. if [ "$i" -eq "$j" ]; then
  264. continue
  265. fi
  266. runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) \
  267. "ping -c 1 container_$j"
  268. done
  269. done
  270. # Teardown the container connections and the network
  271. for i in `seq ${start} ${end}`;
  272. do
  273. net_disconnect ${i} container_${i} multihost
  274. dnet_cmd $(inst_id2port $i) container rm container_${i}
  275. done
  276. if [ -z "${2}" -o "${2}" != "skip_rm" ]; then
  277. dnet_cmd $(inst_id2port 2) network rm multihost
  278. fi
  279. }
  280. function check_etchosts() {
  281. local dnet sbid retval
  282. dnet=${1}
  283. shift
  284. sbid=${1}
  285. shift
  286. retval="true"
  287. for i in $*;
  288. do
  289. run runc ${dnet} ${sbid} "cat /etc/hosts"
  290. if [ "$status" -ne 0 ]; then
  291. retval="${output}"
  292. break
  293. fi
  294. line=$(echo ${output} | grep ${i})
  295. if [ "${line}" == "" ]; then
  296. retval="false"
  297. fi
  298. done
  299. echo ${retval}
  300. }
  301. function test_overlay_singlehost() {
  302. dnet_suffix=$1
  303. shift
  304. echo $(docker ps)
  305. start=1
  306. end=3
  307. # Setup overlay network and connect containers ot it
  308. dnet_cmd $(inst_id2port 1) network create -d overlay multihost
  309. for i in `seq ${start} ${end}`;
  310. do
  311. dnet_cmd $(inst_id2port 1) container create container_${i}
  312. net_connect 1 container_${i} multihost
  313. done
  314. # Now test connectivity between all the containers using service names
  315. for i in `seq ${start} ${end}`;
  316. do
  317. for j in `seq ${start} ${end}`;
  318. do
  319. if [ "$i" -eq "$j" ]; then
  320. continue
  321. fi
  322. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 container_${i}) \
  323. "ping -c 1 container_$j"
  324. done
  325. done
  326. # Teardown the container connections and the network
  327. for i in `seq ${start} ${end}`;
  328. do
  329. net_disconnect 1 container_${i} multihost
  330. dnet_cmd $(inst_id2port 1) container rm container_${i}
  331. done
  332. dnet_cmd $(inst_id2port 1) network rm multihost
  333. }
  334. function test_overlay_hostmode() {
  335. dnet_suffix=$1
  336. shift
  337. echo $(docker ps)
  338. start=1
  339. end=2
  340. # Setup overlay network and connect containers ot it
  341. dnet_cmd $(inst_id2port 1) network create -d overlay multihost1
  342. dnet_cmd $(inst_id2port 1) network create -d overlay multihost2
  343. dnet_cmd $(inst_id2port 1) network ls
  344. for i in `seq ${start} ${end}`;
  345. do
  346. dnet_cmd $(inst_id2port 1) container create mh1_${i}
  347. net_connect 1 mh1_${i} multihost1
  348. done
  349. for i in `seq ${start} ${end}`;
  350. do
  351. dnet_cmd $(inst_id2port 1) container create mh2_${i}
  352. net_connect 1 mh2_${i} multihost2
  353. done
  354. # Now test connectivity between all the containers using service names
  355. for i in `seq ${start} ${end}`;
  356. do
  357. for j in `seq ${start} ${end}`;
  358. do
  359. if [ "$i" -eq "$j" ]; then
  360. continue
  361. fi
  362. # Find the IP addresses of the j containers on both networks
  363. hrun runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) "nslookup mh1_$j"
  364. mh1_j_ip=$(echo ${output} | awk '{print $11}')
  365. hrun runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) "nslookup mh2_$j"
  366. mh2_j_ip=$(echo ${output} | awk '{print $11}')
  367. # Ping the j containers in the same network and ensure they are successfull
  368. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) \
  369. "ping -c 1 mh1_$j"
  370. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) \
  371. "ping -c 1 mh2_$j"
  372. # Try pinging j container IPs from the container in the other network and make sure that they are not successfull
  373. runc_nofail $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) "ping -c 1 ${mh2_j_ip}"
  374. [ "${status}" -ne 0 ]
  375. runc_nofail $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) "ping -c 1 ${mh1_j_ip}"
  376. [ "${status}" -ne 0 ]
  377. # Try pinging the j container IPS from the host(dnet container in this case) and make syre that they are not successfull
  378. hrun docker exec -it $(dnet_container_name 1 $dnet_suffix) "ping -c 1 ${mh1_j_ip}"
  379. [ "${status}" -ne 0 ]
  380. hrun docker exec -it $(dnet_container_name 1 $dnet_suffix) "ping -c 1 ${mh2_j_ip}"
  381. [ "${status}" -ne 0 ]
  382. done
  383. done
  384. # Teardown the container connections and the network
  385. for i in `seq ${start} ${end}`;
  386. do
  387. net_disconnect 1 mh1_${i} multihost1
  388. dnet_cmd $(inst_id2port 1) container rm mh1_${i}
  389. done
  390. for i in `seq ${start} ${end}`;
  391. do
  392. net_disconnect 1 mh2_${i} multihost2
  393. dnet_cmd $(inst_id2port 1) container rm mh2_${i}
  394. done
  395. dnet_cmd $(inst_id2port 1) network rm multihost1
  396. dnet_cmd $(inst_id2port 1) network rm multihost2
  397. }