From df048c50acb81e53c1bda3820e03554f756e51c2 Mon Sep 17 00:00:00 2001 From: Aidaho Date: Wed, 9 Oct 2024 18:03:00 +0300 Subject: [PATCH] v8.2: Add PUT and DELETE methods to InstallView and update schemas Extended InstallView with PUT and DELETE methods to allow updating service settings and deleting installations. Made adjustments to the request and response schemas, including using ServiceInstallFromApi and adding IdStrResponse. --- app/api/routes/routes.py | 2 +- app/modules/roxywi/class_models.py | 14 ++++ app/modules/service/installation.py | 4 +- app/views/install/views.py | 99 ++++++++++++++++++++--------- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 7f76760b..d570587b 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -77,7 +77,7 @@ register_api_id_ip(DefaultsSectionView, 'haproxy_defaults', '/section/defaults', bp.add_url_rule('/service///config/list', view_func=ServiceConfigList.as_view('config_list_ip'), methods=['GET']) bp.add_url_rule('/service///config/list', view_func=ServiceConfigList.as_view('config_list'), methods=['GET']) register_api_id_ip(CheckerView, 'checker', '/tools') -register_api_id_ip(InstallView, 'install', '/install', methods=['POST']) +register_api_id_ip(InstallView, 'install', '/install', methods=['POST', 'PUT', 'DELETE']) register_api_id_ip(ServiceActionView, 'service_action', '/', methods=['GET']) register_api(ServerView, 'server', '/server', 'server_id') diff --git a/app/modules/roxywi/class_models.py b/app/modules/roxywi/class_models.py index 15fcf3a6..89c4767a 100644 --- a/app/modules/roxywi/class_models.py +++ b/app/modules/roxywi/class_models.py @@ -46,6 +46,10 @@ class IdResponse(BaseResponse): id: int +class IdStrResponse(BaseResponse): + id: str + + class IdDataResponse(IdResponse): data: str @@ -225,6 +229,16 @@ class ServiceInstall(BaseModel): syn_flood: Optional[bool] = 0 +class ServiceInstallFromApi(BaseModel): + checker: Optional[bool] = 0 + metrics: Optional[bool] = 0 + auto_start: Optional[bool] = 0 + syn_flood: Optional[bool] = 0 + servers: Optional[List[ServerInstall]] = None + services: Optional[Dict[str, HAClusterService]] = None + docker: Optional[bool] = 0 + + class Checker(BaseModel): checker: Optional[bool] = 0 metrics: Optional[bool] = 0 diff --git a/app/modules/service/installation.py b/app/modules/service/installation.py index a333936d..f5646142 100644 --- a/app/modules/service/installation.py +++ b/app/modules/service/installation.py @@ -18,7 +18,7 @@ import app.modules.server.server as server_mod import app.modules.roxywi.common as roxywi_common from app.modules.server.ssh import return_ssh_keys_path from app.modules.roxywi.class_models import ServiceInstall, HAClusterRequest, HaproxyGlobalRequest, \ - HaproxyDefaultsRequest, HaproxyConfigRequest + HaproxyDefaultsRequest, HaproxyConfigRequest, ServiceInstallFromApi def generate_udp_inv(listener_id: int, action: str) -> object: @@ -427,7 +427,7 @@ def _create_default_config_in_db(server_id: int) -> None: add_sql.insert_new_section(server_id, 'listen', 'stats', stats_config) -def install_service(service: str, json_data: Union[str, ServiceInstall, HAClusterRequest], cluster_id: int = None) -> dict: +def install_service(service: str, json_data: Union[str, ServiceInstall, HAClusterRequest, ServiceInstallFromApi], cluster_id: int = None) -> dict: generate_functions = { 'haproxy': generate_haproxy_inv, 'nginx': generate_service_inv, diff --git a/app/views/install/views.py b/app/views/install/views.py index b126109d..7c3e8496 100644 --- a/app/views/install/views.py +++ b/app/views/install/views.py @@ -10,7 +10,7 @@ import app.modules.db.service as service_sql import app.modules.service.installation as service_mod from app.middleware import get_user_params, check_services, page_for_admin, check_group from app.modules.common.common_classes import SupportClass -from app.modules.roxywi.class_models import BaseResponse, ServiceInstall +from app.modules.roxywi.class_models import ServiceInstallFromApi, IdStrResponse, BaseResponse, ServerInstall, HAClusterService from app.views.service.views import ServiceView @@ -78,11 +78,11 @@ class InstallGetStatus(ServiceView): class InstallView(MethodView): - methods = ['POST'] + methods = ['POST', 'PUT', 'DELETE'] decorators = [jwt_required(), get_user_params(), check_services, page_for_admin(level=3), check_group()] - @validate(body=ServiceInstall) - def post(self, service: Literal['haproxy', 'nginx', 'apache', 'keepalived'], server_id: Union[int, str, None], body: ServiceInstall): + @validate(body=ServiceInstallFromApi) + def post(self, service: Literal['haproxy', 'nginx', 'apache', 'keepalived'], server_id: Union[int, str, None], body: ServiceInstallFromApi): """ Install a specific service. --- @@ -99,33 +99,15 @@ class InstallView(MethodView): type: 'integer' required: true description: The ID or IP of the server - responses: - 200: - description: Successful operation + - name body: + in: body + required: true schema: - type: 'object' + type: object properties: - servers: - type: 'array' - items: - type: 'object' - properties: - id: - type: 'integer' - name: - type: 'string' - services: - type: 'object' - description: 'Which service will be installed.' - properties: - haproxy: - type: 'object' - description: 'Status of HAProxy' - properties: - enabled: - type: 'integer' - docker: - type: 'integer' + docker: + type: 'integer' + description: Should be service run in Docker container syn_flood: type: 'integer' checker: @@ -134,6 +116,9 @@ class InstallView(MethodView): type: 'integer' auto_start: type: 'integer' + responses: + 201: + description: Successful operation default: description: Unexpected error """ @@ -142,6 +127,10 @@ class InstallView(MethodView): server_id = SupportClass().return_server_ip_or_id(server_id) except Exception as e: return roxywi_common.handler_exceptions_for_json_data(e, '') + if not body.servers: + body.servers = [ServerInstall(id=server_id)] + if not body.services: + body.services = {service: HAClusterService(enabled=1, docker=body.docker)} try: output = service_mod.install_service(service, body) except Exception as e: @@ -156,4 +145,54 @@ class InstallView(MethodView): return roxywi_common.handler_exceptions_for_json_data(e, f'Cannot update Tools settings for {service.title()}') else: return output - return BaseResponse().model_dump(mode='json'), 201 + return IdStrResponse(id=f'{server_id}-{service}').model_dump(mode='json'), 201 + + @validate(body=ServiceInstallFromApi) + def put(self, service: Literal['haproxy', 'nginx', 'apache', 'keepalived'], server_id: Union[int, str, None], body: ServiceInstallFromApi): + """ + Update service Tools settings. + --- + tags: + - Service Installation + parameters: + - in: path + name: service + type: 'integer' + required: true + description: The type of service (haproxy, nginx, apache, keepalived) + - in: path + name: server_id + type: 'integer' + required: true + description: The ID or IP of the server + - name body: + in: body + required: true + schema: + type: object + properties: + docker: + type: 'integer' + description: Should be service run in Docker container + syn_flood: + type: 'integer' + checker: + type: 'integer' + metrics: + type: 'integer' + auto_start: + type: 'integer' + responses: + 201: + description: Successful operation + default: + description: Unexpected error + """ + try: + service_sql.update_hapwi_server(server_id, body.checker, body.metrics, body.auto_start, service) + except Exception as e: + return roxywi_common.handler_exceptions_for_json_data(e, f'Cannot update Tools settings for {service.title()}') + return IdStrResponse(id=f'{server_id}-{service}').model_dump(mode='json'), 201 + + def delete(self, service: Literal['haproxy', 'nginx', 'apache', 'keepalived'], server_id: Union[int, str, None]): + return BaseResponse().model_dump(mode='json'), 204