Mirantis/virtlet

View on GitHub
.circleci/config.yml

Summary

Maintainability
Test Coverage
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