# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Dockerfile for running a specific benchmark for a specific fuzzer.
#
# This Dockerfile adds essential files into the runner image, regardless of
# whether it was built from `benchmark-runner/Dockerfile` or a custom
# `runner.Dockerfile`.
#
# The benchmark/fuzzer pair is defined by build arguments. To specify them, pass
# the following arguments to docker build:
#
# $ docker build \
#   --build-arg benchmark=afl \
#   --build-arg fuzzer=freetype2-2017 \
#   ...

ARG fuzzer
ARG benchmark

# We use Docker's multi-stage build feature to create a minimal runner image,
# separate from the sometimes bulky builder images.

# We take the already built builder image for the given fuzzer/benchmark pair
# and refer to it as "builder", so we can copy the build artifacts from it.
FROM gcr.io/fuzzbench/builders/$fuzzer/$benchmark AS builder

# We base the runner image from the intermediate runner image, defined by the
# runner.Dockerfile of each fuzzer.
FROM gcr.io/fuzzbench/runners/$fuzzer/$benchmark-intermediate

# Install runtime dependencies for benchmarks.

RUN apt-get update -y && apt-get install -y \
    libglib2.0-0 \
    libxml2 \
    libarchive13 \
    libgss3

# Set up the directory for the build artifacts.
ENV OUT /out
ENV WORKDIR /out
RUN mkdir -p $WORKDIR
WORKDIR $WORKDIR

# The argument needs to be re-declared otherwise it returns an empty string.
ARG fuzzer

# Copy over all the build artifacts (without * to preserve directory structure).
# This also copies seed and dictionary files if they are available.
COPY --from=builder /out/ ./
# Copy the fuzzer.py file.
COPY fuzzers/$fuzzer/fuzzer.py .
# Copy the fuzzers directory.
COPY fuzzers/ ./fuzzers
# Create empty __init__.py to allow python deps to work.
RUN touch __init__.py

# Define environment variables used when we run the fuzzer:
# - Directory to get starting seeds from.
ENV SEED_CORPUS_DIR=$WORKDIR/seeds
# - Where to place new test cases generated by the fuzzer.
ENV OUTPUT_CORPUS_DIR=$WORKDIR/corpus

# Create the seeds directory if it doesn't exist.
RUN mkdir -p $SEED_CORPUS_DIR $OUTPUT_CORPUS_DIR

# Copy the source code into the image. We do this here instead of in base-image
# because it is likely to change, particularly in development. If this were done
# earlier, build cycles would be intolerably slow.
ENV ROOT_DIR=/src
COPY common $ROOT_DIR/common
COPY experiment/runner.py $ROOT_DIR/experiment/runner.py
COPY docker/benchmark-runner $ROOT_DIR/docker/benchmark-runner

ENV PYTHONPATH=$ROOT_DIR

# |VIRTUALENV_DIR| is set so that python code can know the location of current
# virtualenv directory and strip it if needed to execute in system python
# environment.
ENV VIRTUALENV_DIR=$ROOT_DIR/.venv
RUN virtualenv --python=$(which python3) $VIRTUALENV_DIR
RUN /bin/bash -c "source $VIRTUALENV_DIR/bin/activate && \
    pip3 install -r $ROOT_DIR/docker/benchmark-runner/requirements.txt"
RUN chmod +x $ROOT_DIR/docker/benchmark-runner/startup-runner.sh
ENTRYPOINT $ROOT_DIR/docker/benchmark-runner/startup-runner.sh
