mirror of
https://github.com/Websoft9/websoft9.git
synced 2024-11-26 01:20:28 +00:00
update
This commit is contained in:
parent
62eee2de82
commit
eff1da37ae
33 changed files with 735 additions and 159 deletions
|
@ -1,6 +1,6 @@
|
||||||
# run app : uvicorn src.main:app --reload --port 9999 --log-level error
|
## run app : uvicorn src.main:app --reload --port 9999 --log-level error
|
||||||
# run nginx proxy manager doc:docker run -p 9091:8080 -e SWAGGER_JSON=/foo/api.swagger.json -v /data/websoft9/appmanage_new/docs/:/foo swaggerapi/swagger-ui
|
## run nginx proxy manager doc:docker run -p 9091:8080 -e SWAGGER_JSON=/foo/api.swagger.json -v /data/websoft9/appmanage_new/docs/:/foo swaggerapi/swagger-ui
|
||||||
# supervisorctl
|
## supervisorctl
|
||||||
## supervisorctl reload
|
## supervisorctl reload
|
||||||
## supervisorctl update
|
## supervisorctl update
|
||||||
## supervisorctl status
|
## supervisorctl status
|
||||||
|
|
|
@ -6,7 +6,7 @@ from src.schemas.appResponse import AppResponse
|
||||||
from src.schemas.errorResponse import ErrorResponse
|
from src.schemas.errorResponse import ErrorResponse
|
||||||
from src.services.app_manager import AppManger
|
from src.services.app_manager import AppManger
|
||||||
|
|
||||||
router = APIRouter(prefix="/api/v1")
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/apps/catalog/{locale}",
|
"/apps/catalog/{locale}",
|
||||||
|
@ -23,7 +23,6 @@ def get_catalog_apps(
|
||||||
):
|
):
|
||||||
return AppManger().get_catalog_apps(locale)
|
return AppManger().get_catalog_apps(locale)
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/apps/available/{locale}",
|
"/apps/available/{locale}",
|
||||||
summary="List Available Apps",
|
summary="List Available Apps",
|
||||||
|
|
|
@ -1,12 +1,94 @@
|
||||||
from fastapi import APIRouter, Query
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
from fastapi import APIRouter, Query,Path
|
||||||
|
from fastapi.params import Body
|
||||||
|
from src.schemas.domainNames import DomainNames
|
||||||
|
from src.schemas.errorResponse import ErrorResponse
|
||||||
|
from src.schemas.proxyHosts import ProxyHost
|
||||||
|
from src.services.app_manager import AppManger
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get("/proxys".format(),summary="Get proxys",description="Get proxys")
|
@router.get(
|
||||||
def get_proxys():
|
"/proxys/{app_id}",
|
||||||
return {"proxys": "proxys"}
|
summary="Get Proxys",
|
||||||
|
description="Get proxys by app",
|
||||||
|
responses={
|
||||||
|
200: {"model": list[ProxyHost]},
|
||||||
|
400: {"model": ErrorResponse},
|
||||||
|
500: {"model": ErrorResponse},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def get_proxys(
|
||||||
|
app_id: str = Path(..., description="App ID to get proxys from"),
|
||||||
|
endpointId: int = Query(None, description="Endpoint ID to get proxys from. If not set, get proxys from the local endpoint")
|
||||||
|
):
|
||||||
|
return AppManger().get_proxys_by_app(app_id,endpointId)
|
||||||
|
|
||||||
@router.put("/proxys")
|
@router.post(
|
||||||
def update_settings():
|
"/proxys/{app_id}",
|
||||||
return {"proxys": "proxys"}
|
summary="Create Proxy",
|
||||||
|
description="Create a proxy host",
|
||||||
|
responses={
|
||||||
|
200: {"model": list[ProxyHost]},
|
||||||
|
400: {"model": ErrorResponse},
|
||||||
|
500: {"model": ErrorResponse},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def create_proxys(
|
||||||
|
domain_names: DomainNames = Body(..., description="Domain names to create proxys from", example={"domain_names": ["example1.com","example2.com"]}),
|
||||||
|
app_id: str = Path(..., description="App ID to create proxys from"),
|
||||||
|
endpointId: int = Query(None, description="Endpoint ID to create proxys from. If not set, create proxys from the local endpoint"),
|
||||||
|
):
|
||||||
|
return AppManger().create_proxy_by_app(app_id,domain_names.domain_names,endpointId)
|
||||||
|
|
||||||
|
@router.put(
|
||||||
|
"/proxys/{app_id}}",
|
||||||
|
summary="Update Proxys",
|
||||||
|
description="Update proxys by app",
|
||||||
|
responses={
|
||||||
|
200: {"model": list[ProxyHost]},
|
||||||
|
400: {"model": ErrorResponse},
|
||||||
|
500: {"model": ErrorResponse},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def update_proxys(
|
||||||
|
proxyHost:ProxyHost = Body(..., description="Proxy host to update proxys from"),
|
||||||
|
app_id: str = Path(..., description="App ID to create proxys from"),
|
||||||
|
endpointId: int = Query(None, description="Endpoint ID to create proxys from. If not set, create proxys from the local endpoint"),
|
||||||
|
):
|
||||||
|
return AppManger().update_proxy_by_app(app_id,proxyHost,endpointId)
|
||||||
|
|
||||||
|
@router.delete(
|
||||||
|
"/proxys/app/{app_id}",
|
||||||
|
summary="Delete Proxys",
|
||||||
|
description="Delete proxys by app",
|
||||||
|
status_code=204,
|
||||||
|
responses={
|
||||||
|
204: {"description": "Delete Proxys Success"},
|
||||||
|
400: {"model": ErrorResponse},
|
||||||
|
500: {"model": ErrorResponse},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def delete_proxys_by_app(
|
||||||
|
app_id: str = Path(..., description="App ID to create proxys from"),
|
||||||
|
endpointId: int = Query(None, description="Endpoint ID to create proxys from. If not set, create proxys from the local endpoint"),
|
||||||
|
):
|
||||||
|
AppManger().remove_proxy_by_app(app_id,endpointId)
|
||||||
|
|
||||||
|
@router.delete(
|
||||||
|
"/proxys/{proxy_id}",
|
||||||
|
summary="Delete Proxys",
|
||||||
|
description="Delete proxys by proxy_id",
|
||||||
|
status_code=204,
|
||||||
|
responses={
|
||||||
|
204: {"description": "Delete Proxys Success"},
|
||||||
|
400: {"model": ErrorResponse},
|
||||||
|
500: {"model": ErrorResponse},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def delete_proxys_by_id(
|
||||||
|
proxy_id: int = Path(..., description="Proxy ID to delete proxys from")
|
||||||
|
):
|
||||||
|
AppManger().remove_proxy_by_id(proxy_id)
|
|
@ -1,11 +1,22 @@
|
||||||
from fastapi import APIRouter, Query
|
from fastapi import APIRouter, Query
|
||||||
from typing import List, Optional
|
from src.schemas.appSettings import AppSettings
|
||||||
|
from src.schemas.errorResponse import ErrorResponse
|
||||||
|
|
||||||
|
from src.services.settings_manager import SettingsManager
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get("/settings",summary="Get settings",description="Get settings")
|
@router.get("/settings",
|
||||||
|
summary="Get settings",
|
||||||
|
description="Get settings",
|
||||||
|
responses={
|
||||||
|
200: {"model": AppSettings},
|
||||||
|
400: {"model": ErrorResponse},
|
||||||
|
500: {"model": ErrorResponse},
|
||||||
|
}
|
||||||
|
)
|
||||||
def get_settings():
|
def get_settings():
|
||||||
return {"settings": "settings"}
|
return SettingsManager().read_all()
|
||||||
|
|
||||||
@router.put("/settings")
|
@router.put("/settings")
|
||||||
def update_settings():
|
def update_settings():
|
||||||
|
|
|
@ -1,25 +1,18 @@
|
||||||
# The config for appmanage
|
|
||||||
[appmanage]
|
|
||||||
access_token =
|
|
||||||
|
|
||||||
# The config for nginx proxy manager
|
# The config for nginx proxy manager
|
||||||
[nginx_proxy_manager]
|
[nginx_proxy_manager]
|
||||||
base_url = http://websoft9-proxy:81/api
|
base_url = http://websoft9-proxy:81/api
|
||||||
#base_url = http://47.92.222.186/w9proxy/api
|
|
||||||
user_name = help@websoft9.com
|
user_name = help@websoft9.com
|
||||||
user_pwd = ECTKPRAWhij789yr
|
user_pwd = ECTKPRAWhij789yr
|
||||||
|
|
||||||
#The config for gitea
|
#The config for gitea
|
||||||
[gitea]
|
[gitea]
|
||||||
base_url = http://websoft9-git:3000/api/v1
|
base_url = http://websoft9-git:3000/api/v1
|
||||||
# base_url = http://47.92.222.186/w9git/api/v1
|
|
||||||
user_name = websoft9
|
user_name = websoft9
|
||||||
user_pwd = Rk9qOQ68Inf0
|
user_pwd = Rk9qOQ68Inf0
|
||||||
|
|
||||||
#The config for portainer
|
#The config for portainer
|
||||||
[portainer]
|
[portainer]
|
||||||
base_url = http://websoft9-deployment:9000/api
|
base_url = http://websoft9-deployment:9000/api
|
||||||
#base_url = http://47.92.222.186/w9deployment/api
|
|
||||||
user_name = admin
|
user_name = admin
|
||||||
user_pwd = ]}fU;XmVH].VI{Hh
|
user_pwd = ]}fU;XmVH].VI{Hh
|
||||||
|
|
||||||
|
@ -28,19 +21,4 @@ user_pwd = ]}fU;XmVH].VI{Hh
|
||||||
path = /websoft9/library/apps
|
path = /websoft9/library/apps
|
||||||
|
|
||||||
[app_media]
|
[app_media]
|
||||||
path = /websoft9/media/json/
|
path = /websoft9/media/json/
|
||||||
|
|
||||||
# public_ip_url_list is a list of public ip url, which is used to get the public ip of the server
|
|
||||||
[public_ip_url_list]
|
|
||||||
url_list = https://api.ipify.org/,
|
|
||||||
https://icanhazip.com/,
|
|
||||||
http://ifconfig.co/,
|
|
||||||
https://ident.me/,
|
|
||||||
https://ifconfig.me/,
|
|
||||||
https://ipecho.net/plain,
|
|
||||||
https://ipinfo.io/ip,
|
|
||||||
https://ip.sb/,
|
|
||||||
http://whatismyip.akamai.com/,
|
|
||||||
https://inet-ip.info/,
|
|
||||||
http://bot.whatismyipaddress.com/
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import configparser
|
import configparser
|
||||||
|
from src.core.logger import logger
|
||||||
|
|
||||||
|
|
||||||
class ConfigManager:
|
class ConfigManager:
|
||||||
|
|
|
@ -2,12 +2,14 @@ import logging
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.exceptions import RequestValidationError
|
from fastapi.exceptions import RequestValidationError
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
from src.api.v1.routers import app as api_app
|
from src.api.v1.routers import app as api_app
|
||||||
from src.api.v1.routers import settings as api_settings
|
from src.api.v1.routers import settings as api_settings
|
||||||
from src.api.v1.routers import proxy as api_proxy
|
from src.api.v1.routers import proxy as api_proxy
|
||||||
from src.core.exception import CustomException
|
from src.core.exception import CustomException
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
from src.schemas.errorResponse import ErrorResponse
|
from src.schemas.errorResponse import ErrorResponse
|
||||||
|
from fastapi.responses import HTMLResponse
|
||||||
|
|
||||||
uvicorn_logger = logging.getLogger("uvicorn")
|
uvicorn_logger = logging.getLogger("uvicorn")
|
||||||
|
|
||||||
|
@ -23,8 +25,35 @@ app = FastAPI(
|
||||||
# summary="[ Base URL: /api/v1 ]",
|
# summary="[ Base URL: /api/v1 ]",
|
||||||
description="This documentation describes the AppManage API.",
|
description="This documentation describes the AppManage API.",
|
||||||
version="0.0.1",
|
version="0.0.1",
|
||||||
|
docs_url=None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory="swagger-ui"), name="static")
|
||||||
|
|
||||||
|
@app.get("/docs", response_class=HTMLResponse,include_in_schema=False)
|
||||||
|
async def custom_swagger_ui_html():
|
||||||
|
return """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Websoft9 API</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/static/swagger-ui.css">
|
||||||
|
<script src="/static/swagger-ui-bundle.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="swagger-ui"></div>
|
||||||
|
<script>
|
||||||
|
const ui = SwaggerUIBundle({
|
||||||
|
url: "/openapi.json",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
||||||
|
layout: "BaseLayout"
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
# remove 422 responses
|
# remove 422 responses
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
async def remove_422_responses():
|
async def remove_422_responses():
|
||||||
|
|
29
appmanage_new/src/schemas/appSettings.py
Normal file
29
appmanage_new/src/schemas/appSettings.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from pydantic import BaseModel, Field, HttpUrl
|
||||||
|
|
||||||
|
class NginxProxyManagerSetting(BaseModel):
|
||||||
|
base_url: HttpUrl = Field(..., title="The base url for nginx proxy manager")
|
||||||
|
user_name: str = Field(..., title="The user name for nginx proxy manager")
|
||||||
|
user_pwd: str = Field(..., title="The user password for nginx proxy manager")
|
||||||
|
|
||||||
|
class GiteaSetting(BaseModel):
|
||||||
|
base_url: HttpUrl = Field(..., title="The base url for gitea")
|
||||||
|
user_name: str = Field(..., title="The user name for gitea")
|
||||||
|
user_pwd: str = Field(..., title="The user password for gitea")
|
||||||
|
|
||||||
|
class PortainerSetting(BaseModel):
|
||||||
|
base_url: HttpUrl = Field(..., title="The base url for portainer")
|
||||||
|
user_name: str = Field(..., title="The user name for portainer")
|
||||||
|
user_pwd: str = Field(..., title="The user password for portainer")
|
||||||
|
|
||||||
|
class DockerLibrarySetting(BaseModel):
|
||||||
|
path: str = Field(..., title="The path of docker library")
|
||||||
|
|
||||||
|
class AppMediaSetting(BaseModel):
|
||||||
|
path: str = Field(..., title="The path of app media")
|
||||||
|
|
||||||
|
class AppSettings(BaseModel):
|
||||||
|
nginx_proxy_manager: NginxProxyManagerSetting
|
||||||
|
gitea: GiteaSetting
|
||||||
|
portainer: PortainerSetting
|
||||||
|
docker_library: DockerLibrarySetting
|
||||||
|
app_media: AppMediaSetting
|
24
appmanage_new/src/schemas/domainNames.py
Normal file
24
appmanage_new/src/schemas/domainNames.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
from typing import Optional, List
|
||||||
|
from pydantic import BaseModel, Field, validator
|
||||||
|
from src.core.exception import CustomException
|
||||||
|
|
||||||
|
|
||||||
|
class DomainNames(BaseModel):
|
||||||
|
domain_names: List[str]
|
||||||
|
|
||||||
|
@validator('domain_names', each_item=True)
|
||||||
|
def validate_domain_name(cls, v):
|
||||||
|
if not v.strip():
|
||||||
|
raise CustomException(400,"Invalid Request","domain_names' cannot be empty string.")
|
||||||
|
if v.startswith('http://') or v.startswith('https://'):
|
||||||
|
raise CustomException(400,"Invalid Request","'domain_names' cannot start with 'http://' or 'https://'.")
|
||||||
|
return v
|
||||||
|
|
||||||
|
@validator('domain_names')
|
||||||
|
def validate_domain_names(cls, v):
|
||||||
|
if not v:
|
||||||
|
raise CustomException(400,"Invalid Request","domain_names' cannot be empty.")
|
||||||
|
|
||||||
|
if len(set(v)) != len(v):
|
||||||
|
raise CustomException(400,"Invalid Request","Duplicate entries found in 'domain_names'. All domains must be unique.")
|
||||||
|
return v
|
26
appmanage_new/src/schemas/proxyHosts.py
Normal file
26
appmanage_new/src/schemas/proxyHosts.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from typing import List
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import List
|
||||||
|
from pydantic import BaseModel, validator
|
||||||
|
from src.core.exception import CustomException
|
||||||
|
|
||||||
|
class ProxyHost(BaseModel):
|
||||||
|
proxy_id: int
|
||||||
|
domain_names: List[str]
|
||||||
|
|
||||||
|
@validator('domain_names', each_item=True)
|
||||||
|
def validate_domain_name(cls, v):
|
||||||
|
if not v.strip():
|
||||||
|
raise CustomException(400,"Invalid Request","domain_names' cannot be empty string.")
|
||||||
|
if v.startswith('http://') or v.startswith('https://'):
|
||||||
|
raise CustomException(400,"Invalid Request","'domain_names' cannot start with 'http://' or 'https://'.")
|
||||||
|
return v
|
||||||
|
|
||||||
|
@validator('domain_names')
|
||||||
|
def validate_domain_names(cls, v):
|
||||||
|
if not v:
|
||||||
|
raise CustomException(400,"Invalid Request","domain_names' cannot be empty.")
|
||||||
|
|
||||||
|
if len(set(v)) != len(v):
|
||||||
|
raise CustomException(400,"Invalid Request","Duplicate entries found in 'domain_names'. All domains must be unique.")
|
||||||
|
return v
|
|
@ -8,6 +8,8 @@ from src.core.envHelper import EnvHelper
|
||||||
from src.core.exception import CustomException
|
from src.core.exception import CustomException
|
||||||
from src.schemas.appInstall import appInstall
|
from src.schemas.appInstall import appInstall
|
||||||
from src.schemas.appResponse import AppResponse
|
from src.schemas.appResponse import AppResponse
|
||||||
|
from src.schemas.proxyHosts import ProxyHost
|
||||||
|
from src.services.common_check import check_appId, check_appName_and_appVersion, check_domain_names, check_endpointId
|
||||||
from src.services.git_manager import GitManager
|
from src.services.git_manager import GitManager
|
||||||
from src.services.gitea_manager import GiteaManager
|
from src.services.gitea_manager import GiteaManager
|
||||||
from src.services.portainer_manager import PortainerManager
|
from src.services.portainer_manager import PortainerManager
|
||||||
|
@ -60,7 +62,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
apps_info = []
|
apps_info = []
|
||||||
|
@ -105,7 +107,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -234,22 +236,22 @@ class AppManger:
|
||||||
giteaManager = GiteaManager()
|
giteaManager = GiteaManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_name and app_version
|
# validate the app_name and app_version
|
||||||
app_name = appInstall.app_name
|
app_name = appInstall.app_name
|
||||||
app_version = appInstall.edition.version
|
app_version = appInstall.edition.version
|
||||||
self._check_appName_and_appVersion(app_name,app_version,library_path)
|
check_appName_and_appVersion(app_name,app_version,library_path)
|
||||||
|
|
||||||
# validate the app_id
|
# validate the app_id
|
||||||
app_id = appInstall.app_id
|
app_id = appInstall.app_id
|
||||||
self._check_appId(app_id,endpointId,giteaManager,portainerManager)
|
check_appId(app_id,endpointId,giteaManager,portainerManager)
|
||||||
|
|
||||||
# validate the domain_names
|
# validate the domain_names
|
||||||
proxy_enabled = appInstall.proxy_enabled
|
proxy_enabled = appInstall.proxy_enabled
|
||||||
domain_names = appInstall.domain_names
|
domain_names = appInstall.domain_names
|
||||||
if proxy_enabled:
|
if proxy_enabled:
|
||||||
self._check_domain_names(domain_names)
|
check_domain_names(domain_names)
|
||||||
|
|
||||||
# Install app - Step 1 : create repo in gitea
|
# Install app - Step 1 : create repo in gitea
|
||||||
repo_url = giteaManager.create_repo(app_id)
|
repo_url = giteaManager.create_repo(app_id)
|
||||||
|
@ -317,10 +319,10 @@ class AppManger:
|
||||||
if os.path.exists(nginx_proxy_path):
|
if os.path.exists(nginx_proxy_path):
|
||||||
# Get the advanced config
|
# Get the advanced config
|
||||||
advanced_config = FileHelper.read_file(nginx_proxy_path)
|
advanced_config = FileHelper.read_file(nginx_proxy_path)
|
||||||
ProxyManager().create_proxy_for_app(domain_names,app_id,forward_port,advanced_config)
|
ProxyManager().create_proxy_by_app(domain_names,app_id,forward_port,advanced_config)
|
||||||
else:
|
else:
|
||||||
ProxyManager().create_proxy_for_app(domain_names,app_id,forward_port)
|
ProxyManager().create_proxy_by_app(domain_names,app_id,forward_port)
|
||||||
except (CustomException,Exception) as e:
|
except (CustomException,Exception) as e:
|
||||||
# Rollback-1: remove repo in gitea
|
# Rollback-1: remove repo in gitea
|
||||||
giteaManager.remove_repo(app_id)
|
giteaManager.remove_repo(app_id)
|
||||||
# Rollback-2: remove stack in portainer
|
# Rollback-2: remove stack in portainer
|
||||||
|
@ -336,7 +338,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -364,7 +366,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -399,7 +401,7 @@ class AppManger:
|
||||||
proxys_host = proxyManager.get_proxy_host_by_app(app_id)
|
proxys_host = proxyManager.get_proxy_host_by_app(app_id)
|
||||||
# If the proxy is exists, remove it
|
# If the proxy is exists, remove it
|
||||||
if proxys_host:
|
if proxys_host:
|
||||||
proxyManager.remove_proxy_host_for_app(app_id)
|
proxyManager.remove_proxy_host_by_app(app_id)
|
||||||
|
|
||||||
# Uninstall app - Step 2 : remove repo in gitea
|
# Uninstall app - Step 2 : remove repo in gitea
|
||||||
# Check the repo is exists
|
# Check the repo is exists
|
||||||
|
@ -427,7 +429,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -458,7 +460,7 @@ class AppManger:
|
||||||
proxys_host = proxyManager.get_proxy_host_by_app(app_id)
|
proxys_host = proxyManager.get_proxy_host_by_app(app_id)
|
||||||
# If the proxy is exists, remove it
|
# If the proxy is exists, remove it
|
||||||
if proxys_host:
|
if proxys_host:
|
||||||
proxyManager.remove_proxy_host_for_app(app_id)
|
proxyManager.remove_proxy_host_by_app(app_id)
|
||||||
|
|
||||||
# Check the repo is exists
|
# Check the repo is exists
|
||||||
giteaManager = GiteaManager()
|
giteaManager = GiteaManager()
|
||||||
|
@ -472,7 +474,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
# is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
# is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -503,7 +505,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
# is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
# is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -533,7 +535,7 @@ class AppManger:
|
||||||
portainerManager = PortainerManager()
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
# Check the endpointId is exists.
|
# Check the endpointId is exists.
|
||||||
endpointId = self._check_endpointId(endpointId, portainerManager)
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
# validate the app_id is exists in portainer
|
||||||
# is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
# is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
@ -559,81 +561,164 @@ class AppManger:
|
||||||
)
|
)
|
||||||
portainerManager.restart_stack(app_id,endpointId)
|
portainerManager.restart_stack(app_id,endpointId)
|
||||||
|
|
||||||
def _check_appName_and_appVersion(self,app_name:str, app_version:str,library_path:str):
|
def get_proxys_by_app(self,app_id:str,endpointId:int = None):
|
||||||
"""
|
portainerManager = PortainerManager()
|
||||||
Check the app_name and app_version is exists in docker library
|
proxyManager = ProxyManager()
|
||||||
|
|
||||||
Args:
|
# Check the endpointId is exists.
|
||||||
app_name (str): App Name
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
app_version (str): App Version
|
|
||||||
|
stack_info = portainerManager.get_stack_by_name(app_id,endpointId)
|
||||||
Raises:
|
if stack_info is None:
|
||||||
CustomException: If the app_name or app_version is not exists in docker library
|
|
||||||
"""
|
|
||||||
if not os.path.exists(f"{library_path}/{app_name}"):
|
|
||||||
logger.error(f"When install app:{app_name}, the app is not exists in docker library")
|
|
||||||
raise CustomException(
|
raise CustomException(
|
||||||
status_code=400,
|
status_code=400,
|
||||||
message="Invalid Request",
|
message="Invalid Request",
|
||||||
details=f"app_name:{app_name} not supported",
|
details=f"{app_id} Not Found"
|
||||||
|
)
|
||||||
|
# stack_status = stack_info.get("Status",None)
|
||||||
|
# if stack_status == 2:
|
||||||
|
# raise CustomException(
|
||||||
|
# status_code=400,
|
||||||
|
# message="Invalid Request",
|
||||||
|
# details=f"{app_id} is inactive, can not get proxy,you can redeploy it"
|
||||||
|
# )
|
||||||
|
# Get the proxys
|
||||||
|
proxys_host = proxyManager.get_proxy_host_by_app(app_id)
|
||||||
|
return proxys_host
|
||||||
|
|
||||||
|
def create_proxy_by_app(self,app_id:str,domain_names:list[str],endpointId:int = None):
|
||||||
|
proxyManager = ProxyManager()
|
||||||
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
|
# Check the endpointId is exists.
|
||||||
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
|
# Check the app_id is exists
|
||||||
|
stack_info = portainerManager.get_stack_by_name(app_id,endpointId)
|
||||||
|
if stack_info is None:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"{app_id} Not Found"
|
||||||
|
)
|
||||||
|
# Check the app is active
|
||||||
|
stack_status = stack_info.get("Status",None)
|
||||||
|
if stack_status == 2:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"{app_id} is inactive, can not create proxy,you can redeploy it"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check the domain_names
|
||||||
|
check_domain_names(domain_names)
|
||||||
|
|
||||||
|
# Get the forward port
|
||||||
|
stack_env = self.get_app_by_id(app_id,endpointId).env
|
||||||
|
if stack_env:
|
||||||
|
for item in stack_env:
|
||||||
|
key, value = item.split("=", 1)
|
||||||
|
if key == "APP_HTTP_PORT":
|
||||||
|
forward_port = value
|
||||||
|
break
|
||||||
|
# Create proxy
|
||||||
|
if forward_port:
|
||||||
|
proxy_host = proxyManager.create_proxy_by_app(domain_names,app_id,forward_port)
|
||||||
|
if proxy_host:
|
||||||
|
return ProxyHost(
|
||||||
|
proxy_id=proxy_host.get("id"),
|
||||||
|
domain_names=proxy_host.get("domain_names"),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise CustomException()
|
||||||
|
else:
|
||||||
|
raise CustomException()
|
||||||
|
else:
|
||||||
|
raise CustomException()
|
||||||
|
|
||||||
|
def remove_proxy_by_app(self,app_id:str,endpointId:int = None):
|
||||||
|
proxyManager = ProxyManager()
|
||||||
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
|
# Check the endpointId is exists.
|
||||||
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
|
# Check the app_id is exists
|
||||||
|
stack_info = portainerManager.get_stack_by_name(app_id,endpointId)
|
||||||
|
if stack_info is None:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"{app_id} Not Found"
|
||||||
|
)
|
||||||
|
|
||||||
|
domain_names = proxyManager.get_proxy_host_by_app(app_id)
|
||||||
|
if not domain_names:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"{app_id} is not exists proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Remove proxy
|
||||||
|
proxyManager.remove_proxy_host_by_app(app_id)
|
||||||
|
|
||||||
|
def remove_proxy_by_id(self,proxy_id:int):
|
||||||
|
# Check the proxy id is exists
|
||||||
|
host = ProxyManager().get_proxy_host_by_id(proxy_id)
|
||||||
|
if host is None:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"Proxy ID:{proxy_id} Not Found"
|
||||||
|
)
|
||||||
|
ProxyManager().remove_proxy_host_by_id(proxy_id)
|
||||||
|
|
||||||
|
def update_proxy_by_app(self,app_id:str,proxyHost:ProxyHost,endpointId:int = None):
|
||||||
|
proxyManager = ProxyManager()
|
||||||
|
portainerManager = PortainerManager()
|
||||||
|
|
||||||
|
# Check the endpointId is exists.
|
||||||
|
endpointId = check_endpointId(endpointId, portainerManager)
|
||||||
|
|
||||||
|
# Check the app_id is exists
|
||||||
|
stack_info = portainerManager.get_stack_by_name(app_id,endpointId)
|
||||||
|
if stack_info is None:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"{app_id} Not Found"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check the proxy id is exists
|
||||||
|
host = proxyManager.get_proxy_host_by_id(proxyHost.proxy_id)
|
||||||
|
if host is None:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"Proxy ID:{proxyHost.proxy_id} Not Found"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check the domain_names
|
||||||
|
|
||||||
|
# Update proxy
|
||||||
|
proxy_host = proxyManager.update_proxy_by_app(
|
||||||
|
proxyHost.proxy_id,
|
||||||
|
proxyHost.domain_names,
|
||||||
|
host.get("forward_host"),
|
||||||
|
host.get("forward_port"),
|
||||||
|
host.get("advanced_config"),
|
||||||
|
host.get("forward_scheme")
|
||||||
|
)
|
||||||
|
|
||||||
|
if proxy_host:
|
||||||
|
return ProxyHost(
|
||||||
|
proxy_id=proxy_host.get("id"),
|
||||||
|
domain_names=proxy_host.get("domain_names"),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
raise CustomException()
|
||||||
with open(f"{library_path}/{app_name}/variables.json", "r") as f:
|
|
||||||
variables = json.load(f)
|
|
||||||
community_editions = [d for d in variables["edition"] if d["dist"] == "community"]
|
|
||||||
if not any(
|
|
||||||
app_version in d["version"] for d in community_editions
|
|
||||||
):
|
|
||||||
logger.error(f"When install app:{app_name}, the app version:{app_version} is not exists in docker library")
|
|
||||||
raise CustomException(
|
|
||||||
status_code=400,
|
|
||||||
message="Invalid Request",
|
|
||||||
details=f"app_version:{app_version} not supported",
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_appId(self,app_id:str,endpointId:int,giteaManager:GiteaManager,portainerManager:PortainerManager):
|
|
||||||
"""
|
|
||||||
Check the app_id is exists in gitea and portainer
|
|
||||||
|
|
||||||
Args:
|
|
||||||
app_id (str): App Id
|
|
||||||
endpointId (int): Endpoint Id
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
CustomException: If the app_id is exists in gitea or portainer
|
|
||||||
"""
|
|
||||||
# validate the app_id is exists in gitea
|
|
||||||
is_repo_exists = giteaManager.check_repo_exists(app_id)
|
|
||||||
if is_repo_exists:
|
|
||||||
logger.error(f"When install app,the app_id:{{app_id}} is exists in gitea")
|
|
||||||
raise CustomException(
|
|
||||||
status_code=400,
|
|
||||||
message="Invalid Request",
|
|
||||||
details=f"App_id:{app_id} is exists in gitea"
|
|
||||||
)
|
|
||||||
|
|
||||||
# validate the app_id is exists in portainer
|
|
||||||
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
|
||||||
if is_stack_exists:
|
|
||||||
logger.error(f"When install app, the app_id:{app_id} is exists in portainer")
|
|
||||||
raise CustomException(
|
|
||||||
status_code=400,
|
|
||||||
message="Invalid Request",
|
|
||||||
details=f"app_id:{app_id} is exists in portainer"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_domain_names(self,domain_names:list[str]):
|
|
||||||
"""
|
|
||||||
Check the domain_names is exists in proxy
|
|
||||||
|
|
||||||
Args:
|
|
||||||
domain_names (list[str]): Domain Names
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
CustomException: If the domain_names is not exists in proxy
|
|
||||||
"""
|
|
||||||
ProxyManager().check_proxy_host_exists(domain_names)
|
|
||||||
|
|
||||||
def _init_local_repo_and_push_to_remote(self,local_path:str,repo_url:str):
|
def _init_local_repo_and_push_to_remote(self,local_path:str,repo_url:str):
|
||||||
"""
|
"""
|
||||||
|
@ -653,27 +738,4 @@ class AppManger:
|
||||||
logger.error(f"Init local repo and push to remote repo error:{e}")
|
logger.error(f"Init local repo and push to remote repo error:{e}")
|
||||||
raise CustomException()
|
raise CustomException()
|
||||||
|
|
||||||
def _check_endpointId(self, endpointId, portainerManager):
|
|
||||||
"""
|
|
||||||
Check the endpointId is exists
|
|
||||||
|
|
||||||
Args:
|
|
||||||
endpointId ([type]): [description]
|
|
||||||
portainerManager ([type]): [description]
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
CustomException: If the endpointId is not exists
|
|
||||||
"""
|
|
||||||
if endpointId is None:
|
|
||||||
# Get the local endpointId
|
|
||||||
endpointId = portainerManager.get_local_endpoint_id()
|
|
||||||
else :
|
|
||||||
# validate the endpointId is exists
|
|
||||||
is_endpointId_exists = portainerManager.check_endpoint_exists(endpointId)
|
|
||||||
if not is_endpointId_exists:
|
|
||||||
raise CustomException(
|
|
||||||
status_code=400,
|
|
||||||
message="Invalid Request",
|
|
||||||
details="EndpointId Not Found"
|
|
||||||
)
|
|
||||||
return endpointId
|
|
108
appmanage_new/src/services/common_check.py
Normal file
108
appmanage_new/src/services/common_check.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from src.core.logger import logger
|
||||||
|
from src.core.exception import CustomException
|
||||||
|
from src.services.gitea_manager import GiteaManager
|
||||||
|
from src.services.portainer_manager import PortainerManager
|
||||||
|
from src.services.proxy_manager import ProxyManager
|
||||||
|
|
||||||
|
def check_appName_and_appVersion(app_name:str, app_version:str,library_path:str):
|
||||||
|
"""
|
||||||
|
Check the app_name and app_version is exists in docker library
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app_name (str): App Name
|
||||||
|
app_version (str): App Version
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CustomException: If the app_name or app_version is not exists in docker library
|
||||||
|
"""
|
||||||
|
if not os.path.exists(f"{library_path}/{app_name}"):
|
||||||
|
logger.error(f"When install app:{app_name}, the app is not exists in docker library")
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"app_name:{app_name} not supported",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
|
||||||
|
with open(f"{library_path}/{app_name}/variables.json", "r") as f:
|
||||||
|
variables = json.load(f)
|
||||||
|
community_editions = [d for d in variables["edition"] if d["dist"] == "community"]
|
||||||
|
if not any(
|
||||||
|
app_version in d["version"] for d in community_editions
|
||||||
|
):
|
||||||
|
logger.error(f"When install app:{app_name}, the app version:{app_version} is not exists in docker library")
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"app_version:{app_version} not supported",
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_appId(app_id:str,endpointId:int,giteaManager:GiteaManager,portainerManager:PortainerManager):
|
||||||
|
"""
|
||||||
|
Check the app_id is exists in gitea and portainer
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app_id (str): App Id
|
||||||
|
endpointId (int): Endpoint Id
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CustomException: If the app_id is exists in gitea or portainer
|
||||||
|
"""
|
||||||
|
# validate the app_id is exists in gitea
|
||||||
|
is_repo_exists = giteaManager.check_repo_exists(app_id)
|
||||||
|
if is_repo_exists:
|
||||||
|
logger.error(f"When install app,the app_id:{{app_id}} is exists in gitea")
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"App_id:{app_id} is exists in gitea"
|
||||||
|
)
|
||||||
|
|
||||||
|
# validate the app_id is exists in portainer
|
||||||
|
is_stack_exists = portainerManager.check_stack_exists(app_id,endpointId)
|
||||||
|
if is_stack_exists:
|
||||||
|
logger.error(f"When install app, the app_id:{app_id} is exists in portainer")
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details=f"app_id:{app_id} is exists in portainer"
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_domain_names(domain_names:list[str]):
|
||||||
|
"""
|
||||||
|
Check the domain_names is exists in proxy
|
||||||
|
|
||||||
|
Args:
|
||||||
|
domain_names (list[str]): Domain Names
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CustomException: If the domain_names is not exists in proxy
|
||||||
|
"""
|
||||||
|
ProxyManager().check_proxy_host_exists(domain_names)
|
||||||
|
|
||||||
|
def check_endpointId(endpointId, portainerManager):
|
||||||
|
"""
|
||||||
|
Check the endpointId is exists
|
||||||
|
|
||||||
|
Args:
|
||||||
|
endpointId ([type]): [description]
|
||||||
|
portainerManager ([type]): [description]
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
CustomException: If the endpointId is not exists
|
||||||
|
"""
|
||||||
|
if endpointId is None:
|
||||||
|
# Get the local endpointId
|
||||||
|
endpointId = portainerManager.get_local_endpoint_id()
|
||||||
|
else :
|
||||||
|
# validate the endpointId is exists
|
||||||
|
is_endpointId_exists = portainerManager.check_endpoint_exists(endpointId)
|
||||||
|
if not is_endpointId_exists:
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message="Invalid Request",
|
||||||
|
details="EndpointId Not Found"
|
||||||
|
)
|
||||||
|
return endpointId
|
|
@ -1,13 +1,12 @@
|
||||||
|
import json
|
||||||
import time
|
import time
|
||||||
import jwt
|
import jwt
|
||||||
import keyring
|
import keyring
|
||||||
import json
|
|
||||||
from src.core.config import ConfigManager
|
from src.core.config import ConfigManager
|
||||||
from src.core.exception import CustomException
|
from src.core.exception import CustomException
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
from src.external.nginx_proxy_manager_api import NginxProxyManagerAPI
|
from src.external.nginx_proxy_manager_api import NginxProxyManagerAPI
|
||||||
|
|
||||||
|
|
||||||
class ProxyManager:
|
class ProxyManager:
|
||||||
"""
|
"""
|
||||||
Proxy Manager
|
Proxy Manager
|
||||||
|
@ -87,14 +86,14 @@ class ProxyManager:
|
||||||
if matching_domains:
|
if matching_domains:
|
||||||
raise CustomException(
|
raise CustomException(
|
||||||
status_code=400,
|
status_code=400,
|
||||||
message=f"Proxy Host Already Used",
|
message=f"Invalid Request",
|
||||||
details=f"matching_domains:{matching_domains} already used"
|
details=f"{matching_domains} already used"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.error(f"Check proxy host:{domain_names} exists error:{response.status_code}:{response.text}")
|
logger.error(f"Check proxy host:{domain_names} exists error:{response.status_code}:{response.text}")
|
||||||
raise CustomException()
|
raise CustomException()
|
||||||
|
|
||||||
def create_proxy_for_app(self,domain_names: list[str],forward_host: str,forward_port: int,advanced_config: str = "",forward_scheme: str = "http"):
|
def create_proxy_by_app(self,domain_names: list[str],forward_host: str,forward_port: int,advanced_config: str = "",forward_scheme: str = "http"):
|
||||||
response = self.nginx.create_proxy_host(
|
response = self.nginx.create_proxy_host(
|
||||||
domain_names=domain_names,
|
domain_names=domain_names,
|
||||||
forward_scheme=forward_scheme,
|
forward_scheme=forward_scheme,
|
||||||
|
@ -105,18 +104,30 @@ class ProxyManager:
|
||||||
if response.status_code != 201:
|
if response.status_code != 201:
|
||||||
logger.error(f"Create proxy for app:{forward_host} error:{response.status_code}:{response.text}")
|
logger.error(f"Create proxy for app:{forward_host} error:{response.status_code}:{response.text}")
|
||||||
raise CustomException()
|
raise CustomException()
|
||||||
|
else:
|
||||||
|
return response.json()
|
||||||
|
|
||||||
def update_proxy_for_app(self,domain_names: list[str],forward_host: str,forward_port: int,advanced_config: str = "",forward_scheme: str = "http"):
|
def update_proxy_by_app(self,proxy_id:int,domain_names: list[str],forward_host: str,forward_port: int,advanced_config: str = "",forward_scheme: str = "http"):
|
||||||
response = self.nginx.update_proxy_host(
|
response = self.nginx.update_proxy_host(
|
||||||
|
proxy_id=proxy_id,
|
||||||
domain_names=domain_names,
|
domain_names=domain_names,
|
||||||
forward_scheme=forward_scheme,
|
forward_scheme=forward_scheme,
|
||||||
forward_host=forward_host,
|
forward_host=forward_host,
|
||||||
forward_port=forward_port,
|
forward_port=forward_port,
|
||||||
advanced_config=advanced_config,
|
advanced_config=advanced_config,
|
||||||
)
|
)
|
||||||
if response.status_code != 200:
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
elif response.status_code == 500:
|
||||||
logger.error(f"Update proxy for app:{forward_host} error:{response.status_code}:{response.text}")
|
logger.error(f"Update proxy for app:{forward_host} error:{response.status_code}:{response.text}")
|
||||||
raise CustomException()
|
raise CustomException()
|
||||||
|
else:
|
||||||
|
logger.error(f"Update proxy for app:{forward_host} error:{response.status_code}:{response.text}")
|
||||||
|
raise CustomException(
|
||||||
|
status_code=400,
|
||||||
|
message=f"Invalid Request",
|
||||||
|
details=f"{json.loads(response.text).get('error',{}).get('message')}"
|
||||||
|
)
|
||||||
|
|
||||||
def get_proxy_host_by_app(self,app_id:str):
|
def get_proxy_host_by_app(self,app_id:str):
|
||||||
response = self.nginx.get_proxy_hosts()
|
response = self.nginx.get_proxy_hosts()
|
||||||
|
@ -134,12 +145,37 @@ class ProxyManager:
|
||||||
else:
|
else:
|
||||||
logger.error(f"Get proxy host by app:{app_id} error:{response.status_code}:{response.text}")
|
logger.error(f"Get proxy host by app:{app_id} error:{response.status_code}:{response.text}")
|
||||||
raise CustomException()
|
raise CustomException()
|
||||||
|
|
||||||
def remove_proxy_host_for_app(self,app_id:str):
|
def remove_proxy_host_by_app(self,app_id:str):
|
||||||
proxy_hosts = self.get_proxy_host_by_app(app_id)
|
proxy_hosts = self.get_proxy_host_by_app(app_id)
|
||||||
if proxy_hosts:
|
if proxy_hosts:
|
||||||
for proxy_host in proxy_hosts:
|
for proxy_host in proxy_hosts:
|
||||||
response = self.nginx.delete_proxy_host(proxy_host.get("proxy_id"))
|
response = self.nginx.delete_proxy_host(proxy_host.get("proxy_id"))
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
logger.error(f"Remove proxy host:{proxy_host.get('proxy_id')} for app:{app_id} error:{response.status_code}:{response.text}")
|
logger.error(f"Remove proxy host:{proxy_host.get('proxy_id')} for app:{app_id} error:{response.status_code}:{response.text}")
|
||||||
raise CustomException()
|
raise CustomException()
|
||||||
|
|
||||||
|
def remove_proxy_host_by_id(self,proxy_id:int):
|
||||||
|
response = self.nginx.delete_proxy_host(proxy_id)
|
||||||
|
if response.status_code != 200:
|
||||||
|
logger.error(f"Remove proxy host:{proxy_id} error:{response.status_code}:{response.text}")
|
||||||
|
raise CustomException()
|
||||||
|
|
||||||
|
def get_proxy_hosts(self):
|
||||||
|
response = self.nginx.get_proxy_hosts()
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
else:
|
||||||
|
logger.error(f"Get proxy hosts error:{response.status_code}:{response.text}")
|
||||||
|
raise CustomException()
|
||||||
|
|
||||||
|
def get_proxy_host_by_id(self,proxy_id:int):
|
||||||
|
proxy_hosts = self.get_proxy_hosts()
|
||||||
|
try:
|
||||||
|
for proxy_host in proxy_hosts:
|
||||||
|
if proxy_host.get("id") == proxy_id:
|
||||||
|
return proxy_host
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Get proxy host by id:{proxy_id} error:{e}")
|
||||||
|
raise CustomException()
|
|
@ -0,0 +1,34 @@
|
||||||
|
import os
|
||||||
|
import configparser
|
||||||
|
from typing import Dict
|
||||||
|
from src.core.exception import CustomException
|
||||||
|
from src.core.logger import logger
|
||||||
|
from src.schemas.appSettings import AppSettings
|
||||||
|
|
||||||
|
class SettingsManager:
|
||||||
|
def __init__(self):
|
||||||
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
config_dir = os.path.join(script_dir, "../config")
|
||||||
|
|
||||||
|
self.config_file_path = os.path.join(config_dir, "config.ini")
|
||||||
|
self.config_file_path = os.path.abspath(self.config_file_path)
|
||||||
|
|
||||||
|
self.config = configparser.ConfigParser()
|
||||||
|
|
||||||
|
def read_all(self) -> Dict[str, Dict[str, str]]:
|
||||||
|
try:
|
||||||
|
self.config.read(self.config_file_path)
|
||||||
|
data = {s:dict(self.config.items(s)) for s in self.config.sections()}
|
||||||
|
return AppSettings(**data)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
raise CustomException()
|
||||||
|
|
||||||
|
def write_all(self, data: AppSettings):
|
||||||
|
for section, kv in data.model_dump().items():
|
||||||
|
if section not in self.config.sections():
|
||||||
|
self.config.add_section(section)
|
||||||
|
for key, value in kv.items():
|
||||||
|
self.config.set(section, key, value)
|
||||||
|
with open(self.filename, 'w') as configfile:
|
||||||
|
self.config.write(configfile)
|
|
@ -23,7 +23,7 @@ class FileHelper:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with open(file_path, 'r') as f:
|
with open(file_path, 'r') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
return content
|
return content
|
||||||
except:
|
except:
|
||||||
logger.error(f"Failed to read file {file_path}")
|
logger.error(f"Failed to read file {file_path}")
|
||||||
|
|
BIN
appmanage_new/swagger-ui/favicon-16x16.png
Normal file
BIN
appmanage_new/swagger-ui/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
appmanage_new/swagger-ui/favicon-32x32.png
Normal file
BIN
appmanage_new/swagger-ui/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
16
appmanage_new/swagger-ui/index.css
Normal file
16
appmanage_new/swagger-ui/index.css
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
html {
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: -moz-scrollbars-vertical;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
19
appmanage_new/swagger-ui/index.html
Normal file
19
appmanage_new/swagger-ui/index.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!-- HTML for static distribution bundle build -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Swagger UI</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="swagger-ui"></div>
|
||||||
|
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||||
|
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||||
|
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
79
appmanage_new/swagger-ui/oauth2-redirect.html
Normal file
79
appmanage_new/swagger-ui/oauth2-redirect.html
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<title>Swagger UI: OAuth2 Redirect</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
function run () {
|
||||||
|
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||||
|
var sentState = oauth2.state;
|
||||||
|
var redirectUrl = oauth2.redirectUrl;
|
||||||
|
var isValid, qp, arr;
|
||||||
|
|
||||||
|
if (/code|token|error/.test(window.location.hash)) {
|
||||||
|
qp = window.location.hash.substring(1).replace('?', '&');
|
||||||
|
} else {
|
||||||
|
qp = location.search.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
arr = qp.split("&");
|
||||||
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
||||||
|
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||||
|
function (key, value) {
|
||||||
|
return key === "" ? value : decodeURIComponent(value);
|
||||||
|
}
|
||||||
|
) : {};
|
||||||
|
|
||||||
|
isValid = qp.state === sentState;
|
||||||
|
|
||||||
|
if ((
|
||||||
|
oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||||
|
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||||
|
oauth2.auth.schema.get("flow") === "authorization_code"
|
||||||
|
) && !oauth2.auth.code) {
|
||||||
|
if (!isValid) {
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "warning",
|
||||||
|
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qp.code) {
|
||||||
|
delete oauth2.state;
|
||||||
|
oauth2.auth.code = qp.code;
|
||||||
|
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||||
|
} else {
|
||||||
|
let oauthErrorMsg;
|
||||||
|
if (qp.error) {
|
||||||
|
oauthErrorMsg = "["+qp.error+"]: " +
|
||||||
|
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||||
|
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "error",
|
||||||
|
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||||
|
}
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState !== 'loading') {
|
||||||
|
run();
|
||||||
|
} else {
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
20
appmanage_new/swagger-ui/swagger-initializer.js
Normal file
20
appmanage_new/swagger-ui/swagger-initializer.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
window.onload = function() {
|
||||||
|
//<editor-fold desc="Changeable Configuration Block">
|
||||||
|
|
||||||
|
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
||||||
|
window.ui = SwaggerUIBundle({
|
||||||
|
url: "https://petstore.swagger.io/v2/swagger.json",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
deepLinking: true,
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout"
|
||||||
|
});
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
};
|
3
appmanage_new/swagger-ui/swagger-ui-bundle.js
Normal file
3
appmanage_new/swagger-ui/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
appmanage_new/swagger-ui/swagger-ui-bundle.js.map
Normal file
1
appmanage_new/swagger-ui/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
appmanage_new/swagger-ui/swagger-ui-es-bundle-core.js
Normal file
3
appmanage_new/swagger-ui/swagger-ui-es-bundle-core.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
appmanage_new/swagger-ui/swagger-ui-es-bundle.js
Normal file
3
appmanage_new/swagger-ui/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
appmanage_new/swagger-ui/swagger-ui-es-bundle.js.map
Normal file
1
appmanage_new/swagger-ui/swagger-ui-es-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
appmanage_new/swagger-ui/swagger-ui-standalone-preset.js
Normal file
3
appmanage_new/swagger-ui/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
appmanage_new/swagger-ui/swagger-ui.css
Normal file
3
appmanage_new/swagger-ui/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
appmanage_new/swagger-ui/swagger-ui.css.map
Normal file
1
appmanage_new/swagger-ui/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
2
appmanage_new/swagger-ui/swagger-ui.js
Normal file
2
appmanage_new/swagger-ui/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
appmanage_new/swagger-ui/swagger-ui.js.map
Normal file
1
appmanage_new/swagger-ui/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue