github.com/Equinix-Metal/virtlet@v1.5.2-0.20210807010419-342346535dc5/build/cmd.sh (about) 1 #!/bin/bash 2 set -o errexit 3 set -o nounset 4 set -o pipefail 5 set -o errtrace 6 7 CRIPROXY_DEB_URL="${CRIPROXY_DEB_URL:-https://github.com/Mirantis/criproxy/releases/download/v0.14.0/criproxy-nodeps_0.14.0_amd64.deb}" 8 VIRTLET_IMAGE_REPO="${VIRTLET_IMAGE_REPO:-ryugu-psie-docker-dev-local.jfrog.io/equinix}" 9 VIRTLET_SKIP_RSYNC="${VIRTLET_SKIP_RSYNC:-}" 10 VIRTLET_SKIP_VENDOR="${VIRTLET_SKIP_VENDOR:-false}" 11 VIRTLET_RSYNC_PORT="${VIRTLET_RSYNC_PORT:-18730}" 12 VIRTLET_ON_MASTER="${VIRTLET_ON_MASTER:-}" 13 VIRTLET_MULTI_NODE="${VIRTLET_MULTI_NODE:-}" 14 # XXX: try to extract the docker socket path from DOCKER_HOST if it's set to unix://... 15 DOCKER_SOCKET_PATH="${DOCKER_SOCKET_PATH:-/var/run/docker.sock}" 16 FORCE_UPDATE_IMAGE="${FORCE_UPDATE_IMAGE:-}" 17 IMAGE_REGEXP_TRANSLATION="${IMAGE_REGEXP_TRANSLATION:-1}" 18 GH_RELEASE_TEST_USER="ivan4th" 19 DIND_CRI="${DIND_CRI:-containerd}" 20 MKDOCS_SERVE_ADDRESS="${MKDOCS_SERVE_ADDRESS:-localhost:8042}" 21 22 # Note that project_dir must not end with slash 23 project_dir="$(cd "$(dirname "${BASH_SOURCE}")/.." && pwd)" 24 virtlet_image="${VIRTLET_IMAGE_REPO}/virtlet" 25 remote_project_dir="/go/src/github.com/Equinix-Metal/virtlet" 26 build_name="virtlet-build" 27 tmp_container_name="${build_name}-$(openssl rand -hex 16)" 28 build_image="${VIRTLET_IMAGE_REPO}/${build_name}:latest" 29 volume_name=virtlet_src 30 rsync_git=y 31 exclude=( 32 --exclude 'vendor' 33 --exclude .git 34 --exclude _output 35 --exclude '*.png' 36 ) 37 rsync_pw_file="${project_dir}/_output/rsync.password" 38 busybox_image=busybox:1.27.2 39 virtlet_nodes=() 40 if [[ ${VIRTLET_ON_MASTER} ]]; then 41 virtlet_nodes+=(kube-master) 42 fi 43 if [[ !${VIRTLET_ON_MASTER} || ${VIRTLET_MULTI_NODE} ]]; then 44 virtlet_nodes+=(kube-node-1) 45 fi 46 if [[ ${VIRTLET_MULTI_NODE} ]]; then 47 virtlet_nodes+=(kube-node-2) 48 fi 49 bindata_modtime=1522279343 50 bindata_out="pkg/tools/bindata.go" 51 bindata_dir="deploy/data" 52 bindata_pkg="tools" 53 ldflags=() 54 go_package=github.com/Equinix-Metal/virtlet 55 56 function image_tags_filter { 57 local tag="${1}" 58 local prefix=".items[0].spec.template.spec." 59 local suffix="|=map(.image=\"equinix/virtlet:${tag}\")" 60 echo -n "${prefix}containers${suffix}|${prefix}initContainers${suffix}" 61 } 62 63 function get_version() { 64 inside_git=$(git rev-parse --is-inside-work-tree 2>&1 >/dev/null; echo $?) 65 if [ $inside_git != 0 ]; then 66 echo "Not in GIT repo and VERSION variable is not set." 67 version='latest' 68 else 69 VERSION_HASH=$(git show --summary | head -1 | awk '{print substr($2,0,8)}') 70 version="${VERSION_HASH}" 71 fi 72 echo "$version" >"${project_dir}/_output/version" 73 return 0 74 } 75 76 # from build/common.sh in k8s 77 function rsync_probe { 78 # Wait unil rsync is up and running. 79 local tries=20 80 while (( ${tries} > 0 )) ; do 81 if rsync "rsync://k8s@${1}:${2}/" \ 82 --password-file="${project_dir}/_output/rsyncd.password" \ 83 &> /dev/null ; then 84 return 0 85 fi 86 tries=$(( ${tries} - 1)) 87 sleep 0.1 88 done 89 90 return 1 91 } 92 93 function image_exists { 94 local name="${1}" 95 # can't use 'docker images -q' due to https://github.com/docker/docker/issues/28895 96 docker history -q "${name}" >& /dev/null || return 1 97 } 98 99 function ensure_build_image { 100 mkdir -p "${project_dir}/_output" 101 get_version 102 build_tag="$(cat "${project_dir}/_output/version")" 103 build_image="${VIRTLET_IMAGE_REPO}/${build_name}:${build_tag}" 104 docker login ryugu-psie-docker-dev-local.jfrog.io 105 virtlet_base_image="${VIRTLET_IMAGE_REPO}/virtlet-base:${build_tag}" 106 build_base_image="${VIRTLET_IMAGE_REPO}/virtlet-build-base:${build_tag}" 107 echo >&2 "Trying to pull the base image ${virtlet_base_image}..." 108 if ! docker pull "${virtlet_base_image}"; then 109 docker build -t "${virtlet_base_image}" \ 110 -f "${project_dir}/images/Dockerfile.virtlet-base" \ 111 "${project_dir}/images" 112 docker push "${virtlet_base_image}" 113 fi 114 echo >&2 "Trying to pull the build base image ${build_base_image}..." 115 if ! docker pull "${build_base_image}"; then 116 docker build -t "${build_base_image}" \ 117 --label virtlet_image=build-base \ 118 --build-arg BASE_TAG=${build_tag} \ 119 -f "${project_dir}/images/Dockerfile.build-base" "${project_dir}/images" 120 docker push "${build_base_image}" 121 fi 122 tar -C "${project_dir}/images" -c image_skel/ qemu-build.conf Dockerfile.build | 123 docker build -t "${build_image}" --build-arg BUILD_TAG=${build_tag} \ 124 -f Dockerfile.build - 125 docker tag "${build_image}" "${VIRTLET_IMAGE_REPO}/${build_name}:latest" 126 docker push "${build_image}" 127 docker push "${VIRTLET_IMAGE_REPO}/${build_name}:latest" 128 } 129 130 function get_rsync_addr { 131 local container_ip 132 container_ip=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' virtlet-build) 133 134 # Sometimes we can reach rsync through localhost and a NAT'd port. Other 135 # times (when we are running in another docker container on the Jenkins 136 # machines) we have to talk directly to the container IP. There is no one 137 # strategy that works in all cases so we test to figure out which situation we 138 # are in. 139 if rsync_probe 127.0.0.1 "${VIRTLET_RSYNC_PORT}"; then 140 echo "127.0.0.1:${VIRTLET_RSYNC_PORT}" >"${project_dir}/_output/rsync_addr" 141 return 0 142 elif rsync_probe "${container_ip}" ${VIRTLET_RSYNC_PORT}; then 143 echo "${container_ip}:${VIRTLET_RSYNC_PORT}" >"${project_dir}/_output/rsync_addr" 144 return 0 145 else 146 echo "Could not probe the rsync port" >&2 147 fi 148 } 149 150 function ensure_build_container { 151 if ! docker ps --filter=label=virtlet_build | grep -q virtlet-build; then 152 ensure_build_image 153 cd "${project_dir}" 154 # Need to mount docker socket into the container because of 155 # CRI proxy deployment tests & building the image 156 # We also pass --tmpfs /tmp because log tailing doesn't work 157 # on overlayfs. This breaks 'go test' though unless we also 158 # remount /tmp with exec option (it creates and runs executable files 159 # under /tmp) 160 declare -a docker_cert_args=() 161 if [[ ${DOCKER_CERT_PATH:-} ]]; then 162 docker_cert_args=(-e DOCKER_CERT_PATH=/docker-cert) 163 fi 164 docker run -d --privileged --net=host \ 165 -l virtlet_build \ 166 -v "virtlet_src:${remote_project_dir}" \ 167 -v "virtlet_pkg:/go/pkg" \ 168 -v /sys/fs/cgroup:/sys/fs/cgroup \ 169 -v /lib/modules:/lib/modules:ro \ 170 -v /boot:/boot:ro \ 171 -v "${DOCKER_SOCKET_PATH}:/var/run/docker.sock" \ 172 -e DOCKER_MACHINE_NAME="${DOCKER_MACHINE_NAME:-}" \ 173 -e DOCKER_TLS_VERIFY="${DOCKER_TLS_VERIFY:-}" \ 174 -e TRAVIS="${TRAVIS:-}" \ 175 -e TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST:-}" \ 176 -e TRAVIS_BRANCH="${TRAVIS_BRANCH:-}" \ 177 -e CIRCLECI="${CIRCLECI:-}" \ 178 -e CIRCLE_PULL_REQUEST="${CIRCLE_PULL_REQUEST:-}" \ 179 -e CIRCLE_BRANCH="${CIRCLE_PULL_REQUEST:-}" \ 180 -e VIRTLET_ON_MASTER="${VIRTLET_ON_MASTER:-}" \ 181 -e VIRTLET_MULTI_NODE="${VIRTLET_MULTI_NODE:-}" \ 182 -e GITHUB_TOKEN="${GITHUB_TOKEN:-}" \ 183 -e MKDOCS_SERVE_ADDRESS="${MKDOCS_SERVE_ADDRESS:-}" \ 184 -e VIRTLET_SKIP_VENDOR="${VIRTLET_SKIP_VENDOR:-false}" \ 185 ${docker_cert_args[@]+"${docker_cert_args[@]}"} \ 186 --name virtlet-build \ 187 --tmpfs /tmp \ 188 "${build_image}" \ 189 /bin/bash -c "mount /tmp -o remount,exec && sleep Infinity" >/dev/null 190 if [[ ! ${VIRTLET_SKIP_RSYNC} ]]; then 191 # from build/common.sh in k8s 192 mkdir -p "${project_dir}/_output" 193 dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null >"${rsync_pw_file}" 194 chmod 600 "${rsync_pw_file}" 195 196 docker cp "${rsync_pw_file}" virtlet-build:/rsyncd.password 197 docker exec -d -i virtlet-build /rsyncd.sh "${VIRTLET_RSYNC_PORT}" 198 get_rsync_addr 199 fi 200 if [[ ${DOCKER_CERT_PATH:-} ]]; then 201 tar -C "${DOCKER_CERT_PATH}" -c . | docker exec -i virtlet-build /bin/bash -c 'mkdir /docker-cert && tar -C /docker-cert -x' 202 fi 203 fi 204 if [[ ! ${VIRTLET_SKIP_RSYNC} ]]; then 205 get_rsync_addr 206 RSYNC_ADDR="$(cat "${project_dir}/_output/rsync_addr")" 207 fi 208 } 209 210 function vsh { 211 ensure_build_container 212 cd "${project_dir}" 213 docker exec -it virtlet-build env TERM=xterm bash 214 } 215 216 function sync_source { 217 ensure_build_container 218 cd "${project_dir}" 219 if [[ ! ${VIRTLET_SKIP_RSYNC} ]]; then 220 local -a filters=( 221 --filter '- /_output/' 222 ) 223 if [[ ${VIRTLET_SKIP_VENDOR:-false} != "true" ]]; then 224 filters+=(--filter '- /vendor/') 225 fi 226 if [[ ! ${rsync_git} ]]; then 227 filters+=(--filter '- /.git/') 228 fi 229 rsync "${filters[@]}" \ 230 --password-file "${project_dir}/_output/rsync.password" \ 231 -a --delete --compress-level=9 \ 232 "${project_dir}/" "rsync://virtlet@${RSYNC_ADDR}/virtlet/" 233 fi 234 } 235 236 function vcmd { 237 sync_source >&2 238 local t="" 239 if [[ ${USE_TERM:-} ]]; then 240 t="t" 241 fi 242 docker exec -i"${t}" virtlet-build bash -c "$*" 243 } 244 245 function vcmd_simple { 246 local cmd="${1}" 247 docker exec -i virtlet-build bash -c "${cmd}" 248 } 249 250 function stop { 251 docker ps -a -q --filter=label=virtlet_build | while read container_id; do 252 echo >&2 "Removing container:" "${container_id}" 253 docker rm -fv "${container_id}" 254 done 255 } 256 257 function copy_output { 258 ensure_build_container 259 cd "${project_dir}" 260 vcmd_simple "tar -C '${remote_project_dir}' -cz \$(find . -path '*/_output/*' -type f)" | tar -xvz 261 } 262 263 function copy_back { 264 ensure_build_container 265 cd "${project_dir}" 266 tar -cz $(find . -path '*/_output/*' -type f | grep -v rsync) | vcmd_simple "tar -C '${remote_project_dir}' -xvz" 267 } 268 269 function copy_dind_internal { 270 local virtlet_node="${1}" 271 if ! docker volume ls -q | grep -q "^kubeadm-dind-${virtlet_node}$"; then 272 echo "No active or snapshotted kubeadm-dind-cluster" >&2 273 exit 1 274 fi 275 tar -C _output -c . | 276 docker run -i --rm \ 277 -v "kubeadm-dind-${virtlet_node}:/dind" \ 278 --name ${tmp_container_name} \ 279 "${busybox_image}" \ 280 /bin/sh -c 'tar -C /dind -xv && chmod ug+s /dind/vmwrapper' 281 } 282 283 function kvm_ok { 284 build_tag="$(cat "${project_dir}/_output/version")" 285 # The check is done inside the virtlet node container because it 286 # has proper /lib/modules from the docker host. Also, it'll have 287 # to use the virtlet image later anyway. 288 # Use kube-master node as all of the DIND nodes in the cluster are similar 289 if ! docker exec kube-master docker run --privileged --rm -v /lib/modules:/lib/modules "${virtlet_image}:${build_tag}" kvm-ok; then 290 return 1 291 fi 292 } 293 294 function prepare_node { 295 local node="${1}" 296 if docker exec "${node}" dpkg-query -W criproxy-nodeps >&/dev/null; then 297 return 0 298 fi 299 ensure_build_container 300 echo >&2 "Installing CRI proxy package in the node container (${node})..." 301 if [[ ${DIND_CRI:-} = containerd ]]; then 302 docker exec "${node}" /bin/bash -c 'echo criproxy-nodeps criproxy/primary_cri select containerd | debconf-set-selections' 303 fi 304 docker exec "${node}" /bin/bash -c "curl -sSL '${CRIPROXY_DEB_URL}' >/criproxy.deb && dpkg -i /criproxy.deb && rm /criproxy.deb" 305 306 docker exec "${node}" mount --make-shared /dind 307 docker exec "${node}" mount --make-shared /dev 308 docker exec "${node}" mount --make-shared /boot 309 docker exec "${node}" mount --make-shared /sys/fs/cgroup 310 311 if [[ ${VIRTLET_ON_MASTER} ]]; then 312 if [[ $(kubectl get node kube-master -o jsonpath='{.spec.taints[?(@.key=="node-role.kubernetes.io/master")]}') ]]; then 313 kubectl taint nodes kube-master node-role.kubernetes.io/master- 314 fi 315 fi 316 if [[ ${FORCE_UPDATE_IMAGE} ]] || ! docker exec "${node}" docker history -q "${virtlet_image}:latest" >&/dev/null; then 317 echo >&2 "Propagating Virtlet image to the node container..." 318 if [[ ${DIND_CRI} = containerd ]]; then 319 vcmd "docker save '${virtlet_image}:latest' | docker exec -i '${node}' ctr -n k8s.io images import -" 320 else 321 vcmd "docker save '${virtlet_image}:latest' | docker exec -i '${node}' docker load" 322 fi 323 fi 324 } 325 326 function prepare_all_nodes { 327 for node in $(kubectl get nodes -o jsonpath='{.items[?(@.metadata.name!="kube-master")].metadata.name}'); do 328 prepare_node "${node}" 329 done 330 } 331 332 function apply_runtime_label { 333 local node="${1}" 334 kubectl label node --overwrite "${node}" extraRuntime=virtlet 335 } 336 337 function start_dind { 338 local -a virtlet_config=(--from-literal=image_regexp_translation="${IMAGE_REGEXP_TRANSLATION}") 339 if ! kvm_ok || [[ ${VIRTLET_DISABLE_KVM:-} ]]; then 340 virtlet_config+=(--from-literal=disable_kvm=y) 341 fi 342 kubectl create configmap -n kube-system virtlet-config "${virtlet_config[@]}" 343 kubectl create configmap -n kube-system virtlet-image-translations --from-file "${project_dir}/deploy/images.yaml" 344 start_virtlet 345 } 346 347 function start_virtlet { 348 local -a opts=(--dev) 349 if kubectl version | tail -n1 | grep -q 'v1\.7\.'; then 350 # apply mount propagation hacks for 1.7 351 opts+=(--compat) 352 fi 353 docker exec virtlet-build "${remote_project_dir}/_output/virtletctl" gen "${opts[@]}" | 354 kubectl apply -f - 355 } 356 357 function virtlet_subdir { 358 local dir="${1:-$(pwd)}" 359 local prefix="${project_dir}/" 360 if [[ ${#dir} -lt ${#prefix} || ${dir:0:${#prefix}} != ${prefix} ]]; then 361 echo >&2 "must be in a project subdir" 362 exit 1 363 fi 364 echo -n "${dir:${#prefix}}" 365 } 366 367 function clean { 368 stop 369 docker volume rm virtlet_src || true 370 docker volume rm virtlet_pkg || true 371 docker rmi "${build_image}" || true 372 # find command may produce zero results 373 # -exec rm -rf '{}' ';' produces errors when trying to 374 # enter deleted directories 375 find . -name _output -type d | while read dir; do 376 rm -rf "${dir}" 377 done 378 } 379 380 function gotest { 381 # FIXME: exit 1 in $(virtlet_subdir) doesn't cause the script to exit 382 virtlet_subdir >/dev/null 383 subdir="$(virtlet_subdir)" 384 if ! vcmd "cd '${subdir}' && go test $*"; then 385 vcmd_simple "find . -name 'Test*.out.*' | xargs tar -c -T -" | tar -C "${project_dir}" -x 386 exit 1 387 fi 388 } 389 390 function gobuild { 391 # FIXME: exit 1 in $(virtlet_subdir) doesn't cause the script to exit 392 virtlet_subdir >/dev/null 393 # -gcflags -e removes the limit on error message count, which helps 394 # with using it for syntax checking 395 vcmd "cd '$(virtlet_subdir)' && go build -gcflags -e $*" 396 } 397 398 function build_image_internal { 399 build_internal 400 build_tag="$(cat "${project_dir}/_output/version")" 401 tar -c _output -C "${project_dir}/images" image_skel/ Dockerfile.virtlet | 402 docker build -t "${virtlet_image}:${build_tag}" --build-arg VIRLET_BASE_TAG=build_tag \ 403 -f Dockerfile.virtlet - 404 docker push "${virtlet_image}:${build_tag}" 405 docker tag "${virtlet_image}:${build_tag}" "${virtlet_image}:latest" 406 docker push "${virtlet_image}:latest" 407 } 408 409 function install_vendor_internal { 410 if [ ! -d vendor ]; then 411 glide install --strip-vendor 412 fi 413 } 414 415 function run_tests_internal { 416 install_vendor_internal 417 go test -v ./pkg/... ./tests/network/... 418 } 419 420 function run_integration_internal { 421 install_vendor_internal 422 ( cd tests/integration && ./go.test ) 423 } 424 425 function get_ldflags { 426 # XXX: use kube::version::ldflag (-ldflags -X package.Var=...) 427 # see also versioning.mk in helm 428 # https://stackoverflow.com/questions/11354518/golang-application-auto-build-versioning 429 # see pkg/version/version.go in k8s 430 # for GoVersion / Compiler / Platform 431 local vfile="${project_dir}/pkg/version/version.go" 432 local git_version="$(git describe --tags --abbrev=14 'HEAD^{commit}' | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/")" 433 local git_commit="$(git rev-parse "HEAD^{commit}")" 434 local git_tree_state=$([[ $(git status --porcelain) ]] && echo "dirty" || echo "clean") 435 if [[ ${git_tree_state} == dirty ]]; then 436 git_version+="-dirty" 437 fi 438 local build_date="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" 439 local git_major="" 440 local git_minor="" 441 local version_pkg="${go_package}/pkg/version" 442 local ldflags=(-X "${version_pkg}.gitVersion=${git_version}" 443 -X "${version_pkg}.gitCommit=${git_commit}" 444 -X "${version_pkg}.gitTreeState=${git_tree_state}" 445 -X "${version_pkg}.buildDate=${build_date}") 446 if [[ ${git_version} =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then 447 git_major=${BASH_REMATCH[1]} 448 git_minor=${BASH_REMATCH[2]} 449 ldflags+=(-X "${version_pkg}.gitMajor=${git_major}" 450 -X "${version_pkg}.gitMinor=${git_minor}") 451 fi 452 if [[ ${SET_VIRTLET_IMAGE_TAG:-} ]]; then 453 ldflags+=(-X "${version_pkg}.imageTag=${SET_VIRTLET_IMAGE_TAG}") 454 fi 455 echo "${ldflags[*]}" 456 } 457 458 function build_internal { 459 # we don't just always generate the bindata right there because we 460 # want to keep the source buildable outside this build container. 461 go-bindata -mode 0644 -o /tmp/bindata.go -modtime "${bindata_modtime}" -pkg "${bindata_pkg}" "${bindata_dir}" 462 if ! cmp /tmp/bindata.go "${bindata_out}"; then 463 echo >&2 "${bindata_dir} changed, please re-run ${0} update-bindata" 464 exit 1 465 fi 466 install_vendor_internal 467 ldflags="$(get_ldflags)" 468 mkdir -p "${project_dir}/_output" 469 go build -i -o "${project_dir}/_output/virtlet" -ldflags "${ldflags}" ./cmd/virtlet 470 go build -i -o "${project_dir}/_output/virtletctl" -ldflags "${ldflags}" ./cmd/virtletctl 471 GOOS=darwin go build -i -o "${project_dir}/_output/virtletctl.darwin" -ldflags "${ldflags}" ./cmd/virtletctl 472 go build -i -o "${project_dir}/_output/vmwrapper" ./cmd/vmwrapper 473 go build -i -o "${project_dir}/_output/flexvolume_driver" ./cmd/flexvolume_driver 474 go test -i -c -o "${project_dir}/_output/virtlet-e2e-tests" ./tests/e2e 475 go build -i -o "${project_dir}/_output/virtlet-longevity-tests" -ldflags "${ldflags}" ./cmd/longevity 476 get_version 477 } 478 479 function release_description { 480 local -a tag="${1}" 481 shift 482 git tag -l --format='%(contents:body)' "${tag}" 483 echo 484 echo "SHA256 sums for the files:" 485 echo '```' 486 (cd _output && sha256sum "$@") 487 echo '```' 488 } 489 490 function release_internal { 491 local tag="${1}" 492 local gh_user="Mirantis" 493 if [[ ${tag} =~ test ]]; then 494 gh_user="${GH_RELEASE_TEST_USER}" 495 fi 496 local -a opts=(--user "${gh_user}" --repo virtlet --tag "${tag}") 497 local -a files=(virtletctl virtletctl.darwin) 498 local description="$(release_description "${tag}" "${files[@]}")" 499 local pre_release= 500 if [[ ${tag} =~ -(test|pre).*$ ]]; then 501 pre_release="--pre-release" 502 fi 503 if github-release --quiet delete "${opts[@]}"; then 504 echo >&2 "Replacing the old Virtlet release" 505 fi 506 github-release release "${opts[@]}" \ 507 --name "$(git tag -l --format='%(contents:subject)' "${tag}")" \ 508 --description "${description}" \ 509 ${pre_release} 510 for filename in "${files[@]}"; do 511 echo >&2 "Uploading: ${filename}" 512 github-release upload "${opts[@]}" \ 513 --name "${filename}" \ 514 --replace \ 515 --file "_output/${filename}" 516 done 517 } 518 519 function e2e { 520 ensure_build_container 521 local cluster_url 522 cluster_url="$(kubectl config view -o jsonpath='{.clusters[?(@.name=="dind")].cluster.server}')" 523 docker exec virtlet-build _output/virtlet-e2e-tests -include-unsafe-tests=true -cluster-url "${cluster_url}" "$@" 524 } 525 526 function update_bindata_internal { 527 # set fixed modtime to avoid unwanted differences during the checks 528 # that are done by build/cmd.sh build 529 go-bindata -mode 0644 -modtime "${bindata_modtime}" -o "${bindata_out}" -pkg "${bindata_pkg}" "${bindata_dir}" 530 } 531 532 function update_generated_docs_internal { 533 if [[ ! -f _output/virtletctl ]]; then 534 echo >&2 "Please run build/cmd.sh build first" 535 fi 536 virtletctl gendoc docs/docs/reference 537 tempfile="$(tempfile)" 538 _output/virtletctl gendoc --config >"${tempfile}" 539 sed -i "/<!-- begin -->/,/<!-- end -->/{ 540 //!d 541 /begin/r ${tempfile} 542 }" docs/docs/reference/config.md 543 rm -f "${tempfile}" 544 } 545 546 function update_generated_internal { 547 install_vendor_internal 548 vendor/k8s.io/code-generator/generate-groups.sh all \ 549 github.com/Equinix-Metal/virtlet/pkg/client github.com/Equinix-Metal/virtlet/pkg/api \ 550 virtlet.k8s:v1 \ 551 --go-header-file "build/custom-boilerplate.go.txt" 552 # fix import url case issues 553 find pkg/client \ 554 -name '*.go' \ 555 -exec sed -i 's@github\.com/Equinix/virtlet@github\.com/Equinix/virtlet@g' \ 556 '{}' \; 557 } 558 559 function serve_docs_internal { 560 (cd docs && mkdocs serve -a "${MKDOCS_SERVE_ADDRESS}") 561 } 562 563 function build_docs_internal { 564 site_dir="$(mktemp -d)" 565 trap 'rm -rf "${site_dir}"' EXIT 566 # Use strict mode (-s) for mkdocs so that any broken links 567 # etc. are caught 568 (cd docs && mkdocs build -s -d "${site_dir}" >&2) 569 tar -C "${site_dir}" -c . 570 } 571 572 function build_docs { 573 cd "${project_dir}" 574 rm -rf _docs 575 git clone -b docs . _docs 576 local docs_hash="$(git ls-tree HEAD -- docs | awk '{print $3}')" 577 if [[ ! -e _docs/source_hash || ${docs_hash} != $(cat _docs/source_hash) ]]; then 578 echo >&2 "docs/ directory changed since the last doc build, rebuilding docs" 579 elif [[ $(git status --porcelain) ]]; then 580 echo >&2 "Source directory dirty, rebuilding docs" 581 else 582 echo >&2 "Docs unchanged, no need to rebuild" 583 return 0 584 fi 585 # clean up _docs except for .git and CNAME 586 find _docs -name .git -prune -o -type f \! -name CNAME -exec rm -f '{}' \; 587 vcmd "build/cmd.sh build-docs-internal" | tar -C _docs -xv 588 echo "${docs_hash}" > _docs/source_hash 589 ( 590 cd _docs 591 git add . 592 git commit -m "Update generated docs [ci skip]" 593 # this pushes the changes into the local repo (not github!) 594 git push origin docs 595 ) 596 } 597 598 function usage { 599 echo >&2 "Usage:" 600 echo >&2 " $0 build" 601 echo >&2 " $0 test" 602 echo >&2 " $0 copy" 603 echo >&2 " $0 copy-dind" 604 echo >&2 " $0 start-dind" 605 echo >&2 " $0 vsh" 606 echo >&2 " $0 stop" 607 echo >&2 " $0 clean" 608 echo >&2 " $0 update-bindata" 609 echo >&2 " $0 update-generated-docs" 610 echo >&2 " $0 gotest [TEST_ARGS...]" 611 echo >&2 " $0 gobuild [BUILD_ARGS...]" 612 echo >&2 " $0 run CMD..." 613 echo >&2 " $0 release TAG" 614 echo >&2 " $0 serve-docs" 615 echo >&2 " $0 build-docs" 616 echo >&2 " $0 sync" 617 exit 1 618 } 619 620 cmd="${1:-}" 621 if [[ ! $cmd ]]; then 622 usage 623 fi 624 shift 625 626 case "${cmd}" in 627 gotest) 628 gotest "$@" 629 ;; 630 gobuild) 631 rsync_git= 632 gobuild "$@" 633 ;; 634 prepare-vendor) 635 vcmd "build/cmd.sh install-vendor-internal" 636 ;; 637 build) 638 vcmd "SET_VIRTLET_IMAGE_TAG='${SET_VIRTLET_IMAGE_TAG:-}' build/cmd.sh build-image-internal" 639 ;; 640 build-image-internal) 641 # this is executed inside the container 642 build_image_internal "$@" 643 ;; 644 test) 645 vcmd 'build/cmd.sh run-tests-internal' 646 ;; 647 integration) 648 vcmd 'build/cmd.sh run-integration-internal' 649 ;; 650 install-vendor-internal) 651 install_vendor_internal 652 ;; 653 run-tests-internal) 654 run_tests_internal 655 ;; 656 run-integration-internal) 657 run_integration_internal 658 ;; 659 update-bindata) 660 vcmd "build/cmd.sh update-bindata-internal" 661 docker cp "virtlet-build:${remote_project_dir}/pkg/tools/bindata.go" pkg/tools/bindata.go 662 ;; 663 update-bindata-internal) 664 update_bindata_internal 665 ;; 666 update-generated) 667 vcmd "build/cmd.sh update-generated-internal" 668 docker exec virtlet-build \ 669 /bin/bash -c \ 670 "tar -C '${remote_project_dir}' -c $(find pkg/ -name 'zz_generated.*') pkg/client" | 671 tar -C "${project_dir}" -xv 672 ;; 673 update-generated-internal) 674 update_generated_internal 675 ;; 676 update-generated-docs) 677 vcmd "build/cmd.sh update-generated-docs-internal" 678 docker exec virtlet-build tar -C "${remote_project_dir}" -c docs/docs/reference/config.md docs/docs/reference/virtletctl.md | tar -C "${project_dir}" -xv 679 ;; 680 update-generated-docs-internal) 681 update_generated_docs_internal 682 ;; 683 run) 684 vcmd "$*" 685 ;; 686 vsh) 687 vsh 688 ;; 689 stop) 690 stop 691 ;; 692 clean) 693 clean 694 ;; 695 copy) 696 copy_output 697 ;; 698 copy-back) 699 copy_back 700 ;; 701 copy-dind) 702 VIRTLET_SKIP_RSYNC=y vcmd "build/cmd.sh copy-dind-internal" 703 ;; 704 e2e) 705 e2e "$@" 706 ;; 707 copy-dind-internal) 708 for virtlet_node in "${virtlet_nodes[@]}"; do 709 copy_dind_internal "${virtlet_node}" 710 done 711 ;; 712 prepare-all-nodes) 713 prepare_all_nodes 714 ;; 715 start-dind) 716 for virtlet_node in "${virtlet_nodes[@]}"; do 717 prepare_node "${virtlet_node}" 718 apply_runtime_label "${virtlet_node}" 719 done 720 start_dind 721 ;; 722 start-build-container) 723 ensure_build_container 724 ;; 725 release) 726 if [[ ! ${1:-} ]]; then 727 echo >&2 "must specify the tag" 728 exit 1 729 fi 730 ( vcmd "build/cmd.sh release-internal '${1}'" ) 731 ;; 732 release-internal) 733 release_internal "$@" 734 ;; 735 serve-docs-internal) 736 serve_docs_internal 737 ;; 738 serve-docs) 739 ( USE_TERM=1 vcmd "build/cmd.sh serve-docs-internal" ) 740 ;; 741 build-docs-internal) 742 build_docs_internal 743 ;; 744 build-docs) 745 build_docs 746 ;; 747 sync) 748 sync_source 749 ;; 750 *) 751 usage 752 ;; 753 esac 754 755 # TODO: make it possible to run e2e from within the build container, too 756 # (although we don't need to use that for CircleCI) 757 # TODO: fix indentation in this file (use 2 spaces)