name: kata-containers
website: https://github.com/kata-containers/kata-containers
summary: Build lightweight VMs that seamlessly plug into the containers ecosystem
description: |
  Kata Containers is an open source project and community working to build a
  standard implementation of lightweight Virtual Machines (VMs) that feel and
  perform like containers, but provide the workload isolation and security
  advantages of VMs
confinement: classic
adopt-info: metadata
base: core20

parts:
  metadata:
    plugin: nil
    prime:
      - -*
    build-packages:
      - git
      - git-extras
    override-pull: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      version="9999"

      if echo "${GITHUB_REF:-}" | grep -q -E "^refs/tags"; then
        version=$(echo ${GITHUB_REF:-} | cut -d/ -f3)
        git checkout ${version}
      fi

      snapcraftctl set-grade "stable"
      snapcraftctl set-version "${version}"

      mkdir -p $(dirname ${kata_dir})
      ln -sf $(realpath "${SNAPCRAFT_STAGE}/..") ${kata_dir}

  godeps:
    after: [metadata]
    plugin: nil
    prime:
      - -*
    build-packages:
      - curl
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      # put everything in stage
      cd "${SNAPCRAFT_STAGE}"

      version="$(${yq} r ${kata_dir}/versions.yaml languages.golang.meta.newest-version)"
      tarfile="go${version}.${goos}-${goarch}.tar.gz"
      curl -LO https://golang.org/dl/${tarfile}
      tar -xf ${tarfile} --strip-components=1

  rustdeps:
    after: [metadata]
    plugin: nil
    prime:
      - -*
    build-packages:
      - curl
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      # put everything in stage
      cd "${SNAPCRAFT_STAGE}"

      version="$(${yq} r ${kata_dir}/versions.yaml languages.rust.meta.newest-version)"
      if ! command -v rustup > /dev/null; then
        curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${version}
      fi

      export PATH=${PATH}:${HOME}/.cargo/bin
      rustup toolchain install ${version}
      rustup default ${version}
      if [ "${arch}" == "ppc64le" ] || [ "${arch}" == "s390x" ] ; then
        [ "${arch}" == "ppc64le" ] && arch="powerpc64le"
        rustup target add ${arch}-unknown-linux-gnu
      else
        rustup target add ${arch}-unknown-linux-musl
        $([ "$(whoami)" != "root" ] && echo sudo) ln -sf /usr/bin/g++ /bin/musl-g++
      fi
      rustup component add rustfmt

  docker:
    after: [metadata]
    plugin: nil
    prime:
      - -*
    build-packages:
      - ca-certificates
      - containerd
      - curl
      - gnupg
      - lsb-release
      - runc
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      curl -fsSL https://download.docker.com/linux/ubuntu/gpg |\
          sudo gpg --batch --yes --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
      distro_codename=$(lsb_release -cs)
      echo "deb [arch=${dpkg_arch} signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu ${distro_codename} stable" |\
          sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
      sudo apt-get -y update
      sudo apt-get -y install docker-ce docker-ce-cli containerd.io

      echo "Unmasking docker service"
      sudo -E systemctl unmask docker.service || true
      sudo -E systemctl unmask docker.socket || true
      echo "Adding $USER into docker group"
      sudo -E gpasswd -a $USER docker
      echo "Starting docker"
      sudo -E systemctl start docker || true

  image:
    after: [godeps, docker, qemu, kernel]
    plugin: nil
    build-packages:
      - docker.io
      - cpio
      - git
      - iptables
      - software-properties-common
      - uidmap
      - gnupg2
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      [ "${arch}" = "ppc64le" ] || [ "${arch}" = "s390x" ] && sudo apt-get --no-install-recommends install -y protobuf-compiler

      if [ -n "$http_proxy" ]; then
        echo "Setting proxy $http_proxy"
        sudo -E systemctl set-environment http_proxy="$http_proxy" || true
        sudo -E systemctl set-environment https_proxy="$https_proxy" || true
      fi

      # Copy yq binary. It's used in the container
      cp -a "${yq}" "${GOPATH}/bin/"

      cd "${kata_dir}/tools/osbuilder"

      # build image
      export AGENT_INIT=yes
      export USE_DOCKER=1
      export DEBUG=1
      initrd_distro=$(${yq} r -X ${kata_dir}/versions.yaml assets.initrd.architecture.${arch}.name)
      image_distro=$(${yq} r -X ${kata_dir}/versions.yaml assets.image.architecture.${arch}.name)
      case "$arch" in
        x86_64)
          # In some build systems it's impossible to build a rootfs image, try with the initrd image
          sudo -E PATH=$PATH make image DISTRO="${image_distro}" || sudo -E PATH="$PATH" make initrd DISTRO="${initrd_distro}"
        ;;

        aarch64|ppc64le|s390x)
          sudo -E PATH="$PATH" make initrd DISTRO="${initrd_distro}"
        ;;

        *) die "unsupported architecture: ${arch}" ;;
      esac

      # Install image
      kata_image_dir="${SNAPCRAFT_PART_INSTALL}/usr/share/kata-containers"
      mkdir -p "${kata_image_dir}"
      cp kata-containers*.img "${kata_image_dir}"

  runtime:
    after: [godeps, image, cloud-hypervisor]
    plugin: nil
    build-attributes: [no-patchelf]
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      cd "${kata_dir}/src/runtime"

      qemu_cmd="qemu-system-${qemu_arch}"

      # build and install runtime
      make \
        PREFIX="/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr" \
        SKIP_GO_VERSION_CHECK=1 \
        QEMUCMD="${qemu_cmd}"

      make install \
        PREFIX=/usr \
        DESTDIR="${SNAPCRAFT_PART_INSTALL}" \
        SKIP_GO_VERSION_CHECK=1 \
        QEMUCMD="${qemu_cmd}"

      if [ ! -f ${SNAPCRAFT_PART_INSTALL}/../../image/install/usr/share/kata-containers/kata-containers.img ]; then
        sed -i -e "s|^image =.*|initrd = \"/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr/share/kata-containers/kata-containers-initrd.img\"|" \
          ${SNAPCRAFT_PART_INSTALL}/usr/share/defaults/${SNAPCRAFT_PROJECT_NAME}/configuration.toml
      fi

  kernel:
    after: [godeps]
    plugin: nil
    build-packages:
      - libelf-dev
      - curl
      - build-essential
      - bison
      - flex
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      kernel_version="$(${yq} r $versions_file assets.kernel.version)"
      #Remove extra 'v'
      kernel_version="${kernel_version#v}"

      [ "${arch}" = "s390x" ] && sudo apt-get --no-install-recommends install -y libssl-dev

      cd "${kata_dir}/tools/packaging/kernel"
      kernel_dir_prefix="kata-linux-"

      # Setup and build kernel
      ./build-kernel.sh -v "${kernel_version}" -d setup
      cd ${kernel_dir_prefix}*
      make -j $(nproc ${CI:+--ignore 1}) EXTRAVERSION=".container"

      kernel_suffix="${kernel_version}.container"
      kata_kernel_dir="${SNAPCRAFT_PART_INSTALL}/usr/share/kata-containers"
      mkdir -p "${kata_kernel_dir}"

      # Install bz kernel
      make install INSTALL_PATH="${kata_kernel_dir}" EXTRAVERSION=".container" || true
      vmlinuz_name="vmlinuz-${kernel_suffix}"
      ln -sf "${vmlinuz_name}" "${kata_kernel_dir}/vmlinuz.container"

      # Install raw kernel
      vmlinux_path="vmlinux"
      [ "${arch}" = "s390x" ] && vmlinux_path="arch/s390/boot/vmlinux"
      vmlinux_name="vmlinux-${kernel_suffix}"
      cp "${vmlinux_path}" "${kata_kernel_dir}/${vmlinux_name}"
      ln -sf "${vmlinux_name}" "${kata_kernel_dir}/vmlinux.container"

  qemu:
    plugin: make
    after: [godeps]
    build-packages:
      - gcc
      - python3
      - zlib1g-dev
      - libcap-ng-dev
      - libglib2.0-dev
      - libpixman-1-dev
      - libnuma-dev
      - libltdl-dev
      - libcap-dev
      - libattr1-dev
      - libfdt-dev
      - curl
      - libcapstone-dev
      - bc
      - libblkid-dev
      - libffi-dev
      - libmount-dev
      - libseccomp-dev
      - libselinux1-dev
      - ninja-build
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      branch="$(${yq} r ${versions_file} assets.hypervisor.qemu.version)"
      url="$(${yq} r ${versions_file} assets.hypervisor.qemu.url)"
      commit=""
      patches_dir="${kata_dir}/tools/packaging/qemu/patches/$(echo ${branch} | sed -e 's/.[[:digit:]]*$//' -e 's/^v//').x"
      patches_version_dir="${kata_dir}/tools/packaging/qemu/patches/tag_patches/${branch}"

      # download source
      qemu_dir="${SNAPCRAFT_STAGE}/qemu"
      rm -rf "${qemu_dir}"
      git clone --depth 1 --branch ${branch} --single-branch ${url} "${qemu_dir}"
      cd "${qemu_dir}"
      [ -z "${commit}" ] || git checkout "${commit}"

      [ -n "$(ls -A ui/keycodemapdb)" ] || git clone --depth 1 https://github.com/qemu/keycodemapdb ui/keycodemapdb/
      [ -n "$(ls -A capstone)" ] || git clone --depth 1 https://github.com/qemu/capstone capstone

      # Apply branch patches
      [ -d "${patches_version_dir}" ] || mkdir "${patches_version_dir}"
      ${kata_dir}/tools/packaging/scripts/apply_patches.sh "${patches_dir}"
      ${kata_dir}/tools/packaging/scripts/apply_patches.sh "${patches_version_dir}"

      # Only x86_64 supports libpmem
      [ "${arch}" = "x86_64" ] && sudo apt-get --no-install-recommends install -y apt-utils ca-certificates libpmem-dev

      configure_hypervisor="${kata_dir}/tools/packaging/scripts/configure-hypervisor.sh"
      chmod +x "${configure_hypervisor}"
      # static build. The --prefix, --libdir, --libexecdir, --datadir arguments are
      # based on PREFIX and set by configure-hypervisor.sh
      echo "$(PREFIX=/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr ${configure_hypervisor} -s kata-qemu) \
        --disable-rbd " \
        | xargs ./configure

      # Copy QEMU configurations (Kconfigs)
      case "${branch}" in
      "v5.1.0")
        cp -a "${kata_dir}"/tools/packaging/qemu/default-configs/* default-configs
        ;;

      *)
        cp -a "${kata_dir}"/tools/packaging/qemu/default-configs/* configs/devices/
        ;;
      esac

      # build and install
      make -j $(nproc ${CI:+--ignore 1})
      make install DESTDIR="${SNAPCRAFT_PART_INSTALL}"
    prime:
      - -snap/
      - -usr/bin/qemu-ga
      - -usr/bin/qemu-pr-helper
      - -usr/bin/virtfs-proxy-helper
      - -usr/include/
      - -usr/share/applications/
      - -usr/share/icons/
      - -usr/var/
      - usr/*
      - lib/*
    organize:
      # Hack: move qemu to /
      "snap/kata-containers/current/": "./"

  virtiofsd:
    plugin: nil
    after: [godeps, rustdeps, docker]
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      echo "INFO: Building rust version of virtiofsd"

      cd "${SNAPCRAFT_PROJECT_DIR}"
      # Clean-up build dir in case it already exists
      sudo -E NO_TTY=true make virtiofsd-tarball

      sudo install \
        --owner='root' \
        --group='root' \
        --mode=0755 \
        -D \
        --target-directory="${SNAPCRAFT_PART_INSTALL}/usr/libexec/" \
        build/virtiofsd/builddir/virtiofsd/virtiofsd

  cloud-hypervisor:
    plugin: nil
    after: [godeps, docker]
    override-build: |
      source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"

      if [ "${arch}" == "aarch64" ] || [ "${arch}" == "x86_64" ]; then
          cd "${SNAPCRAFT_PROJECT_DIR}"
          sudo -E NO_TTY=true make cloud-hypervisor-tarball

          tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-cloud-hypervisor.tar.xz"
          tmpdir=$(mktemp -d)

          tar -xvJpf "${tarfile}" -C "${tmpdir}"

          install -D "${tmpdir}/opt/kata/bin/cloud-hypervisor" "${SNAPCRAFT_PART_INSTALL}/usr/bin/cloud-hypervisor"

          rm -rf "${tmpdir}"
      fi

apps:
  runtime:
    command: usr/bin/kata-runtime
  shim:
    command: usr/bin/containerd-shim-kata-v2
  collect-data:
    command: usr/bin/kata-collect-data.sh
