feat(domains): add force_domain_override option and enhance domain conflict detection responses
This commit is contained in:
@@ -190,6 +190,7 @@ class ApplicationsController extends Controller
|
|||||||
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
||||||
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -217,6 +218,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 400,
|
response: 400,
|
||||||
ref: '#/components/responses/400',
|
ref: '#/components/responses/400',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function create_public_application(Request $request)
|
public function create_public_application(Request $request)
|
||||||
@@ -310,6 +340,7 @@ class ApplicationsController extends Controller
|
|||||||
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
||||||
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -337,6 +368,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 400,
|
response: 400,
|
||||||
ref: '#/components/responses/400',
|
ref: '#/components/responses/400',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function create_private_gh_app_application(Request $request)
|
public function create_private_gh_app_application(Request $request)
|
||||||
@@ -430,6 +490,7 @@ class ApplicationsController extends Controller
|
|||||||
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
||||||
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -457,6 +518,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 400,
|
response: 400,
|
||||||
ref: '#/components/responses/400',
|
ref: '#/components/responses/400',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function create_private_deploy_key_application(Request $request)
|
public function create_private_deploy_key_application(Request $request)
|
||||||
@@ -534,6 +624,7 @@ class ApplicationsController extends Controller
|
|||||||
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
||||||
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -561,6 +652,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 400,
|
response: 400,
|
||||||
ref: '#/components/responses/400',
|
ref: '#/components/responses/400',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function create_dockerfile_application(Request $request)
|
public function create_dockerfile_application(Request $request)
|
||||||
@@ -635,6 +755,7 @@ class ApplicationsController extends Controller
|
|||||||
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
'http_basic_auth_username' => ['type' => 'string', 'nullable' => true, 'description' => 'Username for HTTP Basic Authentication'],
|
||||||
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
'http_basic_auth_password' => ['type' => 'string', 'nullable' => true, 'description' => 'Password for HTTP Basic Authentication'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -662,6 +783,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 400,
|
response: 400,
|
||||||
ref: '#/components/responses/400',
|
ref: '#/components/responses/400',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function create_dockerimage_application(Request $request)
|
public function create_dockerimage_application(Request $request)
|
||||||
@@ -699,6 +849,7 @@ class ApplicationsController extends Controller
|
|||||||
'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'],
|
'instant_deploy' => ['type' => 'boolean', 'description' => 'The flag to indicate if the application should be deployed instantly.'],
|
||||||
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
|
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -726,6 +877,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 400,
|
response: 400,
|
||||||
ref: '#/components/responses/400',
|
ref: '#/components/responses/400',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function create_dockercompose_application(Request $request)
|
public function create_dockercompose_application(Request $request)
|
||||||
@@ -746,7 +926,7 @@ class ApplicationsController extends Controller
|
|||||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
$allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', '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', 'use_build_server', 'static_image', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network'];
|
$allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'private_key_uuid', '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', 'use_build_server', 'static_image', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network', 'force_domain_override'];
|
||||||
|
|
||||||
$validator = customApiValidator($request->all(), [
|
$validator = customApiValidator($request->all(), [
|
||||||
'name' => 'string|max:255',
|
'name' => 'string|max:255',
|
||||||
@@ -1380,7 +1560,7 @@ class ApplicationsController extends Controller
|
|||||||
'domains' => data_get($application, 'domains'),
|
'domains' => data_get($application, 'domains'),
|
||||||
]))->setStatusCode(201);
|
]))->setStatusCode(201);
|
||||||
} elseif ($type === 'dockercompose') {
|
} elseif ($type === 'dockercompose') {
|
||||||
$allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'instant_deploy', 'docker_compose_raw'];
|
$allowedFields = ['project_uuid', 'environment_name', 'environment_uuid', 'server_uuid', 'destination_uuid', 'type', 'name', 'description', 'instant_deploy', 'docker_compose_raw', 'force_domain_override'];
|
||||||
|
|
||||||
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
|
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
|
||||||
if ($validator->fails() || ! empty($extraFields)) {
|
if ($validator->fails() || ! empty($extraFields)) {
|
||||||
@@ -1810,6 +1990,7 @@ class ApplicationsController extends Controller
|
|||||||
'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'],
|
'watch_paths' => ['type' => 'string', 'description' => 'The watch paths.'],
|
||||||
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
|
'use_build_server' => ['type' => 'boolean', 'nullable' => true, 'description' => 'Use build server.'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
|
'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -1843,6 +2024,35 @@ class ApplicationsController extends Controller
|
|||||||
response: 404,
|
response: 404,
|
||||||
ref: '#/components/responses/404',
|
ref: '#/components/responses/404',
|
||||||
),
|
),
|
||||||
|
new OA\Response(
|
||||||
|
response: 409,
|
||||||
|
description: 'Domain conflicts detected.',
|
||||||
|
content: [
|
||||||
|
new OA\MediaType(
|
||||||
|
mediaType: 'application/json',
|
||||||
|
schema: new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain conflicts detected. Use force_domain_override=true to proceed.'],
|
||||||
|
'warning' => ['type' => 'string', 'example' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.'],
|
||||||
|
'conflicts' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => new OA\Schema(
|
||||||
|
type: 'object',
|
||||||
|
properties: [
|
||||||
|
'domain' => ['type' => 'string', 'example' => 'example.com'],
|
||||||
|
'resource_name' => ['type' => 'string', 'example' => 'My Application'],
|
||||||
|
'resource_uuid' => ['type' => 'string', 'nullable' => true, 'example' => 'abc123-def456'],
|
||||||
|
'resource_type' => ['type' => 'string', 'enum' => ['application', 'service', 'instance'], 'example' => 'application'],
|
||||||
|
'message' => ['type' => 'string', 'example' => 'Domain example.com is already in use by application \'My Application\''],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
public function update_by_uuid(Request $request)
|
public function update_by_uuid(Request $request)
|
||||||
@@ -1866,7 +2076,7 @@ class ApplicationsController extends Controller
|
|||||||
$this->authorize('update', $application);
|
$this->authorize('update', $application);
|
||||||
|
|
||||||
$server = $application->destination->server;
|
$server = $application->destination->server;
|
||||||
$allowedFields = ['name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', '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', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network'];
|
$allowedFields = ['name', 'description', 'is_static', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', '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', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'docker_compose_location', 'docker_compose_raw', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network', 'force_domain_override'];
|
||||||
|
|
||||||
$validationRules = [
|
$validationRules = [
|
||||||
'name' => 'string|max:255',
|
'name' => 'string|max:255',
|
||||||
@@ -1982,14 +2192,23 @@ class ApplicationsController extends Controller
|
|||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
if (checkIfDomainIsAlreadyUsed($fqdn, $teamId, $uuid)) {
|
// Check for domain conflicts
|
||||||
|
$result = checkIfDomainIsAlreadyUsedViaAPI($fqdn, $teamId, $uuid);
|
||||||
|
if (isset($result['error'])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Validation failed.',
|
'message' => 'Validation failed.',
|
||||||
'errors' => [
|
'errors' => ['domains' => $result['error']],
|
||||||
'domains' => 'One of the domain is already used.',
|
|
||||||
],
|
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are conflicts and force is not enabled, return warning
|
||||||
|
if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.',
|
||||||
|
'conflicts' => $result['conflicts'],
|
||||||
|
'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.',
|
||||||
|
], 409);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$dockerComposeDomainsJson = collect();
|
$dockerComposeDomainsJson = collect();
|
||||||
@@ -3102,131 +3321,6 @@ class ApplicationsController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[OA\Post(
|
|
||||||
// summary: 'Execute Command',
|
|
||||||
// description: "Execute a command on the application's current container.",
|
|
||||||
// path: '/applications/{uuid}/execute',
|
|
||||||
// operationId: 'execute-command-application',
|
|
||||||
// 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: 'Command to execute.',
|
|
||||||
// content: new OA\MediaType(
|
|
||||||
// mediaType: 'application/json',
|
|
||||||
// schema: new OA\Schema(
|
|
||||||
// type: 'object',
|
|
||||||
// properties: [
|
|
||||||
// 'command' => ['type' => 'string', 'description' => 'Command to execute.'],
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// responses: [
|
|
||||||
// new OA\Response(
|
|
||||||
// response: 200,
|
|
||||||
// description: "Execute a command on the application's current container.",
|
|
||||||
// content: [
|
|
||||||
// new OA\MediaType(
|
|
||||||
// mediaType: 'application/json',
|
|
||||||
// schema: new OA\Schema(
|
|
||||||
// type: 'object',
|
|
||||||
// properties: [
|
|
||||||
// 'message' => ['type' => 'string', 'example' => 'Command executed.'],
|
|
||||||
// 'response' => ['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 execute_command_by_uuid(Request $request)
|
|
||||||
// {
|
|
||||||
// // TODO: Need to review this from security perspective, to not allow arbitrary command execution
|
|
||||||
// $allowedFields = ['command'];
|
|
||||||
// $teamId = getTeamIdFromToken();
|
|
||||||
// if (is_null($teamId)) {
|
|
||||||
// return invalidTokenResponse();
|
|
||||||
// }
|
|
||||||
// $uuid = $request->route('uuid');
|
|
||||||
// if (! $uuid) {
|
|
||||||
// return response()->json(['message' => 'UUID is required.'], 400);
|
|
||||||
// }
|
|
||||||
// $application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
|
|
||||||
// if (! $application) {
|
|
||||||
// return response()->json(['message' => 'Application not found.'], 404);
|
|
||||||
// }
|
|
||||||
// $return = validateIncomingRequest($request);
|
|
||||||
// if ($return instanceof \Illuminate\Http\JsonResponse) {
|
|
||||||
// return $return;
|
|
||||||
// }
|
|
||||||
// $validator = customApiValidator($request->all(), [
|
|
||||||
// 'command' => 'string|required',
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// $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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $container = getCurrentApplicationContainerStatus($application->destination->server, $application->id)->firstOrFail();
|
|
||||||
// $status = getContainerStatus($application->destination->server, $container['Names']);
|
|
||||||
|
|
||||||
// if ($status !== 'running') {
|
|
||||||
// return response()->json([
|
|
||||||
// 'message' => 'Application is not running.',
|
|
||||||
// ], 400);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $commands = collect([
|
|
||||||
// executeInDocker($container['Names'], $request->command),
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// $res = instant_remote_process(command: $commands, server: $application->destination->server);
|
|
||||||
|
|
||||||
// return response()->json([
|
|
||||||
// 'message' => 'Command executed.',
|
|
||||||
// 'response' => $res,
|
|
||||||
// ]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private function validateDataApplications(Request $request, Server $server)
|
private function validateDataApplications(Request $request, Server $server)
|
||||||
{
|
{
|
||||||
$teamId = getTeamIdFromToken();
|
$teamId = getTeamIdFromToken();
|
||||||
@@ -3286,14 +3380,23 @@ class ApplicationsController extends Controller
|
|||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
if (checkIfDomainIsAlreadyUsed($fqdn, $teamId, $uuid)) {
|
// Check for domain conflicts
|
||||||
|
$result = checkIfDomainIsAlreadyUsedViaAPI($fqdn, $teamId, $uuid);
|
||||||
|
if (isset($result['error'])) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Validation failed.',
|
'message' => 'Validation failed.',
|
||||||
'errors' => [
|
'errors' => ['domains' => $result['error']],
|
||||||
'domains' => 'One of the domain is already used.',
|
|
||||||
],
|
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are conflicts and force is not enabled, return warning
|
||||||
|
if ($result['hasConflicts'] && ! $request->boolean('force_domain_override')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Domain conflicts detected. Use force_domain_override=true to proceed.',
|
||||||
|
'conflicts' => $result['conflicts'],
|
||||||
|
'warning' => 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.',
|
||||||
|
], 409);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -176,4 +176,5 @@ function removeUnnecessaryFieldsFromRequest(Request $request)
|
|||||||
$request->offsetUnset('private_key_uuid');
|
$request->offsetUnset('private_key_uuid');
|
||||||
$request->offsetUnset('use_build_server');
|
$request->offsetUnset('use_build_server');
|
||||||
$request->offsetUnset('is_static');
|
$request->offsetUnset('is_static');
|
||||||
|
$request->offsetUnset('force_domain_override');
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\ServiceApplication;
|
use App\Models\ServiceApplication;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
function checkDomainUsage(ServiceApplication|Application|null $resource = null, ?string $domain = null)
|
function checkDomainUsage(ServiceApplication|Application|null $resource = null, ?string $domain = null)
|
||||||
{
|
{
|
||||||
@@ -137,3 +138,100 @@ function checkDomainUsage(ServiceApplication|Application|null $resource = null,
|
|||||||
'hasConflicts' => count($conflicts) > 0,
|
'hasConflicts' => count($conflicts) > 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkIfDomainIsAlreadyUsedViaAPI(Collection|array $domains, ?string $teamId = null, ?string $uuid = null)
|
||||||
|
{
|
||||||
|
$conflicts = [];
|
||||||
|
|
||||||
|
if (is_null($teamId)) {
|
||||||
|
return ['error' => 'Team ID is required.'];
|
||||||
|
}
|
||||||
|
if (is_array($domains)) {
|
||||||
|
$domains = collect($domains);
|
||||||
|
}
|
||||||
|
|
||||||
|
$domains = $domains->map(function ($domain) {
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return str($domain);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check applications within the same team
|
||||||
|
$applications = Application::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid', 'name', 'id']);
|
||||||
|
$serviceApplications = ServiceApplication::ownedByCurrentTeamAPI($teamId)->with('service:id,name')->get(['fqdn', 'uuid', 'id', 'service_id']);
|
||||||
|
|
||||||
|
if ($uuid) {
|
||||||
|
$applications = $applications->filter(fn ($app) => $app->uuid !== $uuid);
|
||||||
|
$serviceApplications = $serviceApplications->filter(fn ($app) => $app->uuid !== $uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($applications as $app) {
|
||||||
|
if (is_null($app->fqdn)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
|
||||||
|
foreach ($list_of_domains as $domain) {
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
$naked_domain = str($domain)->value();
|
||||||
|
if ($domains->contains($naked_domain)) {
|
||||||
|
$conflicts[] = [
|
||||||
|
'domain' => $naked_domain,
|
||||||
|
'resource_name' => $app->name,
|
||||||
|
'resource_uuid' => $app->uuid,
|
||||||
|
'resource_type' => 'application',
|
||||||
|
'message' => "Domain $naked_domain is already in use by application '{$app->name}'",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($serviceApplications as $app) {
|
||||||
|
if (str($app->fqdn)->isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
|
||||||
|
foreach ($list_of_domains as $domain) {
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
$naked_domain = str($domain)->value();
|
||||||
|
if ($domains->contains($naked_domain)) {
|
||||||
|
$conflicts[] = [
|
||||||
|
'domain' => $naked_domain,
|
||||||
|
'resource_name' => $app->service->name ?? 'Unknown Service',
|
||||||
|
'resource_uuid' => $app->uuid,
|
||||||
|
'resource_type' => 'service',
|
||||||
|
'message' => "Domain $naked_domain is already in use by service '{$app->service->name}'",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check instance-level domain
|
||||||
|
$settings = instanceSettings();
|
||||||
|
if (data_get($settings, 'fqdn')) {
|
||||||
|
$domain = data_get($settings, 'fqdn');
|
||||||
|
if (str($domain)->endsWith('/')) {
|
||||||
|
$domain = str($domain)->beforeLast('/');
|
||||||
|
}
|
||||||
|
$naked_domain = str($domain)->value();
|
||||||
|
if ($domains->contains($naked_domain)) {
|
||||||
|
$conflicts[] = [
|
||||||
|
'domain' => $naked_domain,
|
||||||
|
'resource_name' => 'Coolify Instance',
|
||||||
|
'resource_uuid' => null,
|
||||||
|
'resource_type' => 'instance',
|
||||||
|
'message' => "Domain $naked_domain is already in use by this Coolify instance",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'conflicts' => $conflicts,
|
||||||
|
'hasConflicts' => count($conflicts) > 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
@@ -1084,79 +1084,6 @@ function check_ip_against_allowlist($ip, $allowlist)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function checkIfDomainIsAlreadyUsed(Collection|array $domains, ?string $teamId = null, ?string $uuid = null)
|
|
||||||
{
|
|
||||||
if (is_null($teamId)) {
|
|
||||||
return response()->json(['error' => 'Team ID is required.'], 400);
|
|
||||||
}
|
|
||||||
if (is_array($domains)) {
|
|
||||||
$domains = collect($domains);
|
|
||||||
}
|
|
||||||
|
|
||||||
$domains = $domains->map(function ($domain) {
|
|
||||||
if (str($domain)->endsWith('/')) {
|
|
||||||
$domain = str($domain)->beforeLast('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
return str($domain);
|
|
||||||
});
|
|
||||||
$applications = Application::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid']);
|
|
||||||
$serviceApplications = ServiceApplication::ownedByCurrentTeamAPI($teamId)->get(['fqdn', 'uuid']);
|
|
||||||
if ($uuid) {
|
|
||||||
$applications = $applications->filter(fn ($app) => $app->uuid !== $uuid);
|
|
||||||
$serviceApplications = $serviceApplications->filter(fn ($app) => $app->uuid !== $uuid);
|
|
||||||
}
|
|
||||||
$domainFound = false;
|
|
||||||
foreach ($applications as $app) {
|
|
||||||
if (is_null($app->fqdn)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
|
|
||||||
foreach ($list_of_domains as $domain) {
|
|
||||||
if (str($domain)->endsWith('/')) {
|
|
||||||
$domain = str($domain)->beforeLast('/');
|
|
||||||
}
|
|
||||||
$naked_domain = str($domain)->value();
|
|
||||||
if ($domains->contains($naked_domain)) {
|
|
||||||
$domainFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($domainFound) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
foreach ($serviceApplications as $app) {
|
|
||||||
if (str($app->fqdn)->isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$list_of_domains = collect(explode(',', $app->fqdn))->filter(fn ($fqdn) => $fqdn !== '');
|
|
||||||
foreach ($list_of_domains as $domain) {
|
|
||||||
if (str($domain)->endsWith('/')) {
|
|
||||||
$domain = str($domain)->beforeLast('/');
|
|
||||||
}
|
|
||||||
$naked_domain = str($domain)->value();
|
|
||||||
if ($domains->contains($naked_domain)) {
|
|
||||||
$domainFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($domainFound) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$settings = instanceSettings();
|
|
||||||
if (data_get($settings, 'fqdn')) {
|
|
||||||
$domain = data_get($settings, 'fqdn');
|
|
||||||
if (str($domain)->endsWith('/')) {
|
|
||||||
$domain = str($domain)->beforeLast('/');
|
|
||||||
}
|
|
||||||
$naked_domain = str($domain)->value();
|
|
||||||
if ($domains->contains($naked_domain)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseCommandsByLineForSudo(Collection $commands, Server $server): array
|
function parseCommandsByLineForSudo(Collection $commands, Server $server): array
|
||||||
{
|
{
|
||||||
|
600
openapi.json
600
openapi.json
@@ -357,6 +357,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -385,6 +389,60 @@
|
|||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#\/components\/responses\/400"
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -709,6 +767,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -737,6 +799,60 @@
|
|||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#\/components\/responses\/400"
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1061,6 +1177,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -1089,6 +1209,60 @@
|
|||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#\/components\/responses\/400"
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1342,6 +1516,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -1370,6 +1548,60 @@
|
|||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#\/components\/responses\/400"
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1606,6 +1838,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -1634,6 +1870,60 @@
|
|||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#\/components\/responses\/400"
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -1709,6 +1999,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -1737,6 +2031,60 @@
|
|||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"$ref": "#\/components\/responses\/400"
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -2175,6 +2523,10 @@
|
|||||||
"connect_to_docker_network": {
|
"connect_to_docker_network": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "The flag to connect the service to the predefined Docker network."
|
"description": "The flag to connect the service to the predefined Docker network."
|
||||||
|
},
|
||||||
|
"force_domain_override": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Force domain usage even if conflicts are detected. Default is false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -2206,6 +2558,60 @@
|
|||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"$ref": "#\/components\/responses\/404"
|
"$ref": "#\/components\/responses\/404"
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Domain conflicts detected.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain conflicts detected. Use force_domain_override=true to proceed."
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior."
|
||||||
|
},
|
||||||
|
"conflicts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"properties": {
|
||||||
|
"domain": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "example.com"
|
||||||
|
},
|
||||||
|
"resource_name": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "My Application"
|
||||||
|
},
|
||||||
|
"resource_uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"example": "abc123-def456"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"application",
|
||||||
|
"service",
|
||||||
|
"instance"
|
||||||
|
],
|
||||||
|
"example": "application"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Domain example.com is already in use by application 'My Application'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
@@ -5196,6 +5602,190 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"\/projects\/{uuid}\/environments": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Projects"
|
||||||
|
],
|
||||||
|
"summary": "List Environments",
|
||||||
|
"description": "List all environments in a project.",
|
||||||
|
"operationId": "get-environments",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "uuid",
|
||||||
|
"in": "path",
|
||||||
|
"description": "Project UUID",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of environments",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#\/components\/schemas\/Environment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"$ref": "#\/components\/responses\/401"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Project not found."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearerAuth": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Projects"
|
||||||
|
],
|
||||||
|
"summary": "Create Environment",
|
||||||
|
"description": "Create environment in project.",
|
||||||
|
"operationId": "create-environment",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "uuid",
|
||||||
|
"in": "path",
|
||||||
|
"description": "Project UUID",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"description": "Environment created.",
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the environment."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "Environment created.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"uuid": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "env123",
|
||||||
|
"description": "The UUID of the environment."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"$ref": "#\/components\/responses\/401"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"$ref": "#\/components\/responses\/400"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Project not found."
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "Environment with this name already exists."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearerAuth": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"\/projects\/{uuid}\/environments\/{environment_name_or_uuid}": {
|
||||||
|
"delete": {
|
||||||
|
"tags": [
|
||||||
|
"Projects"
|
||||||
|
],
|
||||||
|
"summary": "Delete Environment",
|
||||||
|
"description": "Delete environment by name or UUID. Environment must be empty.",
|
||||||
|
"operationId": "delete-environment",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "uuid",
|
||||||
|
"in": "path",
|
||||||
|
"description": "Project UUID",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "environment_name_or_uuid",
|
||||||
|
"in": "path",
|
||||||
|
"description": "Environment name or UUID",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Environment deleted.",
|
||||||
|
"content": {
|
||||||
|
"application\/json": {
|
||||||
|
"schema": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "Environment deleted."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"$ref": "#\/components\/responses\/401"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Environment has resources, so it cannot be deleted."
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Project or environment not found."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearerAuth": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"\/resources": {
|
"\/resources": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -6412,13 +7002,6 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"application\/json": {
|
"application\/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"required": [
|
|
||||||
"server_uuid",
|
|
||||||
"project_uuid",
|
|
||||||
"environment_name",
|
|
||||||
"environment_uuid",
|
|
||||||
"docker_compose_raw"
|
|
||||||
],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -8026,6 +8609,9 @@
|
|||||||
"is_swarm_worker": {
|
"is_swarm_worker": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"is_terminal_enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"is_usable": {
|
"is_usable": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
217
openapi.yaml
217
openapi.yaml
@@ -262,6 +262,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
@@ -276,6 +279,16 @@ paths:
|
|||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -515,6 +528,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
@@ -529,6 +545,16 @@ paths:
|
|||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -768,6 +794,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
@@ -782,6 +811,16 @@ paths:
|
|||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -968,6 +1007,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
@@ -982,6 +1024,16 @@ paths:
|
|||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -1159,6 +1211,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
@@ -1173,6 +1228,16 @@ paths:
|
|||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -1230,6 +1295,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
@@ -1244,6 +1312,16 @@ paths:
|
|||||||
$ref: '#/components/responses/401'
|
$ref: '#/components/responses/401'
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -1560,6 +1638,9 @@ paths:
|
|||||||
connect_to_docker_network:
|
connect_to_docker_network:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: 'The flag to connect the service to the predefined Docker network.'
|
description: 'The flag to connect the service to the predefined Docker network.'
|
||||||
|
force_domain_override:
|
||||||
|
type: boolean
|
||||||
|
description: 'Force domain usage even if conflicts are detected. Default is false.'
|
||||||
type: object
|
type: object
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
@@ -1576,6 +1657,16 @@ paths:
|
|||||||
$ref: '#/components/responses/400'
|
$ref: '#/components/responses/400'
|
||||||
'404':
|
'404':
|
||||||
$ref: '#/components/responses/404'
|
$ref: '#/components/responses/404'
|
||||||
|
'409':
|
||||||
|
description: 'Domain conflicts detected.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Domain conflicts detected. Use force_domain_override=true to proceed.' }
|
||||||
|
warning: { type: string, example: 'Using the same domain for multiple resources can cause routing conflicts and unpredictable behavior.' }
|
||||||
|
conflicts: { type: array, items: { properties: { domain: { type: string, example: example.com }, resource_name: { type: string, example: 'My Application' }, resource_uuid: { type: string, nullable: true, example: abc123-def456 }, resource_type: { type: string, enum: [application, service, instance], example: application }, message: { type: string, example: "Domain example.com is already in use by application 'My Application'" } }, type: object } }
|
||||||
|
type: object
|
||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
@@ -3570,6 +3661,124 @@ paths:
|
|||||||
security:
|
security:
|
||||||
-
|
-
|
||||||
bearerAuth: []
|
bearerAuth: []
|
||||||
|
'/projects/{uuid}/environments':
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Projects
|
||||||
|
summary: 'List Environments'
|
||||||
|
description: 'List all environments in a project.'
|
||||||
|
operationId: get-environments
|
||||||
|
parameters:
|
||||||
|
-
|
||||||
|
name: uuid
|
||||||
|
in: path
|
||||||
|
description: 'Project UUID'
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: 'List of environments'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Environment'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/401'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/400'
|
||||||
|
'404':
|
||||||
|
description: 'Project not found.'
|
||||||
|
security:
|
||||||
|
-
|
||||||
|
bearerAuth: []
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Projects
|
||||||
|
summary: 'Create Environment'
|
||||||
|
description: 'Create environment in project.'
|
||||||
|
operationId: create-environment
|
||||||
|
parameters:
|
||||||
|
-
|
||||||
|
name: uuid
|
||||||
|
in: path
|
||||||
|
description: 'Project UUID'
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
description: 'Environment created.'
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: 'The name of the environment.'
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: 'Environment created.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
uuid: { type: string, example: env123, description: 'The UUID of the environment.' }
|
||||||
|
type: object
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/401'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/400'
|
||||||
|
'404':
|
||||||
|
description: 'Project not found.'
|
||||||
|
'409':
|
||||||
|
description: 'Environment with this name already exists.'
|
||||||
|
security:
|
||||||
|
-
|
||||||
|
bearerAuth: []
|
||||||
|
'/projects/{uuid}/environments/{environment_name_or_uuid}':
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- Projects
|
||||||
|
summary: 'Delete Environment'
|
||||||
|
description: 'Delete environment by name or UUID. Environment must be empty.'
|
||||||
|
operationId: delete-environment
|
||||||
|
parameters:
|
||||||
|
-
|
||||||
|
name: uuid
|
||||||
|
in: path
|
||||||
|
description: 'Project UUID'
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
-
|
||||||
|
name: environment_name_or_uuid
|
||||||
|
in: path
|
||||||
|
description: 'Environment name or UUID'
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: 'Environment deleted.'
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
message: { type: string, example: 'Environment deleted.' }
|
||||||
|
type: object
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/401'
|
||||||
|
'400':
|
||||||
|
description: 'Environment has resources, so it cannot be deleted.'
|
||||||
|
'404':
|
||||||
|
description: 'Project or environment not found.'
|
||||||
|
security:
|
||||||
|
-
|
||||||
|
bearerAuth: []
|
||||||
/resources:
|
/resources:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -4289,12 +4498,6 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
required:
|
|
||||||
- server_uuid
|
|
||||||
- project_uuid
|
|
||||||
- environment_name
|
|
||||||
- environment_uuid
|
|
||||||
- docker_compose_raw
|
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
@@ -5377,6 +5580,8 @@ components:
|
|||||||
type: boolean
|
type: boolean
|
||||||
is_swarm_worker:
|
is_swarm_worker:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
is_terminal_enabled:
|
||||||
|
type: boolean
|
||||||
is_usable:
|
is_usable:
|
||||||
type: boolean
|
type: boolean
|
||||||
logdrain_axiom_api_key:
|
logdrain_axiom_api_key:
|
||||||
|
Reference in New Issue
Block a user