mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-10-01 13:54:51 +02:00
Update to v8.7.0
This commit is contained in:
@@ -0,0 +1,807 @@
|
||||
#!/www/server/panel/pyenv/bin/python
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
import traceback
|
||||
import tarfile
|
||||
import subprocess
|
||||
import argparse
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Optional, Tuple, List, Union, Dict, Iterable
|
||||
from hashlib import sha256, sha1
|
||||
from platform import system, machine
|
||||
from xml.etree import cElementTree
|
||||
from io import FileIO
|
||||
|
||||
__all__ = ['pygvm']
|
||||
|
||||
|
||||
class _GvmSTD:
|
||||
out = sys.stdout
|
||||
err = sys.stderr
|
||||
|
||||
|
||||
_gvm_std = _GvmSTD()
|
||||
|
||||
|
||||
def get_arch() -> Tuple[Optional[str], Optional[str]]:
|
||||
_system_name = system()
|
||||
if _system_name != "Linux":
|
||||
return None, "Currently, this feature is only supported for Linux systems."
|
||||
_arch = machine().lower()
|
||||
arch = None
|
||||
if _arch in ("x86_64", "amd64"):
|
||||
arch = "amd64"
|
||||
elif _arch in ("i386", "i486", "i586", "x86"):
|
||||
arch = "386"
|
||||
elif _arch in ("aarch64", "arm64"):
|
||||
arch = "arm64"
|
||||
if arch is None:
|
||||
return None, "Failed to parse the architecture of the current processor."
|
||||
return arch, None
|
||||
|
||||
|
||||
class GVMError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
template = """#pygvm
|
||||
export GOROOT="/usr/local/btgo"
|
||||
export PATH="/usr/local/btgo/bin:${PATH}"
|
||||
"""
|
||||
|
||||
|
||||
class _Mirror(object):
|
||||
"""
|
||||
Mirror source
|
||||
"""
|
||||
_cloud = ""
|
||||
name = ""
|
||||
|
||||
def test_speed(self, time_out: int) -> float:
|
||||
try:
|
||||
s_time = time.time()
|
||||
res = requests.get(self._cloud, timeout=time_out)
|
||||
if res.status_code != 200:
|
||||
return sys.float_info.max
|
||||
return time.time() - s_time
|
||||
except:
|
||||
return sys.float_info.max
|
||||
|
||||
def get_versions_by_cloud(self, arch: str) -> Tuple[Union[List["GoVersion"], str], Optional[List["GoVersion"]]]:
|
||||
return "Failed to request cloud data! Please check your network connection.", None
|
||||
|
||||
def download_url(self, go_v: "GoVersion") -> str:
|
||||
raise NotImplemented()
|
||||
|
||||
|
||||
class _StudyGolangMirror(_Mirror):
|
||||
_cloud = "https://studygolang.com/dl"
|
||||
name = "Community Source"
|
||||
|
||||
def get_versions_by_cloud(self, arch: str) -> Tuple[Union[List["GoVersion"], str], Optional[List["GoVersion"]]]:
|
||||
"""
|
||||
Get archived and stable versions supported by the cloud
|
||||
"""
|
||||
|
||||
res = requests.get(self._cloud)
|
||||
if res.status_code != 200:
|
||||
return "Failed to request cloud data! Please check your network connection.", None
|
||||
rep = r'(<\s?h3\s?id="stable"\s?>.*\n)(?P<stable>(.*\n)+)(\s*<\s?h3\s?id="unstable"\s?>)(.*\n)+' \
|
||||
r'(?P<history>(\s*<div\s?class="toggle(Visible)?"\s?id="archive"\s?>)(.*\n)+)((\s*</div>\s*\n){5}\s*<div)'
|
||||
res = re.search(rep, res.text)
|
||||
if not res:
|
||||
return "Parsing error", None
|
||||
try:
|
||||
stable = cElementTree.fromstring("<body>" + res.group("stable") + "</body>")
|
||||
history = cElementTree.fromstring(res.group("history")).find('./div[2]')
|
||||
stable_go_versions = self._parser_xml(stable, arch)
|
||||
history_go_versions = self._parser_xml(history, arch)
|
||||
stable_go_versions.sort(key=lambda x: int(x.version.split(".")[1]), reverse=True)
|
||||
history_go_versions.sort(key=lambda x: int(x.version.split(".")[1]), reverse=True)
|
||||
return stable_go_versions, history_go_versions
|
||||
except:
|
||||
traceback.print_exc(file=_gvm_std.err)
|
||||
return "Parsing error", None
|
||||
|
||||
@staticmethod
|
||||
def _parser_xml(datas: cElementTree.Element, arch: str) -> List["GoVersion"]:
|
||||
res_list = []
|
||||
for data in datas.findall('./div'):
|
||||
v = data.attrib.get("id")
|
||||
need_file = "{}.linux-{}.tar.gz".format(v, arch)
|
||||
for i in data.iterfind('.//tr'):
|
||||
if i.attrib.get("class") == "first":
|
||||
continue
|
||||
file_name = i.find("./td[1]/a").text
|
||||
checksum = i.find("./td[6]/tt").text
|
||||
if need_file == file_name:
|
||||
go_v = GoVersion.new(v, checksum, file_name)
|
||||
if go_v:
|
||||
res_list.append(go_v)
|
||||
return res_list
|
||||
|
||||
def download_url(self, go_v: "GoVersion") -> str:
|
||||
return "{}/golang/{}".format(self._cloud, go_v.file_name)
|
||||
|
||||
|
||||
class _GoOfficialDeVMirror(_Mirror):
|
||||
_cloud = "https://go.dev/dl/"
|
||||
name = "go.dev source"
|
||||
|
||||
def get_versions_by_cloud(self, arch: str) -> Tuple[Union[List["GoVersion"], str], Optional[List["GoVersion"]]]:
|
||||
"""
|
||||
Get archived and stable versions supported by the cloud
|
||||
"""
|
||||
res = requests.get(self._cloud)
|
||||
if res.status_code != 200:
|
||||
return "Failed to request cloud data! Please check your network connection.", None
|
||||
|
||||
rep_stable_versions = re.compile(r'<div\s+class="toggleVisible"\s+id="(.|\n)*?</table>(\s+</div>){3}')
|
||||
rep_history_versions = re.compile(r'<div\s+class="toggle"\s+id="(.|\n)*?</table>(\s+</div>){3}')
|
||||
stable_versions, history_versions = [], []
|
||||
for i in rep_stable_versions.finditer(res.text):
|
||||
g = self._parser_xml_node(i.group(), arch)
|
||||
if g is not None:
|
||||
stable_versions.append(g)
|
||||
|
||||
for i in rep_history_versions.finditer(res.text):
|
||||
g = self._parser_xml_node(i.group(), arch)
|
||||
if g is not None:
|
||||
history_versions.append(g)
|
||||
if not stable_versions and history_versions:
|
||||
return "Parsing error", None
|
||||
return stable_versions, history_versions
|
||||
|
||||
@staticmethod
|
||||
def _parser_xml_node(data: str, arch: str) -> Optional["GoVersion"]:
|
||||
try:
|
||||
node = cElementTree.fromstring(data)
|
||||
v = node.attrib.get("id")
|
||||
if v.find("rc") != -1 or v.find("beta") != -1:
|
||||
return None
|
||||
need_file = "{}.linux-{}.tar.gz".format(v, arch)
|
||||
for i in node.iterfind('.//tr'):
|
||||
if i.attrib.get("class") == "first":
|
||||
continue
|
||||
file_name = i.find("./td[1]/a").text
|
||||
checksum = i.find("./td[6]/tt").text
|
||||
if need_file == file_name:
|
||||
go_v = GoVersion.new(v, checksum, file_name)
|
||||
if go_v:
|
||||
return go_v
|
||||
except:
|
||||
return None
|
||||
return None
|
||||
|
||||
def download_url(self, go_v: "GoVersion") -> str:
|
||||
return "{}/{}".format(self._cloud, go_v.file_name)
|
||||
|
||||
|
||||
class _GoOfficialCNMirror(_GoOfficialDeVMirror):
|
||||
_cloud = "https://golang.google.cn/dl/"
|
||||
name = "official"
|
||||
|
||||
|
||||
# 2026-01-16 Verified that the USTC mirror cannot be used
|
||||
class _UstcMirror(_Mirror):
|
||||
_cloud = "https://mirrors.ustc.edu.cn/golang/"
|
||||
name = "ustc"
|
||||
|
||||
def get_versions_by_cloud(self, arch: str) -> Tuple[Union[List["GoVersion"], str], Optional[List["GoVersion"]]]:
|
||||
"""
|
||||
Get archived and stable versions supported by the cloud
|
||||
"""
|
||||
res = requests.get(self._cloud)
|
||||
if res.status_code != 200:
|
||||
return "Failed to request cloud data! Please check your network connection.", None
|
||||
|
||||
rep_version = re.compile(r"<a.*(?P<f>(?P<v>go[\d.]+)\.linux-%s\.tar\.gz(\.sha256)?)" % arch)
|
||||
v_map = {}
|
||||
for i in rep_version.finditer(res.text):
|
||||
v = i.group("v")
|
||||
if v not in v_map:
|
||||
v_map[v] = [v, "", ""]
|
||||
f = i.group("f")
|
||||
if f.endswith(".sha256"):
|
||||
v_map[v][1] = f
|
||||
else:
|
||||
v_map[v][2] = f
|
||||
|
||||
try:
|
||||
v_list = self._get_sha256(list(v_map.values()))
|
||||
except:
|
||||
v_list = []
|
||||
|
||||
if not v_list:
|
||||
return "Parsing error", None
|
||||
|
||||
return [], v_list
|
||||
|
||||
def _get_sha256(self, v_list: List[Iterable[str]]) -> List["GoVersion"]:
|
||||
p = ThreadPoolExecutor(10)
|
||||
t_list = []
|
||||
for idx, (v, s, f) in enumerate(v_list):
|
||||
if not s:
|
||||
continue
|
||||
t = p.submit(self._query_sha256, v_list, s, idx)
|
||||
t_list.append(t)
|
||||
|
||||
for i in t_list:
|
||||
i.result()
|
||||
p.shutdown()
|
||||
|
||||
use_list = []
|
||||
for v, s, f in v_list:
|
||||
g = GoVersion.new(v, s, f)
|
||||
if g:
|
||||
use_list.append(g)
|
||||
return use_list
|
||||
|
||||
def _query_sha256(self, v_list, s, idx):
|
||||
try:
|
||||
res = requests.get("{}/{}".format(self._cloud, s))
|
||||
if res.status_code == 200:
|
||||
v_list[idx][1] = res.text
|
||||
except:
|
||||
v_list[idx][1] = ""
|
||||
|
||||
def download_url(self, go_v: "GoVersion") -> str:
|
||||
return "{}/{}".format(self._cloud, go_v.file_name)
|
||||
|
||||
|
||||
def get_cloud() -> _Mirror:
|
||||
_m_list = [
|
||||
_StudyGolangMirror(),
|
||||
_GoOfficialCNMirror(),
|
||||
_GoOfficialDeVMirror(), # Unstable disable
|
||||
]
|
||||
|
||||
v4_file = '/www/server/panel/data/v4.pl'
|
||||
if os.path.exists(v4_file):
|
||||
try:
|
||||
with open(v4_file, 'rt', encoding='utf-8') as fp:
|
||||
if fp.read().strip() == "-4":
|
||||
_m_list = _m_list[1:]
|
||||
except:
|
||||
pass
|
||||
|
||||
def test_with_time_out(time_out: int) -> _Mirror:
|
||||
p = ThreadPoolExecutor(len(_m_list))
|
||||
res_task = []
|
||||
for m in _m_list:
|
||||
res_task.append(p.submit(m.test_speed, time_out))
|
||||
|
||||
time_list = []
|
||||
for idx, t in enumerate(res_task):
|
||||
time_list.append((t.result(timeout=None), idx))
|
||||
time_list.sort(key=lambda x: x[0])
|
||||
return _m_list[time_list[0][1]]
|
||||
|
||||
try:
|
||||
return test_with_time_out(10)
|
||||
except:
|
||||
try:
|
||||
return test_with_time_out(60)
|
||||
except:
|
||||
pass
|
||||
|
||||
return _Mirror()
|
||||
|
||||
|
||||
class GoVersion:
|
||||
__slots__ = ("version", "checksum", "file_name", "_cloud", "bt_gvm_path")
|
||||
|
||||
def __init__(self, v: str, checksum: str, file_name: str):
|
||||
self.version = v
|
||||
self.checksum = checksum
|
||||
self.file_name = file_name
|
||||
self._cloud: Optional[_Mirror] = None
|
||||
self.bt_gvm_path = "/usr/local/btgojdk"
|
||||
|
||||
def set_cloud(self, c: _Mirror):
|
||||
self._cloud = c
|
||||
print("Using [{}] source for download".format(c.name))
|
||||
|
||||
def check(self, file) -> bool:
|
||||
"""calculate file sha256 """
|
||||
print("[2/4] Verifying file hash.....", file=_gvm_std.out, flush=True)
|
||||
sha_obj = sha256() if len(self.checksum) == 64 else sha1()
|
||||
with open(file, 'rb') as f:
|
||||
for chunk in iter(lambda: f.read(4096), b''):
|
||||
sha_obj.update(chunk)
|
||||
hash_value = sha_obj.hexdigest()
|
||||
print("Calculated value: {}".format(hash_value), file=_gvm_std.out, flush=True)
|
||||
print("Expected value: {}".format(self.checksum), file=_gvm_std.out, flush=True)
|
||||
return hash_value == self.checksum
|
||||
|
||||
@classmethod
|
||||
def new(cls, v: str, checksum: str, file_name: str) -> Optional["GoVersion"]:
|
||||
v_rep = r"(?P<target>go1\.\d{1,2}(\.\d{1,2})?)"
|
||||
v_res = re.search(v_rep, v)
|
||||
v = None
|
||||
if v_res:
|
||||
v = v_res.group("target")
|
||||
|
||||
checksum_rep = r"(?P<target>([0-9a-f]{64})|([0-9a-f]{40}))"
|
||||
checksum_res = re.search(checksum_rep, checksum)
|
||||
checksum = None
|
||||
if checksum_res:
|
||||
checksum = checksum_res.group("target")
|
||||
if not v or not checksum_res:
|
||||
return None
|
||||
return cls(v, checksum, file_name)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "[v:{}, checksum:{}]".format(self.version, self.checksum)
|
||||
|
||||
def serialize(self) -> str:
|
||||
return "({}:{}:{})".format(self.version, self.checksum, self.file_name)
|
||||
|
||||
def show(self) -> str:
|
||||
return self.version
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: str) -> Optional["GoVersion"]:
|
||||
if data[0] == "(" and data[-1] == ")":
|
||||
data = data[1:-1]
|
||||
return cls.new(*data.split(":")[:3])
|
||||
|
||||
def _download(self) -> bool:
|
||||
cache_dir = os.path.join(self.bt_gvm_path, "cached")
|
||||
if not os.path.exists(cache_dir):
|
||||
os.makedirs(cache_dir)
|
||||
dst = os.path.join(cache_dir, self.file_name)
|
||||
if os.path.exists(dst):
|
||||
print("[1/4] Using cached SDK file......", file=_gvm_std.out, flush=True)
|
||||
return self.check(dst)
|
||||
|
||||
print("[1/4] Downloading SDK file......", file=_gvm_std.out, flush=True)
|
||||
response = requests.get(self._cloud.download_url(self), stream=True)
|
||||
total_size = int(response.headers.get('content-length', 0))
|
||||
print("File size to download: %.2fM" % (total_size / (1024 * 1024)), file=_gvm_std.out, flush=True)
|
||||
block_size = 1024 * 1024
|
||||
downloaded_size = 0
|
||||
with open(dst, 'wb') as f:
|
||||
for data in response.iter_content(block_size):
|
||||
f.write(data)
|
||||
downloaded_size += len(data)
|
||||
progress = (downloaded_size / total_size) * 100
|
||||
print(f"Downloading....\t %.2f%% completed" % progress,
|
||||
end='\r', flush=True, file=_gvm_std.out)
|
||||
print('Download complete', file=_gvm_std.out, flush=True)
|
||||
return self.check(dst)
|
||||
|
||||
def _install(self) -> bool:
|
||||
print("[3/4] Extracting and installing.....", file=_gvm_std.out, flush=True)
|
||||
tar_filename = os.path.join(self.bt_gvm_path, "cached", self.file_name)
|
||||
target_directory = self.bt_gvm_path
|
||||
try:
|
||||
with tarfile.open(tar_filename, 'r:gz') as tar:
|
||||
tar.extractall(path=target_directory)
|
||||
except:
|
||||
return False
|
||||
src = os.path.join(self.bt_gvm_path, "go")
|
||||
if not os.path.isdir(src):
|
||||
return False
|
||||
os.rename(src, os.path.join(self.bt_gvm_path, self.version))
|
||||
return True
|
||||
|
||||
def install(self) -> Tuple[bool, str]:
|
||||
if not os.path.exists(self.bt_gvm_path):
|
||||
os.makedirs(self.bt_gvm_path)
|
||||
print("Starting installation......", file=_gvm_std.out, flush=True)
|
||||
dst = os.path.join(self.bt_gvm_path, self.version)
|
||||
if os.path.isdir(dst):
|
||||
return True, "Already installed"
|
||||
|
||||
# Download file
|
||||
if not self._download():
|
||||
return False, "File download and verification failed!"
|
||||
# Install go
|
||||
if not self._install():
|
||||
return False, "Extraction and installation failed!"
|
||||
|
||||
print("[4/4] Using {}.....".format(self.version), file=_gvm_std.out, flush=True)
|
||||
flag, err = self.use(self.bt_gvm_path, self.version)
|
||||
if not flag:
|
||||
return False, err
|
||||
print("Installation complete!", file=_gvm_std.out, flush=True)
|
||||
print("If the 'go' command is not found, try reopening the terminal.", file=_gvm_std.out, flush=True)
|
||||
return True, ""
|
||||
|
||||
@classmethod
|
||||
def use(cls, bt_gvm_path, version) -> Tuple[bool, str]:
|
||||
# Create a symbolic link
|
||||
src = os.path.join(bt_gvm_path, version)
|
||||
if not os.path.isdir(src):
|
||||
return False, "{} file is missing.".format(version)
|
||||
dst = "/usr/local/btgo"
|
||||
if os.path.islink(dst):
|
||||
os.unlink(dst)
|
||||
os.symlink(src, dst)
|
||||
cls.add_to_path()
|
||||
time.sleep(0.1)
|
||||
out, err = cls.test()
|
||||
if version in out:
|
||||
return True, ""
|
||||
else:
|
||||
return False, err
|
||||
|
||||
@staticmethod
|
||||
def test() -> Tuple[str, str]:
|
||||
# Execute the command and get the output
|
||||
os.environ["PATH"] = "/usr/local/btgo/bin:" + os.environ["PATH"]
|
||||
p = subprocess.Popen("go version", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, env=os.environ)
|
||||
output, err = p.communicate()
|
||||
return output.decode(), err.decode()
|
||||
|
||||
@staticmethod
|
||||
def add_to_path():
|
||||
profile = "/etc/profile"
|
||||
with open(profile, "r") as f:
|
||||
profile_data = f.read()
|
||||
if profile_data.find(template) != -1:
|
||||
return
|
||||
with open(profile, "a") as f:
|
||||
f.write("\n" + template)
|
||||
os.system("source {}".format(profile))
|
||||
|
||||
@staticmethod
|
||||
def parse_version(data: str) -> Tuple[bool, str]:
|
||||
v_rep = r"(?P<target>1\.\d{1,2}(\.\d{1,2})?)"
|
||||
v_res = re.search(v_rep, data)
|
||||
v = None
|
||||
if v_res:
|
||||
v = v_res.group("target")
|
||||
return True, "go" + v
|
||||
else:
|
||||
return False, ""
|
||||
|
||||
|
||||
class GVM(object):
|
||||
stable_versions: Optional[List[GoVersion]] = None
|
||||
history_versions: Optional[List[GoVersion]] = None
|
||||
arch = ""
|
||||
use_shell = False
|
||||
bt_gvm_path = "/usr/local/btgojdk"
|
||||
now_version = None
|
||||
|
||||
def __init__(self):
|
||||
self.get_now_version()
|
||||
if not os.path.exists(self.bt_gvm_path):
|
||||
os.makedirs(self.bt_gvm_path)
|
||||
self._cloud = None
|
||||
|
||||
@staticmethod
|
||||
def check_use():
|
||||
res = os.popen("lsattr /etc/profile")
|
||||
return res.read().find("--i--") == -1
|
||||
|
||||
@property
|
||||
def cloud(self):
|
||||
if not isinstance(self._cloud, _Mirror):
|
||||
self._cloud = get_cloud()
|
||||
return self._cloud
|
||||
|
||||
def get_now_version(self) -> None:
|
||||
now_version = "/usr/local/btgo"
|
||||
if os.path.islink(now_version):
|
||||
now_version = os.path.basename(os.readlink(now_version))
|
||||
else:
|
||||
now_version = None
|
||||
self.now_version = now_version
|
||||
|
||||
def __new__(cls, *args, **kwargs) -> Union["GVM", str]:
|
||||
arch, errmsg = get_arch()
|
||||
if errmsg:
|
||||
return errmsg
|
||||
_gvm = super().__new__(cls, *args, **kwargs)
|
||||
_gvm.arch = arch
|
||||
return _gvm
|
||||
|
||||
# Get Go version
|
||||
def get_go_version(self):
|
||||
self.stable_versions, self.history_versions = self._get_versions_by_local()
|
||||
if not self.history_versions:
|
||||
if self.use_shell:
|
||||
print("Local record file not found, requesting GO version data from the cloud. This may take some time, please wait.", file=_gvm_std.out)
|
||||
self.stable_versions, self.history_versions = self._get_versions_by_cloud()
|
||||
# Cache data locally
|
||||
if isinstance(self.stable_versions, list):
|
||||
self._save_cached(self.stable_versions, self.history_versions)
|
||||
if not self.history_versions and isinstance(self.stable_versions, str):
|
||||
raise GVMError("Network error:" + self.stable_versions)
|
||||
return self.stable_versions, self.history_versions
|
||||
|
||||
def _get_versions_by_local(self) -> [Tuple[Optional[List[GoVersion]], Optional[List[GoVersion]]]]:
|
||||
"""
|
||||
Get cached data of local archived and stable versions
|
||||
"""
|
||||
local_path = "/www/server/panel/data/pygvm"
|
||||
if not os.path.exists(local_path):
|
||||
os.makedirs(local_path)
|
||||
return None, None
|
||||
stable_file = os.path.join(local_path, "stable_versions.txt")
|
||||
history_file = os.path.join(local_path, "history_versions.txt")
|
||||
if not os.path.isfile(stable_file) or not os.path.isfile(history_file):
|
||||
return None, None
|
||||
with open(stable_file, "r") as f:
|
||||
_arch = f.readline().strip()
|
||||
if _arch != self.arch:
|
||||
return None, None
|
||||
stable_versions = [GoVersion.deserialize(line.strip()) for line in f.readlines()]
|
||||
with open(history_file, "r") as f:
|
||||
_arch = f.readline().strip()
|
||||
if _arch != self.arch:
|
||||
return None, None
|
||||
history_versions = [GoVersion.deserialize(line.strip()) for line in f.readlines()]
|
||||
|
||||
return stable_versions, history_versions
|
||||
|
||||
def _get_versions_by_cloud(self) -> Tuple[Union[List[GoVersion], str], Optional[List[GoVersion]]]:
|
||||
"""
|
||||
Get supported archived and stable versions from the cloud
|
||||
"""
|
||||
return self.cloud.get_versions_by_cloud(self.arch)
|
||||
|
||||
def _save_cached(self, stable_go_versions: List[GoVersion], history_go_versions: List[GoVersion]) -> None:
|
||||
local_path = "/www/server/panel/data/pygvm"
|
||||
if not os.path.exists(local_path):
|
||||
os.makedirs(local_path)
|
||||
with open(os.path.join(local_path, "stable_versions.txt"), "w") as f:
|
||||
f.write(self.arch + "\n")
|
||||
for go_v in stable_go_versions:
|
||||
f.write(go_v.serialize() + "\n")
|
||||
with open(os.path.join(local_path, "history_versions.txt"), "w") as f:
|
||||
f.write(self.arch + "\n")
|
||||
for go_v in history_go_versions:
|
||||
f.write(go_v.serialize() + "\n")
|
||||
|
||||
@staticmethod
|
||||
def del_cached():
|
||||
local_path = "/www/server/panel/data/pygvm"
|
||||
stable_file = os.path.join(local_path, "stable_versions.txt")
|
||||
history_file = os.path.join(local_path, "history_versions.txt")
|
||||
if os.path.isfile(stable_file):
|
||||
os.remove(stable_file)
|
||||
if os.path.isfile(history_file):
|
||||
os.remove(history_file)
|
||||
|
||||
def api_ls(self) -> List[str]:
|
||||
return [i.strip() for i in os.listdir(self.bt_gvm_path) if i.startswith("go1")]
|
||||
|
||||
def cmd_ls(self) -> None:
|
||||
versions = [i.strip() for i in os.listdir(self.bt_gvm_path) if i.startswith("go1")]
|
||||
if not versions:
|
||||
print("No GO language SDK versions installed")
|
||||
return
|
||||
print("version: ")
|
||||
for i in versions:
|
||||
if i == self.now_version:
|
||||
i += " <- Now use this version"
|
||||
print(" " + i)
|
||||
|
||||
def api_ls_remote(self, is_all: bool) -> Tuple[Optional[List[GoVersion]], Optional[List[GoVersion]], Optional[str]]:
|
||||
try:
|
||||
self.get_go_version()
|
||||
except GVMError as e:
|
||||
return [], [], str(e)
|
||||
if is_all:
|
||||
self.stable_versions.sort(key=lambda x: int(x.version.split(".")[1]), reverse=True)
|
||||
self.history_versions.sort(key=lambda x: int(x.version.split(".")[1]), reverse=True)
|
||||
return self.stable_versions, self.history_versions, None
|
||||
stable_v = [".".join(i.version.split(".")[:2]) for i in self.stable_versions]
|
||||
res_history = {}
|
||||
for i in self.history_versions:
|
||||
parse_list = i.version.split(".")
|
||||
v = ".".join(parse_list[:2])
|
||||
if len(parse_list) > 2:
|
||||
# Patch version
|
||||
three_idx = int(parse_list[2])
|
||||
else:
|
||||
three_idx = 0
|
||||
# Skip if already exists in stable versions
|
||||
if v in stable_v:
|
||||
continue
|
||||
if v in res_history:
|
||||
if three_idx > res_history[v][0]:
|
||||
res_history[v] = [three_idx, i]
|
||||
else:
|
||||
res_history[v] = [three_idx, i]
|
||||
res_h = []
|
||||
for i in res_history.values():
|
||||
res_h.append(i[1])
|
||||
res_h.sort(key=lambda x: int(x.version.split(".")[1]), reverse=True)
|
||||
return self.stable_versions, res_h, None
|
||||
|
||||
def cmd_ls_remote(self, is_all: bool) -> None:
|
||||
stable, history, err = self.api_ls_remote(is_all)
|
||||
installed = self.api_ls()
|
||||
if err:
|
||||
print("Error occurred while obtaining version information", file=sys.stderr)
|
||||
print(err, file=sys.stderr)
|
||||
print("Stable Version:")
|
||||
for i in stable:
|
||||
if i.version in installed:
|
||||
i.version += " <- installed"
|
||||
print(" " + i.version)
|
||||
print("History Version:")
|
||||
for i in history:
|
||||
if i.version in installed:
|
||||
i.version += " <- installed"
|
||||
print(" " + i.version)
|
||||
|
||||
def _get_version(self, version) -> Union[GoVersion, str]:
|
||||
stable, history, err = self.api_ls_remote(True)
|
||||
if err:
|
||||
if self.use_shell:
|
||||
print("Error occurred while obtaining version information", file=_gvm_std.err)
|
||||
print(err, file=_gvm_std.err)
|
||||
|
||||
return err
|
||||
for i in stable:
|
||||
if i.version == version:
|
||||
return i
|
||||
for i in history:
|
||||
if i.version == version:
|
||||
return i
|
||||
if self.use_shell:
|
||||
print("Version not found", file=_gvm_std.err)
|
||||
return "Version not found"
|
||||
|
||||
def api_use(self, version) -> Tuple[bool, str]:
|
||||
versions = self.api_ls()
|
||||
if version not in versions:
|
||||
return False, "Version not found"
|
||||
res = GoVersion.use(self.bt_gvm_path, version)
|
||||
self.get_now_version()
|
||||
return res
|
||||
|
||||
def cmd_use(self, version) -> None:
|
||||
flag, err = self.api_use(version)
|
||||
if flag:
|
||||
print("Switched to: {}".format(version))
|
||||
print("If the 'go' command is not found, try reopening the terminal.")
|
||||
else:
|
||||
print(err, file=sys.stderr)
|
||||
|
||||
def api_install(self, version) -> Tuple[bool, str]:
|
||||
go_v = self._get_version(version)
|
||||
if isinstance(go_v, str):
|
||||
return False, go_v
|
||||
go_v.set_cloud(self.cloud)
|
||||
return go_v.install()
|
||||
|
||||
def cmd_install(self, version) -> None:
|
||||
go_v = self._get_version(version)
|
||||
go_v.set_cloud(self.cloud)
|
||||
if isinstance(go_v, str):
|
||||
pass
|
||||
_, err = go_v.install()
|
||||
if err:
|
||||
print(err, file=sys.stderr)
|
||||
|
||||
def api_uninstall(self, version: str) -> Tuple[bool, str]:
|
||||
versions = self.api_ls()
|
||||
if version not in versions:
|
||||
return False, "Version not found"
|
||||
next_version = None
|
||||
for i in versions:
|
||||
if i != version:
|
||||
next_version = i
|
||||
break
|
||||
if next_version is not None and version == self.now_version:
|
||||
GoVersion.use(self.bt_gvm_path, next_version)
|
||||
target_dir = os.path.join(self.bt_gvm_path, version)
|
||||
if os.path.exists:
|
||||
shutil.rmtree(target_dir, ignore_errors=True)
|
||||
return True, ""
|
||||
|
||||
def cmd_uninstall(self, version: str) -> None:
|
||||
flag, err = self.api_uninstall(version)
|
||||
if flag:
|
||||
print("Successfully uninstalled: {}".format(version))
|
||||
else:
|
||||
print(err, file=sys.stderr)
|
||||
|
||||
def cmd_clean_cache(self) -> None:
|
||||
local_path = "/www/server/panel/data/pygvm"
|
||||
for i in ("stable_versions.txt", "history_versions.txt"):
|
||||
if os.path.isfile(local_path + "/" + i):
|
||||
os.remove(local_path + "/" + i)
|
||||
cache_dir = os.path.join(self.bt_gvm_path, "cached")
|
||||
if os.path.isdir(cache_dir):
|
||||
shutil.rmtree(cache_dir)
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def set_goproxy(proxy: str) -> bool:
|
||||
import public
|
||||
if os.path.isfile("/usr/local/btgo/bin/go"):
|
||||
try:
|
||||
subprocess.check_output([
|
||||
"/usr/local/btgo/bin/go", "env", "-w", "GOPROXY=" + proxy, "GO111MODULE=on"
|
||||
])
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_goproxy() -> str:
|
||||
if os.path.isfile("/usr/local/btgo/bin/go"):
|
||||
try:
|
||||
out = subprocess.check_output(["/usr/local/btgo/bin/go", "env", "GOPROXY"])
|
||||
if out:
|
||||
return out.decode("utf-8").strip()
|
||||
except:
|
||||
pass
|
||||
return ""
|
||||
|
||||
@staticmethod
|
||||
def set_std(out: FileIO, err: FileIO) -> None:
|
||||
_gvm_std.out = out
|
||||
_gvm_std.err = err
|
||||
|
||||
|
||||
pygvm = GVM()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='gvm Go Language SDK Manager')
|
||||
# Add subcommands
|
||||
subparsers = parser.add_subparsers(title='operation', dest='command')
|
||||
# Add ls subcommand
|
||||
subparsers.add_parser('ls', help='Display the installed version of the Go language SDK')
|
||||
# Add clean-cache subcommand
|
||||
subparsers.add_parser('clean-cache', help='Clear cache')
|
||||
# Add ls-remote subcommand
|
||||
parser_ls_r = subparsers.add_parser('ls-remote', help='Display the versions that can install the Go language SDK, and by default only display the newer versions in each version')
|
||||
parser_ls_r.add_argument('-a', action='store_true', help='Show all Go language SDK versions that can be installed')
|
||||
# Add use subcommand
|
||||
parser_use = subparsers.add_parser('use', help='Use specified version')
|
||||
parser_use.add_argument('use_param', type=str, help='Complete version number')
|
||||
# Add install subcommand
|
||||
parser_install = subparsers.add_parser('install', help='Install the specified version')
|
||||
parser_install.add_argument('install_param', type=str, help='Complete version number')
|
||||
# Add uninstall subcommand
|
||||
parser_uninstall = subparsers.add_parser('uninstall', help='Uninstall and delete the specified version')
|
||||
parser_uninstall.add_argument('uninstall_param', type=str, help='Complete version number')
|
||||
|
||||
input_args = parser.parse_args()
|
||||
gvm = GVM()
|
||||
if isinstance(gvm, str):
|
||||
print(gvm, file=sys.stderr)
|
||||
exit(1)
|
||||
gvm.use_shell = True
|
||||
if input_args.command == 'ls':
|
||||
gvm.cmd_ls()
|
||||
elif input_args.command == "ls-remote":
|
||||
_is_all = True if input_args.a else False
|
||||
gvm.cmd_ls_remote(_is_all)
|
||||
elif input_args.command == "use":
|
||||
_flag, _v = GoVersion.parse_version(input_args.use_param)
|
||||
if _flag:
|
||||
gvm.cmd_use(_v)
|
||||
else:
|
||||
print("Version parameter error, it should be the structure of 1.xx.xx", file=sys.stderr)
|
||||
elif input_args.command == "install":
|
||||
_flag, _v = GoVersion.parse_version(input_args.install_param)
|
||||
if _flag:
|
||||
gvm.cmd_install(_v)
|
||||
else:
|
||||
print("Version parameter error, it should be the structure of 1.xx.xx", file=sys.stderr)
|
||||
elif input_args.command == "uninstall":
|
||||
_flag, _v = GoVersion.parse_version(input_args.uninstall_param)
|
||||
if _flag:
|
||||
gvm.cmd_uninstall(_v)
|
||||
else:
|
||||
print("Version parameter error, it should be the structure of 1.xx.xx", file=sys.stderr)
|
||||
elif input_args.command == "clean-cache":
|
||||
gvm.cmd_clean_cache()
|
||||
else:
|
||||
print("Use pygvm - h to view operation instructions", file=sys.stderr)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -759,9 +759,34 @@ export PATH
|
||||
self.install_packages(get)
|
||||
self.start_project(get)
|
||||
return_message=public.return_data(True,'Added project successfully',project_id)
|
||||
|
||||
# ================ git start ======================
|
||||
try:
|
||||
if get.get('deploy_type') in ['ssh', 'github']:
|
||||
if get.get('deploy_type') == 'ssh':
|
||||
from git_tools import GitTools
|
||||
git_obj = GitTools()
|
||||
|
||||
# 已clone项目,使用.git导入
|
||||
res = git_obj.get_git_directory(public.to_dict_obj({"site_id":project_id}))
|
||||
if res['status'] != 0:
|
||||
return public.return_message(-1, 0, res['message'])
|
||||
res = res['message']
|
||||
res = git_obj.import_existing_repository(public.to_dict_obj({"site_id":project_id, "repo" : res['repo'],
|
||||
"branch": res['branch'],"key_path":res['key_path'], "project_type":'node'}))
|
||||
if res['status'] != 0:
|
||||
return public.return_message(-1, 0, res['message'])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
# 失败不删除项目
|
||||
return public.return_message(-1, 0, public.lang("There was an error while configuring Git tools!"))
|
||||
# ================ git end ======================
|
||||
|
||||
del return_message['status']
|
||||
return public.return_message(0,0, return_message)
|
||||
|
||||
|
||||
|
||||
|
||||
def modify_project(self,get):
|
||||
'''
|
||||
@name 修改指定项目
|
||||
@@ -949,7 +974,6 @@ export PATH
|
||||
try:
|
||||
project['project_config'] = json.loads(project['project_config'])
|
||||
p_type = 'pm2' if project['project_config'].get('pm2_name') else 'nodejs'
|
||||
res = None
|
||||
if operation_type == 'delete':
|
||||
temp_get = public.to_dict_obj({'project_name': project['name'],'project_type': p_type,'pm2_name':project['project_config'].get('pm2_name')})
|
||||
res = comMod.main().delete(temp_get)
|
||||
@@ -957,12 +981,18 @@ export PATH
|
||||
res = comMod.main().set_project_status(public.to_dict_obj(
|
||||
{"project_name": project['name'], "project_type": p_type, "status": operation_type,
|
||||
"pm2_name": project['project_config'].get('pm2_name'),"run_user":project['project_config'].get('run_user')}))
|
||||
if res is None or res['status'] != 0:
|
||||
|
||||
if res['status'] != 0:
|
||||
msg_list.append({'name': project['name'],'status':False,'msg':res['message']['result']})
|
||||
else:
|
||||
success_count += 1
|
||||
msg_list.append({'name': project['name'],'status':True, 'msg': res['message']['result']})
|
||||
|
||||
if operation_type == 'delete':
|
||||
# 删除git
|
||||
from git_tools import GitTools
|
||||
GitTools().del_site_git(public.to_dict_obj({'site_id': project['id']}))
|
||||
|
||||
except Exception as e:
|
||||
msg_list.append({'name': project['name'], 'status': False, 'msg': str(e)})
|
||||
|
||||
@@ -1642,11 +1672,14 @@ export PATH
|
||||
for i in self._pids:
|
||||
try:
|
||||
p = psutil.Process(i)
|
||||
except: continue
|
||||
if p.ppid() == pid:
|
||||
if i in project_pids: continue
|
||||
if p.name() in ['bash']: continue
|
||||
project_pids.append(i)
|
||||
if p.status() == "zombie":
|
||||
continue
|
||||
if p.ppid() == pid:
|
||||
if i in project_pids:
|
||||
continue
|
||||
project_pids.append(i)
|
||||
except:
|
||||
continue
|
||||
|
||||
other_pids = []
|
||||
for i in project_pids:
|
||||
@@ -2299,6 +2332,8 @@ cd {}
|
||||
return public.return_message(0,0,False)
|
||||
data=public.readFile(pid_file)
|
||||
if isinstance(data,str) and data:
|
||||
if not data.isdigit():
|
||||
return public.return_message(0,0,False)
|
||||
pid = int(data)
|
||||
pids = self.get_project_pids(pid=pid, without_request=True)
|
||||
else:
|
||||
|
||||
@@ -77,8 +77,11 @@ def _init_ln_gvm() -> None:
|
||||
pass
|
||||
|
||||
|
||||
_init_ln_gvm()
|
||||
EnvironmentReporter().init_report()
|
||||
try:
|
||||
_init_ln_gvm()
|
||||
del _init_ln_gvm
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
class main(projectBase):
|
||||
@@ -1621,7 +1624,7 @@ echo $! > {pid_file}'''.format(
|
||||
block = ''
|
||||
nl_count = 0
|
||||
start = 0
|
||||
fsock = open(filename, 'rU')
|
||||
fsock = open(filename, 'r')
|
||||
try:
|
||||
fsock.seek(0, 2)
|
||||
curpos = fsock.tell()
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# aapanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: baozi <baozi@bt.cn>
|
||||
# -------------------------------------------------------------------
|
||||
# Project monitoring restart module
|
||||
# ------------------------------
|
||||
# Function: Monitor specified project files, and restart the service when files change
|
||||
# 1. Configuration
|
||||
# conf = {
|
||||
# "project_type": "java",
|
||||
# "project_id": 14,
|
||||
# "project_name": "project_name",
|
||||
# "watch_path": "/www/wwwroot/java_p/xxx.jar",
|
||||
# }
|
||||
# File handling:
|
||||
# 1. Compare size
|
||||
# 2. Compare mtime
|
||||
# Directory handling: Todo: Develop as needed
|
||||
# 1. Not supported yet
|
||||
# Todo: Currently only supports Java Spring Boot projects
|
||||
# Service operation logic
|
||||
# BT-Task polling
|
||||
# 1.1 Load configuration file
|
||||
# 1.2 Get status and compare
|
||||
# 1.3 Handle service restart based on comparison results
|
||||
# 1.4 Attempt to reload configuration file
|
||||
|
||||
import threading
|
||||
import json
|
||||
import os.path
|
||||
import time
|
||||
import sys
|
||||
from importlib import import_module
|
||||
from typing import Optional, Dict, Any, Tuple
|
||||
|
||||
|
||||
os.chdir("/www/server/panel")
|
||||
if "class/" not in sys.path:
|
||||
sys.path.insert(0, "class/")
|
||||
|
||||
if "/www/server/panel" not in sys.path:
|
||||
sys.path.insert(0, "/www/server/panel")
|
||||
|
||||
import public
|
||||
|
||||
|
||||
class WatchConfig:
|
||||
_CONF_FILE = "{}/data/watch_project.json".format(public.get_panel_path())
|
||||
|
||||
def __init__(self):
|
||||
self._config: Optional[dict] = None
|
||||
self._conf_time: Optional[int] = None
|
||||
|
||||
@property
|
||||
def config(self) -> dict:
|
||||
if self._config is not None:
|
||||
return self._config
|
||||
data = {}
|
||||
if not os.path.isfile(self._CONF_FILE):
|
||||
self._config = data
|
||||
self.save_conf()
|
||||
return self._config
|
||||
try:
|
||||
data = json.loads(public.readFile(self._CONF_FILE))
|
||||
if isinstance(data, dict):
|
||||
self._config = data
|
||||
self._conf_time = int(os.path.getmtime(self._CONF_FILE)) # Save timestamp when correctly reading configuration
|
||||
else:
|
||||
self._config = {}
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
self._config = {}
|
||||
|
||||
if self._conf_time is None:
|
||||
self.save_conf()
|
||||
return self._config
|
||||
|
||||
def save_conf(self):
|
||||
if self._config is not None:
|
||||
public.writeFile(self._CONF_FILE, json.dumps(self._config))
|
||||
self._conf_time = int(os.path.getmtime(self._CONF_FILE))
|
||||
|
||||
def reload(self) -> bool:
|
||||
if not os.path.exists(self._CONF_FILE):
|
||||
self._config = {}
|
||||
self.save_conf()
|
||||
return True
|
||||
|
||||
now_mtime = int(os.path.getmtime(self._CONF_FILE))
|
||||
if now_mtime == self._conf_time:
|
||||
return False
|
||||
else:
|
||||
self._config = None
|
||||
return True
|
||||
|
||||
|
||||
class Task:
|
||||
WAIT_TIME = 20
|
||||
|
||||
def __init__(self):
|
||||
self.watch_conf = WatchConfig()
|
||||
self._mod_cache: Dict[str, Any] = {}
|
||||
self._status_cache = {}
|
||||
self._sub_thread_cache = {}
|
||||
|
||||
def get_mod_obj(self, project_type: str) -> Any:
|
||||
if project_type in self._mod_cache:
|
||||
return self._mod_cache[project_type]
|
||||
|
||||
try:
|
||||
if project_type == "java" and os.path.exists("/www/server/panel/mod/project/java/projectMod.py"):
|
||||
main_module = import_module("mod.project.java.projectMod")
|
||||
else:
|
||||
if not project_type.endswith("Model"):
|
||||
project_type += "Model"
|
||||
main_module = import_module(".{}".format(project_type), package="projectModel")
|
||||
except ImportError:
|
||||
print(public.get_error_info())
|
||||
# public.print_log(public.get_error_info())
|
||||
return None
|
||||
|
||||
main_class = getattr(main_module, "main", None)
|
||||
if not callable(main_class):
|
||||
return None
|
||||
|
||||
self._mod_cache[project_type] = main_class()
|
||||
return self._mod_cache[project_type]
|
||||
|
||||
def need_restart(self, project_type: str, project_id: int) -> bool:
|
||||
model_main_obj = self.get_mod_obj(project_type)
|
||||
if not model_main_obj:
|
||||
return False
|
||||
stop_by_user = getattr(model_main_obj, "is_stop_by_user")(project_id)
|
||||
if stop_by_user:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_status_by_name(self, project_name: str) -> Tuple[int, float]:
|
||||
conf = self.watch_conf.config[project_name]
|
||||
file = conf['watch_path']
|
||||
if not os.path.exists(file):
|
||||
return 0, 0
|
||||
return os.path.getsize(file), int(os.path.getmtime(file))
|
||||
|
||||
def check_status(self, project_name: str) -> bool:
|
||||
if project_name not in self._status_cache:
|
||||
self._status_cache[project_name] = self.get_status_by_name(project_name)
|
||||
return False
|
||||
|
||||
now_status = self.get_status_by_name(project_name)
|
||||
if self._status_cache[project_name] == now_status:
|
||||
return False
|
||||
else:
|
||||
self._status_cache[project_name] = now_status
|
||||
return True
|
||||
|
||||
def restart_with_threading(self, project_type, project_name):
|
||||
try:
|
||||
model_main_obj = self.get_mod_obj(project_type)
|
||||
get_obj = public.dict_obj()
|
||||
get_obj.project_name = project_name
|
||||
getattr(model_main_obj, "restart_project")(get_obj)
|
||||
except:
|
||||
# print(public.get_error_info())
|
||||
public.print_log(public.get_error_info())
|
||||
|
||||
def _run(self):
|
||||
while True:
|
||||
# print(self.watch_conf.config)
|
||||
# print(self.watch_conf._conf_time)
|
||||
# print(self._status_cache)
|
||||
for p_name, p_conf in self.watch_conf.config.items():
|
||||
p_type = p_conf["project_type"]
|
||||
if self.need_restart(p_type, p_conf["project_id"]):
|
||||
if self.check_status(p_name):
|
||||
if p_name in self._sub_thread_cache:
|
||||
self._sub_thread_cache[p_name].join()
|
||||
restart_task = threading.Thread(target=self.restart_with_threading, args=(p_type, p_name))
|
||||
restart_task.start()
|
||||
self._sub_thread_cache[p_name] = restart_task
|
||||
|
||||
# public.print_log("---------WAIT--------------")
|
||||
for i in range(int(self.WAIT_TIME / 5)):
|
||||
time.sleep(5)
|
||||
if self.watch_conf.reload():
|
||||
print("Configuration file changed, reloading configuration")
|
||||
# public.print_log("Configuration file changed, reloading configuration")
|
||||
# public.print_log(self.watch_conf.config)
|
||||
break
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self._run()
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
except:
|
||||
public.print_log(public.get_error_info())
|
||||
# print(self.watch_conf.config)
|
||||
self.watch_conf = WatchConfig()
|
||||
self.run()
|
||||
|
||||
|
||||
class main:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def project_is_watch(get):
|
||||
try:
|
||||
project_name = get.project_name.strip()
|
||||
except AttributeError:
|
||||
return public.returnMsg(False, "Parameter error")
|
||||
|
||||
conf = WatchConfig()
|
||||
if project_name in conf.config:
|
||||
return conf.config[project_name]
|
||||
else:
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
def add_project_watch(get):
|
||||
try:
|
||||
project_name = get.project_name.strip()
|
||||
except AttributeError:
|
||||
return public.returnMsg(False, "Parameter error")
|
||||
|
||||
site_info = public.M('sites').where("name = ?", (project_name, )).find()
|
||||
if isinstance(site_info, str) and site_info.startswith("error"):
|
||||
return public.returnMsg(False, "Database query error:" + site_info)
|
||||
if not isinstance(site_info, dict):
|
||||
return public.returnMsg(False, "Specified website not found")
|
||||
if site_info["project_type"] != "Java":
|
||||
return public.returnMsg(False, "Currently only supports Java Springboot projects")
|
||||
project_config = json.loads(site_info["project_config"])
|
||||
if project_config['java_type'] != 'springboot':
|
||||
return public.returnMsg(False, "Currently only supports Java Springboot projects")
|
||||
|
||||
conf = WatchConfig()
|
||||
conf.config[project_name] = {
|
||||
"project_type": site_info["project_type"].lower(),
|
||||
"project_id": site_info["id"],
|
||||
"project_name": project_name,
|
||||
"watch_path": project_config["project_jar"]
|
||||
}
|
||||
conf.save_conf()
|
||||
return public.returnMsg(True, "Added successfully")
|
||||
|
||||
@staticmethod
|
||||
def del_project_watch(get):
|
||||
try:
|
||||
project_name = get.project_name.strip()
|
||||
except AttributeError:
|
||||
return public.returnMsg(False, "Parameter error")
|
||||
|
||||
conf = WatchConfig()
|
||||
if project_name in conf.config:
|
||||
del conf.config[project_name]
|
||||
conf.save_conf()
|
||||
|
||||
return public.returnMsg(True, "Deleted successfully")
|
||||
|
||||
|
||||
def use_project_watch(project_name: str) -> bool:
|
||||
conf = WatchConfig()
|
||||
return project_name in conf.config
|
||||
|
||||
|
||||
def add_project_watch(p_name: str, p_type: str, site_id: int, watch_path: str) -> None:
|
||||
conf = WatchConfig()
|
||||
conf.config[p_name] = {
|
||||
"project_type": p_type.lower(),
|
||||
"project_id": site_id,
|
||||
"project_name": p_name,
|
||||
"watch_path": watch_path
|
||||
}
|
||||
try:
|
||||
site_ids = public.M('sites').field("id").select()
|
||||
site_id_list = [i['id'] for i in site_ids]
|
||||
public.print_log(site_id_list)
|
||||
remove_list = []
|
||||
for k, v in conf.config.items():
|
||||
if v["project_id"] not in site_id_list:
|
||||
remove_list.append(k)
|
||||
for i in remove_list:
|
||||
del conf.config[i]
|
||||
except:
|
||||
pass
|
||||
conf.save_conf()
|
||||
|
||||
|
||||
def del_project_watch(p_name: str) -> None:
|
||||
conf = WatchConfig()
|
||||
if p_name in conf.config:
|
||||
del conf.config[p_name]
|
||||
conf.save_conf()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Task().run()
|
||||
Reference in New Issue
Block a user