test: initial aws cli bats tests

This commit is contained in:
Luke McCrone
2024-01-29 20:07:00 -03:00
parent b908a4b981
commit 1409d664b4
8 changed files with 640 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
name: system tests
on: pull_request
#on:
# workflow_dispatch:
# inputs:
# run_workflow:
# description: 'Run command-line tests'
jobs:
build:
name: RunTests
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 'stable'
id: go
- name: Get Dependencies
run: |
go get -v -t -d ./...
- name: Install BATS
run: |
git clone https://github.com/bats-core/bats-core.git
cd bats-core && ./install.sh $HOME
- name: Build and Run
run: |
make testbin
export AWS_ACCESS_KEY_ID=user
export AWS_SECRET_ACCESS_KEY=pass
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile versity
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile versity
export VERSITY_EXE=./versitygw
mkdir /tmp/gw
VERSITYGW_TEST_ENV=$GITHUB_WORKSPACE/tests/.env.versitygw $HOME/bin/bats ./tests/s3_bucket_tests.sh
VERSITYGW_TEST_ENV=$GITHUB_WORKSPACE/tests/.env.versitygw $HOME/bin/bats ./tests/posix_tests.sh
+7
View File
@@ -39,3 +39,10 @@ VERSION
/profile.txt
dist/
# secrets file for local github-actions testing
.secrets
# env files for testing
.env*
!.env.default
+6
View File
@@ -0,0 +1,6 @@
AWS_REGION=us-west-2
AWS_PROFILE=versity
VERSITY_EXE=./versitygw
BACKEND=posix
LOCAL_FOLDER=/tmp/gw
AWS_ENDPOINT_URL=http://127.0.0.1:7070
+6
View File
@@ -0,0 +1,6 @@
AWS_REGION=us-east-1
AWS_PROFILE=versity
VERSITY_EXE=./versitygw
BACKEND=posix
LOCAL_FOLDER=/tmp/gw
AWS_ENDPOINT_URL=http://127.0.0.1:7070
+13
View File
@@ -0,0 +1,13 @@
# Command-Line Tests
Instructions:
1. Build the `versitygw` binary.
2. Create a local AWS profile for connection to S3, and add the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` values above to the profile.
3. Create an environment file (`.env`) similar to the ones in this folder, setting the `AWS_PROFILE` parameter to the name of the profile you created.
4. In the root repo folder, run with `VERSITYGW_TEST_ENV=<env file> tests/s3_bucket_tests.sh`.
5. If running/testing the GitHub workflow locally, create a `.secrets` file, and set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` parameters here to the values of your AWS S3 IAM account.
```
AWS_ACCESS_KEY_ID=<key_id>
AWS_SECRET_ACCESS_KEY=<secret_key>
```
6. To run the workflow locally, install **act** and run with `act -W .github/workflows/system.yml`.
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env bats
source ./tests/tests.sh
# check if object exists both on S3 and locally
# param: object path
# 0 for yes, 1 for no, 2 for error
object_exists_remote_and_local() {
if [ $# -ne 1 ]; then
echo "object existence check requires single name parameter"
return 2
fi
object_exists "$1" || local exist_result=$?
if [[ $exist_result -eq 2 ]]; then
echo "Error checking if object exists"
return 2
fi
if [[ $exist_result -eq 1 ]]; then
echo "Error: object doesn't exist remotely"
return 1
fi
if [[ ! -e "$LOCAL_FOLDER"/"$1" ]]; then
echo "Error: object doesn't exist locally"
return 1
fi
return 0
}
# check if object doesn't exist both on S3 and locally
# param: object path
# return 0 for doesn't exist, 1 for still exists, 2 for error
object_not_exists_remote_and_local() {
if [ $# -ne 1 ]; then
echo "object non-existence check requires single name parameter"
return 2
fi
object_exists "$1" || local exist_result=$?
if [[ $exist_result -eq 2 ]]; then
echo "Error checking if object doesn't exist"
return 2
fi
if [[ $exist_result -eq 0 ]]; then
echo "Error: object exists remotely"
return 1
fi
if [[ -e "$LOCAL_FOLDER"/"$1" ]]; then
echo "Error: object exists locally"
return 1
fi
return 0
}
# check if a bucket doesn't exist both on S3 and on gateway
# param: bucket name
# return: 0 for doesn't exist, 1 for does, 2 for error
bucket_not_exists_remote_and_local() {
if [ $# -ne 1 ]; then
echo "bucket existence check requires single name parameter"
return 2
fi
bucket_exists "$1" || local exist_result=$?
if [[ $exist_result -eq 2 ]]; then
echo "Error checking if bucket exists"
return 2
fi
if [[ $exist_result -eq 0 ]]; then
echo "Error: bucket exists remotely"
return 1
fi
if [[ -e "$LOCAL_FOLDER"/"$1" ]]; then
echo "Error: bucket exists locally"
return 1
fi
return 0
}
# check if a bucket exists both on S3 and on gateway
# param: bucket name
# return: 0 for yes, 1 for no, 2 for error
bucket_exists_remote_and_local() {
if [ $# -ne 1 ]; then
echo "bucket existence check requires single name parameter"
return 2
fi
bucket_exists "$1" || local exist_result=$?
if [[ $exist_result -eq 2 ]]; then
echo "Error checking if bucket exists"
return 2
fi
if [[ $exist_result -eq 1 ]]; then
echo "Error: bucket doesn't exist remotely"
return 1
fi
if [[ ! -e "$LOCAL_FOLDER"/"$1" ]]; then
echo "Error: bucket doesn't exist locally"
return 1
fi
return 0
}
# test that changes to local folders and files are reflected on S3
@test test_local_creation_deletion {
local bucket_name="versity-gwtest-put-object-test"
local object_name="test-object"
bucket_exists_remote_and_local $bucket_name || local bucket_exists=$?
if [[ $bucket_exists -eq 2 ]]; then
fail "Bucket existence check error"
fi
local object="$bucket_name"/"$object_name"
if [[ $bucket_exists -eq 0 ]]; then
object_exists_remote_and_local "$object" || local object_exists=$?
if [[ $object_exists -eq 2 ]]; then
fail "Object existence check error"
fi
if [[ $object_exists -eq 0 ]]; then
delete_object "$object" || local delete_object=$?
[[ $delete_object -eq 0 ]] || fail "Failed to delete object"
fi
delete_bucket $bucket_name || local delete_bucket=$?
[[ $delete_bucket -eq 0 ]] || fail "Failed to delete bucket"
fi
mkdir "$LOCAL_FOLDER"/$bucket_name
touch "$LOCAL_FOLDER"/$object
bucket_exists_remote_and_local $bucket_name || local bucket_exists_two=$?
[[ $bucket_exists_two -eq 0 ]] || fail "Failed bucket existence check"
object_exists_remote_and_local $object || local object_exists_two=$?
[[ $object_exists_two -eq 0 ]] || fail "Failed object existence check"
rm "$LOCAL_FOLDER"/$object
sleep 1
object_not_exists_remote_and_local $object || local object_deleted=$?
[[ $object_deleted -eq 0 ]] || fail "Failed object deletion check"
rmdir "$LOCAL_FOLDER"/$bucket_name
sleep 1
bucket_not_exists_remote_and_local $bucket_name || local bucket_deleted=$?
[[ $bucket_deleted -eq 0 ]] || fail "Failed bucket deletion check"
}
+353
View File
@@ -0,0 +1,353 @@
#!/usr/bin/env bats
source ./tests/tests.sh
# create an AWS bucket
# param: bucket name
# return 0 for success, 1 for failure
create_bucket() {
if [ $# -ne 1 ]; then
echo "create bucket missing bucket name"
return 1
fi
local exit_code=0
local error
error=$(aws s3 mb s3://"$1" 2>&1) || exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "error creating bucket: $error"
return 1
fi
return 0
}
# delete an AWS bucket
# param: bucket name
# return 0 for success, 1 for failure
delete_bucket() {
if [ $# -ne 1 ]; then
echo "delete bucket missing bucket name"
return 1
fi
local exit_code=0
local error
error=$(aws s3 rb s3://"$1" 2>&1) || exit_code="$?"
if [ $exit_code -ne 0 ]; then
if [[ "$error" == *"The specified bucket does not exist"* ]]; then
return 0
else
echo "error deleting bucket: $error"
return 1
fi
fi
return 0
}
# check if bucket exists
# param: bucket name
# return 0 for true, 1 for false, 2 for error
bucket_exists() {
if [ $# -ne 1 ]; then
echo "bucket exists check missing bucket name"
return 2
fi
local exit_code=0
local error
error=$(aws s3 ls s3://"$1" 2>&1) || exit_code="$?"
echo "Exit code: $exit_code, error: $error"
if [ $exit_code -ne 0 ]; then
if [[ "$error" == *"The specified bucket does not exist"* ]] || [[ "$error" == *"Access Denied"* ]]; then
return 1
else
echo "error checking if bucket exists: $error"
return 2
fi
fi
return 0
}
# create bucket if it doesn't exist
# param: bucket name
# return 0 for success, 1 for failure
check_and_create_bucket() {
if [ $# -ne 1 ]; then
echo "bucket creation function requires bucket name"
return 1
fi
local exists_result
bucket_exists "$1" || exists_result=$?
if [[ $exists_result -eq 2 ]]; then
echo "Bucket existence check error"
return 1
fi
local create_result
if [[ $exists_result -eq 1 ]]; then
create_bucket "$1" || create_result=$?
if [[ $create_result -ne 0 ]]; then
echo "Error creating bucket"
return 1
fi
fi
return 0
}
# check if object exists on S3 via gateway
# param: object path
# return 0 for true, 1 for false, 2 for error
object_exists() {
if [ $# -ne 1 ]; then
echo "object exists check missing object name"
return 2
fi
local exit_code=0
local error
error=$(aws s3 ls s3://"$1" 2>&1) || exit_code="$?"
if [ $exit_code -ne 0 ]; then
if [[ "$error" == "" ]]; then
return 1
else
echo "error checking if object exists: $error"
return 2
fi
fi
return 0
}
# add object to versitygw
# params: source file, destination copy location
# return 0 for success, 1 for failure
put_object() {
if [ $# -ne 2 ]; then
echo "put object command requires source, destination"
return 1
fi
local exit_code=0
local error
error=$(aws s3 cp "$1" s3://"$2" 2>&1) || exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "error copying object to bucket: $error"
return 1
fi
return 0
}
# add object to versitygw if it doesn't exist
# params: source file, destination copy location
# return 0 for success or already exists, 1 for failure
check_and_put_object() {
if [ $# -ne 2 ]; then
echo "check and put object function requires source, destination"
return 1
fi
object_exists "$2" || local exists_result=$?
if [ $exists_result -eq 2 ]; then
echo "error checking if object exists"
return 1
fi
if [ $exists_result -eq 1 ]; then
put_object "$1" "$2" || local put_result=$?
if [ $put_result -ne 0 ]; then
echo "error adding object"
return 1
fi
fi
return 0
}
# delete object from versitygw
# param: object location
# return 0 for success, 1 for failure
delete_object() {
if [ $# -ne 1 ]; then
echo "delete object command requires object parameter"
return 1
fi
local exit_code=0
local error
error=$(aws s3 rm s3://"$1" 2>&1) || exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "error deleting object: $error"
return 1
fi
return 0
}
# list buckets on versitygw
# no params
# export bucket_array (bucket names) on success, return 1 for failure
list_buckets() {
local exit_code=0
local output
output=$(aws s3 ls 2>&1) || exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "error listing buckets: $output"
return 1
fi
bucket_array=()
while IFS= read -r line; do
bucket_name=$(echo "$line" | awk '{print $NF}')
bucket_array+=("$bucket_name")
done <<< "$output"
export bucket_array
}
# list objects on versitygw, in bucket or folder
# param: path of bucket or folder
# export object_array (object names) on success, return 1 for failure
list_objects() {
if [ $# -ne 1 ]; then
echo "list objects command requires bucket or folder"
return 1
fi
local exit_code=0
local output
output=$(aws s3 ls s3://"$1" 2>&1) || exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "error listing objects: $output"
return 1
fi
object_array=()
while IFS= read -r line; do
object_name=$(echo "$line" | awk '{print $NF}')
object_array+=("$object_name")
done <<< "$output"
export object_array
}
# test creation and deletion of bucket on versitygw
@test "create_delete_bucket_test" {
local bucket_name="versity-gwtest-create-delete-bucket-test"
bucket_exists $bucket_name || local exists=$?
if [[ $exists -eq 2 ]]; then
fail "Bucket existence check error"
fi
if [[ $exists -eq 0 ]]; then
delete_bucket $bucket_name || local delete_result=$?
[[ $delete_result -eq 0 ]] || fail "Failed to delete bucket"
bucket_exists $bucket_name || local exists_two=$?
[[ $exists_two -eq 1 ]] || fail "Failed bucket deletion"
fi
create_bucket $bucket_name || local create_result=$?
[[ $create_result -eq 0 ]] || fail "Failed to create bucket"
bucket_exists $bucket_name || local exists_three=$?
[[ $exists_three -eq 0 ]] || fail "Failed bucket existence check"
delete_bucket $bucket_name || local delete_result_two=$?
[[ $delete_result_two -eq 0 ]] || fail "Failed to delete bucket"
}
# test adding and removing an object on versitygw
@test "put_object_test" {
local bucket_name="versity-gwtest-put-object-test"
local object_name="test-object"
bucket_exists $bucket_name || local bucket_exists=$?
if [[ $bucket_exists -eq 2 ]]; then
fail "Bucket existence check error"
fi
local object="$bucket_name"/"$object_name"
if [[ $bucket_exists -eq 0 ]]; then
object_exists "$object" || local object_exists=$?
if [[ $object_exists -eq 2 ]]; then
fail "Object existence check error"
fi
if [[ $object_exists -eq 0 ]]; then
delete_object "$object" || local delete_object=$?
[[ $delete_object -eq 0 ]] || fail "Failed to delete object"
fi
delete_bucket $bucket_name || local delete_bucket=$?
[[ $delete_bucket -eq 0 ]] || fail "Failed to delete bucket"
fi
touch "$object_name"
create_bucket $bucket_name || local create_bucket=$?
[[ $create_bucket -eq 0 ]] || fail "Failed to create bucket"
put_object "$object_name" "$object" || local put_object=$?
[[ $put_object -eq 0 ]] || fail "Failed to add object to bucket"
object_exists "$object" || local object_exists_two=$?
[[ $object_exists_two -eq 0 ]] || fail "Object not added to bucket"
delete_object "$object" || local delete_object_two=$?
[[ $delete_object_two -eq 0 ]] || fail "Failed to delete object"
delete_bucket $bucket_name || local delete_bucket=$?
[[ $delete_bucket -eq 0 ]] || fail "Failed to delete bucket"
rm "$object_name"
}
# test listing buckets on versitygw
@test "test_list_buckets" {
bucket_name_one="versity-gwtest-list-one"
bucket_name_two="versity-gwtest-list-two"
bucket_exists $bucket_name_one || local exists=$?
if [[ $exists -eq 2 ]]; then
fail "Bucket existence check error"
fi
if [[ $exists -eq 1 ]]; then
create_bucket $bucket_name_one || local bucket_create_one=$?
[[ $bucket_create_one -eq 0 ]] || fail "Failed to create bucket"
fi
bucket_exists $bucket_name_two || local exists_two=$?
if [[ $exists_two -eq 2 ]]; then
fail "Bucket existence check error"
fi
if [[ $exists_two -eq 1 ]]; then
create_bucket $bucket_name_two || local bucket_create_two=$?
[[ $bucket_create_two -eq 0 ]] || fail "Failed to create bucket"
fi
list_buckets
local bucket_one_found=false
local bucket_two_found=false
for bucket in "${bucket_array[@]}"; do
if [ "$bucket" == $bucket_name_one ]; then
bucket_one_found=true
elif [ "$bucket" == $bucket_name_two ]; then
bucket_two_found=true
fi
if [ $bucket_one_found == true ] && [ $bucket_two_found == true ]; then
return
fi
done
fail "$bucket_name_one and/or $bucket_name_two not listed (all buckets: ${bucket_array[*]})"
delete_bucket $bucket_name_one || local deleted_one=$?
[[ $deleted_one -eq 0 ]] || fail "Failed to delete bucket one"
delete_bucket $bucket_name_two || local deleted_two=$?
[[ $deleted_two -eq 0 ]] || fail "Failed to delete bucket one"
}
# test listing a bucket's objects on versitygw
@test test_list_objects {
bucket_name="versity-gwtest-list-object"
object_one="test-file-one"
object_two="test-file-two"
touch $object_one $object_two
check_and_create_bucket $bucket_name || local result_one=$?
[[ result_one -eq 0 ]] || fail "Error creating bucket"
put_object $object_one "$bucket_name"/"$object_one" || local result_two=$?
[[ result_two -eq 0 ]] || fail "Error adding object one"
put_object $object_two "$bucket_name"/"$object_two" || local result_three=$?
[[ result_three -eq 0 ]] || fail "Error adding object two"
list_objects $bucket_name
local object_one_found=false
local object_two_found=false
for object in "${object_array[@]}"; do
if [ "$object" == $object_one ]; then
object_one_found=true
elif [ "$object" == $object_two ]; then
object_two_found=true
fi
done
if [ $object_one_found != true ] || [ $object_two_found != true ]; then
fail "$object_one and/or $object_two not listed (all objects: ${object_array[*]})"
fi
delete_object "$bucket_name"/"$object_one"
delete_object "$bucket_name"/"$object_two"
delete_bucket $bucket_name
rm $object_one $object_two
}
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env bats
setup() {
if [ "$GITHUB_ACTIONS" != "true" ] && [ -r .secrets ]; then
source .secrets
else
echo "Warning: no secrets file found"
fi
if [ -z "$VERSITYGW_TEST_ENV" ]; then
if [ -r tests/.env ]; then
source tests/.env
else
echo "Warning: no .env file found in tests folder"
fi
else
echo "$VERSITYGW_TEST_ENV"
source $VERSITYGW_TEST_ENV
fi
if [ -z "$AWS_ACCESS_KEY_ID" ]; then
echo "No AWS access key set"
return 1
elif [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
echo "No AWS secret access key set"
return 1
elif [ -z "$VERSITY_EXE" ]; then
echo "No versity executable location set"
return 1
elif [ -z "$BACKEND" ]; then
echo "No backend parameter set (options: 'posix')"
return 1
elif [ -z "$AWS_REGION" ]; then
echo "No AWS region set"
return 1
elif [ -z "$AWS_PROFILE" ]; then
echo "No AWS profile set"
return 1
elif [ -z "$LOCAL_FOLDER" ]; then
echo "No local storage folder set"
return 1
elif [ -z "$AWS_ENDPOINT_URL" ]; then
echo "No AWS endpoint URL set"
return 1
fi
ROOT_ACCESS_KEY="$AWS_ACCESS_KEY_ID" ROOT_SECRET_KEY="$AWS_SECRET_ACCESS_KEY" "$VERSITY_EXE" "$BACKEND" "$LOCAL_FOLDER" &
export AWS_REGION
export AWS_PROFILE
export AWS_ENDPOINT_URL
export LOCAL_FOLDER
versitygw_pid=$!
export versitygw_pid
}
fail() {
echo "$1"
return 1
}
teardown() {
if [ -n "$versitygw_pid" ]; then
if ps -p "$versitygw_pid" > /dev/null; then
kill "$versitygw_pid"
wait "$versitygw_pid" || true
else
echo "Process with PID $versitygw_pid does not exist."
fi
else
echo "versitygw_pid is not set or empty."
fi
}