openapi services

This commit is contained in:
Andras Bacsai 2024-07-09 13:30:13 +02:00
parent c72fd2fc9d
commit 6c33bd9c72
4 changed files with 716 additions and 0 deletions

View File

@ -12,6 +12,7 @@
use App\Models\Server; use App\Models\Server;
use App\Models\Service; use App\Models\Service;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use OpenApi\Attributes as OA;
class ServicesController extends Controller class ServicesController extends Controller
{ {
@ -33,6 +34,38 @@ private function removeSensitiveData($service)
return serializeApiResponse($service); return serializeApiResponse($service);
} }
#[OA\Get(
summary: 'List',
description: 'List all services.',
path: '/services',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
responses: [
new OA\Response(
response: 200,
description: 'Get all services',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'array',
items: new OA\Items(ref: '#/components/schemas/Service')
)
),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
),
new OA\Response(
response: 400,
ref: '#/components/responses/400',
),
]
)]
public function services(Request $request) public function services(Request $request)
{ {
$teamId = getTeamIdFromToken(); $teamId = getTeamIdFromToken();
@ -51,6 +84,154 @@ public function services(Request $request)
return response()->json($services->flatten()); return response()->json($services->flatten());
} }
#[OA\Post(
summary: 'Create',
description: 'Create a one-click service',
path: '/services',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
requestBody: new OA\RequestBody(
required: true,
content: new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
required: ['server_uuid', 'project_uuid', 'environment_name', 'type'],
properties: [
'type' => ['type' => 'string',
'enum' => [
'activepieces',
'appsmith',
'appwrite',
'authentik',
'babybuddy',
'budge',
'changedetection',
'chatwoot',
'classicpress-with-mariadb',
'classicpress-with-mysql',
'classicpress-without-database',
'cloudflared',
'code-server',
'dashboard',
'directus',
'directus-with-postgresql',
'docker-registry',
'docuseal',
'docuseal-with-postgres',
'dokuwiki',
'duplicati',
'emby',
'embystat',
'fider',
'filebrowser',
'firefly',
'formbricks',
'ghost',
'gitea',
'gitea-with-mariadb',
'gitea-with-mysql',
'gitea-with-postgresql',
'glance',
'glances',
'glitchtip',
'grafana',
'grafana-with-postgresql',
'grocy',
'heimdall',
'homepage',
'jellyfin',
'kuzzle',
'listmonk',
'logto',
'mediawiki',
'meilisearch',
'metabase',
'metube',
'minio',
'moodle',
'n8n',
'n8n-with-postgresql',
'next-image-transformation',
'nextcloud',
'nocodb',
'odoo',
'openblocks',
'pairdrop',
'penpot',
'phpmyadmin',
'pocketbase',
'posthog',
'reactive-resume',
'rocketchat',
'shlink',
'slash',
'snapdrop',
'statusnook',
'stirling-pdf',
'supabase',
'syncthing',
'tolgee',
'trigger',
'trigger-with-external-database',
'twenty',
'umami',
'unleash-with-postgresql',
'unleash-without-database',
'uptime-kuma',
'vaultwarden',
'vikunja',
'weblate',
'whoogle',
'wordpress-with-mariadb',
'wordpress-with-mysql',
'wordpress-without-database',
],
],
'server_uuid' => ['type' => 'string'],
'project_uuid' => ['type' => 'string'],
'environment_name' => ['type' => 'string'],
'destination_uuid' => ['type' => 'string'],
'name' => ['type' => 'string'],
'description' => ['type' => 'string'],
'project_uuid' => ['type' => 'string'],
'environment_name' => ['type' => 'string'],
'server_uuid' => ['type' => 'string'],
'destination_uuid' => ['type' => 'string'],
'instant_deploy' => ['type' => 'boolean'],
],
),
),
),
responses: [
new OA\Response(
response: 201,
description: 'Create a service.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'uuid' => ['type' => 'string'],
'domains' => ['type' => 'array', 'items' => ['type' => 'string']],
]
)
),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
),
new OA\Response(
response: 400,
ref: '#/components/responses/400',
),
]
)]
public function create_service(Request $request) public function create_service(Request $request)
{ {
$allowedFields = ['type', 'name', 'description', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy']; $allowedFields = ['type', 'name', 'description', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy'];
@ -182,6 +363,44 @@ public function create_service(Request $request)
return response()->json(['message' => 'Invalid service type.'], 400); return response()->json(['message' => 'Invalid service type.'], 400);
} }
#[OA\Get(
summary: 'Get',
description: 'Get service by UUID.',
path: '/services/{uuid}',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
parameters: [
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Service UUID', schema: new OA\Schema(type: 'string')),
],
responses: [
new OA\Response(
response: 200,
description: 'Get a service by Uuid.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
ref: '#/components/schemas/Service'
)
),
]
),
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 service_by_uuid(Request $request) public function service_by_uuid(Request $request)
{ {
$teamId = getTeamIdFromToken(); $teamId = getTeamIdFromToken();
@ -199,6 +418,47 @@ public function service_by_uuid(Request $request)
return response()->json($this->removeSensitiveData($service)); return response()->json($this->removeSensitiveData($service));
} }
#[OA\Delete(
summary: 'Delete',
description: 'Delete service by UUID.',
path: '/services/{uuid}',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
parameters: [
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Service UUID', schema: new OA\Schema(type: 'string')),
],
responses: [
new OA\Response(
response: 200,
description: 'Delete a service by Uuid',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'message' => ['type' => 'string', 'example' => 'Service deletion 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 delete_by_uuid(Request $request) public function delete_by_uuid(Request $request)
{ {
$teamId = getTeamIdFromToken(); $teamId = getTeamIdFromToken();
@ -219,6 +479,54 @@ public function delete_by_uuid(Request $request)
]); ]);
} }
#[OA\Get(
summary: 'Start',
description: 'Start service. `Post` request is also accepted.',
path: '/services/{uuid}/start',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
parameters: [
new OA\Parameter(
name: 'uuid',
in: 'path',
description: 'UUID of the service.',
required: true,
schema: new OA\Schema(
type: 'string',
format: 'uuid',
)
),
],
responses: [
new OA\Response(
response: 200,
description: 'Start service.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'message' => ['type' => 'string', 'example' => 'Service 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) public function action_deploy(Request $request)
{ {
$teamId = getTeamIdFromToken(); $teamId = getTeamIdFromToken();
@ -246,6 +554,54 @@ public function action_deploy(Request $request)
); );
} }
#[OA\Get(
summary: 'Stop',
description: 'Stop service. `Post` request is also accepted.',
path: '/services/{uuid}/stop',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
parameters: [
new OA\Parameter(
name: 'uuid',
in: 'path',
description: 'UUID of the service.',
required: true,
schema: new OA\Schema(
type: 'string',
format: 'uuid',
)
),
],
responses: [
new OA\Response(
response: 200,
description: 'Stop service.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'message' => ['type' => 'string', 'example' => 'Service 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) public function action_stop(Request $request)
{ {
$teamId = getTeamIdFromToken(); $teamId = getTeamIdFromToken();
@ -273,6 +629,54 @@ public function action_stop(Request $request)
); );
} }
#[OA\Get(
summary: 'Restart',
description: 'Restart service. `Post` request is also accepted.',
path: '/services/{uuid}/restart',
security: [
['bearerAuth' => []],
],
tags: ['Services'],
parameters: [
new OA\Parameter(
name: 'uuid',
in: 'path',
description: 'UUID of the service.',
required: true,
schema: new OA\Schema(
type: 'string',
format: 'uuid',
)
),
],
responses: [
new OA\Response(
response: 200,
description: 'Restart service.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'message' => ['type' => 'string', 'example' => 'Service 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) public function action_restart(Request $request)
{ {
$teamId = getTeamIdFromToken(); $teamId = getTeamIdFromToken();

View File

@ -6,8 +6,32 @@
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use OpenApi\Attributes as OA;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
#[OA\Schema(
description: 'Service model',
type: 'object',
properties: [
'id' => ['type' => 'integer'],
'uuid' => ['type' => 'string'],
'name' => ['type' => 'string'],
'environment_id' => ['type' => 'integer'],
'created_at' => ['type' => 'string'],
'updated_at' => ['type' => 'string'],
'server_id' => ['type' => 'integer'],
'description' => ['type' => 'string'],
'docker_compose_raw' => ['type' => 'string'],
'docker_compose' => ['type' => 'string'],
'destination_type' => ['type' => 'string'],
'destination_id' => ['type' => 'integer'],
'deleted_at' => ['type' => 'string'],
'connect_to_docker_network' => ['type' => 'boolean'],
'config_hash' => ['type' => 'string'],
'service_type' => ['type' => 'string'],
'is_container_label_escape_enabled' => ['type' => 'boolean'],
],
)]
class Service extends BaseModel class Service extends BaseModel
{ {
use HasFactory, SoftDeletes; use HasFactory, SoftDeletes;

View File

@ -199,3 +199,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
return handleError($e); return handleError($e);
} }
} }
function serviceKeys()
{
$services = get_service_templates();
$serviceKeys = $services->keys();
return $serviceKeys;
}

