Skip to content

Commit

Permalink
Fix running backup and restore plugin (#709)
Browse files Browse the repository at this point in the history
* Fix running backup and restore plugin
  • Loading branch information
NyakudyaA authored Jan 3, 2025
1 parent b2031b8 commit ae25c98
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-latest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ jobs:
# - clustering
- jdbconfig
- libjpeg
- backup_restore
steps:
- uses: actions/checkout@v4
- name: Download artifact
Expand Down
54 changes: 54 additions & 0 deletions scenario_tests/backup_restore/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

volumes:
geoserver-data-dir:
geoserver-data:
geoserver-backup-dir:


services:

geoserver:
image: 'kartoza/geoserver:${TAG:-manual-build}'
restart: 'always'
volumes:
- geoserver-data-dir:/opt/geoserver/data_dir
- geoserver-backup-dir:/settings
- ./tests:/tests
environment:
GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver
GEOSERVER_ADMIN_USER: admin
SAMPLE_DATA: true
CONSOLE_HANDLER_LEVEL: WARNING
COMMUNITY_EXTENSIONS: backup-restore-plugin
TEST_CLASS: test_geoserver_backup.TestGeoServerBackup
ports:
- "8080:8080"
healthcheck:
test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"]
interval: 1m30s
timeout: 10s
retries: 3

restore:
image: 'kartoza/geoserver:${TAG:-manual-build}'
restart: 'always'
volumes:
- geoserver-data:/opt/geoserver/data_dir
- geoserver-backup-dir:/settings
- ./tests:/tests
environment:
GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver
GEOSERVER_ADMIN_USER: admin
CONSOLE_HANDLER_LEVEL: WARNING
RECREATE_DATADIR: TRUE
COMMUNITY_EXTENSIONS: backup-restore-plugin
TEST_CLASS: test_geoserver_restore.TestGeoServerRestore
ports:
- "8080"
healthcheck:
test: [ "CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml" ]
interval: 1m30s
timeout: 10s
retries: 3


44 changes: 44 additions & 0 deletions scenario_tests/backup_restore/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash

# exit immediately if test fails
set -e

source ../test-env.sh

# Run service
if [[ $(dpkg -l | grep "docker-compose") > /dev/null ]];then
VERSION='docker-compose'
else
VERSION='docker compose'
fi

${VERSION} -f docker-compose.yml up -d

if [[ -n "${PRINT_TEST_LOGS}" ]]; then
${VERSION} -f docker-compose.yml logs -f &
fi


services=("geoserver")

for service in "${services[@]}"; do

# Execute tests
test_url_availability http://localhost:8080/geoserver/rest/about/version.xml
echo "Execute test for $service"
${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh

done

services=("restore")

for service in "${services[@]}"; do

# Execute tests
test_url_availability http://localhost:8080/geoserver/rest/about/version.xml
echo "Execute test for $service"
${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh

done

${VERSION} -f docker-compose.yml down -v
Empty file.
17 changes: 17 additions & 0 deletions scenario_tests/backup_restore/tests/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

set -e

source /scripts/env-data.sh

# execute tests
pushd /tests

cat << EOF
Settings used:
GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD}
GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER}
EOF

python3 -m unittest -v ${TEST_CLASS}
73 changes: 73 additions & 0 deletions scenario_tests/backup_restore/tests/test_geoserver_backup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import unittest
import requests
from requests.auth import HTTPBasicAuth
from os import environ, mkdir, chmod
from os.path import join, exists
from shutil import chown
import json
import time


class TestGeoServerBackup(unittest.TestCase):

def setUp(self):
"""Set up the base URL, authentication, and create the zip file."""
self.gs_url = 'http://localhost:8080/geoserver'
self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin')
self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver')
self.username = 'geoserveruser'
self.group_name = 'geoserverusers'
self.backup_path = "/settings/backup/"

def test_create_backup(self):
"""Test creating a GeoServer backup using the Backup and Restore plugin."""
auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password)
base_url = f"{self.gs_url}/rest/br/backup/"
if not exists(self.backup_path):
mkdir(self.backup_path)
backup_file = join(self.backup_path, 'geoserver.zip')
# Create the empty zip file
with open(backup_file, "wb") as f:
pass

# Change ownership of the zip file
chmod(self.backup_path, 0o777)
chown(backup_file, user=self.username, group=self.group_name)
headers = {
"Content-Type": "application/json"
}

payload = {
"backup": {
"archiveFile": backup_file,
"overwrite": True,
"options": {}
}
}

# Send the POST request to trigger the backup
response = requests.post(base_url, json=payload, auth=auth, headers=headers)
response_data = json.loads(response.text)
execution_id = response_data["backup"]["execution"]["id"]
execution_url = f"{self.gs_url}/rest/br/backup/{execution_id}.json"
# wait for backup to complete
time.sleep(40)
response_execution_request = requests.get(execution_url, auth=auth)
if response_execution_request.status_code == 200:
try:
response_execution_json = response_execution_request.json()
response_status = response_execution_json["backup"]["execution"]["status"]
self.assertEqual(response_status, 'COMPLETED', "backup initiated successfully")
except ValueError as e:
print("Error parsing JSON:", e)
print("Raw response content:", response_execution_request.text)
else:
print(f"Request failed with status code {response_execution_request.status_code}")
print("Response content:", response_execution_request.text)

# Verify the response status code
self.assertEqual(response.status_code, 201, "backup initiated successfully")


