Adding a plugin¶
In this section, we provide instructions for creating a new plugin for the BugZoo platform. Plugins are used to dynamically provide binaries, libraries and static data to containers at run-time. Plugins are packaged as Docker container images and provided to BugZoo as part of a manifest file belonging to a source. The manifest file provides instructions for building the Docker image for the plugin and specifies how it should be imported into a running bug container.
Note
Before adding your plugin, you must first create a source that will provide it.
Writing a Dockerfile¶
Each plugin is accompanied by a Docker container image that is responsible for
providing the libraries, binaries and static data required to run the plugin
inside a separate container.
BugZoo uses a Dockerfile
to provide instructions for building the Docker
container image for your plugin. Below, we give an example Dockerfile
that is used to provide a genprog
plugin for BugZoo, which is
explained in more detail below.
FROM ubuntu:16.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
opam \
ocaml \
build-essential \
jq \
aspcud \
vim \
m4 && \
echo "yes" >> /tmp/yes.txt && \
opam init -y < /tmp/yes.txt && \
opam install -y cil
# all files required to run genprog are written to /opt/genprog
RUN mkdir -p /opt/genprog
WORKDIR /opt/genprog
ADD Makefile Makefile
ADD src src
RUN mkdir bin && \
eval $(opam config env) && \
make && \
mv src/repair bin/genprog && \
ln -s bin/genprog bin/repair && \
mv src/distserver bin/distserver && \
mv src/nhtserver bin/nhtserver
VOLUME /opt/genprog
The process for writing a Dockerfile
for your plugin is almost the same
as writing another other Dockerfile
. The Dockerfile should provide
executable instructions for building the binaries and libraries for your
software. There are however, a number of important differences. Firstly, all of
the files that are required by your plugin must be stored inside a volume
that can be mounted inside another container. In the example above, all of the
files required to run GenProg are written to /opt/genprog
, which is
subsequently declared to be a volume:
VOLUME /opt/genprog
In general, we recommend installing the files for your plugin to
/opt/myplugin
, where myplugin
is replaced by the name of your
plugin.
Simply installing the files for your plugin to /opt/myplugin
is
usually not enough, however. The binaries and libraries for your plugin may
be dynamically linked to system libraries that are not present in other
containers into which they may be mounted. (Worse yet, the container
may use an older, incompatible libc
or ld
.)
To ensure compatibility, you must package your plugin as a static binary.
Whilst some languages will automatically compile their programs to static
binaries by default (e.g., Go), others will require special build options
to produce a static binary (e.g., C and C++). Below we provide tips for
creating static binaries with minimal effort:
- C/C++ and OCaml:
Whilst compilation options are the preferred way to create a static binary, StaticX can be used to transform a dynamically linked binary into a static one, allowing it to be used in any container.
- Go:
Go produces static binaries by default.
- Python:
PyInstaller can be used to package your application, including its dependencies and files, into a single executable file. The resulting binary will still be dynamically linked to
libc
andld
, however, so StaticX must be used to wrap the binary into a truly static one.
Writing a plugin manifest¶
Now that you’ve written a Dockerfile
for building a Docker image for
your plugin, you need to write a manifest file for your plugin in order to
register it with BugZoo. BugZoo automatically scans its source for all files
ending in .bugzoo.yml
and treats them as manifest files. Let’s create
a new file named myplugin.bugzoo.yml
to serve as the manifest file for
the plugin.
The manifest file is written in YAML and should start with a version
property, specifying the version of the BugZoo Manifest File Format that is
used by the file. For more details on the file format, see here.
The blueprints
section of the file is used to provide instructions for
building an image. The tag
property specifies the qualified name of the
Docker image that should be built for the plugin. The file
property
gives the location of the Dockerfile
(relative to the location of the
manifest file) that should be used to build the Docker image.
The plugins
section of the file declares the plugin to BugZoo.
The name
property gives a unique name for the plugin.
The image
property specifies the Docker image that should be used to
provide the files for the plugin.
The environment
property is used to manipulate the values of
environment variables inside a container upon loading the plugin. This property
is commonly used to extend the PATH
to include the static binaries for
the plugin.
version: '1.1'
blueprints:
- tag: squareslab/genprog
file: Dockerfile
plugins:
- name: genprog
image: squareslab/genprog
environment:
PATH: "/opt/genprog/bin:${PATH}"
Example plugins¶
Below, we briefly describe a number of real-world plugins for BugZoo.
GenProg: A search-based program repair tool, written in OCaml.
Kaskara: A static analysis tool for C++, written in C++. Depends on Clang/LLVM.
SOSRepair: A semantics-based program repair tool, written in Python and C. Depends on two different versions of Clang/LLVM.