mirror of
https://github.com/pterodactyl/panel.git
synced 2024-11-25 18:42:31 +01:00
Add support for modification of server startup variables and command
This commit is contained in:
parent
62313eeac5
commit
1d97b0be98
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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);
|
||||
|
3
public/js/admin.min.js
vendored
3
public/js/admin.min.js
vendored
@ -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) {
|
||||
|
@ -223,12 +223,52 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="tab_startup">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"></div>
|
||||
<div class="panel-body">
|
||||
Startup
|
||||
<form action="{{ route('admin.servers.post.startup', $server->id) }}" method="POST">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"></div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-info">Changing any of the values below will require a restart for them to take effect.</div>
|
||||
<label class="control-label">Server Startup Command</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">{{ $server->a_serviceExecutable }}</span>
|
||||
<input type="text" class="form-control" name="startup" value="{{ old('startup', $server->startup) }}" />
|
||||
</div>
|
||||
<p class="text-muted"><small>The following data replacers are avaliable for the startup command: <code>@{{SERVER_MEMORY}}</code>, <code>@{{SERVER_IP}}</code>, and <code>@{{SERVER_PORT}}</code>. They will be replaced with the allocated memory, server ip, and server port respectively.</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
@foreach($startup as $item)
|
||||
<div class="form-group col-md-6">
|
||||
<label class="control-label">
|
||||
@if($item->required === 1)<span class="label label-primary">Required</span> @endif
|
||||
@if($item->user_viewable === 0)<span data-toggle="tooltip" data-placement="top" title="Not Visible to Users" class="label label-danger"><i class="fa fa-eye-slash"></i></span> @endif
|
||||
@if($item->user_editable === 0)<span data-toggle="tooltip" data-placement="top" title="Not Editable by Users" class="label label-danger"><i class="fa fa-edit"></i></span> @endif
|
||||
{{ $item->name }}
|
||||
</label>
|
||||
<div>
|
||||
<input type="text" name="{{ $item->env_variable }}" class="form-control" value="{{ old($item->env_variable, $item->a_serverValue) }}" data-action="matchRegex" data-regex="{{ $item->regex }}" />
|
||||
</div>
|
||||
<p class="text-muted"><small>{{ $item->description }}<br />Regex: <code>{{ $item->regex }}</code><br />Access as: <code>{{{{$item->env_variable}}}}</code></small></p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{!! csrf_field() !!}
|
||||
<input type="submit" class="btn btn-primary btn-sm" value="Update Startup Arguments" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane" id="tab_manage">
|
||||
<div class="panel panel-default">
|
||||
@ -315,11 +355,23 @@
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('#sidebar_links').find("a[href='/admin/servers']").addClass('active');
|
||||
$('input[name="default"]').on('change', function (event) {
|
||||
$('select[name="remove_additional[]"]').find('option:disabled').prop('disabled', false);
|
||||
$('select[name="remove_additional[]"]').find('option[value="' + $(this).val() + '"]').prop('disabled', true).prop('selected', false);
|
||||
});
|
||||
$('[data-action="matchRegex"]').keyup(function (event) {
|
||||
if (!$(this).data('regex')) return;
|
||||
var input = $(this).val();
|
||||
var regex = new RegExp(escapeRegExp($(this).data('regex')));
|
||||
console.log(regex);
|
||||
if (!regex.test(input)) {
|
||||
$(this).parent().parent().removeClass('has-success').addClass('has-error');
|
||||
} else {
|
||||
$(this).parent().parent().removeClass('has-error').addClass('has-success');
|
||||
}
|
||||
});
|
||||
$('form[data-attr="deleteServer"]').submit(function (event) {
|
||||
event.preventDefault();
|
||||
swal({
|
||||
|
Loading…
Reference in New Issue
Block a user