if __name__ == "__main__":
unittest.main()
67 changes: 67 additions & 0 deletions scenario_tests/backup_restore/tests/test_geoserver_restore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import sys
import unittest
import requests
from requests.auth import HTTPBasicAuth
from os import environ, chmod
from os.path import join, exists
import json
import time


class TestGeoServerRestore(unittest.TestCase):

def setUp(self):
"""Set up the base URL, authentication, and create the zip file."""
self.gs_url = 'http://localhost:8080/geoserver'
self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin')
self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver')
self.backup_path = "/settings/backup/"

def test_restore_backup(self):
"""Test restoring an existing backup of a GeoServer instance using the Backup and Restore plugin."""
auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password)
base_url = f"{self.gs_url}/rest/br/restore/"
backup_file = join(self.backup_path, 'geoserver.zip')
chmod(self.backup_path, 0o777)
if not exists(backup_file):
sys.exit()

headers = {
"Content-Type": "application/json"
}

payload = {
"restore": {
"archiveFile": backup_file,
"options": {
"option": ["BK_BEST_EFFORT=true"]
}
}
}

# Send the POST request to trigger the backup
response = requests.post(base_url, json=payload, auth=auth, headers=headers)
response_data = json.loads(response.text)
execution_id = response_data["restore"]["execution"]["id"]
execution_url = f"{self.gs_url}/rest/br/restore/{execution_id}.json"
# wait for backup to complete
time.sleep(30)
response_execution_request = requests.get(execution_url, auth=auth)
if response_execution_request.status_code == 200:
try:
response_execution_json = response_execution_request.json()
response_status = response_execution_json["restore"]["execution"]["status"]
self.assertEqual(response_status, 'COMPLETED', "backup initiated successfully")
except ValueError as e:
print("Error parsing JSON:", e)
print("Raw response content:", response_execution_request.text)
else:
print(f"Request failed with status code {response_execution_request.status_code}")
print("Response content:", response_execution_request.text)

# Verify the response status code
self.assertEqual(response.status_code, 201, "backup initiated successfully")


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion scripts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export JAVA_OPTS="${JAVA_OPTS} ${GEOSERVER_OPTS}"
# Chown again - seems to fix issue with resolving all created directories
if [[ ${RUN_AS_ROOT} =~ [Ff][Aa][Ll][Ss][Ee] ]];then
dir_ownership=("${CATALINA_HOME}" /home/"${USER_NAME}"/ "${COMMUNITY_PLUGINS_DIR}"
"${STABLE_PLUGINS_DIR}" "${REQUIRED_PLUGINS_DIR}" "${GEOSERVER_HOME}" /usr/share/fonts/ /tomcat_apps.zip
"${STABLE_PLUGINS_DIR}" "${REQUIRED_PLUGINS_DIR}" "${GEOSERVER_HOME}" /usr/share/fonts/
/tmp/ "${FOOTPRINTS_DATA_DIR}" "${CERT_DIR}" "${FONTS_DIR}" /scripts/
"${EXTRA_CONFIG_DIR}" "/docker-entrypoint-geoserver.d" "${MONITOR_AUDIT_PATH}")
for directory in "${dir_ownership[@]}"; do
Expand Down
6 changes: 3 additions & 3 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,16 @@ rm -f /tmp/resources/overlays/README.txt &&
# Package tomcat webapps - useful to activate later
if [[ -d "${CATALINA_HOME}"/webapps.dist ]]; then
mv "${CATALINA_HOME}"/webapps.dist /tomcat_apps
zip -r /tomcat_apps.zip /tomcat_apps
zip -r "${REQUIRED_PLUGINS_DIR}"/tomcat_apps.zip /tomcat_apps
rm -r /tomcat_apps
else
cp -r "${CATALINA_HOME}"/webapps/ROOT /tomcat_apps
cp -r "${CATALINA_HOME}"/webapps/docs /tomcat_apps
cp -r "${CATALINA_HOME}"/webapps/examples /tomcat_apps
cp -r "${CATALINA_HOME}"/webapps/host-manager /tomcat_apps
cp -r "${CATALINA_HOME}"/webapps/manager /tomcat_apps
zip -r /tomcat_apps.zip /tomcat_apps
rm -r /tomcat_apps
zip -r "${REQUIRED_PLUGINS_DIR}"/tomcat_apps.zip /tomcat_apps
rm -rf /tomcat_apps
fi

pushd ${CATALINA_HOME}/lib || exit
Expand Down
8 changes: 6 additions & 2 deletions scripts/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,12 @@ fi


if [[ "${TOMCAT_EXTRAS}" =~ [Tt][Rr][Uu][Ee] ]]; then
unzip -qq /tomcat_apps.zip -d /tmp/ &&
cp -r /tmp/tomcat_apps/webapps.dist/* "${CATALINA_HOME}"/webapps/ &&
unzip -qq "${REQUIRED_PLUGINS_DIR}"/tomcat_apps.zip -d /tmp/
if [[ -d /tmp/tomcat_apps/webapps.dist ]];then
cp -r /tmp/tomcat_apps/webapps.dist/* "${CATALINA_HOME}"/webapps/
else
cp -r /tmp/tomcat_apps/* "${CATALINA_HOME}"/webapps/
fi
rm -r /tmp/tomcat_apps
if [[ ${POSTGRES_JNDI} =~ [Ff][Aa][Ll][Ss][Ee] ]]; then
if [[ -f ${EXTRA_CONFIG_DIR}/context.xml ]]; then
Expand Down

0 comments on commit ae25c98

Please sign in to comment.