From: Dan Brown Date: Mon, 3 Apr 2023 16:26:09 +0000 (+0100) Subject: Started testing of backup command X-Git-Url: http://source.bookstackapp.com/system-cli/commitdiff_plain/0248e2c0d91d7dab5bb7d4da26b9a558b5497be1 Started testing of backup command Came across a couple of issues during build: 1. DB needed init SQL query to fix user permissions to allow backup, added detail to readme in new "known issues". 2. App container work needed to wait for database to be alive. --- diff --git a/docker-compose.yml b/docker-compose.yml index 9499d98..e41da62 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.8" +version: "3.9" services: app: @@ -7,11 +7,14 @@ services: volumes: - ./:/cli depends_on: - - db + db: + condition: service_completed_successfully db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: bookstack MYSQL_USER: bookstack - MYSQL_PASSWORD: bookstack \ No newline at end of file + MYSQL_PASSWORD: bookstack + volumes: + - ./docker-mysql-init.sql:/docker-entrypoint-initdb.d/init.sql \ No newline at end of file diff --git a/docker-mysql-init.sql b/docker-mysql-init.sql new file mode 100644 index 0000000..e90c66d --- /dev/null +++ b/docker-mysql-init.sql @@ -0,0 +1 @@ +GRANT RELOAD ON *.* TO 'bookstack'@'%'; \ No newline at end of file diff --git a/readme.md b/readme.md index 22bd0c3..064e134 100644 --- a/readme.md +++ b/readme.md @@ -55,4 +55,15 @@ Within the environment a pre-existing BookStack instance can be found at `/var/w ### Contributing I welcome issues and PRs but keep in mind that I'd like to keep the feature-set narrow to limit support/maintenance burden. -Therefore, I likely won't leave issues open long, or merge PRs, for requests to add new features or for changes that increase the scope of what this script already supports. \ No newline at end of file +Therefore, I likely won't leave issues open long, or merge PRs, for requests to add new features or for changes that increase the scope of what this script already supports. + +### Known Issues + +#### mysqldump - Couldn't execute 'FLUSH TABLES' + +mysqldump may produce the following: + +> mysqldump: Couldn't execute 'FLUSH TABLES': Access denied; you need (at least one of) the RELOAD or FLUSH_TABLES privilege(s) for this operation (1227) + +This was due to 8.0.32 mysqldump, changing the required permissions, and this should be largely [fixed as per 8.0.33](https://bugs.mysql.com/bug.php?id=109685). +Temporary workaround is to provide the database user RELOAD permissions: `GRANT RELOAD ON *.* TO 'bookstack'@'%';` \ No newline at end of file diff --git a/src/Commands/BackupCommand.php b/src/Commands/BackupCommand.php index 7c3730a..05d90c7 100644 --- a/src/Commands/BackupCommand.php +++ b/src/Commands/BackupCommand.php @@ -49,9 +49,12 @@ final class BackupCommand extends Command $zip = new ZipArchive(); $zip->open($zipTempFile, ZipArchive::CREATE); - // Add default files (.env config file and this CLI) + // Add default files (.env config file and this CLI if existing) $zip->addFile($appDir . DIRECTORY_SEPARATOR . '.env', '.env'); - $zip->addFile($appDir . DIRECTORY_SEPARATOR . 'scripts' . DIRECTORY_SEPARATOR . 'run', 'run'); + $cliPath = $appDir . DIRECTORY_SEPARATOR . 'bookstack-system-cli'; + if (file_exists($cliPath)) { + $zip->addFile($cliPath, 'bookstack-system-cli'); + } if ($handleDatabase) { $output->writeln("Dumping the database via mysqldump..."); diff --git a/src/Services/MySqlRunner.php b/src/Services/MySqlRunner.php index b61bf66..5b130a5 100644 --- a/src/Services/MySqlRunner.php +++ b/src/Services/MySqlRunner.php @@ -86,7 +86,9 @@ class MySqlRunner fwrite($file, $data); $hasOutput = true; }, function ($error) use (&$errors) { - $errors .= $error . "\n"; + if (!str_contains($error, '[Warning] ')) { + $errors .= $error . "\n"; + } }); } catch (\Exception $exception) { fclose($file); diff --git a/tests/CommandResult.php b/tests/CommandResult.php index 492e216..011f022 100644 --- a/tests/CommandResult.php +++ b/tests/CommandResult.php @@ -20,7 +20,21 @@ class CommandResult public function assertSuccessfulExit(): void { - Assert::assertEquals(0, $this->tester->getStatusCode()); + try { + $statusCode = $this->tester->getStatusCode(); + } catch (\Exception $exception) { + $statusCode = 1; + } + + Assert::assertEquals(0, $statusCode); + } + + public function dumpError(): void + { + if ($this->error) { + echo $this->error->getMessage() . "\n" . + $this->error->getTraceAsString(); + } } public function assertErrorExit(): void diff --git a/tests/Commands/BackupCommandTest.php b/tests/Commands/BackupCommandTest.php new file mode 100644 index 0000000..7f598d7 --- /dev/null +++ b/tests/Commands/BackupCommandTest.php @@ -0,0 +1,47 @@ +assertCount(0, glob('bookstack-backup-*.zip')); + + file_put_contents('/var/www/bookstack/themes/test.txt', static::$uniqueUserEmail . '-themes'); + file_put_contents('/var/www/bookstack/public/uploads/test.txt', static::$uniqueUserEmail . '-public-uploads'); + file_put_contents('/var/www/bookstack/storage/uploads/test.txt', static::$uniqueUserEmail . '-storage-uploads'); + + $result = $this->runCommand('backup'); + $result->dumpError(); + $result->assertSuccessfulExit(); + $result->assertStdoutContains("Backup finished."); + + $this->assertCount(1, glob('bookstack-backup-*.zip')); + $zipFile = glob('bookstack-backup-*.zip')[0]; + + $zip = new \ZipArchive(); + $zip->open($zipFile); + $dbDump = $zip->getFromName('db.sql'); + $this->assertStringContainsString('APP_KEY=', $zip->getFromName('.env')); + $this->assertStringContainsString(static::$uniqueUserEmail, $dbDump); + $this->assertStringContainsString('page_revisions', $dbDump); + $this->assertStringContainsString(static::$uniqueUserEmail . '-public-uploads', $zip->getFromName('public/uploads/test.txt')); + $this->assertStringContainsString(static::$uniqueUserEmail . '-storage-uploads', $zip->getFromName('storage/uploads/test.txt')); + $this->assertStringContainsString(static::$uniqueUserEmail . '-themes', $zip->getFromName('themes/test.txt')); + } +} \ No newline at end of file