diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index fb58018c6..2d2b390e6 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -97,40 +97,10 @@ public function applications(Request $request) return response()->json($applications); } - public function create_public_application(Request $request) - { - $this->create_application($request, 'public'); - } - - public function create_private_gh_app_application(Request $request) - { - $this->create_application($request, 'private-gh-app'); - } - - public function create_private_deploy_key_application(Request $request) - { - $this->create_application($request, 'private-deploy-key'); - } - - public function create_dockerfile_application(Request $request) - { - $this->create_application($request, 'dockerfile'); - } - - public function create_dockerimage_application(Request $request) - { - $this->create_application($request, 'docker-image'); - } - - public function create_dockercompose_application(Request $request) - { - $this->create_application($request, 'dockercompose'); - } - #[OA\Post( - summary: 'Create', - description: 'Create new application.', - path: '/applications', + summary: 'Create (Public)', + description: 'Create new application based on a public git repository.', + path: '/applications/public', security: [ ['bearerAuth' => []], ], @@ -143,23 +113,22 @@ public function create_dockercompose_application(Request $request) mediaType: 'application/json', schema: new OA\Schema( type: 'object', - required: ['type', 'project_uuid', 'server_uuid', 'environment_name'], + required: ['project_uuid', 'server_uuid', 'environment_name', 'git_repository', 'git_branch', 'build_pack', 'ports_exposes'], properties: [ - 'type' => ['type' => 'string', 'enum' => ['public', 'private-gh-app', 'private-deploy-key', 'dockerfile', 'docker-image', 'dockercompose']], 'project_uuid' => ['type' => 'string'], 'server_uuid' => ['type' => 'string'], 'environment_name' => ['type' => 'string'], 'destination_uuid' => ['type' => 'string'], 'name' => ['type' => 'string'], 'description' => ['type' => 'string'], - 'is_static' => ['type' => 'boolean'], 'domains' => ['type' => 'string'], 'git_repository' => ['type' => 'string'], 'git_branch' => ['type' => 'string'], 'git_commit_sha' => ['type' => 'string'], 'docker_registry_image_name' => ['type' => 'string'], 'docker_registry_image_tag' => ['type' => 'string'], - 'build_pack' => ['type' => 'string'], + 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose']], + 'is_static' => ['type' => 'boolean'], 'install_command' => ['type' => 'string'], 'build_command' => ['type' => 'string'], 'start_command' => ['type' => 'string'], @@ -197,7 +166,7 @@ public function create_dockercompose_application(Request $request) 'manual_webhook_secret_bitbucket' => ['type' => 'string'], 'manual_webhook_secret_gitea' => ['type' => 'string'], 'redirect' => ['type' => 'string'], - 'github_app_uuid' => ['type' => 'string'], + // 'github_app_uuid' => ['type' => 'string'], 'instant_deploy' => ['type' => 'boolean'], 'dockerfile' => ['type' => 'string'], 'docker_compose_location' => ['type' => 'string'], @@ -212,16 +181,8 @@ public function create_dockercompose_application(Request $request) responses: [ new OA\Response( response: 200, - description: 'Get all applications.', - content: [ - new OA\MediaType( - mediaType: 'application/json', - schema: new OA\Schema( - type: 'array', - items: new OA\Items(ref: '#/components/schemas/Application') - ) - ), - ]), + description: 'Application created successfully.', + ), new OA\Response( response: 401, ref: '#/components/responses/401', @@ -232,6 +193,433 @@ public function create_dockercompose_application(Request $request) ), ] )] + public function create_public_application(Request $request) + { + return $this->create_application($request, 'public'); + } + + #[OA\Post( + summary: 'Create (Private - GH App)', + description: 'Create new application based on a private repository through a Github App.', + path: '/applications/private-gh-app', + security: [ + ['bearerAuth' => []], + ], + tags: ['Applications'], + requestBody: new OA\RequestBody( + description: 'Application object that needs to be created.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['project_uuid', 'server_uuid', 'environment_name', 'github_app_uuid', 'git_repository', 'git_branch', 'build_pack', 'ports_exposes'], + properties: [ + 'project_uuid' => ['type' => 'string'], + 'server_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'github_app_uuid' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'domains' => ['type' => 'string'], + 'git_repository' => ['type' => 'string'], + 'git_branch' => ['type' => 'string'], + 'git_commit_sha' => ['type' => 'string'], + 'docker_registry_image_name' => ['type' => 'string'], + 'docker_registry_image_tag' => ['type' => 'string'], + 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose']], + 'is_static' => ['type' => 'boolean'], + 'install_command' => ['type' => 'string'], + 'build_command' => ['type' => 'string'], + 'start_command' => ['type' => 'string'], + 'ports_exposes' => ['type' => 'string'], + 'ports_mappings' => ['type' => 'string'], + 'base_directory' => ['type' => 'string'], + 'publish_directory' => ['type' => 'string'], + 'health_check_enabled' => ['type' => 'boolean'], + 'health_check_path' => ['type' => 'string'], + 'health_check_port' => ['type' => 'integer'], + 'health_check_host' => ['type' => 'string'], + 'health_check_method' => ['type' => 'string'], + 'health_check_return_code' => ['type' => 'integer'], + 'health_check_scheme' => ['type' => 'string'], + 'health_check_response_text' => ['type' => 'string'], + 'health_check_interval' => ['type' => 'integer'], + 'health_check_timeout' => ['type' => 'integer'], + 'health_check_retries' => ['type' => 'integer'], + 'health_check_start_period' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'string'], + 'custom_labels' => ['type' => 'string'], + 'custom_docker_run_options' => ['type' => 'string'], + 'post_deployment_command' => ['type' => 'string'], + 'post_deployment_command_container' => ['type' => 'string'], + 'pre_deployment_command' => ['type' => 'string'], + 'pre_deployment_command_container' => ['type' => 'string'], + 'manual_webhook_secret_github' => ['type' => 'string'], + 'manual_webhook_secret_gitlab' => ['type' => 'string'], + 'manual_webhook_secret_bitbucket' => ['type' => 'string'], + 'manual_webhook_secret_gitea' => ['type' => 'string'], + 'redirect' => ['type' => 'string'], + 'instant_deploy' => ['type' => 'boolean'], + 'dockerfile' => ['type' => 'string'], + 'docker_compose_location' => ['type' => 'string'], + 'docker_compose_raw' => ['type' => 'string'], + 'docker_compose_custom_start_command' => ['type' => 'string'], + 'docker_compose_custom_build_command' => ['type' => 'string'], + 'docker_compose_domains' => ['type' => 'array'], + 'watch_paths' => ['type' => 'string'], + ], + )), + ]), + responses: [ + new OA\Response( + response: 200, + description: 'Application created successfully.', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_private_gh_app_application(Request $request) + { + return $this->create_application($request, 'private-gh-app'); + } + + #[OA\Post( + summary: 'Create (Private - Deploy Key)', + description: 'Create new application based on a private repository through a Deploy Key.', + path: '/applications/private-deploy-key', + security: [ + ['bearerAuth' => []], + ], + tags: ['Applications'], + requestBody: new OA\RequestBody( + description: 'Application object that needs to be created.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['project_uuid', 'server_uuid', 'environment_name', 'private_key_uuid', 'git_repository', 'git_branch', 'build_pack', 'ports_exposes'], + properties: [ + 'project_uuid' => ['type' => 'string'], + 'server_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'private_key_uuid' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'domains' => ['type' => 'string'], + 'git_repository' => ['type' => 'string'], + 'git_branch' => ['type' => 'string'], + 'git_commit_sha' => ['type' => 'string'], + 'docker_registry_image_name' => ['type' => 'string'], + 'docker_registry_image_tag' => ['type' => 'string'], + 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose']], + 'is_static' => ['type' => 'boolean'], + 'install_command' => ['type' => 'string'], + 'build_command' => ['type' => 'string'], + 'start_command' => ['type' => 'string'], + 'ports_exposes' => ['type' => 'string'], + 'ports_mappings' => ['type' => 'string'], + 'base_directory' => ['type' => 'string'], + 'publish_directory' => ['type' => 'string'], + 'health_check_enabled' => ['type' => 'boolean'], + 'health_check_path' => ['type' => 'string'], + 'health_check_port' => ['type' => 'integer'], + 'health_check_host' => ['type' => 'string'], + 'health_check_method' => ['type' => 'string'], + 'health_check_return_code' => ['type' => 'integer'], + 'health_check_scheme' => ['type' => 'string'], + 'health_check_response_text' => ['type' => 'string'], + 'health_check_interval' => ['type' => 'integer'], + 'health_check_timeout' => ['type' => 'integer'], + 'health_check_retries' => ['type' => 'integer'], + 'health_check_start_period' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'string'], + 'custom_labels' => ['type' => 'string'], + 'custom_docker_run_options' => ['type' => 'string'], + 'post_deployment_command' => ['type' => 'string'], + 'post_deployment_command_container' => ['type' => 'string'], + 'pre_deployment_command' => ['type' => 'string'], + 'pre_deployment_command_container' => ['type' => 'string'], + 'manual_webhook_secret_github' => ['type' => 'string'], + 'manual_webhook_secret_gitlab' => ['type' => 'string'], + 'manual_webhook_secret_bitbucket' => ['type' => 'string'], + 'manual_webhook_secret_gitea' => ['type' => 'string'], + 'redirect' => ['type' => 'string'], + 'instant_deploy' => ['type' => 'boolean'], + 'dockerfile' => ['type' => 'string'], + 'docker_compose_location' => ['type' => 'string'], + 'docker_compose_raw' => ['type' => 'string'], + 'docker_compose_custom_start_command' => ['type' => 'string'], + 'docker_compose_custom_build_command' => ['type' => 'string'], + 'docker_compose_domains' => ['type' => 'array'], + 'watch_paths' => ['type' => 'string'], + ], + )), + ]), + responses: [ + new OA\Response( + response: 200, + description: 'Application created successfully.', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_private_deploy_key_application(Request $request) + { + return $this->create_application($request, 'private-deploy-key'); + } + + #[OA\Post( + summary: 'Create (Dockerfile)', + description: 'Create new application based on a simple Dockerfile.', + path: '/applications/dockerfile', + security: [ + ['bearerAuth' => []], + ], + tags: ['Applications'], + requestBody: new OA\RequestBody( + description: 'Application object that needs to be created.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['project_uuid', 'server_uuid', 'environment_name', 'dockerfile'], + properties: [ + 'project_uuid' => ['type' => 'string'], + 'server_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'dockerfile' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'domains' => ['type' => 'string'], + 'docker_registry_image_name' => ['type' => 'string'], + 'docker_registry_image_tag' => ['type' => 'string'], + 'ports_exposes' => ['type' => 'string'], + 'ports_mappings' => ['type' => 'string'], + 'base_directory' => ['type' => 'string'], + 'health_check_enabled' => ['type' => 'boolean'], + 'health_check_path' => ['type' => 'string'], + 'health_check_port' => ['type' => 'integer'], + 'health_check_host' => ['type' => 'string'], + 'health_check_method' => ['type' => 'string'], + 'health_check_return_code' => ['type' => 'integer'], + 'health_check_scheme' => ['type' => 'string'], + 'health_check_response_text' => ['type' => 'string'], + 'health_check_interval' => ['type' => 'integer'], + 'health_check_timeout' => ['type' => 'integer'], + 'health_check_retries' => ['type' => 'integer'], + 'health_check_start_period' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'string'], + 'custom_labels' => ['type' => 'string'], + 'custom_docker_run_options' => ['type' => 'string'], + 'post_deployment_command' => ['type' => 'string'], + 'post_deployment_command_container' => ['type' => 'string'], + 'pre_deployment_command' => ['type' => 'string'], + 'pre_deployment_command_container' => ['type' => 'string'], + 'manual_webhook_secret_github' => ['type' => 'string'], + 'manual_webhook_secret_gitlab' => ['type' => 'string'], + 'manual_webhook_secret_bitbucket' => ['type' => 'string'], + 'manual_webhook_secret_gitea' => ['type' => 'string'], + 'redirect' => ['type' => 'string'], + 'instant_deploy' => ['type' => 'boolean'], + ], + )), + ]), + responses: [ + new OA\Response( + response: 200, + description: 'Application created successfully.', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_dockerfile_application(Request $request) + { + return $this->create_application($request, 'dockerfile'); + } + + #[OA\Post( + summary: 'Create (Docker Image)', + description: 'Create new application based on a prebuilt docker image', + path: '/applications/dockerimage', + security: [ + ['bearerAuth' => []], + ], + tags: ['Applications'], + requestBody: new OA\RequestBody( + description: 'Application object that needs to be created.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['project_uuid', 'server_uuid', 'environment_name', 'docker_registry_image_name', 'ports_exposes'], + properties: [ + 'project_uuid' => ['type' => 'string'], + 'server_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'docker_registry_image_name' => ['type' => 'string'], + 'docker_registry_image_tag' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'domains' => ['type' => 'string'], + 'git_repository' => ['type' => 'string'], + 'git_branch' => ['type' => 'string'], + 'git_commit_sha' => ['type' => 'string'], + 'ports_exposes' => ['type' => 'string'], + 'ports_mappings' => ['type' => 'string'], + 'health_check_enabled' => ['type' => 'boolean'], + 'health_check_path' => ['type' => 'string'], + 'health_check_port' => ['type' => 'integer'], + 'health_check_host' => ['type' => 'string'], + 'health_check_method' => ['type' => 'string'], + 'health_check_return_code' => ['type' => 'integer'], + 'health_check_scheme' => ['type' => 'string'], + 'health_check_response_text' => ['type' => 'string'], + 'health_check_interval' => ['type' => 'integer'], + 'health_check_timeout' => ['type' => 'integer'], + 'health_check_retries' => ['type' => 'integer'], + 'health_check_start_period' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'string'], + 'custom_labels' => ['type' => 'string'], + 'custom_docker_run_options' => ['type' => 'string'], + 'post_deployment_command' => ['type' => 'string'], + 'post_deployment_command_container' => ['type' => 'string'], + 'pre_deployment_command' => ['type' => 'string'], + 'pre_deployment_command_container' => ['type' => 'string'], + 'manual_webhook_secret_github' => ['type' => 'string'], + 'manual_webhook_secret_gitlab' => ['type' => 'string'], + 'manual_webhook_secret_bitbucket' => ['type' => 'string'], + 'manual_webhook_secret_gitea' => ['type' => 'string'], + 'redirect' => ['type' => 'string'], + 'instant_deploy' => ['type' => 'boolean'], + ], + )), + ]), + responses: [ + new OA\Response( + response: 200, + description: 'Application created successfully.', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_dockerimage_application(Request $request) + { + return $this->create_application($request, 'dockerimage'); + } + + #[OA\Post( + summary: 'Create (Docker Compose)', + description: 'Create new application based on a docker-compose file.', + path: '/applications/dockercompose', + security: [ + ['bearerAuth' => []], + ], + tags: ['Applications'], + requestBody: new OA\RequestBody( + description: 'Application object that needs to be created.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['project_uuid', 'server_uuid', 'environment_name', 'docker_compose_raw'], + properties: [ + 'project_uuid' => ['type' => 'string'], + 'server_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'docker_compose_raw' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'instant_deploy' => ['type' => 'boolean'], + ], + )), + ]), + responses: [ + new OA\Response( + response: 200, + description: 'Application created successfully.', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_dockercompose_application(Request $request) + { + return $this->create_application($request, 'dockercompose'); + } + private function create_application(Request $request, $type) { $allowedFields = ['project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'redirect', 'github_app_uuid', 'instant_deploy', 'dockerfile', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'watch_paths']; @@ -620,7 +1008,7 @@ private function create_application(Request $request, $type) 'uuid' => data_get($application, 'uuid'), 'domains' => data_get($application, 'domains'), ])); - } elseif ($type === 'docker-image') { + } elseif ($type === 'dockerimage') { if (! $request->has('name')) { $request->offsetSet('name', 'docker-image-'.new Cuid2(7)); } @@ -748,7 +1136,9 @@ private function create_application(Request $request, $type) $service->name = "service-$service->uuid"; $service->parse(isNew: true); - StartService::dispatch($service); + if ($instantDeploy) { + StartService::dispatch($service); + } return response()->json(serializeApiResponse([ 'uuid' => data_get($service, 'uuid'), @@ -783,7 +1173,7 @@ private function create_application(Request $request, $type) responses: [ new OA\Response( response: 200, - description: 'Get all applications.', + description: 'Get application by UUID.', content: [ new OA\MediaType( mediaType: 'application/json', @@ -824,6 +1214,55 @@ public function application_by_uuid(Request $request) return response()->json($this->removeSensitiveData($application)); } + #[OA\Delete( + summary: 'Delete', + description: 'Delete application by UUID.', + path: '/applications/{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', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Application deleted.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Application deleted.'], + ] + ) + ), + ]), + 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 delete_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); @@ -851,6 +1290,105 @@ public function delete_by_uuid(Request $request) ]); } + #[OA\Patch( + summary: 'Update', + description: 'Update application by UUID.', + path: '/applications', + security: [ + ['bearerAuth' => []], + ], + tags: ['Applications'], + requestBody: new OA\RequestBody( + description: 'Application updated.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'project_uuid' => ['type' => 'string'], + 'server_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'domains' => ['type' => 'string'], + 'git_repository' => ['type' => 'string'], + 'git_branch' => ['type' => 'string'], + 'git_commit_sha' => ['type' => 'string'], + 'docker_registry_image_name' => ['type' => 'string'], + 'docker_registry_image_tag' => ['type' => 'string'], + 'build_pack' => ['type' => 'string', 'enum' => ['nixpacks', 'static', 'dockerfile', 'dockercompose']], + 'is_static' => ['type' => 'boolean'], + 'install_command' => ['type' => 'string'], + 'build_command' => ['type' => 'string'], + 'start_command' => ['type' => 'string'], + 'ports_exposes' => ['type' => 'string'], + 'ports_mappings' => ['type' => 'string'], + 'base_directory' => ['type' => 'string'], + 'publish_directory' => ['type' => 'string'], + 'health_check_enabled' => ['type' => 'boolean'], + 'health_check_path' => ['type' => 'string'], + 'health_check_port' => ['type' => 'integer'], + 'health_check_host' => ['type' => 'string'], + 'health_check_method' => ['type' => 'string'], + 'health_check_return_code' => ['type' => 'integer'], + 'health_check_scheme' => ['type' => 'string'], + 'health_check_response_text' => ['type' => 'string'], + 'health_check_interval' => ['type' => 'integer'], + 'health_check_timeout' => ['type' => 'integer'], + 'health_check_retries' => ['type' => 'integer'], + 'health_check_start_period' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'string'], + 'custom_labels' => ['type' => 'string'], + 'custom_docker_run_options' => ['type' => 'string'], + 'post_deployment_command' => ['type' => 'string'], + 'post_deployment_command_container' => ['type' => 'string'], + 'pre_deployment_command' => ['type' => 'string'], + 'pre_deployment_command_container' => ['type' => 'string'], + 'manual_webhook_secret_github' => ['type' => 'string'], + 'manual_webhook_secret_gitlab' => ['type' => 'string'], + 'manual_webhook_secret_bitbucket' => ['type' => 'string'], + 'manual_webhook_secret_gitea' => ['type' => 'string'], + 'redirect' => ['type' => 'string'], + 'github_app_uuid' => ['type' => 'string'], + 'instant_deploy' => ['type' => 'boolean'], + 'dockerfile' => ['type' => 'string'], + 'docker_compose_location' => ['type' => 'string'], + 'docker_compose_raw' => ['type' => 'string'], + 'docker_compose_custom_start_command' => ['type' => 'string'], + 'docker_compose_custom_build_command' => ['type' => 'string'], + 'docker_compose_domains' => ['type' => 'array'], + 'watch_paths' => ['type' => 'string'], + ], + )), + ]), + responses: [ + new OA\Response( + response: 200, + description: 'Application updated.', + ), + 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 update_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); @@ -961,6 +1499,53 @@ public function update_by_uuid(Request $request) return response()->json($this->removeSensitiveData($application)); } + #[OA\Get( + summary: 'List Envs', + description: 'List all envs by application UUID.', + path: '/applications/{uuid}/envs', + 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', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'All environment variables by application UUID.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'array', + items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable') + ) + ), + ]), + 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 envs(Request $request) { $teamId = getTeamIdFromToken(); @@ -996,6 +1581,77 @@ public function envs(Request $request) return response()->json($envs); } + #[OA\Patch( + summary: 'Update Env', + description: 'Update env by application UUID.', + path: '/applications/{uuid}/envs', + 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', + ) + ), + ], + requestBody: new OA\RequestBody( + description: 'Env updated.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['key', 'value'], + properties: [ + 'key' => ['type' => 'string'], + 'value' => ['type' => 'string'], + 'is_preview' => ['type' => 'boolean'], + 'is_build_time' => ['type' => 'boolean'], + 'is_literal' => ['type' => 'boolean'], + 'is_multiline' => ['type' => 'boolean'], + 'is_shown_once' => ['type' => 'boolean'], + ], + ), + ), + ], + ), + responses: [ + new OA\Response( + response: 201, + description: 'Environment variable updated.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Environment variable updated.'], + ] + ) + ), + ]), + 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 update_env_by_uuid(Request $request) { $allowedFields = ['key', 'value', 'is_preview', 'is_build_time', 'is_literal']; @@ -1064,7 +1720,7 @@ public function update_env_by_uuid(Request $request) } $env->save(); - return response()->json($this->removeSensitiveData($env)); + return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } else { return response()->json([ 'message' => 'Environment variable not found.', @@ -1091,7 +1747,7 @@ public function update_env_by_uuid(Request $request) } $env->save(); - return response()->json($this->removeSensitiveData($env)); + return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } else { return response()->json([ @@ -1107,6 +1763,85 @@ public function update_env_by_uuid(Request $request) } + #[OA\Patch( + summary: 'Update Envs (Bulk)', + description: 'Update multiple envs by application UUID.', + path: '/applications/{uuid}/envs/bulk', + 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', + ) + ), + ], + requestBody: new OA\RequestBody( + description: 'Bulk envs updated.', + required: true, + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['data'], + properties: [ + 'data' => [ + 'type' => 'array', + 'items' => new OA\Schema( + type: 'object', + properties: [ + 'key' => ['type' => 'string'], + 'value' => ['type' => 'string'], + 'is_preview' => ['type' => 'boolean'], + 'is_build_time' => ['type' => 'boolean'], + 'is_literal' => ['type' => 'boolean'], + 'is_multiline' => ['type' => 'boolean'], + 'is_shown_once' => ['type' => 'boolean'], + ], + ), + ], + ], + ), + ), + ], + ), + responses: [ + new OA\Response( + response: 201, + description: 'Environment variables updated.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Environment variables updated.'], + ] + ) + ), + ]), + 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 create_bulk_envs(Request $request) { $teamId = getTeamIdFromToken(); @@ -1216,9 +1951,77 @@ public function create_bulk_envs(Request $request) } } - return response()->json($this->removeSensitiveData($env)); + return response()->json($this->removeSensitiveData($env))->setStatusCode(201); } + #[OA\Post( + summary: 'Create Env', + description: 'Create env by application UUID.', + path: '/applications/{uuid}/envs', + 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', + ) + ), + ], + requestBody: new OA\RequestBody( + required: true, + description: 'Env created.', + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'key' => ['type' => 'string'], + 'value' => ['type' => 'string'], + 'is_preview' => ['type' => 'boolean'], + 'is_build_time' => ['type' => 'boolean'], + 'is_literal' => ['type' => 'boolean'], + 'is_multiline' => ['type' => 'boolean'], + 'is_shown_once' => ['type' => 'boolean'], + ], + ), + ), + ), + responses: [ + new OA\Response( + response: 201, + description: 'Environment variable created.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'uuid' => ['type' => 'string', 'example' => 'nc0k04gk8g0cgsk440g0koko'], + ] + ) + ), + ]), + 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 create_env(Request $request) { $allowedFields = ['key', 'value', 'is_preview', 'is_build_time', 'is_literal']; @@ -1276,7 +2079,9 @@ public function create_env(Request $request) 'is_shown_once' => $request->is_shown_once ?? false, ]); - return response()->json($this->removeSensitiveData($env))->setStatusCode(201); + return response()->json([ + 'uuid' => $env->uuid, + ])->setStatusCode(201); } } else { $env = $application->environment_variables->where('key', $request->key)->first(); @@ -1295,7 +2100,9 @@ public function create_env(Request $request) 'is_shown_once' => $request->is_shown_once ?? false, ]); - return response()->json($this->removeSensitiveData($env))->setStatusCode(201); + return response()->json([ + 'uuid' => $env->uuid, + ])->setStatusCode(201); } } @@ -1306,6 +2113,65 @@ public function create_env(Request $request) } + #[OA\Delete( + summary: 'Delete Env', + description: 'Delete env by UUID.', + path: '/applications/{uuid}/envs/{env_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: 'env_uuid', + in: 'path', + description: 'UUID of the environment variable.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Environment variable deleted.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Environment variable deleted.'], + ] + ) + ), + ]), + 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 delete_env_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); @@ -1332,6 +2198,74 @@ public function delete_env_by_uuid(Request $request) ]); } + #[OA\Get( + summary: 'Start', + description: 'Start application. `Post` request is also accepted.', + path: '/applications/{uuid}/start', + 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: 'force', + in: 'query', + description: 'Force rebuild.', + schema: new OA\Schema( + type: 'boolean', + default: false, + ) + ), + new OA\Parameter( + name: 'instant_deploy', + in: 'query', + description: 'Instant deploy (skip queuing).', + schema: new OA\Schema( + type: 'boolean', + default: false, + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Start application.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Deployment request queued.'], + 'deployment_uuid' => ['type' => 'string', 'example' => 'doogksw'], + 'deployment_api_url' => ['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 action_deploy(Request $request) { $teamId = getTeamIdFromToken(); @@ -1369,6 +2303,55 @@ public function action_deploy(Request $request) ); } + #[OA\Get( + summary: 'Stop', + description: 'Stop application. `Post` request is also accepted.', + path: '/applications/{uuid}/stop', + 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', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Stop application.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Application stopping request queued.'], + ] + ) + ), + ]), + 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 action_stop(Request $request) { $teamId = getTeamIdFromToken(); @@ -1392,6 +2375,58 @@ public function action_stop(Request $request) ); } + #[OA\Get( + summary: 'Restart', + description: 'Restart application. `Post` request is also accepted.', + path: '/applications/{uuid}/restart', + 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', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Restart application.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Restart request queued.'], + 'deployment_uuid' => ['type' => 'string', 'example' => 'doogksw'], + 'deployment_api_url' => ['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 action_restart(Request $request) { $teamId = getTeamIdFromToken(); diff --git a/app/Http/Controllers/Api/DatabasesController.php b/app/Http/Controllers/Api/DatabasesController.php index 152285e91..2ff21344c 100644 --- a/app/Http/Controllers/Api/DatabasesController.php +++ b/app/Http/Controllers/Api/DatabasesController.php @@ -12,7 +12,7 @@ use App\Models\Project; use App\Models\Server; use Illuminate\Http\Request; -use Illuminate\Validation\Rule; +use OpenApi\Attributes as OA; class DatabasesController extends Controller { @@ -41,6 +41,33 @@ private function removeSensitiveData($database) return serializeApiResponse($database); } + #[OA\Get( + summary: 'List', + description: 'List all databases.', + path: '/databases', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + responses: [ + new OA\Response( + response: 200, + description: 'Get all databases', + content: new OA\JsonContent( + type: 'string', + example: 'Content is very complex. Will be implemented later.', + ), + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] public function databases(Request $request) { $teamId = getTeamIdFromToken(); @@ -59,6 +86,49 @@ public function databases(Request $request) return response()->json($databases); } + #[OA\Get( + summary: 'Get', + description: 'Get database by UUID.', + path: '/databases/{uuid}', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + parameters: [ + new OA\Parameter( + name: 'uuid', + in: 'path', + description: 'UUID of the database.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Get all databases', + content: new OA\JsonContent( + type: 'string', + example: 'Content is very complex. Will be implemented later.', + ), + ), + 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 database_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); @@ -76,6 +146,95 @@ public function database_by_uuid(Request $request) return response()->json($this->removeSensitiveData($database)); } + #[OA\Patch( + summary: 'Update', + description: 'Update database by UUID.', + path: '/databases/{uuid}', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + parameters: [ + new OA\Parameter( + name: 'uuid', + in: 'path', + description: 'UUID of the database.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'postgres_user' => ['type' => 'string'], + 'postgres_password' => ['type' => 'string'], + 'postgres_db' => ['type' => 'string'], + 'postgres_initdb_args' => ['type' => 'string'], + 'postgres_host_auth_method' => ['type' => 'string'], + 'postgres_conf' => ['type' => 'string'], + 'clickhouse_admin_user' => ['type' => 'string'], + 'clickhouse_admin_password' => ['type' => 'string'], + 'dragonfly_password' => ['type' => 'string'], + 'redis_password' => ['type' => 'string'], + 'redis_conf' => ['type' => 'string'], + 'keydb_password' => ['type' => 'string'], + 'keydb_conf' => ['type' => 'string'], + 'mariadb_conf' => ['type' => 'string'], + 'mariadb_root_password' => ['type' => 'string'], + 'mariadb_user' => ['type' => 'string'], + 'mariadb_password' => ['type' => 'string'], + 'mariadb_database' => ['type' => 'string'], + 'mongo_conf' => ['type' => 'string'], + 'mongo_initdb_root_username' => ['type' => 'string'], + 'mongo_initdb_root_password' => ['type' => 'string'], + 'mongo_initdb_init_database' => ['type' => 'string'], + 'mysql_root_password' => ['type' => 'string'], + 'mysql_user' => ['type' => 'string'], + 'mysql_database' => ['type' => 'string'], + 'mysql_conf' => ['type' => 'string'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + 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 update_by_uuid(Request $request) { $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf']; @@ -301,9 +460,505 @@ public function update_by_uuid(Request $request) } - public function create_database(Request $request) + #[OA\Post( + summary: 'Create (PostgreSQL)', + description: 'Create a new PostgreSQL database.', + path: '/databases/postgresql', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'postgres_user' => ['type' => 'string'], + 'postgres_password' => ['type' => 'string'], + 'postgres_db' => ['type' => 'string'], + 'postgres_initdb_args' => ['type' => 'string'], + 'postgres_host_auth_method' => ['type' => 'string'], + 'postgres_conf' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_postgresql(Request $request) { - $allowedFields = ['type', 'name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf']; + return $this->create_database($request, NewDatabaseTypes::POSTGRESQL); + } + + #[OA\Post( + summary: 'Create (Clickhouse)', + description: 'Create a new Clickhouse database.', + path: '/databases/clickhouse', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'clickhouse_admin_user' => ['type' => 'string'], + 'clickhouse_admin_password' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_clickhouse(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::CLICKHOUSE); + } + + #[OA\Post( + summary: 'Create (DragonFly)', + description: 'Create a new DragonFly database.', + path: '/databases/dragonfly', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'dragonfly_password' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_dragonfly(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::DRAGONFLY); + } + + #[OA\Post( + summary: 'Create (Redis)', + description: 'Create a new Redis database.', + path: '/databases/redis', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'redis_password' => ['type' => 'string'], + 'redis_conf' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_redis(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::REDIS); + } + + #[OA\Post( + summary: 'Create (KeyDB)', + description: 'Create a new KeyDB database.', + path: '/databases/keydb', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'keydb_password' => ['type' => 'string'], + 'keydb_conf' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_keydb(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::KEYDB); + } + + #[OA\Post( + summary: 'Create (MariaDB)', + description: 'Create a new MariaDB database.', + path: '/databases/mariadb', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'mariadb_conf' => ['type' => 'string'], + 'mariadb_root_password' => ['type' => 'string'], + 'mariadb_user' => ['type' => 'string'], + 'mariadb_password' => ['type' => 'string'], + 'mariadb_database' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_mariadb(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::MARIADB); + } + + #[OA\Post( + summary: 'Create (MySQL)', + description: 'Create a new MySQL database.', + path: '/databases/mysql', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'mysql_root_password' => ['type' => 'string'], + 'mysql_user' => ['type' => 'string'], + 'mysql_database' => ['type' => 'string'], + 'mysql_conf' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_mysql(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::MYSQL); + } + + #[OA\Post( + summary: 'Create (MongoDB)', + description: 'Create a new MongoDB database.', + path: '/databases/mongodb', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + + requestBody: new OA\RequestBody( + description: 'Database data', + required: true, + content: new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + required: ['server_uuid', 'project_uuid', 'environment_name'], + properties: [ + 'server_uuid' => ['type' => 'string'], + 'project_uuid' => ['type' => 'string'], + 'environment_name' => ['type' => 'string'], + 'destination_uuid' => ['type' => 'string'], + 'mongo_conf' => ['type' => 'string'], + 'mongo_initdb_root_username' => ['type' => 'string'], + 'name' => ['type' => 'string'], + 'description' => ['type' => 'string'], + 'image' => ['type' => 'string'], + 'is_public' => ['type' => 'boolean'], + 'public_port' => ['type' => 'integer'], + 'limits_memory' => ['type' => 'string'], + 'limits_memory_swap' => ['type' => 'string'], + 'limits_memory_swappiness' => ['type' => 'integer'], + 'limits_memory_reservation' => ['type' => 'string'], + 'limits_cpus' => ['type' => 'string'], + 'limits_cpuset' => ['type' => 'string'], + 'limits_cpu_shares' => ['type' => 'integer'], + 'instant_deploy' => ['type' => 'boolean'], + ], + ), + ) + ), + responses: [ + new OA\Response( + response: 200, + description: 'Database updated', + ), + new OA\Response( + response: 401, + ref: '#/components/responses/401', + ), + new OA\Response( + response: 400, + ref: '#/components/responses/400', + ), + ] + )] + public function create_database_mongodb(Request $request) + { + return $this->create_database($request, NewDatabaseTypes::MONGODB); + } + + public function create_database(Request $request, NewDatabaseTypes $type) + { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf']; $teamId = getTeamIdFromToken(); if (is_null($teamId)) { @@ -314,56 +969,10 @@ public function create_database(Request $request) if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } - $validator = customApiValidator($request->all(), [ - 'type' => ['required', Rule::enum(NewDatabaseTypes::class)], - 'name' => 'string|max:255', - 'description' => 'string|nullable', - 'image' => 'string', - 'project_uuid' => 'string|required', - 'environment_name' => 'string|required', - 'server_uuid' => 'string|required', - 'destination_uuid' => 'string', - 'is_public' => 'boolean', - 'public_port' => 'numeric|nullable', - 'limits_memory' => 'string', - 'limits_memory_swap' => 'string', - 'limits_memory_swappiness' => 'numeric', - 'limits_memory_reservation' => 'string', - 'limits_cpus' => 'string', - 'limits_cpuset' => 'string|nullable', - 'limits_cpu_shares' => 'numeric', - 'postgres_user' => 'string', - 'postgres_password' => 'string', - 'postgres_db' => 'string', - 'postgres_initdb_args' => 'string', - 'postgres_host_auth_method' => 'string', - 'postgres_conf' => 'string', - 'clickhouse_admin_user' => 'string', - 'clickhouse_admin_password' => 'string', - 'dragonfly_password' => 'string', - 'redis_password' => 'string', - 'redis_conf' => 'string', - 'keydb_password' => 'string', - 'keydb_conf' => 'string', - 'mariadb_conf' => 'string', - 'mariadb_root_password' => 'string', - 'mariadb_user' => 'string', - 'mariadb_password' => 'string', - 'mariadb_database' => 'string', - 'mongo_conf' => 'string', - 'mongo_initdb_root_username' => 'string', - 'mongo_initdb_root_password' => 'string', - 'mongo_initdb_init_database' => 'string', - 'mysql_root_password' => 'string', - 'mysql_user' => 'string', - 'mysql_database' => 'string', - 'mysql_conf' => 'string', - 'instant_deploy' => 'boolean', - ]); $extraFields = array_diff(array_keys($request->all()), $allowedFields); - if ($validator->fails() || ! empty($extraFields)) { - $errors = $validator->errors(); + if (! empty($extraFields)) { + $errors = collect([]); if (! empty($extraFields)) { foreach ($extraFields as $field) { $errors->add($field, 'This field is not allowed.'); @@ -405,7 +1014,65 @@ public function create_database(Request $request) return response()->json(['message' => 'Public port already used by another database.'], 400); } } - if ($request->type === NewDatabaseTypes::POSTGRESQL->value) { + $validator = customApiValidator($request->all(), [ + 'name' => 'string|max:255', + 'description' => 'string|nullable', + 'image' => 'string', + 'project_uuid' => 'string|required', + 'environment_name' => 'string|required', + 'server_uuid' => 'string|required', + 'destination_uuid' => 'string', + 'is_public' => 'boolean', + 'public_port' => 'numeric|nullable', + 'limits_memory' => 'string', + 'limits_memory_swap' => 'string', + 'limits_memory_swappiness' => 'numeric', + 'limits_memory_reservation' => 'string', + 'limits_cpus' => 'string', + 'limits_cpuset' => 'string|nullable', + 'limits_cpu_shares' => 'numeric', + 'instant_deploy' => 'boolean', + ]); + if ($validator->failed()) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $validator->errors(), + ], 422); + } + if ($request->public_port) { + if ($request->public_port < 1024 || $request->public_port > 65535) { + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => [ + 'public_port' => 'The public port should be between 1024 and 65535.', + ], + ], 422); + } + } + if ($type === NewDatabaseTypes::POSTGRESQL) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf']; + $validator = customApiValidator($request->all(), [ + 'postgres_user' => 'string', + 'postgres_password' => 'string', + 'postgres_db' => 'string', + 'postgres_initdb_args' => 'string', + 'postgres_host_auth_method' => 'string', + 'postgres_conf' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); if ($request->has('postgres_conf')) { if (! isBase64Encoded($request->postgres_conf)) { @@ -430,16 +1097,38 @@ public function create_database(Request $request) $database = create_standalone_postgresql($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } + } + $database->refresh(); + $payload = [ + 'uuid' => $database->uuid, + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; } - return response()->json(serializeApiResponse([ - 'uuid' => $database->uuid, - ]))->setStatusCode(201); + return response()->json(serializeApiResponse($payload))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::MARIADB->value) { + } elseif ($type === NewDatabaseTypes::MARIADB) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database']; + $validator = customApiValidator($request->all(), [ + 'clickhouse_admin_user' => 'string', + 'clickhouse_admin_password' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); if ($request->has('mariadb_conf')) { if (! isBase64Encoded($request->mariadb_conf)) { @@ -464,15 +1153,40 @@ public function create_database(Request $request) $database = create_standalone_mariadb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } - return response()->json(serializeApiResponse([ + $database->refresh(); + $payload = [ 'uuid' => $database->uuid, - ]))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::MYSQL->value) { + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; + } + + return response()->json(serializeApiResponse($payload))->setStatusCode(201); + } elseif ($type === NewDatabaseTypes::MYSQL) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mysql_user', 'mysql_database', 'mysql_conf']; + $validator = customApiValidator($request->all(), [ + 'mysql_root_password' => 'string', + 'mysql_user' => 'string', + 'mysql_database' => 'string', + 'mysql_conf' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); if ($request->has('mysql_conf')) { if (! isBase64Encoded($request->mysql_conf)) { @@ -497,15 +1211,38 @@ public function create_database(Request $request) $database = create_standalone_mysql($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } - return response()->json(serializeApiResponse([ + $database->refresh(); + $payload = [ 'uuid' => $database->uuid, - ]))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::REDIS->value) { + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; + } + + return response()->json(serializeApiResponse($payload))->setStatusCode(201); + } elseif ($type === NewDatabaseTypes::REDIS) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'redis_password', 'redis_conf']; + $validator = customApiValidator($request->all(), [ + 'redis_password' => 'string', + 'redis_conf' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); if ($request->has('redis_conf')) { if (! isBase64Encoded($request->redis_conf)) { @@ -530,28 +1267,68 @@ public function create_database(Request $request) $database = create_standalone_redis($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } - return response()->json(serializeApiResponse([ + $database->refresh(); + $payload = [ 'uuid' => $database->uuid, - ]))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::DRAGONFLY->value) { + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; + } + + return response()->json(serializeApiResponse($payload))->setStatusCode(201); + } elseif ($type === NewDatabaseTypes::DRAGONFLY) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'dragonfly_password']; + $validator = customApiValidator($request->all(), [ + 'dragonfly_password' => 'string', + ]); + + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } + removeUnnecessaryFieldsFromRequest($request); $database = create_standalone_dragonfly($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } return response()->json(serializeApiResponse([ 'uuid' => $database->uuid, ]))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::KEYDB->value) { + } elseif ($type === NewDatabaseTypes::KEYDB) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'keydb_password', 'keydb_conf']; + $validator = customApiValidator($request->all(), [ + 'keydb_password' => 'string', + 'keydb_conf' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); if ($request->has('keydb_conf')) { if (! isBase64Encoded($request->keydb_conf)) { @@ -576,28 +1353,76 @@ public function create_database(Request $request) $database = create_standalone_keydb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } - return response()->json(serializeApiResponse([ + $database->refresh(); + $payload = [ 'uuid' => $database->uuid, - ]))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::CLICKHOUSE->value) { + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; + } + + return response()->json(serializeApiResponse($payload))->setStatusCode(201); + } elseif ($type === NewDatabaseTypes::CLICKHOUSE) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'clickhouse_admin_user', 'clickhouse_admin_password']; + $validator = customApiValidator($request->all(), [ + 'clickhouse_admin_user' => 'string', + 'clickhouse_admin_password' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); $database = create_standalone_clickhouse($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } - return response()->json(serializeApiResponse([ + $database->refresh(); + $payload = [ 'uuid' => $database->uuid, - ]))->setStatusCode(201); - } elseif ($request->type === NewDatabaseTypes::MONGODB->value) { + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; + } + + return response()->json(serializeApiResponse($payload))->setStatusCode(201); + } elseif ($type === NewDatabaseTypes::MONGODB) { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database']; + $validator = customApiValidator($request->all(), [ + 'mongo_conf' => 'string', + 'mongo_initdb_root_username' => 'string', + 'mongo_initdb_root_password' => 'string', + 'mongo_initdb_init_database' => 'string', + ]); + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } removeUnnecessaryFieldsFromRequest($request); if ($request->has('mongo_conf')) { if (! isBase64Encoded($request->mongo_conf)) { @@ -622,19 +1447,72 @@ public function create_database(Request $request) $database = create_standalone_mongodb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { StartDatabase::dispatch($database); - if ($request->is_public && $request->public_port) { - StartDatabaseProxy::dispatch($database); - } } - return response()->json(serializeApiResponse([ + $database->refresh(); + $payload = [ 'uuid' => $database->uuid, - ]))->setStatusCode(201); + 'internal_db_url' => $database->internal_db_url, + ]; + if ($database->is_public && $database->public_port) { + $payload['external_db_url'] = $database->external_db_url; + } + + return response()->json(serializeApiResponse($payload))->setStatusCode(201); } return response()->json(['message' => 'Invalid database type requested.'], 400); } + #[OA\Delete( + summary: 'Delete', + description: 'Delete database by UUID.', + path: '/databases/{uuid}', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + parameters: [ + new OA\Parameter( + name: 'uuid', + in: 'path', + description: 'UUID of the database.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Database deleted.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Database deleted.'], + ] + ) + ), + ]), + 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 delete_by_uuid(Request $request) { $teamId = getTeamIdFromToken(); @@ -656,6 +1534,54 @@ public function delete_by_uuid(Request $request) ]); } + #[OA\Get( + summary: 'Start', + description: 'Start database. `Post` request is also accepted.', + path: '/databases/{uuid}/start', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + parameters: [ + new OA\Parameter( + name: 'uuid', + in: 'path', + description: 'UUID of the database.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Start database.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Database starting request queued.'], + ]) + ), + ]), + 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 action_deploy(Request $request) { $teamId = getTeamIdFromToken(); @@ -683,6 +1609,54 @@ public function action_deploy(Request $request) ); } + #[OA\Get( + summary: 'Stop', + description: 'Stop database. `Post` request is also accepted.', + path: '/databases/{uuid}/stop', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + parameters: [ + new OA\Parameter( + name: 'uuid', + in: 'path', + description: 'UUID of the database.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Stop database.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Database stopping request queued.'], + ]) + ), + ]), + 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 action_stop(Request $request) { $teamId = getTeamIdFromToken(); @@ -710,6 +1684,54 @@ public function action_stop(Request $request) ); } + #[OA\Get( + summary: 'Restart', + description: 'Restart database. `Post` request is also accepted.', + path: '/databases/{uuid}/restart', + security: [ + ['bearerAuth' => []], + ], + tags: ['Databases'], + parameters: [ + new OA\Parameter( + name: 'uuid', + in: 'path', + description: 'UUID of the database.', + required: true, + schema: new OA\Schema( + type: 'string', + format: 'uuid', + ) + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Restart database.', + content: [ + new OA\MediaType( + mediaType: 'application/json', + schema: new OA\Schema( + type: 'object', + properties: [ + 'message' => ['type' => 'string', 'example' => 'Database restaring request queued.'], + ]) + ), + ]), + 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 action_restart(Request $request) { $teamId = getTeamIdFromToken(); diff --git a/app/Models/EnvironmentVariable.php b/app/Models/EnvironmentVariable.php index 04a556274..1d2a9dc66 100644 --- a/app/Models/EnvironmentVariable.php +++ b/app/Models/EnvironmentVariable.php @@ -6,9 +6,33 @@ use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; +use OpenApi\Attributes as OA; use Symfony\Component\Yaml\Yaml; use Visus\Cuid2\Cuid2; +#[OA\Schema( + description: 'Environment Variable model', + type: 'object', + properties: [ + 'id' => ['type' => 'integer'], + 'uuid' => ['type' => 'string'], + 'application_id' => ['type' => 'integer'], + 'service_id' => ['type' => 'integer'], + 'database_id' => ['type' => 'integer'], + 'is_build_time' => ['type' => 'boolean'], + 'is_literal' => ['type' => 'boolean'], + 'is_multiline' => ['type' => 'boolean'], + 'is_preview' => ['type' => 'boolean'], + 'is_shared' => ['type' => 'boolean'], + 'is_shown_once' => ['type' => 'boolean'], + 'key' => ['type' => 'string'], + 'value' => ['type' => 'string'], + 'real_value' => ['type' => 'string'], + 'version' => ['type' => 'string'], + 'created_at' => ['type' => 'string'], + 'updated_at' => ['type' => 'string'], + ] +)] class EnvironmentVariable extends Model { protected $guarded = []; diff --git a/openapi.yaml b/openapi.yaml index 8ae08befa..1131b171e 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -29,27 +29,19 @@ paths: security: - bearerAuth: [] - post: + patch: tags: - Applications - summary: Create - description: 'Create new application.' - operationId: b79c870f7f32360e4ed7fee8e053a055 + summary: Update + description: 'Update application by UUID.' + operationId: ff28a22d25b1f658c40b54d2073abbca requestBody: - description: 'Application object that needs to be created.' + description: 'Application updated.' required: true content: application/json: schema: - required: - - type - - project_uuid - - server_uuid - - environment_name properties: - type: - type: string - enum: [public, private-gh-app, private-deploy-key, dockerfile, docker-image, dockercompose] project_uuid: type: string server_uuid: @@ -62,8 +54,6 @@ paths: type: string description: type: string - is_static: - type: boolean domains: type: string git_repository: @@ -78,6 +68,9 @@ paths: type: string build_pack: type: string + enum: [nixpacks, static, dockerfile, dockercompose] + is_static: + type: boolean install_command: type: string build_command: @@ -173,13 +166,756 @@ paths: type: object responses: '200': - description: 'Get all applications.' - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Application' + description: 'Application updated.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + /applications/public: + post: + tags: + - Applications + summary: 'Create (Public)' + description: 'Create new application based on a public git repository.' + operationId: cb56324ad19693469b4461d3f6065a5b + requestBody: + description: 'Application object that needs to be created.' + required: true + content: + application/json: + schema: + required: + - project_uuid + - server_uuid + - environment_name + - git_repository + - git_branch + - build_pack + - ports_exposes + properties: + project_uuid: + type: string + server_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + domains: + type: string + git_repository: + type: string + git_branch: + type: string + git_commit_sha: + type: string + docker_registry_image_name: + type: string + docker_registry_image_tag: + type: string + build_pack: + type: string + enum: [nixpacks, static, dockerfile, dockercompose] + is_static: + type: boolean + install_command: + type: string + build_command: + type: string + start_command: + type: string + ports_exposes: + type: string + ports_mappings: + type: string + base_directory: + type: string + publish_directory: + type: string + health_check_enabled: + type: boolean + health_check_path: + type: string + health_check_port: + type: integer + health_check_host: + type: string + health_check_method: + type: string + health_check_return_code: + type: integer + health_check_scheme: + type: string + health_check_response_text: + type: string + health_check_interval: + type: integer + health_check_timeout: + type: integer + health_check_retries: + type: integer + health_check_start_period: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: string + custom_labels: + type: string + custom_docker_run_options: + type: string + post_deployment_command: + type: string + post_deployment_command_container: + type: string + pre_deployment_command: + type: string + pre_deployment_command_container: + type: string + manual_webhook_secret_github: + type: string + manual_webhook_secret_gitlab: + type: string + manual_webhook_secret_bitbucket: + type: string + manual_webhook_secret_gitea: + type: string + redirect: + type: string + instant_deploy: + type: boolean + dockerfile: + type: string + docker_compose_location: + type: string + docker_compose_raw: + type: string + docker_compose_custom_start_command: + type: string + docker_compose_custom_build_command: + type: string + docker_compose_domains: + type: array + watch_paths: + type: string + type: object + responses: + '200': + description: 'Application created successfully.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /applications/private-gh-app: + post: + tags: + - Applications + summary: 'Create (Private - GH App)' + description: 'Create new application based on a private repository through a Github App.' + operationId: 4d46c84bda4f1a411f6dda15fce4061f + requestBody: + description: 'Application object that needs to be created.' + required: true + content: + application/json: + schema: + required: + - project_uuid + - server_uuid + - environment_name + - github_app_uuid + - git_repository + - git_branch + - build_pack + - ports_exposes + properties: + project_uuid: + type: string + server_uuid: + type: string + environment_name: + type: string + github_app_uuid: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + domains: + type: string + git_repository: + type: string + git_branch: + type: string + git_commit_sha: + type: string + docker_registry_image_name: + type: string + docker_registry_image_tag: + type: string + build_pack: + type: string + enum: [nixpacks, static, dockerfile, dockercompose] + is_static: + type: boolean + install_command: + type: string + build_command: + type: string + start_command: + type: string + ports_exposes: + type: string + ports_mappings: + type: string + base_directory: + type: string + publish_directory: + type: string + health_check_enabled: + type: boolean + health_check_path: + type: string + health_check_port: + type: integer + health_check_host: + type: string + health_check_method: + type: string + health_check_return_code: + type: integer + health_check_scheme: + type: string + health_check_response_text: + type: string + health_check_interval: + type: integer + health_check_timeout: + type: integer + health_check_retries: + type: integer + health_check_start_period: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: string + custom_labels: + type: string + custom_docker_run_options: + type: string + post_deployment_command: + type: string + post_deployment_command_container: + type: string + pre_deployment_command: + type: string + pre_deployment_command_container: + type: string + manual_webhook_secret_github: + type: string + manual_webhook_secret_gitlab: + type: string + manual_webhook_secret_bitbucket: + type: string + manual_webhook_secret_gitea: + type: string + redirect: + type: string + instant_deploy: + type: boolean + dockerfile: + type: string + docker_compose_location: + type: string + docker_compose_raw: + type: string + docker_compose_custom_start_command: + type: string + docker_compose_custom_build_command: + type: string + docker_compose_domains: + type: array + watch_paths: + type: string + type: object + responses: + '200': + description: 'Application created successfully.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /applications/private-deploy-key: + post: + tags: + - Applications + summary: 'Create (Private - Deploy Key)' + description: 'Create new application based on a private repository through a Deploy Key.' + operationId: e3eaa989ffb05366247a00cdfd551efa + requestBody: + description: 'Application object that needs to be created.' + required: true + content: + application/json: + schema: + required: + - project_uuid + - server_uuid + - environment_name + - private_key_uuid + - git_repository + - git_branch + - build_pack + - ports_exposes + properties: + project_uuid: + type: string + server_uuid: + type: string + environment_name: + type: string + private_key_uuid: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + domains: + type: string + git_repository: + type: string + git_branch: + type: string + git_commit_sha: + type: string + docker_registry_image_name: + type: string + docker_registry_image_tag: + type: string + build_pack: + type: string + enum: [nixpacks, static, dockerfile, dockercompose] + is_static: + type: boolean + install_command: + type: string + build_command: + type: string + start_command: + type: string + ports_exposes: + type: string + ports_mappings: + type: string + base_directory: + type: string + publish_directory: + type: string + health_check_enabled: + type: boolean + health_check_path: + type: string + health_check_port: + type: integer + health_check_host: + type: string + health_check_method: + type: string + health_check_return_code: + type: integer + health_check_scheme: + type: string + health_check_response_text: + type: string + health_check_interval: + type: integer + health_check_timeout: + type: integer + health_check_retries: + type: integer + health_check_start_period: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: string + custom_labels: + type: string + custom_docker_run_options: + type: string + post_deployment_command: + type: string + post_deployment_command_container: + type: string + pre_deployment_command: + type: string + pre_deployment_command_container: + type: string + manual_webhook_secret_github: + type: string + manual_webhook_secret_gitlab: + type: string + manual_webhook_secret_bitbucket: + type: string + manual_webhook_secret_gitea: + type: string + redirect: + type: string + instant_deploy: + type: boolean + dockerfile: + type: string + docker_compose_location: + type: string + docker_compose_raw: + type: string + docker_compose_custom_start_command: + type: string + docker_compose_custom_build_command: + type: string + docker_compose_domains: + type: array + watch_paths: + type: string + type: object + responses: + '200': + description: 'Application created successfully.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /applications/dockerfile: + post: + tags: + - Applications + summary: 'Create (Dockerfile)' + description: 'Create new application based on a simple Dockerfile.' + operationId: 2b433ad6f5d259eb7f4f3b5af9913708 + requestBody: + description: 'Application object that needs to be created.' + required: true + content: + application/json: + schema: + required: + - project_uuid + - server_uuid + - environment_name + - dockerfile + properties: + project_uuid: + type: string + server_uuid: + type: string + environment_name: + type: string + dockerfile: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + domains: + type: string + docker_registry_image_name: + type: string + docker_registry_image_tag: + type: string + ports_exposes: + type: string + ports_mappings: + type: string + base_directory: + type: string + health_check_enabled: + type: boolean + health_check_path: + type: string + health_check_port: + type: integer + health_check_host: + type: string + health_check_method: + type: string + health_check_return_code: + type: integer + health_check_scheme: + type: string + health_check_response_text: + type: string + health_check_interval: + type: integer + health_check_timeout: + type: integer + health_check_retries: + type: integer + health_check_start_period: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: string + custom_labels: + type: string + custom_docker_run_options: + type: string + post_deployment_command: + type: string + post_deployment_command_container: + type: string + pre_deployment_command: + type: string + pre_deployment_command_container: + type: string + manual_webhook_secret_github: + type: string + manual_webhook_secret_gitlab: + type: string + manual_webhook_secret_bitbucket: + type: string + manual_webhook_secret_gitea: + type: string + redirect: + type: string + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Application created successfully.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /applications/dockerimage: + post: + tags: + - Applications + summary: 'Create (Docker Image)' + description: 'Create new application based on a prebuilt docker image' + operationId: e9a2d6dd9404acf880dc3053f09477fc + requestBody: + description: 'Application object that needs to be created.' + required: true + content: + application/json: + schema: + required: + - project_uuid + - server_uuid + - environment_name + - docker_registry_image_name + - ports_exposes + properties: + project_uuid: + type: string + server_uuid: + type: string + environment_name: + type: string + docker_registry_image_name: + type: string + docker_registry_image_tag: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + domains: + type: string + git_repository: + type: string + git_branch: + type: string + git_commit_sha: + type: string + ports_exposes: + type: string + ports_mappings: + type: string + health_check_enabled: + type: boolean + health_check_path: + type: string + health_check_port: + type: integer + health_check_host: + type: string + health_check_method: + type: string + health_check_return_code: + type: integer + health_check_scheme: + type: string + health_check_response_text: + type: string + health_check_interval: + type: integer + health_check_timeout: + type: integer + health_check_retries: + type: integer + health_check_start_period: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: string + custom_labels: + type: string + custom_docker_run_options: + type: string + post_deployment_command: + type: string + post_deployment_command_container: + type: string + pre_deployment_command: + type: string + pre_deployment_command_container: + type: string + manual_webhook_secret_github: + type: string + manual_webhook_secret_gitlab: + type: string + manual_webhook_secret_bitbucket: + type: string + manual_webhook_secret_gitea: + type: string + redirect: + type: string + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Application created successfully.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /applications/dockercompose: + post: + tags: + - Applications + summary: 'Create (Docker Compose)' + description: 'Create new application based on a docker-compose file.' + operationId: 3731add8226c2d664455978cac46c242 + requestBody: + description: 'Application object that needs to be created.' + required: true + content: + application/json: + schema: + required: + - project_uuid + - server_uuid + - environment_name + - docker_compose_raw + properties: + project_uuid: + type: string + server_uuid: + type: string + environment_name: + type: string + docker_compose_raw: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Application created successfully.' '401': $ref: '#/components/responses/401' '400': @@ -205,7 +941,7 @@ paths: format: uuid responses: '200': - description: 'Get all applications.' + description: 'Get application by UUID.' content: application/json: schema: @@ -219,6 +955,1248 @@ paths: security: - bearerAuth: [] + delete: + tags: + - Applications + summary: Delete + description: 'Delete application by UUID.' + operationId: 1e110b190a1045d34f3e1c61608a8702 + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Application deleted.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Application deleted.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/applications/{uuid}/envs': + get: + tags: + - Applications + summary: 'List Envs' + description: 'List all envs by application UUID.' + operationId: 7c8e0c286870e23294a075cc0584df2f + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'All environment variables by application UUID.' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/EnvironmentVariable' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + post: + tags: + - Applications + summary: 'Create Env' + description: 'Create env by application UUID.' + operationId: 4699ffbb7d6e58581fd0b0a14f36ffc2 + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + requestBody: + description: 'Env created.' + required: true + content: + application/json: + schema: + properties: + key: + type: string + value: + type: string + is_preview: + type: boolean + is_build_time: + type: boolean + is_literal: + type: boolean + is_multiline: + type: boolean + is_shown_once: + type: boolean + type: object + responses: + '201': + description: 'Environment variable created.' + content: + application/json: + schema: + properties: + uuid: { type: string, example: nc0k04gk8g0cgsk440g0koko } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + patch: + tags: + - Applications + summary: 'Update Env' + description: 'Update env by application UUID.' + operationId: 3d70a2d569f395be220b3f09ad36674b + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + requestBody: + description: 'Env updated.' + required: true + content: + application/json: + schema: + required: + - key + - value + properties: + key: + type: string + value: + type: string + is_preview: + type: boolean + is_build_time: + type: boolean + is_literal: + type: boolean + is_multiline: + type: boolean + is_shown_once: + type: boolean + type: object + responses: + '201': + description: 'Environment variable updated.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Environment variable updated.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/applications/{uuid}/envs/bulk': + patch: + tags: + - Applications + summary: 'Update Envs (Bulk)' + description: 'Update multiple envs by application UUID.' + operationId: ae96f0f585ed158b2abd2d9ba40f3cf9 + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + requestBody: + description: 'Bulk envs updated.' + required: true + content: + application/json: + schema: + required: + - data + properties: + data: + type: array + items: { properties: { key: { type: string }, value: { type: string }, is_preview: { type: boolean }, is_build_time: { type: boolean }, is_literal: { type: boolean }, is_multiline: { type: boolean }, is_shown_once: { type: boolean } }, type: object } + type: object + responses: + '201': + description: 'Environment variables updated.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Environment variables updated.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/applications/{uuid}/envs/{env_uuid}': + delete: + tags: + - Applications + summary: 'Delete Env' + description: 'Delete env by UUID.' + operationId: 96097c5cfc7dc0e7a3de229645f630c7 + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + - + name: env_uuid + in: path + description: 'UUID of the environment variable.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Environment variable deleted.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Environment variable deleted.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/applications/{uuid}/start': + get: + tags: + - Applications + summary: Start + description: 'Start application. `Post` request is also accepted.' + operationId: dc87c2061ab303757a0e061f87900c4c + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + - + name: force + in: query + description: 'Force rebuild.' + schema: + type: boolean + default: false + - + name: instant_deploy + in: query + description: 'Instant deploy (skip queuing).' + schema: + type: boolean + default: false + responses: + '200': + description: 'Start application.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Deployment request queued.' } + deployment_uuid: { type: string, example: doogksw } + deployment_api_url: { type: string } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/applications/{uuid}/stop': + get: + tags: + - Applications + summary: Stop + description: 'Stop application. `Post` request is also accepted.' + operationId: 133ef3c7bd5043901f24bb5002a536eb + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Stop application.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Application stopping request queued.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/applications/{uuid}/restart': + get: + tags: + - Applications + summary: Restart + description: 'Restart application. `Post` request is also accepted.' + operationId: b231ae7baab9ef47f0627be820e735bc + parameters: + - + name: uuid + in: path + description: 'UUID of the application.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Restart application.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Restart request queued.' } + deployment_uuid: { type: string, example: doogksw } + deployment_api_url: { type: string } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + /databases: + get: + tags: + - Databases + summary: List + description: 'List all databases.' + operationId: ecd0ee1e46e4c854c18e6c9daa3d37f3 + responses: + '200': + description: 'Get all databases' + content: + application/json: + schema: + type: string + example: 'Content is very complex. Will be implemented later.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + '/databases/{uuid}': + get: + tags: + - Databases + summary: Get + description: 'Get database by UUID.' + operationId: b49cb2d3e8f34c4e80cdffd8a201031d + parameters: + - + name: uuid + in: path + description: 'UUID of the database.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Get all databases' + content: + application/json: + schema: + type: string + example: 'Content is very complex. Will be implemented later.' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + delete: + tags: + - Databases + summary: Delete + description: 'Delete database by UUID.' + operationId: 20610931b2bae8aba34eee68624ab673 + parameters: + - + name: uuid + in: path + description: 'UUID of the database.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Database deleted.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Database deleted.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + patch: + tags: + - Databases + summary: Update + description: 'Update database by UUID.' + operationId: 5ba459ed390a721711a1708760e9de3b + parameters: + - + name: uuid + in: path + description: 'UUID of the database.' + required: true + schema: + type: string + format: uuid + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + properties: + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + postgres_user: + type: string + postgres_password: + type: string + postgres_db: + type: string + postgres_initdb_args: + type: string + postgres_host_auth_method: + type: string + postgres_conf: + type: string + clickhouse_admin_user: + type: string + clickhouse_admin_password: + type: string + dragonfly_password: + type: string + redis_password: + type: string + redis_conf: + type: string + keydb_password: + type: string + keydb_conf: + type: string + mariadb_conf: + type: string + mariadb_root_password: + type: string + mariadb_user: + type: string + mariadb_password: + type: string + mariadb_database: + type: string + mongo_conf: + type: string + mongo_initdb_root_username: + type: string + mongo_initdb_root_password: + type: string + mongo_initdb_init_database: + type: string + mysql_root_password: + type: string + mysql_user: + type: string + mysql_database: + type: string + mysql_conf: + type: string + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + /databases/postgresql: + post: + tags: + - Databases + summary: 'Create (PostgreSQL)' + description: 'Create a new PostgreSQL database.' + operationId: 8f7f491ddc46a9fa065b4424512231cd + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + postgres_user: + type: string + postgres_password: + type: string + postgres_db: + type: string + postgres_initdb_args: + type: string + postgres_host_auth_method: + type: string + postgres_conf: + type: string + destination_uuid: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/clickhouse: + post: + tags: + - Databases + summary: 'Create (Clickhouse)' + description: 'Create a new Clickhouse database.' + operationId: a1189fa7f956f238f0e95c9150ff57f6 + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + clickhouse_admin_user: + type: string + clickhouse_admin_password: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/dragonfly: + post: + tags: + - Databases + summary: 'Create (DragonFly)' + description: 'Create a new DragonFly database.' + operationId: e73f7de1c8eee4219e5ec98c4b9b7efe + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + dragonfly_password: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/redis: + post: + tags: + - Databases + summary: 'Create (Redis)' + description: 'Create a new Redis database.' + operationId: 4d352d13544ee2953fd48ad7b0651098 + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + redis_password: + type: string + redis_conf: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/keydb: + post: + tags: + - Databases + summary: 'Create (KeyDB)' + description: 'Create a new KeyDB database.' + operationId: b908f3929c371c217d489638e0a21ff6 + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + keydb_password: + type: string + keydb_conf: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/mariadb: + post: + tags: + - Databases + summary: 'Create (MariaDB)' + description: 'Create a new MariaDB database.' + operationId: 6bea521ddcd738dcbb5f3783a7308acf + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + mariadb_conf: + type: string + mariadb_root_password: + type: string + mariadb_user: + type: string + mariadb_password: + type: string + mariadb_database: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/mysql: + post: + tags: + - Databases + summary: 'Create (MySQL)' + description: 'Create a new MySQL database.' + operationId: 0a1158cf759c4493cbb1e30024c60623 + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + mysql_root_password: + type: string + mysql_user: + type: string + mysql_database: + type: string + mysql_conf: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + /databases/mongodb: + post: + tags: + - Databases + summary: 'Create (MongoDB)' + description: 'Create a new MongoDB database.' + operationId: fdba3de84d02519bb37599fea34b115d + requestBody: + description: 'Database data' + required: true + content: + application/json: + schema: + required: + - server_uuid + - project_uuid + - environment_name + properties: + server_uuid: + type: string + project_uuid: + type: string + environment_name: + type: string + destination_uuid: + type: string + mongo_conf: + type: string + mongo_initdb_root_username: + type: string + name: + type: string + description: + type: string + image: + type: string + is_public: + type: boolean + public_port: + type: integer + limits_memory: + type: string + limits_memory_swap: + type: string + limits_memory_swappiness: + type: integer + limits_memory_reservation: + type: string + limits_cpus: + type: string + limits_cpuset: + type: string + limits_cpu_shares: + type: integer + instant_deploy: + type: boolean + type: object + responses: + '200': + description: 'Database updated' + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + security: + - + bearerAuth: [] + '/databases/{uuid}/start': + get: + tags: + - Databases + summary: Start + description: 'Start database. `Post` request is also accepted.' + operationId: 4c6eb21e734d411e2b3388578761123d + parameters: + - + name: uuid + in: path + description: 'UUID of the database.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Start database.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Database starting request queued.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/databases/{uuid}/stop': + get: + tags: + - Databases + summary: Stop + description: 'Stop database. `Post` request is also accepted.' + operationId: cb6d983c2679aff841c7501ce612a372 + parameters: + - + name: uuid + in: path + description: 'UUID of the database.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Stop database.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Database stopping request queued.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] + '/databases/{uuid}/restart': + get: + tags: + - Databases + summary: Restart + description: 'Restart database. `Post` request is also accepted.' + operationId: 04c7a5e4752b4a00036addb433f3f218 + parameters: + - + name: uuid + in: path + description: 'UUID of the database.' + required: true + schema: + type: string + format: uuid + responses: + '200': + description: 'Restart database.' + content: + application/json: + schema: + properties: + message: { type: string, example: 'Database restaring request queued.' } + type: object + '401': + $ref: '#/components/responses/401' + '400': + $ref: '#/components/responses/400' + '404': + $ref: '#/components/responses/404' + security: + - + bearerAuth: [] /deployments: get: tags: @@ -1193,6 +3171,44 @@ components: description: type: string type: object + EnvironmentVariable: + description: 'Environment Variable model' + properties: + id: + type: integer + uuid: + type: string + application_id: + type: integer + service_id: + type: integer + database_id: + type: integer + is_build_time: + type: boolean + is_literal: + type: boolean + is_multiline: + type: boolean + is_preview: + type: boolean + is_shared: + type: boolean + is_shown_once: + type: boolean + key: + type: string + value: + type: string + real_value: + type: string + version: + type: string + created_at: + type: string + updated_at: + type: string + type: object PrivateKey: description: 'Private Key model' properties: @@ -1696,6 +3712,9 @@ tags: - name: Applications description: Applications + - + name: Databases + description: Databases - name: Deployments description: Deployments diff --git a/routes/api.php b/routes/api.php index ecf797017..854928730 100644 --- a/routes/api.php +++ b/routes/api.php @@ -73,7 +73,7 @@ Route::get('/applications/{uuid}/envs', [ApplicationsController::class, 'envs']); Route::post('/applications/{uuid}/envs', [ApplicationsController::class, 'create_env'])->middleware([IgnoreReadOnlyApiToken::class]); - Route::post('/applications/{uuid}/envs/bulk', [ApplicationsController::class, 'create_bulk_envs'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::patch('/applications/{uuid}/envs/bulk', [ApplicationsController::class, 'create_bulk_envs'])->middleware([IgnoreReadOnlyApiToken::class]); Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid']); Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]); @@ -82,7 +82,14 @@ Route::match(['get', 'post'], '/applications/{uuid}/stop', [ApplicationsController::class, 'action_stop'])->middleware([IgnoreReadOnlyApiToken::class]); Route::get('/databases', [DatabasesController::class, 'databases']); - Route::post('/databases', [DatabasesController::class, 'create_database'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/postgresql', [DatabasesController::class, 'create_database_postgresql'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/mysql', [DatabasesController::class, 'create_database_mysql'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/mariadb', [DatabasesController::class, 'create_database_mariadb'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/mongodb', [DatabasesController::class, 'create_database_mongodb'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/redis', [DatabasesController::class, 'create_database_redis'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/clickhouse', [DatabasesController::class, 'create_database_clickhouse'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/dragonfly', [DatabasesController::class, 'create_database_dragonfly'])->middleware([IgnoreReadOnlyApiToken::class]); + Route::post('/databases/keydb', [DatabasesController::class, 'create_database_keydb'])->middleware([IgnoreReadOnlyApiToken::class]); Route::get('/databases/{uuid}', [DatabasesController::class, 'database_by_uuid']); Route::patch('/databases/{uuid}', [DatabasesController::class, 'update_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);