.circleci/config.yml
version: 2.1
defaults: &defaults
docker:
- image: ubuntu:xenial
working_directory: ~/virtlet
environment:
DOCKER_VERSION: "17.03.0-ce"
KUBECTL_VERSION: "v1.9.3"
KUBECTL_SHA1: "a27d808eb011dbeea876fe5326349ed167a7ed28"
# remove DIND_CRI to use dockershim
DIND_CRI: containerd
# Uncomment the following to use ginkgo.focus for e2e
# E2E_FOCUS: "Specify a regexp.*here"
# The branch which is used for publishing docs
DOCS_SOURCE_BRANCH: master
prereqs: &prereqs
name: Install prerequisites
command: |
apt-get -qq update
apt-get install -y curl ca-certificates openssh-client rsync socat wget git
setup_env: &setup_env
name: Set up the environment
command: |
# Install Docker client
curl -sSL -o "/tmp/docker-${DOCKER_VERSION}.tgz" "https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz"
tar -xz -C /tmp -f "/tmp/docker-${DOCKER_VERSION}.tgz"
mv /tmp/docker/* /usr/bin
# Disable apparmor
docker run --rm --pid=host -it --privileged ubuntu:xenial \
nsenter -t 1 -m -u -i -n /bin/bash -c \
"service apparmor stop &&
service apparmor teardown &&
update-rc.d -f apparmor remove &&
apt-get remove -y apparmor"
# Start port forwarder
build/portforward.sh start
restore_image_cache: &restore_image_cache
name: Restore image cache
keys:
# bump '-vNNN' to update the cache (also everywhere this key is used in the file)
- images-v1-{{ checksum "images/Dockerfile.build-base" }}-{{ checksum "images/Dockerfile.virtlet-base" }}
restore_vendor_cache: &restore_vendor_cache
name: Restore vendor cache
keys:
# bump '-vNNN' to update the cache (also everywhere this key is used in the file)
- vendor-v1-{{ checksum "glide.yaml" }}-{{ checksum "glide.lock" }}
restore_images_and_vendor: &restore_images_and_vendor
name: Prepare build image & vendor dir
command: |
if [[ -f _output/images.tar ]]; then
docker load -i _output/images.tar
fi
if [[ -f _output/vendor.tar ]]; then
build/portforward.sh 18730&
build/cmd.sh start-build-container
docker exec -i virtlet-build tar -C /go/src/github.com/Mirantis/virtlet -xv <_output/vendor.tar
fi
extract_binaries_from_the_image: &extract_binaries_from_the_image
name: Extract binaries from the image (in non-workflow case)
command: |
if [[ -f _output/vmwrapper ]]; then
exit 0
fi
tag="$(echo "${CIRCLE_TAG:-${CIRCLE_BRANCH}}"|tr / _)"
image="mirantis/virtlet:${tag}"
echo "Extracting binaries from ${image}"
mkdir -p _output/
docker run "${image}" tar -C / -c vmwrapper virtlet-e2e-tests virtletctl | tar -C _output/ -xv
push_images: &push_images
<<: *defaults
steps:
- run:
<<: *prereqs
# the checkout is needed for getting cache key from dockerfiles
- checkout
- setup_remote_docker
- run:
name: Install Docker client
command: |
apt-get -qq update
apt-get install -y curl ca-certificates
curl -sSL -o "/tmp/docker-${DOCKER_VERSION}.tgz" "https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz"
tar -xz -C /tmp -f "/tmp/docker-${DOCKER_VERSION}.tgz"
mv /tmp/docker/* /usr/bin
- restore_cache:
<<: *restore_image_cache
- attach_workspace:
at: _output
- run:
name: Restore images
command: |
if [[ ! ${DOCKER_USER:-} || ! ${DOCKER_PASS} ]]; then
echo >&2 "*** WARNING: can't push images for outside forks"
exit 0
fi
docker load -i _output/virtlet.tar
if [[ -f _output/images.tar ]]; then
docker load -i _output/images.tar
fi
- run:
name: Retag the image
command: |
if [[ ! ${DOCKER_USER:-} || ! ${DOCKER_PASS} ]]; then
echo >&2 "*** WARNING: can't push images for outside forks"
exit 0
fi
tag="$(echo "${CIRCLE_TAG:-${CIRCLE_BRANCH}}"|tr / _)"
# we want to push 'latest' image for the master branch
if [[ ${tag} != master ]]; then
docker tag mirantis/virtlet:latest "mirantis/virtlet:${tag}"
docker rmi mirantis/virtlet:latest
fi
- run:
name: Push the images
command: |
if [[ ! ${DOCKER_USER:-} || ! ${DOCKER_PASS} ]]; then
echo >&2 "*** WARNING: can't push images for outside forks"
exit 0
fi
docker login -u $DOCKER_USER -p $DOCKER_PASS
for img in build-base virtlet-base virtlet; do
docker images -q -f label=virtlet.image="${img}" --format '{{.Repository}}:{{.Tag}}'
done | grep '^mirantis/virtlet' | while read img; do
echo >&2 "*** Pushing: ${img}"
docker push "${img}"
done
e2e: &e2e
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- attach_workspace:
at: _output
- run:
<<: *extract_binaries_from_the_image
- run:
name: Restore virtlet image
command: |
if [[ -f _output/virtlet.tar ]]; then
docker load -i _output/virtlet.tar
fi
- run:
name: Start the demo
command: |
build/portforward.sh 8080&
if [[ ${CIRCLE_JOB} = e2e_calico ]]; then
export CNI_PLUGIN=calico
echo >&2 "*** Using Calico CNI"
elif [[ ${CIRCLE_JOB} = e2e_flannel ]]; then
export CNI_PLUGIN=flannel
echo >&2 "*** Using Flannel CNI"
elif [[ ${CIRCLE_JOB} = e2e_weave ]]; then
export CNI_PLUGIN=weave
echo >&2 "*** Using Weave CNI"
elif [[ ${CIRCLE_JOB} = e2e_multi_cni ]]; then
export MULTI_CNI=1
echo >&2 "*** Using multiple CNIs (flannel + calico)"
elif [[ ${CIRCLE_JOB} = e2e_1_13 ]]; then
export KUBE_VERSION=1.13
fi
# APISERVER_PORT is set explicitly to avoid dynamic allocation
# of the port by kdc
APISERVER_PORT=8080 \
SKIP_SNAPSHOT=1 \
NONINTERACTIVE=1 \
NO_VM_CONSOLE=1 \
INJECT_LOCAL_IMAGE=1 \
VIRTLET_DEMO_BRANCH=master \
ENABLE_CEPH=1 \
DEMO_LOG_LEVEL=6 \
FEATURE_GATES="BlockVolume=true" \
KUBELET_FEATURE_GATES="BlockVolume=true" \
BASE_LOCATION="$PWD" \
deploy/demo.sh
- run:
name: Install kubectl
command: |
curl -L https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl
echo ${KUBECTL_SHA1} /usr/local/bin/kubectl |sha1sum -c
chmod +x /usr/local/bin/kubectl
- run:
name: Prepare all of the nodes for Virtlet pod
command: |
build/portforward.sh 8080&
VIRTLET_SKIP_RSYNC=1 build/cmd.sh prepare-all-nodes
- run:
name: Run e2e tests
command: |
build/portforward.sh 8080&
mkdir -p ~/junit
e2e_opts=("-ginkgo.skip=\[Heavy\]|\[MultiCNI\]|\[Disruptive\]|\[Flaky\]")
if [[ ${CIRCLE_JOB} = e2e_multi_cni ]]; then
# per-node config test requires an additional worker node
e2e_opts="-ginkgo.skip=\[Heavy\]|\[Disruptive\]|\[Flaky\]|Per-node configuration"
fi
if [[ ${E2E_FOCUS:-} ]]; then
e2e_opts+=("-ginkgo.focus=${E2E_FOCUS}")
fi
if [[ ${CIRCLE_JOB} = e2e_debian ]]; then
e2e_opts+=(-image cdimage.debian.org/cdimage/openstack/archive/9.8.0/debian-9.8.0-openstack-amd64.qcow2
-sshuser debian
-memoryLimit 256
-use-dhcp-network-config)
fi
_output/virtlet-e2e-tests -test.v "${e2e_opts[@]}" \
-junitOutput ~/junit/junit.xml \
-include-unsafe-tests=true
- store_test_results:
path: ~/junit
- run:
name: Dump the cluster state and display Virtlet version
when: always
command: |
build/portforward.sh 8080&
mkdir -p /tmp/cluster_state
bash -x ./dind-cluster*.sh dump | gzip >/tmp/cluster_state/kdc-dump.gz
_output/virtletctl diag dump --json | gzip >/tmp/cluster_state/virtlet-dump.json.gz
_output/virtletctl version
- store_artifacts:
path: /tmp/cluster_state
jobs:
prepare_build:
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- restore_cache:
<<: *restore_image_cache
- restore_cache:
<<: *restore_vendor_cache
- run:
name: Prepare images and the vendor dir
command: |
if [[ ! -f _output/images.tar || ! -f _output/vendor.tar ]]; then
build/portforward.sh 18730&
build/cmd.sh prepare-vendor
fi
- run:
name: Store base images
command: |
if [[ ! -f _output/images.tar ]]; then
mkdir -p _output
build_base_image="$(docker images -q -f label=virtlet.image=build-base --format '{{.Repository}}:{{.Tag}}')"
virtlet_base_image="$(docker images -q -f label=virtlet.image=virtlet-base --format '{{.Repository}}:{{.Tag}}')"
docker save "${build_base_image}" "${virtlet_base_image}" >_output/images.tar
fi
- save_cache:
name: Save image cache
key: images-v1-{{ checksum "images/Dockerfile.build-base" }}-{{ checksum "images/Dockerfile.virtlet-base" }}
paths:
- _output/images.tar
- run:
name: Store vendor archive
command: |
if [[ ! -f _output/vendor.tar ]]; then
mkdir -p _output
docker exec virtlet-build tar -C /go/src/github.com/Mirantis/virtlet -c vendor >_output/vendor.tar
fi
- save_cache:
name: Save vendor cache
key: vendor-v1-{{ checksum "glide.yaml" }}-{{ checksum "glide.lock" }}
paths:
- _output/vendor.tar
build:
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- restore_cache:
<<: *restore_image_cache
- restore_cache:
<<: *restore_vendor_cache
- run:
<<: *restore_images_and_vendor
- run:
name: Verify that the generated code for CRDs is up to date
command: |
build/portforward.sh 18730&
build/cmd.sh update-generated
if [[ $(git status --porcelain) ]]; then
git status
echo >&2 "Generated files out of sync, please run build/cmd.sh update-generated"
exit 1
fi
- run:
name: Build virtlet
command: |
build/portforward.sh 18730&
SET_VIRTLET_IMAGE_TAG="${CIRCLE_TAG:-}" build/cmd.sh build
build/cmd.sh copy
- run:
name: Save image
command: |
docker save mirantis/virtlet >_output/virtlet.tar
- persist_to_workspace:
root: _output
paths:
- virtlet.tar
- virtlet-e2e-tests
- virtletctl
- virtletctl.darwin
# needed by integration tests
- vmwrapper
- store_artifacts:
path: /go/src/github.com/Mirantis/virtlet/_output
destination: virtlet
test:
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- restore_cache:
<<: *restore_image_cache
- restore_cache:
<<: *restore_vendor_cache
- run:
<<: *restore_images_and_vendor
- run:
name: Run tests
command: |
build/portforward.sh 18730&
build/cmd.sh test
integration:
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- restore_cache:
<<: *restore_image_cache
- restore_cache:
<<: *restore_vendor_cache
- run:
<<: *restore_images_and_vendor
- attach_workspace:
at: _output
- run:
<<: *extract_binaries_from_the_image
- run:
name: Run tests
command: |
build/portforward.sh 18730&
rm -f _output/*.tar
build/cmd.sh copy-back
build/cmd.sh integration
e2e:
<<: *e2e
e2e_calico:
<<: *e2e
e2e_flannel:
<<: *e2e
e2e_weave:
<<: *e2e
e2e_multi_cni:
<<: *e2e
e2e_1_13:
<<: *e2e
e2e_debian:
<<: *e2e
push_branch:
<<: *push_images
push_tested:
<<: *push_images
build_docs:
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- restore_cache:
<<: *restore_image_cache
- run:
name: Update docs and push them to docs branch
command: |
build/portforward.sh 18730&
git config --global user.email bot@virtlet.cloud
git config --global user.name virtlet-bot
git fetch -f https://github.com/Mirantis/virtlet.git docs:docs
build/cmd.sh build-docs
if [[ ${CIRCLE_BRANCH:-} != ${DOCS_SOURCE_BRANCH} ]]; then
echo >&2 "Not updating docs branch: current branch is ${CIRCLE_BRANCH:-} not ${DOCS_SOURCE_BRANCH}"
elif [[ ! ${GITHUB_TOKEN:-} ]]; then
echo >&2 "Not updating docs branch: missing GITHUB_TOKEN env var"
else
# if the docs didn't change, this push will do nothing
git push https://${GITHUB_TOKEN}@github.com/Mirantis/virtlet.git docs:docs
fi
tar -czf /tmp/docs.tar.gz _docs
- store_artifacts:
path: /tmp/docs.tar.gz
release:
<<: *defaults
steps:
- run:
<<: *prereqs
- checkout
- setup_remote_docker
- run:
<<: *setup_env
- restore_cache:
<<: *restore_image_cache
- attach_workspace:
at: _output
- run:
<<: *restore_images_and_vendor
- run:
name: Make a release
command: |
build/portforward.sh 18730&
build/cmd.sh start-build-container
docker cp _output virtlet-build:/go/src/github.com/Mirantis/virtlet/
build/cmd.sh release "${CIRCLE_TAG}"
workflows:
version: 2
build-and-test:
jobs:
- prepare_build:
filters:
tags:
only: /^v[0-9].*/
- build:
requires:
- prepare_build
filters:
branches:
ignore: /^.*-docs$/
tags:
only: /^v[0-9].*/
- test:
requires:
- prepare_build
filters:
branches:
ignore: /^.*-docs$/
tags:
only: /^v[0-9].*/
- integration:
requires:
- build
filters:
branches:
ignore: /^.*-docs$/
tags:
only: /^v[0-9].*/
- e2e:
requires:
- build
filters:
branches:
ignore: /^.*-docs$/
tags:
only: /^v[0-9].*/
- e2e_calico:
requires:
- build
filters:
branches:
ignore: /^.*-docs$/
tags:
only: /^v[0-9].*/
- e2e_flannel:
requires:
- build
filters:
branches:
only: /^master$|^.*-net$/
tags:
only: /^v[0-9].*/
- e2e_weave:
requires:
- build
filters:
branches:
only: /^master$|^.*-net$/
tags:
only: /^v[0-9].*/
# XXX: temporarily disabled, to be fixed
# - e2e_multi_cni:
# requires:
# - build
# filters:
# branches:
# only: /^master$|^.*-net$|^.*-ext-e2e$/
# tags:
# only: /^v[0-9].*/
- e2e_1_13:
requires:
- build
filters:
branches:
ignore: /^.*-docs$/
tags:
only: /^v[0-9].*/
- e2e_debian:
requires:
- build
filters:
branches:
only: /^master$|^.*-ext-e2e$/
tags:
only: /^v[0-9].*/
- push_branch:
requires:
- build
filters:
branches:
ignore: /^master$|^pull\/|^.*-docs$/
- push_tested:
requires:
- test
- e2e
- e2e_calico
- e2e_flannel
- e2e_weave
# XXX: temporarily disabled, to be fixed
# - e2e_multi_cni
- e2e_1_13
- e2e_debian
- integration
filters:
branches:
only: master
tags:
only: /^v[0-9].*/
- release:
requires:
- push_tested
filters:
branches:
ignore: /.*/
tags:
only: /^v[0-9].*/
- build_docs:
requires:
- prepare_build