Initial YakPanel commit

This commit is contained in:
Niranjan
2026-04-07 02:04:22 +05:30
commit 2826d3e7f3
5359 changed files with 1390724 additions and 0 deletions

View File

View File

@@ -0,0 +1,258 @@
# coding: utf-8
# -------------------------------------------------------------------
# YakPanel
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
# -------------------------------------------------------------------
# Author: csj <csj@yakpanel.com>
# -------------------------------------------------------------------
# ------------------------------
# docker应用商店 apphub 业务类
# ------------------------------
import json
import os
import sys
import re
import time
from datetime import datetime, timedelta
if "/www/server/panel/class" not in sys.path:
sys.path.insert(0, "/www/server/panel/class")
import public
from mod.base.git_tool import GitTool
from mod.project.docker.app.base import App
import mod.base.git_tool.install as GitInstall
class AppHub():
_instance = None
hub_config_path = os.path.join(App.dk_project_path,'dk_app','apphub_config.json') #/www/dk_project/dk_app/apphub_config.json
hub_home_path = os.path.join(App.dk_project_path,'dk_app','apphub','apphub') #/www/dk_project/dk_app/apphub/apphub
hub_apps_path = os.path.join(hub_home_path,'apps.json') #/www/dk_project/dk_app/apphub/apphub/apps.json
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance") or cls._instance is None:
cls._instance = super(AppHub, cls).__new__(cls)
return cls._instance
@classmethod
def get_config(cls):
'''
@name 获取外部应用配置
'''
if not os.path.exists(cls.hub_config_path):
apphub_config = {
"git_config": {
"git_url": "",
"git_branch": "main",
"user_config": {
"name": "",
"password": ""
}
}
}
public.writeFile(cls.hub_config_path, json.dumps(apphub_config))
return json.loads(public.readFile(cls.hub_config_path))
def install_apphub(self,get):
git_install = GitInstall.install_git()
if not git_install:
return public.return_message(-1, 0, public.lang("If the installation fails, check the network or install git manually"))
return public.return_message(0, 0, public.lang("The environment was successfully installed"))
def get_hub_apps(self):
'''
@name 获取外部应用列表
'''
res = []
try:
if os.path.exists(AppHub.hub_apps_path):
res=json.loads(public.readFile(self.hub_apps_path))
except:
pass
return res
def generate_apphub(self, get):
'''
@name 解析外部应用列表
'''
apps = []
if not os.path.isdir(self.hub_home_path):
return public.return_message(-1, 0, public.lang("The apphub directory does not exist"))
for name in os.listdir(self.hub_home_path):
app_dir = os.path.join(self.hub_home_path, name)
if not os.path.isdir(app_dir): continue
app_info=public.readFile(os.path.join(app_dir, 'app.json'))
if not app_info: continue
try:
app_info = json.loads(app_info)
except Exception as e:
continue
if "reuse" not in app_info: app_info["reuse"] = True
if "icon" not in app_info: app_info["icon"] = ""
if "sort" not in app_info: app_info["sort"] = 999
if "cpu" not in app_info: app_info["cpu"] = 0
if "mem" not in app_info: app_info["mem"] = 0
if "disk" not in app_info: app_info["disk"] = 10240
if "installed" not in app_info: app_info["installed"] = False
if "updateat" not in app_info: app_info["updateat"] = 0
apps.append(app_info)
self.apphub_apps = apps
public.writeFile(self.hub_apps_path, json.dumps(apps, indent=4, ensure_ascii=False))
self.generate_apphub_icon()
return public.return_message(0, 0, public.lang("The resolution was successful"))
def generate_apphub_icon(self):
'''
@name 创建外部应用图标
#/static/img/soft_ico/apphub/ico-apphub_xxx.png
'''
apphub_ico_path = "{}/YakPanel/static/img/soft_ico/apphub/".format(public.get_panel_path())
if os.path.exists(apphub_ico_path):
public.ExecShell("rm -rf {}".format(apphub_ico_path))
public.ExecShell("mkdir -p {}".format(apphub_ico_path))
for name in os.listdir(self.hub_home_path):
app_dir = os.path.join(self.hub_home_path, name,'icon.png')
if not os.path.exists(app_dir): continue
app_icon_path = os.path.join(apphub_ico_path, "ico-apphub_{}.png".format(name))
public.ExecShell("cp {} {}".format(app_dir,app_icon_path))
return True
def set_apphub_git(self, get):
'''
@name 设置git配置
@param get: git_url, git_branch, user, password
'''
config = self.get_config()
git_config = config.get("git_config", {})
git_config["git_url"] = get.git_url.strip()
git_config["git_branch"] = get.git_branch.strip()
if "name" in get and "password" in get:
git_config["user_config"] = {
"name": get.get("name", ""),
"password": get.get("password", "")
}
config["git_config"] = git_config
public.writeFile(self.hub_config_path, json.dumps(config, indent=4, ensure_ascii=False))
return public.return_message(0, 0, public.lang("GIT INFORMATION IS SUCCESSFULLY CONFIGURED"))
def import_git_apphub(self,get):
'''
@name 从git导入外部应用
@param None
'''
if not GitInstall.installed():
return public.return_message(-1, 0, public.lang("If you don't have a git environment, please install git first"))
abs_path = os.path.dirname(self.hub_home_path)
if not os.path.exists(abs_path): os.makedirs(abs_path)
gitconfig = self.get_config()
if not gitconfig or not gitconfig.get("git_config", {}).get("git_url", ""):
return public.return_message(-1, 0, public.lang("Please set the git information first"))
git_url = gitconfig.get("git_config", {}).get("git_url", "")
git_user = gitconfig.get("git_config", {}).get("user_config", {})
git_branch = gitconfig.get("git_config", {}).get("git_branch", {})
git = GitTool(project_path=abs_path, git_url=git_url,user_config=git_user,git_id="-1")
public.ExecShell("rm -rf /tmp/git_-1_log.log")
res = git.pull(git_branch)
if res is not None:
return public.return_message(-1, 0, public.lang("Import from git failed"))
#解析全部应用
res = self.generate_apphub(get)
if not res["status"]:
return public.return_message(-1, 0, res["msg"])
#删除模板
public.ExecShell("rm -rf {}".format(os.path.join(AppHub.hub_home_path, "templates")))
public.set_module_logs('apphub', 'import_git_apphub', 1)
return public.return_message(0, 0, public.lang("Import from git successful"))
def import_zip_apphub(self, get):
'''
@name 从压缩到包导入外部应用
@param get: sfile: zip文件路径
'''
sfile = get.sfile.strip()
files = sfile.split(",")
for sfile in files:
if not sfile.endswith(('.zip', '.gz')):
return public.return_message(-1, 0, public.lang("The file format is incorrect, please select the zip or gz file"))
if not os.path.exists(self.hub_home_path):
os.makedirs(self.hub_home_path)
if sfile.endswith('.zip'):
res, err = public.ExecShell("unzip -o {} -d {}".format(sfile, self.hub_home_path))
elif sfile.endswith('.gz'):
res, err = public.ExecShell("tar -xzvf {} -C {}".format(sfile, self.hub_home_path))
else:
err = "{},Unsupported file formats".format(sfile)
if err:
return public.return_message(-1, 0, public.lang("Import failure:{}", str(err)))
res = self.generate_apphub(get)
if not res["status"]:
return public.return_message(-1, 0, res["msg"])
public.set_module_logs('apphub', 'import_zip_apphub', 1)
return public.return_message(0, 0, public.lang("Successful import"))
def parser_zip_apphub(self, get):
'''
@name 解析zip包
@param get: sfile: zip文件路径
@return app_list: 外部应用列表
'''
sfile = get.sfile.strip()
app_list = []
from mod.project.docker.apphub.tool import GzHandler, ZipHandler
if sfile.endswith(".gz"):
handler = GzHandler()
else:
handler = ZipHandler()
files = handler.get_files(sfile)
if 'status' in files:
return public.return_message(-1, 0, files['msg'])
for file, file_struck in files.items():
if 'app.json' in file_struck and file_struck['app.json']['is_dir'] == 0:
filename = file_struck['app.json']['fullpath']
appinfo = handler.get_file_info(sfile, filename)
if 'status' in appinfo and appinfo['status'] == False:
return public.return_message(-1, 0, appinfo['msg'])
try:
appinfo = json.loads(appinfo['data'])
appinfo["parser_from"] = sfile
app_list.append(appinfo)
except:
pass
return app_list

