no message

This commit is contained in:
kuaifan 2025-05-08 20:36:26 +08:00
parent df79ef59ea
commit 959b30c788
2 changed files with 229 additions and 12 deletions

View File

@ -2,8 +2,9 @@
namespace App\Http\Controllers\Api;
use App\Module\Apps\Apps;
use App\Module\Base;
use Request;
/**
* @apiDefine apps
@ -12,16 +13,226 @@ use App\Module\Apps\Apps;
*/
class AppsController extends AbstractController
{
public function up()
/**
* @api {get} api/apps/list 01. 获取应用列表
*
* @apiVersion 1.0.0
* @apiGroup apps
* @apiName list
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Array} data 应用列表数据
*/
public function list()
{
$appName = 'MysqlExposePort';
return Apps::dockerComposeUp($appName);
return Apps::appList();
}
public function down()
/**
* @api {get} api/apps/info 02. 获取应用详情
*
* @apiVersion 1.0.0
* @apiGroup apps
* @apiName info
*
* @apiParam {String} app_name 应用名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 应用详细信息
* @apiSuccess {Object} data.info 应用基本信息
* @apiSuccess {Object} data.local 应用本地安装信息
* @apiSuccess {Array} data.versions 可用版本列表
*/
public function info()
{
$appName = 'MysqlExposePort';
$appName = Request::input('app_name');
if (empty($appName)) {
return Base::retError('应用名称不能为空');
}
return Apps::appInfo($appName);
}
/**
* @api {post} api/apps/install 03. 安装应用
*
* @apiVersion 1.0.0
* @apiGroup apps
* @apiName install
*
* @apiParam {String} app_name 应用名称
* @apiParam {String} [version] 版本号,不指定则使用最新版本
* @apiParam {Object} [params] 应用参数
* @apiParam {Object} [resources] 资源限制
* @apiParam {String} [resources.cpu_limit] CPU限制
* @apiParam {String} [resources.memory_limit] 内存限制
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 安装结果信息
*/
public function install()
{
$appName = Request::input('app_name');
$version = Request::input('version', 'latest');
$params = Request::input('params', []);
$resources = Request::input('resources', []);
if (empty($appName)) {
return Base::retError('应用名称不能为空');
}
// 保存用户设置的参数
$localData = [];
// 设置参数
if (!empty($params) && is_array($params)) {
$localData['params'] = $params;
}
// 设置资源限制
if (!empty($resources) && is_array($resources)) {
$localData['resources'] = $resources;
}
// 保存配置
if (!empty($localData)) {
Apps::saveAppLocalInfo($appName, $localData);
}
// 执行安装
return Apps::dockerComposeUp($appName, $version);
}
/**
* @api {post} api/apps/uninstall 04. 卸载应用
*
* @apiVersion 1.0.0
* @apiGroup apps
* @apiName uninstall
*
* @apiParam {String} app_name 应用名称
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 卸载结果信息
*/
public function uninstall()
{
$appName = Request::input('app_name');
if (empty($appName)) {
return Base::retError('应用名称不能为空');
}
// 执行卸载
return Apps::dockerComposeDown($appName);
}
/**
* @api {post} api/apps/update_status 04. 更新应用状态
*
* @apiVersion 1.0.0
* @apiGroup apps
* @apiName updateStatus
*
* @apiParam {String} app_name 应用名称
* @apiParam {String} status 新状态,可选值: installed, error
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 更新结果
*/
public function updateStatus()
{
$appName = Request::input('app_name');
$status = Request::input('status');
if (empty($appName)) {
return Base::retError('应用名称不能为空');
}
$status = str_replace(['successful', 'failed'], ['installed', 'error'], $status);
if (empty($status) || !in_array($status, ['installed', 'error'])) {
return Base::retError('状态无效');
}
// 获取当前应用信息
$appInfo = Apps::getAppLocalInfo($appName);
// 只有在安装中的状态才能更新
if ($appInfo['status'] !== 'installing') {
return Base::retError('当前应用不在安装中,不能更新状态');
}
// 更新状态
$updateData = [
'status' => $status
];
// 如果状态是安装成功,记录完成时间
if ($status === 'installed') {
// todo 安装完成要更新nginx配置
}
// 保存配置
if (Apps::saveAppLocalInfo($appName, $updateData)) {
return Base::retSuccess('更新状态成功');
} else {
return Base::retError('更新状态失败');
}
}
/**
* @api {get} api/apps/logs 05. 获取应用日志
*
* @apiVersion 1.0.0
* @apiGroup apps
* @apiName logs
*
* @apiParam {String} app_name 应用名称
* @apiParam {Number} [lines=50] 获取日志行数默认50行
*
* @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述)
* @apiSuccess {Object} data 返回数据
* @apiSuccess {String} data.log 日志内容
*/
public function logs()
{
$appName = Request::input('app_name');
$lines = intval(Request::input('lines', 50));
if (empty($appName)) {
return Base::retError('应用名称不能为空');
}
// 限制获取行数
if ($lines <= 0) {
$lines = 50;
} else if ($lines > 2000) {
$lines = 2000;
}
// 日志文件路径
$logFile = base_path('docker/logs/apps/' . $appName . '.log');
if (!file_exists($logFile)) {
return Base::retSuccess('日志返回成功', [
'log' => ''
]);
}
// 读取日志文件最后几行
$output = [];
$cmd = 'tail -n ' . $lines . ' ' . escapeshellarg($logFile);
exec($cmd, $output);
$logContent = implode("\n", $output);
return Base::retSuccess('日志返回成功', [
'log' => $logContent
]);
}
}

View File

@ -91,10 +91,16 @@ class Apps
}
// 保存版本信息到.applocal文件
self::saveAppLocalInfo($appName, [
$localData = [
'status' => $command === 'up' ? 'installing' : 'not_installed',
'installed_version' => $versionInfo['version'],
'installed_at' => date('Y-m-d H:i:s')
]);
];
if ($command === 'up') {
$localData['installed_at'] = date('Y-m-d H:i:s');
} else {
$localData['uninstalled_at'] = date('Y-m-d H:i:s');
}
self::saveAppLocalInfo($appName, $localData);
$params = self::getAppLocalInfo($appName)['params'] ?? [];
// 生成docker-compose.yml文件
@ -111,7 +117,7 @@ class Apps
}
$result['compose'] = $res['data'];
// nginx配置文件处理
// nginx配置文件处理 // todo 要单独处理
$nginxFile = $versionInfo['path'] . '/nginx.conf';
$nginxTarget = base_path('docker/nginx/apps/' . $appName . '.conf');
if (file_exists($nginxTarget)) {
@ -268,7 +274,7 @@ class Apps
'created_at' => '', // 应用首次添加到系统的时间
'installed_at' => '', // 最近一次安装/更新的时间
'installed_version' => '', // 最近一次安装/更新的版本
'status' => 'not_installed', // 应用状态: installed, not_installed, error
'status' => 'not_installed', // 应用状态: installing, installed, not_installed, error
'params' => [], // 用户自定义参数值
'resources' => [
'cpu_limit' => '', // CPU限制例如 '0.5' 或 '2'