Merge pull request #5038 from Vann-Dev/main
feat(api): add applications logs api
This commit is contained in:
		@@ -1388,6 +1388,108 @@ class ApplicationsController extends Controller
 | 
				
			|||||||
        return response()->json($this->removeSensitiveData($application));
 | 
					        return response()->json($this->removeSensitiveData($application));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[OA\Get(
 | 
				
			||||||
 | 
					        summary: 'Get application logs.',
 | 
				
			||||||
 | 
					        description: 'Get application logs by UUID.',
 | 
				
			||||||
 | 
					        path: '/applications/{uuid}/logs',
 | 
				
			||||||
 | 
					        operationId: 'get-application-logs-by-uuid',
 | 
				
			||||||
 | 
					        security: [
 | 
				
			||||||
 | 
					            ['bearerAuth' => []],
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        tags: ['Applications'],
 | 
				
			||||||
 | 
					        parameters: [
 | 
				
			||||||
 | 
					            new OA\Parameter(
 | 
				
			||||||
 | 
					                name: 'uuid',
 | 
				
			||||||
 | 
					                in: 'path',
 | 
				
			||||||
 | 
					                description: 'UUID of the application.',
 | 
				
			||||||
 | 
					                required: true,
 | 
				
			||||||
 | 
					                schema: new OA\Schema(
 | 
				
			||||||
 | 
					                    type: 'string',
 | 
				
			||||||
 | 
					                    format: 'uuid',
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            new OA\Parameter(
 | 
				
			||||||
 | 
					                name: 'lines',
 | 
				
			||||||
 | 
					                in: 'query',
 | 
				
			||||||
 | 
					                description: 'Number of lines to show from the end of the logs.',
 | 
				
			||||||
 | 
					                required: false,
 | 
				
			||||||
 | 
					                schema: new OA\Schema(
 | 
				
			||||||
 | 
					                    type: 'integer',
 | 
				
			||||||
 | 
					                    format: 'int32',
 | 
				
			||||||
 | 
					                    default: 100,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        responses: [
 | 
				
			||||||
 | 
					            new OA\Response(
 | 
				
			||||||
 | 
					                response: 200,
 | 
				
			||||||
 | 
					                description: 'Get application logs by UUID.',
 | 
				
			||||||
 | 
					                content: [
 | 
				
			||||||
 | 
					                    new OA\MediaType(
 | 
				
			||||||
 | 
					                        mediaType: 'application/json',
 | 
				
			||||||
 | 
					                        schema: new OA\Schema(
 | 
				
			||||||
 | 
					                            type: 'object',
 | 
				
			||||||
 | 
					                            properties: [
 | 
				
			||||||
 | 
					                                'logs' => ['type' => 'string'],
 | 
				
			||||||
 | 
					                            ]
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            new OA\Response(
 | 
				
			||||||
 | 
					                response: 401,
 | 
				
			||||||
 | 
					                ref: '#/components/responses/401',
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            new OA\Response(
 | 
				
			||||||
 | 
					                response: 400,
 | 
				
			||||||
 | 
					                ref: '#/components/responses/400',
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            new OA\Response(
 | 
				
			||||||
 | 
					                response: 404,
 | 
				
			||||||
 | 
					                ref: '#/components/responses/404',
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    public function logs_by_uuid(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $teamId = getTeamIdFromToken();
 | 
				
			||||||
 | 
					        if (is_null($teamId)) {
 | 
				
			||||||
 | 
					            return invalidTokenResponse();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $uuid = $request->route('uuid');
 | 
				
			||||||
 | 
					        if (! $uuid) {
 | 
				
			||||||
 | 
					            return response()->json(['message' => 'UUID is required.'], 400);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
 | 
				
			||||||
 | 
					        if (! $application) {
 | 
				
			||||||
 | 
					            return response()->json(['message' => 'Application not found.'], 404);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $containers = getCurrentApplicationContainerStatus($application->destination->server, $application->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($containers->count() == 0) {
 | 
				
			||||||
 | 
					            return response()->json([
 | 
				
			||||||
 | 
					                'message' => 'Application is not running.',
 | 
				
			||||||
 | 
					            ], 400);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $container = $containers->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $status = getContainerStatus($application->destination->server, $container['Names']);
 | 
				
			||||||
 | 
					        if ($status !== 'running') {
 | 
				
			||||||
 | 
					            return response()->json([
 | 
				
			||||||
 | 
					                'message' => 'Application is not running.',
 | 
				
			||||||
 | 
					            ], 400);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $lines = $request->query->get('lines', 100) ?: 100;
 | 
				
			||||||
 | 
					        $logs = getContainerLogs($application->destination->server, $container['ID'], $lines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json([
 | 
				
			||||||
 | 
					            'logs' => $logs,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[OA\Delete(
 | 
					    #[OA\Delete(
 | 
				
			||||||
        summary: 'Delete',
 | 
					        summary: 'Delete',
 | 
				
			||||||
        description: 'Delete application by UUID.',
 | 
					        description: 'Delete application by UUID.',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -852,6 +852,23 @@ function validateComposeFile(string $compose, int $server_id): string|Throwable
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getContainerLogs(Server $server, string $container_id, int $lines = 100): string
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if ($server->isSwarm()) {
 | 
				
			||||||
 | 
					        $output = instant_remote_process([
 | 
				
			||||||
 | 
					            "docker service logs -n {$lines} {$container_id}",
 | 
				
			||||||
 | 
					        ], $server);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        $output = instant_remote_process([
 | 
				
			||||||
 | 
					            "docker logs -n {$lines} {$container_id}",
 | 
				
			||||||
 | 
					        ], $server);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $output .= removeAnsiColors($output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $output;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function escapeEnvVariables($value)
 | 
					function escapeEnvVariables($value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    $search = ['\\', "\r", "\t", "\x0", '"', "'"];
 | 
					    $search = ['\\', "\r", "\t", "\x0", '"', "'"];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,6 +88,7 @@ Route::group([
 | 
				
			|||||||
    Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid'])->middleware(['api.ability:write']);
 | 
					    Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid'])->middleware(['api.ability:write']);
 | 
				
			||||||
    Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware(['api.ability:write']);
 | 
					    Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware(['api.ability:write']);
 | 
				
			||||||
    // Route::post('/applications/{uuid}/execute', [ApplicationsController::class, 'execute_command_by_uuid'])->middleware(['ability:write']);
 | 
					    // Route::post('/applications/{uuid}/execute', [ApplicationsController::class, 'execute_command_by_uuid'])->middleware(['ability:write']);
 | 
				
			||||||
 | 
					    Route::get('/applications/{uuid}/logs', [ApplicationsController::class, 'logs_by_uuid'])->middleware(['api.ability:read']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Route::match(['get', 'post'], '/applications/{uuid}/start', [ApplicationsController::class, 'action_deploy'])->middleware(['api.ability:write']);
 | 
					    Route::match(['get', 'post'], '/applications/{uuid}/start', [ApplicationsController::class, 'action_deploy'])->middleware(['api.ability:write']);
 | 
				
			||||||
    Route::match(['get', 'post'], '/applications/{uuid}/restart', [ApplicationsController::class, 'action_restart'])->middleware(['api.ability:write']);
 | 
					    Route::match(['get', 'post'], '/applications/{uuid}/restart', [ApplicationsController::class, 'action_restart'])->middleware(['api.ability:write']);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user