Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
feat(webapp oci):initial version of webapp image
Browse files Browse the repository at this point in the history
feat(github-actions): build webapp image

feat(github-actions): build webapp image

update docs, include a script to run tests based on env vars

fixup! feat(github-actions): build webapp image

use an entrypoint script that starts a cronjob to run every minute

ci: attempt to have 2 tags for the webapp image, one with the sha

fixup! feat(webapp oci):initial version of webapp image

fixup! use an entrypoint script that starts a cronjob to run every minute

fixup! use an entrypoint script that starts a cronjob to run every minute

fixup! ci: attempt to have 2 tags for the webapp image, one with the sha

tasks to run webapp image locally

ci: fix gh actions invalid workflow file error

debug logs on the entrypoint shell script

fixup! ci: fix gh actions invalid workflow file error

run the test delete-objects every 20 minutes

change test frequency to every 3 minutes

change timezone and add output of tests to the smile txt

wip
  • Loading branch information
fczuardi committed Feb 8, 2024
1 parent a5dc98a commit a5df3bd
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 18 deletions.
30 changes: 26 additions & 4 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
name: Build Docker Image
name: Build Docker Images

on:
push:
branches:
- main
- bucket-tester-app-image
env:
REGISTRY: ghcr.io
DOCKER_USERNAME: fczuardi
Expand All @@ -14,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Login to Docker Hub
uses: docker/login-action@v3
Expand All @@ -25,14 +26,35 @@ jobs:

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push Docker image
- name: Build and push (main) Docker image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Pre-build webapp
run: |
wget --quiet https://github.com/belitre/gotpl/releases/download/v0.7/gotpl-v0.7-linux-amd64.zip && unzip gotpl-v0.7-linux-amd64.zip
linux-amd64/gotpl -f example.config.yaml src/templates/nginx.conf --output .
- name: Build and push (webapp) Docker image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
file: webapp.Dockerfile
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:webapp
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:webapp-${{github.sha}}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ config.yaml
results
venv
mgc
nginx.conf
!src/templates/nginx.conf
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ WORKDIR /app
COPY src /app/src
COPY vendor /app/vendor
COPY justfile /app/justfile
COPY run_tests.sh /app/run_tests.sh
COPY requirements.txt /app/requirements.txt
COPY LICENSE /app/LICENSE
RUN pip install --no-cache-dir --no-dependencies -r requirements.txt
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@ vim config.yaml #edit with your remotes
```
### Run tests using a pre-made docker image

**object-storage-tests** is available as two
[docker images](https://hub.docker.com/r/fczuardi/object-storage-tests):
- tag `latest` is the [main tests runner][Dockerfile] with its commands and
**object-storage-tests** is available as three
[docker images](https://github.com/marmotitude/object-storage-tests/pkgs/container/object-storage-tests/versions?filters%5Bversion_type%5D=tagged):
- tag `main` is the [main tests runner][Dockerfile] with its commands and
requirements.
- tag `devshell` is a [shell for developers][devshell.Dockerfile] to use it
interactively and make contributions.
- tag `webapp` is the same as main with a [webserver exposed on port 5000][webapp.Dockerfile] that
serves html reports from the `results` folder, this image have a `run_tests.sh` script that updates
the folder with a new report.

If you are on a machine with podman installed, you can use `just run <command>` to execute a
command from within the main test runner image (tag latest). For example:
Expand Down
50 changes: 50 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/sh
set +x

# Check if CONFIG_YAML_CONTENT is present
if [ -z "$CONFIG_YAML_CONTENT" ]; then
echo "Error: CONFIG_YAML_CONTENT environment variable is not set."
printf ":-(\n\nError: CONFIG_YAML_CONTENT environment variable is not set. $(date)" > /app/results/smile.txt
exit 1
fi

# create config.yaml file from env var
echo "$CONFIG_YAML_CONTENT" > /app/config.yaml

# create ~/.aws config files
just _setup

# space separated list of remote names
remotes=$(dasel -f /app/config.yaml -r yaml -s '.remotes.all().key()' | grep -v '\-second$' | tr '\n' ' ')

echo "Remotes: $remotes"
date

# Sync local_results_folder with remote_results_bucket as source
remote_results_bucket=$(dasel -f ./config.yaml -r yaml -s '.results_bucket')
local_results_folder="./results"
rclone mkdir "$remote_results_bucket" # create remote bucket if it doesnt exist
rclone sync "$remote_results_bucket" "$local_results_folder" # fetch previous results

# Do a list-buckets on each remote
for remote in $remotes; do
echo "Executing AWS CLI command for profile $remote"
echo "$remote" >> /app/results/smile.txt
aws s3api list-buckets --cli-connect-timeout 2 --cli-read-timeout 2 --profile "$remote" >> /app/results/smile.txt
done

# asure that results folder is readable
chmod -R 755 results

# Schedule for TEST_SUITE=big
echo "8 7,9,11,14,16,18,22,0 * * * TEST_SUITE=big /app/run_tests.sh" >> /etc/crontabs/root

# Schedule for TEST_SUITE=small
echo "*/5 * * * * TEST_SUITE=small /app/run_tests.sh" >> /etc/crontabs/root

# Start cron
crond -f &

# Start Nginx
exec nginx -g 'daemon off;'

14 changes: 13 additions & 1 deletion example.config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
current_remote: "example-mgc"
# credentials and endpoints for multiple object storage providers
remotes:
aws-east-1:
s3:
Expand Down Expand Up @@ -32,3 +32,15 @@ remotes:
region: us-east-1
access_key: "test:tester"
secret_key: "testing"

# TODO: mgc tool supports only one remote / profile, this config will be deprecated in the future
current_remote: "example-mgc"

# config for a webserver to expose results in a website, see webapp.Dockerfile
webapp:
nginx:
listen: 5000
server_name: localhost
locations:
"/":
root: "/app/results"
23 changes: 18 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
date := `date +%Y%m%d-%H%M%S`
config_file := env_var_or_default("CONFIG_PATH", "./") + "config.yaml"
results_prefix := "results"
rclone_conf_exists := path_exists(env_var("HOME") + "/.config/rclone")
aws_conf_exists := path_exists(env_var("HOME") + "/.aws")
rclone_conf_path := env_var("HOME") + "/.config/rclone"
rclone_conf_exists := path_exists(rclone_conf_path)
aws_conf_path := env_var("HOME") + "/.aws"
aws_conf_exists := path_exists(aws_conf_path)
distroboxrc_cm := `dasel -f ~/.distroboxrc \
-s container_manager -r toml 2>/dev/null || true`
fallback_cm := if distroboxrc_cm == "" { "podman" } else { distroboxrc_cm }
Expand All @@ -17,6 +19,7 @@ k6_iterations := "1"

# OCI
main_image := "ghcr.io/marmotitude/object-storage-tests:main"
webapp_image := "ghcr.io/marmotitude/object-storage-tests:webapp"
devshell_image := "docker.io/fczuardi/object-storage-tests:devshell"
distrobox_name := "devshell-obj"

Expand Down Expand Up @@ -128,6 +131,16 @@ build builder=oci_manager:
build-dev builder=oci_manager:
{{builder}} build --rm -t {{devshell_image}} -f ./devshell.Dockerfile .

# Build webapp image.
build-webapp builder=oci_manager:
# write ./nginx.conf to be copied by Dockerfile
gotpl -f config.yaml src/templates/nginx.conf --output .
{{builder}} build --no-cache --rm -t {{webapp_image}} -f ./webapp.Dockerfile .
rm ./nginx.conf

# Launch webapp container
run-webapp:
docker run -e CONFIG_YAML_CONTENT="$(cat ./small-config.yaml)" -p 5000:5000 {{webapp_image}}

# Private recipes
#----------------
Expand All @@ -153,9 +166,9 @@ _setup-aws:
{{ if aws_conf_exists == "false" { "just __setup-aws" } else { "" } }}
__setup-aws:
@echo "writing ~/.aws…"
@mkdir -p ~/.aws
gotpl src/templates/aws/config -f {{config_file}} -o ~/.aws
gotpl src/templates/aws/credentials -f {{config_file}} -o ~/.aws
@mkdir -p {{aws_conf_path}}
gotpl src/templates/aws/config -f {{config_file}} -o {{aws_conf_path}}
gotpl src/templates/aws/credentials -f {{config_file}} -o {{aws_conf_path}}

_setup-mgc:
@echo "writing ~/.config/mgc…"
Expand Down
34 changes: 34 additions & 0 deletions run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/sh
set +x

# cron job starts on /root and is run by user root
cd /app

touch results/debug_last_test_start

# space separated list of remote names
remotes=$(dasel -f ./config.yaml -r yaml -s '.remotes.all().key()' | grep -v '\-second$' | tr '\n' ' ')
small_set_remotes=$(dasel -f ./config.yaml -r yaml -s '.small_set_remotes')

# Check if TEST_SUITE is set and execute commands accordingly
if [ "$TEST_SUITE" = "big" ]; then
# Run tests for big suite
just group-test index-s3 _big "$remotes" > results/debug_last_test.txt 2>&1
elif [ "$TEST_SUITE" = "small" ]; then
# Run tests for small suite
just group-test delete-objects _small "$small_set_remotes" > results/debug_last_test.txt 2>&1
else
echo "Unknown TEST_SUITE value: $TEST_SUITE" > results/debug_last_test.txt 2>&1
exit 1
fi


# asure that results folder is readable
chmod -R 755 results

printf ":-)\n\nLast test ended on $(date)" > results/smile.txt

# Sync remote_results_bucket with local_results_folder as source (send results)
remote_results_bucket=$(dasel -f ./config.yaml -r yaml -s '.results_bucket')
local_results_folder="./results"
rclone sync "$local_results_folder" "$remote_results_bucket"
18 changes: 13 additions & 5 deletions src/k6/index-s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,15 @@ const swiftConfig = config.remotes[__ENV.AWS_CLI_PROFILE].swift
const mgcConfig = config.remotes[__ENV.AWS_CLI_PROFILE].mgc
const s3 = makeS3Client(s3Config);
const bucketName = __ENV.TEST_BUCKET
const profileName = __ENV.AWS_CLI_PROFILE
const testFileName = "LICENSE"
const testFile = open(`../../${testFileName}`, "r");
let s3ConfigSecond;
try {
s3ConfigSecond = config.remotes[`${profile}-second`].s3;
} catch (error) {
s3ConfigSecond = false;
}


export function setup() {
Expand Down Expand Up @@ -99,6 +106,7 @@ export default function ({
mgcData,
rcloneData,
awsCliCreateBucketData,
awsCliDeleteObjectsData,
}) {
describe("Run k6-jslib-aws buckets test", async (_t) => {
await k6JsLibBucketsTest(k6JsLibBucketsData);
Expand Down Expand Up @@ -136,15 +144,15 @@ export function teardown({
awsCliPresignData,
boto3Data,
mgcData,
rcloneData,
awsCliCreateBucketData
awsCliCreateBucketData,
awsCliDeleteObjectsData
}) {
describe("Teardown k6-jslib-aws objects test", (_t) => {
k6JsLibObjectsTeardown(k6JsLibObjectsData);
});
describe("Teardown k6-jslib-aws buckets test", (_t) => {
k6JsLibBucketsTeardown(k6JsLibBucketsData);
});
describe("Teardown k6-jslib-aws objects test", (_t) => {
k6JsLibObjectsTeardown(k6JsLibObjectsData);
});
describe("Teardown aws-cli multipart tests", (_t) => {
awsCliMultipartTeardown(awsCliMultipartData);
});
Expand Down
26 changes: 26 additions & 0 deletions src/templates/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Set number of worker processes automatically based on number of CPU cores.
worker_processes auto;

events {
# The maximum number of simultaneous connections that can be opened by
# a worker process.
worker_connections 1024;
}

http {
charset utf-8;

server {
listen {{ .webapp.nginx.listen }};
server_name {{ .webapp.nginx.server_name }};

{{- range $location_name, $location := .webapp.nginx.locations}}
location {{ $location_name }} {
root {{ $location.root }};
index index.html;
autoindex on;
autoindex_localtime on;
}
{{- end}}
}
}
47 changes: 47 additions & 0 deletions webapp.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Use main image as base
FROM ghcr.io/marmotitude/object-storage-tests:main

# Install Nginx and cron
RUN apk update && \
apk add --no-cache nginx dcron tzdata

# Set the timezone to America/Sao_Paulo
RUN ln -sf /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime && \
echo "America/Sao_Paulo" > /etc/timezone

# Keep a backup of alpine's default nginx config
RUN mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig

# Copy our custom Nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf

# Set the working directory to /app
WORKDIR /app

# Create the directory for the results
RUN mkdir -p results

# Set ownership and permissions for Nginx to read from /app/results
RUN chown -R root:root results && \
chmod -R 755 results

# Write dummy file to results directory with a smile and timestamp
RUN printf ":-)\n\nBuilt on $(date) by:$(hostname)" > results/smile.txt

# Copy the shell script that runs desired tests outputing to results folder
# this script will be executed by an external scheduler periodically
COPY run_tests.sh /app/run_tests.sh

# Expose port 5000
EXPOSE 5000

COPY justfile /app/justfile

# Copy the entrypoint script
COPY entrypoint.sh /app/entrypoint.sh

# Make the script executable
RUN chmod +x /app/entrypoint.sh

# Set the ENTRYPOINT to the script
ENTRYPOINT ["/app/entrypoint.sh"]

0 comments on commit a5df3bd

Please sign in to comment.