feat: more api endpoints

This commit is contained in:
Andras Bacsai 2024-06-21 16:46:13 +02:00
parent 72033279c2
commit cd85094113
7 changed files with 230 additions and 8 deletions

View File

@ -0,0 +1,136 @@
<?php
namespace App\Http\Controllers\Api;
use App\Actions\Application\StopApplication;
use App\Http\Controllers\Controller;
use App\Models\Application;
use App\Models\Project;
use Illuminate\Http\Request;
use Visus\Cuid2\Cuid2;
class Applications extends Controller
{
public function applications(Request $request)
{
$teamId = get_team_id_from_token();
if (is_null($teamId)) {
return invalid_token();
}
$projects = Project::where('team_id', $teamId)->get();
$applications = collect();
$applications->push($projects->pluck('applications')->flatten());
$applications = $applications->flatten();
return response()->json($applications);
}
public function application_by_uuid(Request $request)
{
$teamId = get_team_id_from_token();
if (is_null($teamId)) {
return invalid_token();
}
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['error' => 'UUID is required.'], 400);
}
$application = Application::where('uuid', $uuid)->first();
if (! $application) {
return response()->json(['error' => 'Application not found.'], 404);
}
return response()->json($application);
}
public function action_deploy(Request $request)
{
$teamId = get_team_id_from_token();
if (is_null($teamId)) {
return invalid_token();
}
$force = $request->query->get('force') ?? false;
$instant_deploy = $request->query->get('instant_deploy') ?? false;
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['error' => 'UUID is required.'], 400);
}
$application = Application::where('uuid', $uuid)->first();
if (! $application) {
return response()->json(['error' => 'Application not found.'], 404);
}
$deployment_uuid = new Cuid2(7);
queue_application_deployment(
application: $application,
deployment_uuid: $deployment_uuid,
force_rebuild: $force,
is_api: true,
no_questions_asked: $instant_deploy
);
return response()->json(
[
'message' => 'Deployment request queued.',
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_api_url' => base_url().'/api/v1/deployment/'.$deployment_uuid->toString(),
],
200
);
}
public function action_stop(Request $request)
{
$teamId = get_team_id_from_token();
if (is_null($teamId)) {
return invalid_token();
}
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['error' => 'UUID is required.'], 400);
}
$application = Application::where('uuid', $uuid)->first();
if (! $application) {
return response()->json(['error' => 'Application not found.'], 404);
}
StopApplication::dispatch($application);
return response()->json(['message' => 'Stopping request queued.'], 200);
}
public function action_restart(Request $request)
{
$teamId = get_team_id_from_token();
if (is_null($teamId)) {
return invalid_token();
}
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['error' => 'UUID is required.'], 400);
}
$application = Application::where('uuid', $uuid)->first();
if (! $application) {
return response()->json(['error' => 'Application not found.'], 404);
}
$deployment_uuid = new Cuid2(7);
queue_application_deployment(
application: $application,
deployment_uuid: $deployment_uuid,
restart_only: true,
is_api: true,
);
return response()->json(
[
'message' => 'Restart request queued.',
'deployment_uuid' => $deployment_uuid->toString(),
'deployment_api_url' => base_url().'/api/v1/deployment/'.$deployment_uuid->toString(),
],
200
);
}
}

View File

@ -38,7 +38,25 @@ public function deployments(Request $request)
'status', 'status',
])->sortBy('id')->toArray(); ])->sortBy('id')->toArray();
return response()->json($deployments_per_server, 200); return response()->json(serialize_api_response($deployments_per_server), 200);
}
public function deployment_by_uuid(Request $request)
{
$teamId = get_team_id_from_token();
if (is_null($teamId)) {
return invalid_token();
}
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['error' => 'UUID is required.'], 400);
}
$deployment = ApplicationDeploymentQueue::where('deployment_uuid', $uuid)->first()->makeHidden('logs');
if (! $deployment) {
return response()->json(['error' => 'Deployment not found.'], 404);
}
return response()->json(serialize_api_response($deployment), 200);
} }
public function deploy(Request $request) public function deploy(Request $request)

View File

