Compare commits

...
Author SHA1 Message Date
shimon a9cbad0991 folder backup 2023-03-01 16:55:20 +02:00
shimon 3b58eede44 folder backup 2023-03-01 15:21:16 +02:00
shimon 3c858caaa2 folder backup 2023-03-01 13:45:05 +02:00
shimon 0e9286d2f5 folder backup 2023-02-28 19:32:30 +02:00
shimon 0d7c11f19b folder backup 2023-02-28 09:35:57 +02:00
shimon 7f854b5c87 folder backup 2023-02-27 13:58:24 +02:00
shimon 890a9d4e1f folder backup 2023-02-27 13:22:53 +02:00
shimon 498b0a1c47 Merge remote-tracking branch 'origin/feat-cloud-folder-backup' into feat-cloud-folder-backup 2023-02-27 13:15:21 +02:00
shimon 0c29345d40 folder backup 2023-02-27 13:15:04 +02:00
d9b55b4b04 Update src/Appwrite/Platform/Tasks/FolderBackup.php
Co-authored-by: Eldad A. Fux <eldad.fux@gmail.com>
2023-02-27 08:36:00 +02:00
shimon cffe8173ba folder backup 2023-02-26 18:49:52 +02:00
shimon 9df3d47402 Merge remote-tracking branch 'origin/feat-cloud-folder-backup' into feat-cloud-folder-backup 2023-02-26 18:47:07 +02:00
shimon cf551b96dc folder backup 2023-02-26 18:46:57 +02:00
Shimon NewmanandGitHub cf615423e9 Delete .env 2023-02-26 18:44:54 +02:00
shimon bdca6c88c7 folder backup 2023-02-26 18:39:31 +02:00
shimon e585142490 folder backup 2023-02-26 18:36:42 +02:00
shimon b747e30d3f folder backup 2023-02-26 14:07:26 +02:00
shimon 58d2f7f3ce video tests 2023-02-23 19:32:32 +02:00
shimon ef0ae4f5ce video tests 2023-02-23 19:19:22 +02:00
shimon 72d1bfb4c2 video tests 2023-02-23 19:18:58 +02:00
12 changed files with 279 additions and 25 deletions
+2 -4
View File
@@ -32,7 +32,7 @@ _APP_CONNECTIONS_DB_CONSOLE=db_fra1_01=mariadb://user:password@mariadb:3306/appw
_APP_CONNECTIONS_CACHE=redis_fra1_01=redis://redis:6379
_APP_CONNECTIONS_QUEUE=redis_fra1_01=redis://redis:6379
_APP_CONNECTIONS_PUBSUB=redis_fra1_01=redis://redis:6379
_APP_CONNECTIONS_STORAGE=local://localhost
_APP_CONNECTIONS_STORAGE=
_APP_STORAGE_ANTIVIRUS=disabled
_APP_STORAGE_ANTIVIRUS_HOST=clamav
_APP_STORAGE_ANTIVIRUS_PORT=3310
@@ -66,10 +66,8 @@ _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
_APP_USAGE_STATS=enabled
_APP_USAGE_AGGREGATION_INTERVAL=30
_APP_LOGGING_PROVIDER=
_APP_LOGGING_CONFIG=
_APP_GRAPHQL_MAX_BATCH_SIZE=10
_APP_GRAPHQL_MAX_COMPLEXITY=250
_APP_GRAPHQL_MAX_DEPTH=3
_APP_REGION=default
DOCKERHUB_PULL_USERNAME
DOCKERHUB_PULL_PASSWORD
_APP_BACKUP_HEARTBEAT=
+1 -1
View File
@@ -33,7 +33,7 @@
- Fix max mimetype size [#4814](https://github.com/appwrite/appwrite/pull/4814)
- New usage metrics collection flow [#4770](https://github.com/appwrite/appwrite/pull/4770)
- Deprecated influxdb, telegraf containers and removed all of their occurrences from the code.
- Removed _APP_INFLUXDB_HOST, _APP_INFLUXDB_PORT, _APP_STATSD_HOST, _APP_STATSD_PORT env variables.
- Removed _APP_INFLUXDB_HOST, _APP_INFLUXDB_PORT, _APP_STATSD_HOST, _APP_STATSD_PORT, _APP_USAGE_AGGREGATION_INTERVAL env variables.
- Removed usage labels dependency.
- Dropped type attribute from stats collection.
- Usage metrics are processed via new usage worker.
+3 -1
View File
@@ -132,7 +132,9 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/worker-mails && \
chmod +x /usr/local/bin/worker-messaging && \
chmod +x /usr/local/bin/worker-webhooks && \
chmod +x /usr/local/bin/worker-usage
chmod +x /usr/local/bin/worker-usage && \
chmod +x /usr/local/bin/backup && \
chmod +x /usr/local/bin/restore
# Letsencrypt Permissions
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
+25
View File
@@ -7,6 +7,7 @@ use Appwrite\Event\Func;
use Appwrite\Platform\Appwrite;
use Utopia\CLI\CLI;
use Utopia\Database\Validator\Authorization;
use Utopia\DSN\DSN;
use Utopia\Platform\Service;
use Utopia\App;
use Utopia\CLI\Console;
@@ -18,6 +19,14 @@ use Utopia\Database\Document;
use Utopia\Logger\Log;
use Utopia\Pools\Group;
use Utopia\Registry\Registry;
use Utopia\Storage\Device;
use Utopia\Storage\Device\Backblaze;
use Utopia\Storage\Device\DOSpaces;
use Utopia\Storage\Device\Linode;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\Wasabi;
use Utopia\Storage\Storage;
Authorization::disable();
@@ -121,6 +130,22 @@ CLI::setResource('queueForFunctions', function (Group $pools) {
return new Func($pools->get('queue')->pop()->getResource());
}, ['pools']);
CLI::setResource('deviceLocal', function () {
return new Local();
});
CLI::setResource('deviceFiles', function ($project) {
return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
}, ['project']);
CLI::setResource('deviceFunctions', function ($project) {
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
}, ['project']);
CLI::setResource('deviceBuilds', function ($project) {
return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId());
}, ['project']);
CLI::setResource('logError', function (Registry $register) {
return function (Throwable $error, string $namespace, string $action) use ($register) {
$logger = $register->get('logger');
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/cli.php backup $@
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
php /usr/src/code/app/cli.php restore $@
+2 -2
View File
@@ -47,7 +47,7 @@
"utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.20.*",
"utopia-php/cache": "0.8.*",
"utopia-php/cli": "0.14.*",
"utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.30.*",
"utopia-php/queue": "0.5.*",
@@ -63,7 +63,7 @@
"utopia-php/logger": "0.3.*",
"utopia-php/messaging": "0.1.*",
"utopia-php/registry": "0.5.*",
"utopia-php/storage": "0.13.*",
"utopia-php/storage": "dev-feat-transfer as 0.13.2",
"utopia-php/swoole": "0.5.*",
"utopia-php/websocket": "0.1.*",
"resque/php-resque": "1.3.6",
Generated
+26 -16
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "60f1cefcf6d210ed231acb4a99f2f20c",
"content-hash": "d82e08efceeebb37f8ed6b75972af70a",
"packages": [
{
"name": "adhocore/jwt",
@@ -2168,16 +2168,16 @@
},
{
"name": "utopia-php/storage",
"version": "0.13.2",
"version": "dev-feat-transfer",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "ad1c00f24ca56e73888acc2af3deee4919b1194b"
"reference": "00b26ef3d04b04f2df64a64636f6b81f8ae1a166"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/ad1c00f24ca56e73888acc2af3deee4919b1194b",
"reference": "ad1c00f24ca56e73888acc2af3deee4919b1194b",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/00b26ef3d04b04f2df64a64636f6b81f8ae1a166",
"reference": "00b26ef3d04b04f2df64a64636f6b81f8ae1a166",
"shasum": ""
},
"require": {
@@ -2217,9 +2217,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/0.13.2"
"source": "https://github.com/utopia-php/storage/tree/feat-transfer"
},
"time": "2022-12-20T11:11:35+00:00"
"time": "2022-11-02T07:42:34+00:00"
},
{
"name": "utopia-php/swoole",
@@ -4604,16 +4604,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.1",
"version": "3.7.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
"reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
"reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879",
"reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879",
"shasum": ""
},
"require": {
@@ -4649,14 +4649,15 @@
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
"standards",
"static analysis"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2022-06-18T07:21:10+00:00"
"time": "2023-02-22T23:07:41+00:00"
},
{
"name": "swoole/ide-helper",
@@ -5041,9 +5042,18 @@
"time": "2023-02-08T07:49:20+00:00"
}
],
"aliases": [],
"aliases": [
{
"package": "utopia-php/storage",
"version": "dev-feat-transfer",
"alias": "0.13.2",
"alias_normalized": "0.13.2.0"
}
],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"utopia-php/storage": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@@ -5067,5 +5077,5 @@
"platform-overrides": {
"php": "8.0"
},
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.2.0"
}
+18
View File
@@ -85,6 +85,7 @@ services:
- ./public:/usr/src/code/public
- ./src:/usr/src/code/src
- ./dev:/usr/local/dev
- ./vendor/utopia-php/storage:/usr/src/code/vendor/utopia-php/storage
depends_on:
- mariadb
- redis
@@ -581,6 +582,23 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_SCHEDULES
appwrite-backup:
entrypoint: backup
<<: *x-logging
container_name: appwrite-backup
image: appwrite-dev
networks:
- appwrite
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
- appwrite-certificates:/storage/certificates:rw
- ./vendor/utopia-php/cli:/usr/src/code/vendor/utopia-php/cli
environment:
- _APP_ENV
- _APP_CONNECTIONS_STORAGE
- _APP_BACKUP_HEARTBEAT
appwrite-worker-usage:
entrypoint: worker-usage
<<: *x-logging
+5 -1
View File
@@ -15,6 +15,8 @@ use Appwrite\Platform\Tasks\SSL;
use Appwrite\Platform\Tasks\Vars;
use Appwrite\Platform\Tasks\Version;
use Appwrite\Platform\Tasks\VolumeSync;
use Appwrite\Platform\Tasks\Backup;
use Appwrite\Platform\Tasks\Restore;
class Tasks extends Service
{
@@ -33,6 +35,8 @@ class Tasks extends Service
->addAction(Migrate::getName(), new Migrate())
->addAction(SDKs::getName(), new SDKs())
->addAction(VolumeSync::getName(), new VolumeSync())
->addAction(Specs::getName(), new Specs());
->addAction(Specs::getName(), new Specs())
->addAction(Backup::getName(), new Backup())
->addAction(Restore::getName(), new Restore());
}
}
+112
View File
@@ -0,0 +1,112 @@
<?php
namespace Appwrite\Platform\Tasks;
use Utopia\App;
use Utopia\CLI\Console;
use Utopia\Platform\Action;
use Utopia\Storage\Device\Local;
class Backup extends Action
{
public static function getName(): string
{
return 'backup';
}
public function __construct()
{
$this
->desc('Backup process')
->callback(fn() => $this->action());
}
/**
* @throws \Exception
*/
public function action(): void
{
Console::title('Backup V1');
Console::success(APP_NAME . ' backup process v1 has started');
$jobInitTime = '13:10'; // (hour:minutes)
$now = new \DateTime();
$now->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$next = new \DateTime($now->format("Y-m-d $jobInitTime"));
$next->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$delay = $next->getTimestamp() - $now->getTimestamp();
/**
* If time passed for the target day.
*/
if ($delay <= 0) {
$next->add(\DateInterval::createFromDateString('1 days'));
$delay = $next->getTimestamp() - $now->getTimestamp();
}
$folders = [
'cert' => APP_STORAGE_CERTIFICATES,
'config' => APP_STORAGE_CONFIG,
];
$sleep = 86400; //24 hours
$remote = getDevice('/');
Console::log('[' . $now->format("Y-m-d H:i:s.v") . '] Delaying for ' . $delay . ' setting loop to [' . $next->format("Y-m-d H:i:s.v") . ']');
Console::loop(function () use ($delay, $sleep, $folders, $remote) {
$success = 0;
foreach ($folders as $key => $folder) {
$local = new Local($folder);
$filename = $key . '-' . date("Y-m-d") . '.tar.gz';
$source = $local->getRoot() . '/' . $filename;
$destination = '/' . $key . '/' . $filename;
$stdout = '';
$stderr = '';
Console::execute(
'cd ' . $folder . ' && tar --exclude ' . $filename . ' -zcf ' . $source . ' *',
'',
$stdout,
$stderr
);
try {
if (!$local->exists($source)) {
continue;
}
$local->transfer($source, $destination, $remote);
if ($remote->exists($destination)) {
$success++;
}
Console::info("Backing up local $source to {$remote->getName()} $destination");
/**
* Backup folder, long tail cleanup.
*/
$now = new \DateTime();
$now->setTimezone(new \DateTimeZone(date_default_timezone_get()));
for ($i = 0; $i < 20; $i++) {
$now->sub(\DateInterval::createFromDateString('1 days'));
if ($i >= 10) {
$destination = '/' . $key . '/' . $key . '-' . $now->format("Y-m-d") . '.tar.gz';
$remote->delete($destination);
}
}
} catch (\Exception $e) {
Console::error($e->getMessage());
}
}
/**
* heartbeat url
*/
$url = App::getEnv('_APP_BACKUP_HEARTBEAT', '');
if ($success === count($folders) && $url !== '') {
file_get_contents($url);
}
}, $sleep, $delay);
}
}
+79
View File
@@ -0,0 +1,79 @@
<?php
namespace Appwrite\Platform\Tasks;
use Utopia\CLI\Console;
use Utopia\Platform\Action;
use Utopia\Storage\Device\Local;
class Restore extends Action
{
public static function getName(): string
{
return 'restore';
}
public function __construct()
{
$this
->desc('Restore process')
->callback(fn() => $this->action());
}
public function action(): void
{
$folders = [
'cert' => APP_STORAGE_CERTIFICATES,
'config' => APP_STORAGE_CONFIG,
];
$folder = \strtolower(Console::confirm('Please enter the folder you wish to restore'));
$date = Console::confirm('Please enter the date of the backup file in datetime format(Y-m-d)');
if (!array_key_exists($folder, $folders)) {
console::Error('Unknown folder given');
exit;
}
if (!is_a(\DateTime::createFromFormat("Y-m-d", $date), 'DateTime')) {
console::Error('Unknown date format');
exit;
}
$remote = getDevice('/');
$local = new Local();
$filename = $folder . '-' . $date . '.tar.gz';
$destination = $folders[$folder] . '/' . $filename;
$source = '/' . $folder . '/' . $filename;
try {
if (!$remote->exists($source)) {
Console::error("Backup file not found for folder :$folder ,date: $date");
}
$result = $remote->transfer($source, $destination, $local);
if (!$result) {
Console::error("Error while trying to download back file");
}
// if (!$local->exists($destination)) {
// Console::error("Backup file not found for folder :$folder ,date $date");
// }
$stdout = '';
$stderr = '';
Console::execute(
'cd ' . $folders[$folder] . ' && tar -xf ' . $filename,
'',
$stdout,
$stderr
);
console::info("Restoring from {$remote->getName()} $source to $destination");
} catch (\Exception $e) {
Console::error($e->getMessage());
}
}
}