View File

@ -2784,6 +2784,246 @@ paths:
security: security:
- -
bearerAuth: [] bearerAuth: []
/services:
get:
tags:
- Services
summary: List
description: 'List all services.'
operationId: 5d014ac25d33391b8f4c2316060ba452
responses:
'200':
description: 'Get all services'
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Service'
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
security:
-
bearerAuth: []
post:
tags:
- Services
summary: Create
description: 'Create a one-click service'
operationId: 3d6cbfb54d919b53ba3984a113e837d7
requestBody:
required: true
content:
application/json:
schema:
required:
- server_uuid
- project_uuid
- environment_name
- type
properties:
type:
type: string
enum: [activepieces, appsmith, appwrite, authentik, babybuddy, budge, changedetection, chatwoot, classicpress-with-mariadb, classicpress-with-mysql, classicpress-without-database, cloudflared, code-server, dashboard, directus, directus-with-postgresql, docker-registry, docuseal, docuseal-with-postgres, dokuwiki, duplicati, emby, embystat, fider, filebrowser, firefly, formbricks, ghost, gitea, gitea-with-mariadb, gitea-with-mysql, gitea-with-postgresql, glance, glances, glitchtip, grafana, grafana-with-postgresql, grocy, heimdall, homepage, jellyfin, kuzzle, listmonk, logto, mediawiki, meilisearch, metabase, metube, minio, moodle, n8n, n8n-with-postgresql, next-image-transformation, nextcloud, nocodb, odoo, openblocks, pairdrop, penpot, phpmyadmin, pocketbase, posthog, reactive-resume, rocketchat, shlink, slash, snapdrop, statusnook, stirling-pdf, supabase, syncthing, tolgee, trigger, trigger-with-external-database, twenty, umami, unleash-with-postgresql, unleash-without-database, uptime-kuma, vaultwarden, vikunja, weblate, whoogle, wordpress-with-mariadb, wordpress-with-mysql, wordpress-without-database]
server_uuid:
type: string
project_uuid:
type: string
environment_name:
type: string
destination_uuid:
type: string
name:
type: string
description:
type: string
instant_deploy:
type: boolean
type: object
responses:
'201':
description: 'Create a service.'
content:
application/json:
schema:
properties:
uuid: { type: string }
domains: { type: array, items: { type: string } }
type: object
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
security:
-
bearerAuth: []
'/services/{uuid}':
get:
tags:
- Services
summary: Get
description: 'Get service by UUID.'
operationId: 895d39ee2cb3994285de57256c2d428d
parameters:
-
name: uuid
in: path
description: 'Service UUID'
required: true
schema:
type: string
responses:
'200':
description: 'Get a service by Uuid.'
content:
application/json:
schema:
$ref: '#/components/schemas/Service'
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
security:
-
bearerAuth: []
delete:
tags:
- Services
summary: Delete
description: 'Delete service by UUID.'
operationId: 6e1a61e4fddaa9d95bb9fc66dfaf0442
parameters:
-
name: uuid
in: path
description: 'Service UUID'
required: true
schema:
type: string
responses:
'200':
description: 'Delete a service by Uuid'
content:
application/json:
schema:
properties:
message: { type: string, example: 'Service deletion request queued.' }
type: object
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
security:
-
bearerAuth: []
'/services/{uuid}/start':
get:
tags:
- Services
summary: Start
description: 'Start service. `Post` request is also accepted.'
operationId: d2ddd9c028d123fbdec830dc4b25b4cb
parameters:
-
name: uuid
in: path
description: 'UUID of the service.'
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 'Start service.'
content:
application/json:
schema:
properties:
message: { type: string, example: 'Service starting request queued.' }
type: object
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
security:
-
bearerAuth: []
'/services/{uuid}/stop':
get:
tags:
- Services
summary: Stop
description: 'Stop service. `Post` request is also accepted.'
operationId: 87399d34758ce16830740c68626614db
parameters:
-
name: uuid
in: path
description: 'UUID of the service.'
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 'Stop service.'
content:
application/json:
schema:
properties:
message: { type: string, example: 'Service stopping request queued.' }
type: object
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
security:
-
bearerAuth: []
'/services/{uuid}/restart':
get:
tags:
- Services
summary: Restart
description: 'Restart service. `Post` request is also accepted.'
operationId: 836645faa615b75052759dae78639469
parameters:
-
name: uuid
in: path
description: 'UUID of the service.'
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 'Restart service.'
content:
application/json:
schema:
properties:
message: { type: string, example: 'Service restaring request queued.' }
type: object
'401':
$ref: '#/components/responses/401'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
security:
-
bearerAuth: []
/teams: /teams:
get: get:
tags: tags:
@ -3503,6 +3743,44 @@ components:
updated_at: updated_at:
type: string type: string
type: object type: object
Service:
description: 'Service model'
properties:
id:
type: integer
uuid:
type: string
name:
type: string
environment_id:
type: integer
created_at:
type: string
updated_at:
type: string
server_id:
type: integer
description:
type: string
docker_compose_raw:
type: string
docker_compose:
type: string
destination_type:
type: string
destination_id:
type: integer
deleted_at:
type: string
connect_to_docker_network:
type: boolean
config_hash:
type: string
service_type:
type: string
is_container_label_escape_enabled:
type: boolean
type: object
Team: Team:
description: 'Team model' description: 'Team model'
properties: properties:
@ -3730,6 +4008,9 @@ tags:
- -
name: Servers name: Servers
description: Servers description: Servers
-
name: Services
description: Services
- -
name: Teams name: Teams
description: Teams description: Teams