mirror of
https://github.com/nextcloud/nextcloudpi.git
synced 2026-01-09 06:32:00 -03:30
Add basic integration test for nc-backup
Signed-off-by: Tobias K <6317548+theCalcaholic@users.noreply.github.com> Signed-off-by: Tobias Knöppler <6317548+theCalcaholic@users.noreply.github.com>
This commit is contained in:
parent
cde1b44063
commit
b69ad71507
178
tests/NcpRobotLib.py
Normal file
178
tests/NcpRobotLib.py
Normal file
@ -0,0 +1,178 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from subprocess import PIPE
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
from typing import Dict
|
||||
from robot.api import FatalError, Error, logger
|
||||
import tempfile
|
||||
|
||||
|
||||
class NcpRobotLib:
|
||||
ROBOT_LIBRARY_SCOPE = "SUITE"
|
||||
|
||||
def __init__(self, http_port=80, https_port=443, webui_port=4443):
|
||||
self._http_port = http_port
|
||||
self._https_port = https_port
|
||||
self._webui_port = webui_port
|
||||
self._docker: Dict[str, any] = {
|
||||
'container': None
|
||||
}
|
||||
|
||||
def setup_ncp(self, instance_type, version):
|
||||
if instance_type == 'docker':
|
||||
container_name = 'nextcloudpi-' + ''.join(random.choice(string.digits) for i in range(6))
|
||||
image = version if ':' in version else f"ownyourbits/nextcloudpi:{version}"
|
||||
d_run = subprocess.run([
|
||||
'docker', 'run', '-d',
|
||||
'-p', f'127.0.0.1:{self._http_port}:80',
|
||||
'-p', f'127.0.0.1:{self._https_port}:443',
|
||||
'-p', f'127.0.0.1:{self._webui_port}:4443',
|
||||
'--name', container_name,
|
||||
image, 'localhost'
|
||||
],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
if d_run.returncode != 0:
|
||||
raise FatalError(f"Failed to start test instance: \n'{d_run.stderr}'")
|
||||
|
||||
self._docker['container'] = container_name
|
||||
logger.info("Waiting for container startup")
|
||||
time.sleep(20)
|
||||
self.ncp_is_running()
|
||||
|
||||
else:
|
||||
raise FatalError(f"Invalid instance type '{instance_type}'")
|
||||
|
||||
def ncp_is_running(self):
|
||||
|
||||
d_run = subprocess.run(['docker', 'container', 'ls', '--filter', f'name={self._docker["container"]}'],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
re_string = r'.* Up.* ' + self._docker['container'] + r'.*'
|
||||
docker_success_re = re.compile(re_string, flags=re.DOTALL)
|
||||
|
||||
if not docker_success_re.match(d_run.stdout.decode('utf-8')):
|
||||
raise AssertionError(f"Failed to start test instance: 'Container status is not 'Up'")
|
||||
|
||||
def destroy_ncp(self):
|
||||
# time.sleep(60)
|
||||
if self._docker['container'] is None:
|
||||
raise Error("Container not running")
|
||||
|
||||
_ = subprocess.run(['docker', 'stop', self._docker['container']])
|
||||
try:
|
||||
self.ncp_is_running()
|
||||
raise FatalError("Failed to stop instance - ncp is still running")
|
||||
except AssertionError:
|
||||
pass
|
||||
finally:
|
||||
d_run = subprocess.run(['docker', 'rm', self._docker['container']])
|
||||
err = None
|
||||
if d_run.returncode != 0:
|
||||
err = FatalError(f"Failed to delete container {self._docker['container']}")
|
||||
self._docker['container'] = None
|
||||
if err is not None:
|
||||
raise FatalError(err)
|
||||
|
||||
def create_backup_in(self, target, *args):
|
||||
logger.info(f"Creating backup in {target}...")
|
||||
self.ncp_is_running()
|
||||
backup_cfg = {
|
||||
"id": "nc-backup",
|
||||
"name": "nc-backup",
|
||||
"title": "nc-backup",
|
||||
"description": "Backup this NC instance to a file",
|
||||
"info": "This will always include the current Nextcloud directory and the Database.\nYou can choose to include or exclude NC-data.",
|
||||
"infotitle": "",
|
||||
"params": [
|
||||
{
|
||||
"id": "DESTDIR",
|
||||
"name": "Destination directory",
|
||||
"value": target,
|
||||
"suggest": "/media/USBdrive/ncp-backups"
|
||||
},
|
||||
{
|
||||
"id": "INCLUDEDATA",
|
||||
"name": "Include data",
|
||||
"value": "no" if 'dataless' in args else "yes",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "COMPRESS",
|
||||
"name": "Compress",
|
||||
"value": "yes" if 'compressed' in args else "no",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "BACKUPLIMIT",
|
||||
"name": "Number of backups to keep",
|
||||
"value": "99",
|
||||
"suggest": "4"
|
||||
}
|
||||
]
|
||||
}
|
||||
temp_dir = tempfile.TemporaryDirectory()
|
||||
tmp_file_path = os.path.join(temp_dir.name, 'nc-backup.cfg')
|
||||
with open(tmp_file_path, 'w') as f:
|
||||
json.dump(backup_cfg, f)
|
||||
|
||||
backup_config_path = '/data/ncp/nc-backup.cfg'
|
||||
d_run = self.run_on_ncp('rm', backup_config_path)
|
||||
logger.info(d_run.stdout)
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f"Unexpected error: {d_run.stderr}")
|
||||
|
||||
d_run = subprocess.run(['docker', 'cp', tmp_file_path, f'{self._docker["container"]}:{backup_config_path}'])
|
||||
logger.info(d_run.stdout)
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f"Unexpected error: {d_run.stderr}")
|
||||
|
||||
temp_dir.cleanup()
|
||||
|
||||
d_run = self.run_on_ncp('chown', 'root:www-data', backup_config_path)
|
||||
logger.info(d_run.stdout)
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f"Unexpected error: {d_run.stderr}")
|
||||
|
||||
d_run = self.run_on_ncp('chmod', '660', backup_config_path)
|
||||
logger.info(d_run.stdout)
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f"Unexpected error: {d_run.stderr}")
|
||||
|
||||
d_run = self.run_on_ncp('bash', '-c', "set -x "
|
||||
"&& source /usr/local/etc/library.sh "
|
||||
"&& echo \"ncp library loaded.\" "
|
||||
"&& run_app nc-backup")
|
||||
logger.info(d_run.stdout)
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f"An error occurred while creating backup: \n{d_run.stderr}")
|
||||
|
||||
def run_on_ncp(self, *command):
|
||||
run_cmd = ['docker', 'exec', self._docker['container']]
|
||||
run_cmd.extend(command)
|
||||
logger.debug(f"Executing: '{run_cmd}'")
|
||||
return subprocess.run(run_cmd, stdout=PIPE, stderr=PIPE)
|
||||
|
||||
def assert_file_exists_in_archive(self, backup_path, file, silent=False):
|
||||
if not silent:
|
||||
logger.info(f"Checking if '{file}' exists in any archive in '{backup_path}'")
|
||||
d_run = self.run_on_ncp('bash', '-c', f'compgen -G "{backup_path}"')
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f'No such backup: {backup_path}')
|
||||
archive = d_run.stdout.decode('utf-8').split('\n')[0]
|
||||
d_run = self.run_on_ncp('tar', '-tf', archive)
|
||||
if d_run.returncode != 0:
|
||||
raise AssertionError(f'Error reading archive: {archive}')
|
||||
match = re.search(file, d_run.stdout.decode('utf-8'))
|
||||
if match is None:
|
||||
raise AssertionError(f'File not found in backup: {file}')
|
||||
|
||||
def assert_file_exists_not_in_archive(self, backup_path, file):
|
||||
logger.info(f"Checking that '{file}' does not exist in any archive in '{backup_path}'")
|
||||
try:
|
||||
self.assert_file_exists_in_archive(backup_path, file, True)
|
||||
raise AssertionError(f"File unexpectedly found in backup: {file}")
|
||||
except AssertionError:
|
||||
pass
|
||||
23
tests/nc_backup_test.robot
Normal file
23
tests/nc_backup_test.robot
Normal file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
*** Settings ***
|
||||
Library NcpRobotLib.py 8080 8443 4443
|
||||
Suite Setup Setup Ncp docker latest
|
||||
Suite Teardown Destroy Ncp
|
||||
Test Teardown Run on Ncp rm -rf /opt/ncp-backups/*.tar
|
||||
|
||||
*** Test Cases ***
|
||||
|
||||
Create dataless Backup
|
||||
#[Documentation] Creates and validates a backup using nc-backup
|
||||
Create Backup in /opt/ncp-backups dataless
|
||||
Assert file exists in archive /opt/ncp-backups/*.tar nextcloud/config/config.php
|
||||
Assert file exists in archive /opt/ncp-backups/*.tar nextcloud-sqlbkp_.*.bak
|
||||
Assert file exists not in archive /opt/ncp-backups/*.tar ncdata/files/ncp
|
||||
|
||||
Create Backup with data
|
||||
#[Documentation] Creates and validates a backup using nc-backup
|
||||
Create Backup in /opt/ncp-backups
|
||||
Assert file exists in archive /opt/ncp-backups/*.tar nextcloud/config/config.php
|
||||
Assert file exists in archive /opt/ncp-backups/*.tar nextcloud-sqlbkp_.*.bak
|
||||
Assert file exists in archive /opt/ncp-backups/*.tar data/ncp/files/Nextcloud.png
|
||||
2
tests/requirements.txt
Normal file
2
tests/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
selenium~=4.7
|
||||
robotframework~=6.0
|
||||
Loading…
x
Reference in New Issue
Block a user