1
0
Fork 0
mirror of synced 2024-06-03 11:24:48 +12:00
appwrite/app/tasks/install.php

227 lines
8.8 KiB
PHP
Raw Normal View History

2020-07-29 07:48:51 +12:00
<?php
global $cli;
use Appwrite\Auth\Auth;
2020-07-31 18:31:29 +12:00
use Appwrite\Docker\Compose;
2020-08-01 00:49:44 +12:00
use Appwrite\Docker\Env;
2021-12-14 22:11:34 +13:00
use Appwrite\Utopia\View;
2021-02-04 05:54:41 +13:00
use Utopia\Analytics\GoogleAnalytics;
2020-07-29 07:48:51 +12:00
use Utopia\CLI\Console;
2020-07-29 16:03:28 +12:00
use Utopia\Config\Config;
2021-05-12 20:12:33 +12:00
use Utopia\Validator\Text;
2020-07-29 07:48:51 +12:00
$cli
->task('install')
->desc('Install Appwrite')
2021-05-12 20:12:33 +12:00
->param('httpPort', '', new Text(4), 'Server HTTP port', true)
->param('httpsPort', '', new Text(4), 'Server HTTPS port', true)
->param('organization', 'appwrite', new Text(0), 'Docker Registry organization', true)
->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true)
2021-05-14 18:58:18 +12:00
->param('interactive','Y', new Text(1), 'Run an interactive session', true)
->action(function ($httpPort, $httpsPort, $organization, $image, $interactive) {
2020-07-29 07:48:51 +12:00
/**
* 1. Start - DONE
2020-07-31 18:31:29 +12:00
* 2. Check for older setup and get older version - DONE
2020-07-29 07:48:51 +12:00
* 2.1 If older version is equal or bigger(?) than current version, **stop setup**
2020-07-31 18:31:29 +12:00
* 2.2. Get ENV vars - DONE
2020-07-29 07:48:51 +12:00
* 2.2.1 Fetch from older docker-compose.yml file
* 2.2.2 Fetch from older .env file (manually parse)
2020-07-29 19:29:34 +12:00
* 2.3 Use old ENV vars as default values
2020-07-29 07:48:51 +12:00
* 2.4 Ask for all required vars not given as CLI args and if in interactive mode
* Otherwise, just use default vars. - DONE
* 3. Ask user to backup important volumes, env vars, and SQL tables
* In th future we can try and automate this for smaller/medium size setups
2020-07-31 18:31:29 +12:00
* 4. Drop new docker-compose.yml setup (located inside the container, no network dependencies with appwrite.io) - DONE
2020-07-29 18:56:39 +12:00
* 5. Run docker-compose up -d - DONE
2020-07-29 07:48:51 +12:00
* 6. Run data migration
*/
2021-01-08 09:50:27 +13:00
$config = Config::getParam('variables');
2020-07-31 18:31:29 +12:00
$path = '/usr/src/code/appwrite';
2020-08-01 00:49:44 +12:00
$defaultHTTPPort = '80';
$defaultHTTPSPort = '443';
2021-01-08 09:50:27 +13:00
$vars = [];
2021-02-04 22:26:58 +13:00
/**
2021-02-04 23:33:32 +13:00
* We are using a random value every execution for identification.
* This allows us to collect information without invading the privacy of our users.
2021-02-04 22:26:58 +13:00
*/
2021-02-04 23:33:32 +13:00
$analytics = new GoogleAnalytics('UA-26264668-9', uniqid('server.', true));
2021-02-04 22:26:58 +13:00
2021-01-08 09:50:27 +13:00
foreach($config as $category) {
foreach($category['variables'] ?? [] as $var) {
$vars[] = $var;
}
}
2020-10-15 17:38:46 +13:00
2020-07-29 07:48:51 +12:00
Console::success('Starting Appwrite installation...');
2020-07-31 18:31:29 +12:00
// Create directory with write permissions
if (null !== $path && !\file_exists(\dirname($path))) {
if (!@\mkdir(\dirname($path), 0755, true)) {
Console::error('Can\'t create directory '.\dirname($path));
2021-01-29 21:39:42 +13:00
Console::exit(1);
2020-07-31 18:31:29 +12:00
}
}
$data = @file_get_contents($path.'/docker-compose.yml');
if($data !== false) {
2021-05-18 20:36:22 +12:00
$time = \time();
2021-05-19 07:30:09 +12:00
Console::info('Compose file found, creating backup: docker-compose.yml.'.$time.'.backup');
2021-05-18 20:36:22 +12:00
file_put_contents($path.'/docker-compose.yml.'.$time.'.backup',$data);
2020-07-31 18:31:29 +12:00
$compose = new Compose($data);
2020-08-01 00:49:44 +12:00
$appwrite = $compose->getService('appwrite');
2020-10-15 17:38:46 +13:00
$oldVersion = ($appwrite) ? $appwrite->getImageVersion() : null;
try {
$ports = $compose->getService('traefik')->getPorts();
} catch (\Throwable $th) {
$ports = [
$defaultHTTPPort => $defaultHTTPPort,
$defaultHTTPSPort => $defaultHTTPSPort
];
Console::warning('Traefik not found. Falling back to default ports.');
}
2020-07-31 18:31:29 +12:00
2020-10-15 17:38:46 +13:00
if($oldVersion) {
2020-07-31 18:31:29 +12:00
foreach($compose->getServices() as $service) { // Fetch all env vars from previous compose file
if(!$service) {
continue;
}
$env = $service->getEnvironment()->list();
2020-08-01 00:49:44 +12:00
foreach ($env as $key => $value) {
foreach($vars as &$var) {
if($var['name'] === $key) {
$var['default'] = $value;
}
}
}
}
$data = @file_get_contents($path.'/.env');
if($data !== false) { // Fetch all env vars from previous .env file
2021-05-19 07:30:17 +12:00
Console::info('Env file found, creating backup: .env.'.$time.'.backup');
2021-05-18 20:36:22 +12:00
file_put_contents($path.'/.env.'.$time.'.backup',$data);
2020-08-01 00:49:44 +12:00
$env = new Env($data);
foreach ($env->list() as $key => $value) {
foreach($vars as &$var) {
if($var['name'] === $key) {
$var['default'] = $value;
}
}
}
2020-07-31 18:31:29 +12:00
}
2020-08-01 00:49:44 +12:00
foreach ($ports as $key => $value) {
if($value === $defaultHTTPPort) {
$defaultHTTPPort = $key;
}
if($value === $defaultHTTPSPort) {
$defaultHTTPSPort = $key;
}
}
2020-07-31 18:31:29 +12:00
}
}
2021-05-12 20:12:33 +12:00
if(empty($httpPort)) {
$httpPort = Console::confirm('Choose your server HTTP port: (default: '.$defaultHTTPPort.')');
$httpPort = ($httpPort) ? $httpPort : $defaultHTTPPort;
}
2020-07-29 19:29:34 +12:00
2021-05-12 20:12:33 +12:00
if(empty($httpsPort)) {
$httpsPort = Console::confirm('Choose your server HTTPS port: (default: '.$defaultHTTPSPort.')');
$httpsPort = ($httpsPort) ? $httpsPort : $defaultHTTPSPort;
}
2021-07-16 04:12:18 +12:00
2020-07-29 07:48:51 +12:00
$input = [];
foreach($vars as $key => $var) {
if(!empty($var['filter']) && ($interactive !== 'Y' || !Console::isInteractive())) {
2021-05-18 18:33:48 +12:00
if($data && $var['default'] !== null) {
$input[$var['name']] = $var['default'];
continue;
}
if($var['filter'] === 'token') {
$input[$var['name']] = Auth::tokenGenerator();
continue;
}
if($var['filter'] === 'password') {
$input[$var['name']] = Auth::passwordGenerator();
continue;
}
}
2021-05-12 22:54:14 +12:00
if(!$var['required'] || !Console::isInteractive() || $interactive !== 'Y') {
2020-07-29 16:03:28 +12:00
$input[$var['name']] = $var['default'];
2020-07-29 07:48:51 +12:00
continue;
}
2020-07-29 16:03:28 +12:00
$input[$var['name']] = Console::confirm($var['question'].' (default: \''.$var['default'].'\')');
2020-07-29 07:48:51 +12:00
if(empty($input[$var['name']])) {
2020-07-29 16:03:28 +12:00
$input[$var['name']] = $var['default'];
2020-07-29 07:48:51 +12:00
}
}
2020-07-29 19:29:34 +12:00
$templateForCompose = new View(__DIR__.'/../views/install/compose.phtml');
$templateForEnv = new View(__DIR__.'/../views/install/env.phtml');
2020-10-15 17:38:46 +13:00
2020-07-29 18:56:39 +12:00
$templateForCompose
->setParam('httpPort', $httpPort)
->setParam('httpsPort', $httpsPort)
2021-01-30 06:38:57 +13:00
->setParam('version', APP_VERSION_STABLE)
2021-05-19 07:29:44 +12:00
->setParam('organization', $organization)
->setParam('image', $image)
2020-07-29 18:56:39 +12:00
;
2020-07-29 18:56:39 +12:00
$templateForEnv
->setParam('vars', $input)
;
2020-07-29 07:48:51 +12:00
2020-08-01 00:50:39 +12:00
if(!file_put_contents($path.'/docker-compose.yml', $templateForCompose->render(false))) {
2021-02-04 22:26:58 +13:00
$message = 'Failed to save Docker Compose file';
2021-02-04 23:51:19 +13:00
$analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message);
2021-02-04 22:26:58 +13:00
Console::error($message);
2021-01-29 21:39:42 +13:00
Console::exit(1);
2020-07-29 18:56:39 +12:00
}
2020-08-01 00:50:39 +12:00
if(!file_put_contents($path.'/.env', $templateForEnv->render(false))) {
2021-02-04 22:26:58 +13:00
$message = 'Failed to save environment variables file';
2021-02-04 23:51:19 +13:00
$analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message);
2021-02-04 22:26:58 +13:00
Console::error($message);
2021-01-29 21:39:42 +13:00
Console::exit(1);
2020-07-29 18:56:39 +12:00
}
2020-07-29 07:48:51 +12:00
2021-01-30 06:12:59 +13:00
$env = '';
2020-07-29 16:03:28 +12:00
$stdout = '';
$stderr = '';
2021-01-30 06:12:59 +13:00
foreach ($input as $key => $value) {
if($value) {
2021-07-16 04:12:18 +12:00
$env .= $key.'='.\escapeshellarg($value).' ';
2021-01-30 06:12:59 +13:00
}
}
Console::log("Running \"docker-compose -f {$path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes\"");
2020-10-26 02:48:04 +13:00
2021-01-30 06:12:59 +13:00
$exit = Console::execute("${env} docker-compose -f {$path}/docker-compose.yml up -d --remove-orphans --renew-anon-volumes", '', $stdout, $stderr);
2020-07-29 07:48:51 +12:00
2020-10-15 17:38:46 +13:00
if ($exit !== 0) {
2021-02-04 22:26:58 +13:00
$message = 'Failed to install Appwrite dockers';
2021-02-04 23:51:19 +13:00
$analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message);
2021-02-04 22:26:58 +13:00
Console::error($message);
2020-10-26 02:48:04 +13:00
Console::error($stderr);
2021-01-29 21:39:42 +13:00
Console::exit($exit);
2020-07-29 07:48:51 +12:00
} else {
2021-02-04 22:26:58 +13:00
$message = 'Appwrite installed successfully';
2021-02-04 23:51:19 +13:00
$analytics->createEvent('install/server', 'install', APP_VERSION_STABLE.' - '.$message);
2021-02-04 22:26:58 +13:00
Console::success($message);
2020-07-29 07:48:51 +12:00
}
});