Download bt-source/panel/mod/project/docker/runtime/runtimeManage.py from SZFSPC/apple: direct link, hf CLI and curl.
- Browser
- Download file 47.4 kB
-
https://huggingface.co/spaces/SZFSPC/apple/resolve/main/bt-source/panel/mod/project/docker/runtime/runtimeManage.py
- Command line
-
hf download hf://spaces/SZFSPC/apple/bt-source/panel/mod/project/docker/runtime/runtimeManage.py
-
curl -L -o runtimeManage.py https://huggingface.co/spaces/SZFSPC/apple/resolve/main/bt-source/panel/mod/project/docker/runtime/runtimeManage.py
47.4 kB
| # coding: utf-8 | |
| # ------------------------------------------------------------------- | |
| # 宝塔Linux面板 | |
| # ------------------------------------------------------------------- | |
| # Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved. | |
| # ------------------------------------------------------------------- | |
| # Author: wzz <wzz@bt.cn> | |
| # ------------------------------------------------------------------- | |
| # ------------------------------ | |
| # docker模型 - docker runtime 业务类 | |
| # ------------------------------ | |
| import json | |
| import os | |
| import sys | |
| import time | |
| if "/www/server/panel/class" not in sys.path: | |
| sys.path.insert(0, "/www/server/panel/class") | |
| import public | |
| from btdockerModel import dk_public as dp | |
| from mod.project.docker.runtime.base import Runtime | |
| class RuntimeManage(Runtime): | |
| def __init__(self): | |
| super(RuntimeManage, self).__init__() | |
| self.runtime_path = "/www/dk_project/runtime" | |
| self.runtime_templates_path = "{}/templates".format(self.runtime_path) | |
| self.exts_file = "{}/php/exts.json".format(self.runtime_templates_path) | |
| self.versions_file = "{}/versions.json".format(self.runtime_templates_path) | |
| self.service_templates_path = "{}/".format(self.runtime_templates_path) + "{}" | |
| self.runtime_build_path = "{}/build".format(self.runtime_path) | |
| if not os.path.exists(self.runtime_build_path): os.makedirs(self.runtime_build_path, 384, True) | |
| self.php_build_path = "{}/php".format(self.runtime_build_path) | |
| if not os.path.exists(self.php_build_path): os.makedirs(self.php_build_path, 384, True) | |
| self.runtime_run_path = "{}/run".format(self.runtime_path) | |
| self.service_run_path = "{}/".format(self.runtime_run_path) + "{}" | |
| self.site_path = "/www/dk_project/wwwroot" | |
| self.site_path_pl = "/www/dk_project/wwwroot.pl" | |
| if os.path.exists(self.site_path_pl): | |
| self.site_path = public.readFile(self.site_path_pl).strip() | |
| if not os.path.exists(self.site_path): os.makedirs(self.site_path, 384, True) | |
| # 2024/11/1 10:33 下载模板到指定目录 | |
| def download_templates(self): | |
| ''' | |
| @name 下载模板到指定目录 | |
| ''' | |
| if os.path.exists(self.runtime_templates_path): | |
| public.ExecShell("rm -rf {}".format(self.runtime_templates_path)) | |
| app_url = "{}/src/dk_app/runtime/templates.zip".format(public.get_url()) | |
| to_file = '/tmp/templates.zip' | |
| if os.path.exists(to_file): public.ExecShell("rm -f {}".format(to_file)) | |
| public.downloadFile(app_url, to_file) | |
| if not os.path.exists(to_file) or os.path.getsize(to_file) < 10: | |
| return public.returnResult(False, msg="模板更新失败!") | |
| public.ExecShell("unzip -o -d {} {}".format(self.runtime_path, to_file)) | |
| return public.returnResult(True, "模板更新成功!") | |
| # 2024/11/1 10:18 检查模板是否存在 | |
| def check_templates(self, get): | |
| ''' | |
| @name 检查模板是否存在 | |
| ''' | |
| get.force_update = int(get.get("force_update", 0)) | |
| if get.force_update == 1: | |
| return self.download_templates() | |
| if not os.path.exists(self.runtime_templates_path): | |
| return self.download_templates() | |
| # 2024/11/1 09:16 构建指定的PHP镜像 | |
| def build_php_image(self, get): | |
| ''' | |
| @name 构建指定的PHP镜像 | |
| ''' | |
| self.service_templates_path = self.service_templates_path.format("php") | |
| self.project_path = "{}/{}".format(self.php_build_path, get.runtime_name) | |
| if not os.path.exists(self.project_path): os.makedirs(self.project_path, 384, True) | |
| self.compose_file = "{}/docker-compose.yml".format(self.project_path) | |
| self.build_log = "{}/build.log".format(self.project_path) | |
| public.ExecShell("rm -f {}".format(self.build_log)) | |
| if get.runtime_version.startswith("8."): | |
| public.ExecShell("\cp -r {}/php8/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php8/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="PHP8模板不存在") | |
| elif get.runtime_version.startswith("7."): | |
| if get.runtime_version in ("7.0", "7.1"): | |
| public.ExecShell("\cp -r {}/php70/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php70/.env {}/".format(self.service_templates_path, self.project_path)) | |
| else: | |
| public.ExecShell("\cp -r {}/php72/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php72/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="PHP7模板不存在") | |
| elif get.runtime_version.startswith("5."): | |
| public.ExecShell("\cp -r {}/php5/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php5/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="PHP5模板不存在") | |
| else: | |
| return public.returnResult(False, msg="PHP版本: 【{}】错误".format(get.runtime_version)) | |
| exts = get.exts.replace(",", " ") | |
| public.ExecShell("sed -i 's/^VERSION=.*/VERSION={}/' {}/.env".format(get.runtime_version, self.project_path)) | |
| public.ExecShell("sed -i 's/^REPO_URL=.*/REPO_URL={}/' {}/.env".format(get.repo_url, self.project_path)) | |
| public.ExecShell("sed -i 's/^EXTS=.*/EXTS=\"{}\"/' {}/.env".format(exts, self.project_path)) | |
| public.ExecShell("sed -i 's/btphp:/{}:/g' {}/.env".format(get.runtime_name, self.project_path)) | |
| public.ExecShell("sed -i 's/btphp:/{}/g' {}/*.yml".format(get.runtime_name, self.project_path)) | |
| cmd = ("nohup echo '正在构建【{runtime_name}】,可能需要等待1-5分钟以上...' >> {build_log};" | |
| "docker-compose -f {compose_file} build --progress=plain >> {build_log} 2>&1 && " | |
| "echo 'bt_successful' >> {build_log} || echo 'bt_failed' >> {build_log} &" | |
| .format( | |
| runtime_name=get.runtime_name, | |
| build_log=self.build_log, | |
| compose_file=self.compose_file, | |
| )) | |
| import subprocess | |
| subprocess.Popen(cmd, shell=True) | |
| public.set_module_logs('build_runtime_php', 'runtime_buildphp_{}'.format(get.runtime_version), 1) | |
| # 2024/11/6 16:01 运行指定php项目 | |
| def run_php_project(self, get): | |
| ''' | |
| @name 运行指定php项目 | |
| ''' | |
| self.service_templates_path = self.service_templates_path.format("php") | |
| run_php_templates_path = os.path.join(self.service_templates_path, "runphp") | |
| self.service_run_path = self.service_run_path.format("php") | |
| if not os.path.exists(self.service_run_path): os.makedirs(self.service_run_path, 384, True) | |
| get.project_name = get.site_name.replace(".", "_") | |
| self.project_path = "{}/{}".format(self.service_run_path, get.project_name) | |
| if not os.path.exists(self.project_path): os.makedirs(self.project_path, 384, True) | |
| self.compose_file = "{}/docker-compose.yml".format(self.project_path) | |
| self.create_log = "{}/create.log".format(self.project_path) | |
| get.php_version = get.name.split(":")[1] | |
| get.project_path = self.project_path | |
| if get.php_version.startswith("8."): | |
| public.ExecShell("\cp -r {}/php8/* {}/".format(run_php_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php8/.env {}/".format(run_php_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="PHP8模板不存在") | |
| elif get.php_version.startswith("7."): | |
| if get.php_version in ("7.0", "7.1"): | |
| public.ExecShell("\cp -r {}/php70/* {}/".format(run_php_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php70/.env {}/".format(run_php_templates_path, self.project_path)) | |
| else: | |
| public.ExecShell("\cp -r {}/php72/* {}/".format(run_php_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php72/.env {}/".format(run_php_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="PHP7模板不存在") | |
| elif get.php_version.startswith("5."): | |
| public.ExecShell("\cp -r {}/php5/* {}/".format(run_php_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/php5/.env {}/".format(run_php_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="PHP5模板不存在") | |
| else: | |
| return public.returnResult(False, msg="PHP版本: 【{}】错误".format(get.php_version)) | |
| public.ExecShell("sed -i 's/^IMAGE_NAME=.*/IMAGE_NAME={}/' {}/.env".format(get.name, self.project_path)) | |
| public.ExecShell( | |
| "sed -i 's/^WEB_HTTP_PORT=.*/WEB_HTTP_PORT={}/' {}/.env".format(get.runtime_port, self.project_path)) | |
| public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(get.site_path, self.project_path)) | |
| cmd = ("nohup echo '正在创建【{site_name}】,可能需要等待1-5分钟以上...' >> {build_log};" | |
| "docker-compose -f {compose_file} up -d >> {build_log} 2>&1 && " | |
| "echo 'bt_successful' >> {build_log} || echo 'bt_failed' >> {build_log} &" | |
| .format( | |
| site_name=get.site_name, | |
| build_log=self.create_log, | |
| compose_file=self.compose_file, | |
| )) | |
| import subprocess | |
| subprocess.Popen(cmd, shell=True) | |
| # public.set_module_logs('runtime_runphp_{}'.format(get.version), 'run_php', 1) | |
| return public.returnResult() | |
| # 2024/11/1 15:02 运行python项目 | |
| def run_python_project(self, get): | |
| ''' | |
| @name 运行python项目 | |
| ''' | |
| self.service_templates_path = self.service_templates_path.format("python") | |
| self.service_run_path = self.service_run_path.format("python") | |
| if not os.path.exists(self.service_run_path): os.makedirs(self.service_run_path, 384, True) | |
| self.project_path = "{}/{}".format(self.service_run_path, get.runtime_name) | |
| if not os.path.exists(self.project_path): os.makedirs(self.project_path, 384, True) | |
| self.compose_file = "{}/docker-compose.yml".format(self.project_path) | |
| self.create_log = "{}/create.log".format(self.project_path) | |
| public.ExecShell("rm -f {}".format(self.create_log)) | |
| public.ExecShell("\cp -r {}/python3/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/python3/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="Python模板不存在") | |
| public.ExecShell("sed -i 's/^VERSION=.*/VERSION={}/' {}/.env".format(get.runtime_version, self.project_path)) | |
| public.ExecShell("sed -i 's/^REPO_URL=.*/REPO_URL={}/' {}/.env".format(get.repo_url, self.project_path)) | |
| public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(get.site_path, self.project_path)) | |
| public.ExecShell("sed -i 's/btpython:/{}/g' {}/*.yml".format(get.runtime_name, self.project_path)) | |
| port_conf = self.handle_ports(get.ports) | |
| public.ExecShell("sed -i 's,:BTPORT_CONF:,{},g' {}/*.yml".format(port_conf, self.project_path)) | |
| try: | |
| import yaml | |
| import glob | |
| yaml_files = glob.glob("{}/*.yml".format(self.project_path)) | |
| for yf in yaml_files: | |
| data = public.readFile(yf) | |
| if data: | |
| data = yaml.safe_load(data) | |
| data["services"]["{}-python3".format(get.runtime_name)]["environment"][1] = "COMMAND={}".format(get.command) | |
| public.writeFile(yf, yaml.dump(data)) | |
| except: | |
| public.ExecShell("sed -i 's/:COMMAND:/{}/g' {}/*.yml".format(get.command, self.project_path)) | |
| cmd = ("nohup echo '正在创建【{runtime_name}】,可能需要等待1-5分钟以上...' >> {build_log};" | |
| "docker-compose -f {compose_file} up -d >> {build_log} 2>&1 && " | |
| "echo 'bt_successful' >> {build_log} || echo 'bt_failed' >> {build_log} &" | |
| .format( | |
| runtime_name=get.runtime_name, | |
| build_log=self.create_log, | |
| compose_file=self.compose_file, | |
| )) | |
| import subprocess | |
| subprocess.Popen(cmd, shell=True) | |
| public.set_module_logs('runtime_python', 'runtime_python_{}'.format(get.runtime_version), 1) | |
| # 2024/11/4 14:46 运行golang项目 | |
| def run_go_project(self, get): | |
| ''' | |
| @name 运行golang项目 | |
| ''' | |
| self.service_templates_path = self.service_templates_path.format("go") | |
| self.service_run_path = self.service_run_path.format("go") | |
| if not os.path.exists(self.service_run_path): os.makedirs(self.service_run_path, 384, True) | |
| self.project_path = "{}/{}".format(self.service_run_path, get.runtime_name) | |
| if not os.path.exists(self.project_path): os.makedirs(self.project_path, 384, True) | |
| self.compose_file = "{}/docker-compose.yml".format(self.project_path) | |
| self.create_log = "{}/create.log".format(self.project_path) | |
| public.ExecShell("rm -f {}".format(self.create_log)) | |
| public.ExecShell("\cp -r {}/go/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/go/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="Golang模板不存在") | |
| public.ExecShell("sed -i 's/^VERSION=.*/VERSION={}/' {}/.env".format(get.runtime_version, self.project_path)) | |
| public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(get.site_path, self.project_path)) | |
| public.ExecShell("sed -i 's/btgo:/{}/g' {}/*.yml".format(get.runtime_name, self.project_path)) | |
| port_conf = self.handle_ports(get.ports) | |
| public.ExecShell("sed -i 's,:BTPORT_CONF:,{},g' {}/*.yml".format(port_conf, self.project_path)) | |
| try: | |
| import yaml | |
| import glob | |
| yaml_files = glob.glob("{}/*.yml".format(self.project_path)) | |
| for yf in yaml_files: | |
| data = public.readFile(yf) | |
| if data: | |
| data = yaml.safe_load(data) | |
| data["services"]["{}-golang".format(get.runtime_name)]["environment"][0] = "COMMAND={}".format(get.command) | |
| public.writeFile(yf, yaml.dump(data)) | |
| except: | |
| public.ExecShell("sed -i 's/:COMMAND:/{}/g' {}/*.yml".format(get.command, self.project_path)) | |
| cmd = ("nohup echo '正在创建【{runtime_name}】,可能需要等待1-5分钟以上...' >> {build_log};" | |
| "docker-compose -f {compose_file} up -d >> {build_log} 2>&1 && " | |
| "echo 'bt_successful' >> {build_log} || echo 'bt_failed' >> {build_log} &" | |
| .format( | |
| runtime_name=get.runtime_name, | |
| build_log=self.create_log, | |
| compose_file=self.compose_file, | |
| )) | |
| import subprocess | |
| subprocess.Popen(cmd, shell=True) | |
| public.set_module_logs('runtime_go', 'runtime_go_{}'.format(get.runtime_version), 1) | |
| # 2024/11/4 14:54 运行java项目 | |
| def run_java_project(self, get): | |
| ''' | |
| @name 运行java项目 | |
| ''' | |
| self.service_templates_path = self.service_templates_path.format("java") | |
| self.service_run_path = self.service_run_path.format("java") | |
| if not os.path.exists(self.service_run_path): os.makedirs(self.service_run_path, 384, True) | |
| self.project_path = "{}/{}".format(self.service_run_path, get.runtime_name) | |
| if not os.path.exists(self.project_path): os.makedirs(self.project_path, 384, True) | |
| self.compose_file = "{}/docker-compose.yml".format(self.project_path) | |
| self.create_log = "{}/create.log".format(self.project_path) | |
| public.ExecShell("rm -f {}".format(self.create_log)) | |
| public.ExecShell("\cp -r {}/java/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/java/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="Java模板不存在") | |
| public.ExecShell("sed -i 's/^VERSION=.*/VERSION={}/' {}/.env".format(get.runtime_version, self.project_path)) | |
| public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(get.site_path, self.project_path)) | |
| public.ExecShell("sed -i 's/btjava:/{}/g' {}/*.yml".format(get.runtime_name, self.project_path)) | |
| port_conf = self.handle_ports(get.ports) | |
| public.ExecShell("sed -i 's,:BTPORT_CONF:,{},g' {}/*.yml".format(port_conf, self.project_path)) | |
| try: | |
| import yaml | |
| import glob | |
| yaml_files = glob.glob("{}/*.yml".format(self.project_path)) | |
| for yf in yaml_files: | |
| data = public.readFile(yf) | |
| if data: | |
| data = yaml.safe_load(data) | |
| data["services"]["{}-java".format(get.runtime_name)]["environment"][0] = "COMMAND={}".format(get.command) | |
| public.writeFile(yf, yaml.dump(data)) | |
| except: | |
| public.ExecShell("sed -i 's/:COMMAND:/{}/g' {}/*.yml".format(get.command, self.project_path)) | |
| cmd = ("nohup echo '正在创建【{runtime_name}】,可能需要等待1-5分钟以上...' >> {build_log};" | |
| "docker-compose -f {compose_file} up -d >> {build_log} 2>&1 && " | |
| "echo 'bt_successful' >> {build_log} || echo 'bt_failed' >> {build_log} &" | |
| .format( | |
| runtime_name=get.runtime_name, | |
| build_log=self.create_log, | |
| compose_file=self.compose_file, | |
| )) | |
| import subprocess | |
| subprocess.Popen(cmd, shell=True) | |
| public.set_module_logs('runtime_java', 'runtime_java_{}'.format(get.runtime_version), 1) | |
| def run_nodejs_project(self, get): | |
| ''' | |
| @name 运行nodejs项目 | |
| ''' | |
| self.service_templates_path = self.service_templates_path.format("nodejs") | |
| self.service_run_path = self.service_run_path.format("nodejs") | |
| if not os.path.exists(self.service_run_path): os.makedirs(self.service_run_path, 384, True) | |
| self.project_path = "{}/{}".format(self.service_run_path, get.runtime_name) | |
| if not os.path.exists(self.project_path): os.makedirs(self.project_path, 384, True) | |
| self.compose_file = "{}/docker-compose.yml".format(self.project_path) | |
| self.create_log = "{}/create.log".format(self.project_path) | |
| public.ExecShell("rm -f {}".format(self.create_log)) | |
| public.ExecShell("\cp -r {}/nodejs/* {}/".format(self.service_templates_path, self.project_path)) | |
| public.ExecShell("\cp -r {}/nodejs/.env {}/".format(self.service_templates_path, self.project_path)) | |
| if not os.path.exists(self.compose_file): | |
| return public.returnResult(False, msg="Nodejs模板不存在") | |
| repo_url = '"{}"'.format(get.repo_url.replace("/","\\/")) | |
| public.ExecShell("sed -i 's/^VERSION=.*/VERSION={}/' {}/.env".format(get.runtime_version, self.project_path)) | |
| public.ExecShell("sed -i 's/^REPO_URL=.*/REPO_URL={}/' {}/.env".format(repo_url, self.project_path)) | |
| public.ExecShell("sed -i 's,^SITE_PATH=.*,SITE_PATH={},' {}/.env".format(get.site_path, self.project_path)) | |
| public.ExecShell("sed -i 's/btnodejs:/{}/g' {}/*.yml".format(get.runtime_name, self.project_path)) | |
| port_conf = self.handle_ports(get.ports) | |
| public.ExecShell("sed -i 's,:BTPORT_CONF:,{},g' {}/*.yml".format(port_conf, self.project_path)) | |
| public.ExecShell("sed -i 's/:COMMAND:/{}/g' {}/*.yml".format(get.command, self.project_path)) | |
| cmd = ("nohup echo '正在创建【{runtime_name}】,可能需要等待1-5分钟以上...' >> {build_log};" | |
| "docker-compose -f {compose_file} up -d >> {build_log} 2>&1 && " | |
| "echo 'bt_successful' >> {build_log} || echo 'bt_failed' >> {build_log} &" | |
| .format( | |
| runtime_name=get.runtime_name, | |
| build_log=self.create_log, | |
| compose_file=self.compose_file, | |
| )) | |
| import subprocess | |
| subprocess.Popen(cmd, shell=True) | |
| public.set_module_logs('runtime_nodejs', 'runtime_nodejs_{}'.format(get.runtime_version), 1) | |
| # 2024/11/1 15:29 处理端口配置信息 | |
| def handle_ports(self, ports): | |
| ''' | |
| @name 处理端口配置信息 | |
| ''' | |
| # {"2362/tcp":"6236","646/tcp":["127.0.0.1","734"]} | |
| ports = json.loads(ports) | |
| # 构造 - ${HOST_IP}:${WEB_HTTP_PORT}:${APP_PORT} 用在docker-compose.yml中 | |
| ports_str = "" | |
| for port in ports: | |
| if ports_str != "" and not "\n" in ports_str: | |
| ports_str += "\\n" | |
| ports_str += " - " | |
| if isinstance(ports[port], list): | |
| if "tcp/udp" in port: | |
| ports_str += "127.0.0.1:{}:{}".format(ports[port][1], port.split("/")[0]) | |
| else: | |
| ports_str += "127.0.0.1:{}:{}".format(ports[port][1], port) | |
| else: | |
| if "tcp/udp" in port: | |
| ports_str += "0.0.0.0:{}:{}".format(ports[port], port.split("/")[0]) | |
| else: | |
| ports_str += "0.0.0.0:{}:{}".format(ports[port], port) | |
| return ports_str | |
| # 2024/11/20 10:11 添加默认的PHP扩展模板 | |
| def add_default_php_ext_template(self): | |
| ''' | |
| @name 添加默认的PHP扩展模板 | |
| ''' | |
| ext_templates = { | |
| "wordpress": "exif,igbinary,imagick,intl,apcu,memcached,opcache,shmop,mysqli,pdo_mysql,gd", | |
| "flarum": "curl,gd,pdo_mysql,mysqli,bz2,exif,yaf,imap", | |
| "苹果CMS-V10": "mysqli,pdo_mysql,zip,gd,redis,memcache,memcached", | |
| "SeaCMS": "mysqli,pdo_mysql,gd,curl", | |
| } | |
| top_php = "8.3" | |
| if os.path.exists(self.versions_file): | |
| try: | |
| top_php = json.loads(public.readFile(self.versions_file))["php"][0] | |
| except: | |
| pass | |
| for name in ext_templates.keys(): | |
| args = public.dict_obj() | |
| args.exts = ext_templates[name] | |
| args.name = "{}_{}".format(name, top_php) | |
| args.version = top_php | |
| self.create_php_ext_template(args) | |
| args.name = "{}_7.4".format(name) | |
| args.version = "7.4" | |
| self.create_php_ext_template(args) | |
| # 2024/10/31 10:29 获取指定运行环境列表 | |
| def get_runtime_list(self, get): | |
| ''' | |
| @name 获取指定运行环境列表 | |
| ''' | |
| get.runtime_type = get.get("runtime_type", "all") | |
| get.p = get.get("p", 1) | |
| get.row = get.get("row", 10) | |
| if not os.path.exists(self.exts_file): | |
| self.check_templates(get) | |
| from mod.project.docker.app.base import App | |
| cbnet = App().check_baota_net() | |
| if not cbnet["status"]: return cbnet | |
| if get.runtime_type == "all": | |
| all_runtime_list = dp.sql('runtime').order('addtime desc').select() | |
| else: | |
| all_runtime_list = dp.sql('runtime').where('type=?', get.runtime_type).order('addtime desc').select() | |
| all_runtime_list = self.check_runtime_status(all_runtime_list) | |
| all_runtime_list = self.get_page(all_runtime_list, get) | |
| return self.pageResult(data=all_runtime_list["data"], page=all_runtime_list["page"]) | |
| # 2024/11/1 11:40 检查运行环境的状态 | |
| def check_runtime_status(self, all_runtime_list): | |
| ''' | |
| @name 检查运行环境的状态 | |
| ''' | |
| from btdockerModel.dockerSock import image | |
| sk_image = image.dockerImage() | |
| all_images = sk_image.get_images() | |
| for runtime in all_runtime_list: | |
| runtime["status"] = "abnormal" | |
| if runtime["type"] == "php": | |
| stdout, stderr = public.ExecShell("grep 'bt_successful' {}".format(runtime["log_file"])) | |
| if not stdout: | |
| runtime["status"] = "initializing" | |
| stdout, stderr = public.ExecShell("grep 'bt_failed' {}".format(runtime["log_file"])) | |
| if stdout: | |
| runtime["status"] = "abnormal" | |
| continue | |
| # 检查是否存在 runtime["name"]:runtime["version"]的镜像 | |
| for image in all_images: | |
| if "{}:{}".format(runtime["name"], runtime["version"]) in image["RepoTags"]: | |
| runtime["status"] = "normal" | |
| break | |
| elif runtime["type"] in ["java", "go", "python","nodejs"]: | |
| runtime["status"] = "running" | |
| # 检查是否存在运行中的容器 | |
| stdout, stderr = public.ExecShell( | |
| "docker-compose -f {} ps --format ".format(runtime["compose"]) + "\"{{.State}}\"") | |
| runtime["status"] = stdout.strip() if stdout.strip() else "exited" | |
| return all_runtime_list | |
| # 2024/10/31 10:30 创建指定运行环境 | |
| def create_runtime(self, get): | |
| ''' | |
| @name 创建指定运行环境 | |
| ''' | |
| get.runtime_name = get.get("runtime_name", None) | |
| if get.runtime_name is None: return public.returnResult(False, msg="请传运行环境名称:runtime_name") | |
| get.runtime_type = get.get("runtime_type", None) | |
| if get.runtime_type is None: return public.returnResult(False, msg="请传运行环境类型:runtime_type") | |
| get.runtime_version = get.get("runtime_version", None) | |
| if get.runtime_version is None: return public.returnResult(False, msg="请传运行环境版本:runtime_version") | |
| get.remark = get.get("remark", "") | |
| if get.runtime_type in ["php", "python","nodejs"]: | |
| get.repo_url = get.get("repo_url", None) | |
| if get.repo_url is None: return public.returnResult(False, msg="请传源加速地址:repo_url") | |
| get.exts = get.get("exts", None) | |
| if get.runtime_type in ["java", "go", "python","nodejs"]: | |
| get.site_path = get.get("site_path", None) | |
| if get.site_path is None: return public.returnResult(False, msg="请传站点路径:site_path") | |
| get.command = get.get("command", None) | |
| if get.command is None: return public.returnResult(False, msg="请传启动命令:command") | |
| get.ports = get.get("ports", None) | |
| if get.ports is None: return public.returnResult(False, msg="请传端口映射:ports") | |
| posts_dict = json.loads(get.ports) | |
| get.ports_dict = {} | |
| for p in posts_dict.keys(): | |
| if type(posts_dict[p]) == list: | |
| get.ports_dict[p] = [{"HostIp": posts_dict[p][0], "HostPort": posts_dict[p][1]}] | |
| else: | |
| get.ports_dict[p] = [{"HostIp": "0.0.0.0", "HostPort": posts_dict[p]}] | |
| find_result = dp.sql("runtime").where("name=? and type=?", (get.runtime_name, get.runtime_type)).find() | |
| if find_result: | |
| return public.returnResult(False, msg="运行环境【{}】已存在,请更换其他名称!".format(get.runtime_name)) | |
| self.check_templates(get) | |
| public.set_module_logs('runtime'.format(get.runtime_version), 'create_runtime', 1) | |
| if get.runtime_type == "php": | |
| self.build_php_image(get) | |
| dp.sql("runtime").insert({ | |
| "name": get.runtime_name, | |
| "type": get.runtime_type, | |
| "version": get.runtime_version, | |
| "repo_url": get.repo_url, | |
| "exts": get.exts, | |
| "addtime": int(time.time()), | |
| "runtime_path": self.project_path, | |
| "compose": self.compose_file, | |
| "log_file": self.build_log, | |
| "remark": public.xssencode2(get.remark) | |
| }) | |
| else: | |
| if get.runtime_type == "python": | |
| self.run_python_project(get) | |
| elif get.runtime_type == "go": | |
| self.run_go_project(get) | |
| elif get.runtime_type == "java": | |
| self.run_java_project(get) | |
| elif get.runtime_type == "nodejs": | |
| self.run_nodejs_project(get) | |
| dp.sql("runtime").insert({ | |
| "name": get.runtime_name, | |
| "type": get.runtime_type, | |
| "version": get.runtime_version, | |
| "repo_url": get.get('repo_url',''), | |
| "path": get.site_path, | |
| "command": get.command, | |
| "ports": json.dumps(get.ports_dict), | |
| "addtime": int(time.time()), | |
| "runtime_path": self.project_path, | |
| "compose": self.compose_file, | |
| "log_file": self.create_log, | |
| "remark": public.xssencode2(get.remark) | |
| }) | |
| return public.returnResult(msg="创建运行环境【{}】成功".format(get.runtime_name)) | |
| # 2024/11/19 11:59 | |
| def remove_image(self, get): | |
| ''' | |
| @name | |
| ''' | |
| image_name = "{}:{}".format(get.runtime_name, get.runtime_version) | |
| stdout, stderr = public.ExecShell("docker ps -a |grep {}".format(image_name)) | |
| if stdout: return False | |
| public.ExecShell("docker image rm -f {}".format(image_name)) | |
| return True | |
| # 2024/10/31 10:33 编辑指定运行环境 | |
| def modify_runtime(self, get): | |
| ''' | |
| @name 编辑指定运行环境 | |
| ''' | |
| get.id = get.get("id", None) | |
| if get.id is None: return public.returnResult(False, msg="请传运行环境ID:id") | |
| get.runtime_name = get.get("runtime_name", None) | |
| if get.runtime_name is None: return public.returnResult(False, msg="请传运行环境名称:runtime_name") | |
| get.runtime_type = get.get("runtime_type", None) | |
| if get.runtime_type is None: return public.returnResult(False, msg="请传运行环境类型:runtime_type") | |
| get.runtime_version = get.get("runtime_version", None) | |
| if get.runtime_version is None: return public.returnResult(False, msg="请传运行环境版本:runtime_version") | |
| get.remark = get.get("remark", "") | |
| if get.runtime_type in ["php", "python"]: | |
| get.repo_url = get.get("repo_url", None) | |
| if get.repo_url is None: return public.returnResult(False, msg="请传代码仓库地址:repo_url") | |
| get.exts = get.get("exts", None) | |
| if get.runtime_type in ["java", "go", "python","nodejs"]: | |
| get.site_path = get.get("site_path", None) | |
| if get.site_path is None: return public.returnResult(False, msg="请传站点路径:site_path") | |
| get.command = get.get("command", None) | |
| if get.command is None: return public.returnResult(False, msg="请传启动命令:command") | |
| get.ports = get.get("ports", None) | |
| if get.ports is None: return public.returnResult(False, msg="请传端口映射:ports") | |
| posts_dict = json.loads(get.ports) | |
| get.ports_dict = {} | |
| for p in posts_dict.keys(): | |
| if type(posts_dict[p]) == list: | |
| get.ports_dict[p] = [{"HostIp": posts_dict[p][0], "HostPort": posts_dict[p][1]}] | |
| else: | |
| get.ports_dict[p] = [{"HostIp": "0.0.0.0", "HostPort": posts_dict[p]}] | |
| find_result = dp.sql("runtime").where("id=? and type=?", (get.id, get.runtime_type)).find() | |
| if not find_result: return public.returnResult(False, msg="运行环境不存在") | |
| if not self.remove_image(get): | |
| return public.returnResult(False, | |
| msg="原删除镜像失败,请手动删除:{} 后再尝试编辑".format(find_result["name"])) | |
| if get.runtime_type == "php": | |
| self.build_php_image(get) | |
| dp.sql("runtime").where("id=? and type=?", (get.id, get.runtime_type)).update({ | |
| "repo_url": get.repo_url, | |
| "exts": get.exts | |
| }) | |
| else: | |
| if get.runtime_type == "python": | |
| self.run_python_project(get) | |
| elif get.runtime_type == "java": | |
| self.run_java_project(get) | |
| elif get.runtime_type == "nodejs": | |
| self.run_nodejs_project(get) | |
| elif get.runtime_type == "go": | |
| self.run_go_project(get) | |
| else: | |
| return public.returnResult(False, msg="不支持的运行环境类型:{}".format(get.runtime_type)) | |
| dp.sql("runtime").where("id=? and type=?", (get.id, get.runtime_type)).update({ | |
| "path": get.site_path, | |
| "repo_url": get.get("repo_url", ""), | |
| "command": get.command, | |
| "ports": json.dumps(get.ports_dict) | |
| }) | |
| return public.returnResult(msg="编辑成功") | |
| # 2024/11/1 14:29 删除指定运行环境 | |
| def delete_runtime(self, get): | |
| ''' | |
| @name 删除指定运行环境 | |
| ''' | |
| get.id = get.get("id", None) | |
| if get.id is None: return public.returnResult(False, msg="请传运行环境ID:id") | |
| find_result = dp.sql("runtime").where("id=?", get.id).find() | |
| if not find_result: return public.returnResult(False, msg="运行环境不存在") | |
| if find_result["type"] == "php": | |
| public.ExecShell("docker-compose -f {} down".format(find_result["compose"])) | |
| public.ExecShell("docker-compose -f {} rm -f".format(find_result["compose"])) | |
| public.ExecShell("docker image rm -f {}:{}".format(find_result["name"], find_result["version"])) | |
| public.ExecShell("rm -rf {}".format(find_result["runtime_path"])) | |
| elif find_result["type"] in ["java", "go", "python"]: | |
| public.ExecShell("docker-compose -f {} down".format(find_result["compose"])) | |
| public.ExecShell("docker-compose -f {} rm -f".format(find_result["compose"])) | |
| public.ExecShell("rm -rf {}".format(find_result["runtime_path"])) | |
| dp.sql("runtime").where("id=?", get.id).delete() | |
| find_result = dp.sql("runtime").where("id=?", get.id).find() | |
| if find_result: return public.returnResult(False, msg="删除失败") | |
| return public.returnResult(msg="删除成功") | |
| # 2024/11/1 14:33 批量删除指定运行环境 | |
| def batch_delete_runtime(self, get): | |
| ''' | |
| @name 批量删除指定运行环境 | |
| ''' | |
| get.ids = get.get("ids", None) | |
| if get.ids is None: return public.returnResult(False, msg="请传运行环境ID:ids") | |
| get.ids = get.ids.split(",") | |
| delete_result = [] | |
| for id in get.ids: | |
| find_result = dp.sql("runtime").where("id=?", id).find() | |
| if not find_result: | |
| delete_result.append({"id": id, "status": False, "msg": "运行环境不存在"}) | |
| continue | |
| if find_result["type"] == "php": | |
| public.ExecShell("docker-compose -f {} down".format(find_result["compose"])) | |
| public.ExecShell("docker-compose -f {} rm -f".format(find_result["compose"])) | |
| public.ExecShell("docker image rm -f {}:{}".format(find_result["name"], find_result["version"])) | |
| public.ExecShell("rm -rf {}".format(find_result["runtime_path"])) | |
| elif find_result["type"] in ["java", "go", "python"]: | |
| public.ExecShell("docker-compose -f {} down".format(find_result["compose"])) | |
| public.ExecShell("docker-compose -f {} rm -f".format(find_result["compose"])) | |
| public.ExecShell("rm -rf {}".format(find_result["runtime_path"])) | |
| dp.sql("runtime").where("id=?", id).delete() | |
| find_result = dp.sql("runtime").where("id=?", id).find() | |
| if find_result: | |
| delete_result.append({"id": id, "status": False, "msg": "删除失败"}) | |
| continue | |
| delete_result.append({"id": id, "status": True, "msg": "删除成功"}) | |
| return public.returnResult(msg="批量删除成功", data=delete_result) | |
| # 2024/10/31 10:30 清理构建缓存 | |
| def build_prune(self, get): | |
| ''' | |
| @name 清理构建缓存 | |
| ''' | |
| from btdockerModel.dockerSock import image | |
| sk_image = image.dockerImage() | |
| sk_image.build_prune() | |
| get.force_update = 1 | |
| self.check_templates(get) | |
| return public.returnResult(msg="清理所有构建缓存成功") | |
| # 2024/10/31 10:33 设置运行环境运行状态(仅java/go/python/nodejs) | |
| def set_runtime_status(self, get): | |
| ''' | |
| @name 设置运行环境运行状态(仅java/go/python/nodejs) | |
| ''' | |
| get.compose_file = get.get("compose_file", None) | |
| if get.compose_file is None: return public.returnResult(False, msg="请传compose文件路径:compose_file") | |
| get.runtime_status = get.get("runtime_status", None) | |
| if get.runtime_status is None: return public.returnResult(False, msg="请传运行状态:runtime_status") | |
| if not get.compose_file.endswith(".yml"): return public.returnResult(False, msg="compose文件路径错误") | |
| self.path = get.compose_file | |
| if get.runtime_status == "stop": | |
| cmd = self.get_compose_stop() | |
| opt_status = "停止" | |
| elif get.runtime_status == "start": | |
| cmd = self.get_compose_up() | |
| opt_status = "启动" | |
| elif get.runtime_status == "restart": | |
| cmd = self.get_compose_restart() | |
| opt_status = "重启" | |
| else: | |
| return public.returnResult(False, msg="运行状态【{}】错误".format(get.runtime_status)) | |
| public.ExecShell(cmd) | |
| return public.returnResult(msg="{}成功".format(opt_status)) | |
| # 2024/10/31 10:33 获取指定运行环境的日志 | |
| def get_runtime_logs(self, get): | |
| ''' | |
| @name 获取指定运行环境的日志 | |
| ''' | |
| get.log_type = get.get("log_type", "run") | |
| get.compose_file = get.get("compose_file", None) | |
| get.log_file = get.get("log_file", None) | |
| if get.log_type == "run": | |
| if get.compose_file is None: | |
| return public.returnResult(False, msg="请传compose文件路径:compose_file") | |
| command = self.set_type(0).set_path(get.compose_file).set_tail("500").get_tail_compose_log() | |
| stdout, stderr = public.ExecShell(command) | |
| return public.returnResult(True, data=stdout) | |
| else: | |
| if get.log_file is None: | |
| return public.returnResult(False, msg="请传日志文件路径:log_file") | |
| log_body = public.readFile(get.log_file) | |
| return public.returnResult(True, data=log_body) | |
| # 2024/10/31 10:33 获取运行环境版本信息 | |
| def get_runtime_versions(self, get): | |
| ''' | |
| @name 获取运行环境版本信息 | |
| ''' | |
| get.runtime_type = get.get("runtime_type", "all") | |
| if get.runtime_type == "": return public.returnResult(False, msg="请传运行环境类型:runtime_type") | |
| if not get.runtime_type in ("all", "php", "java", "go", "python","nodejs"): | |
| return public.returnResult(False, msg="运行环境类型【{}】错误,仅支持:all、php、java、go、python、nodejs".format(get.runtime_type)) | |
| repo_urls = [ | |
| { | |
| "name": "中国科技大学", | |
| "repo": "mirrors.ustc.edu.cn" | |
| }, | |
| { | |
| "name": "网易", | |
| "repo": "mirrors.163.com" | |
| }, | |
| { | |
| "name": "阿里云", | |
| "repo": "mirrors.aliyun.com" | |
| }, | |
| { | |
| "name": "清华大学", | |
| "repo": "mirrors.tuna.tsinghua.edu.cn" | |
| }] | |
| versions = { | |
| "php": ["8.3", "8.2", "8.1", "8.0", "7.4", "7.3", "7.2", "7.1", "7.0", "5.6"], | |
| "java": ["22", "21", "17", "11", "1.8"], | |
| "go": ["1.22", "1.21"], | |
| "python": ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8", "3.7"], | |
| "nodejs": ["25.1.0","25","24", "23", "22.21.1","21.7.3","20.19.5","18.20.8"], | |
| "repo_urls": repo_urls | |
| } | |
| if os.path.exists(self.versions_file): | |
| new_versions = public.readFile(self.versions_file) | |
| if new_versions: | |
| try: | |
| new_versions = json.loads(new_versions) | |
| if new_versions.get(get.runtime_type,"") != "": | |
| versions = new_versions | |
| else: | |
| get.force_update = 1 | |
| self.check_templates(get) | |
| except: | |
| pass | |
| if get.runtime_type != "all": | |
| versions = {get.runtime_type: versions.get(get.runtime_type, [])} | |
| if get.runtime_type == "nodejs": | |
| versions["repo_urls"] = [ | |
| {"name": "淘宝源","repo": "https://registry.npmmirror.com/"}, | |
| {"name": "阿里源","repo": "https://npm.aliyun.com/"}, | |
| {"name": "网易源","repo": "https://mirrors.163.com/npm/"}, | |
| {"name": "中国科学技术大学源","repo": "https://mirrors.ustc.edu.cn/npm/"}, | |
| {"name": "清华大学源","repo": "https://mirrors.tuna.tsinghua.edu.cn/npm/"}, | |
| ] | |
| else: | |
| versions["repo_urls"] = repo_urls | |
| return public.returnResult(data=versions) | |
| # 2024/10/31 10:34 获取扩展模板列表 | |
| def get_php_ext_list(self, get): | |
| ''' | |
| @name 获取扩展模板列表 | |
| ''' | |
| get.p = get.get("p", 1) | |
| get.row = get.get("row", 10) | |
| exts = dp.sql("ext_templates").select() | |
| page_data = self.get_page(exts, get) | |
| return self.pageResult(True, data=page_data["data"], page=page_data["page"]) | |
| # 2024/10/31 15:56 获取所有支持的扩展列表 | |
| def get_all_exts(self, get): | |
| ''' | |
| @name 获取所有支持的扩展列表 | |
| ''' | |
| get.version = get.get("version", "all") | |
| if not os.path.exists(self.exts_file): self.check_templates(get) | |
| try: | |
| exts = json.loads(public.readFile(self.exts_file)) | |
| if get.version != "all": exts = {get.version: exts.get(get.version, [])} | |
| return public.returnResult(data=exts) | |
| except: | |
| import traceback | |
| return public.returnResult(False, data={}, msg=traceback.format_exc()) | |
| # 2024/10/31 10:34 创建扩展模板 | |
| def create_php_ext_template(self, get): | |
| ''' | |
| @name 创建扩展模板 | |
| ''' | |
| get.name = get.get("name", None) | |
| if get.name is None: return public.returnResult(False, msg="请传模板名称:name") | |
| get.version = get.get("version", None) | |
| if get.version is None: return public.returnResult(False, msg="请传模板版本:version") | |
| get.exts = get.get("exts", None) | |
| if get.exts is None: return public.returnResult(False, msg="请传模板扩展:exts") | |
| find_result = dp.sql("ext_templates").where("name=?", get.name).find() | |
| if find_result: return public.returnResult(False, msg="模板【{}】已存在,请更换其他名称!".format(get.name)) | |
| dp.sql("ext_templates").insert({ | |
| "name": get.name, | |
| "version": get.version, | |
| "exts": get.exts, | |
| "addtime": int(time.time()) | |
| }) | |
| return public.returnResult(msg="创建扩展【{}】成功".format(get.name)) | |
| # 2024/10/31 10:34 删除指定扩展模板 | |
| def delete_php_ext_template(self, get): | |
| ''' | |
| @name 删除指定扩展模板 | |
| ''' | |
| get.id = get.get("id", None) | |
| if get.id is None: return public.returnResult(False, msg="请传模板ID:id") | |
| find_result = dp.sql("ext_templates").where("id=?", get.id).find() | |
| if not find_result: return public.returnResult(False, msg="模板不存在") | |
| dp.sql("ext_templates").where("id=?", get.id).delete() | |
| find_result = dp.sql("ext_templates").where("id=?", get.id).find() | |
| if find_result: return public.returnResult(False, msg="删除失败") | |
| return public.returnResult(msg="删除成功") | |
| # 2024/10/31 10:34 批量删除指定扩展模板 | |
| def batch_delete_php_ext_template(self, get): | |
| ''' | |
| @name 批量删除指定扩展模板 | |
| ''' | |
| get.ids = get.get("ids", None) | |
| if get.ids is None: return public.returnResult(False, msg="请传模板ID:ids") | |
| get.ids = get.ids.split(",") | |
| delete_result = [] | |
| for id in get.ids: | |
| find_result = dp.sql("ext_templates").where("id=?", id).find() | |
| if not find_result: | |
| delete_result.append({"id": id, "status": False, "msg": "模板不存在"}) | |
| continue | |
| dp.sql("ext_templates").where("id=?", id).delete() | |
| find_result = dp.sql("ext_templates").where("id=?", id).find() | |
| if find_result: | |
| delete_result.append({"id": id, "status": False, "msg": "删除失败"}) | |
| continue | |
| delete_result.append({"id": id, "status": True, "msg": "删除成功"}) | |
| return public.returnResult(msg="批量删除成功", data=delete_result) | |
| # 2024/10/31 10:35 编辑扩展模板 | |
| def modify_php_ext_template(self, get): | |
| ''' | |
| @name 编辑扩展模板 | |
| ''' | |
| get.id = get.get("id", None) | |
| if get.id is None: return public.returnResult(False, msg="请传模板ID:id") | |
| get.version = get.get("version", None) | |
| if get.version is None: return public.returnResult(False, msg="请传模板版本:version") | |
| get.exts = get.get("exts", None) | |
| if get.exts is None: return public.returnResult(False, msg="请传模板扩展:exts") | |
| find_result = dp.sql("ext_templates").where("id=?", get.id).find() | |
| if not find_result: return public.returnResult(False, msg="模板不存在") | |
| dp.sql("ext_templates").where("id=?", get.id).update({ | |
| "version": get.version, | |
| "exts": get.exts | |
| }) | |
| return public.returnResult(msg="编辑成功") | |