@ -1,5 +1,7 @@
<?php <?php
use Illuminate\Database\Eloquent\Collection;
function get_team_id_from_token() function get_team_id_from_token()
{ {
$token = auth()->user()->currentAccessToken(); $token = auth()->user()->currentAccessToken();
@ -10,3 +12,27 @@ function invalid_token()
{ {
return response()->json(['error' => 'Invalid token.', 'docs' => 'https://coolify.io/docs/api-reference/authorization'], 400); return response()->json(['error' => 'Invalid token.', 'docs' => 'https://coolify.io/docs/api-reference/authorization'], 400);
} }
function serialize_api_response($data)
{
if (! $data instanceof Collection) {
$data = collect($data);
}
$data = $data->sortKeys();
$created_at = data_get($data, 'created_at');
$updated_at = data_get($data, 'updated_at');
if ($created_at) {
unset($data['created_at']);
$data['created_at'] = $created_at;
}
if ($updated_at) {
unset($data['updated_at']);
$data['updated_at'] = $updated_at;
}
if (data_get($data, 'id')) {
$data = $data->prepend($data['id'], 'id');
}
return $data;
}

View File

@ -8,7 +8,7 @@
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use Spatie\Url\Url; use Spatie\Url\Url;
function queue_application_deployment(Application $application, string $deployment_uuid, ?int $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, ?Server $server = null, ?StandaloneDocker $destination = null, bool $only_this_server = false, bool $rollback = false) function queue_application_deployment(Application $application, string $deployment_uuid, ?int $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $is_api = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, ?Server $server = null, ?StandaloneDocker $destination = null, bool $only_this_server = false, bool $rollback = false)
{ {
$application_id = $application->id; $application_id = $application->id;
$deployment_link = Url::fromString($application->link()."/deployment/{$deployment_uuid}"); $deployment_link = Url::fromString($application->link()."/deployment/{$deployment_uuid}");
@ -35,6 +35,7 @@ function queue_application_deployment(Application $application, string $deployme
'pull_request_id' => $pull_request_id, 'pull_request_id' => $pull_request_id,
'force_rebuild' => $force_rebuild, 'force_rebuild' => $force_rebuild,
'is_webhook' => $is_webhook, 'is_webhook' => $is_webhook,
'is_api' => $is_api,
'restart_only' => $restart_only, 'restart_only' => $restart_only,
'commit' => $commit, 'commit' => $commit,
'rollback' => $rollback, 'rollback' => $rollback,

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('application_deployment_queues', function (Blueprint $table) {
$table->boolean('is_api')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('application_deployment_queues', function (Blueprint $table) {
$table->dropColumn('is_api');
});
}
};

View File

@ -75,7 +75,11 @@ class="w-6 h-6" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@if (data_get($deployment, 'rollback') === true) @if (data_get($deployment, 'rollback') === true)
Rollback Rollback
@else @else
Manual @if (data_get($deployment, 'is_api'))
API
@else
Manual
@endif
@endif @endif
@if (data_get($deployment, 'commit')) @if (data_get($deployment, 'commit'))
<div class="dark:hover:text-white" <div class="dark:hover:text-white"

View File

@ -1,5 +1,6 @@
<?php <?php
use App\Http\Controllers\Api\Applications;
use App\Http\Controllers\Api\Deploy; use App\Http\Controllers\Api\Deploy;
use App\Http\Controllers\Api\Domains; use App\Http\Controllers\Api\Domains;
use App\Http\Controllers\Api\Resources; use App\Http\Controllers\Api\Resources;
@ -31,17 +32,25 @@
Route::get('/version', function () { Route::get('/version', function () {
return response(config('version')); return response(config('version'));
}); });
Route::get('/deploy', [Deploy::class, 'deploy']); Route::match(['get', 'post'], '/deploy', [Deploy::class, 'deploy']);
Route::get('/deployments', [Deploy::class, 'deployments']); Route::get('/deployments', [Deploy::class, 'deployments']);
Route::get('/deployment/{uuid}', [Deploy::class, 'deployment_by_uuid']);
Route::get('/servers', [Server::class, 'servers']); Route::get('/servers', [Server::class, 'servers']);
Route::get('/server/{uuid}', [Server::class, 'server_by_uuid']); Route::get('/server/{uuid}', [Server::class, 'server_by_uuid']);
Route::get('/resources', [Resources::class, 'resources']); Route::get('/resources', [Resources::class, 'resources']);
Route::get('/applications', [Applications::class, 'applications']);
Route::get('/application/{uuid}', [Applications::class, 'application_by_uuid']);
Route::match(['get', 'post'], '/application/{uuid}/action/deploy', [Applications::class, 'action_deploy']);
Route::match(['get', 'post'], '/application/{uuid}/action/restart', [Applications::class, 'action_restart']);
Route::match(['get', 'post'], '/application/{uuid}/action/stop', [Applications::class, 'action_stop']);
Route::get('/domains', [Domains::class, 'domains']); Route::get('/domains', [Domains::class, 'domains']);
Route::put('/domains', [Domains::class, 'updateDomains']); // Route::put('/domains', [Domains::class, 'updateDomains']);
Route::delete('/domains', [Domains::class, 'deleteDomains']); // Route::delete('/domains', [Domains::class, 'deleteDomains']);
Route::get('/teams', [Team::class, 'teams']); Route::get('/teams', [Team::class, 'teams']);
Route::get('/team/current', [Team::class, 'current_team']); Route::get('/team/current', [Team::class, 'current_team']);
@ -49,12 +58,12 @@
Route::get('/team/{id}', [Team::class, 'team_by_id']); Route::get('/team/{id}', [Team::class, 'team_by_id']);
Route::get('/team/{id}/members', [Team::class, 'members_by_id']); Route::get('/team/{id}/members', [Team::class, 'members_by_id']);
//Route::get('/projects', [Project::class, 'projects']); // Route::get('/projects', [Project::class, 'projects']);
//Route::get('/project/{uuid}', [Project::class, 'project_by_uuid']); //Route::get('/project/{uuid}', [Project::class, 'project_by_uuid']);
//Route::get('/project/{uuid}/{environment_name}', [Project::class, 'environment_details']); //Route::get('/project/{uuid}/{environment_name}', [Project::class, 'environment_details']);
}); });
Route::get('/{any}', function () { Route::any('/{any}', function () {
return response()->json(['error' => 'Not found.'], 404); return response()->json(['error' => 'Not found.'], 404);
})->where('any', '.*'); })->where('any', '.*');