From 73297c40b9ed53921ae5e4ae49837d2bd2b028e4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 29 May 2025 18:37:41 +1200 Subject: [PATCH] :-'Generic Commit' --- .gitea/workflows/demo.yaml | 21 +++++++----- .test-docker/compose.yaml | 11 ++++++ Dockerfile | 2 +- src/config.cpp | 13 ++++++++ test-docker.sh | 28 ++++++++-------- test.sh | 68 +++++++++++++++++++------------------- 6 files changed, 84 insertions(+), 59 deletions(-) create mode 100644 .test-docker/compose.yaml diff --git a/.gitea/workflows/demo.yaml b/.gitea/workflows/demo.yaml index 056c3cf..1f0b284 100644 --- a/.gitea/workflows/demo.yaml +++ b/.gitea/workflows/demo.yaml @@ -3,18 +3,21 @@ run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 on: [push] jobs: - Explore-Gitea-Actions: + Build: runs-on: ubuntu-latest steps: - - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event." - - run: cat /etc/issue - - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}." - name: Check out repository code uses: actions/checkout@v4 - - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner." - - run: echo "🖥️ The workflow is now ready to test your code on the runner." - - name: List files in the repository + - name: Build the project run: | - ls ${{ gitea.workspace }} - - run: echo "🍏 This job's status is ${{ job.status }}." + ./build.sh all + - name: Test the project + run: | + ./test-docker.sh + run: | + ./test.sh + - name: Push the Docker image + run: | + ./publish.sh + diff --git a/.test-docker/compose.yaml b/.test-docker/compose.yaml new file mode 100644 index 0000000..61b487a --- /dev/null +++ b/.test-docker/compose.yaml @@ -0,0 +1,11 @@ +services: + sos: + image: gitea.jde.nz/public/simple-object-storage:test + ports: + - 7703:80 + volumes: + - ${LOCALCONFIG}:/data/sos_config.json:ro + environment: + - SOS_CONFIG=/data/sos_config.json + restart: no + diff --git a/Dockerfile b/Dockerfile index f4a3246..b1a813c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ ARG TARGETARCH # Copy binary from builder -RUN mkdir -p /sos +RUN mkdir -p /sos && mkdir -p /data/storage COPY --chmod=0755 output/simple_object_storage.${TARGETARCH} /sos/sos diff --git a/src/config.cpp b/src/config.cpp index 8240621..117a536 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -8,6 +8,19 @@ namespace simple_object_storage { bool load_config(const std::string& config_path, ServerConfig& config) { try { + if (config_path.empty()) { + std::cerr << "Config path is empty" << std::endl; + return false; + } + if (!std::filesystem::exists(config_path)) { + std::cerr << "Config file does not exist: " << config_path << std::endl; + return false; + } + if (!std::filesystem::is_regular_file(config_path)) { + std::cerr << "Config file is not a regular file: " << config_path << std::endl; + return false; + } + std::ifstream file(config_path); if (!file.is_open()) { std::cerr << "Failed to open config file: " << config_path << std::endl; diff --git a/test-docker.sh b/test-docker.sh index 29fd1be..10a8192 100755 --- a/test-docker.sh +++ b/test-docker.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -euo pipefail SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) @@ -8,20 +9,17 @@ SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # build the docker image docker buildx build --load -t gitea.jde.nz/public/simple-object-storage:test --platform linux/amd64 . -DATADIR="/home/${USER}/.simple_object_storage" -if [ ! -d "${DATADIR}" ]; then - mkdir -p "${DATADIR}" -fi +export LOCALCONFIG="${SCRIPT_DIR}/.test-docker/config.json" -CONFIGFILE="${SCRIPT_DIR}/.docker/config.json" -if [ ! -f "${CONFIGFILE}" ]; then - echo "Config file not found: ${CONFIGFILE}" - exit 1 -fi +COMPOSE_FILE="${SCRIPT_DIR}/.test-docker/compose.yaml" + +docker compose -f "${COMPOSE_FILE}" up -d + +"${SCRIPT_DIR}/test.sh" "http://localhost:7703" +RESULT=$? + +docker compose -f "${COMPOSE_FILE}" down +docker compose -f "${COMPOSE_FILE}" rm -v + +exit $RESULT -docker run --rm \ - -p 8123:80 \ - --name simple-object-storage-test \ - -v "${DATADIR}":/data/storage \ - -v "${CONFIGFILE}":/data/sos_config.json:ro \ - gitea.jde.nz/public/simple-object-storage:test diff --git a/test.sh b/test.sh index 3ee613a..d093725 100755 --- a/test.sh +++ b/test.sh @@ -3,6 +3,11 @@ set -euo pipefail +HOSTURL="$1" +if [ -z "${HOSTURL}" ]; then + HOSTURL="http://localhost:8123" +fi + #------------------------------------------------------------------------------------------------ SCRIPT_DIR=$(dirname "$0") @@ -44,30 +49,25 @@ if ! command -v jq &> /dev/null; then fi # read ~/.config/simple_object_storage/config.json -CONFIG_PATH="${SCRIPT_DIR}/.docker/config.json" +CONFIG_PATH="${SCRIPT_DIR}/.test-docker/config.json" if [ ! -f "${CONFIG_PATH}" ]; then echo "config file not found at ${CONFIG_PATH}" exit 1 fi CONFIG=$(cat "${CONFIG_PATH}") -HOST=localhost -PORT=8123 - # extract the first write token from the config WRITE_TOKEN=$(echo "$CONFIG" | jq -r '.write_tokens[0]') -BASE_URL="http://${HOST}:${PORT}" - BASE_TAG="autotest" # test if server is running -if ! curl -s "${BASE_URL}/status" | jq -r '.result' | grep -q 'success'; then - die "server is not running" +if ! curl -s "${HOSTURL}/status" | jq -r '.result' | grep -q 'success'; then + die "server is not running on ${HOSTURL}" fi -echo "Simple Object Storage server is running at ${BASE_URL}" +echo "Simple Object Storage server is running at ${HOSTURL}" # test every action in the README.md file, leaving the system in the same state it was found # and print the output of each action @@ -92,7 +92,7 @@ UPLOAD_RESPONSE=$(curl -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" \ -F "metadata=${METADATA_JSON}" \ - "http://localhost:8123/upload") + "${HOSTURL}/upload") echo "upload response: ${UPLOAD_RESPONSE}" @@ -102,7 +102,7 @@ OBJECT_HASH=$(echo "${UPLOAD_RESPONSE}" | jq -r '.hash') title "2: Check sos hash matches" # check the hash matches. -CMD="${BASE_URL}/hash/${BASE_TAG}:test1" +CMD="${HOSTURL}/hash/${BASE_TAG}:test1" echo "checking hash via ${CMD}" CHECK_HASH=$(curl -s "${CMD}" | jq -r '.hash') [ "${OBJECT_HASH}" != "${CHECK_HASH}" ] && die "hash does not match: ${OBJECT_HASH} != ${CHECK_HASH}" @@ -117,13 +117,13 @@ echo "md5sum of ${SCRIPT_DIR}/${SCRIPT_NAME} is ${MD5SUM}" # download the object echo "downloading ${OBJECT_HASH} to ${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded1" -if ! curl -s "${BASE_URL}/object/${OBJECT_HASH}" -o "${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded1"; then +if ! curl -s "${HOSTURL}/object/${OBJECT_HASH}" -o "${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded1"; then die "failed to download ${OBJECT_HASH}" fi # download the object again via the label:tag echo "downloading ${BASE_TAG}:test1 to ${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded2" -if ! curl -s "${BASE_URL}/object/${BASE_TAG}:test1" -o "${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded2"; then +if ! curl -s "${HOSTURL}/object/${BASE_TAG}:test1" -o "${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded2"; then die "failed to download ${BASE_TAG}:test1" fi @@ -156,7 +156,7 @@ UPLOAD_RESPONSE=$(curl -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" \ -F "metadata=${METADATA_JSON}" \ - "http://localhost:8123/upload") + "${HOSTURL}/upload") echo "upload response: ${UPLOAD_RESPONSE}" @@ -167,7 +167,7 @@ if [ ! "${OBJECT_HASH}" == "${OBJECT_HASH2}" ]; then fi # test the description and custom field matches our new ones. -METADATA_RESPONSE=$(curl "http://localhost:8123/meta/${OBJECT_HASH2}") +METADATA_RESPONSE=$(curl "${HOSTURL}/meta/${OBJECT_HASH2}") echo "metadata response: ${METADATA_RESPONSE}" @@ -181,7 +181,7 @@ fi # download via the label:tag echo "downloading ${LABELTAG} to ${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded3" -if ! curl -s "${BASE_URL}/object/${LABELTAG}" -o "${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded3"; then +if ! curl -s "${HOSTURL}/object/${LABELTAG}" -o "${SCRIPT_DIR}/${SCRIPT_NAME}.downloaded3"; then die "failed to download ${LABELTAG}" fi @@ -199,13 +199,13 @@ title "4: Delete the object" # delete the object echo "deleting ${OBJECT_HASH}" -if ! curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${BASE_URL}/deleteobject?hash=${OBJECT_HASH}" | jq -r '.result' | grep -q 'success'; then +if ! curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${OBJECT_HASH}" | jq -r '.result' | grep -q 'success'; then die "failed to delete ${OBJECT_HASH}" fi # verify the object is deleted echo "verifying ${OBJECT_HASH} is deleted" -DELETE_RESPONSE=$(curl -s "${BASE_URL}/object/${OBJECT_HASH}") +DELETE_RESPONSE=$(curl -s "${HOSTURL}/object/${OBJECT_HASH}") if ! echo "${DELETE_RESPONSE}" | jq -r '.result' | grep -q 'error'; then die "failed to verify ${OBJECT_HASH} is deleted" fi @@ -230,7 +230,7 @@ UPLOAD_RESPONSE=$(curl -X PUT \ -H "Authorization: Bearer ${WRITE_TOKEN}" \ -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" \ -F "metadata=${EXTRA_METADATA_JSON}" \ - "http://localhost:8123/upload") + "${HOSTURL}/upload") UPLOAD_EXIT_CODE=$? echo "Upload response: ${UPLOAD_RESPONSE}" echo "Upload exit code: ${UPLOAD_EXIT_CODE}" @@ -248,12 +248,12 @@ echo "Received hash: ${OBJECT_HASH}" # Verify the object exists echo "Verifying object exists..." -EXISTS_RESPONSE=$(curl -s "${BASE_URL}/exists/${BASE_TAG}:test2") +EXISTS_RESPONSE=$(curl -s "${HOSTURL}/exists/${BASE_TAG}:test2") echo "Exists response: ${EXISTS_RESPONSE}" # Get metadata and verify extra fields are preserved echo "Retrieving metadata for ${BASE_TAG}:test2" -METADATA_RESPONSE=$(curl -s "${BASE_URL}/meta/${BASE_TAG}:test2") +METADATA_RESPONSE=$(curl -s "${HOSTURL}/meta/${BASE_TAG}:test2") CURL_EXIT_CODE=$? echo "Curl exit code: ${CURL_EXIT_CODE}" echo "Full metadata response: ${METADATA_RESPONSE}" @@ -277,7 +277,7 @@ fi title "6: Test tag versioning behavior" # Clean up -curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${BASE_URL}/deleteobject?hash=${OBJECT_HASH}" > /dev/null +curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${OBJECT_HASH}" > /dev/null # Upload first version with tag 'latest' FIRST_METADATA_JSON=$(cat < /dev/null -curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${BASE_URL}/deleteobject?hash=${SECOND_HASH}" > /dev/null +curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${FIRST_HASH}" > /dev/null +curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${SECOND_HASH}" > /dev/null # Use a known invalid token INVALID_TOKEN="invalid_token" @@ -362,13 +362,13 @@ INVALID_TOKEN="invalid_token" # Make 5 requests with an invalid token for i in {1..5}; do echo "Attempt $i with invalid token" - RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${INVALID_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${BASE_URL}/upload") + RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${INVALID_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${HOSTURL}/upload") echo "Response: ${RESPONSE}" done # Now try a request with a valid token - should be rate limited echo "Attempting request with valid token (should be rate limited)" -RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${WRITE_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${BASE_URL}/upload") +RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${WRITE_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${HOSTURL}/upload") if ! echo "${RESPONSE}" | jq -r '.error' | grep -q "Too many authentication attempts"; then die "Expected rate limit error, got: ${RESPONSE}" fi @@ -379,16 +379,16 @@ echo "(Normally 5 mins, but we set to 2s for this test!)" sleep 3 # Now try a request with a valid token - should be rate limited echo "Attempting request with valid token (should NOT be rate limited)" -RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${WRITE_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${BASE_URL}/upload") +RESPONSE=$(curl -s -X PUT -H "Authorization: Bearer ${WRITE_TOKEN}" -F "file=@${SCRIPT_DIR}/${SCRIPT_NAME}" -F "metadata={\"labeltags\":[\"test:latest\"]}" "${HOSTURL}/upload") if echo "${RESPONSE}" | jq -r '.error' | grep -q "Too many authentication attempts"; then die "Expected no rate limit error, got: ${RESPONSE}" fi # delete the object -TODELHASH=$(curl -s "${BASE_URL}/hash/test:latest" | jq -r '.hash') +TODELHASH=$(curl -s "${HOSTURL}/hash/test:latest" | jq -r '.hash') echo "deleting test:latest ${TODELHASH}" -if ! curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${BASE_URL}/deleteobject?hash=${TODELHASH}" | jq -r '.result' | grep -q 'success'; then +if ! curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?hash=${TODELHASH}" | jq -r '.result' | grep -q 'success'; then die "failed to delete ${TODELHASH}" fi