From 6590e3da1791bcfb628e44f94229934b5d830c9f Mon Sep 17 00:00:00 2001 From: Marco Primi Date: Tue, 30 Jul 2024 15:49:03 -0700 Subject: [PATCH] Setup Antithesis --- .../antithesis-build-latest-images.yml | 79 +++++++++++++++ .../antithesis-run-experiment-custom.yml | 80 ++++++++++++++++ .../workflows/antithesis-run-experiment.yml | 40 ++++++++ .../antithesis-test-pull-request.yml | 22 +++++ antithesis/Makefile | 33 +++++++ antithesis/config/Dockerfile | 7 ++ antithesis/config/buildinfo | 3 + antithesis/config/docker-compose.yml | 87 +++++++++++++++++ antithesis/config/environment | 6 ++ antithesis/config/version | 3 + antithesis/scripts/buildinfo.sh | 41 ++++++++ antithesis/scripts/launch_experiment.sh | 95 +++++++++++++++++++ antithesis/system-under-test/Dockerfile | 51 ++++++++++ antithesis/system-under-test/buildinfo | 3 + antithesis/system-under-test/version | 3 + antithesis/workload/Dockerfile | 51 ++++++++++ antithesis/workload/buildinfo | 3 + antithesis/workload/version | 3 + 18 files changed, 610 insertions(+) create mode 100644 .github/workflows/antithesis-build-latest-images.yml create mode 100644 .github/workflows/antithesis-run-experiment-custom.yml create mode 100644 .github/workflows/antithesis-run-experiment.yml create mode 100644 .github/workflows/antithesis-test-pull-request.yml create mode 100644 antithesis/Makefile create mode 100644 antithesis/config/Dockerfile create mode 100644 antithesis/config/buildinfo create mode 100644 antithesis/config/docker-compose.yml create mode 100644 antithesis/config/environment create mode 100644 antithesis/config/version create mode 100755 antithesis/scripts/buildinfo.sh create mode 100755 antithesis/scripts/launch_experiment.sh create mode 100644 antithesis/system-under-test/Dockerfile create mode 100644 antithesis/system-under-test/buildinfo create mode 100644 antithesis/system-under-test/version create mode 100644 antithesis/workload/Dockerfile create mode 100644 antithesis/workload/buildinfo create mode 100644 antithesis/workload/version diff --git a/.github/workflows/antithesis-build-latest-images.yml b/.github/workflows/antithesis-build-latest-images.yml new file mode 100644 index 0000000..e2ace89 --- /dev/null +++ b/.github/workflows/antithesis-build-latest-images.yml @@ -0,0 +1,79 @@ +name: "Build and publish 'latest' Images" + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + workflow_dispatch: + push: + branches: [ "main" ] + +env: + # REGISTRY_URL: ${{ secrets.ANTITHESIS_REGISTRY_URL }} + # REGISTRY_REPOSITORY: ${{ secrets.ANTITHESIS_REPOSITORY }} + # REGISTRY_LOGIN: ${{ secrets.ANTITHESIS_REGISTRY_LOGIN }} + SUT_IMAGE: raft_sut + WORKLOAD_IMAGE: raft_workload + CONFIG_IMAGE: raft_config + IMAGES_TAG: latest + NATS_UPSTREAM_IMAGE: nats + NATS_UPSTREAM_TAG: latest + NATS_IMAGE: nats_server + NATS_TAG: latest + GIT_TAG: antithesis/latest + +jobs: + build: + runs-on: ubuntu-latest + # Allow this workflow to push + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Login to Antithesis Docker Registry + uses: docker/login-action@v3 + with: + registry: ${{ secrets.ANTITHESIS_REGISTRY_URL }} + username: _json_key + password: ${{ secrets.ANTITHESIS_REGISTRY_LOGIN }} + + - name: Populate buildinfo and version files + run: ./antithesis/scripts/buildinfo.sh + + - name: Build, tag SUT image + timeout-minutes: 100 + run: | + docker build -f ./antithesis/system-under-test/Dockerfile -t ${SUT_IMAGE}:${IMAGES_TAG} . + docker tag ${SUT_IMAGE}:${IMAGES_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${SUT_IMAGE}:${IMAGES_TAG} + + - name: Build, tag workload image + run: | + docker build -f ./antithesis/workload/Dockerfile -t ${WORKLOAD_IMAGE}:${IMAGES_TAG} . + docker tag ${WORKLOAD_IMAGE}:${IMAGES_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${WORKLOAD_IMAGE}:${IMAGES_TAG} + + - name: Build tag config image + run: | + docker build -f ./antithesis/config/Dockerfile -t ${CONFIG_IMAGE}:${IMAGES_TAG} . + docker tag ${CONFIG_IMAGE}:${IMAGES_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${CONFIG_IMAGE}:${IMAGES_TAG} + + - name: Pull and tag upstream nats-server image + run: | + docker pull ${NATS_UPSTREAM_IMAGE}:${NATS_UPSTREAM_TAG} + docker tag ${NATS_UPSTREAM_IMAGE}:${NATS_UPSTREAM_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${NATS_IMAGE}:${NATS_TAG} + + - name: Publish images + run: | + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${SUT_IMAGE}:${IMAGES_TAG} + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${WORKLOAD_IMAGE}:${IMAGES_TAG} + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${CONFIG_IMAGE}:${IMAGES_TAG} + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${NATS_IMAGE}:${NATS_TAG} + + - name: Update git tag tracking the latest images + run: | + git tag -f ${{ env.GIT_TAG }} + git push -f origin ${{ env.GIT_TAG }} diff --git a/.github/workflows/antithesis-run-experiment-custom.yml b/.github/workflows/antithesis-run-experiment-custom.yml new file mode 100644 index 0000000..a88ab7b --- /dev/null +++ b/.github/workflows/antithesis-run-experiment-custom.yml @@ -0,0 +1,80 @@ +name: "Experiment with custom-branch images" + +env: + ANTITHESIS_WEBOOK_TOKEN: ${{ secrets.ANTITHESIS_WEBOOK_TOKEN }} + ANTITHESIS_WEBOOK_URL: ${{ secrets.ANTITHESIS_WEBOOK_URL }} + ANTITHESIS_WEBOOK_USERNAME: ${{ secrets.ANTITHESIS_WEBOOK_USERNAME }} + SUT_IMAGE: raft_sut + WORKLOAD_IMAGE: raft_workload + CONFIG_IMAGE: raft_config + IMAGES_TAG: custom_${{ github.triggering_actor }}_${{ github.run_number }} + NATS_UPSTREAM_IMAGE: nats + NATS_UPSTREAM_TAG: latest + NATS_IMAGE: nats_server + NATS_TAG: latest + +on: + workflow_dispatch: + inputs: + duration: + description: 'Duration (fuzzing hours)' + required: true + type: string + default: "1.0" + description: + description: 'Experiment description (avoid quotes, please!)' + required: true + type: string + default: "No description provided" + email: + description: 'Additional email notification recipient (separate with ;)' + required: false + type: string + default: "" + +jobs: + build-publish-and-trigger-experiment: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Populate buildinfo and version files + run: ./antithesis/scripts/buildinfo.sh + + - name: Login to Antithesis Docker Registry + uses: docker/login-action@v3 + with: + registry: ${{ secrets.ANTITHESIS_REGISTRY_URL }} + username: _json_key + password: ${{ secrets.ANTITHESIS_REGISTRY_LOGIN }} + + - name: Build, tag SUT image + run: | + docker build -f ./antithesis/system-under-test/Dockerfile -t ${SUT_IMAGE}:${IMAGES_TAG} . + docker tag ${SUT_IMAGE}:${IMAGES_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${SUT_IMAGE}:${IMAGES_TAG} + + - name: Build, tag workload image + run: | + docker build -f ./antithesis/workload/Dockerfile -t ${WORKLOAD_IMAGE}:${IMAGES_TAG} . + docker tag ${WORKLOAD_IMAGE}:${IMAGES_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${WORKLOAD_IMAGE}:${IMAGES_TAG} + + - name: Build tag config image + run: | + docker build -f ./antithesis/config/Dockerfile -t ${CONFIG_IMAGE}:${IMAGES_TAG} . + docker tag ${CONFIG_IMAGE}:${IMAGES_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${CONFIG_IMAGE}:${IMAGES_TAG} + + - name: Pull and tag upstream nats-server image + run: | + docker pull ${NATS_UPSTREAM_IMAGE}:${NATS_UPSTREAM_TAG} + docker tag ${NATS_UPSTREAM_IMAGE}:${NATS_UPSTREAM_TAG} ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${NATS_IMAGE}:${NATS_TAG} + + - name: Publish images + run: | + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${SUT_IMAGE}:${IMAGES_TAG} + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${WORKLOAD_IMAGE}:${IMAGES_TAG} + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${CONFIG_IMAGE}:${IMAGES_TAG} + docker push ${{ secrets.ANTITHESIS_REGISTRY_URL }}/${{ secrets.ANTITHESIS_REPOSITORY }}/${NATS_IMAGE}:${NATS_TAG} + + - name: "Launch single experiment" + run: ./antithesis/scripts/launch_experiment.sh 'default' '${{ inputs.duration }}' '${{ env.IMAGES_TAG }}' '${{ inputs.description }}' '${{ inputs.email }}' diff --git a/.github/workflows/antithesis-run-experiment.yml b/.github/workflows/antithesis-run-experiment.yml new file mode 100644 index 0000000..e609178 --- /dev/null +++ b/.github/workflows/antithesis-run-experiment.yml @@ -0,0 +1,40 @@ +name: "Experiment with existing images" + +env: + ANTITHESIS_WEBOOK_TOKEN: ${{ secrets.ANTITHESIS_WEBOOK_TOKEN }} + ANTITHESIS_WEBOOK_URL: ${{ secrets.ANTITHESIS_WEBOOK_URL }} + ANTITHESIS_WEBOOK_USERNAME: ${{ secrets.ANTITHESIS_WEBOOK_USERNAME }} + +on: + workflow_dispatch: + inputs: + duration: + description: 'Duration (fuzzing hours)' + required: true + type: string + default: "1.0" + imgtag: + description: 'Image' + required: true + type: string + default: "latest" + description: + description: 'Experiment description (avoid quotes, please!)' + required: true + type: string + default: "No description provided" + email: + description: 'Additional email notification recipient (separate with ;)' + required: false + type: string + default: "" + +jobs: + parametrized-experiment: + runs-on: ubuntu-latest + steps: + - name: Checkout repository (without submodules) + uses: actions/checkout@v4 + + - name: "Launch single experiment" + run: ./antithesis/scripts/launch_experiment.sh 'default' '${{ inputs.duration }}' '${{ inputs.imgtag }}' '${{ inputs.description }}' '${{ inputs.email }}' diff --git a/.github/workflows/antithesis-test-pull-request.yml b/.github/workflows/antithesis-test-pull-request.yml new file mode 100644 index 0000000..db263b6 --- /dev/null +++ b/.github/workflows/antithesis-test-pull-request.yml @@ -0,0 +1,22 @@ +name: "Pull Request: Build Antithesis Images" + +on: [pull_request] + +env: + +jobs: + build: + runs-on: ubuntu-latest + # Explicitly enable selected permissions (disables the rest by default) + permissions: + contents: read + + steps: + - name: Checkout repository (without submodules) + uses: actions/checkout@v4 + with: + submodules: false + + - name: Build Antithesis images + run: | + make -C ./antithesis build diff --git a/antithesis/Makefile b/antithesis/Makefile new file mode 100644 index 0000000..0739a2f --- /dev/null +++ b/antithesis/Makefile @@ -0,0 +1,33 @@ +# This Makefile locally builds the images and stands up the system as described +# in the config image docker-compose. + +# Uncomment if needed to debug build: +# DOCKER_BUILD_FLAGS = --no-cache + +.PHONY: run +run: clean build pull_nats_server ./config/docker-compose.yml + docker-compose -f ./config/docker-compose.yml --env-file ./config/environment up + +.PHONY: build +build: build_workload build_sut build_config + +.PHONY: build_sut +build_sut: ./system-under-test/Dockerfile + docker build $(DOCKER_BUILD_FLAGS) -f ./system-under-test/Dockerfile -t raft_sut:latest .. + +.PHONY: build_workload +build_workload: ./workload/Dockerfile + docker build $(DOCKER_BUILD_FLAGS) -f ./workload/Dockerfile -t raft_workload:latest .. + +.PHONY: build_config +build_config: ./config/Dockerfile + docker build $(DOCKER_BUILD_FLAGS) -f ./config/Dockerfile -t raft_config:latest .. + +.PHONY: pull_nats_server +pull_nats_server: + docker pull nats:latest + docker tag nats:latest nats_server:latest + +.PHONY: clean +clean: + docker-compose -f ./config/docker-compose.yml --env-file ./config/environment down diff --git a/antithesis/config/Dockerfile b/antithesis/config/Dockerfile new file mode 100644 index 0000000..8cfacf4 --- /dev/null +++ b/antithesis/config/Dockerfile @@ -0,0 +1,7 @@ +FROM scratch +COPY ./antithesis/config/docker-compose.yml docker-compose.yaml +COPY ./antithesis/config/environment .env + +# Install version and buildinfo files +COPY ./antithesis/config/version /opt/antithesis/version +COPY ./antithesis/config/buildinfo /opt/antithesis/buildinfo diff --git a/antithesis/config/buildinfo b/antithesis/config/buildinfo new file mode 100644 index 0000000..9564278 --- /dev/null +++ b/antithesis/config/buildinfo @@ -0,0 +1,3 @@ +This file is populated by GH workflows via /scripts/buildinfo.sh + +If you can read this, the step was skipped... diff --git a/antithesis/config/docker-compose.yml b/antithesis/config/docker-compose.yml new file mode 100644 index 0000000..ac4de5c --- /dev/null +++ b/antithesis/config/docker-compose.yml @@ -0,0 +1,87 @@ +services: + replica-A: + container_name: replica-A + hostname: replica-A + image: raft_sut:latest + entrypoint: /bin/raft-replica + command: -replica-id replica-A -group-id "test-raft" -nats-url nats://nats-server:4222 -peers replica-A,replica-B,replica-C + networks: + antithesis-net: + ipv4_address: 10.20.20.2 + deploy: + resources: + limits: + cpus: ${CPU_LIMIT} + memory: ${MEM_LIMIT} + depends_on: + nats-server: + condition: service_started + restart: false + replica-B: + container_name: replica-B + hostname: replica-B + image: raft_sut:latest + entrypoint: /bin/raft-replica + command: -replica-id replica-B -group-id "test-raft" -nats-url nats://nats-server:4222 -peers replica-A,replica-B,replica-C + networks: + antithesis-net: + ipv4_address: 10.20.20.3 + deploy: + resources: + limits: + cpus: ${CPU_LIMIT} + memory: ${MEM_LIMIT} + depends_on: + nats-server: + condition: service_started + restart: false + replica-C: + container_name: replica-C + hostname: replica-C + image: raft_sut:latest + entrypoint: /bin/raft-replica + command: -replica-id replica-C -group-id "test-raft" -nats-url nats://nats-server:4222 -peers replica-A,replica-B,replica-C + networks: + antithesis-net: + ipv4_address: 10.20.20.4 + deploy: + resources: + limits: + cpus: ${CPU_LIMIT} + memory: ${MEM_LIMIT} + depends_on: + nats-server: + condition: service_started + restart: false + + workload: + container_name: workload + hostname: workload + image: raft_workload:latest + entrypoint: /bin/workload + command: -group-id "test-raft" -nats-url nats://nats-server:4222 + networks: + antithesis-net: + ipv4_address: 10.20.20.130 + depends_on: + nats-server: + condition: service_started + restart: false + + nats-server: + container_name: nats-server + hostname: nats-server + image: nats_server:latest + command: --port 4222 + ports: + - "4222:4222" + networks: + antithesis-net: + ipv4_address: 10.20.20.150 + +networks: + antithesis-net: + driver: bridge + ipam: + config: + - subnet: 10.20.20.0/24 diff --git a/antithesis/config/environment b/antithesis/config/environment new file mode 100644 index 0000000..0d5e8bf --- /dev/null +++ b/antithesis/config/environment @@ -0,0 +1,6 @@ +# Soft-limit Go runtime memory +GOMEMLIMIT=512MiB + +# Hard limits on server containers resources +MEM_LIMIT=2G +CPU_LIMIT=1.0 diff --git a/antithesis/config/version b/antithesis/config/version new file mode 100644 index 0000000..9564278 --- /dev/null +++ b/antithesis/config/version @@ -0,0 +1,3 @@ +This file is populated by GH workflows via /scripts/buildinfo.sh + +If you can read this, the step was skipped... diff --git a/antithesis/scripts/buildinfo.sh b/antithesis/scripts/buildinfo.sh new file mode 100755 index 0000000..3a8bdf3 --- /dev/null +++ b/antithesis/scripts/buildinfo.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# This script is invoked by GH workflows to populate the version file in each image + +set -e + +SUT_DIR="./antithesis/system-under-test" +WORKLOAD_DIR="./antithesis/workload" +CONFIG_DIR="./antithesis/config" + +VERSION_FILE="version" +BUILDINFO_FILE="buildinfo" + +for d in "${SUT_DIR}" "${WORKLOAD_DIR}" "${CONFIG_DIR}"; do + # Files are expected to exist + test -f "${d}/${VERSION_FILE}" + test -f "${d}/${BUILDINFO_FILE}" + + # Write branch name and commit info into each image 'version' file + echo "Branch: $(git branch --show-current)" > "${d}/${VERSION_FILE}" + git log -1 >> "${d}/${VERSION_FILE}" + + # Write build metadata into each image 'buildinfo' file + echo " +GITHUB_ACTOR=${GITHUB_ACTOR} +GITHUB_TRIGGERING_ACTOR=${GITHUB_TRIGGERING_ACTOR} +GITHUB_REF_NAME=${GITHUB_REF_NAME} +GITHUB_SHA=${GITHUB_SHA} +GITHUB_JOB=${GITHUB_JOB} +GITHUB_REPOSITORY=${GITHUB_REPOSITORY} +GITHUB_RUN_ID=${GITHUB_RUN_ID} +GITHUB_RUN_NUMBER=${GITHUB_RUN_NUMBER} +GITHUB_WORKFLOW=${GITHUB_WORKFLOW} +GITHUB_WORKFLOW_REF=${GITHUB_WORKFLOW_REF} +RUNNER_ARCH=${RUNNER_ARCH} +RUNNER_OS=${RUNNER_OS} +USER=${USER} +HOSTNAME=${HOSTNAME} +" > "${d}/${BUILDINFO_FILE}" + +done diff --git a/antithesis/scripts/launch_experiment.sh b/antithesis/scripts/launch_experiment.sh new file mode 100755 index 0000000..ebae782 --- /dev/null +++ b/antithesis/scripts/launch_experiment.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# This script triggers a single experiment by calling the endpoint provided by the Antithesis team. +# +# This script takes 5 arguments: +# 1. Workload (test) name +# 2. Duration (wallclock) +# 3. Images tag +# 4. Experiment description (empty string is ok) +# 5. Additional email addresses to send the report to (empty string is ok) +# Reference: +# - https://antithesis.com/docs/getting_started/webhook.html + +################################################################################ + +# URL +URL='https://synadia.antithesis.com/api/v1/launch_experiment/synadia' +REQUIRED=" + jq + curl +" + +################################################################################ + +# Ensure required commands are available +for cmd in ${REQUIRED}; do + if ! command -v "${cmd}" >/dev/null 2>&1; then + echo "Missing required command: ${cmd}" + exit 1 + fi +done + +# Ensure API username is set in environment +if [ -z "${ANTITHESIS_WEBOOK_USERNAME}" ]; then + echo "Environment variable ANTITHESIS_WEBOOK_USERNAME is not set." + exit 1 +fi + +# Ensure token is set in environment +if [ -z "${ANTITHESIS_WEBOOK_TOKEN}" ]; then + echo "Environment variable ANTITHESIS_WEBOOK_TOKEN is not set." + exit 1 +fi + +# Ensure URL is set in environment +if [ -z "${ANTITHESIS_WEBOOK_URL}" ]; then + echo "Environment variable ANTITHESIS_WEBOOK_TOKEN is not set." + exit 1 +fi +URL="${ANTITHESIS_WEBOOK_URL}" + + +# Ensure the right number of arguments +if [ "$#" -ne 5 ]; then + echo "Expecting 5 arguments, got $#: ${*}" + exit 1 +fi + +# Put arguments into variables for readability +workload="${1}" +duration="${2}" +images_tag="${3}" +experiment_description="[${GITHUB_ACTOR:-$USER}] ${4}" +email="antithesis-reports@synadia.com;${5}" + +echo "Triggering ${duration} hours experiment with workload: '${workload}' using images version: '${images_tag}'" + +################################################################################ + +# Don't ignore mid-pipeline errors +set -o pipefail + +# Invoke endpoint +jq -n \ + --arg w "${workload}" \ + --arg d "${duration}" \ + --arg i "raft_sut:${images_tag};raft_workload:${images_tag};raft_config:${images_tag};nats_server:latest" \ + --arg n "${experiment_description}" \ + --arg e "${email}" \ + '{ params: {"custom.workload": $w, "custom.duration": $d, "antithesis.images": $i, "antithesis.description": $n, "antithesis.report.recipients": $e } }' \ +| tee /dev/fd/2 \ +| curl \ + --fail \ + --silent \ + --show-error \ + -u "${ANTITHESIS_WEBOOK_USERNAME}:${ANTITHESIS_WEBOOK_TOKEN}" \ + -X POST \ + --data @- \ + -H "content-type: application/json" \ + "${URL}" + +if [ $? -ne 0 ]; then + echo "Error launching experiment" + exit 1 +fi diff --git a/antithesis/system-under-test/Dockerfile b/antithesis/system-under-test/Dockerfile new file mode 100644 index 0000000..8f18d6e --- /dev/null +++ b/antithesis/system-under-test/Dockerfile @@ -0,0 +1,51 @@ +# Not alpine because docker assumes glibc. alpine uses musl not glibc. Hence why /lib64/ld-linux-x86-64.so.2 doesn't exist. +FROM --platform=x86-64 ubuntu:latest AS builder + +# Update and upgrade repo +RUN apt-get update -y -q && apt-get upgrade -y -q + +# Install tools we might need +RUN DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y -q curl build-essential ca-certificates git + +# Download Go and install it to /usr/local/go +RUN curl -s https://dl.google.com/go/go1.22.5.linux-amd64.tar.gz | tar -C /usr/local -xz + +ENV PATH $PATH:/usr/local/go/bin + +# Copy nats-server source code +COPY ./toy-raft /toy-raft + +WORKDIR / + +# Install instrumentor (lands in /root/go/bin/antithesis-go-instrumentor) +RUN go install github.com/antithesishq/antithesis-sdk-go/tools/antithesis-go-instrumentor@latest + +# Instrument code (lands in /nats-server_instrumented) +RUN mkdir -p /toy-raft_instrumented +RUN /root/go/bin/antithesis-go-instrumentor /toy-raft /toy-raft_instrumented + +# Build instrumented toy-raft +WORKDIR /toy-raft_instrumented/customer +RUN go mod download +RUN go build -C ./cmd/replica -v -a -o raft-replica_no_race -tags enable_antithesis_sdk +RUN go build -C ./cmd/replica -v -a -race -o raft-replica_race -tags enable_antithesis_sdk + +# Install binary, library and symbols +FROM --platform=x86-64 ubuntu:latest +RUN mkdir -p /bin +COPY --from=builder /toy-raft_instrumented/customer/cmd/replica/raft-replica_no_race /bin/raft-replica_no_race +COPY --from=builder /toy-raft_instrumented/customer/cmd/replica/raft-replica_race /bin/raft-replica_race +COPY --from=builder /toy-raft_instrumented/symbols /symbols + +# Link default server (referenced in entrypoint) +RUN ln -s /bin/raft-replica_race /bin/raft-replica + +# Verify binary was compiled and instrumented properly +RUN /bin/raft-replica -help + +# Install version and buildinfo files +RUN mkdir -p /opt/antithesis/ +COPY ./antithesis/system-under-test/version /opt/antithesis/version +COPY ./antithesis/system-under-test/buildinfo /opt/antithesis/buildinfo + +ENTRYPOINT ["/bin/raft-replica"] diff --git a/antithesis/system-under-test/buildinfo b/antithesis/system-under-test/buildinfo new file mode 100644 index 0000000..9564278 --- /dev/null +++ b/antithesis/system-under-test/buildinfo @@ -0,0 +1,3 @@ +This file is populated by GH workflows via /scripts/buildinfo.sh + +If you can read this, the step was skipped... diff --git a/antithesis/system-under-test/version b/antithesis/system-under-test/version new file mode 100644 index 0000000..9564278 --- /dev/null +++ b/antithesis/system-under-test/version @@ -0,0 +1,3 @@ +This file is populated by GH workflows via /scripts/buildinfo.sh + +If you can read this, the step was skipped... diff --git a/antithesis/workload/Dockerfile b/antithesis/workload/Dockerfile new file mode 100644 index 0000000..8162d5f --- /dev/null +++ b/antithesis/workload/Dockerfile @@ -0,0 +1,51 @@ +# Not alpine because docker assumes glibc. alpine uses musl not glibc. Hence why /lib64/ld-linux-x86-64.so.2 doesn't exist. +FROM --platform=x86-64 ubuntu:latest AS builder + +# Update and upgrade repo +RUN apt-get update -y -q && apt-get upgrade -y -q + +# Install tools we might need +RUN DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y -q curl build-essential ca-certificates git + +# Download Go and install it to /usr/local/go +RUN curl -s https://dl.google.com/go/go1.22.5.linux-amd64.tar.gz | tar -C /usr/local -xz + +ENV PATH $PATH:/usr/local/go/bin + +# Copy toy-raft source code +COPY ./toy-raft /toy-raft + +WORKDIR / + +# Install instrumentor (lands in /root/go/bin/antithesis-go-instrumentor) +RUN go install github.com/antithesishq/antithesis-sdk-go/tools/antithesis-go-instrumentor@latest + +# Instrument code (lands in /nats-server_instrumented) +RUN mkdir -p /toy-raft_instrumented +RUN /root/go/bin/antithesis-go-instrumentor /toy-raft /toy-raft_instrumented + +# Build instrumented toy-raft +WORKDIR /toy-raft_instrumented/customer +RUN go mod download +RUN go build -C ./cmd/workload -v -a -o workload_no_race -tags enable_antithesis_sdk +RUN go build -C ./cmd/workload -v -a -race -o workload_race -tags enable_antithesis_sdk + +# Install binary, library and symbols +FROM --platform=x86-64 ubuntu:latest +RUN mkdir -p /bin +COPY --from=builder /toy-raft_instrumented/customer/cmd/workload/workload_no_race /bin/workload_no_race +COPY --from=builder /toy-raft_instrumented/customer/cmd/workload/workload_race /bin/workload_race +COPY --from=builder /toy-raft_instrumented/symbols /symbols + +# Link default server (referenced in entrypoint) +RUN ln -s /bin/workload_race /bin/workload + +# Verify binary was compiled and instrumented properly +RUN /bin/workload -help + +# Install version and buildinfo files +RUN mkdir -p /opt/antithesis/ +COPY ./antithesis/workload/version /opt/antithesis/version +COPY ./antithesis/workload/buildinfo /opt/antithesis/buildinfo + +ENTRYPOINT ["/bin/workload"] diff --git a/antithesis/workload/buildinfo b/antithesis/workload/buildinfo new file mode 100644 index 0000000..9564278 --- /dev/null +++ b/antithesis/workload/buildinfo @@ -0,0 +1,3 @@ +This file is populated by GH workflows via /scripts/buildinfo.sh + +If you can read this, the step was skipped... diff --git a/antithesis/workload/version b/antithesis/workload/version new file mode 100644 index 0000000..9564278 --- /dev/null +++ b/antithesis/workload/version @@ -0,0 +1,3 @@ +This file is populated by GH workflows via /scripts/buildinfo.sh + +If you can read this, the step was skipped...