View File

@@ -0,0 +1,190 @@
import os
import json
import shutil
import datetime
import tarfile
import zipfile
import public
class BaseCompressHandler:
"""压缩文件处理基类"""
def __init__(self):
pass
def get_files(self, sfile):
"""获取压缩包内文件列表"""
pass
def get_file_info(self, sfile,filename):
"""获取压缩包内文件信息"""
pass
def check_file_exists(self, file_path):
"""检查文件是否存在"""
if not os.path.exists(file_path):
return False
return True
class GzHandler(BaseCompressHandler):
"""tar.gz压缩文件处理类"""
def get_filename(self, item):
"""获取压缩包文件名"""
filename = item.name
try:
filename = item.name.encode('cp437').decode('gbk')
except:
pass
if item.isdir():
filename += '/'
return filename
def check_file_type(self, file_path):
"""检查文件是否为tar文件"""
if not tarfile.is_tarfile(file_path):
if file_path[-3:] == ".gz":
return False, 'This is not tar.gz archive file, the gz archive file does not support preview, only decompression'
return False, 'Not a valid tar.gz archive file'
return True, ''
def get_files(self, sfile):
"""获取压缩包内文件列表"""
if not self.check_file_exists(sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
is_valid, message = self.check_file_type(sfile)
if not is_valid:
return public.returnMsg(False, message)
zip_file = tarfile.open(sfile)
data = {}
for item in zip_file.getmembers():
file_name = self.get_filename(item)
temp_list = file_name.split("/")
sub_data = data
for name in temp_list:
if not name: continue
if name not in sub_data:
if file_name.endswith(name) and not ".{}".format(name) in file_name:
sub_data[name] = {
'file_size': item.size,
'filename': name,
'fullpath': file_name,
'date_time': public.format_date(times=item.mtime),
'is_dir': 1 if item.isdir() else 0
}
else:
sub_data[name] = {}
sub_data = sub_data[name]
zip_file.close()
return data
def get_file_info(self, sfile, filename):
"""获取压缩包内文件信息"""
if not self.check_file_exists(sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
tmp_path = '{}/tmp/{}'.format(public.get_panel_path(), public.md5(sfile + filename))
result = {}
result['status'] = True
result['data'] = ''
with tarfile.open(sfile, 'r') as zip_file:
try:
zip_file.extract(filename, tmp_path)
result['data'] = public.readFile('{}/{}'.format(tmp_path, filename))
except:
pass
public.ExecShell("rm -rf {}".format(tmp_path))
return result
class ZipHandler(BaseCompressHandler):
"""zip压缩文件处理类"""
def check_file_type(self, sfile, is_close=False):
"""检查文件是否为zip文件"""
zip_file = None
try:
zip_file = zipfile.ZipFile(sfile)
except:
pass
if is_close and zip_file:
zip_file.close()
return zip_file
def get_filename(self, item):
"""获取压缩包文件名"""
path = item.filename
try:
path_name = path.encode('cp437').decode('utf-8')
except:
try:
path_name = path.encode('cp437').decode('gbk')
path_name = path_name.encode('utf-8').decode('utf-8')
except:
path_name = path
return path_name
def get_files(self, sfile):
"""获取压缩包内文件列表"""
if not self.check_file_exists(sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
zip_file = self.check_file_type(sfile)
if not zip_file:
return public.returnMsg(False, 'NOT_ZIP_FILE')
data = {}
for item in zip_file.infolist():
file_name = self.get_filename(item)
temp_list = file_name.lstrip("./").split("/")
sub_data = data
for name in temp_list:
if not name: continue
if name not in sub_data:
if file_name.endswith(name):
sub_data[name] = {
'file_size': item.file_size,
'compress_size': item.compress_size,
'compress_type': item.compress_type,
'filename': name,
'fullpath': file_name,
'date_time': datetime.datetime(*item.date_time).strftime("%Y-%m-%d %H:%M:%S"),
'is_dir': 1 if item.is_dir() else 0
}
else:
sub_data[name] = {}
sub_data = sub_data[name]
zip_file.close()
return data
def get_file_info(self, sfile,filename):
"""获取压缩包内文件信息"""
if not self.check_file_exists(sfile):
return public.returnMsg(False, 'FILE_NOT_EXISTS')
result = {}
result['status'] = True
result['data'] = ''
with zipfile.ZipFile(sfile, 'r') as zip_file:
for item in zip_file.infolist():
z_filename = self.get_filename(item)
if z_filename == filename:
buff = zip_file.read(item.filename)
encoding, srcBody = public.decode_data(buff)
result['encoding'] = encoding
result['data'] = srcBody
break
return result