Skip to content

Commit 6159f99

Browse files
authored
Quick install cli (hestiacp#4443)
* Implement CLI install for Quick install - CLI install for Quick install apps Install apps: with v-quick-install-app install user domain appname [options] Notes: - App name is casesensitive (WordPress instead of Wordpress for example) - Option as email="info@hestiacp.com" password="12345678" - Does only check if all fields are present if field is not present it will select the default value if available otherwise returns error Other options: - apps List all available apps (Usage: v-quick-install-app apps) - options list all available apps options (Usage: v-quick-install-app options user domain app) * Minor changes in comments
1 parent 73bb31a commit 6159f99

File tree

5 files changed

+894
-10
lines changed

5 files changed

+894
-10
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
# Bin folder
2121
/bin/v-generate-password-hash
22+
/bin/v-quick-install-app
2223

2324
# Exclude bats submodules if present
2425
/test/test_helper/*

bin/v-quick-install-app

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#!/usr/local/hestia/php/bin/php
2+
<?php
3+
//# info: Install Quick Install Web App via CLI
4+
//# options: action [user] [domain] [app] [options ...]
5+
//#
6+
//# example: v-quick-install-app install admin domain.com wordpress email="info@hestiacp" password="123456" username="admin" site_name="HestiaCP Demo" install_directory="/" language="nl_NL" php_version="8.2" database_create="true"
7+
//# example: v-quick-install-app apps
8+
//# example: v-quick-install-app options admin domain.com wordpress
9+
//# Install Quick Install Web App via CLI run v-quick-install-app apps for supported apps.
10+
//# v-quick-install-app options for the app options and v-quick-install-app install to install the app
11+
//# Please note app names are case sensitive
12+
13+
use Symfony\Component\Console\Application;
14+
use Symfony\Component\Console\Input\InputArgument;
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Output\ConsoleOutput;
17+
18+
19+
use Hestiacp\quoteshellarg\quoteshellarg;
20+
21+
session_start();
22+
require_once( __DIR__ . '/../web/inc/vendor/autoload.php');
23+
require_once( __DIR__ . '/../web/src/init.php');
24+
25+
26+
define("HESTIA_DIR_BIN", "/usr/local/hestia/bin/");
27+
define("HESTIA_CMD", "/usr/bin/sudo /usr/local/hestia/bin/");
28+
define("DEFAULT_PHP_VERSION", "php-" . exec('php -r "echo substr(phpversion(),0,3);"'));
29+
30+
exec(HESTIA_CMD . "v-list-sys-config json", $output, $return_var);
31+
$data = json_decode(implode("", $output), true);
32+
$sys_arr = $data["config"];
33+
foreach ($sys_arr as $key => $value) {
34+
$_SESSION[$key] = $value;
35+
}
36+
37+
38+
$_SESSION['userContext'] = 'user';
39+
$application = new Application();
40+
$application -> register('install')
41+
->setDescription('Install app via the CLI')
42+
-> addArgument('user', InputArgument::REQUIRED, 'Hestia User')
43+
-> addArgument('domain', InputArgument::REQUIRED, 'Domain')
44+
-> addArgument('app', InputArgument::REQUIRED, 'App Name')
45+
-> addArgument('options', InputArgument::IS_ARRAY, 'Options')
46+
-> setCode(function($input, $output){
47+
$user = $input -> getArgument('user');
48+
$_SESSION['user'] = $user;
49+
$v_domain = $input -> getArgument('domain');
50+
$app = $input -> getArgument('app');
51+
$options = $input -> getArgument('options');
52+
$data = [];
53+
foreach($options as $option){
54+
$o = explode('=', $option);
55+
$data['webapp_'.$o[0]] = $o[1];
56+
}
57+
$hestia = new \Hestia\System\HestiaApp();
58+
if(class_exists("\Hestia\WebApp\Installers\\" . $app . "\\" . $app . "Setup") === false){
59+
$output -> writeln('App not found');
60+
return Command::FAILURE;
61+
}
62+
$app_installer_class = "\Hestia\WebApp\Installers\\" . $app . "\\" . $app . "Setup";
63+
$app_installer = new $app_installer_class($v_domain, $hestia);
64+
65+
// check for default fields
66+
$WebappInstaller = new \Hestia\WebApp\AppWizard($app_installer, $v_domain, $hestia);
67+
$fields = $WebappInstaller -> getOptions();
68+
$array = [];
69+
foreach($fields as $key => $field){
70+
if(is_array($field)){
71+
if(!empty($field['value'])){
72+
$array['webapp_'.$key] = $field['value'];
73+
}
74+
}
75+
}
76+
$data = array_merge($array, $data);
77+
//loop trough data and check all fields are set
78+
79+
$error = false;
80+
foreach($fields as $key => $field){
81+
if(empty($data['webapp_'.$key])){
82+
if(strpos($key, 'database_') !== false){
83+
if($data['webapp_database_create'] != true){
84+
$output -> writeln('Missing required field: ' . $key);
85+
$error = true;
86+
}
87+
}else{
88+
//all ways the case
89+
$output -> writeln('Missing required field: ' . $key);
90+
$error = true;
91+
}
92+
}
93+
}
94+
95+
if($error !== false){
96+
return Command::FAILURE;
97+
}
98+
99+
$installer = new \Hestia\WebApp\AppWizard($app_installer, $v_domain, $hestia);
100+
$installer -> execute($data);
101+
return Command::SUCCESS;
102+
});
103+
104+
$application -> register('apps')
105+
->setDescription('List availble apps')
106+
-> setCode(function($input, $output){
107+
$appInstallers = glob(__DIR__ . "/../web/src/app/WebApp/Installers/*/*.php");
108+
$output -> writeln('Available Apps');
109+
$output -> writeln('---------------------------------');
110+
foreach($appInstallers as $appInstaller){
111+
$app = basename(dirname($appInstaller));
112+
$hestia = new \Hestia\System\HestiaApp();
113+
$domain = 'demo.hestiacp.com';
114+
if( !file_exists(__DIR__ . "/../web/src/app/WebApp/Installers/" . $app . "/". $app . "Setup.php") ){
115+
continue;
116+
}
117+
$app_installer_class = "\Hestia\WebApp\Installers\\" . $app . "\\" . $app . "Setup";
118+
$app_installer = new $app_installer_class($domain, $hestia);
119+
$info = $app_installer -> info();
120+
$output -> writeln($info['name'] . ' - ' . $info['version']);
121+
}
122+
$output -> writeln('---------------------------------');
123+
$output -> writeln('Please note app names are case sensitive');
124+
125+
return Command::SUCCESS;
126+
});
127+
128+
$application -> register('options')
129+
->setDescription('List options requied / optional for the app')
130+
-> addArgument('user', InputArgument::REQUIRED, 'Hestia User')
131+
-> addArgument('domain', InputArgument::REQUIRED, 'Domain')
132+
-> addArgument('app', InputArgument::REQUIRED, 'App Name')
133+
-> setCode(function($input, $output){
134+
$user = $input -> getArgument('user');
135+
$_SESSION['user'] = $user;
136+
$v_domain = $input -> getArgument('domain');
137+
$app = $input -> getArgument('app');
138+
$hestia = new \Hestia\System\HestiaApp();
139+
140+
if(class_exists("\Hestia\WebApp\Installers\\" . $app . "\\" . $app . "Setup") === false){
141+
$output -> writeln('App not found');
142+
return Command::FAILURE;
143+
}
144+
$app_installer_class = "\Hestia\WebApp\Installers\\" . $app . "\\" . $app . "Setup";
145+
$app_installer = new $app_installer_class($v_domain, $hestia);
146+
$WebappInstaller = new \Hestia\WebApp\AppWizard($app_installer, $v_domain, $hestia);
147+
$output -> writeln('To install '.$app.' use the following command:');
148+
$output -> writeln('v-quick-install-app install ' . $user . ' ' . $v_domain . ' ' . $app . ' email="info@hestiacp" password="12346"');
149+
$output -> writeln('---------------------------------');
150+
$output -> writeln('Options for ' . $app);
151+
$output -> writeln('---------------------------------');
152+
$options = $WebappInstaller -> getOptions();
153+
foreach($options as $key => $option){
154+
if(!is_array($option)){
155+
$output -> writeln('Key: ' . $key . ' Type: ' . $option .' (Required)');
156+
}else{
157+
$required = '';
158+
if(empty($option['value'])){
159+
$option['value'] = 'none';
160+
if(strpos($key, 'database_') === false){
161+
$required = '(' . 'Required' . ')';
162+
}
163+
}
164+
if(!empty($option['type'])){
165+
if($option['type'] == 'boolean'){
166+
$option['value'] = $option['value'] ? 'true' : 'false';
167+
}
168+
$output -> writeln('Key: ' .$key . ' Default Value: ' . $option['value'] .' Type: ' . $option['type'] . ' ' . $required);
169+
}else{
170+
$output -> writeln('Key :' .$key . ' Default Value: ' . $option['value'] . ' ' . $required);
171+
}
172+
}
173+
}
174+
return Command::SUCCESS;
175+
});
176+
177+
178+
$application -> run();

web/src/app/WebApp/Installers/WordPress/WordPressSetup.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ class WordpressSetup extends BaseSetup {
2424
//],
2525

2626
"site_name" => ["type" => "text", "value" => "WordPress Blog"],
27-
"wordpress_account_username" => ["value" => "wpadmin"],
28-
"wordpress_account_email" => "text",
29-
"wordpress_account_password" => "password",
30-
"install_directory" => ["type" => "text", "value" => "", "placeholder" => "/"],
27+
"username" => ["value" => "wpadmin"],
28+
"email" => "text",
29+
"password" => "password",
30+
"install_directory" => ["type" => "text", "value" => "/", "placeholder" => "/"],
3131
"language" => [
3232
"type" => "select",
3333
"value" => "en_US",
@@ -249,13 +249,13 @@ public function install(array $options = null) {
249249
"weblog_title=" .
250250
rawurlencode($options["site_name"]) .
251251
"&user_name=" .
252-
rawurlencode($options["wordpress_account_username"]) .
252+
rawurlencode($options["username"]) .
253253
"&admin_password=" .
254-
rawurlencode($options["wordpress_account_password"]) .
254+
rawurlencode($options["password"]) .
255255
"&admin_password2=" .
256-
rawurlencode($options["wordpress_account_password"]) .
256+
rawurlencode($options["password"]) .
257257
"&admin_email=" .
258-
rawurlencode($options["wordpress_account_email"]),
258+
rawurlencode($options["email"]),
259259
),
260260
$output,
261261
$return_var,

web/src/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
},
77
"require-dev": {
88
"filp/whoops": "2.15.4"
9+
},
10+
"require": {
11+
"symfony/console": "^7.1"
912
}
1013
}

0 commit comments

Comments
 (0)