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