From 1d97b0be982d42ab1ff88a11c392bf31f4eccc86 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 10 Jan 2016 18:57:22 -0500 Subject: [PATCH] Add support for modification of server startup variables and command --- .../Controllers/Admin/ServersController.php | 29 ++++- app/Http/Routes/AdminRoutes.php | 6 + app/Repositories/ServerRepository.php | 105 ++++++++++++++++++ public/js/admin.min.js | 3 + resources/views/admin/servers/view.blade.php | 62 ++++++++++- 5 files changed, 199 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Admin/ServersController.php b/app/Http/Controllers/Admin/ServersController.php index 093d30200..5694d432d 100644 --- a/app/Http/Controllers/Admin/ServersController.php +++ b/app/Http/Controllers/Admin/ServersController.php @@ -52,6 +52,7 @@ class ServersController extends Controller 'users.email as a_ownerEmail', 'locations.long as a_locationName', 'services.name as a_serviceName', + 'services.executable as a_serviceExecutable', 'service_options.name as a_servceOptionName' )->join('nodes', 'servers.node', '=', 'nodes.id') ->join('users', 'servers.owner', '=', 'users.id') @@ -68,7 +69,12 @@ class ServersController extends Controller return view('admin.servers.view', [ 'server' => $server, 'assigned' => Models\Allocation::select('id', 'ip', 'port')->where('assigned_to', $id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(), - 'unassigned' => Models\Allocation::select('id', 'ip', 'port')->where('node', $server->node)->whereNull('assigned_to')->orderBy('ip', 'asc')->orderBy('port', 'asc')->get() + 'unassigned' => Models\Allocation::select('id', 'ip', 'port')->where('node', $server->node)->whereNull('assigned_to')->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(), + 'startup' => Models\ServiceVariables::select('service_variables.*', 'server_variables.variable_value as a_serverValue') + ->join('server_variables', 'server_variables.variable_id', '=', 'service_variables.id') + ->where('service_variables.option_id', $server->option) + ->where('server_variables.server_id', $server->id) + ->get() ]); } @@ -325,4 +331,25 @@ class ServersController extends Controller } } + public function postUpdateServerStartup(Request $request, $id) + { + try { + $server = new ServerRepository; + $server->updateStartup($id, $request->except([ + '_token' + ])); + Alert::success('Server startup variables were successfully updated.')->flash(); + } catch (\Pterodactyl\Exceptions\DisplayException $e) { + Alert::danger($e->getMessage())->flash(); + } catch(\Exception $e) { + Log::error($e); + Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash(); + } finally { + return redirect()->route('admin.servers.view', [ + 'id' => $id, + 'tab' => 'tab_startup' + ])->withInput(); + } + } + } diff --git a/app/Http/Routes/AdminRoutes.php b/app/Http/Routes/AdminRoutes.php index e2ebef0cb..0fbb12cab 100644 --- a/app/Http/Routes/AdminRoutes.php +++ b/app/Http/Routes/AdminRoutes.php @@ -115,6 +115,12 @@ class AdminRoutes { 'uses' => 'Admin\ServersController@postUpdateServerDetails' ]); + // Change Server Details + $router->post('/view/{id}/startup', [ + 'as' => 'admin.servers.post.startup', + 'uses' => 'Admin\ServersController@postUpdateServerStartup' + ]); + // Rebuild Server $router->post('/view/{id}/rebuild', [ 'uses' => 'Admin\ServersController@postUpdateServerToggleBuild' diff --git a/app/Repositories/ServerRepository.php b/app/Repositories/ServerRepository.php index 07f703feb..f398d4b1b 100644 --- a/app/Repositories/ServerRepository.php +++ b/app/Repositories/ServerRepository.php @@ -522,6 +522,111 @@ class ServerRepository } + public function updateStartup($id, array $data) + { + + $server = Models\Server::findOrFail($id); + + DB::beginTransaction(); + + // Check the startup + if (isset($data['startup'])) { + $server->startup = $data['startup']; + $server->save(); + } + + // Check those Variables + $variables = Models\ServiceVariables::select('service_variables.*', 'server_variables.variable_value as a_currentValue') + ->join('server_variables', 'server_variables.variable_id', '=', 'service_variables.id') + ->where('option_id', $server->option)->get(); + + $variableList = []; + if ($variables) { + foreach($variables as &$variable) { + // Move on if the new data wasn't even sent + if (!isset($data[$variable->env_variable])) { + $variableList = array_merge($variableList, [[ + 'id' => $variable->id, + 'env' => $variable->env_variable, + 'val' => $variable->a_currentValue + ]]); + continue; + } + + // Update Empty but skip validation + if (empty($data[$variable->env_variable])) { + $variableList = array_merge($variableList, [[ + 'id' => $variable->id, + 'env' => $variable->env_variable, + 'val' => null + ]]); + continue; + } + + // Is the variable required? + // @TODO: is this even logical to perform this check? + if (isset($data[$variable->env_variable]) && empty($data[$variable->env_variable])) { + if ($variable->required === 1) { + throw new DisplayException('A required service option variable field (' . $variable->env_variable . ') was included in this request but was left blank.'); + } + } + + // Check aganist Regex Pattern + if (!is_null($variable->regex) && !preg_match($variable->regex, $data[$variable->env_variable])) { + throw new DisplayException('Failed to validate service option variable field (' . $variable->env_variable . ') aganist regex (' . $variable->regex . ').'); + } + + $variableList = array_merge($variableList, [[ + 'id' => $variable->id, + 'env' => $variable->env_variable, + 'val' => $data[$variable->env_variable] + ]]); + } + } + + // Add Variables + $environmentVariables = []; + $environmentVariables = array_merge($environmentVariables, [ + 'STARTUP' => $server->startup + ]); + foreach($variableList as $item) { + $environmentVariables = array_merge($environmentVariables, [ + $item['env'] => $item['val'] + ]); + $var = Models\ServerVariables::where('server_id', $server->id)->where('variable_id', $item['id'])->update([ + 'variable_value' => $item['val'] + ]); + } + + try { + + $node = Models\Node::getByID($server->node); + $client = Models\Node::guzzleRequest($server->node); + + $client->request('PATCH', '/server', [ + 'headers' => [ + 'X-Access-Server' => $server->uuid, + 'X-Access-Token' => $node->daemonSecret + ], + 'json' => [ + 'build' => [ + 'env|overwrite' => $environmentVariables + ] + ] + ]); + + DB::commit(); + return true; + } catch (\GuzzleHttp\Exception\TransferException $ex) { + DB::rollBack(); + throw new DisplayException('An error occured while attempting to update the server configuration: ' . $ex->getMessage()); + } catch (\Exception $e) { + DB::rollBack(); + throw $e; + } + + } + public function deleteServer($id, $force) { $server = Models\Server::findOrFail($id); diff --git a/public/js/admin.min.js b/public/js/admin.min.js index 07217aa42..7f0660884 100755 --- a/public/js/admin.min.js +++ b/public/js/admin.min.js @@ -8,6 +8,9 @@ function randomKey(length) { return text; } +function escapeRegExp(str) { + return str.replace(/^\/|\/$/g, ''); +} $(document).ready(function () { $.urlParam=function(name){var results=new RegExp("[\\?&]"+name+"=([^&#]*)").exec(decodeURIComponent(window.location.href));if(results==null){return null}else{return results[1]||0}};function getPageName(url){var index=url.lastIndexOf("/")+1;var filenameWithExtension=url.substr(index);var filename=filenameWithExtension.split(".")[0];return filename} function centerModal(element) { diff --git a/resources/views/admin/servers/view.blade.php b/resources/views/admin/servers/view.blade.php index 5fb31d6db..229e018c6 100644 --- a/resources/views/admin/servers/view.blade.php +++ b/resources/views/admin/servers/view.blade.php @@ -223,12 +223,52 @@
-
-
-
- Startup +
+
+
+
+
+
+
Changing any of the values below will require a restart for them to take effect.
+ +
+ {{ $server->a_serviceExecutable }} + +
+

The following data replacers are avaliable for the startup command: @{{SERVER_MEMORY}}, @{{SERVER_IP}}, and @{{SERVER_PORT}}. They will be replaced with the allocated memory, server ip, and server port respectively.

+
+
+
+
+
+
+ @foreach($startup as $item) +
+ +
+ +
+

{{ $item->description }}
Regex: {{ $item->regex }}
Access as: {{{{$item->env_variable}}}}

+
+ @endforeach +
+
+
+
+
+
+ {!! csrf_field() !!} + +
+
+
-
+
@@ -315,11 +355,23 @@