Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix running backup and restore plugin #709

Merged
merged 7 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading