Build pvr package artifacts using container-ci

Intro

A Pantavisor-enabled device uses the pvr cli to manage the device revisions, from there, you can add applications and manage those applications. And the way that pvr uses share packages or parts of your device is by using the pvr export command. That allows you to create a tar gzip file that contains the objects and the JSON state that defines the whole revision or parts of that revision.

For now, we can call that tar.gz file pvpackage or pvpkg, those packages can be imported into another device to bring all that is needed to run that package inside pantavisor.

Because Pantavisor has more configurations than the docker container from when is built. We use src.json as the spec for all the configurations that need it to run something in pantavisor. This is the spec for the full src.json file.

How to take advantage of pvpkgs

Now we can take advantage of those pvpkg by using container-ci. This utility repository will allow you to build packages in development to be exported and installed on the device using the pvtx app. If you have pvr-sdk installed on your device you can access this feature by using, http://DEVICE_IP:12368/app/.

Let’s take this repository as an example:

In here we have a very simple go application exposing in the port 5000 a web server that shows the details about the revision running on the device.

Building your pvpkgs

In the repository where you have your application and your Dockerfile add container-ci as a submodule

git submodule add https://gitlab.com/pantacor/ci/container-ci.git

After that, you can create the configurations for your container using:

./container-ci/pvpkg_install -p DOCKER_PLATFORM docker_image:docker_tag plaform_name
Usage:
pvpkg_install [options] image:tag appname
pvpkg_install will use the platforms in your container-ci.conf.
For more information see container-ci/mkdocker.sh --help
  -p same platform argument as docker --platform (optional)

Example:

./container-ci/pvpkg_install -p linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/mips,linux/riscv64 registry.gitlab.com/pantacor/pantavisor-web-status:master pvwebstatus

This is going to create a pvpkg folder with this structure:

pvpkg/
├── amd64
│   └── pvwebstatus
│       └── src.json
├── arm32v6
│   └── pvwebstatus
│       └── src.json
├── arm32v7
│   └── pvwebstatus
│       └── src.json
├── arm64v8
│   └── pvwebstatus
│       └── src.json
├── mips
│   └── pvwebstatus
│       └── src.json
└── riscv64
    └── pvwebstatus
        └── src.json

Where the src.json inside every pvwebstatus folder will be something like this:

{
  "#spec": "service-manifest-src@1",
  "template": "builtin-lxc-docker",
  "docker_name": "registry.gitlab.com/pantacor/pantavisor-web-status",
  "docker_tag": "master",
  "docker_source": "remote,local",
  "docker_platform": "linux/amd64"
}

and it will create a pvpkg.json in the root of the project with this structure.

{
  "name": "pvwebstatus",
  "version": "v0.0.1"
}

we could add extra parameters to be used in pvr app add at the end of the pvpkg_install command.

Example:

./container-ci/pvpkg_install -p linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/mips,linux/riscv64 registry.gitlab.com/pantacor/pantavisor-web-status:master pvwebstatus --group system

after this we could use the build_exports to create all the packages for different architectures.

./container-ci/build_exports

And that will create the pvr folders and the pvr export of all the architectures selected.

releases/
├── amd64
│   ├── pvwebstatus
│   │   ├── lxc.container.conf
│   │   ├── root.squashfs
│   │   ├── root.squashfs.docker-digest
│   │   ├── run.json
│   │   └── src.json
│   └── _sigs
│       └── pvwebstatus.json
├── arm32v6
│   ├── pvwebstatus
│   │   ├── lxc.container.conf
│   │   ├── root.squashfs
│   │   ├── root.squashfs.docker-digest
│   │   ├── run.json
│   │   └── src.json
│   └── _sigs
│       └── pvwebstatus.json
├── arm32v7
│   ├── pvwebstatus
│   │   ├── lxc.container.conf
│   │   ├── root.squashfs
│   │   ├── root.squashfs.docker-digest
│   │   ├── run.json
│   │   └── src.json
│   └── _sigs
│       └── pvwebstatus.json
├── arm64v8
│   ├── pvwebstatus
│   │   ├── lxc.container.conf
│   │   ├── root.squashfs
│   │   ├── root.squashfs.docker-digest
│   │   ├── run.json
│   │   └── src.json
│   └── _sigs
│       └── pvwebstatus.json
├── mips
│   ├── pvwebstatus
│   │   ├── lxc.container.conf
│   │   ├── root.squashfs
│   │   ├── root.squashfs.docker-digest
│   │   ├── run.json
│   │   └── src.json
│   └── _sigs
│       └── pvwebstatus.json
└── riscv64
    ├── pvwebstatus
    │   ├── lxc.container.conf
    │   ├── root.squashfs
    │   ├── root.squashfs.docker-digest
    │   ├── run.json
    │   └── src.json
    └── _sigs
        └── pvwebstatus.json
├── pvwebstatus-v0.0.1-0-g7ab223a.amd64.tgz
├── pvwebstatus-v0.0.1-0-g7ab223a.arm32v6.tgz
├── pvwebstatus-v0.0.1-0-g7ab223a.arm32v7.tgz
├── pvwebstatus-v0.0.1-0-g7ab223a.arm64v8.tgz
├── pvwebstatus-v0.0.1-0-g7ab223a.mips.tgz
├── pvwebstatus-v0.0.1-0-g7ab223a.riscv64.tgz

The template for the package name will be

${PACKAGE_NAME}-${PACKAGE_VERSION}-${BUILD_VERSION}.${ARCH}.tgz

The default values of those variables are:

  • PACKAGE_NAME: “name” key inside the pvpkg.json
  • PACKAGE_VERSION: “version” key inside the pvpkg.json
  • BUILD_VERSION: 0-COUNT-gSHORTREV (git info)
  • ARCH: the platform arch