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