mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-10 16:00:31 +00:00
Compare commits
376
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d674f14ad | ||
|
|
b772effacd | ||
|
|
2417cc9eed | ||
|
|
c0796dc7c4 | ||
|
|
ff9747560e | ||
|
|
9c2828385b | ||
|
|
ad5df58d0f | ||
|
|
bb5e0f98c2 | ||
|
|
bfa2eb43ea | ||
|
|
be27983938 | ||
|
|
7ff1819799 | ||
|
|
7ff39c91da | ||
|
|
da23b8e6d9 | ||
|
|
a1799f5b4b | ||
|
|
34496f6a00 | ||
|
|
5d8208a061 | ||
|
|
f94e60c53c | ||
|
|
dd70be51b3 | ||
|
|
12e1a6a855 | ||
|
|
07648367c1 | ||
|
|
5b86ca38e0 | ||
|
|
79d9d9dfc2 | ||
|
|
e667477f4b | ||
|
|
0367149386 | ||
|
|
3d0ce2add4 | ||
|
|
17224b8920 | ||
|
|
05d125c762 | ||
|
|
e1a268b21d | ||
|
|
c486e8a354 | ||
|
|
eba74d91b3 | ||
|
|
613f8c2b57 | ||
|
|
16e2ad64a2 | ||
|
|
3274895dcf | ||
|
|
7367d47d27 | ||
|
|
4ed2a03222 | ||
|
|
586df4627a | ||
|
|
25181b6c27 | ||
|
|
72e6b9b188 | ||
|
|
e2efa20582 | ||
|
|
2cebb1beca | ||
|
|
fb24a699e6 | ||
|
|
1c16a0a69f | ||
|
|
26e480f242 | ||
|
|
fcf864156d | ||
|
|
d773391763 | ||
|
|
b47d63330e | ||
|
|
026ed1eb42 | ||
|
|
fb80724a96 | ||
|
|
a7ab866e95 | ||
|
|
06f636c9aa | ||
|
|
bbc5b8b731 | ||
|
|
cd154b13a9 | ||
|
|
f71a8a1603 | ||
|
|
d2ecae7e97 | ||
|
|
649e7b1912 | ||
|
|
2a97b0a9de | ||
|
|
5ca02a1dcf | ||
|
|
f088cec4d5 | ||
|
|
dde40064d2 | ||
|
|
597000ce52 | ||
|
|
4597cb26a1 | ||
|
|
e16ab09253 | ||
|
|
595be6f470 | ||
|
|
7afe9ac878 | ||
|
|
1f53b64b08 | ||
|
|
49ca336dd6 | ||
|
|
7cabb54c4e | ||
|
|
f55841f41c | ||
|
|
8983cb6186 | ||
|
|
222181baff | ||
|
|
02c002bda6 | ||
|
|
a5fbd01ea5 | ||
|
|
3652e07988 | ||
|
|
6ed000985c | ||
|
|
4a8b524a7c | ||
|
|
39509ad9a8 | ||
|
|
f977a2488d | ||
|
|
e7b1aadb0e | ||
|
|
339b085db7 | ||
|
|
a7c00900d8 | ||
|
|
99023569fc | ||
|
|
e4478da423 | ||
|
|
d0bb9165bf | ||
|
|
72a0e0200e | ||
|
|
5d83f21a26 | ||
|
|
56936aa6cd | ||
|
|
f4a649dc2f | ||
|
|
464ca8d272 | ||
|
|
7897bdabc4 | ||
|
|
3675c2f3f3 | ||
|
|
4eb264bea4 | ||
|
|
129e864975 | ||
|
|
7f05c1ef33 | ||
|
|
97d6d9c69f | ||
|
|
8937acee13 | ||
|
|
7518c5fe95 | ||
|
|
45fbb9f010 | ||
|
|
eff55da020 | ||
|
|
e87bf0b3fc | ||
|
|
3f141346fa | ||
|
|
34b39f6eb8 | ||
|
|
b8fd8ee0d9 | ||
|
|
b8895f215c | ||
|
|
c4b3efeb9d | ||
|
|
8f0c84c2a5 | ||
|
|
90b9c53420 | ||
|
|
46f9f4f561 | ||
|
|
de265a19b2 | ||
|
|
8af6868694 | ||
|
|
b1dde54e38 | ||
|
|
0a6163c89b | ||
|
|
07d0b37692 | ||
|
|
ac9881dd4c | ||
|
|
280c1b4fea | ||
|
|
6b24ee23e6 | ||
|
|
d93f8c5e6e | ||
|
|
384f065040 | ||
|
|
672fedc7e5 | ||
|
|
0433a26a07 | ||
|
|
4ebd4bddee | ||
|
|
030ab743f3 | ||
|
|
d4623a68dd | ||
|
|
a38d1c96d8 | ||
|
|
61ddf89fdd | ||
|
|
5c7d9b4ffe | ||
|
|
563ea985a4 | ||
|
|
657b2ddc8a | ||
|
|
50221c2ace | ||
|
|
b0bf3be707 | ||
|
|
caaf05897a | ||
|
|
0354b11ddb | ||
|
|
bdcf9b075e | ||
|
|
ab77aa2b5b | ||
|
|
1d54dcc95c | ||
|
|
0138d481a6 | ||
|
|
ba6cdc6e10 | ||
|
|
389d9c652f | ||
|
|
4942c6c206 | ||
|
|
40e264e0d4 | ||
|
|
b73b851245 | ||
|
|
49a777e2d8 | ||
|
|
7df43aeb59 | ||
|
|
86047c48e4 | ||
|
|
6000a206a8 | ||
|
|
da75f050e2 | ||
|
|
7ed81996b8 | ||
|
|
2040f8f3b0 | ||
|
|
c216726449 | ||
|
|
a33b17d5da | ||
|
|
58c994a3e2 | ||
|
|
98d01556c2 | ||
|
|
fd21e8de14 | ||
|
|
37ef2059f1 | ||
|
|
41c49ca95f | ||
|
|
1999f102bf | ||
|
|
aa91bb88bc | ||
|
|
7410a41331 | ||
|
|
a987370657 | ||
|
|
1883b05f26 | ||
|
|
c408619042 | ||
|
|
1181b13c83 | ||
|
|
c1aef03f09 | ||
|
|
6609871b1e | ||
|
|
813f1718fb | ||
|
|
49bcc14df7 | ||
|
|
28108a1c02 | ||
|
|
c169dfa395 | ||
|
|
3b26a692b6 | ||
|
|
9a6b51b092 | ||
|
|
c3121fcd38 | ||
|
|
7e8581a7de | ||
|
|
0ba83d1353 | ||
|
|
a302e100ec | ||
|
|
4f58fd492d | ||
|
|
0b06a4fac6 | ||
|
|
4e1a7bf42c | ||
|
|
ef2fb1c62e | ||
|
|
f5fcbcd87a | ||
|
|
986bffaf2b | ||
|
|
766a2a0546 | ||
|
|
291b594ad9 | ||
|
|
7742e3da38 | ||
|
|
c5f70eae4c | ||
|
|
8bdf02c4c0 | ||
|
|
8abe132c25 | ||
|
|
3a447b02a1 | ||
|
|
aa718eef88 | ||
|
|
60b1c9ba32 | ||
|
|
9b50581fd4 | ||
|
|
ee33fdab89 | ||
|
|
c8f19467ba | ||
|
|
1fc0f1c71b | ||
|
|
2258ba108d | ||
|
|
d21f4ffae6 | ||
|
|
4bd9c4c0fc | ||
|
|
29165f0f6f | ||
|
|
f75b786916 | ||
|
|
011914339e | ||
|
|
08a07214ef | ||
|
|
f682f07dbc | ||
|
|
50e99f1f4c | ||
|
|
feabc488fe | ||
|
|
72d3f5071b | ||
|
|
27dc662430 | ||
|
|
80e233c4a6 | ||
|
|
a099308a82 | ||
|
|
6f0673f184 | ||
|
|
b428e699db | ||
|
|
f4334eadc0 | ||
|
|
a2a6503030 | ||
|
|
9c22005b79 | ||
|
|
7448953b7d | ||
|
|
18214095ab | ||
|
|
bcfc78e510 | ||
|
|
cc6b506176 | ||
|
|
c61828fb39 | ||
|
|
23876ed186 | ||
|
|
ac4962cf19 | ||
|
|
d9e7c8d880 | ||
|
|
ea25b800d2 | ||
|
|
7ba06e73d7 | ||
|
|
39cf26628f | ||
|
|
ea7f324a9d | ||
|
|
789d451ea2 | ||
|
|
7313f3d591 | ||
|
|
1662546bef | ||
|
|
53f75086ec | ||
|
|
81fcc61ec9 | ||
|
|
324a47966b | ||
|
|
5a0c50b9a2 | ||
|
|
66465beb39 | ||
|
|
c5d403f10a | ||
|
|
598098c2ed | ||
|
|
bff1a8ad60 | ||
|
|
592e315f21 | ||
|
|
76933bc6ef | ||
|
|
0dc312db64 | ||
|
|
4deb92e715 | ||
|
|
bc95e47b92 | ||
|
|
f2335d313c | ||
|
|
4c287f4a2d | ||
|
|
0a6e1c275b | ||
|
|
ff2dc05e7f | ||
|
|
f62ce085bf | ||
|
|
29306827ba | ||
|
|
222d07175a | ||
|
|
663196c3d9 | ||
|
|
df839714a3 | ||
|
|
dcb004e983 | ||
|
|
cee0604efc | ||
|
|
dfbd364f60 | ||
|
|
339d6732d7 | ||
|
|
b0dbfb4c7c | ||
|
|
021603d25d | ||
|
|
a875e1ec5c | ||
|
|
5c5904216b | ||
|
|
1dae294d76 | ||
|
|
acbb151b15 | ||
|
|
a1311a2a0d | ||
|
|
bc8d564ce8 | ||
|
|
97cdf7bc78 | ||
|
|
ce69b4de01 | ||
|
|
e880df8142 | ||
|
|
a35ca87778 | ||
|
|
5a34e2d380 | ||
|
|
abf3247c50 | ||
|
|
8663ed129d | ||
|
|
c0a0f4c801 | ||
|
|
e84aa49003 | ||
|
|
6f45b90520 | ||
|
|
0685984a80 | ||
|
|
5f33c083bf | ||
|
|
ab0e0f3f43 | ||
|
|
6b62b84157 | ||
|
|
fd9627576b | ||
|
|
39f334f3a2 | ||
|
|
ca84909716 | ||
|
|
283609cf2d | ||
|
|
9591409fe2 | ||
|
|
9cf52ccc97 | ||
|
|
261cb2061b | ||
|
|
f45af6e0cc | ||
|
|
c752ea4959 | ||
|
|
b2b578a5f0 | ||
|
|
47e60bfdcb | ||
|
|
780b6cdec9 | ||
|
|
0a5b13a418 | ||
|
|
ebdc3f05de | ||
|
|
aad79077bf | ||
|
|
00b25b39c5 | ||
|
|
dd6a709053 | ||
|
|
99b04e3635 | ||
|
|
2e06b78409 | ||
|
|
c7d603e142 | ||
|
|
4fcf845934 | ||
|
|
83cefb2a72 | ||
|
|
7ab40996e0 | ||
|
|
bbe4d49947 | ||
|
|
b6fbacc992 | ||
|
|
89491eac56 | ||
|
|
acf27693b2 | ||
|
|
5fd9d20f99 | ||
|
|
fd9c421969 | ||
|
|
f5bae6d75c | ||
|
|
4ac8bc7bd2 | ||
|
|
ec81d0d2c3 | ||
|
|
815b633fb8 | ||
|
|
c69c76f97d | ||
|
|
75197db3e6 | ||
|
|
d09d686378 | ||
|
|
d6f16cf700 | ||
|
|
536a5fc1a0 | ||
|
|
a07df9d7fe | ||
|
|
e9c195c778 | ||
|
|
0637ca308b | ||
|
|
fd1e0e72a0 | ||
|
|
34b80373c7 | ||
|
|
1ade1b8d8b | ||
|
|
19fa30fb96 | ||
|
|
efe7815a7e | ||
|
|
e9b4ff1932 | ||
|
|
0dca3fc997 | ||
|
|
4e6ebb53ac | ||
|
|
83ed835c9e | ||
|
|
7bcc897379 | ||
|
|
cd2109fefe | ||
|
|
d337c4726d | ||
|
|
356e6a4ef6 | ||
|
|
037da3a7fd | ||
|
|
18462296ae | ||
|
|
1d76e54b0d | ||
|
|
22c903f555 | ||
|
|
6d4d53e2c7 | ||
|
|
6b81ae1b7b | ||
|
|
5b62a0f2b3 | ||
|
|
137465683a | ||
|
|
6be7b4a75a | ||
|
|
58ca377418 | ||
|
|
b173e808c7 | ||
|
|
ec44ba9335 | ||
|
|
f54ac59ff7 | ||
|
|
db44204c1a | ||
|
|
ec01aef71a | ||
|
|
b706774b5b | ||
|
|
9eee2d6b6f | ||
|
|
c9d4e2a4b5 | ||
|
|
4c4df5cbb0 | ||
|
|
cb69128838 | ||
|
|
81af207dc5 | ||
|
|
5e9c43fc71 | ||
|
|
fb44e3c1e2 | ||
|
|
7e23ae126a | ||
|
|
7e229c05e7 | ||
|
|
764fc8fec4 | ||
|
|
ad17918c84 | ||
|
|
d7013727b9 | ||
|
|
6a8bd11fc9 | ||
|
|
4df0c3e461 | ||
|
|
f8f47b51e9 | ||
|
|
b735178fcd | ||
|
|
1759c2c81e | ||
|
|
2be7054b40 | ||
|
|
c77d2f7dd6 | ||
|
|
3256ac9f44 | ||
|
|
b156ef9476 | ||
|
|
c49c16cbb5 | ||
|
|
2b7ec9ffe1 | ||
|
|
c2ad006a19 | ||
|
|
c12bab477c | ||
|
|
fe39545cf6 | ||
|
|
39d3b819fb | ||
|
|
04a0e15899 | ||
|
|
3dc81d85e9 | ||
|
|
5a8ddde495 | ||
|
|
4e6f872c02 | ||
|
|
e76836f394 |
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.2'
|
||||
node-version: '22.19.0'
|
||||
- name: Build Web
|
||||
run: |
|
||||
cd frontend && npm install && npm run build:pro
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.2'
|
||||
node-version: '22.19.0'
|
||||
- name: Build Web
|
||||
run: |
|
||||
cd frontend && npm install && npm run build:pro
|
||||
|
||||
@@ -32,6 +32,7 @@ builds:
|
||||
- arm
|
||||
- ppc64le
|
||||
- s390x
|
||||
- riscv64
|
||||
hooks:
|
||||
post:
|
||||
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
|
||||
@@ -57,6 +58,7 @@ builds:
|
||||
- arm
|
||||
- ppc64le
|
||||
- s390x
|
||||
- riscv64
|
||||
hooks:
|
||||
post:
|
||||
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
|
||||
|
||||
@@ -60,7 +60,7 @@ func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /ai/ollama/model/close [post]
|
||||
// @Router /ai/ollama/close [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"关闭 Ollama 模型连接 [name]","formatEN":"close conn for Ollama model [name]"}
|
||||
func (b *BaseApi) CloseOllamaModel(c *gin.Context) {
|
||||
var req dto.OllamaModelName
|
||||
|
||||
@@ -109,7 +109,7 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
|
||||
// @Success 200 {object} response.DatabaseConn
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/installed/conninfo/:key [get]
|
||||
// @Router /apps/installed/conninfo [POST]
|
||||
func (b *BaseApi) LoadConnInfo(c *gin.Context) {
|
||||
var req dto.OperationWithNameAndType
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
|
||||
@@ -74,7 +74,7 @@ func (b *BaseApi) RefreshToken(c *gin.Context) {
|
||||
// @Success 200 {array} object
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /buckets [post]
|
||||
// @Router /backups/buckets [post]
|
||||
func (b *BaseApi) ListBuckets(c *gin.Context) {
|
||||
var req dto.ForBuckets
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -133,6 +133,28 @@ func (b *BaseApi) UpdateBackup(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Upload file for recover
|
||||
// @Accept json
|
||||
// @Param request body dto.UploadForRecover true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /backups/upload [post]
|
||||
// @x-panel-log {"bodyKeys":["filePath"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传备份文件 [filePath]","formatEN":"upload backup file [filePath]"}
|
||||
func (b *BaseApi) UploadForRecover(c *gin.Context) {
|
||||
var req dto.UploadForRecover
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := backupService.UploadForRecover(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Load backup account options
|
||||
// @Accept json
|
||||
@@ -273,7 +295,7 @@ func (b *BaseApi) SearchBackupRecordsByCronjob(c *gin.Context) {
|
||||
// @Success 200 {string} filePath
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /backup/record/download [post]
|
||||
// @Router /backups/record/download [post]
|
||||
// @x-panel-log {"bodyKeys":["source","fileName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载备份记录 [source][fileName]","formatEN":"download backup records [source][fileName]"}
|
||||
func (b *BaseApi) DownloadRecord(c *gin.Context) {
|
||||
var req dto.DownloadRecord
|
||||
@@ -296,7 +318,7 @@ func (b *BaseApi) DownloadRecord(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /backup/record/description/update [post]
|
||||
// @Router /backups/record/description/update [post]
|
||||
func (b *BaseApi) UpdateRecordDescription(c *gin.Context) {
|
||||
var req dto.UpdateDescription
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -317,7 +339,7 @@ func (b *BaseApi) UpdateRecordDescription(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /record/del [post]
|
||||
// @Router /backups/record/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"backup_records","output_column":"file_name","output_value":"files"}],"formatZH":"删除备份记录 [files]","formatEN":"delete backup records [files]"}
|
||||
func (b *BaseApi) DeleteBackupRecord(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
|
||||
@@ -104,7 +104,7 @@ func (b *BaseApi) SearchClam(c *gin.Context) {
|
||||
// @Success 200 {object} dto.ClamBaseInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/clam/base [get]
|
||||
// @Router /toolbox/clam/base [post]
|
||||
func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) {
|
||||
info, err := clamService.LoadBaseInfo()
|
||||
if err != nil {
|
||||
@@ -152,7 +152,7 @@ func (b *BaseApi) CleanClamRecord(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := clamService.CleanRecord(req); err != nil {
|
||||
if err := clamService.CleanRecord(req.ID); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (b *BaseApi) SearchClamRecord(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
total, list, err := clamService.LoadRecords(req)
|
||||
total, list, err := clamService.SearchRecords(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
@@ -186,29 +186,6 @@ func (b *BaseApi) SearchClamRecord(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags Clam
|
||||
// @Summary Load clam record detail
|
||||
// @Accept json
|
||||
// @Param request body dto.ClamLogReq true "request"
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/clam/record/log [post]
|
||||
func (b *BaseApi) LoadClamRecordLog(c *gin.Context) {
|
||||
var req dto.ClamLogReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := clamService.LoadRecordLog(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, content)
|
||||
}
|
||||
|
||||
// @Tags Clam
|
||||
// @Summary Load clam file
|
||||
// @Accept json
|
||||
@@ -289,7 +266,7 @@ func (b *BaseApi) HandleClamScan(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := clamService.HandleOnce(req); err != nil {
|
||||
if err := clamService.HandleOnce(req.ID); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (b *BaseApi) LoadContainerUsers(c *gin.Context) {
|
||||
// @Summary List containers
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} string
|
||||
// @Success 200 {array} dto.ContainerOptions
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/list [post]
|
||||
@@ -65,6 +65,23 @@ func (b *BaseApi) ListContainer(c *gin.Context) {
|
||||
helper.SuccessWithData(c, containerService.List())
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary List containers by image
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} dto.ContainerOptions
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/list/byimage [post]
|
||||
func (b *BaseApi) ListContainerByImage(c *gin.Context) {
|
||||
var req dto.OperationWithName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, containerService.ListByImage(req.Name))
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Load containers status
|
||||
// @Accept json
|
||||
@@ -680,7 +697,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
|
||||
// @Param tail query string false "显示行号"
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/search/log [post]
|
||||
// @Router /containers/search/log [get]
|
||||
func (b *BaseApi) ContainerStreamLogs(c *gin.Context) {
|
||||
c.Header("Content-Type", "text/event-stream")
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
|
||||
+22
-24
@@ -226,6 +226,28 @@ func (b *BaseApi) CleanRecord(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Cronjob
|
||||
// @Summary Handle stop job
|
||||
// @Accept json
|
||||
// @Param request body dto.OperateByID true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /cronjobs/stop [post]
|
||||
func (b *BaseApi) StopCronJob(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := cronjobService.HandleStop(req.ID); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Cronjob
|
||||
// @Summary Delete cronjob
|
||||
// @Accept json
|
||||
@@ -314,30 +336,6 @@ func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Cronjob
|
||||
// @Summary Download cronjob records
|
||||
// @Accept json
|
||||
// @Param request body dto.CronjobDownload true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /cronjobs/download [post]
|
||||
// @x-panel-log {"bodyKeys":["recordID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"recordID","isList":false,"db":"job_records","output_column":"file","output_value":"file"}],"formatZH":"下载计划任务记录 [file]","formatEN":"download the cronjob record [file]"}
|
||||
func (b *BaseApi) TargetDownload(c *gin.Context) {
|
||||
var req dto.CronjobDownload
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
filePath, err := cronjobService.Download(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
// @Tags Cronjob
|
||||
// @Summary Handle cronjob once
|
||||
// @Accept json
|
||||
|
||||
@@ -83,6 +83,38 @@ func (b *BaseApi) UpdateAppLauncher(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load quick jump options
|
||||
// @Success 200 {Array} dto.QuickJump
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/quick/option [get]
|
||||
func (b *BaseApi) LoadQuickOption(c *gin.Context) {
|
||||
helper.SuccessWithData(c, dashboardService.LoadQuickOptions())
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Update quick jump
|
||||
// @Accept json
|
||||
// @Param request body dto.ChangeQuicks true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/quick/change [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"切换快速跳转","formatEN":"change quick jump"}
|
||||
func (b *BaseApi) UpdateQuickJump(c *gin.Context) {
|
||||
var req dto.ChangeQuicks
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := dashboardService.ChangeQuick(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load dashboard base info
|
||||
// @Accept json
|
||||
|
||||
@@ -160,7 +160,7 @@ func (b *BaseApi) GetDatabase(c *gin.Context) {
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /db/remote/del/check [post]
|
||||
// @Router /databases/db/del/check [post]
|
||||
func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags Disk Management
|
||||
// @Summary Get complete disk information
|
||||
// @Description Get information about all disks including partitioned and unpartitioned disks
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.CompleteDiskInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/disks [get]
|
||||
func (b *BaseApi) GetCompleteDiskInfo(c *gin.Context) {
|
||||
diskInfo, err := diskService.GetCompleteDiskInfo()
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, diskInfo)
|
||||
}
|
||||
|
||||
// @Tags Disk Management
|
||||
// @Summary Partition disk
|
||||
// @Description Create partition and format disk with specified filesystem
|
||||
// @Accept json
|
||||
// @Param request body request.DiskPartitionRequest true "partition request"
|
||||
// @Success 200 {string} string "Partition created successfully"
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/disks/partition [post]
|
||||
// @x-panel-log {"bodyKeys":["device", "filesystem", "mountPoint"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"对磁盘 [device] 进行分区,文件系统 [filesystem],挂载点 [mountPoint]","formatEN":"Partition disk [device] with filesystem [filesystem], mount point [mountPoint]"}
|
||||
func (b *BaseApi) PartitionDisk(c *gin.Context) {
|
||||
var req request.DiskPartitionRequest
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := diskService.PartitionDisk(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, result)
|
||||
}
|
||||
|
||||
// @Tags Disk Management
|
||||
// @Summary Mount disk
|
||||
// @Description Mount partition to specified mount point
|
||||
// @Accept json
|
||||
// @Param request body request.DiskMountRequest true "mount request"
|
||||
// @Success 200 {string} string "Disk mounted successfully"
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/disks/mount [post]
|
||||
// @x-panel-log {"bodyKeys":["device", "mountPoint"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"挂载磁盘 [device] 到 [mountPoint]","formatEN":"Mount disk [device] to [mountPoint]"}
|
||||
func (b *BaseApi) MountDisk(c *gin.Context) {
|
||||
var req request.DiskMountRequest
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err := diskService.MountDisk(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Disk Management
|
||||
// @Summary Unmount disk
|
||||
// @Description Unmount partition from mount point
|
||||
// @Accept json
|
||||
// @Param request body request.DiskUnmountRequest true "unmount request"
|
||||
// @Success 200 {string} string "Disk unmounted successfully"
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/disks/unmount [post]
|
||||
// @x-panel-log {"bodyKeys":["device", "mountPoint"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"卸载磁盘 [device] 从 [mountPoint]","formatEN":"Unmount disk [device] from [mountPoint]"}
|
||||
func (b *BaseApi) UnmountDisk(c *gin.Context) {
|
||||
var req request.DiskUnmountRequest
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err := diskService.UnmountDisk(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.Success(c)
|
||||
}
|
||||
@@ -17,8 +17,9 @@ var (
|
||||
appInstallService = service.NewIAppInstalledService()
|
||||
appIgnoreUpgradeService = service.NewIAppIgnoreUpgradeService()
|
||||
|
||||
aiToolService = service.NewIAIToolService()
|
||||
mcpServerService = service.NewIMcpServerService()
|
||||
aiToolService = service.NewIAIToolService()
|
||||
mcpServerService = service.NewIMcpServerService()
|
||||
tensorrtLLMService = service.NewITensorRTLLMService()
|
||||
|
||||
containerService = service.NewIContainerService()
|
||||
composeTemplateService = service.NewIComposeTemplateService()
|
||||
@@ -38,6 +39,7 @@ var (
|
||||
sshService = service.NewISSHService()
|
||||
firewallService = service.NewIFirewallService()
|
||||
monitorService = service.NewIMonitorService()
|
||||
systemService = service.NewISystemService()
|
||||
|
||||
deviceService = service.NewIDeviceService()
|
||||
fail2banService = service.NewIFail2BanService()
|
||||
@@ -71,4 +73,6 @@ var (
|
||||
taskService = service.NewITaskService()
|
||||
groupService = service.NewIGroupService()
|
||||
alertService = service.NewIAlertService()
|
||||
|
||||
diskService = service.NewIDiskService()
|
||||
)
|
||||
|
||||
@@ -880,7 +880,7 @@ func (b *BaseApi) GetPathByType(c *gin.Context) {
|
||||
// @Success 200 {object} dto.DiskInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mount [post]
|
||||
// @Router /files/mount [post]
|
||||
func (b *BaseApi) GetHostMount(c *gin.Context) {
|
||||
disks := fileService.GetHostMount()
|
||||
helper.SuccessWithData(c, disks)
|
||||
@@ -892,7 +892,7 @@ func (b *BaseApi) GetHostMount(c *gin.Context) {
|
||||
// @Success 200 {object} response.UserGroupResponse
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /user/group [post]
|
||||
// @Router /files/user/group [post]
|
||||
func (b *BaseApi) GetUsersAndGroups(c *gin.Context) {
|
||||
res, err := fileService.GetUsersAndGroups()
|
||||
if err != nil {
|
||||
@@ -901,3 +901,44 @@ func (b *BaseApi) GetUsersAndGroups(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Convert file
|
||||
// @Accept json
|
||||
// @Param request body request.FileConvert true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/convert [post]
|
||||
func (b *BaseApi) ConvertFile(c *gin.Context) {
|
||||
var req request.FileConvertRequest
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
fileService.Convert(req)
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Convert file
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/convert/log [post]
|
||||
func (b *BaseApi) ConvertLog(c *gin.Context) {
|
||||
var req dto.PageInfo
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
total, logs, err := fileService.ConvertLog(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Items: logs,
|
||||
Total: total,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func (b *BaseApi) OperateFirewall(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := firewallService.OperateFirewall(req.Operation); err != nil {
|
||||
if err := firewallService.OperateFirewall(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /agent/groups [post]
|
||||
// @Router /groups [post]
|
||||
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"}
|
||||
func (b *BaseApi) CreateGroup(c *gin.Context) {
|
||||
var req dto.GroupCreate
|
||||
@@ -35,7 +35,7 @@ func (b *BaseApi) CreateGroup(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /agent/groups/del [post]
|
||||
// @Router /groups/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"name","output_value":"name"},{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"}
|
||||
func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
@@ -57,7 +57,7 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /agent/groups/update [post]
|
||||
// @Router /groups/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"}
|
||||
func (b *BaseApi) UpdateGroup(c *gin.Context) {
|
||||
var req dto.GroupUpdate
|
||||
@@ -79,7 +79,7 @@ func (b *BaseApi) UpdateGroup(c *gin.Context) {
|
||||
// @Success 200 {array} dto.OperateByType
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /agent/groups/search [post]
|
||||
// @Router /groups/search [post]
|
||||
func (b *BaseApi) ListGroup(c *gin.Context) {
|
||||
var req dto.OperateByType
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
|
||||
@@ -116,7 +116,11 @@ func CheckBind(req interface{}, c *gin.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ErrResponse(ctx *gin.Context, code int) {
|
||||
ctx.JSON(code, nil)
|
||||
ctx.Abort()
|
||||
func GetParamInt32(paramName string, c *gin.Context) (int32, error) {
|
||||
idParam, ok := c.Params.Get(paramName)
|
||||
if !ok {
|
||||
return 0, errors.New("error id in path")
|
||||
}
|
||||
intNum, _ := strconv.Atoi(idParam)
|
||||
return int32(intNum), nil
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func (b *BaseApi) GetToolStatus(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/tool/create [post]
|
||||
// @Router /hosts/tool/init [post]
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 [type] 配置","formatEN":"create [type] config"}
|
||||
func (b *BaseApi) InitToolConfig(c *gin.Context) {
|
||||
var req request.HostToolCreate
|
||||
@@ -95,28 +95,6 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) {
|
||||
helper.SuccessWithData(c, config)
|
||||
}
|
||||
|
||||
// @Tags Host tool
|
||||
// @Summary Get tool logs
|
||||
// @Accept json
|
||||
// @Param request body request.HostToolLogReq true "request"
|
||||
// @Success 200 {string} logContent
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/tool/log [post]
|
||||
func (b *BaseApi) GetToolLog(c *gin.Context) {
|
||||
var req request.HostToolLogReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
logContent, err := hostToolService.GetToolLog(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, logContent)
|
||||
}
|
||||
|
||||
// @Tags Host tool
|
||||
// @Summary Create Supervisor process
|
||||
// @Accept json
|
||||
|
||||
@@ -9,14 +9,14 @@ import (
|
||||
// @Tags Container Image
|
||||
// @Summary Page images
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchWithPage true "request"
|
||||
// @Param request body dto.PageImage true "request"
|
||||
// @Produce json
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/image/search [post]
|
||||
func (b *BaseApi) SearchImage(c *gin.Context) {
|
||||
var req dto.SearchWithPage
|
||||
var req dto.PageImage
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (b *BaseApi) ListRepo(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/repo/status [get]
|
||||
// @Router /containers/repo/status [post]
|
||||
func (b *BaseApi) CheckRepoStatus(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
// @Success 200 {object} response.McpServersRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/search [post]
|
||||
// @Router /ai/mcp/search [post]
|
||||
func (b *BaseApi) PageMcpServers(c *gin.Context) {
|
||||
var req request.McpServerSearch
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -30,7 +30,7 @@ func (b *BaseApi) PageMcpServers(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/server [post]
|
||||
// @Router /ai/mcp/server [post]
|
||||
func (b *BaseApi) CreateMcpServer(c *gin.Context) {
|
||||
var req request.McpServerCreate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -51,7 +51,7 @@ func (b *BaseApi) CreateMcpServer(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/server/update [post]
|
||||
// @Router /ai/mcp/server/update [post]
|
||||
func (b *BaseApi) UpdateMcpServer(c *gin.Context) {
|
||||
var req request.McpServerUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -72,7 +72,7 @@ func (b *BaseApi) UpdateMcpServer(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/server/del [post]
|
||||
// @Router /ai/mcp/server/del [post]
|
||||
func (b *BaseApi) DeleteMcpServer(c *gin.Context) {
|
||||
var req request.McpServerDelete
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -93,7 +93,7 @@ func (b *BaseApi) DeleteMcpServer(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/server/op [post]
|
||||
// @Router /ai/mcp/server/op [post]
|
||||
func (b *BaseApi) OperateMcpServer(c *gin.Context) {
|
||||
var req request.McpServerOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -114,7 +114,7 @@ func (b *BaseApi) OperateMcpServer(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/domain/bind [post]
|
||||
// @Router /ai/mcp/domain/bind [post]
|
||||
func (b *BaseApi) BindMcpDomain(c *gin.Context) {
|
||||
var req request.McpBindDomain
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -135,7 +135,7 @@ func (b *BaseApi) BindMcpDomain(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/domain/update [post]
|
||||
// @Router /ai/mcp/domain/update [post]
|
||||
func (b *BaseApi) UpdateMcpBindDomain(c *gin.Context) {
|
||||
var req request.McpBindDomainUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -155,7 +155,7 @@ func (b *BaseApi) UpdateMcpBindDomain(c *gin.Context) {
|
||||
// @Success 200 {object} response.McpBindDomainRes
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /mcp/domain/get [get]
|
||||
// @Router /ai/mcp/domain/get [get]
|
||||
func (b *BaseApi) GetMcpBindDomain(c *gin.Context) {
|
||||
res, err := mcpServerService.GetBindDomain()
|
||||
if err != nil {
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"github.com/shirou/gopsutil/v4/net"
|
||||
)
|
||||
|
||||
// @Tags Monitor
|
||||
|
||||
@@ -129,7 +129,7 @@ func (b *BaseApi) BuildNginx(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /openresty/module/update [post]
|
||||
// @Router /openresty/modules/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 OpenResty 模块","formatEN":"Update OpenResty module"}
|
||||
func (b *BaseApi) UpdateNginxModule(c *gin.Context) {
|
||||
var req request.NginxModuleUpdate
|
||||
|
||||
@@ -36,3 +36,24 @@ func (b *BaseApi) StopProcess(c *gin.Context) {
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Process
|
||||
// @Summary Get Process Info By PID
|
||||
// @Param pid path int true "PID"
|
||||
// @Success 200 {object} websocket.PsProcessData
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /process/{pid} [get]
|
||||
func (b *BaseApi) GetProcessInfoByPID(c *gin.Context) {
|
||||
pid, err := helper.GetParamInt32("pid", c)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
data, err := processService.GetProcessInfoByPID(pid)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func (b *BaseApi) DeleteRuntime(c *gin.Context) {
|
||||
// @Success 200 {array} dto.AppResource
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /installed/delete/check/:id [get]
|
||||
// @Router /runtimes/installed/delete/check/:id [get]
|
||||
func (b *BaseApi) DeleteRuntimeCheck(c *gin.Context) {
|
||||
runTimeId, err := helper.GetIntParamByKey(c, "id")
|
||||
if err != nil {
|
||||
@@ -459,7 +459,7 @@ func (b *BaseApi) GetSupervisorProcess(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/supervisor/process/operate [post]
|
||||
// @Router /runtimes/supervisor/process [post]
|
||||
func (b *BaseApi) OperateSupervisorProcess(c *gin.Context) {
|
||||
var req request.PHPSupervisorProcessConfig
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -480,7 +480,7 @@ func (b *BaseApi) OperateSupervisorProcess(c *gin.Context) {
|
||||
// @Success 200 {string} content
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/supervisor/process/file/operate [post]
|
||||
// @Router /runtimes/supervisor/process/file [post]
|
||||
func (b *BaseApi) OperateSupervisorProcessFile(c *gin.Context) {
|
||||
var req request.PHPSupervisorProcessFileReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -497,7 +497,7 @@ func (b *BaseApi) OperateSupervisorProcessFile(c *gin.Context) {
|
||||
// @Tags Runtime
|
||||
// @Summary Update PHP container config
|
||||
// @Accept json
|
||||
// @Param request body request.PHPContainerUpdate true "request"
|
||||
// @Param request body request.PHPContainerConfig true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
@@ -518,7 +518,7 @@ func (b *BaseApi) UpdatePHPContainer(c *gin.Context) {
|
||||
// @Summary Get PHP container config
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
// @Success 200 {object} response.PHPContainerConfig
|
||||
// @Success 200 {object} request.PHPContainerConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/php/container/:id [get]
|
||||
@@ -539,7 +539,7 @@ func (b *BaseApi) GetPHPContainerConfig(c *gin.Context) {
|
||||
// @Tags Runtime
|
||||
// @Summary Update runtime remark
|
||||
// @Accept json
|
||||
// @Param request body request.RuntimeRemarkUpdate true "request"
|
||||
// @Param request body request.RuntimeRemark true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
@@ -555,3 +555,25 @@ func (b *BaseApi) UpdateRuntimeRemark(c *gin.Context) {
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Get PHP runtime status
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /runtimes/php/fpm/status/:id [get]
|
||||
func (b *BaseApi) GetFPMStatus(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
data, err := runtimeService.GetFPMStatus(id)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
+31
-35
@@ -2,12 +2,10 @@ package v2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -71,6 +69,16 @@ func (b *BaseApi) LoadBaseDir(c *gin.Context) {
|
||||
helper.SuccessWithData(c, global.Dir.DataDir)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load local conn
|
||||
// @Success 200 {object} dto.SSHConnData
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/ssh/conn [get]
|
||||
func (b *BaseApi) LoadLocalConn(c *gin.Context) {
|
||||
helper.SuccessWithData(c, settingService.GetLocalConn())
|
||||
}
|
||||
|
||||
func (b *BaseApi) CheckLocalConn(c *gin.Context) {
|
||||
_, err := loadLocalConn()
|
||||
helper.SuccessWithData(c, err == nil)
|
||||
@@ -87,6 +95,7 @@ func (b *BaseApi) CheckLocalConnByInfo(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, settingService.TestConnByInfo(req))
|
||||
}
|
||||
|
||||
@@ -96,51 +105,38 @@ func (b *BaseApi) CheckLocalConnByInfo(c *gin.Context) {
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/ssh [post]
|
||||
func (b *BaseApi) SaveLocalConnInfo(c *gin.Context) {
|
||||
func (b *BaseApi) SaveLocalConn(c *gin.Context) {
|
||||
var req dto.SSHConnData
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, settingService.SaveConnInfo(req))
|
||||
|
||||
if err := settingService.SaveConnInfo(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
func loadLocalConn() (*ssh.SSHClient, error) {
|
||||
itemPath := ""
|
||||
currentInfo, _ := user.Current()
|
||||
if len(currentInfo.HomeDir) == 0 {
|
||||
itemPath = "/root/.ssh/id_ed25519_1panel"
|
||||
} else {
|
||||
itemPath = path.Join(currentInfo.HomeDir, ".ssh/id_ed25519_1panel")
|
||||
}
|
||||
if _, err := os.Stat(itemPath); err != nil {
|
||||
_ = sshService.CreateRootCert(dto.CreateRootCert{EncryptionMode: "ed25519", Name: "id_ed25519_1panel", Description: "1Panel Terminal"})
|
||||
}
|
||||
|
||||
privateKey, _ := os.ReadFile(itemPath)
|
||||
connWithKey := ssh.ConnInfo{
|
||||
Addr: "127.0.0.1",
|
||||
User: "root",
|
||||
Port: 22,
|
||||
AuthMode: "key",
|
||||
PrivateKey: privateKey,
|
||||
}
|
||||
client, err := ssh.NewClient(connWithKey)
|
||||
if err == nil {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
connInfoInDB, err := settingService.GetSSHInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
connInfoInDB := settingService.GetSettingByKey("LocalSSHConn")
|
||||
if len(connInfoInDB) == 0 {
|
||||
return nil, errors.New("no such ssh conn info in db!")
|
||||
}
|
||||
var connInDB ssh.ConnInfo
|
||||
var connInDB model.LocalConnInfo
|
||||
if err := json.Unmarshal([]byte(connInfoInDB), &connInDB); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ssh.NewClient(connInDB)
|
||||
sshInfo := ssh.ConnInfo{
|
||||
Addr: connInDB.Addr,
|
||||
Port: int(connInDB.Port),
|
||||
User: connInDB.User,
|
||||
AuthMode: connInDB.AuthMode,
|
||||
Password: connInDB.Password,
|
||||
PrivateKey: []byte(connInDB.PrivateKey),
|
||||
PassPhrase: []byte(connInDB.PassPhrase),
|
||||
}
|
||||
return ssh.NewClient(sshInfo)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
|
||||
@@ -36,7 +36,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := snapshotService.SnapshotCreate(nil, req, 0, 0, 0); err != nil {
|
||||
if err := snapshotService.SnapshotCreate(nil, req, 0, 3); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/snapshot/recrete [post]
|
||||
// @Router /settings/snapshot/recreate [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"重试创建快照 [name]","formatEN":"recrete the snapshot [name]"}
|
||||
func (b *BaseApi) RecreateSnapshot(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
|
||||
+106
-47
@@ -68,21 +68,23 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Update host SSH setting by file
|
||||
// @Summary Generate host SSH secret
|
||||
// @Accept json
|
||||
// @Param request body dto.SSHConf true "request"
|
||||
// @Param request body dto.RootCertOperate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/conffile/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"}
|
||||
func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
|
||||
var req dto.SSHConf
|
||||
// @Router /hosts/ssh/cert [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
|
||||
func (b *BaseApi) CreateRootCert(c *gin.Context) {
|
||||
var req dto.RootCertOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := sshService.UpdateByFile(req.File); err != nil {
|
||||
if err := loadCertAfterDecrypt(&req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
}
|
||||
if err := sshService.CreateRootCert(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
@@ -90,45 +92,23 @@ func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Generate host SSH secret
|
||||
// @Summary Update host SSH secret
|
||||
// @Accept json
|
||||
// @Param request body dto.CreateRootCert true "request"
|
||||
// @Param request body dto.RootCertOperate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/ssh/cert [post]
|
||||
// @Router /hosts/ssh/cert/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
|
||||
func (b *BaseApi) CreateRootCert(c *gin.Context) {
|
||||
var req dto.CreateRootCert
|
||||
func (b *BaseApi) EditRootCert(c *gin.Context) {
|
||||
var req dto.RootCertOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if len(req.PassPhrase) != 0 {
|
||||
passPhrase, err := base64.StdEncoding.DecodeString(req.PassPhrase)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
req.PassPhrase = string(passPhrase)
|
||||
if err := loadCertAfterDecrypt(&req); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
}
|
||||
if len(req.PrivateKey) != 0 {
|
||||
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
req.PrivateKey = string(privateKey)
|
||||
}
|
||||
if len(req.PublicKey) != 0 {
|
||||
publicKey, err := base64.StdEncoding.DecodeString(req.PublicKey)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
req.PublicKey = string(publicKey)
|
||||
}
|
||||
|
||||
if err := sshService.CreateRootCert(req); err != nil {
|
||||
if err := sshService.EditRootCert(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
@@ -201,7 +181,7 @@ func (b *BaseApi) DeleteRootCert(c *gin.Context) {
|
||||
// @Summary Load host SSH logs
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchSSHLog true "request"
|
||||
// @Success 200 {object} dto.SSHLog
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/ssh/log [post]
|
||||
@@ -211,7 +191,54 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := sshService.LoadLog(c, req)
|
||||
total, data, err := sshService.LoadLog(c, req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
Total: total,
|
||||
Items: data,
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Export host SSH logs
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchSSHLog true "request"
|
||||
// @Success 200 {string} path
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/ssh/log/export [post]
|
||||
func (b *BaseApi) ExportSSHLogs(c *gin.Context) {
|
||||
var req dto.SearchSSHLog
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
tmpFile, err := sshService.ExportLog(c, req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, tmpFile)
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host SSH conf
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithName true "request"
|
||||
// @Success 200 {string} conf
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/ssh/file [post]
|
||||
func (b *BaseApi) LoadSSHFile(c *gin.Context) {
|
||||
var req dto.OperationWithName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := sshService.LoadSSHFile(req.Name)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
@@ -220,16 +247,48 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host SSH conf
|
||||
// @Success 200 {string} conf
|
||||
// @Summary Update host SSH setting by file
|
||||
// @Accept json
|
||||
// @Param request body dto.SSHConf true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/ssh/conf [get]
|
||||
func (b *BaseApi) LoadSSHConf(c *gin.Context) {
|
||||
data, err := sshService.LoadSSHConf()
|
||||
if err != nil {
|
||||
// @Router /hosts/ssh/file/update [post]
|
||||
// @x-panel-log {"bodyKeys":["key"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件 [key]","formatEN":"update SSH conf [key]"}
|
||||
func (b *BaseApi) UpdateSSHByFile(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := sshService.UpdateByFile(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
func loadCertAfterDecrypt(req *dto.RootCertOperate) error {
|
||||
if len(req.PassPhrase) != 0 {
|
||||
passPhrase, err := base64.StdEncoding.DecodeString(req.PassPhrase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.PassPhrase = string(passPhrase)
|
||||
}
|
||||
if len(req.PrivateKey) != 0 {
|
||||
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.PrivateKey = string(privateKey)
|
||||
}
|
||||
if len(req.PublicKey) != 0 {
|
||||
publicKey, err := base64.StdEncoding.DecodeString(req.PublicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.PublicKey = string(publicKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags Host
|
||||
// @Summary Check if a system component exists
|
||||
// @Accept json
|
||||
// @Param name query string true "Component name to check (e.g., rsync, docker)"
|
||||
// @Success 200 {object} response.ComponentInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/components/{name} [get]
|
||||
func (b *BaseApi) CheckComponentExistence(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
if name == "" {
|
||||
helper.BadRequest(c, errors.New("empty component name"))
|
||||
return
|
||||
}
|
||||
|
||||
info := systemService.IsComponentExist(name)
|
||||
helper.SuccessWithData(c, info)
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (b *BaseApi) PageTensorRTLLMs(c *gin.Context) {
|
||||
var req request.TensorRTLLMSearch
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
list := tensorrtLLMService.Page(req)
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
func (b *BaseApi) CreateTensorRTLLM(c *gin.Context) {
|
||||
var req request.TensorRTLLMCreate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := tensorrtLLMService.Create(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
func (b *BaseApi) UpdateTensorRTLLM(c *gin.Context) {
|
||||
var req request.TensorRTLLMUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := tensorrtLLMService.Update(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
func (b *BaseApi) DeleteTensorRTLLM(c *gin.Context) {
|
||||
var req request.TensorRTLLMDelete
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := tensorrtLLMService.Delete(req.ID)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
func (b *BaseApi) OperateTensorRTLLM(c *gin.Context) {
|
||||
var req request.TensorRTLLMOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := tensorrtLLMService.Operate(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
@@ -86,15 +85,16 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
source := c.Query("source")
|
||||
var containerID string
|
||||
var initCmd []string
|
||||
switch source {
|
||||
case "redis", "redis-cluster":
|
||||
containerID, initCmd, err = loadRedisInitCmd(c, source)
|
||||
initCmd, err = loadRedisInitCmd(c, source)
|
||||
case "ollama":
|
||||
containerID, initCmd, err = loadOllamaInitCmd(c)
|
||||
initCmd, err = loadOllamaInitCmd(c)
|
||||
case "container":
|
||||
containerID, initCmd, err = loadContainerInitCmd(c)
|
||||
initCmd, err = loadContainerInitCmd(c)
|
||||
case "database":
|
||||
initCmd, err = loadDatabaseInitCmd(c)
|
||||
default:
|
||||
if wshandleError(wsConn, fmt.Errorf("not support such source %s", source)) {
|
||||
return
|
||||
@@ -103,12 +103,10 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
pidMap := loadMapFromDockerTop(containerID)
|
||||
slave, err := terminal.NewCommand("docker", initCmd...)
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(containerID, strings.ReplaceAll(strings.Join(initCmd, " "), fmt.Sprintf("exec -it %s ", containerID), ""), pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||
@@ -127,18 +125,18 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
|
||||
_ = wsConn.WriteControl(websocket.CloseMessage, nil, dt)
|
||||
}
|
||||
|
||||
func loadRedisInitCmd(c *gin.Context, redisType string) (string, []string, error) {
|
||||
func loadRedisInitCmd(c *gin.Context, redisType string) ([]string, error) {
|
||||
name := c.Query("name")
|
||||
from := c.Query("from")
|
||||
commands := []string{"exec", "-it"}
|
||||
database, err := databaseService.Get(name)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("no such database in db, err: %v", err)
|
||||
return nil, fmt.Errorf("no such database in db, err: %v", err)
|
||||
}
|
||||
if from == "local" {
|
||||
redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: redisType})
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("no such app in db, err: %v", err)
|
||||
return nil, fmt.Errorf("no such app in db, err: %v", err)
|
||||
}
|
||||
name = redisInfo.ContainerName
|
||||
commands = append(commands, []string{name, "redis-cli"}...)
|
||||
@@ -152,38 +150,61 @@ func loadRedisInitCmd(c *gin.Context, redisType string) (string, []string, error
|
||||
commands = append(commands, []string{"-a", database.Password, "--no-auth-warning"}...)
|
||||
}
|
||||
}
|
||||
return name, commands, nil
|
||||
return commands, nil
|
||||
}
|
||||
|
||||
func loadOllamaInitCmd(c *gin.Context) (string, []string, error) {
|
||||
func loadOllamaInitCmd(c *gin.Context) ([]string, error) {
|
||||
name := c.Query("name")
|
||||
if cmd.CheckIllegal(name) {
|
||||
return "", nil, fmt.Errorf("ollama model %s contains illegal characters", name)
|
||||
return nil, fmt.Errorf("ollama model %s contains illegal characters", name)
|
||||
}
|
||||
ollamaInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: "", Type: "ollama"})
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("no such app in db, err: %v", err)
|
||||
return nil, fmt.Errorf("no such app in db, err: %v", err)
|
||||
}
|
||||
containerName := ollamaInfo.ContainerName
|
||||
return containerName, []string{"exec", "-it", containerName, "ollama", "run", name}, nil
|
||||
return []string{"exec", "-it", containerName, "ollama", "run", name}, nil
|
||||
}
|
||||
|
||||
func loadContainerInitCmd(c *gin.Context) (string, []string, error) {
|
||||
func loadContainerInitCmd(c *gin.Context) ([]string, error) {
|
||||
containerID := c.Query("containerid")
|
||||
command := c.Query("command")
|
||||
user := c.Query("user")
|
||||
if cmd.CheckIllegal(user, containerID, command) {
|
||||
return "", nil, fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID)
|
||||
return nil, fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID)
|
||||
}
|
||||
if len(command) == 0 || len(containerID) == 0 {
|
||||
return "", nil, fmt.Errorf("error param of command: %s or containerID: %s", command, containerID)
|
||||
return nil, fmt.Errorf("error param of command: %s or containerID: %s", command, containerID)
|
||||
}
|
||||
commands := []string{"exec", "-it", containerID, command}
|
||||
if len(user) != 0 {
|
||||
commands = []string{"exec", "-it", "-u", user, containerID, command}
|
||||
}
|
||||
|
||||
return containerID, commands, nil
|
||||
return commands, nil
|
||||
}
|
||||
|
||||
func loadDatabaseInitCmd(c *gin.Context) ([]string, error) {
|
||||
database := c.Query("database")
|
||||
databaseType := c.Query("databaseType")
|
||||
if len(database) == 0 || len(databaseType) == 0 {
|
||||
return nil, fmt.Errorf("error param of database: %s or database type: %s", database, databaseType)
|
||||
}
|
||||
databaseConn, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Type: databaseType, Name: database})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no such database in db, err: %v", err)
|
||||
}
|
||||
commands := []string{"exec", "-it", databaseConn.ContainerName}
|
||||
switch databaseType {
|
||||
case "mysql", "mysql-cluster":
|
||||
commands = append(commands, []string{"mysql", "-uroot", "-p" + databaseConn.Password}...)
|
||||
case "mariadb":
|
||||
commands = append(commands, []string{"mariadb", "-uroot", "-p" + databaseConn.Password}...)
|
||||
case "postgresql", "postgresql-cluster":
|
||||
commands = []string{"exec", "-e", fmt.Sprintf("PGPASSWORD=%s", databaseConn.Password), "-it", databaseConn.ContainerName, "psql", "-t", "-U", databaseConn.Username}
|
||||
}
|
||||
|
||||
return commands, nil
|
||||
}
|
||||
|
||||
func wshandleError(ws *websocket.Conn, err error) bool {
|
||||
@@ -206,42 +227,6 @@ func wshandleError(ws *websocket.Conn, err error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func loadMapFromDockerTop(containerID string) map[string]string {
|
||||
pidMap := make(map[string]string)
|
||||
sudo := cmd.SudoHandleCmd()
|
||||
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s docker top %s -eo pid,command ", sudo, containerID)
|
||||
if err != nil {
|
||||
return pidMap
|
||||
}
|
||||
lines := strings.Split(stdout, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
pidMap[parts[0]] = strings.Join(parts[1:], " ")
|
||||
}
|
||||
return pidMap
|
||||
}
|
||||
|
||||
func killBash(containerID, comm string, pidMap map[string]string) {
|
||||
sudo := cmd.SudoHandleCmd()
|
||||
newPidMap := loadMapFromDockerTop(containerID)
|
||||
for pid, command := range newPidMap {
|
||||
isOld := false
|
||||
for pid2 := range pidMap {
|
||||
if pid == pid2 {
|
||||
isOld = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isOld && command == comm {
|
||||
_, _ = cmd.RunDefaultWithStdoutBashCf("%s kill -9 %s", sudo, pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var upGrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024 * 1024 * 10,
|
||||
|
||||
@@ -527,7 +527,7 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/proxy/file [post]
|
||||
// @Router /websites/proxies/file [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"}
|
||||
func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
|
||||
var req request.NginxProxyUpdate
|
||||
@@ -840,7 +840,7 @@ func (b *BaseApi) CreateLoadBalance(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/lbs/delete [post]
|
||||
// @Router /websites/lbs/del [post]
|
||||
func (b *BaseApi) DeleteLoadBalance(c *gin.Context) {
|
||||
var req request.WebsiteLBDelete
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -953,7 +953,7 @@ func (b *BaseApi) GetProxyCache(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/realip [post]
|
||||
// @Router /websites/realip/config [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改 [domain] 网站真实IP配置 ","formatEN":"Modify the real IP configuration of [domain] website"}
|
||||
func (b *BaseApi) SetRealIPConfig(c *gin.Context) {
|
||||
var req request.WebsiteRealIP
|
||||
@@ -1121,3 +1121,85 @@ func (b *BaseApi) OperateCrossSiteAccess(c *gin.Context) {
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Exec Composer
|
||||
// @Accept json
|
||||
// @Param request body request.ExecComposerReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/exec/composer [post]
|
||||
func (b *BaseApi) ExecComposer(c *gin.Context) {
|
||||
var req request.ExecComposerReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.ExecComposer(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Batch operate websites
|
||||
// @Accept json
|
||||
// @Param request body request.BatchOpWebsite true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/batch/operate [post]
|
||||
func (b *BaseApi) BatchOpWebsites(c *gin.Context) {
|
||||
var req request.BatchWebsiteOp
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.BatchOpWebsite(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Get CORS Config
|
||||
// @Accept json
|
||||
// @Param id path int true "id"
|
||||
// @Success 200 {object} request.CorsConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/cors/{id} [get]
|
||||
func (b *BaseApi) GetCORSConfig(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
res, err := websiteService.GetCors(id)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Update CORS Config
|
||||
// @Accept json
|
||||
// @Param request body request.CorsConfigReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/cors/update [post]
|
||||
func (b *BaseApi) UpdateCORSConfig(c *gin.Context) {
|
||||
var req request.CorsConfigReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.UpdateCors(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
@@ -216,6 +219,79 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website SSL
|
||||
// @Summary Upload SSL file
|
||||
// @Accept multipart/form-data
|
||||
// @Param type formData string true "type"
|
||||
// @Param description formData string false "description"
|
||||
// @Param sslID formData string false "sslID"
|
||||
// @Param privateKeyFile formData file true "privateKeyFile"
|
||||
// @Param certificateFile formData file true "certificateFile"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/ssl/upload/file [post]
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传 ssl 文件 [type]","formatEN":"Upload ssl file [type]"}
|
||||
func (b *BaseApi) UploadSSLFile(c *gin.Context) {
|
||||
var req request.WebsiteSSLFileUpload
|
||||
|
||||
req.Type = c.PostForm("type")
|
||||
req.Description = c.PostForm("description")
|
||||
sslID := c.PostForm("sslID")
|
||||
if sslID != "" {
|
||||
req.SSLID, _ = strconv.ParseUint(sslID, 10, 64)
|
||||
}
|
||||
|
||||
privateKeyFile, err := c.FormFile("privateKeyFile")
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
certificateFile, err := c.FormFile("certificateFile")
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
privateKeyContent, err := readUploadedFile(privateKeyFile)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
certificateContent, err := readUploadedFile(certificateFile)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
uploadReq := request.WebsiteSSLUpload{
|
||||
Type: "paste",
|
||||
PrivateKey: string(privateKeyContent),
|
||||
Certificate: string(certificateContent),
|
||||
Description: req.Description,
|
||||
SSLID: uint(req.SSLID),
|
||||
}
|
||||
|
||||
if err := websiteSSLService.Upload(uploadReq); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func readUploadedFile(fileHeader *multipart.FileHeader) ([]byte, error) {
|
||||
file, err := fileHeader.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
return io.ReadAll(file)
|
||||
}
|
||||
|
||||
// @Tags Website SSL
|
||||
// @Summary Download SSL file
|
||||
// @Accept json
|
||||
@@ -245,3 +321,15 @@ func (b *BaseApi) DownloadWebsiteSSL(c *gin.Context) {
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name()))
|
||||
http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file)
|
||||
}
|
||||
|
||||
func (b *BaseApi) ImportMasterSSL(c *gin.Context) {
|
||||
var req model.WebsiteSSL
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteSSLService.ImportMasterSSL(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
+33
-28
@@ -36,40 +36,43 @@ type AlertSearch struct {
|
||||
}
|
||||
|
||||
type AlertDTO struct {
|
||||
ID uint `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Cycle uint `json:"cycle"`
|
||||
Count uint `json:"count"`
|
||||
Method string `json:"method"`
|
||||
Title string `json:"title"`
|
||||
Project string `json:"project"`
|
||||
Status string `json:"status"`
|
||||
SendCount uint `json:"sendCount"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID uint `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Cycle uint `json:"cycle"`
|
||||
Count uint `json:"count"`
|
||||
Method string `json:"method"`
|
||||
Title string `json:"title"`
|
||||
Project string `json:"project"`
|
||||
Status string `json:"status"`
|
||||
SendCount uint `json:"sendCount"`
|
||||
AdvancedParams string `json:"advancedParams"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type AlertCreate struct {
|
||||
Type string `json:"type" validate:"required"`
|
||||
Cycle uint `json:"cycle"`
|
||||
Count uint `json:"count"`
|
||||
Method string `json:"method" validate:"required"`
|
||||
Title string `json:"title"`
|
||||
Project string `json:"project"`
|
||||
Status string `json:"status"`
|
||||
SendCount uint `json:"sendCount"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Cycle uint `json:"cycle"`
|
||||
Count uint `json:"count"`
|
||||
Method string `json:"method" validate:"required"`
|
||||
Title string `json:"title"`
|
||||
Project string `json:"project"`
|
||||
Status string `json:"status"`
|
||||
SendCount uint `json:"sendCount"`
|
||||
AdvancedParams string `json:"advancedParams"`
|
||||
}
|
||||
|
||||
type AlertUpdate struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Type string `json:"type"`
|
||||
Cycle uint `json:"cycle"`
|
||||
Count uint `json:"count"`
|
||||
Method string `json:"method"`
|
||||
Title string `json:"title"`
|
||||
Project string `json:"project"`
|
||||
Status string `json:"status"`
|
||||
SendCount uint `json:"sendCount"`
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Type string `json:"type"`
|
||||
Cycle uint `json:"cycle"`
|
||||
Count uint `json:"count"`
|
||||
Method string `json:"method"`
|
||||
Title string `json:"title"`
|
||||
Project string `json:"project"`
|
||||
Status string `json:"status"`
|
||||
SendCount uint `json:"sendCount"`
|
||||
AdvancedParams string `json:"advancedParams"`
|
||||
}
|
||||
|
||||
type DeleteRequest struct {
|
||||
@@ -289,6 +292,7 @@ type AlertConfigTest struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Sender string `json:"sender"`
|
||||
UserName string `json:"userName"`
|
||||
Password string `json:"password"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
|
||||
@@ -320,6 +324,7 @@ type AlertEmailConfig struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Sender string `json:"sender"`
|
||||
UserName string `json:"userName"`
|
||||
Password string `json:"password"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
|
||||
|
||||
@@ -128,6 +128,7 @@ type Locale struct {
|
||||
Zh string `json:"zh"`
|
||||
Ko string `json:"ko"`
|
||||
Tr string `json:"tr"`
|
||||
Es string `json:"es-es" yaml:"es-es"`
|
||||
}
|
||||
|
||||
type AppForm struct {
|
||||
|
||||
@@ -53,6 +53,11 @@ type BackupOption struct {
|
||||
IsPublic bool `json:"isPublic"`
|
||||
}
|
||||
|
||||
type UploadForRecover struct {
|
||||
FilePath string `json:"filePath"`
|
||||
TargetDir string `json:"targetDir"`
|
||||
}
|
||||
|
||||
type CommonBackup struct {
|
||||
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql mysql-cluster postgresql-cluster redis-cluster"`
|
||||
Name string `json:"name"`
|
||||
@@ -94,6 +99,9 @@ type BackupRecords struct {
|
||||
DownloadAccountID uint `json:"downloadAccountID"`
|
||||
FileDir string `json:"fileDir"`
|
||||
FileName string `json:"fileName"`
|
||||
TaskID string `json:"taskID"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
|
||||
+16
-9
@@ -30,8 +30,10 @@ type ClamInfo struct {
|
||||
Path string `json:"path"`
|
||||
InfectedStrategy string `json:"infectedStrategy"`
|
||||
InfectedDir string `json:"infectedDir"`
|
||||
LastHandleDate string `json:"lastHandleDate"`
|
||||
LastRecordStatus string `json:"lastRecordStatus"`
|
||||
LastRecordTime string `json:"lastRecordTime"`
|
||||
Spec string `json:"spec"`
|
||||
Timeout uint `json:"timeout"`
|
||||
Description string `json:"description"`
|
||||
AlertCount uint `json:"alertCount"`
|
||||
AlertMethod string `json:"alertMethod"`
|
||||
@@ -41,6 +43,7 @@ type ClamLogSearch struct {
|
||||
PageInfo
|
||||
|
||||
ClamID uint `json:"clamID"`
|
||||
Status string `json:"status"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
EndTime time.Time `json:"endTime"`
|
||||
}
|
||||
@@ -56,13 +59,16 @@ type ClamFileReq struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
type ClamLog struct {
|
||||
Name string `json:"name"`
|
||||
ScanDate string `json:"scanDate"`
|
||||
ScanTime string `json:"scanTime"`
|
||||
InfectedFiles string `json:"infectedFiles"`
|
||||
TotalError string `json:"totalError"`
|
||||
Status string `json:"status"`
|
||||
type ClamRecord struct {
|
||||
ID uint `json:"id"`
|
||||
TaskID string `json:"taskID"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
ScanTime string `json:"scanTime"`
|
||||
InfectedFiles string `json:"infectedFiles"`
|
||||
TotalError string `json:"totalError"`
|
||||
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type ClamCreate struct {
|
||||
@@ -72,6 +78,7 @@ type ClamCreate struct {
|
||||
InfectedStrategy string `json:"infectedStrategy"`
|
||||
InfectedDir string `json:"infectedDir"`
|
||||
Spec string `json:"spec"`
|
||||
Timeout uint `json:"timeout"`
|
||||
Description string `json:"description"`
|
||||
AlertCount uint `json:"alertCount"`
|
||||
AlertTitle string `json:"alertTitle"`
|
||||
@@ -86,6 +93,7 @@ type ClamUpdate struct {
|
||||
InfectedStrategy string `json:"infectedStrategy"`
|
||||
InfectedDir string `json:"infectedDir"`
|
||||
Spec string `json:"spec"`
|
||||
Timeout uint `json:"timeout"`
|
||||
Description string `json:"description"`
|
||||
AlertCount uint `json:"alertCount"`
|
||||
AlertTitle string `json:"alertTitle"`
|
||||
@@ -98,7 +106,6 @@ type ClamUpdateStatus struct {
|
||||
}
|
||||
|
||||
type ClamDelete struct {
|
||||
RemoveRecord bool `json:"removeRecord"`
|
||||
RemoveInfected bool `json:"removeInfected"`
|
||||
Ids []uint `json:"ids" validate:"required"`
|
||||
}
|
||||
|
||||
+27
-21
@@ -71,7 +71,6 @@ type ResourceLimit struct {
|
||||
|
||||
type ContainerOperate struct {
|
||||
TaskID string `json:"taskID"`
|
||||
ContainerID string `json:"containerID"`
|
||||
ForcePull bool `json:"forcePull"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
@@ -107,10 +106,10 @@ type ContainerCreateByCommand struct {
|
||||
}
|
||||
|
||||
type ContainerUpgrade struct {
|
||||
TaskID string `json:"taskID"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
ForcePull bool `json:"forcePull"`
|
||||
TaskID string `json:"taskID"`
|
||||
Names []string `json:"names" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
ForcePull bool `json:"forcePull"`
|
||||
}
|
||||
|
||||
type ContainerListStats struct {
|
||||
@@ -144,6 +143,7 @@ type VolumeHelper struct {
|
||||
SourceDir string `json:"sourceDir"`
|
||||
ContainerDir string `json:"containerDir"`
|
||||
Mode string `json:"mode"`
|
||||
Shared string `json:"shared"`
|
||||
}
|
||||
type PortHelper struct {
|
||||
HostIP string `json:"hostIP"`
|
||||
@@ -209,11 +209,12 @@ type NetworkCreate struct {
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
Name string `json:"name"`
|
||||
Labels []string `json:"labels"`
|
||||
Driver string `json:"driver"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Name string `json:"name"`
|
||||
Labels []VolumeOption `json:"labels"`
|
||||
Driver string `json:"driver"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Options []VolumeOption `json:"options"`
|
||||
}
|
||||
type VolumeCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
@@ -221,7 +222,10 @@ type VolumeCreate struct {
|
||||
Options []string `json:"options"`
|
||||
Labels []string `json:"labels"`
|
||||
}
|
||||
|
||||
type VolumeOption struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
type BatchDelete struct {
|
||||
TaskID string `json:"taskID"`
|
||||
Force bool `json:"force"`
|
||||
@@ -229,15 +233,16 @@ type BatchDelete struct {
|
||||
}
|
||||
|
||||
type ComposeInfo struct {
|
||||
Name string `json:"name"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
ContainerNumber int `json:"containerNumber"`
|
||||
ConfigFile string `json:"configFile"`
|
||||
Workdir string `json:"workdir"`
|
||||
Path string `json:"path"`
|
||||
Containers []ComposeContainer `json:"containers"`
|
||||
Env []string `json:"env"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
ContainerCount int `json:"containerCount"`
|
||||
RunningCount int `json:"runningCount"`
|
||||
ConfigFile string `json:"configFile"`
|
||||
Workdir string `json:"workdir"`
|
||||
Path string `json:"path"`
|
||||
Containers []ComposeContainer `json:"containers"`
|
||||
Env []string `json:"env"`
|
||||
}
|
||||
type ComposeContainer struct {
|
||||
ContainerID string `json:"containerID"`
|
||||
@@ -257,8 +262,9 @@ type ComposeCreate struct {
|
||||
type ComposeOperation struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path"`
|
||||
Operation string `json:"operation" validate:"required,oneof=up start stop down delete"`
|
||||
Operation string `json:"operation" validate:"required,oneof=up start restart stop down delete"`
|
||||
WithFile bool `json:"withFile"`
|
||||
Force bool `josn:"force"`
|
||||
}
|
||||
type ComposeUpdate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
|
||||
@@ -65,11 +65,6 @@ type CronjobUpdateStatus struct {
|
||||
Status string `json:"status" validate:"required"`
|
||||
}
|
||||
|
||||
type CronjobDownload struct {
|
||||
RecordID uint `json:"recordID" validate:"required"`
|
||||
BackupAccountID uint `json:"backupAccountID" validate:"required"`
|
||||
}
|
||||
|
||||
type CronjobClean struct {
|
||||
IsDelete bool `json:"isDelete"`
|
||||
CleanData bool `json:"cleanData"`
|
||||
|
||||
@@ -23,9 +23,25 @@ type DashboardBase struct {
|
||||
CPULogicalCores int `json:"cpuLogicalCores"`
|
||||
CPUModelName string `json:"cpuModelName"`
|
||||
|
||||
QuickJumps []QuickJump `json:"quickJump"`
|
||||
CurrentInfo DashboardCurrent `json:"currentInfo"`
|
||||
}
|
||||
|
||||
type ChangeQuicks struct {
|
||||
Quicks []QuickJump `json:"quicks"`
|
||||
}
|
||||
|
||||
type QuickJump struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
Title string `json:"title"`
|
||||
Detail string `json:"detail"`
|
||||
Recommend int `json:"recommend"`
|
||||
IsShow bool `json:"isShow"`
|
||||
Router string `json:"router"`
|
||||
}
|
||||
|
||||
type OsInfo struct {
|
||||
OS string `json:"os"`
|
||||
Platform string `json:"platform"`
|
||||
|
||||
@@ -329,3 +329,8 @@ type LoadRedisStatus struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
}
|
||||
|
||||
type DBResource struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ type SwapHelper struct {
|
||||
Size uint64 `json:"size"`
|
||||
Used string `json:"used"`
|
||||
|
||||
IsNew bool `json:"isNew"`
|
||||
IsNew bool `json:"isNew"`
|
||||
TaskID string `json:"taskID"`
|
||||
}
|
||||
|
||||
type TimeZoneOptions struct {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package dto
|
||||
|
||||
type LsblkDevice struct {
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
Type string `json:"type"`
|
||||
MountPoint *string `json:"mountpoint"`
|
||||
FsType *string `json:"fstype"`
|
||||
Model *string `json:"model"`
|
||||
Serial string `json:"serial"`
|
||||
Tran string `json:"tran"`
|
||||
Rota bool `json:"rota"`
|
||||
Children []LsblkDevice `json:"children,omitempty"`
|
||||
}
|
||||
|
||||
type LsblkOutput struct {
|
||||
BlockDevices []LsblkDevice `json:"blockdevices"`
|
||||
}
|
||||
|
||||
type DiskFormatRequest struct {
|
||||
Device string `json:"device" `
|
||||
Filesystem string `json:"filesystem" `
|
||||
Label string `json:"label,omitempty" `
|
||||
QuickFormat bool `json:"quickFormat,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dto
|
||||
|
||||
type LogFileRes struct {
|
||||
Lines []string `json:"lines"`
|
||||
IsEndOfFile bool `json:"isEndOfFile"`
|
||||
TotalPages int `json:"totalPages"`
|
||||
TotalLines int `json:"totalLines"`
|
||||
}
|
||||
@@ -17,7 +17,8 @@ type RuleSearch struct {
|
||||
}
|
||||
|
||||
type FirewallOperation struct {
|
||||
Operation string `json:"operation" validate:"required,oneof=start stop restart disablePing enablePing"`
|
||||
Operation string `json:"operation" validate:"required,oneof=start stop restart disablePing enablePing"`
|
||||
WithDockerRestart bool `json:"withDockerRestart"`
|
||||
}
|
||||
|
||||
type PortRuleOperate struct {
|
||||
@@ -36,6 +37,7 @@ type ForwardRuleOperate struct {
|
||||
Operation string `json:"operation" validate:"required,oneof=add remove"`
|
||||
Num string `json:"num"`
|
||||
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
|
||||
Interface string `json:"interface"`
|
||||
Port string `json:"port" validate:"required"`
|
||||
TargetIP string `json:"targetIP"`
|
||||
TargetPort string `json:"targetPort" validate:"required"`
|
||||
|
||||
+13
-6
@@ -2,12 +2,19 @@ package dto
|
||||
|
||||
import "time"
|
||||
|
||||
type PageImage struct {
|
||||
PageInfo
|
||||
Name string `json:"name"`
|
||||
OrderBy string `json:"orderBy" validate:"required,oneof=size tags createdAt isUsed"`
|
||||
Order string `json:"order" validate:"required,oneof=null ascending descending"`
|
||||
}
|
||||
|
||||
type ImageInfo struct {
|
||||
ID string `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
IsUsed bool `json:"isUsed"`
|
||||
Tags []string `json:"tags"`
|
||||
Size string `json:"size"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type ImageLoad struct {
|
||||
@@ -23,14 +30,14 @@ type ImageBuild struct {
|
||||
}
|
||||
|
||||
type ImagePull struct {
|
||||
TaskID string `json:"taskID"`
|
||||
RepoID uint `json:"repoID"`
|
||||
ImageName string `json:"imageName" validate:"required"`
|
||||
TaskID string `json:"taskID"`
|
||||
RepoID uint `json:"repoID"`
|
||||
ImageName []string `json:"imageName" validate:"required"`
|
||||
}
|
||||
|
||||
type ImageTag struct {
|
||||
SourceID string `json:"sourceID" validate:"required"`
|
||||
TargetName string `json:"targetName" validate:"required"`
|
||||
SourceID string `json:"sourceID" validate:"required"`
|
||||
Tags []string `json:"tags" validate:"required"`
|
||||
}
|
||||
|
||||
type ImagePush struct {
|
||||
|
||||
@@ -40,6 +40,7 @@ type AppContainerConfig struct {
|
||||
WebUI string `json:"webUI"`
|
||||
Type string `json:"type"`
|
||||
SpecifyIP string `json:"specifyIP"`
|
||||
RestartPolicy string `json:"restartPolicy" validate:"omitempty,oneof=always unless-stopped no on-failure"`
|
||||
}
|
||||
|
||||
type AppInstalledSearch struct {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package request
|
||||
|
||||
type DiskPartitionRequest struct {
|
||||
Device string `json:"device" validate:"required"`
|
||||
Filesystem string `json:"filesystem" validate:"required,oneof=ext4 xfs"`
|
||||
Label string `json:"label"`
|
||||
AutoMount bool `json:"autoMount"`
|
||||
MountPoint string `json:"mountPoint" validate:"required"`
|
||||
}
|
||||
|
||||
type DiskMountRequest struct {
|
||||
Device string `json:"device" validate:"required"`
|
||||
MountPoint string `json:"mountPoint" validate:"required"`
|
||||
Filesystem string `json:"filesystem" validate:"required,oneof=ext4 xfs"`
|
||||
AutoMount bool `json:"autoMount"`
|
||||
}
|
||||
|
||||
type DiskUnmountRequest struct {
|
||||
MountPoint string `json:"mountPoint" validate:"required"`
|
||||
}
|
||||
@@ -148,3 +148,19 @@ type FileExistReq struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Dir string `json:"dir" validate:"required"`
|
||||
}
|
||||
|
||||
type FileConvert struct {
|
||||
Path string `json:"path" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
InputFile string `json:"inputFile" validate:"required"`
|
||||
Extension string `json:"extension" validate:"required"`
|
||||
OutputFormat string `json:"outputFormat" validate:"required"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type FileConvertRequest struct {
|
||||
Files []FileConvert `json:"files" validate:"required"`
|
||||
OutputPath string `json:"outputPath" validate:"required"`
|
||||
DeleteSource bool `json:"deleteSource"`
|
||||
TaskID string `json:"taskID"`
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ type SupervisorProcessConfig struct {
|
||||
Numprocs string `json:"numprocs"`
|
||||
AutoRestart string `json:"autoRestart"`
|
||||
AutoStart string `json:"autoStart"`
|
||||
Environment string `json:"environment"`
|
||||
}
|
||||
|
||||
type SupervisorProcessFileReq struct {
|
||||
|
||||
@@ -20,6 +20,7 @@ type McpServerCreate struct {
|
||||
HostIP string `json:"hostIP"`
|
||||
StreamableHttpPath string `json:"streamableHttpPath"`
|
||||
OutputTransport string `json:"outputTransport" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
}
|
||||
|
||||
type McpServerUpdate struct {
|
||||
|
||||
@@ -81,8 +81,8 @@ type NginxCommonReq struct {
|
||||
|
||||
type NginxAntiLeechUpdate struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
Extends string `json:"extends" validate:"required"`
|
||||
Return string `json:"return" validate:"required"`
|
||||
Extends string `json:"extends"`
|
||||
Return string `json:"return"`
|
||||
Enable bool `json:"enable" `
|
||||
ServerNames []string `json:"serverNames"`
|
||||
Cache bool `json:"cache"`
|
||||
|
||||
@@ -100,6 +100,7 @@ type PHPConfigUpdate struct {
|
||||
Scope string `json:"scope" validate:"required"`
|
||||
DisableFunctions []string `json:"disableFunctions"`
|
||||
UploadMaxSize string `json:"uploadMaxSize"`
|
||||
MaxExecutionTime string `json:"maxExecutionTime"`
|
||||
}
|
||||
|
||||
type PHPFileUpdate struct {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package request
|
||||
|
||||
import "github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
|
||||
type TensorRTLLMSearch struct {
|
||||
dto.PageInfo
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type TensorRTLLMCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
ContainerName string `json:"containerName" validate:"required"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
ModelDir string `json:"modelDir" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
Command string `json:"command" validate:"required"`
|
||||
ModelType string `json:"modelType"`
|
||||
ModelSpeedup bool `json:"modelSpeedup"`
|
||||
DockerConfig
|
||||
}
|
||||
|
||||
type TensorRTLLMUpdate struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
TensorRTLLMCreate
|
||||
}
|
||||
|
||||
type TensorRTLLMDelete struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type TensorRTLLMOperate struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required"`
|
||||
}
|
||||
|
||||
type DockerConfig struct {
|
||||
ExposedPorts []ExposedPort `json:"exposedPorts"`
|
||||
Environments []Environment `json:"environments"`
|
||||
Volumes []Volume `json:"volumes"`
|
||||
}
|
||||
@@ -95,6 +95,7 @@ type WebsiteDelete struct {
|
||||
DeleteApp bool `json:"deleteApp"`
|
||||
DeleteBackup bool `json:"deleteBackup"`
|
||||
ForceDelete bool `json:"forceDelete"`
|
||||
DeleteDB bool `json:"deleteDB"`
|
||||
}
|
||||
|
||||
type WebsiteOp struct {
|
||||
@@ -102,6 +103,12 @@ type WebsiteOp struct {
|
||||
Operate string `json:"operate"`
|
||||
}
|
||||
|
||||
type BatchWebsiteOp struct {
|
||||
IDs []uint `json:"ids" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required"`
|
||||
TaskID string `json:"taskID" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteRedirectUpdate struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
@@ -152,21 +159,22 @@ type WebsiteDomainDelete struct {
|
||||
}
|
||||
|
||||
type WebsiteHTTPSOp struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Enable bool `json:"enable"`
|
||||
WebsiteSSLID uint `json:"websiteSSLId"`
|
||||
Type string `json:"type" validate:"oneof=existed auto manual"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKeyPath string `json:"privateKeyPath"`
|
||||
CertificatePath string `json:"certificatePath"`
|
||||
ImportType string `json:"importType"`
|
||||
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
|
||||
SSLProtocol []string `json:"SSLProtocol"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
Hsts bool `json:"hsts"`
|
||||
HttpsPorts []int `json:"httpsPorts"`
|
||||
Http3 bool `json:"http3"`
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Enable bool `json:"enable"`
|
||||
WebsiteSSLID uint `json:"websiteSSLId"`
|
||||
Type string `json:"type" validate:"oneof=existed auto manual"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKeyPath string `json:"privateKeyPath"`
|
||||
CertificatePath string `json:"certificatePath"`
|
||||
ImportType string `json:"importType"`
|
||||
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
|
||||
SSLProtocol []string `json:"SSLProtocol"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
Hsts bool `json:"hsts"`
|
||||
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
|
||||
HttpsPorts []int `json:"httpsPorts"`
|
||||
Http3 bool `json:"http3"`
|
||||
}
|
||||
|
||||
type WebsiteNginxUpdate struct {
|
||||
@@ -203,22 +211,39 @@ type WebsiteUpdateDirPermission struct {
|
||||
}
|
||||
|
||||
type WebsiteProxyConfig struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required"`
|
||||
Enable bool `json:"enable" `
|
||||
Cache bool `json:"cache" `
|
||||
CacheTime int `json:"cacheTime" `
|
||||
CacheUnit string `json:"cacheUnit"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Modifier string `json:"modifier"`
|
||||
Match string `json:"match" validate:"required"`
|
||||
ProxyPass string `json:"proxyPass" validate:"required"`
|
||||
ProxyHost string `json:"proxyHost" validate:"required"`
|
||||
Content string `json:"content"`
|
||||
FilePath string `json:"filePath"`
|
||||
Replaces map[string]string `json:"replaces"`
|
||||
SNI bool `json:"sni"`
|
||||
ProxySSLName string `json:"proxySSLName"`
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required"`
|
||||
Enable bool `json:"enable" `
|
||||
Cache bool `json:"cache" `
|
||||
CacheTime int `json:"cacheTime"`
|
||||
CacheUnit string `json:"cacheUnit"`
|
||||
ServerCacheTime int `json:"serverCacheTime"`
|
||||
ServerCacheUnit string `json:"serverCacheUnit"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Modifier string `json:"modifier"`
|
||||
Match string `json:"match" validate:"required"`
|
||||
ProxyPass string `json:"proxyPass" validate:"required"`
|
||||
ProxyHost string `json:"proxyHost" validate:"required"`
|
||||
Content string `json:"content"`
|
||||
FilePath string `json:"filePath"`
|
||||
Replaces map[string]string `json:"replaces"`
|
||||
SNI bool `json:"sni"`
|
||||
ProxySSLName string `json:"proxySSLName"`
|
||||
CorsConfig
|
||||
}
|
||||
|
||||
type CorsConfig struct {
|
||||
Cors bool `json:"cors"`
|
||||
AllowOrigins string `json:"allowOrigins"`
|
||||
AllowMethods string `json:"allowMethods"`
|
||||
AllowHeaders string `json:"allowHeaders"`
|
||||
AllowCredentials bool `json:"allowCredentials"`
|
||||
Preflight bool `json:"preflight"`
|
||||
}
|
||||
|
||||
type CorsConfigReq struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
CorsConfig
|
||||
}
|
||||
|
||||
type WebsiteProxyReq struct {
|
||||
@@ -283,8 +308,8 @@ type WebsiteRealIP struct {
|
||||
|
||||
type ChangeDatabase struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
DatabaseID uint `json:"databaseID" validate:"required"`
|
||||
DatabaseType string `json:"databaseType" validate:"required"`
|
||||
DatabaseID uint `json:"databaseID" `
|
||||
DatabaseType string `json:"databaseType" `
|
||||
}
|
||||
|
||||
type WebsiteProxyDel struct {
|
||||
@@ -296,3 +321,13 @@ type CrossSiteAccessOp struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
Operation string `json:"operation" validate:"required,oneof=Enable Disable"`
|
||||
}
|
||||
|
||||
type ExecComposerReq struct {
|
||||
Command string `json:"command" validate:"required"`
|
||||
ExtCommand string `json:"extCommand"`
|
||||
Mirror string `json:"mirror" validate:"required"`
|
||||
Dir string `json:"dir" validate:"required"`
|
||||
User string `json:"user" validate:"required"`
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
TaskID string `json:"taskID" validate:"required"`
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ type WebsiteSSLSearch struct {
|
||||
dto.PageInfo
|
||||
AcmeAccountID string `json:"acmeAccountID"`
|
||||
Domain string `json:"domain"`
|
||||
OrderBy string `json:"orderBy" validate:"required,oneof=expire_date"`
|
||||
Order string `json:"order" validate:"required,oneof=null ascending descending"`
|
||||
}
|
||||
|
||||
type WebsiteSSLCreate struct {
|
||||
@@ -27,6 +29,8 @@ type WebsiteSSLCreate struct {
|
||||
Nameserver2 string `json:"nameserver2"`
|
||||
ExecShell bool `json:"execShell"`
|
||||
Shell string `json:"shell"`
|
||||
PushNode bool `json:"pushNode"`
|
||||
Nodes string `json:"nodes"`
|
||||
}
|
||||
|
||||
type WebsiteDNSReq struct {
|
||||
@@ -105,6 +109,8 @@ type WebsiteSSLUpdate struct {
|
||||
Nameserver2 string `json:"nameserver2"`
|
||||
ExecShell bool `json:"execShell"`
|
||||
Shell string `json:"shell"`
|
||||
PushNode bool `json:"pushNode"`
|
||||
Nodes string `json:"nodes"`
|
||||
}
|
||||
|
||||
type WebsiteSSLUpload struct {
|
||||
@@ -151,3 +157,9 @@ type WebsiteCAObtain struct {
|
||||
type WebsiteCARenew struct {
|
||||
SSLID uint `json:"SSLID" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteSSLFileUpload struct {
|
||||
Type string `json:"type"`
|
||||
Description string `json:"description"`
|
||||
SSLID uint64 `json:"sslID"`
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ type AppInstalledCheck struct {
|
||||
InstallPath string `json:"installPath"`
|
||||
HttpPort int `json:"httpPort"`
|
||||
HttpsPort int `json:"httpsPort"`
|
||||
WebsiteDir string `json:"websiteDir"`
|
||||
}
|
||||
|
||||
type AppDetailDTO struct {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package response
|
||||
|
||||
type DiskInfo struct {
|
||||
DiskBasicInfo
|
||||
Partitions []DiskBasicInfo `json:"partitions"`
|
||||
}
|
||||
|
||||
type DiskBasicInfo struct {
|
||||
Device string `json:"device"`
|
||||
Size string `json:"size"`
|
||||
Model string `json:"model"`
|
||||
DiskType string `json:"diskType"`
|
||||
IsRemovable bool `json:"isRemovable"`
|
||||
IsSystem bool `json:"isSystem"`
|
||||
Filesystem string `json:"filesystem"`
|
||||
Used string `json:"used"`
|
||||
Avail string `json:"avail"`
|
||||
UsePercent int `json:"usePercent"`
|
||||
MountPoint string `json:"mountPoint"`
|
||||
IsMounted bool `json:"isMounted"`
|
||||
Serial string `json:"serial"`
|
||||
}
|
||||
|
||||
type CompleteDiskInfo struct {
|
||||
Disks []DiskInfo `json:"disks"`
|
||||
UnpartitionedDisks []DiskBasicInfo `json:"unpartitionedDisks"`
|
||||
SystemDisk *DiskInfo `json:"systemDisk"`
|
||||
TotalDisks int `json:"totalDisks"`
|
||||
TotalCapacity int64 `json:"totalCapacity"`
|
||||
}
|
||||
|
||||
type MountInfo struct {
|
||||
Device string `json:"device"`
|
||||
MountPoint string `json:"mountPoint"`
|
||||
Filesystem string `json:"filesystem"`
|
||||
Options string `json:"options"`
|
||||
}
|
||||
@@ -44,6 +44,7 @@ type FileLineContent struct {
|
||||
TaskStatus string `json:"taskStatus"`
|
||||
Lines []string `json:"lines"`
|
||||
Scope string `json:"scope"`
|
||||
TotalLines int `json:"totalLines"`
|
||||
}
|
||||
|
||||
type FileExist struct {
|
||||
@@ -72,3 +73,11 @@ type DepthDirSizeRes struct {
|
||||
Path string `json:"path"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
type FileConvertLog struct {
|
||||
Date string `json:"date"`
|
||||
Type string `json:"type"`
|
||||
Log string `json:"log"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ type SupervisorProcessConfig struct {
|
||||
Status []ProcessStatus `json:"status"`
|
||||
AutoRestart string `json:"autoRestart"`
|
||||
AutoStart string `json:"autoStart"`
|
||||
Environment string `json:"environment"`
|
||||
}
|
||||
|
||||
type ProcessStatus struct {
|
||||
|
||||
@@ -78,3 +78,8 @@ type PHPExtensionRes struct {
|
||||
Extensions []string `json:"extensions"`
|
||||
SupportExtensions []SupportExtension `json:"supportExtensions"`
|
||||
}
|
||||
|
||||
type FpmStatusItem struct {
|
||||
Key string `json:"key"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package response
|
||||
|
||||
type ComponentInfo struct {
|
||||
Exists bool `json:"exists"`
|
||||
Version string `json:"version"`
|
||||
Path string `json:"path"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
)
|
||||
|
||||
type TensorRTLLMsRes struct {
|
||||
Items []TensorRTLLMDTO `json:"items"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
type TensorRTLLMDTO struct {
|
||||
model.TensorRTLLM
|
||||
Version string `json:"version"`
|
||||
Model string `json:"model"`
|
||||
Dir string `json:"dir"`
|
||||
ModelDir string `json:"modelDir"`
|
||||
Image string `json:"image"`
|
||||
Command string `json:"command"`
|
||||
|
||||
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
|
||||
Environments []request.Environment `json:"environments"`
|
||||
Volumes []request.Volume `json:"volumes"`
|
||||
}
|
||||
@@ -59,15 +59,16 @@ type WebsiteNginxConfig struct {
|
||||
}
|
||||
|
||||
type WebsiteHTTPS struct {
|
||||
Enable bool `json:"enable"`
|
||||
HttpConfig string `json:"httpConfig"`
|
||||
SSL model.WebsiteSSL `json:"SSL"`
|
||||
SSLProtocol []string `json:"SSLProtocol"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
Hsts bool `json:"hsts"`
|
||||
HttpsPorts []int `json:"httpsPorts"`
|
||||
HttpsPort string `json:"httpsPort"`
|
||||
Http3 bool `json:"http3"`
|
||||
Enable bool `json:"enable"`
|
||||
HttpConfig string `json:"httpConfig"`
|
||||
SSL model.WebsiteSSL `json:"SSL"`
|
||||
SSLProtocol []string `json:"SSLProtocol"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
Hsts bool `json:"hsts"`
|
||||
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
|
||||
HttpsPorts []int `json:"httpsPorts"`
|
||||
HttpsPort string `json:"httpsPort"`
|
||||
Http3 bool `json:"http3"`
|
||||
}
|
||||
|
||||
type WebsiteLog struct {
|
||||
@@ -81,6 +82,7 @@ type PHPConfig struct {
|
||||
Params map[string]string `json:"params"`
|
||||
DisableFunctions []string `json:"disableFunctions"`
|
||||
UploadMaxSize string `json:"uploadMaxSize"`
|
||||
MaxExecutionTime string `json:"maxExecutionTime"`
|
||||
}
|
||||
|
||||
type NginxRewriteRes struct {
|
||||
|
||||
@@ -69,6 +69,8 @@ type SSHConnData struct {
|
||||
Password string `json:"password"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
PassPhrase string `json:"passPhrase"`
|
||||
|
||||
LocalSSHConnShow string `json:"localSSHConnShow"`
|
||||
}
|
||||
|
||||
type SystemProxy struct {
|
||||
|
||||
@@ -22,7 +22,8 @@ type SSHInfo struct {
|
||||
CurrentUser string `json:"currentUser"`
|
||||
}
|
||||
|
||||
type CreateRootCert struct {
|
||||
type RootCertOperate struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Mode string `json:"mode"`
|
||||
EncryptionMode string `json:"encryptionMode" validate:"required,oneof=rsa ed25519 ecdsa dsa"`
|
||||
@@ -54,12 +55,6 @@ type SearchSSHLog struct {
|
||||
Info string `json:"info"`
|
||||
Status string `json:"Status" validate:"required,oneof=Success Failed All"`
|
||||
}
|
||||
type SSHLog struct {
|
||||
Logs []SSHHistory `json:"logs"`
|
||||
TotalCount int `json:"totalCount"`
|
||||
SuccessfulCount int `json:"successfulCount"`
|
||||
FailedCount int `json:"failedCount"`
|
||||
}
|
||||
|
||||
type SSHHistory struct {
|
||||
Date time.Time `json:"date"`
|
||||
|
||||
@@ -3,14 +3,15 @@ package model
|
||||
type Alert struct {
|
||||
BaseModel
|
||||
|
||||
Title string `gorm:"type:varchar(256);not null" json:"title"`
|
||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||
Cycle uint `gorm:"type:integer;not null" json:"cycle"`
|
||||
Count uint `gorm:"type:integer;not null" json:"count"`
|
||||
Project string `gorm:"type:varchar(64)" json:"project"`
|
||||
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
||||
Method string `gorm:"type:varchar(64);not null" json:"method"`
|
||||
SendCount uint `gorm:"type:integer" json:"sendCount"`
|
||||
Title string `gorm:"type:varchar(256);not null" json:"title"`
|
||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||
Cycle uint `gorm:"type:integer;not null" json:"cycle"`
|
||||
Count uint `gorm:"type:integer;not null" json:"count"`
|
||||
Project string `gorm:"type:varchar(64)" json:"project"`
|
||||
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
||||
Method string `gorm:"type:varchar(64);not null" json:"method"`
|
||||
SendCount uint `gorm:"type:integer" json:"sendCount"`
|
||||
AdvancedParams string `gorm:"type:longText" json:"advancedParam"`
|
||||
}
|
||||
|
||||
type AlertTask struct {
|
||||
@@ -43,3 +44,12 @@ type AlertConfig struct {
|
||||
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
||||
Config string `gorm:"type:varchar(256);not null" json:"config"`
|
||||
}
|
||||
|
||||
type LoginLog struct {
|
||||
BaseModel
|
||||
IP string `json:"ip"`
|
||||
Address string `json:"address"`
|
||||
Agent string `json:"agent"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
@@ -43,11 +43,17 @@ type App struct {
|
||||
func (i *App) IsLocalApp() bool {
|
||||
return i.Resource == constant.ResourceLocal
|
||||
}
|
||||
func (i *App) IsCustomApp() bool {
|
||||
return i.Resource == constant.AppResourceCustom
|
||||
}
|
||||
|
||||
func (i *App) GetAppResourcePath() string {
|
||||
if i.IsLocalApp() {
|
||||
//这里要去掉本地应用的local前缀
|
||||
return filepath.Join(global.Dir.LocalAppResourceDir, strings.TrimPrefix(i.Key, "local"))
|
||||
}
|
||||
if i.IsCustomApp() {
|
||||
return filepath.Join(global.Dir.CustomAppResourceDir, i.Key)
|
||||
}
|
||||
return filepath.Join(global.Dir.RemoteAppResourceDir, i.Key)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,3 +4,14 @@ type AppLauncher struct {
|
||||
BaseModel
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type QuickJump struct {
|
||||
BaseModel
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
Title string `json:"title"`
|
||||
Detail string `json:"detail"`
|
||||
Recommend int `json:"recommend"`
|
||||
IsShow bool `json:"isShow"`
|
||||
Router string `json:"router"`
|
||||
}
|
||||
|
||||
@@ -27,5 +27,8 @@ type BackupRecord struct {
|
||||
FileDir string `json:"fileDir"`
|
||||
FileName string `json:"fileName"`
|
||||
|
||||
TaskID string `json:"taskID"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
+20
-1
@@ -1,14 +1,33 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Clam struct {
|
||||
BaseModel
|
||||
|
||||
Name string `gorm:"not null" json:"name"`
|
||||
Status string `json:"status"`
|
||||
Path string `gorm:"not null" json:"path"`
|
||||
InfectedStrategy string `json:"infectedStrategy"`
|
||||
InfectedDir string `json:"infectedDir"`
|
||||
Spec string `json:"spec"`
|
||||
RetryTimes uint `json:"retryTimes"`
|
||||
Timeout uint `json:"timeout"`
|
||||
EntryID int `json:"entryID"`
|
||||
Description string `json:"description"`
|
||||
|
||||
Status string `json:"status"`
|
||||
IsExecuting bool `json:"isExecuting"`
|
||||
}
|
||||
|
||||
type ClamRecord struct {
|
||||
BaseModel
|
||||
|
||||
ClamID uint `json:"clamID"`
|
||||
TaskID string `json:"taskID"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
ScanTime string `json:"scanTime"`
|
||||
InfectedFiles string `json:"infectedFiles"`
|
||||
TotalError string `json:"totalError"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// BackupAccounts ---> SourceAccountIDs
|
||||
// BackupAccounts ---> DownloadAccountID
|
||||
type Cronjob struct {
|
||||
BaseModel
|
||||
|
||||
@@ -40,10 +38,13 @@ type Cronjob struct {
|
||||
IgnoreErr bool `json:"ignoreErr"`
|
||||
RetainCopies uint64 `json:"retainCopies"`
|
||||
|
||||
Status string `json:"status"`
|
||||
EntryIDs string `json:"entryIDs"`
|
||||
Records []JobRecords `json:"records"`
|
||||
Secret string `json:"secret"`
|
||||
IsExecuting bool `json:"isExecuting"`
|
||||
Status string `json:"status"`
|
||||
EntryIDs string `json:"entryIDs"`
|
||||
Records []JobRecords `json:"records"`
|
||||
Secret string `json:"secret"`
|
||||
|
||||
Config string `json:"config"`
|
||||
}
|
||||
|
||||
type JobRecords struct {
|
||||
|
||||
@@ -18,4 +18,5 @@ type Forward struct {
|
||||
Port string `gorm:"not null" json:"port"`
|
||||
TargetIP string `gorm:"not null" json:"targetIP"`
|
||||
TargetPort string `gorm:"not null" json:"targetPort"`
|
||||
Interface string `json:"interface"`
|
||||
}
|
||||
|
||||
@@ -17,4 +17,5 @@ type McpServer struct {
|
||||
HostIP string `json:"hostIP"`
|
||||
StreamableHttpPath string `json:"streamableHttpPath"`
|
||||
OutputTransport string `json:"outputTransport"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
@@ -2,14 +2,18 @@ package model
|
||||
|
||||
type MonitorBase struct {
|
||||
BaseModel
|
||||
Cpu float64 `json:"cpu"`
|
||||
Cpu float64 `json:"cpu"`
|
||||
TopCPU string `json:"topCPU"`
|
||||
TopCPUItems interface{} `gorm:"-" json:"topCPUItems"`
|
||||
|
||||
Memory float64 `json:"memory"`
|
||||
TopMem string `json:"topMem"`
|
||||
TopMemItems interface{} `gorm:"-" json:"topMemItems"`
|
||||
|
||||
LoadUsage float64 `json:"loadUsage"`
|
||||
CpuLoad1 float64 `json:"cpuLoad1"`
|
||||
CpuLoad5 float64 `json:"cpuLoad5"`
|
||||
CpuLoad15 float64 `json:"cpuLoad15"`
|
||||
|
||||
Memory float64 `json:"memory"`
|
||||
}
|
||||
|
||||
type MonitorIO struct {
|
||||
|
||||
@@ -49,3 +49,7 @@ func (r *Runtime) GetPHPPath() string {
|
||||
func (r *Runtime) GetLogPath() string {
|
||||
return path.Join(r.GetPath(), "build.log")
|
||||
}
|
||||
|
||||
func (r *Runtime) GetSlowLogPath() string {
|
||||
return path.Join(r.GetPath(), "log", "fpm.slow.log")
|
||||
}
|
||||
|
||||
@@ -15,3 +15,13 @@ type NodeInfo struct {
|
||||
ServerCrt string `json:"serverCrt"`
|
||||
ServerKey string `json:"serverKey"`
|
||||
}
|
||||
|
||||
type LocalConnInfo struct {
|
||||
Addr string `json:"addr"`
|
||||
Port uint `json:"port"`
|
||||
User string `json:"user"`
|
||||
AuthMode string `json:"authMode"`
|
||||
Password string `json:"password"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
PassPhrase string `json:"passPhrase"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package model
|
||||
|
||||
type TensorRTLLM struct {
|
||||
BaseModel
|
||||
Name string `json:"name"`
|
||||
DockerCompose string `json:"dockerCompose"`
|
||||
ContainerName string `json:"containerName"`
|
||||
Message string `json:"message"`
|
||||
Status string `json:"status"`
|
||||
Env string `json:"env"`
|
||||
TaskID string `json:"taskID"`
|
||||
ModelType string `json:"modelType"`
|
||||
ModelSpeedup bool `json:"modelSpeedup"`
|
||||
}
|
||||
@@ -10,32 +10,37 @@ import (
|
||||
|
||||
type WebsiteSSL struct {
|
||||
BaseModel
|
||||
PrimaryDomain string `json:"primaryDomain"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Pem string `json:"pem"`
|
||||
Domains string `json:"domains"`
|
||||
CertURL string `json:"certURL"`
|
||||
Type string `json:"type"`
|
||||
Provider string `json:"provider"`
|
||||
Organization string `json:"organization"`
|
||||
DnsAccountID uint `json:"dnsAccountId"`
|
||||
AcmeAccountID uint `gorm:"column:acme_account_id" json:"acmeAccountId" `
|
||||
CaID uint `json:"caId"`
|
||||
AutoRenew bool `json:"autoRenew"`
|
||||
ExpireDate time.Time `json:"expireDate"`
|
||||
StartDate time.Time `json:"startDate"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
KeyType string `json:"keyType"`
|
||||
PushDir bool `json:"pushDir"`
|
||||
Dir string `json:"dir"`
|
||||
Description string `json:"description"`
|
||||
SkipDNS bool `json:"skipDNS"`
|
||||
Nameserver1 string `json:"nameserver1"`
|
||||
Nameserver2 string `json:"nameserver2"`
|
||||
DisableCNAME bool `json:"disableCNAME"`
|
||||
ExecShell bool `json:"execShell"`
|
||||
Shell string `json:"shell"`
|
||||
PrimaryDomain string `json:"primaryDomain"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Pem string `json:"pem"`
|
||||
Domains string `json:"domains"`
|
||||
CertURL string `json:"certURL"`
|
||||
Type string `json:"type"`
|
||||
Provider string `json:"provider"`
|
||||
Organization string `json:"organization"`
|
||||
DnsAccountID uint `json:"dnsAccountId"`
|
||||
AcmeAccountID uint `gorm:"column:acme_account_id" json:"acmeAccountId" `
|
||||
CaID uint `json:"caId"`
|
||||
AutoRenew bool `json:"autoRenew"`
|
||||
ExpireDate time.Time `json:"expireDate"`
|
||||
StartDate time.Time `json:"startDate"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
KeyType string `json:"keyType"`
|
||||
PushDir bool `json:"pushDir"`
|
||||
Dir string `json:"dir"`
|
||||
Description string `json:"description"`
|
||||
SkipDNS bool `json:"skipDNS"`
|
||||
Nameserver1 string `json:"nameserver1"`
|
||||
Nameserver2 string `json:"nameserver2"`
|
||||
DisableCNAME bool `json:"disableCNAME"`
|
||||
ExecShell bool `json:"execShell"`
|
||||
Shell string `json:"shell"`
|
||||
MasterSSLID uint `json:"masterSslId"`
|
||||
Nodes string `json:"nodes"`
|
||||
PushNode bool `json:"pushNode"`
|
||||
PrivateKeyPath string `json:"privateKeyPath"`
|
||||
CertPath string `json:"certPath"`
|
||||
|
||||
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
|
||||
DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"`
|
||||
|
||||
+18
-1
@@ -33,6 +33,8 @@ type IAppRepo interface {
|
||||
BatchDelete(ctx context.Context, apps []model.App) error
|
||||
DeleteByIDs(ctx context.Context, ids []uint) error
|
||||
DeleteBy(opts ...DBOption) error
|
||||
|
||||
GetTopRecomment() ([]string, error)
|
||||
}
|
||||
|
||||
func NewIAppRepo() IAppRepo {
|
||||
@@ -44,7 +46,7 @@ func (a AppRepo) WithByLikeName(name string) DBOption {
|
||||
if len(name) == 0 {
|
||||
return g
|
||||
}
|
||||
return g.Where("name like ? or short_desc_zh like ? or short_desc_en like ?", "%"+name+"%", "%"+name+"%", "%"+name+"%")
|
||||
return g.Where("name like ? or description like ? or short_desc_zh like ? or short_desc_en like ?", "%"+name+"%", "%"+name+"%", "%"+name+"%", "%"+name+"%")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +125,21 @@ func (a AppRepo) GetBy(opts ...DBOption) ([]model.App, error) {
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (a AppRepo) GetTopRecomment() ([]string, error) {
|
||||
var (
|
||||
apps []model.App
|
||||
names []string
|
||||
)
|
||||
db := getDb().Model(&model.App{})
|
||||
if err := db.Order("recommend asc").Limit(6).Find(&apps).Error; err != nil {
|
||||
return names, err
|
||||
}
|
||||
for _, item := range apps {
|
||||
names = append(names, item.Key)
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func (a AppRepo) BatchCreate(ctx context.Context, apps []model.App) error {
|
||||
return getTx(ctx).Omit(clause.Associations).Create(&apps).Error
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ type ILauncherRepo interface {
|
||||
Create(launcher *model.AppLauncher) error
|
||||
Save(launcher *model.AppLauncher) error
|
||||
Delete(opts ...DBOption) error
|
||||
|
||||
GetQuickJump(opts ...DBOption) (model.QuickJump, error)
|
||||
ListQuickJump(withAll bool) []model.QuickJump
|
||||
UpdateQuicks(quicks []model.QuickJump) error
|
||||
}
|
||||
|
||||
func NewILauncherRepo() ILauncherRepo {
|
||||
@@ -57,3 +61,46 @@ func (u *LauncherRepo) Delete(opts ...DBOption) error {
|
||||
}
|
||||
return db.Delete(&model.AppLauncher{}).Error
|
||||
}
|
||||
|
||||
func (u *LauncherRepo) GetQuickJump(opts ...DBOption) (model.QuickJump, error) {
|
||||
var launcher model.QuickJump
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.First(&launcher).Error
|
||||
return launcher, err
|
||||
}
|
||||
func (u *LauncherRepo) ListQuickJump(withAll bool) []model.QuickJump {
|
||||
var quicks []model.QuickJump
|
||||
if withAll {
|
||||
_ = global.DB.Find(&quicks).Error
|
||||
} else {
|
||||
_ = global.DB.Where("is_show = ?", true).Find(&quicks).Error
|
||||
}
|
||||
if !withAll && len(quicks) == 0 {
|
||||
return []model.QuickJump{
|
||||
{Name: "Website", Title: "menu.website", Recommend: 10, IsShow: true, Router: "/websites"},
|
||||
{Name: "Database", Title: "menu.database", Recommend: 30, IsShow: true, Router: "/databases"},
|
||||
{Name: "Cronjob", Title: "menu.cronjob", Recommend: 50, IsShow: true, Router: "/cronjobs"},
|
||||
{Name: "AppInstalled", Title: "home.appInstalled", Recommend: 70, IsShow: true, Router: "/apps/installed"},
|
||||
}
|
||||
}
|
||||
|
||||
return quicks
|
||||
}
|
||||
func (u *LauncherRepo) UpdateQuicks(quicks []model.QuickJump) error {
|
||||
tx := global.DB.Begin()
|
||||
for _, item := range quicks {
|
||||
if err := tx.Model(&model.QuickJump{}).Where("id = ?", item.ID).Updates(map[string]interface{}{
|
||||
"is_show": item.IsShow,
|
||||
"detail": item.Detail,
|
||||
"alias": item.Alias,
|
||||
}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ClamRepo struct{}
|
||||
@@ -14,6 +19,14 @@ type IClamRepo interface {
|
||||
Delete(opts ...DBOption) error
|
||||
Get(opts ...DBOption) (model.Clam, error)
|
||||
List(opts ...DBOption) ([]model.Clam, error)
|
||||
|
||||
WithByClamID(id uint) DBOption
|
||||
ListRecord(opts ...DBOption) ([]model.ClamRecord, error)
|
||||
RecordFirst(id uint) (model.ClamRecord, error)
|
||||
DeleteRecord(opts ...DBOption) error
|
||||
StartRecords(clamID uint) model.ClamRecord
|
||||
EndRecords(record model.ClamRecord, status, message string)
|
||||
PageRecords(page, size int, opts ...DBOption) (int64, []model.ClamRecord, error)
|
||||
}
|
||||
|
||||
func NewIClamRepo() IClamRepo {
|
||||
@@ -67,3 +80,69 @@ func (u *ClamRepo) Delete(opts ...DBOption) error {
|
||||
}
|
||||
return db.Delete(&model.Clam{}).Error
|
||||
}
|
||||
|
||||
func (c *ClamRepo) WithByClamID(id uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("clam_id = ?", id)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *ClamRepo) ListRecord(opts ...DBOption) ([]model.ClamRecord, error) {
|
||||
var record []model.ClamRecord
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.Find(&record).Error
|
||||
return record, err
|
||||
}
|
||||
|
||||
func (u *ClamRepo) RecordFirst(id uint) (model.ClamRecord, error) {
|
||||
var record model.ClamRecord
|
||||
err := global.DB.Where("clam_id = ?", id).Order("created_at desc").First(&record).Error
|
||||
return record, err
|
||||
}
|
||||
|
||||
func (u *ClamRepo) PageRecords(page, size int, opts ...DBOption) (int64, []model.ClamRecord, error) {
|
||||
var records []model.ClamRecord
|
||||
db := global.DB.Model(&model.ClamRecord{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Order("created_at desc").Limit(size).Offset(size * (page - 1)).Find(&records).Error
|
||||
return count, records, err
|
||||
}
|
||||
func (u *ClamRepo) StartRecords(clamID uint) model.ClamRecord {
|
||||
var record model.ClamRecord
|
||||
record.StartTime = time.Now()
|
||||
record.ClamID = clamID
|
||||
record.TaskID = uuid.New().String()
|
||||
record.Status = constant.StatusWaiting
|
||||
if err := global.DB.Create(&record).Error; err != nil {
|
||||
global.LOG.Errorf("create record status failed, err: %v", err)
|
||||
}
|
||||
_ = u.Update(clamID, map[string]interface{}{"is_executing": true})
|
||||
return record
|
||||
}
|
||||
func (u *ClamRepo) EndRecords(record model.ClamRecord, status, message string) {
|
||||
upMap := make(map[string]interface{})
|
||||
upMap["status"] = status
|
||||
upMap["message"] = message
|
||||
upMap["task_id"] = record.TaskID
|
||||
upMap["scan_time"] = record.ScanTime
|
||||
upMap["infected_files"] = record.InfectedFiles
|
||||
upMap["total_error"] = record.TotalError
|
||||
if err := global.DB.Model(&model.ClamRecord{}).Where("id = ?", record.ID).Updates(upMap).Error; err != nil {
|
||||
global.LOG.Errorf("update record status failed, err: %v", err)
|
||||
}
|
||||
_ = u.Update(record.ClamID, map[string]interface{}{"is_executing": false})
|
||||
}
|
||||
func (u *ClamRepo) DeleteRecord(opts ...DBOption) error {
|
||||
db := global.DB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
return db.Delete(&model.ClamRecord{}).Error
|
||||
}
|
||||
|
||||
@@ -29,9 +29,10 @@ type ICronjobRepo interface {
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
DeleteRecord(opts ...DBOption) error
|
||||
StartRecords(cronjobID uint, targetPath, cronjobType string) model.JobRecords
|
||||
StartRecords(cronjobID uint) model.JobRecords
|
||||
UpdateRecords(id uint, vars map[string]interface{}) error
|
||||
EndRecords(record model.JobRecords, status, message, records string)
|
||||
AddFailedRecord(cronjobID uint, message string)
|
||||
PageRecords(page, size int, opts ...DBOption) (int64, []model.JobRecords, error)
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ func (c *CronjobRepo) WithByRecordDropID(id int) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath, cronjobType string) model.JobRecords {
|
||||
func (u *CronjobRepo) StartRecords(cronjobID uint) model.JobRecords {
|
||||
var record model.JobRecords
|
||||
record.StartTime = time.Now()
|
||||
record.CronjobID = cronjobID
|
||||
@@ -152,6 +153,7 @@ func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath, cronjobType strin
|
||||
if err := global.DB.Create(&record).Error; err != nil {
|
||||
global.LOG.Errorf("create record status failed, err: %v", err)
|
||||
}
|
||||
_ = u.Update(cronjobID, map[string]interface{}{"is_executing": true})
|
||||
return record
|
||||
}
|
||||
func (u *CronjobRepo) EndRecords(record model.JobRecords, status, message, records string) {
|
||||
@@ -165,6 +167,17 @@ func (u *CronjobRepo) EndRecords(record model.JobRecords, status, message, recor
|
||||
if err := global.DB.Model(&model.JobRecords{}).Where("id = ?", record.ID).Updates(errMap).Error; err != nil {
|
||||
global.LOG.Errorf("update record status failed, err: %v", err)
|
||||
}
|
||||
_ = u.Update(record.CronjobID, map[string]interface{}{"is_executing": false})
|
||||
}
|
||||
func (u *CronjobRepo) AddFailedRecord(cronjobID uint, message string) {
|
||||
var record model.JobRecords
|
||||
record.StartTime = time.Now()
|
||||
record.CronjobID = cronjobID
|
||||
record.Status = constant.StatusFailed
|
||||
record.Message = message
|
||||
if err := global.DB.Create(&record).Error; err != nil {
|
||||
global.LOG.Errorf("create record status failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *CronjobRepo) Save(id uint, cronjob model.Cronjob) error {
|
||||
|
||||
@@ -19,7 +19,7 @@ type IHostRepo interface {
|
||||
GetCert(opts ...DBOption) (model.RootCert, error)
|
||||
PageCert(limit, offset int, opts ...DBOption) (int64, []model.RootCert, error)
|
||||
ListCert(opts ...DBOption) ([]model.RootCert, error)
|
||||
CreateCert(cert *model.RootCert) error
|
||||
SaveCert(cert *model.RootCert) error
|
||||
UpdateCert(id uint, vars map[string]interface{}) error
|
||||
DeleteCert(opts ...DBOption) error
|
||||
}
|
||||
@@ -107,8 +107,8 @@ func (u *HostRepo) ListCert(opts ...DBOption) ([]model.RootCert, error) {
|
||||
return ops, err
|
||||
}
|
||||
|
||||
func (u *HostRepo) CreateCert(cert *model.RootCert) error {
|
||||
return global.DB.Create(cert).Error
|
||||
func (u *HostRepo) SaveCert(cert *model.RootCert) error {
|
||||
return global.DB.Save(cert).Error
|
||||
}
|
||||
|
||||
func (u *HostRepo) UpdateCert(id uint, vars map[string]interface{}) error {
|
||||
|
||||
@@ -17,6 +17,7 @@ type IRuntimeRepo interface {
|
||||
WithNotId(id uint) DBOption
|
||||
WithStatus(status string) DBOption
|
||||
WithDetailId(id uint) DBOption
|
||||
WithDetailIdsIn(ids []uint) DBOption
|
||||
WithPort(port int) DBOption
|
||||
WithNormalStatus(status string) DBOption
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error)
|
||||
@@ -55,6 +56,12 @@ func (r *RuntimeRepo) WithDetailId(id uint) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RuntimeRepo) WithDetailIdsIn(ids []uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("app_detail_id in(?) ", ids)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RuntimeRepo) WithNotId(id uint) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id != ?", id)
|
||||
|
||||
@@ -24,6 +24,7 @@ type ITaskRepo interface {
|
||||
DeleteAll() error
|
||||
|
||||
WithByID(id string) DBOption
|
||||
WithByIDNotIn(ids []string) DBOption
|
||||
WithResourceID(id uint) DBOption
|
||||
WithOperate(taskOperate string) DBOption
|
||||
WithByStatus(status string) DBOption
|
||||
@@ -58,6 +59,12 @@ func (t TaskRepo) WithByID(id string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithByIDNotIn(ids []string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id not in (?)", ids)
|
||||
}
|
||||
}
|
||||
|
||||
func (t TaskRepo) WithOperate(taskOperate string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("operate = ?", taskOperate)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package repo
|
||||
|
||||
import "github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
|
||||
type TensorRTLLMRepo struct {
|
||||
}
|
||||
|
||||
type ITensorRTLLMRepo interface {
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.TensorRTLLM, error)
|
||||
GetFirst(opts ...DBOption) (*model.TensorRTLLM, error)
|
||||
Create(tensorrtLLM *model.TensorRTLLM) error
|
||||
Save(tensorrtLLM *model.TensorRTLLM) error
|
||||
DeleteBy(opts ...DBOption) error
|
||||
List(opts ...DBOption) ([]model.TensorRTLLM, error)
|
||||
}
|
||||
|
||||
func NewITensorRTLLMRepo() ITensorRTLLMRepo {
|
||||
return &TensorRTLLMRepo{}
|
||||
}
|
||||
|
||||
func (t TensorRTLLMRepo) Page(page, size int, opts ...DBOption) (int64, []model.TensorRTLLM, error) {
|
||||
var servers []model.TensorRTLLM
|
||||
db := getDb(opts...).Model(&model.TensorRTLLM{})
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Find(&servers).Error
|
||||
return count, servers, err
|
||||
}
|
||||
|
||||
func (t TensorRTLLMRepo) GetFirst(opts ...DBOption) (*model.TensorRTLLM, error) {
|
||||
var tensorrtLLM model.TensorRTLLM
|
||||
if err := getDb(opts...).First(&tensorrtLLM).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tensorrtLLM, nil
|
||||
}
|
||||
|
||||
func (t TensorRTLLMRepo) List(opts ...DBOption) ([]model.TensorRTLLM, error) {
|
||||
var tensorrtLLMs []model.TensorRTLLM
|
||||
if err := getDb(opts...).Find(&tensorrtLLMs).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tensorrtLLMs, nil
|
||||
}
|
||||
|
||||
func (t TensorRTLLMRepo) Create(tensorrtLLM *model.TensorRTLLM) error {
|
||||
return getDb().Create(tensorrtLLM).Error
|
||||
}
|
||||
|
||||
func (t TensorRTLLMRepo) Save(tensorrtLLM *model.TensorRTLLM) error {
|
||||
return getDb().Save(tensorrtLLM).Error
|
||||
}
|
||||
|
||||
func (t TensorRTLLMRepo) DeleteBy(opts ...DBOption) error {
|
||||
return getDb(opts...).Delete(&model.TensorRTLLM{}).Error
|
||||
}
|
||||
@@ -19,6 +19,8 @@ type IWebsiteRepo interface {
|
||||
WithRuntimeID(runtimeID uint) DBOption
|
||||
WithParentID(websiteID uint) DBOption
|
||||
WithType(websiteType string) DBOption
|
||||
WithDBType(dbType string) DBOption
|
||||
WithDBID(dbID uint) DBOption
|
||||
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.Website, error)
|
||||
List(opts ...DBOption) ([]model.Website, error)
|
||||
@@ -100,6 +102,18 @@ func (w *WebsiteRepo) WithType(websiteType string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WebsiteRepo) WithDBType(dbType string) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("db_type = ?", dbType)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WebsiteRepo) WithDBID(dbID uint) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("db_id = ?", dbID)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WebsiteRepo) Page(page, size int, opts ...DBOption) (int64, []model.Website, error) {
|
||||
var websites []model.Website
|
||||
db := getDb(opts...).Model(&model.Website{})
|
||||
|
||||
@@ -17,6 +17,7 @@ type ISSLRepo interface {
|
||||
WithByDnsAccountId(dnsAccountId uint) DBOption
|
||||
WithByCAID(caID uint) DBOption
|
||||
WithByDomain(domain string) DBOption
|
||||
WithByMasterSSLID(sslID uint) DBOption
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.WebsiteSSL, error)
|
||||
GetFirst(opts ...DBOption) (*model.WebsiteSSL, error)
|
||||
List(opts ...DBOption) ([]model.WebsiteSSL, error)
|
||||
@@ -52,12 +53,19 @@ func (w WebsiteSSLRepo) WithByCAID(caID uint) DBOption {
|
||||
return db.Where("ca_id = ?", caID)
|
||||
}
|
||||
}
|
||||
|
||||
func (w WebsiteSSLRepo) WithByDomain(domain string) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("primary_domain Like ? or domains Like ?", "%"+domain+"%", "%"+domain+"%")
|
||||
}
|
||||
}
|
||||
|
||||
func (w WebsiteSSLRepo) WithByMasterSSLID(sslID uint) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("master_ssl_id = ?", sslID)
|
||||
}
|
||||
}
|
||||
|
||||
func (w WebsiteSSLRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteSSL, error) {
|
||||
var sslList []model.WebsiteSSL
|
||||
db := getDb(opts...).Model(&model.WebsiteSSL{})
|
||||
|
||||
+49
-25
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/copier"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/email"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -70,17 +70,18 @@ func (a AlertService) PageAlert(search dto.AlertSearch) (int64, []dto.AlertDTO,
|
||||
for _, item := range alerts {
|
||||
|
||||
result = append(result, dto.AlertDTO{
|
||||
ID: item.ID,
|
||||
Type: item.Type,
|
||||
Cycle: item.Cycle,
|
||||
Count: item.Count,
|
||||
Method: item.Method,
|
||||
Title: item.Title,
|
||||
Project: item.Project,
|
||||
Status: item.Status,
|
||||
SendCount: item.SendCount,
|
||||
CreatedAt: item.CreatedAt,
|
||||
UpdatedAt: item.UpdatedAt,
|
||||
ID: item.ID,
|
||||
Type: item.Type,
|
||||
Cycle: item.Cycle,
|
||||
Count: item.Count,
|
||||
Method: item.Method,
|
||||
Title: item.Title,
|
||||
Project: item.Project,
|
||||
Status: item.Status,
|
||||
SendCount: item.SendCount,
|
||||
AdvancedParams: item.AdvancedParams,
|
||||
CreatedAt: item.CreatedAt,
|
||||
UpdatedAt: item.UpdatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -100,17 +101,18 @@ func (a AlertService) GetAlerts() ([]dto.AlertDTO, error) {
|
||||
for _, item := range alerts {
|
||||
|
||||
result = append(result, dto.AlertDTO{
|
||||
ID: item.ID,
|
||||
Type: item.Type,
|
||||
Cycle: item.Cycle,
|
||||
Count: item.Count,
|
||||
Method: item.Method,
|
||||
Title: item.Title,
|
||||
Project: item.Project,
|
||||
Status: item.Status,
|
||||
SendCount: item.SendCount,
|
||||
CreatedAt: item.CreatedAt,
|
||||
UpdatedAt: item.UpdatedAt,
|
||||
ID: item.ID,
|
||||
Type: item.Type,
|
||||
Cycle: item.Cycle,
|
||||
Count: item.Count,
|
||||
Method: item.Method,
|
||||
Title: item.Title,
|
||||
Project: item.Project,
|
||||
Status: item.Status,
|
||||
SendCount: item.SendCount,
|
||||
AdvancedParams: item.AdvancedParams,
|
||||
CreatedAt: item.CreatedAt,
|
||||
UpdatedAt: item.UpdatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -165,6 +167,7 @@ func (a AlertService) UpdateAlert(req dto.AlertUpdate) error {
|
||||
upMap["project"] = req.Project
|
||||
upMap["status"] = req.Status
|
||||
upMap["send_count"] = req.SendCount
|
||||
upMap["advanced_params"] = req.AdvancedParams
|
||||
|
||||
if err := alertRepo.Update(upMap, repo.WithByID(req.ID)); err != nil {
|
||||
return err
|
||||
@@ -174,7 +177,24 @@ func (a AlertService) UpdateAlert(req dto.AlertUpdate) error {
|
||||
}
|
||||
|
||||
func (a AlertService) DeleteAlert(id uint) error {
|
||||
return alertRepo.Delete(repo.WithByID(id))
|
||||
alertInfo, _ := alertRepo.Get(repo.WithByID(id))
|
||||
if alertInfo.ID == 0 {
|
||||
return buserr.New("ErrRecordNotFound")
|
||||
}
|
||||
err := alertRepo.Delete(repo.WithByID(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
alerts, err := a.GetAlerts()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(alerts) > 0 {
|
||||
NewIAlertTaskHelper().InitTask(alertInfo.Type)
|
||||
} else {
|
||||
NewIAlertTaskHelper().StopTask()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AlertService) GetAlert(id uint) (dto.AlertDTO, error) {
|
||||
@@ -459,10 +479,14 @@ func (a AlertService) DeleteAlertConfig(id uint) error {
|
||||
}
|
||||
|
||||
func (a AlertService) TestAlertConfig(req dto.AlertConfigTest) (bool, error) {
|
||||
username := req.UserName
|
||||
if username == "" {
|
||||
username = req.Sender
|
||||
}
|
||||
cfg := email.SMTPConfig{
|
||||
Host: req.Host,
|
||||
Port: req.Port,
|
||||
Username: req.Sender,
|
||||
Username: username,
|
||||
Password: req.Password,
|
||||
From: fmt.Sprintf("%s <%s>", req.DisplayName, req.Sender),
|
||||
Encryption: req.Encryption,
|
||||
|
||||
+575
-580
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,165 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
alertUtil "github.com/1Panel-dev/1Panel/agent/utils/alert"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AlertSender struct {
|
||||
alert dto.AlertDTO
|
||||
quotaType string
|
||||
}
|
||||
|
||||
func NewAlertSender(alert dto.AlertDTO, quotaType string) *AlertSender {
|
||||
return &AlertSender{
|
||||
alert: alert,
|
||||
quotaType: quotaType,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AlertSender) Send(quota string, params []dto.Param) {
|
||||
methods := strings.Split(s.alert.Method, ",")
|
||||
for _, method := range methods {
|
||||
method = strings.TrimSpace(method)
|
||||
switch method {
|
||||
case constant.SMS:
|
||||
s.sendSMS(quota, params)
|
||||
case constant.Email:
|
||||
s.sendEmail(quota, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AlertSender) ResourceSend(quota string, params []dto.Param) {
|
||||
methods := strings.Split(s.alert.Method, ",")
|
||||
for _, method := range methods {
|
||||
method = strings.TrimSpace(method)
|
||||
switch method {
|
||||
case constant.SMS:
|
||||
s.sendResourceSMS(quota, params)
|
||||
case constant.Email:
|
||||
s.sendResourceEmail(quota, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AlertSender) sendSMS(quota string, params []dto.Param) {
|
||||
if !alertUtil.CheckSMSSendLimit(constant.SMS) {
|
||||
return
|
||||
}
|
||||
|
||||
totalCount, isValid := s.canSendAlert(constant.SMS)
|
||||
if !isValid {
|
||||
return
|
||||
}
|
||||
|
||||
create := dto.AlertLogCreate{
|
||||
Status: constant.AlertSuccess,
|
||||
Count: totalCount + 1,
|
||||
AlertId: s.alert.ID,
|
||||
Type: s.alert.Type,
|
||||
}
|
||||
|
||||
_ = xpack.CreateSMSAlertLog(s.alert.Type, s.alert, create, quota, params, constant.SMS)
|
||||
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.SMS)
|
||||
global.LOG.Infof("%s alert sms push successful", s.alert.Type)
|
||||
}
|
||||
|
||||
func (s *AlertSender) sendEmail(quota string, params []dto.Param) {
|
||||
totalCount, isValid := s.canSendAlert(constant.Email)
|
||||
if !isValid {
|
||||
return
|
||||
}
|
||||
|
||||
create := dto.AlertLogCreate{
|
||||
Status: constant.AlertSuccess,
|
||||
Count: totalCount + 1,
|
||||
AlertId: s.alert.ID,
|
||||
Type: s.alert.Type,
|
||||
AlertRule: alertUtil.ProcessAlertRule(s.alert),
|
||||
AlertDetail: alertUtil.ProcessAlertDetail(s.alert, quota, params, constant.Email),
|
||||
}
|
||||
|
||||
transport := xpack.LoadRequestTransport()
|
||||
_ = alertUtil.CreateEmailAlertLog(create, s.alert, params, transport)
|
||||
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Email)
|
||||
global.LOG.Infof("%s alert email push successful", s.alert.Type)
|
||||
}
|
||||
|
||||
func (s *AlertSender) sendResourceSMS(quota string, params []dto.Param) {
|
||||
if !alertUtil.CheckSMSSendLimit(constant.SMS) {
|
||||
return
|
||||
}
|
||||
|
||||
todayCount, isValid := s.canResourceSendAlert(constant.SMS)
|
||||
if !isValid {
|
||||
return
|
||||
}
|
||||
|
||||
create := dto.AlertLogCreate{
|
||||
Status: constant.AlertSuccess,
|
||||
Count: todayCount + 1,
|
||||
AlertId: s.alert.ID,
|
||||
Type: s.alert.Type,
|
||||
}
|
||||
|
||||
if err := xpack.CreateSMSAlertLog(s.alert.Type, s.alert, create, quota, params, constant.SMS); err != nil {
|
||||
global.LOG.Errorf("failed to send SMS alert: %v", err)
|
||||
return
|
||||
}
|
||||
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.SMS)
|
||||
global.LOG.Infof("%s alert sms push successful", s.alert.Type)
|
||||
}
|
||||
|
||||
func (s *AlertSender) sendResourceEmail(quota string, params []dto.Param) {
|
||||
todayCount, isValid := s.canResourceSendAlert(constant.Email)
|
||||
if !isValid {
|
||||
return
|
||||
}
|
||||
|
||||
create := dto.AlertLogCreate{
|
||||
Status: constant.AlertSuccess,
|
||||
Count: todayCount + 1,
|
||||
AlertId: s.alert.ID,
|
||||
Type: s.alert.Type,
|
||||
AlertRule: alertUtil.ProcessAlertRule(s.alert),
|
||||
AlertDetail: alertUtil.ProcessAlertDetail(s.alert, quota, params, constant.Email),
|
||||
}
|
||||
|
||||
transport := xpack.LoadRequestTransport()
|
||||
if err := alertUtil.CreateEmailAlertLog(create, s.alert, params, transport); err != nil {
|
||||
global.LOG.Errorf("failed to send Email alert: %v", err)
|
||||
return
|
||||
}
|
||||
alertUtil.CreateNewAlertTask(quota, s.alert.Type, s.quotaType, constant.Email)
|
||||
global.LOG.Infof("%s alert email push successful", s.alert.Type)
|
||||
}
|
||||
|
||||
func (s *AlertSender) canSendAlert(method string) (uint, bool) {
|
||||
todayCount, totalCount, err := alertRepo.LoadTaskCount(s.alert.Type, s.quotaType, method)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("error getting task count: %v", err)
|
||||
return totalCount, false
|
||||
}
|
||||
|
||||
if todayCount >= 1 || s.alert.SendCount <= totalCount {
|
||||
return totalCount, false
|
||||
}
|
||||
return totalCount, true
|
||||
}
|
||||
|
||||
func (s *AlertSender) canResourceSendAlert(method string) (uint, bool) {
|
||||
todayCount, _, err := alertRepo.LoadTaskCount(s.alert.Type, s.quotaType, method)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("error getting task count: %v", err)
|
||||
return todayCount, false
|
||||
}
|
||||
if s.alert.SendCount <= todayCount {
|
||||
return todayCount, false
|
||||
}
|
||||
return todayCount, true
|
||||
}
|
||||
+40
-29
@@ -56,7 +56,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
var opts []repo.DBOption
|
||||
opts = append(opts, appRepo.OrderByRecommend())
|
||||
if req.Name != "" {
|
||||
opts = append(opts, appRepo.WithByLikeName(req.Name))
|
||||
opts = append(opts, appRepo.WithByLikeName(strings.TrimSpace(req.Name)))
|
||||
}
|
||||
if req.Type != "" {
|
||||
opts = append(opts, appRepo.WithType(req.Type))
|
||||
@@ -73,7 +73,11 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts = append(opts, appRepo.WithArch(info.KernelArch))
|
||||
kernelArch := info.KernelArch
|
||||
if kernelArch == "aarch64" {
|
||||
kernelArch = "arm64"
|
||||
}
|
||||
opts = append(opts, appRepo.WithArch(kernelArch))
|
||||
}
|
||||
if len(req.Tags) != 0 {
|
||||
tags, err := tagRepo.GetByKeys(req.Tags)
|
||||
@@ -100,7 +104,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var appDTOs []*response.AppItem
|
||||
appDTOs := make([]*response.AppItem, 0)
|
||||
info := &dto.SettingInfo{}
|
||||
if req.Type == "php" {
|
||||
info, _ = NewISettingService().GetSettingInfo()
|
||||
@@ -108,7 +112,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
lang := strings.ToLower(common.GetLang(ctx))
|
||||
for _, ap := range apps {
|
||||
if req.Type == "php" {
|
||||
if ap.RequiredPanelVersion == 0 || !common.CompareAppVersion(common.GetSystemVersion(info.SystemVersion), fmt.Sprintf("%f", ap.RequiredPanelVersion)) {
|
||||
if !global.CONF.Base.IsOffLine && (ap.RequiredPanelVersion == 0 || !common.CompareAppVersion(common.GetSystemVersion(info.SystemVersion), fmt.Sprintf("%f", ap.RequiredPanelVersion))) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -132,8 +136,21 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
continue
|
||||
}
|
||||
appDTO.Tags = tags
|
||||
installs, _ := appInstallRepo.ListBy(context.Background(), appInstallRepo.WithAppId(ap.ID))
|
||||
appDTO.Installed = len(installs) > 0
|
||||
if ap.Type == constant.RuntimePHP || ap.Type == constant.RuntimeGo || ap.Type == constant.RuntimeNode || ap.Type == constant.RuntimePython || ap.Type == constant.RuntimeJava || ap.Type == constant.RuntimeDotNet {
|
||||
details, _ := appDetailRepo.GetBy(appDetailRepo.WithAppId(ap.ID))
|
||||
var ids []uint
|
||||
if len(details) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, d := range details {
|
||||
ids = append(ids, d.ID)
|
||||
}
|
||||
runtimes, _ := runtimeRepo.List(runtimeRepo.WithDetailIdsIn(ids))
|
||||
appDTO.Installed = len(runtimes) > 0
|
||||
} else {
|
||||
installs, _ := appInstallRepo.ListBy(context.Background(), appInstallRepo.WithAppId(ap.ID))
|
||||
appDTO.Installed = len(installs) > 0
|
||||
}
|
||||
}
|
||||
res.Items = appDTOs
|
||||
res.Total = total
|
||||
@@ -355,29 +372,6 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
|
||||
}
|
||||
}
|
||||
}
|
||||
if app.Key == "openresty" && (app.Resource == "remote" || app.Resource == "custom") && common.CompareVersion(appDetail.Version, "1.27") {
|
||||
if dir, ok := req.Params["WEBSITE_DIR"]; ok {
|
||||
siteDir := dir.(string)
|
||||
if siteDir == "" || !strings.HasPrefix(siteDir, "/") {
|
||||
siteDir = path.Join(global.Dir.DataDir, dir.(string))
|
||||
}
|
||||
req.Params["WEBSITE_DIR"] = siteDir
|
||||
oldWebStePath, _ := settingRepo.GetValueByKey("WEBSITE_DIR")
|
||||
fileOp := files.NewFileOp()
|
||||
if oldWebStePath != "" && oldWebStePath != siteDir && fileOp.Stat(oldWebStePath) {
|
||||
_ = fileOp.Rename(oldWebStePath, siteDir)
|
||||
}
|
||||
if !fileOp.Stat(siteDir) {
|
||||
_ = fileOp.CreateDir(siteDir, constant.DirPerm)
|
||||
_ = fileOp.CreateDir(path.Join(siteDir, "conf.d"), constant.DirPerm)
|
||||
}
|
||||
err = settingRepo.UpdateOrCreate("WEBSITE_DIR", siteDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go RestartPHPRuntime()
|
||||
}
|
||||
}
|
||||
for key := range req.Params {
|
||||
if !strings.Contains(key, "PANEL_APP_PORT") {
|
||||
continue
|
||||
@@ -486,6 +480,20 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
|
||||
req.Params["DATABASE_NAME"] = database.Name
|
||||
}
|
||||
}
|
||||
if app.Key == "openresty" {
|
||||
req.Params["CONTAINER_PACKAGE_URL"] = "http://archive.ubuntu.com/ubuntu/"
|
||||
req.Params["RESTY_ADD_PACKAGE_BUILDDEPS"] = ""
|
||||
req.Params["RESTY_CONFIG_OPTIONS_MORE"] = ""
|
||||
}
|
||||
if app.Key == "openresty" && (app.Resource == "remote" || app.Resource == "custom") && common.CompareVersion(appDetail.Version, "1.27") {
|
||||
if dir, ok := req.Params["WEBSITE_DIR"]; ok {
|
||||
siteDir := dir.(string)
|
||||
if siteDir == "" || !strings.HasPrefix(siteDir, "/") {
|
||||
siteDir = path.Join(global.Dir.DataDir, dir.(string))
|
||||
}
|
||||
req.Params["WEBSITE_DIR"] = siteDir
|
||||
}
|
||||
}
|
||||
paramByte, err = json.Marshal(req.Params)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -513,6 +521,9 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
|
||||
return err
|
||||
}
|
||||
if app.Key == "openresty" {
|
||||
if err = handleSiteDir(app, appDetail, req, t); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = handleOpenrestyFile(appInstall); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -164,6 +164,11 @@ func (a *AppInstallService) CheckExist(req request.AppInstalledInfo) (*response.
|
||||
res.HttpPort = appInstall.HttpPort
|
||||
res.HttpsPort = appInstall.HttpsPort
|
||||
|
||||
if appInstall.App.Key == "openresty" {
|
||||
websiteDir, _ := settingRepo.GetValueByKey("WEBSITE_DIR")
|
||||
res.WebsiteDir = websiteDir
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -788,6 +793,7 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
|
||||
}
|
||||
res.AppContainerConfig = config
|
||||
res.HostMode = isHostModel(install.DockerCompose)
|
||||
res.RestartPolicy = getRestartPolicy(install.DockerCompose)
|
||||
res.WebUI = install.WebUI
|
||||
res.Type = install.App.Type
|
||||
return &res, nil
|
||||
|
||||
+197
-32
@@ -1,11 +1,13 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"maps"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -357,7 +359,7 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(install.DockerCompose))
|
||||
images, err := composeV2.GetImagesFromDockerCompose(content, []byte(install.DockerCompose))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -540,6 +542,9 @@ func handleUpgradeCompose(install model.AppInstall, detail model.AppDetail) (map
|
||||
if oldServiceValue["deploy"] != nil {
|
||||
serviceValue["deploy"] = oldServiceValue["deploy"]
|
||||
}
|
||||
if oldServiceValue["restart"] != nil {
|
||||
serviceValue["restart"] = oldServiceValue["restart"]
|
||||
}
|
||||
servicesMap[install.ServiceName] = serviceValue
|
||||
composeMap["services"] = servicesMap
|
||||
return composeMap, nil
|
||||
@@ -578,6 +583,76 @@ func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string
|
||||
return string(composeByte), nil
|
||||
}
|
||||
|
||||
func buildNginx(parentTask *task.Task) error {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
buildPath := path.Join(nginxInstall.GetPath(), "build")
|
||||
if !fileOp.Stat(buildPath) {
|
||||
return buserr.New("ErrBuildDirNotFound")
|
||||
}
|
||||
moduleConfigPath := path.Join(buildPath, "module.json")
|
||||
moduleContent, err := fileOp.GetContent(moduleConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
modules []dto.NginxModule
|
||||
addModuleParams []string
|
||||
addPackages []string
|
||||
)
|
||||
if len(moduleContent) > 0 {
|
||||
_ = json.Unmarshal(moduleContent, &modules)
|
||||
bashFile, err := os.OpenFile(path.Join(buildPath, "tmp", "pre.sh"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer bashFile.Close()
|
||||
bashFileWriter := bufio.NewWriter(bashFile)
|
||||
for _, module := range modules {
|
||||
if !module.Enable {
|
||||
continue
|
||||
}
|
||||
_, err = bashFileWriter.WriteString(module.Script + "\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addModuleParams = append(addModuleParams, module.Params)
|
||||
addPackages = append(addPackages, module.Packages...)
|
||||
}
|
||||
err = bashFileWriter.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
envs, err := gotenv.Read(nginxInstall.GetEnvPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
envs["RESTY_CONFIG_OPTIONS_MORE"] = ""
|
||||
envs["RESTY_ADD_PACKAGE_BUILDDEPS"] = ""
|
||||
if len(addModuleParams) > 0 {
|
||||
envs["RESTY_CONFIG_OPTIONS_MORE"] = strings.Join(addModuleParams, " ")
|
||||
}
|
||||
if len(addPackages) > 0 {
|
||||
envs["RESTY_ADD_PACKAGE_BUILDDEPS"] = strings.Join(addPackages, " ")
|
||||
}
|
||||
_ = gotenv.Write(envs, nginxInstall.GetEnvPath())
|
||||
if len(addModuleParams) == 0 && len(addPackages) == 0 {
|
||||
return nil
|
||||
}
|
||||
logStr := fmt.Sprintf("%s %s", i18n.GetMsgByKey("TaskBuild"), i18n.GetMsgByKey("Image"))
|
||||
parentTask.LogStart(logStr)
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*parentTask), cmd.WithTimeout(60*time.Minute))
|
||||
if err = cmdMgr.RunBashCf("docker compose -f %s build", nginxInstall.GetComposePath()); err != nil {
|
||||
return err
|
||||
}
|
||||
parentTask.LogSuccess(logStr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
install, err := appInstallRepo.GetFirst(repo.WithByID(req.InstallID))
|
||||
if err != nil {
|
||||
@@ -602,29 +677,29 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
backupFile string
|
||||
)
|
||||
backUpApp := func(t *task.Task) error {
|
||||
if req.Backup {
|
||||
backupService := NewIBackupService()
|
||||
backupRecordService := NewIBackupRecordService()
|
||||
fileName := fmt.Sprintf("upgrade_backup_%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
|
||||
backupRecord, err := backupService.AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name, FileName: fileName})
|
||||
if err == nil {
|
||||
backups, _ := backupRecordService.ListAppRecords(install.App.Key, install.Name, "upgrade_backup")
|
||||
if len(backups) > 3 {
|
||||
backupsToDelete := backups[:len(backups)-3]
|
||||
var deleteIDs []uint
|
||||
for _, backup := range backupsToDelete {
|
||||
deleteIDs = append(deleteIDs, backup.ID)
|
||||
}
|
||||
_ = backupRecordService.BatchDeleteRecord(deleteIDs)
|
||||
backupService := NewIBackupService()
|
||||
backupRecordService := NewIBackupRecordService()
|
||||
fileName := fmt.Sprintf("upgrade_backup_%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
|
||||
backupRecord, err := backupService.AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name, FileName: fileName})
|
||||
if err == nil {
|
||||
backups, _ := backupRecordService.ListAppRecords(install.App.Key, install.Name, "upgrade_backup")
|
||||
if len(backups) > 3 {
|
||||
backupsToDelete := backups[:len(backups)-3]
|
||||
var deleteIDs []uint
|
||||
for _, backup := range backupsToDelete {
|
||||
deleteIDs = append(deleteIDs, backup.ID)
|
||||
}
|
||||
backupFile = path.Join(global.Dir.LocalBackupDir, backupRecord.FileDir, backupRecord.FileName)
|
||||
} else {
|
||||
return buserr.WithNameAndErr("ErrAppBackup", install.Name, err)
|
||||
_ = backupRecordService.BatchDeleteRecord(deleteIDs)
|
||||
}
|
||||
backupFile = path.Join(global.Dir.LocalBackupDir, backupRecord.FileDir, backupRecord.FileName)
|
||||
} else {
|
||||
return buserr.WithNameAndErr("ErrAppBackup", install.Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
upgradeTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), backUpApp, nil)
|
||||
if req.Backup {
|
||||
upgradeTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), backUpApp, nil)
|
||||
}
|
||||
|
||||
upgradeApp := func(t *task.Task) error {
|
||||
fileOp := files.NewFileOp()
|
||||
@@ -659,7 +734,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
if req.DockerCompose != "" {
|
||||
composeContent = []byte(req.DockerCompose)
|
||||
}
|
||||
images, err := composeV2.GetDockerComposeImagesV2(content, composeContent)
|
||||
images, err := composeV2.GetImagesFromDockerCompose(content, composeContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -710,6 +785,14 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
return err
|
||||
}
|
||||
envParams := make(map[string]string, len(envs))
|
||||
if install.App.Key == constant.AppOpenresty {
|
||||
packageUrl, _ := env.GetEnvValueByKey(install.GetEnvPath(), "CONTAINER_PACKAGE_URL")
|
||||
addPackage, _ := env.GetEnvValueByKey(install.GetEnvPath(), "RESTY_ADD_PACKAGE_BUILDDEPS")
|
||||
options, _ := env.GetEnvValueByKey(install.GetEnvPath(), "RESTY_CONFIG_OPTIONS_MORE")
|
||||
envParams["CONTAINER_PACKAGE_URL"] = packageUrl
|
||||
envParams["RESTY_ADD_PACKAGE_BUILDDEPS"] = addPackage
|
||||
envParams["RESTY_CONFIG_OPTIONS_MORE"] = options
|
||||
}
|
||||
handleMap(envs, envParams)
|
||||
if err = env.Write(envParams, install.GetEnvPath()); err != nil {
|
||||
return err
|
||||
@@ -723,6 +806,13 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if install.App.Key == constant.AppOpenresty {
|
||||
if err = buildNginx(t); err != nil {
|
||||
t.Log(err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logStr := fmt.Sprintf("%s %s", i18n.GetMsgByKey("Run"), i18n.GetMsgByKey("App"))
|
||||
t.Log(logStr)
|
||||
if out, err := compose.Up(install.GetComposePath()); err != nil {
|
||||
@@ -748,7 +838,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
}
|
||||
}
|
||||
|
||||
upgradeTask.AddSubTask(task.GetTaskName(install.Name, task.TaskScopeApp, task.TaskUpgrade), upgradeApp, rollBackApp)
|
||||
upgradeTask.AddSubTaskWithOps(task.GetTaskName(install.Name, task.TaskScopeApp, task.TaskUpgrade), upgradeApp, rollBackApp, 0, 1*time.Hour)
|
||||
|
||||
go func() {
|
||||
err = upgradeTask.Execute()
|
||||
@@ -856,7 +946,7 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
|
||||
}
|
||||
|
||||
func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall, logger *log.Logger) (err error) {
|
||||
if app.IsLocalApp() {
|
||||
if app.IsLocalApp() || app.IsCustomApp() {
|
||||
return nil
|
||||
}
|
||||
appResourceDir := path.Join(global.Dir.AppResourceDir, app.Resource)
|
||||
@@ -873,9 +963,9 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
|
||||
_ = fileOp.CreateDir(appVersionDir, constant.DirPerm)
|
||||
}
|
||||
if logger == nil {
|
||||
global.LOG.Infof("download app[%s] from %s", app.Name, appDetail.DownloadUrl)
|
||||
global.LOG.Infof("download app [%s] from %s", app.Name, appDetail.DownloadUrl)
|
||||
} else {
|
||||
logger.Printf("download app[%s] from %s", app.Name, appDetail.DownloadUrl)
|
||||
logger.Printf("download app [%s] from %s", app.Name, appDetail.DownloadUrl)
|
||||
}
|
||||
|
||||
filePath := path.Join(appVersionDir, app.Key+"-"+appDetail.Version+".tar.gz")
|
||||
@@ -891,9 +981,9 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
|
||||
|
||||
if err = files.DownloadFileWithProxy(appDetail.DownloadUrl, filePath); err != nil {
|
||||
if logger == nil {
|
||||
global.LOG.Errorf("download app[%s] error %v", app.Name, err)
|
||||
global.LOG.Errorf("download app [%s] error %v", app.Name, err)
|
||||
} else {
|
||||
logger.Printf("download app[%s] error %v", app.Name, err)
|
||||
logger.Printf("download app [%s] error %v", app.Name, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -955,11 +1045,11 @@ func copyData(task *task.Task, app model.App, appDetail model.AppDetail, appInst
|
||||
return
|
||||
}
|
||||
envPath := path.Join(appDir, ".env")
|
||||
envParams := make(map[string]string, len(req.Params))
|
||||
envParams := make(map[string]string)
|
||||
if fileOp.Stat(envPath) {
|
||||
envs, _ := gotenv.Read(envPath)
|
||||
for k, v := range envs {
|
||||
envParams[k] = v
|
||||
if envParams = maps.Clone(envs); envParams == nil {
|
||||
envParams = make(map[string]string)
|
||||
}
|
||||
}
|
||||
handleMap(req.Params, envParams)
|
||||
@@ -992,7 +1082,7 @@ func runScript(task *task.Task, appInstall *model.AppInstall, operate string) er
|
||||
task.LogStart(logStr)
|
||||
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute), cmd.WithWorkDir(workDir))
|
||||
out, err := cmdMgr.RunWithStdoutBashCf(scriptPath)
|
||||
out, err := cmdMgr.RunWithStdoutBashC(scriptPath)
|
||||
if err != nil {
|
||||
if out != "" {
|
||||
err = errors.New(out)
|
||||
@@ -1073,7 +1163,11 @@ func upApp(task *task.Task, appInstall *model.AppInstall, pullImages bool) error
|
||||
appInstall.Message = errMsg + errOur
|
||||
installErr := errors.New(appInstall.Message)
|
||||
task.LogFailedWithErr(i18n.GetMsgByKey("PullImage"), installErr)
|
||||
return installErr
|
||||
if exist, _ := dockerCLi.ImageExists(image); !exist {
|
||||
return installErr
|
||||
} else {
|
||||
task.Log(i18n.GetMsgByKey("UseExistImage"))
|
||||
}
|
||||
} else {
|
||||
task.Log(i18n.GetMsgByKey("PullImageSuccess"))
|
||||
}
|
||||
@@ -1658,6 +1752,14 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
|
||||
deploy["resources"] = resource
|
||||
serviceValue["deploy"] = deploy
|
||||
|
||||
if req.RestartPolicy != "" {
|
||||
if req.RestartPolicy == "on-failure" {
|
||||
serviceValue["restart"] = "on-failure:5"
|
||||
} else {
|
||||
serviceValue["restart"] = req.RestartPolicy
|
||||
}
|
||||
}
|
||||
|
||||
ports, ok := serviceValue["ports"].([]interface{})
|
||||
if ok {
|
||||
for i, port := range ports {
|
||||
@@ -1760,6 +1862,17 @@ func isHostModel(dockerCompose string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getRestartPolicy(yml string) string {
|
||||
var project docker.ComposeProject
|
||||
if err := yaml.Unmarshal([]byte(yml), &project); err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, service := range project.Services {
|
||||
return service.Restart
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getMajorVersion(version string) string {
|
||||
parts := strings.Split(version, ".")
|
||||
if len(parts) >= 2 {
|
||||
@@ -1786,6 +1899,11 @@ func ignoreUpdate(installed model.AppInstall) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
if installed.App.Key == "sqlbot" {
|
||||
if common.CompareVersion("1.1.0", installed.Version) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1825,6 +1943,53 @@ func getAppTags(appID uint, lang string) ([]response.TagDTO, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func handleSiteDir(app model.App, appDetail model.AppDetail, req request.AppInstallCreate, t *task.Task) error {
|
||||
if app.Key == "openresty" && (app.Resource == "remote" || app.Resource == "custom") && common.CompareVersion(appDetail.Version, "1.27") {
|
||||
if dir, ok := req.Params["WEBSITE_DIR"]; ok {
|
||||
siteDir := dir.(string)
|
||||
if siteDir == "" || !strings.HasPrefix(siteDir, "/") {
|
||||
siteDir = path.Join(global.Dir.DataDir, dir.(string))
|
||||
}
|
||||
req.Params["WEBSITE_DIR"] = siteDir
|
||||
oldWebStePath, _ := settingRepo.GetValueByKey("WEBSITE_DIR")
|
||||
fileOp := files.NewFileOp()
|
||||
if oldWebStePath != "" && oldWebStePath != siteDir && fileOp.Stat(oldWebStePath) {
|
||||
t.Log(i18n.GetWithName("MoveSiteDir", siteDir))
|
||||
if fileOp.Stat(siteDir) {
|
||||
if fileOp.Stat(path.Join(siteDir, "conf.d")) {
|
||||
_ = fileOp.Rename(path.Join(siteDir, "conf.d"), path.Join(siteDir, "conf.d.bak"))
|
||||
}
|
||||
if fileOp.Stat(path.Join(siteDir, "sites")) {
|
||||
_ = fileOp.Rename(path.Join(siteDir, "sites"), path.Join(siteDir, "sites.bak"))
|
||||
}
|
||||
if err := fileOp.Rename(path.Join(oldWebStePath, "sites"), path.Join(siteDir, "sites")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.Rename(path.Join(oldWebStePath, "conf.d"), path.Join(siteDir, "conf.d")); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := fileOp.Rename(oldWebStePath, siteDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
t.Log(i18n.GetMsgByKey("MoveSiteDirSuccess"))
|
||||
}
|
||||
if !fileOp.Stat(siteDir) {
|
||||
_ = fileOp.CreateDir(siteDir, constant.DirPerm)
|
||||
_ = fileOp.CreateDir(path.Join(siteDir, "conf.d"), constant.DirPerm)
|
||||
}
|
||||
err := settingRepo.UpdateOrCreate("WEBSITE_DIR", siteDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go RestartPHPRuntime()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleOpenrestyFile(appInstall *model.AppInstall) error {
|
||||
websites, _ := websiteRepo.List()
|
||||
hasDefaultWebsite := false
|
||||
@@ -1902,7 +2067,7 @@ func handleSSLConfig(appInstall *model.AppInstall, hasDefaultWebsite bool) error
|
||||
}
|
||||
defaultConfig.FilePath = defaultConfigPath
|
||||
defaultServer := defaultConfig.FindServers()[0]
|
||||
updateDefaultServer(defaultServer, appInstall.HttpPort, appInstall.HttpsPort, !hasDefaultWebsite)
|
||||
updateDefaultServer(defaultServer, appInstall.HttpPort, appInstall.HttpsPort, !hasDefaultWebsite, true)
|
||||
defaultServer.UpdateDirective("include", []string{"/usr/local/openresty/nginx/conf/ssl/root_ssl.conf"})
|
||||
defaultServer.UpdateDirective("http2", []string{"on"})
|
||||
if err = nginx.WriteConfig(defaultConfig, nginx.IndentedStyle); err != nil {
|
||||
|
||||
@@ -14,9 +14,11 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cloud_storage"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cloud_storage/client"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
|
||||
@@ -37,6 +39,7 @@ type IBackupService interface {
|
||||
Delete(id uint) error
|
||||
RefreshToken(req dto.OperateByID) error
|
||||
GetLocalDir() (string, error)
|
||||
UploadForRecover(req dto.UploadForRecover) error
|
||||
|
||||
MysqlBackup(db dto.CommonBackup) error
|
||||
PostgresqlBackup(db dto.CommonBackup) error
|
||||
@@ -307,6 +310,16 @@ func (u *BackupService) RefreshToken(req dto.OperateByID) error {
|
||||
return backupRepo.Save(&backup)
|
||||
}
|
||||
|
||||
func (u *BackupService) UploadForRecover(req dto.UploadForRecover) error {
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(req.TargetDir) {
|
||||
if err := fileOp.CreateDir(req.TargetDir, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return fileOp.Copy(req.FilePath, req.TargetDir)
|
||||
}
|
||||
|
||||
func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, error) {
|
||||
client, err := newClient(backup, false)
|
||||
if err != nil {
|
||||
@@ -393,9 +406,13 @@ type backupClientHelper struct {
|
||||
name string
|
||||
backupPath string
|
||||
client cloud_storage.CloudStorageClient
|
||||
|
||||
isOk bool
|
||||
hasBackup bool
|
||||
message string
|
||||
}
|
||||
|
||||
func NewBackupClientMap(ids []string) (map[string]backupClientHelper, error) {
|
||||
func NewBackupClientMap(ids []string) map[string]backupClientHelper {
|
||||
var accounts []model.BackupAccount
|
||||
var idItems []uint
|
||||
for i := 0; i < len(ids); i++ {
|
||||
@@ -406,18 +423,63 @@ func NewBackupClientMap(ids []string) (map[string]backupClientHelper, error) {
|
||||
clientMap := make(map[string]backupClientHelper)
|
||||
for _, item := range accounts {
|
||||
backClient, err := newClient(&item, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientMap[fmt.Sprintf("%v", item.ID)] = backupClientHelper{
|
||||
itemHelper := backupClientHelper{
|
||||
client: backClient,
|
||||
name: item.Name,
|
||||
backupPath: item.BackupPath,
|
||||
accountType: item.Type,
|
||||
id: item.ID,
|
||||
isOk: err == nil,
|
||||
}
|
||||
if err != nil {
|
||||
itemHelper.message = err.Error()
|
||||
}
|
||||
clientMap[fmt.Sprintf("%v", item.ID)] = itemHelper
|
||||
}
|
||||
return clientMap, nil
|
||||
return clientMap
|
||||
}
|
||||
|
||||
func uploadWithMap(taskItem task.Task, accountMap map[string]backupClientHelper, src, dst, accountIDs string, downloadAccountID, retry uint) error {
|
||||
accounts := strings.Split(accountIDs, ",")
|
||||
for _, account := range accounts {
|
||||
if len(account) == 0 {
|
||||
continue
|
||||
}
|
||||
itemBackup, ok := accountMap[account]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if itemBackup.hasBackup {
|
||||
continue
|
||||
}
|
||||
if !itemBackup.isOk {
|
||||
taskItem.LogFailed(i18n.GetMsgWithDetail("LoadBackupFailed", itemBackup.message))
|
||||
continue
|
||||
}
|
||||
name := itemBackup.name
|
||||
if itemBackup.name == "localhost" {
|
||||
name = i18n.GetMsgByKey("Localhost")
|
||||
}
|
||||
taskItem.LogStart(i18n.GetMsgWithMap("UploadFile", map[string]interface{}{
|
||||
"file": path.Join(itemBackup.backupPath, dst),
|
||||
"backup": name,
|
||||
}))
|
||||
for i := 0; i < int(retry)+1; i++ {
|
||||
_, err := itemBackup.client.Upload(src, path.Join(itemBackup.backupPath, dst))
|
||||
taskItem.LogWithStatus(i18n.GetMsgByKey("Upload"), err)
|
||||
if err != nil {
|
||||
if account == fmt.Sprintf("%d", downloadAccountID) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
itemBackup.hasBackup = true
|
||||
accountMap[account] = itemBackup
|
||||
}
|
||||
os.RemoveAll(src)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newClient(account *model.BackupAccount, isEncrypt bool) (cloud_storage.CloudStorageClient, error) {
|
||||
|
||||
@@ -45,36 +45,29 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, er
|
||||
fileName = fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
|
||||
}
|
||||
|
||||
backupApp := func() (*model.BackupRecord, error) {
|
||||
if err = handleAppBackup(&install, nil, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
|
||||
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err)
|
||||
return nil, err
|
||||
}
|
||||
record := &model.BackupRecord{
|
||||
Type: "app",
|
||||
Name: req.Name,
|
||||
DetailName: req.DetailName,
|
||||
SourceAccountIDs: "1",
|
||||
DownloadAccountID: 1,
|
||||
FileDir: itemDir,
|
||||
FileName: fileName,
|
||||
Description: req.Description,
|
||||
}
|
||||
if err := backupRepo.CreateRecord(record); err != nil {
|
||||
global.LOG.Errorf("save backup record failed, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return record, nil
|
||||
record := &model.BackupRecord{
|
||||
Type: "app",
|
||||
Name: req.Name,
|
||||
DetailName: req.DetailName,
|
||||
SourceAccountIDs: "1",
|
||||
DownloadAccountID: 1,
|
||||
FileDir: itemDir,
|
||||
FileName: fileName,
|
||||
TaskID: req.TaskID,
|
||||
Status: constant.StatusWaiting,
|
||||
Description: req.Description,
|
||||
}
|
||||
if err := backupRepo.CreateRecord(record); err != nil {
|
||||
global.LOG.Errorf("save backup record failed, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.TaskID != "" {
|
||||
go func() {
|
||||
_, _ = backupApp()
|
||||
}()
|
||||
} else {
|
||||
return backupApp()
|
||||
if err = handleAppBackup(&install, nil, record.ID, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
|
||||
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err)
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
return record, nil
|
||||
}
|
||||
|
||||
func (u *BackupService) AppRecover(req dto.CommonRecover) error {
|
||||
@@ -94,11 +87,9 @@ func (u *BackupService) AppRecover(req dto.CommonRecover) error {
|
||||
if _, err := compose.Down(install.GetComposePath()); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
if err := handleAppRecover(&install, nil, req.File, false, req.Secret, req.TaskID); err != nil {
|
||||
global.LOG.Errorf("recover app %s failed, err: %v", req.DetailName, err)
|
||||
}
|
||||
}()
|
||||
if err := handleAppRecover(&install, nil, req.File, false, req.Secret, req.TaskID); err != nil {
|
||||
global.LOG.Errorf("recover app %s failed, err: %v", req.DetailName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -111,7 +102,7 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
|
||||
}
|
||||
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
|
||||
databaseHelper := DatabaseHelper{Database: db.MysqlName, DBType: resourceKey, Name: db.Name}
|
||||
if err := handleMysqlBackup(databaseHelper, parentTask, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
|
||||
if err := handleMysqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
|
||||
return err
|
||||
}
|
||||
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
|
||||
@@ -122,7 +113,7 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
|
||||
}
|
||||
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
|
||||
databaseHelper := DatabaseHelper{Database: db.PostgresqlName, DBType: resourceKey, Name: db.Name}
|
||||
if err := handlePostgresqlBackup(databaseHelper, parentTask, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
|
||||
if err := handlePostgresqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
|
||||
return err
|
||||
}
|
||||
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
|
||||
@@ -130,25 +121,34 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret, taskID string) error {
|
||||
func handleAppBackup(install *model.AppInstall, parentTask *task.Task, recordID uint, backupDir, fileName, excludes, secret, taskID string) error {
|
||||
var (
|
||||
err error
|
||||
backupTask *task.Task
|
||||
)
|
||||
backupTask = parentTask
|
||||
if parentTask == nil {
|
||||
backupTask, err = task.NewTaskWithOps(install.Name, task.TaskBackup, task.TaskScopeApp, taskID, install.ID)
|
||||
backupTask, err = task.NewTaskWithOps(install.Name, task.TaskBackup, task.TaskScopeBackup, taskID, install.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
itemHandler := func() error { return doAppBackup(install, backupTask, backupDir, fileName, excludes, secret) }
|
||||
backupTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), func(t *task.Task) error { return itemHandler() }, nil)
|
||||
if parentTask != nil {
|
||||
return itemHandler()
|
||||
}
|
||||
return backupTask.Execute()
|
||||
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
|
||||
go func() {
|
||||
if err := backupTask.Execute(); err != nil {
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverFile string, isRollback bool, secret, taskID string) error {
|
||||
@@ -160,7 +160,7 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
)
|
||||
recoverTask = parentTask
|
||||
if parentTask == nil {
|
||||
recoverTask, err = task.NewTaskWithOps(install.Name, task.TaskRecover, task.TaskScopeApp, taskID, install.ID)
|
||||
recoverTask, err = task.NewTaskWithOps(install.Name, task.TaskRecover, task.TaskScopeBackup, taskID, install.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -170,7 +170,7 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
fileOp := files.NewFileOp()
|
||||
if !isRollback {
|
||||
rollbackFile = path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)))
|
||||
if err := handleAppBackup(install, recoverTask, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
|
||||
if err := handleAppBackup(install, recoverTask, 0, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
|
||||
t.Log(fmt.Sprintf("backup app %s for rollback before recover failed, err: %v", install.Name, err))
|
||||
}
|
||||
}
|
||||
@@ -308,6 +308,10 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
return nil
|
||||
}
|
||||
|
||||
if parentTask != nil {
|
||||
return recoverApp(parentTask)
|
||||
}
|
||||
|
||||
rollBackApp := func(t *task.Task) {
|
||||
if isRollback {
|
||||
return
|
||||
@@ -324,12 +328,11 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
}
|
||||
}
|
||||
|
||||
recoverTask.AddSubTask(task.GetTaskName(install.Name, task.TaskRecover, task.TaskScopeApp), recoverApp, rollBackApp)
|
||||
if parentTask != nil {
|
||||
return recoverApp(parentTask)
|
||||
}
|
||||
return recoverTask.Execute()
|
||||
recoverTask.AddSubTask(task.GetTaskName(install.Name, task.TaskRecover, task.TaskScopeBackup), recoverApp, rollBackApp)
|
||||
go func() {
|
||||
_ = recoverTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret string) error {
|
||||
@@ -351,6 +354,7 @@ func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fi
|
||||
}
|
||||
|
||||
appPath := install.GetPath()
|
||||
parentTask.LogStart(i18n.GetMsgByKey("TaskBackup"))
|
||||
if err := fileOp.TarGzCompressPro(true, appPath, path.Join(tmpDir, "app.tar.gz"), "", excludes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -30,11 +30,6 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
|
||||
targetDir := path.Join(global.Dir.LocalBackupDir, itemDir)
|
||||
fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
|
||||
|
||||
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
|
||||
if err := handleMysqlBackup(databaseHelper, nil, targetDir, fileName, req.TaskID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := &model.BackupRecord{
|
||||
Type: req.Type,
|
||||
Name: req.Name,
|
||||
@@ -43,68 +38,41 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
|
||||
DownloadAccountID: 1,
|
||||
FileDir: itemDir,
|
||||
FileName: fileName,
|
||||
TaskID: req.TaskID,
|
||||
Status: constant.StatusWaiting,
|
||||
Description: req.Description,
|
||||
}
|
||||
if err := backupRepo.CreateRecord(record); err != nil {
|
||||
global.LOG.Errorf("save backup record failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
|
||||
if err := handleMysqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil {
|
||||
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *BackupService) MysqlRecover(req dto.CommonRecover) error {
|
||||
if err := handleMysqlRecover(req, nil, false, req.TaskID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return handleMysqlRecover(req, nil, false, req.TaskID)
|
||||
}
|
||||
|
||||
func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
file := req.File
|
||||
fileName := path.Base(req.File)
|
||||
if strings.HasSuffix(fileName, ".tar.gz") {
|
||||
fileNameItem := time.Now().Format(constant.DateTimeSlimLayout)
|
||||
dstDir := fmt.Sprintf("%s/%s", path.Dir(req.File), fileNameItem)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(dstDir) {
|
||||
if err := fileOp.CreateDir(dstDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err)
|
||||
}
|
||||
}
|
||||
if err := fileOp.TarGzExtractPro(req.File, dstDir, ""); err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("decompress file %s successful, now start to check test.sql is exist", req.File)
|
||||
hasTestSql := false
|
||||
_ = filepath.Walk(dstDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if !info.IsDir() && info.Name() == "test.sql" {
|
||||
hasTestSql = true
|
||||
file = path
|
||||
fileName = "test.sql"
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if !hasTestSql {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return fmt.Errorf("no such file named test.sql in %s", fileName)
|
||||
}
|
||||
defer func() {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
}()
|
||||
recoveFile, err := loadSqlFile(req.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.File = recoveFile
|
||||
|
||||
req.File = path.Dir(file) + "/" + fileName
|
||||
if err := handleMysqlRecover(req, nil, false, req.TaskID); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("recover from uploads successful!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, fileName, taskID string) error {
|
||||
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error {
|
||||
var (
|
||||
err error
|
||||
backupTask *task.Task
|
||||
@@ -116,18 +84,25 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, file
|
||||
}
|
||||
itemName := fmt.Sprintf("%s[%s] - %s", db.Database, db.DBType, db.Name)
|
||||
if parentTask == nil {
|
||||
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, dbInfo.ID)
|
||||
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeBackup, taskID, dbInfo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
itemHandler := func() error { return doMysqlBackup(db, targetDir, fileName) }
|
||||
backupTask.AddSubTask(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeDatabase), func(t *task.Task) error { return itemHandler() }, nil)
|
||||
if parentTask != nil {
|
||||
return itemHandler()
|
||||
}
|
||||
return backupTask.Execute()
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
|
||||
go func() {
|
||||
if err := backupTask.Execute(); err != nil {
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool, taskID string) error {
|
||||
@@ -142,7 +117,7 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
}
|
||||
itemName := fmt.Sprintf("%s[%s] - %s", req.Name, req.Type, req.DetailName)
|
||||
if parentTask == nil {
|
||||
itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeDatabase, taskID, dbInfo.ID)
|
||||
itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeBackup, taskID, dbInfo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -172,8 +147,6 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
Format: dbInfo.Format,
|
||||
TargetDir: path.Dir(rollbackFile),
|
||||
FileName: path.Base(rollbackFile),
|
||||
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("backup mysql db %s for rollback before recover failed, err: %v", req.DetailName, err)
|
||||
}
|
||||
@@ -186,8 +159,6 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
Version: version,
|
||||
Format: dbInfo.Format,
|
||||
SourceFile: rollbackFile,
|
||||
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
|
||||
} else {
|
||||
@@ -205,8 +176,6 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
Version: version,
|
||||
Format: dbInfo.Format,
|
||||
SourceFile: req.File,
|
||||
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("recover mysql db %s from %s failed, err: %v", req.DetailName, req.File, err)
|
||||
return err
|
||||
@@ -214,12 +183,15 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
isOk = true
|
||||
return nil
|
||||
}
|
||||
itemTask.AddSubTask(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil)
|
||||
if parentTask != nil {
|
||||
return recoverDatabase(parentTask)
|
||||
}
|
||||
|
||||
return itemTask.Execute()
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 3, time.Hour)
|
||||
go func() {
|
||||
_ = itemTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
|
||||
@@ -238,8 +210,58 @@ func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
|
||||
Format: dbInfo.Format,
|
||||
TargetDir: targetDir,
|
||||
FileName: fileName,
|
||||
|
||||
Timeout: 300,
|
||||
}
|
||||
return cli.Backup(backupInfo)
|
||||
}
|
||||
|
||||
func loadSqlFile(file string) (string, error) {
|
||||
if !strings.HasSuffix(file, ".tar.gz") && !strings.HasSuffix(file, ".zip") {
|
||||
return file, nil
|
||||
}
|
||||
fileName := path.Base(file)
|
||||
fileDir := path.Dir(file)
|
||||
fileNameItem := time.Now().Format(constant.DateTimeSlimLayout)
|
||||
dstDir := fmt.Sprintf("%s/%s", fileDir, fileNameItem)
|
||||
_ = os.Mkdir(dstDir, constant.DirPerm)
|
||||
if strings.HasSuffix(fileName, ".tar.gz") {
|
||||
fileOp := files.NewFileOp()
|
||||
if err := fileOp.TarGzExtractPro(file, dstDir, ""); err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(fileName, ".zip") {
|
||||
archiver, err := files.NewShellArchiver(files.Zip)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return "", err
|
||||
}
|
||||
if err := archiver.Extract(file, dstDir, ""); err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
global.LOG.Infof("decompress file %s successful, now start to check test.sql is exist", file)
|
||||
var sqlFiles []string
|
||||
hasTestSql := false
|
||||
_ = filepath.Walk(dstDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if !info.IsDir() && strings.HasSuffix(info.Name(), ".sql") {
|
||||
sqlFiles = append(sqlFiles, path)
|
||||
if info.Name() == "test.sql" {
|
||||
hasTestSql = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if len(sqlFiles) == 1 {
|
||||
return sqlFiles[0], nil
|
||||
}
|
||||
if !hasTestSql {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return "", fmt.Errorf("no such file named test.sql in %s", fileName)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
@@ -31,11 +29,6 @@ func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
|
||||
targetDir := path.Join(global.Dir.LocalBackupDir, itemDir)
|
||||
fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
|
||||
|
||||
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
|
||||
if err := handlePostgresqlBackup(databaseHelper, nil, targetDir, fileName, req.TaskID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := &model.BackupRecord{
|
||||
Type: req.Type,
|
||||
Name: req.Name,
|
||||
@@ -44,11 +37,18 @@ func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
|
||||
DownloadAccountID: 1,
|
||||
FileDir: itemDir,
|
||||
FileName: fileName,
|
||||
TaskID: req.TaskID,
|
||||
Status: constant.StatusWaiting,
|
||||
Description: req.Description,
|
||||
}
|
||||
if err := backupRepo.CreateRecord(record); err != nil {
|
||||
global.LOG.Errorf("save backup record failed, err: %v", err)
|
||||
}
|
||||
|
||||
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
|
||||
if err := handlePostgresqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (u *BackupService) PostgresqlRecover(req dto.CommonRecover) error {
|
||||
@@ -59,44 +59,11 @@ func (u *BackupService) PostgresqlRecover(req dto.CommonRecover) error {
|
||||
}
|
||||
|
||||
func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
file := req.File
|
||||
fileName := path.Base(req.File)
|
||||
if strings.HasSuffix(fileName, ".tar.gz") {
|
||||
fileNameItem := time.Now().Format(constant.DateTimeSlimLayout)
|
||||
dstDir := fmt.Sprintf("%s/%s", path.Dir(req.File), fileNameItem)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(dstDir) {
|
||||
if err := fileOp.CreateDir(dstDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err)
|
||||
}
|
||||
}
|
||||
if err := fileOp.TarGzExtractPro(req.File, dstDir, ""); err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("decompress file %s successful, now start to check test.sql is exist", req.File)
|
||||
hasTestSql := false
|
||||
_ = filepath.Walk(dstDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if !info.IsDir() && info.Name() == "test.sql" {
|
||||
hasTestSql = true
|
||||
file = path
|
||||
fileName = "test.sql"
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if !hasTestSql {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return fmt.Errorf("no such file named test.sql in %s", fileName)
|
||||
}
|
||||
defer func() {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
}()
|
||||
recoveFile, err := loadSqlFile(req.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.File = path.Dir(file) + "/" + fileName
|
||||
req.File = recoveFile
|
||||
if err := handlePostgresqlRecover(req, nil, false); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,7 +71,7 @@ func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, fileName, taskID string) error {
|
||||
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error {
|
||||
var (
|
||||
err error
|
||||
backupTask *task.Task
|
||||
@@ -112,18 +79,25 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir,
|
||||
backupTask = parentTask
|
||||
itemName := fmt.Sprintf("%s - %s", db.Database, db.Name)
|
||||
if parentTask == nil {
|
||||
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, db.ID)
|
||||
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeBackup, taskID, db.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName) }
|
||||
backupTask.AddSubTask(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeDatabase), func(task *task.Task) error { return itemHandler() }, nil)
|
||||
if parentTask != nil {
|
||||
return itemHandler()
|
||||
}
|
||||
return backupTask.Execute()
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
|
||||
go func() {
|
||||
if err := backupTask.Execute(); err != nil {
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool) error {
|
||||
@@ -137,7 +111,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
}
|
||||
itemTask = parentTask
|
||||
if parentTask == nil {
|
||||
itemTask, err = task.NewTaskWithOps(req.Name, task.TaskRecover, task.TaskScopeDatabase, req.TaskID, dbInfo.ID)
|
||||
itemTask, err = task.NewTaskWithOps(req.Name, task.TaskRecover, task.TaskScopeBackup, req.TaskID, dbInfo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -198,12 +172,15 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
isOk = true
|
||||
return nil
|
||||
}
|
||||
itemTask.AddSubTask(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil)
|
||||
if parentTask != nil {
|
||||
return recoverDatabase(parentTask)
|
||||
}
|
||||
|
||||
return itemTask.Execute()
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 3, time.Hour)
|
||||
go func() {
|
||||
_ = itemTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error {
|
||||
|
||||
@@ -6,10 +6,12 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
@@ -238,6 +240,9 @@ func (u *BackupRecordService) LoadRecordSize(req dto.SearchForSize) ([]dto.Recor
|
||||
return nil, err
|
||||
}
|
||||
for _, item := range records {
|
||||
if item.Status == constant.StatusWaiting {
|
||||
continue
|
||||
}
|
||||
list = append(list, backupSizeHelper{ID: item.ID, DownloadID: item.DownloadAccountID, FilePath: path.Join(item.FileDir, item.FileName)})
|
||||
}
|
||||
}
|
||||
@@ -249,20 +254,32 @@ func (u *BackupRecordService) LoadRecordSize(req dto.SearchForSize) ([]dto.Recor
|
||||
recordIds = append(recordIds, fmt.Sprintf("%v", record.DownloadID))
|
||||
}
|
||||
}
|
||||
clientMap, err := NewBackupClientMap(recordIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientMap := NewBackupClientMap(recordIds)
|
||||
var datas []dto.RecordFileSize
|
||||
var wg sync.WaitGroup
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
for i := 0; i < len(list); i++ {
|
||||
datas = append(datas, dto.RecordFileSize{ID: list[i].ID})
|
||||
if val, ok := clientMap[fmt.Sprintf("%v", list[i].DownloadID)]; ok {
|
||||
if !val.isOk {
|
||||
continue
|
||||
}
|
||||
wg.Add(1)
|
||||
go func(index int) {
|
||||
datas[index].Size, _ = val.client.Size(path.Join(val.backupPath, list[i].FilePath))
|
||||
wg.Done()
|
||||
defer wg.Done()
|
||||
done := make(chan struct{}, 1)
|
||||
go func() {
|
||||
datas[index].Size, _ = val.client.Size(path.Join(val.backupPath, list[i].FilePath))
|
||||
defer close(done)
|
||||
}()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user