Compare commits

...
Author SHA1 Message Date
ssongliu 217d780ed1 fix: Fix the issue of abnormal time display on the monitoring page (#11001) 2025-11-20 02:11:01 +00:00
蘭 fe62dc18fa fix: Fix the issue of creating file/folder hierarchy errors (#10999) 2025-11-19 08:42:59 +00:00
KOMATA d0e95903c9 chore: disable CSS code splitting in Vite config (#10996) 2025-11-19 14:03:23 +08:00
CityFun 1ec7f519c6 fix: resolve certificate push losing other domain data (#10998)
Refs https://github.com/1Panel-dev/1Panel/issues/10988
2025-11-19 06:02:59 +00:00
CityFun 450e8b18cf refactor: remove unused code (#10995) 2025-11-19 03:50:59 +00:00
ssongliu bb882286aa fix: Fix the monitoring settings menu title display issue (#10994) 2025-11-19 03:48:58 +00:00
蘭 d9bbde9e50 feat: code editor supports creating files and folders (#10989)
#10424
2025-11-18 14:34:58 +00:00
CityFun 29746d1b32 refactor: remove unused code (#10987) 2025-11-18 19:12:37 +08:00
ssongliu 5f211961ae fix: Fix the issue of abnormal disk display on the overview page (#10986)
Refs #10982
2025-11-18 09:26:57 +00:00
CityFun 91d364b18b feat: improve LVM partition recognition in disk management (#10985) 2025-11-18 06:22:56 +00:00
CityFun f1677f5a67 fix: resolve network connection count always showing 0 in process list (#10979) 2025-11-18 14:04:23 +08:00
KOMATA fd270263f4 fix: Update Enter key event handling in terminal input to prevent default behavior (#10984) 2025-11-18 14:04:00 +08:00
ssongliu 81c1e90e54 chore: Clean up some unused code (#10977) 2025-11-17 08:32:54 +00:00
ssongliu 3b737184ea fix: Fix the issue of postgres database not being synchronized (#10976)
Refs #10966
2025-11-17 08:30:55 +00:00
ssongliu 4779bffceb fix: Fix the system proxy validation issue (#10975)
Refs #10974
2025-11-17 08:28:55 +00:00
KOMATA 4209ee4486 feat: enhance S3 region selection with dropdown and custom input option (#10967)
* feat: enhance S3 region selection with dropdown and custom input option

* refactor: streamline S3 region selection and endpoint handling in backup account settings
2025-11-17 13:39:33 +08:00
ssongliu 6ca352bf85 fix: Fix the issue where pressing Enter to submit in description edit… (#10972)
…ing does not take effect
2025-11-17 04:18:53 +00:00
CityFun a4d77a1cc2 fix: resolve incorrect container filter condition when redirecting applications (#10971) 2025-11-17 11:44:32 +08:00
ssongliu b9367abfb9 feat: Optimize container cleanup task logs (#10970) 2025-11-17 03:40:53 +00:00
ssongliu a6062897d5 fix: Support encrypted backup of databases (#10963) 2025-11-14 22:12:55 +08:00
蘭 1afe84ed02 fix: Fix menu drag and drop issue (#10962)
#10961
2025-11-14 10:24:53 +00:00
ssongliu 388458f759 feat: Image build supports setting build parameters (#10960)
Refs #10898
2025-11-14 10:22:49 +00:00
CityFun 512ff23f19 feat: add tooltips for transfer application (#10959) 2025-11-14 05:44:49 +00:00
ssongliu 45a32ff255 chore: remove debug log in controller (#10958) 2025-11-14 05:42:50 +00:00
蘭 e4e2d76f75 feat: File manager multi-tab start path optimization (#10957)
#10302
2025-11-14 05:40:52 +00:00
KOMATA 282e196534 refactor: Simplify PHP config update logic by replacing regex with a dedicated function for key matching (#10956) 2025-11-14 13:39:39 +08:00
ssongliu e4fbd3cf86 fix: Fix the issue of abnormal ufw status loading (#10949) 2025-11-13 21:36:35 +08:00
ssongliu 402931862f fix: Fix the issue where iptables description does not take effect (#10947) 2025-11-13 08:36:47 +00:00
CityFun a70e2635ab fix(ssl): prevent domain loss when editing certificate remark (#10946) 2025-11-13 15:43:25 +08:00
ssongliu 8c9ae38017 fix: Modify the binding position of the 1PANEL_OUTPUT chain (#10945) 2025-11-13 15:43:10 +08:00
CityFun 3920076bd9 feat(website): support 128 characters for site alias (#10943)
Refs https://github.com/1Panel-dev/1Panel/issues/10787
2025-11-13 07:42:46 +00:00
ssongliu 55cbf572e0 fix: Fix the issue where deleting rules in iptables advanced settings… (#10942)
… fails
2025-11-13 06:38:47 +00:00
CityFun c4bd4734a5 feat(log): optimize log display (#10941) 2025-11-13 14:37:39 +08:00
ssongliu e7810febd6 fix: Fix the issue of abnormal context in the cmd method (#10939) 2025-11-13 14:37:28 +08:00
ssongliu 0bc9e85734 fix: Fix the issue of abnormal iptables range port addition (#10938) 2025-11-12 22:26:59 +08:00
蘭 4d85ae5fa6 fix: Fix the issue of initializing SMS sending quantity as a string (#10936) 2025-11-12 14:24:45 +00:00
蘭 a7342d6ef2 fix: More button operations rename using drawer processing parameters (#10933)
#10591
2025-11-12 10:30:46 +00:00
ssongliu 5b0fccd19a fix: Fix the issue of license status refresh after import (#10934) 2025-11-12 18:29:10 +08:00
ssongliu ebbfed711c fix: Modify the service backup directory (#10930) 2025-11-12 10:28:44 +00:00
ssongliu d631888d09 fix: Modify the unbound status of iptables firewall (#10928) 2025-11-12 06:46:44 +00:00
KOMATA afd62e8539 fix: Fix bug in iptables firewall module (#10927) 2025-11-12 11:49:24 +08:00
ssongliu 4aca66c417 fix: Add existence check when restarting Docker (#10926)
Refs  #10890
2025-11-12 02:24:42 +00:00
ssongliu 944463e9a8 fix: Fix the issue of excessively long container detail ports (#10924) 2025-11-11 22:52:57 +08:00
ssongliu cf4274afdc feat: support paginated viewing of imported data (#10923) 2025-11-11 22:41:28 +08:00
ssongliu 102f7c316d fix: display iptables default allowed ports (#10922) 2025-11-11 14:22:42 +00:00
KOMATA ffc81ea85a fix: enhance ping status and update logic in firewall service (#10920)
* fix: Update ping status check method

* fix: Enhance ping status update logic and support for alternative sysctl configuration path
2025-11-11 22:20:09 +08:00
KOMATA 02d22ba63f feat: refactor regex usage across multiple files and centralize patterns in a new utility (#10896) 2025-11-11 16:14:09 +08:00
CityFun 51e98623c9 feat: add MODEL_PATH environment for tensorrt llm (#10921) 2025-11-11 15:41:29 +08:00
ssongliu 8e94170fed fix: modify some API documentation (#10919)
Refs #10893
2025-11-11 06:26:41 +00:00
ssongliu 42cee513e0 style: modify license binding display information (#10918)
Refs #10895
2025-11-11 06:24:40 +00:00
CityFun 2c18382f46 feat: optimize website log display (#10914) 2025-11-11 06:22:40 +00:00
CityFun 3773412139 feat: order env for tensorrt_llm (#10916) 2025-11-11 14:09:25 +08:00
ssongliu e17bbdd6a7 fix: Fix the issue of abnormal option switching on the monitoring page (#10913) 2025-11-11 11:26:24 +08:00
巴山夜语 82a0f3a770 feat: Add utility to retrieve service configuration paths (#10891) 2025-11-11 11:12:34 +08:00
ssongliu 11e16abe64 fix: modify cronjob name validation (#10911) 2025-11-10 22:37:42 +08:00
ssongliu 6db79f4b7b feat: support iptables firewall control (#10903) 2025-11-10 21:17:53 +08:00
ssongliu 977a4be3c1 fix: Fix the issue of abnormal application port forwarding (#10910) 2025-11-10 10:52:40 +00:00
CityFun 51ae668154 fix: Fixed issue with update runtime ExtraHosts failed (#10909) 2025-11-10 10:38:39 +00:00
CityFun c6fe487e46 fix: Fixed the issue of database transfer failure to child nodes (#10906) 2025-11-10 18:09:39 +08:00
KOMATA ec4533e7de feat: enhance terminal connection UI with improved popover design and search functionality (#10902) 2025-11-10 17:27:47 +08:00
CityFun 3b73de32ad feat: support tensorrt LLM speedup (#10905) 2025-11-10 08:40:37 +00:00
CityFun da5668ac27 fix: Fix incorrect upgrade notification issue (#10901) 2025-11-10 04:02:38 +00:00
刘瑞斌 c1039fb7f2 feat: Add ResizeObserver to dynamically adjust terminal size on container resize (#10894) 2025-11-10 09:39:02 +08:00
CityFun c82d6838c5 feat: Optimize system disk detection logic (#10889)
Refs https://github.com/1Panel-dev/1Panel/issues/10888
2025-11-07 10:06:31 +00:00
CityFun c40c7b57cb feat: Change the order of backup buttons (#10886) 2025-11-07 08:36:31 +00:00
CityFun 009237a35a feat: change gin start mode (#10885) 2025-11-07 08:34:30 +00:00
KOMATA f4f6f65b4c feat: add lighter fill color and table row hover background for dark theme (#10883) 2025-11-07 14:51:27 +08:00
CityFun 313a8a3380 chore(deps): bump dependencies in go.mod (#10884) 2025-11-07 06:50:30 +00:00
CityFun f686e7cbc4 fix: Fixed issue where applications failed to load when creating deployment websites (#10882) 2025-11-07 06:48:30 +00:00
CityFun 7fa39687b5 fix: Fixed issue where original Compose file content was cleared during comparison (#10880) 2025-11-07 06:46:30 +00:00
CityFun 9d84120181 feat: Add log cleanup support for scheduled tasks (#10871)
Refs https://github.com/1Panel-dev/1Panel/issues/5639
2025-11-05 10:08:25 +00:00
CityFun 3be0dab8a3 fix: Fix the issue where PHP extensions fail to install. (#10869) 2025-11-05 15:34:02 +08:00
CityFun 3a9275d5fa feat: Optimize the check for deleting associated databases when removing app (#10868) 2025-11-05 07:32:27 +00:00
ssongliu 6296aa04c6 feat: Cronjob reports add an unexecuted status (#10866)
Refs #10861
2025-11-05 07:30:25 +00:00
KOMATA cfe9e94e16 feat: add sensitive info mask (#10865) 2025-11-05 09:38:42 +08:00
ssongliu 902d329e78 feat: Container overview page supports displaying disk usage information (#10864) 2025-11-04 22:53:54 +08:00
CityFun 62f59eb1c3 feat: Add a check during upgrade to detect whether the Compose file has been modified. (#10863) 2025-11-04 22:53:33 +08:00
CityFun a7d4c4ebec feat: Optimize environment port mappings (#10856) 2025-11-04 15:55:16 +08:00
CityFun 0ca96621d4 feat: Edit the application Compose content to add a comparison. (#10855) 2025-11-04 15:36:34 +08:00
ssongliu 7ea179c2da fix: SSH client execution compatible with controller (#10854) 2025-11-04 15:36:18 +08:00
CityFun 6982396572 style: Optimize batch delete website (#10853)
Refs https://github.com/1Panel-dev/1Panel/issues/10851
2025-11-04 06:14:24 +00:00
KOMATA 36c4fbfeee fix: disable ip input when choosing unsupported network type (#10849) 2025-11-04 09:51:35 +08:00
CityFun 868c6f47a0 style: Optimize application installation style (#10847)
Refs https://github.com/1Panel-dev/1Panel/issues/10845
2025-11-03 10:46:23 +00:00
KOMATA 74695ab276 fix: add copy button for image name (#10837) 2025-11-03 16:47:04 +08:00
KOMATA cb74d8d51b feat: Add network details drawer component (#10836) 2025-11-03 16:46:39 +08:00
ssongliu eaa620b081 feat: Add real-time process display on the overview page (#10833) 2025-10-31 10:36:19 +00:00
CityFun 18ab07ec4f feat: Support application migration to other nodes. (#10832)
Refs https://github.com/1Panel-dev/1Panel/issues/10509
2025-10-31 10:34:20 +00:00
ssongliu e86bc9a8db feat: Container operations support task logs (#10824)
Refs #10817
2025-10-30 09:42:18 +00:00
ssongliu 75837c87b4 fix: Update swagger API documentation (#10822)
Refs #10816
2025-10-30 08:50:18 +00:00
ssongliu 9a73095a8f feat: System monitoring supports process viewing (#10821)
Refs #3437
2025-10-30 08:48:18 +00:00
wanghe-fit2cloud 9242bf6482 feat: service handling on more platforms 2025-10-30 14:50:33 +08:00
CityFun f552a0ac36 feat: update docker sdk (#10814) 2025-10-29 05:42:17 +00:00
ssongliu 141e2f61eb fix: Optimize the compose env file prompt message (#10813)
Refs #7604
2025-10-29 05:40:19 +00:00
蘭 b6d7b319f2 fix: Fix the issue of failure caused by incorrect email service parameters (#10811)
#10803
2025-10-29 05:38:18 +00:00
ssongliu 4cdc6c80ec feat: Compose templates support import and export (#10809) 2025-10-29 13:36:24 +08:00
Jimes cee9d7ffb0 chore: Correct typo in redirect text 2025-10-29 09:05:24 +08:00
Jimes 3f48bdb216 chore: replace '登陆' with '登录' 2025-10-29 09:03:58 +08:00
CityFun 2cef8dcea4 feat: change tensorrt button logic (#10805) 2025-10-28 18:56:45 +08:00
CityFun c327936db1 core: update github.com/docker/compose/v2 version (#10804) 2025-10-28 10:20:16 +00:00
CityFun 1b53cd4ca8 feat: add sync waf ip group cron job (#10802)
Refs https://github.com/1Panel-dev/1Panel/issues/8915
2025-10-28 10:18:18 +00:00
ssongliu 08f9f6f8e5 feat: Support using proxies for inter-node requests (#10799)
Refs #9903
2025-10-28 10:16:18 +00:00
CityFun fb6b2729c6 feat: Website Load balancer config support fail_timeout (#10796)
Refs https://github.com/1Panel-dev/1Panel/issues/10565
2025-10-28 08:28:16 +00:00
CityFun aa55a18ed8 feat: Fix highlighting issues in the ssh config editor. (#10794)
Refs https://github.com/1Panel-dev/1Panel/issues/6496
2025-10-28 08:26:18 +00:00
ssongliu 6c74c64b29 style: Optimize the container details page style (#10791) 2025-10-28 08:24:17 +00:00
maolei fddbf34684 feat: Add automatic SSL certificate selection when creating a website with HTTPS enabled (#10789)
Optimize the default selection logic after the SSL list is loaded.
Add a flagging mechanism for manual SSL certificate selection, which disables automatic selection once triggered.
Add listeners for changes to the primary and more domains to trigger this automatic selection logic.
2025-10-28 13:49:34 +08:00
KOMATA ea878bba73 feat: add Docker Inspect dialog with tabbed container info view and enhanced visual formatting (#10783)
* feat: Expand Docker inspect detail drawer

* chore: i18n

* fix: switch order in mount detail card.
2025-10-27 18:11:50 +08:00
CityFun db002ec915 feat: Add settings to prevent certificate leakage. (#10785)
Refs https://github.com/1Panel-dev/1Panel/issues/10755
2025-10-27 10:06:17 +00:00
ssongliu 606d3c1717 fix: Improve system monitoring settings (#10784)
Refs #5121 #8390
2025-10-27 10:04:17 +00:00
CityFun b0fbb39cd3 style: Optimize app name display for large screens (#10782)
Refs https://github.com/1Panel-dev/1Panel/issues/10764
2025-10-27 10:02:18 +00:00
ssongliu 2478d26c59 fix: Add validation rules for scheduled task names (#10780)
Refs #10741
2025-10-27 10:00:18 +00:00
ssongliu e072620f9b style: Optimize the style of firewall import and export (#10778) 2025-10-27 17:59:06 +08:00
CityFun dd3419bf52 feat: support architecture detail display for local app (#10777)
Refs https://github.com/1Panel-dev/1Panel/issues/10770
2025-10-27 09:58:16 +00:00
ssongliu f12e70ef5d feat: Support importing licenses when adding nodes (#10776)
Refs #9793
2025-10-27 09:56:16 +00:00
ssongliu 2836207850 fix: Fix the issue of abnormal redirection after deleting a tab (#10774)
Refs #10767
2025-10-27 09:54:16 +00:00
ssongliu 4253b48bba fix: Fix the issue of abnormal menu tab switching (#10773)
Refs #10765
2025-10-27 09:52:18 +00:00
KOMATA ff36b65af4 feat: Optimize i18n by dynamically loading module (#10759)
* feat: Optimize internationalization support, dynamically load language packs and update language settings

* feat: Refactor i18n initialization to load initial messages dynamically
2025-10-27 17:49:52 +08:00
KOMATA 1ef4803954 feat: Enhance cache display and setting in proxy configuration (#10751)
* feat: Enhance caching options for proxy configuration

* fix: typo

* feat: Update caching and directive handling in proxy configuration

* feat: Update default cache time and unit to improve caching configuration

* feat: Implement RemoveCorsOption method to streamline CORS directive removal

* feat: Enhance cache display and initialization in proxy configuration

* refactor: Clean up AddBrowserCache and RemoveCache methods by removing commented-out code
2025-10-24 18:17:51 +08:00
CityFun 08ebbee328 feat: support bach set website group (#10754) 2025-10-24 10:00:14 +00:00
ssongliu d8e4144d46 feat: Child nodes support upgrading together with the master node (#10753)
Refs #9647
2025-10-24 09:14:15 +00:00
CityFun 0b1819576d feat: runtime support config extra_hosts (#10750)
Refs https://github.com/1Panel-dev/1Panel/issues/10250
2025-10-24 08:56:15 +00:00
BugKing 6ce33754a8 chore: Add id attribute to welcome dialog (#10746) 2025-10-24 15:45:11 +08:00
KOMATA 21e0808a86 fix: Replace RemoveDirective with RemoveDirectiveByFullParams for better parameter matching (#10748) 2025-10-24 15:19:32 +08:00
KOMATA 3480182473 feat: Refactor quick command function, turn cascader into palette (#10732) 2025-10-23 17:20:16 +08:00
CityFun e516158294 feat: Reduce Echarts bundle size (#10731) 2025-10-23 17:17:42 +08:00
ssongliu c8ee0af152 fix: Fix the packaging failure issue (#10734) 2025-10-23 16:40:45 +08:00
ssongliu 3b82d2a1ee feat: Add xplay welcome page (#10733) 2025-10-23 16:27:11 +08:00
CityFun 274fd526b7 feat: optimization waf map load (#10730) 2025-10-23 16:00:23 +08:00
ssongliu 86b0e01d9d fix: Optimize the container command input method (#10724) 2025-10-22 18:33:10 +08:00
ssongliu c06ba18023 feat: compatible with openrc and sysvinit (#10723) 2025-10-22 18:32:42 +08:00
KOMATA f462591e9c feat: add firewall rule import/export with JSON validation and alerts (#10706) 2025-10-22 18:31:26 +08:00
330 changed files with 16446 additions and 5191 deletions
+3 -2
View File
@@ -70,11 +70,12 @@ archives:
wrap_in_directory: true
files:
- 1pctl
- install.sh
- 1panel-core.service
- 1panel-agent.service
- install.sh
- GeoIP.mmdb
- initscript/*
- lang/*
- GeoIP.mmdb
checksum:
name_template: 'checksums.txt'
+4 -4
View File
@@ -30,19 +30,19 @@ build_frontend:
build_core_on_linux:
cd $(CORE_PATH) \
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
&& CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
build_agent_on_linux:
cd $(AGENT_PATH) \
&& GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
&& CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_core_on_darwin:
cd $(CORE_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(CORE_NAME) $(CORE_MAIN)
build_agent_on_darwin:
cd $(AGENT_PATH) \
&& GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -trimpath -ldflags '-s -w' -o $(BUILD_PATH)/$(AGENT_NAME) $(AGENT_MAIN)
build_all: build_frontend build_core_on_linux build_agent_on_linux
+22
View File
@@ -28,6 +28,28 @@ func (b *BaseApi) CreateComposeTemplate(c *gin.Context) {
helper.Success(c)
}
// @Tags Container Compose-template
// @Summary Bacth compose template
// @Accept json
// @Param request body dto.ComposeTemplateBatch true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/template/batch [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量导入编排模版","formatEN":"batch import compose templates"}
func (b *BaseApi) BatchComposeTemplate(c *gin.Context) {
var req dto.ComposeTemplateBatch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := composeTemplateService.Batch(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Container Compose-template
// @Summary Page compose templates
// @Accept json
+1 -1
View File
@@ -314,7 +314,7 @@ func (b *BaseApi) ContainerCreateByCommand(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/upgrade [post]
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [name][image]","formatEN":"upgrade container image [name][image]"}
// @x-panel-log {"bodyKeys":["names","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [names][image]","formatEN":"upgrade container image [names][image]"}
func (b *BaseApi) ContainerUpgrade(c *gin.Context) {
var req dto.ContainerUpgrade
if err := helper.CheckBindAndValidate(&req, c); err != nil {
+1 -1
View File
@@ -211,7 +211,7 @@ func (b *BaseApi) LoadRecordLog(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /cronjobs/records/clean [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
// @x-panel-log {"bodyKeys":["cronjobID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"cronjobID","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
func (b *BaseApi) CleanRecord(c *gin.Context) {
var req dto.CronjobClean
if err := helper.CheckBindAndValidate(&req, c); err != nil {
+1
View File
@@ -38,6 +38,7 @@ var (
fileService = service.NewIFileService()
sshService = service.NewISSHService()
firewallService = service.NewIFirewallService()
iptablesService = service.NewIIptablesService()
monitorService = service.NewIMonitorService()
systemService = service.NewISystemService()
+124 -8
View File
@@ -8,12 +8,19 @@ import (
// @Tags Firewall
// @Summary Load firewall base info
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200 {object} dto.FirewallBaseInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/base [get]
// @Router /hosts/firewall/base [post]
func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) {
data, err := firewallService.LoadBaseInfo()
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := firewallService.LoadBaseInfo(req.Name)
if err != nil {
helper.InternalServer(c, err)
return
@@ -95,14 +102,14 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) {
// OperateForwardRule
// @Tags Firewall
// @Summary Create group
// @Summary Operate forward rule
// @Accept json
// @Param request body dto.ForwardRuleOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/forward [post]
// @x-panel-log {"bodyKeys":["source_port"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新端口转发规则 [source_port]","formatEN":"update port forward rules [source_port]"}
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新端口转发规则","formatEN":"update port forward rules"}
func (b *BaseApi) OperateForwardRule(c *gin.Context) {
var req dto.ForwardRuleOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -117,7 +124,7 @@ func (b *BaseApi) OperateForwardRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Create group
// @Summary Operate Ip rule
// @Accept json
// @Param request body dto.AddrRuleOperate true "request"
// @Success 200
@@ -139,7 +146,7 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Create group
// @Summary Batch operate rule
// @Accept json
// @Param request body dto.BatchRuleOperate true "request"
// @Success 200
@@ -181,7 +188,7 @@ func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) {
}
// @Tags Firewall
// @Summary Create group
// @Summary Update port rule
// @Accept json
// @Param request body dto.PortRuleUpdate true "request"
// @Success 200
@@ -202,7 +209,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Create group
// @Summary Update Ip rule
// @Accept json
// @Param request body dto.AddrRuleUpdate true "request"
// @Success 200
@@ -221,3 +228,112 @@ func (b *BaseApi) UpdateAddrRule(c *gin.Context) {
}
helper.Success(c)
}
// @Tags Firewall
// @Summary search iptables filter rules
// @Accept json
// @Param request body dto.SearchPageWithType true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/search [post]
func (b *BaseApi) SearchFilterRules(c *gin.Context) {
var req dto.SearchPageWithType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := iptablesService.Search(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags Firewall
// @Summary Operate iptables filter rule
// @Accept json
// @Param request body dto.IptablesRuleOp true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/rule/operate [post]
// @x-panel-log {"bodyKeys":["operation","chain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] filter规则到 [chain]","formatEN":"[operation] filter rule to [chain]"}
func (b *BaseApi) OperateFilterRule(c *gin.Context) {
var req dto.IptablesRuleOp
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := iptablesService.OperateRule(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Firewall
// @Summary Batch operate iptables filter rules
// @Accept json
// @Param request body dto.IptablesBatchOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/rule/batch [post]
func (b *BaseApi) BatchOperateFilterRule(c *gin.Context) {
var req dto.IptablesBatchOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := iptablesService.BatchOperate(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Firewall
// @Summary Apply/Unload/Init iptables filter
// @Accept json
// @Param request body dto.IptablesOp true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/operate [post]
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] iptables filter 防火墙","formatEN":"[operate] iptables filter firewall"}
func (b *BaseApi) OperateFilterChain(c *gin.Context) {
var req dto.IptablesOp
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := iptablesService.Operate(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Firewall
// @Summary load chain status with name
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/filter/chain/status [post]
func (b *BaseApi) LoadChainStatus(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
helper.SuccessWithData(c, iptablesService.LoadChainStatus(req))
}
+2 -2
View File
@@ -161,13 +161,13 @@ func (b *BaseApi) GetNginxModules(c *gin.Context) {
// @Tags OpenResty
// @Summary Operate default HTTPs
// @Accept json
// @Param request body request.NginxOperateReq true "request"
// @Param request body request.NginxDefaultHTTPSUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /openresty/https [post]
func (b *BaseApi) OperateDefaultHTTPs(c *gin.Context) {
var req request.NginxOperateReq
var req request.NginxDefaultHTTPSUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
+1 -1
View File
@@ -40,7 +40,7 @@ func (b *BaseApi) StopProcess(c *gin.Context) {
// @Tags Process
// @Summary Get Process Info By PID
// @Param pid path int true "PID"
// @Success 200 {object} websocket.PsProcessData
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /process/{pid} [get]
+1 -1
View File
@@ -53,7 +53,7 @@ func (b *BaseApi) OperateSSH(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/update [post]
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"}
// @x-panel-log {"bodyKeys":["key","newValue"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [newValue]","formatEN":"update SSH setting [key] => [newValue]"}
func (b *BaseApi) UpdateSSH(c *gin.Context) {
var req dto.SSHUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
+22 -2
View File
@@ -672,7 +672,7 @@ func (b *BaseApi) UpdateAntiLeech(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/redirect/update [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":"Update domain [domain] redirect config"}
// @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":"Update domain [domain] redirect config"}
func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
var req request.NginxRedirectReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -1145,7 +1145,7 @@ func (b *BaseApi) ExecComposer(c *gin.Context) {
// @Tags Website
// @Summary Batch operate websites
// @Accept json
// @Param request body request.BatchOpWebsite true "request"
// @Param request body request.BatchWebsiteOp true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
@@ -1162,6 +1162,26 @@ func (b *BaseApi) BatchOpWebsites(c *gin.Context) {
helper.Success(c)
}
// @Tags Website
// @Summary Batch set website group
// @Accept json
// @Param request body request.BatchWebsiteGroup true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/batch/group [post]
func (b *BaseApi) BatchSetWebsiteGroup(c *gin.Context) {
var req request.BatchWebsiteGroup
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.BatchSetGroup(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Get CORS Config
// @Accept json
+1 -2
View File
@@ -235,7 +235,6 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) {
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 != "" {
@@ -279,7 +278,7 @@ func (b *BaseApi) UploadSSLFile(c *gin.Context) {
return
}
helper.SuccessWithData(c, nil)
helper.Success(c)
}
func readUploadedFile(fileHeader *multipart.FileHeader) ([]byte, error) {
+1 -1
View File
@@ -317,7 +317,7 @@ type AlertCommonConfig struct {
type AlertSmsConfig struct {
Phone string `json:"phone"`
AlertDailyNum uint `json:"alertDailyNum"`
AlertDailyNum string `json:"alertDailyNum"`
}
type AlertEmailConfig struct {
+4
View File
@@ -8,6 +8,10 @@ type ComposeTemplateCreate struct {
Content string `json:"content"`
}
type ComposeTemplateBatch struct {
Templates []ComposeTemplateCreate `json:"templates" validate:"required"`
}
type ComposeTemplateUpdate struct {
ID uint `json:"id"`
Description string `json:"description"`
+19 -9
View File
@@ -31,6 +31,9 @@ type ContainerInfo struct {
Network []string `json:"network"`
Ports []string `json:"ports"`
SizeRw int64 `json:"sizeRw"`
SizeRootFs int64 `json:"sizeRootFs"`
IsFromApp bool `json:"isFromApp"`
IsFromCompose bool `json:"isFromCompose"`
@@ -45,14 +48,13 @@ type ContainerOptions struct {
}
type ContainerStatus struct {
All uint `json:"all"`
Created uint `json:"created"`
Running uint `json:"running"`
Paused uint `json:"paused"`
Restarting uint `json:"restarting"`
Removing uint `json:"removing"`
Exited uint `json:"exited"`
Dead uint `json:"dead"`
Created int `json:"created"`
Running int `json:"running"`
Paused int `json:"paused"`
Restarting int `json:"restarting"`
Removing int `json:"removing"`
Exited int `json:"exited"`
Dead int `json:"dead"`
ContainerCount int `json:"containerCount"`
ComposeCount int `json:"composeCount"`
@@ -62,7 +64,14 @@ type ContainerStatus struct {
VolumeCount int `json:"volumeCount"`
RepoCount int `json:"repoCount"`
ImageSize uint64 `json:"imageSize"`
ContainerUsage int64 `json:"containerUsage"`
ContainerReclaimable int64 `json:"containerReclaimable"`
ImageUsage int64 `json:"imageUsage"`
ImageReclaimable int64 `json:"imageReclaimable"`
VolumeUsage int64 `json:"volumeUsage"`
VolumeReclaimable int64 `json:"volumeReclaimable"`
BuildCacheUsage int64 `json:"buildCacheUsage"`
BuildCacheReclaimable int64 `json:"buildCacheReclaimable"`
}
type ResourceLimit struct {
CPU int `json:"cpu"`
@@ -153,6 +162,7 @@ type PortHelper struct {
}
type ContainerOperation struct {
TaskID string `json:"taskID"`
Names []string `json:"names" validate:"required"`
Operation string `json:"operation" validate:"required,oneof=up start stop restart kill pause unpause remove"`
}
+6
View File
@@ -53,6 +53,12 @@ type CronjobOperate struct {
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
AlertMethod string `json:"alertMethod"`
CleanLogConfig
}
type CleanLogConfig struct {
Scopes []string `json:"scopes"`
}
type SnapshotRule struct {
+3
View File
@@ -116,6 +116,9 @@ type DashboardCurrent struct {
GPUData []GPUInfo `json:"gpuData"`
XPUData []XPUInfo `json:"xpuData"`
TopCPUItems []Process `json:"topCPUItems"`
TopMemItems []Process `json:"topMemItems"`
ShotTime time.Time `json:"shotTime"`
}
+9 -8
View File
@@ -281,14 +281,15 @@ type DatabaseItem struct {
}
type DatabaseCreate struct {
Name string `json:"name" validate:"required,max=256"`
Type string `json:"type" validate:"required"`
From string `json:"from" validate:"required,oneof=local remote"`
Version string `json:"version" validate:"required"`
Address string `json:"address"`
Port uint `json:"port"`
Username string `json:"username" validate:"required"`
Password string `json:"password"`
Name string `json:"name" validate:"required,max=256"`
Type string `json:"type" validate:"required"`
From string `json:"from" validate:"required,oneof=local remote"`
Version string `json:"version" validate:"required"`
Address string `json:"address"`
Port uint `json:"port"`
InitialDB string `json:"initialDB"`
Username string `json:"username" validate:"required"`
Password string `json:"password"`
SSL bool `json:"ssl"`
RootCert string `json:"rootCert"`
+37 -2
View File
@@ -4,6 +4,8 @@ type FirewallBaseInfo struct {
Name string `json:"name"`
IsExist bool `json:"isExist"`
IsActive bool `json:"isActive"`
IsInit bool `json:"isInit"`
IsBind bool `json:"isBind"`
Version string `json:"version"`
PingStatus string `json:"pingStatus"`
}
@@ -22,7 +24,9 @@ type FirewallOperation struct {
}
type PortRuleOperate struct {
ID uint `json:"id"`
Operation string `json:"operation" validate:"required,oneof=add remove"`
Chain string `json:"chain"`
Address string `json:"address"`
Port string `json:"port" validate:"required"`
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
@@ -46,8 +50,11 @@ type ForwardRuleOperate struct {
type UpdateFirewallDescription struct {
Type string `json:"type"`
Address string `json:"address"`
Port string `json:"port"`
Chain string `json:"chain"`
SrcIP string `json:"srcIP"`
DstIP string `json:"dstIP"`
SrcPort string `json:"srcPort"`
DstPort string `json:"dstPort"`
Protocol string `json:"protocol"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
@@ -55,6 +62,7 @@ type UpdateFirewallDescription struct {
}
type AddrRuleOperate struct {
ID uint `json:"id"`
Operation string `json:"operation" validate:"required,oneof=add remove"`
Address string `json:"address" validate:"required"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
@@ -76,3 +84,30 @@ type BatchRuleOperate struct {
Type string `json:"type" validate:"required"`
Rules []PortRuleOperate `json:"rules"`
}
type IptablesOp struct {
Name string `json:"name" validate:"required,oneof=1PANEL_INPUT 1PANEL_OUTPUT 1PANEL_BASIC"`
Operate string `json:"operate" validate:"required,oneof=init-base init-forward init-advance bind-base unbind-base bind unbind"`
}
type IptablesRuleOp struct {
Operation string `json:"operation" validate:"required,oneof=add remove"`
ID uint `json:"id"`
Chain string `json:"chain" validate:"required,oneof=1PANEL_BASIC 1PANEL_BASIC_BEFORE 1PANEL_INPUT 1PANEL_OUTPUT"`
Protocol string `json:"protocol"`
SrcIP string `json:"srcIP"`
SrcPort uint `json:"srcPort"`
DstIP string `json:"dstIP"`
DstPort uint `json:"dstPort"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop reject"`
Description string `json:"description"`
}
type IptablesBatchOperate struct {
Rules []IptablesRuleOp `json:"rules"`
}
type IptablesChainStatus struct {
IsBind bool `json:"isBind"`
DefaultStrategy string `json:"defaultStrategy"`
}
+4 -1
View File
@@ -18,7 +18,8 @@ type ImageInfo struct {
}
type ImageLoad struct {
Path string `json:"path" validate:"required"`
TaskID string `json:"taskID"`
Path string `json:"path" validate:"required"`
}
type ImageBuild struct {
@@ -27,6 +28,7 @@ type ImageBuild struct {
Name string `json:"name" validate:"required"`
Dockerfile string `json:"dockerfile" validate:"required"`
Tags []string `json:"tags"`
Args []string `json:"args"`
}
type ImagePull struct {
@@ -48,6 +50,7 @@ type ImagePush struct {
}
type ImageSave struct {
TaskID string `json:"taskID"`
TagName string `json:"tagName" validate:"required"`
Path string `json:"path" validate:"required"`
Name string `json:"name" validate:"required"`
+13 -2
View File
@@ -4,7 +4,8 @@ import "time"
type MonitorSearch struct {
Param string `json:"param" validate:"required,oneof=all cpu memory load io network"`
Info string `json:"info"`
IO string `json:"io"`
Network string `json:"network"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
}
@@ -15,14 +16,24 @@ type MonitorData struct {
Value []interface{} `json:"value"`
}
type Process struct {
Name string `json:"name"`
Pid int32 `json:"pid"`
Percent float64 `json:"percent"`
Memory uint64 `json:"memory"`
Cmd string `json:"cmd"`
User string `json:"user"`
}
type MonitorSetting struct {
MonitorStatus string `json:"monitorStatus"`
MonitorStoreDays string `json:"monitorStoreDays"`
MonitorInterval string `json:"monitorInterval"`
DefaultNetwork string `json:"defaultNetwork"`
DefaultIO string `json:"defaultIO"`
}
type MonitorSettingUpdate struct {
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork"`
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork DefaultIO"`
Value string `json:"value"`
}
+7 -6
View File
@@ -73,12 +73,13 @@ type NginxUpstream struct {
}
type NginxUpstreamServer struct {
Server string `json:"server"`
Weight int `json:"weight"`
FailTimeout string `json:"failTimeout"`
MaxFails int `json:"maxFails"`
MaxConns int `json:"maxConns"`
Flag string `json:"flag"`
Server string `json:"server"`
Weight int `json:"weight"`
FailTimeout int `json:"failTimeout"`
FailTimeoutUnit string `json:"failTimeoutUnit"`
MaxFails int `json:"maxFails"`
MaxConns int `json:"maxConns"`
Flag string `json:"flag"`
}
var LBAlgorithms = map[string]struct{}{"ip_hash": {}, "least_conn": {}}
+5
View File
@@ -130,3 +130,8 @@ type NginxModuleUpdate struct {
type NginxOperateReq struct {
Operate string `json:"operate" validate:"required,oneof=enable disable"`
}
type NginxDefaultHTTPSUpdate struct {
Operate string `json:"operate" validate:"required,oneof=enable disable"`
SSLRejectHandshake bool `json:"sslRejectHandshake"`
}
+7
View File
@@ -32,6 +32,7 @@ type NodeConfig struct {
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
ExtraHosts []ExtraHost `json:"extraHosts"`
}
type Environment struct {
@@ -49,6 +50,11 @@ type ExposedPort struct {
HostIP string `json:"hostIP"`
}
type ExtraHost struct {
Hostname string `json:"hostname"`
IP string `json:"ip"`
}
type RuntimeDelete struct {
ID uint `json:"id"`
ForceDelete bool `json:"forceDelete"`
@@ -135,6 +141,7 @@ type PHPContainerConfig struct {
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
ExtraHosts []ExtraHost `json:"extraHosts"`
}
type RuntimeRemark struct {
+2
View File
@@ -14,6 +14,8 @@ type TensorRTLLMCreate struct {
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
}
+5
View File
@@ -109,6 +109,11 @@ type BatchWebsiteOp struct {
TaskID string `json:"taskID" validate:"required"`
}
type BatchWebsiteGroup struct {
IDs []uint `json:"ids" validate:"required"`
GroupID uint `json:"groupID" validate:"required"`
}
type WebsiteRedirectUpdate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
+7 -1
View File
@@ -128,6 +128,9 @@ type AppInstallDTO struct {
Favorite bool `json:"favorite"`
App AppDetail `json:"app"`
Container string `json:"container"`
IsEdit bool `json:"isEdit"`
LinkDB bool `json:"linkDB"`
ServiceName string `json:"serviceName"`
}
type AppInstallInfo struct {
@@ -139,6 +142,8 @@ type AppInstallInfo struct {
HttpPort int `json:"HttpPort"`
Container string `json:"container"`
ComposePath string `json:"composePath"`
AppKey string `json:"appKey"`
AppPorts []int `json:"appPorts"`
Env map[string]interface{} `json:"env"`
}
@@ -176,6 +181,7 @@ type AppParam struct {
}
type AppConfig struct {
Params []AppParam `json:"params"`
Params []AppParam `json:"params"`
RawCompose string `json:"rawCompose"`
request.AppContainerConfig
}
+1 -1
View File
@@ -24,7 +24,7 @@ type DiskBasicInfo struct {
type CompleteDiskInfo struct {
Disks []DiskInfo `json:"disks"`
UnpartitionedDisks []DiskBasicInfo `json:"unpartitionedDisks"`
SystemDisk *DiskInfo `json:"systemDisk"`
SystemDisks []DiskInfo `json:"systemDisks"`
TotalDisks int `json:"totalDisks"`
TotalCapacity int64 `json:"totalCapacity"`
}
+2 -1
View File
@@ -82,5 +82,6 @@ type NginxBuildConfig struct {
}
type NginxConfigRes struct {
Https bool `json:"https"`
Https bool `json:"https"`
SSLRejectHandshake bool `json:"sslRejectHandshake"`
}
+1
View File
@@ -28,6 +28,7 @@ type RuntimeDTO struct {
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
Environments []request.Environment `json:"environments"`
Volumes []request.Volume `json:"volumes"`
ExtraHosts []request.ExtraHost `json:"extraHosts"`
ContainerStatus string `json:"containerStatus"`
Container string `json:"container"`
Remark string `json:"remark"`
+1
View File
@@ -10,6 +10,7 @@ type SettingInfo struct {
NtpSite string `json:"ntpSite"`
DefaultNetwork string `json:"defaultNetwork"`
DefaultIO string `json:"defaultIO"`
LastCleanTime string `json:"lastCleanTime"`
LastCleanSize string `json:"lastCleanSize"`
LastCleanData string `json:"lastCleanData"`
+2
View File
@@ -43,6 +43,8 @@ type Cronjob struct {
EntryIDs string `json:"entryIDs"`
Records []JobRecords `json:"records"`
Secret string `json:"secret"`
Config string `json:"config"`
}
type JobRecords struct {
+1
View File
@@ -9,6 +9,7 @@ type Database struct {
From string `json:"from" gorm:"not null"`
Address string `json:"address" gorm:"not null"`
Port uint `json:"port" gorm:"not null"`
InitialDB string `json:"initialDB"`
Username string `json:"username"`
Password string `json:"password"`
+11 -15
View File
@@ -3,20 +3,16 @@ package model
type Firewall struct {
BaseModel
Type string `gorm:"not null" json:"type"`
Port string `gorm:"not null" json:"port"`
Protocol string `gorm:"not null" json:"protocol"`
Address string `gorm:"not null" json:"address"`
Type string `json:"type"`
Port string `json:"port"` // Deprecated
Address string `json:"address"` // Deprecated
Chain string `json:"chain"`
Protocol string `json:"protocol"`
SrcIP string `json:"srcIP"`
SrcPort string `json:"srcPort"`
DstIP string `json:"dstIP"`
DstPort string `json:"dstPort"`
Strategy string `gorm:"not null" json:"strategy"`
Description string `gorm:"not null" json:"description"`
}
type Forward struct {
BaseModel
Protocol string `gorm:"not null" json:"protocol"`
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"`
Description string `json:"description"`
}
+7 -3
View File
@@ -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 {
+5 -4
View File
@@ -6,8 +6,9 @@ type TensorRTLLM struct {
DockerCompose string `json:"dockerCompose"`
ContainerName string `json:"containerName"`
Message string `json:"message"`
//Port int `json:"port"`
Status string `json:"status"`
Env string `json:"env"`
TaskID string `json:"taskID"`
Status string `json:"status"`
Env string `json:"env"`
TaskID string `json:"taskID"`
ModelType string `json:"modelType"`
ModelSpeedup bool `json:"modelSpeedup"`
}
-9
View File
@@ -27,7 +27,6 @@ type IAppRepo interface {
GetFirst(opts ...DBOption) (model.App, error)
GetBy(opts ...DBOption) ([]model.App, error)
BatchCreate(ctx context.Context, apps []model.App) error
GetByKey(ctx context.Context, key string) (model.App, error)
Create(ctx context.Context, app *model.App) error
Save(ctx context.Context, app *model.App) error
BatchDelete(ctx context.Context, apps []model.App) error
@@ -144,14 +143,6 @@ func (a AppRepo) BatchCreate(ctx context.Context, apps []model.App) error {
return getTx(ctx).Omit(clause.Associations).Create(&apps).Error
}
func (a AppRepo) GetByKey(ctx context.Context, key string) (model.App, error) {
var app model.App
if err := getTx(ctx).Where("key = ?", key).First(&app).Error; err != nil {
return app, err
}
return app, nil
}
func (a AppRepo) Create(ctx context.Context, app *model.App) error {
return getTx(ctx).Omit(clause.Associations).Create(app).Error
}
+2 -1
View File
@@ -20,6 +20,7 @@ type IBackupRepo interface {
WithByPublic(isPublic bool) DBOption
ListRecord(opts ...DBOption) ([]model.BackupRecord, error)
GetRecord(opts ...DBOption) (*model.BackupRecord, error)
PageRecord(page, size int, opts ...DBOption) (int64, []model.BackupRecord, error)
CreateRecord(record *model.BackupRecord) error
DeleteRecord(ctx context.Context, opts ...DBOption) error
@@ -160,7 +161,7 @@ func (u *BackupRepo) WithByCronID(cronjobID uint) DBOption {
}
func (u *BackupRepo) GetRecord(opts ...DBOption) (*model.BackupRecord, error) {
var record *model.BackupRecord
record := &model.BackupRecord{}
db := global.DB.Model(&model.BackupRecord{})
for _, opt := range opts {
db = opt(db)
+1 -1
View File
@@ -173,7 +173,7 @@ func (u *CronjobRepo) AddFailedRecord(cronjobID uint, message string) {
var record model.JobRecords
record.StartTime = time.Now()
record.CronjobID = cronjobID
record.Status = constant.StatusFailed
record.Status = constant.StatusUnexecuted
record.Message = message
if err := global.DB.Create(&record).Error; err != nil {
global.LOG.Errorf("create record status failed, err: %v", err)
+40 -21
View File
@@ -4,16 +4,16 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"gorm.io/gorm"
)
type HostRepo struct{}
type IHostRepo interface {
GetFirewallRecord(opts ...DBOption) (model.Firewall, error)
ListFirewallRecord() ([]model.Firewall, error)
ListFirewallRecord(opts ...DBOption) ([]model.Firewall, error)
SaveFirewallRecord(firewall *model.Firewall) error
DeleteFirewallRecordByID(id uint) error
DeleteFirewallRecord(fType, port, protocol, address, strategy string) error
SyncCert(data []model.RootCert) error
GetCert(opts ...DBOption) (model.RootCert, error)
@@ -22,6 +22,8 @@ type IHostRepo interface {
SaveCert(cert *model.RootCert) error
UpdateCert(id uint, vars map[string]interface{}) error
DeleteCert(opts ...DBOption) error
WithByChain(chain string) DBOption
}
func NewIHostRepo() IHostRepo {
@@ -38,12 +40,16 @@ func (h *HostRepo) GetFirewallRecord(opts ...DBOption) (model.Firewall, error) {
return firewall, err
}
func (h *HostRepo) ListFirewallRecord() ([]model.Firewall, error) {
var datas []model.Firewall
if err := global.DB.Find(&datas).Error; err != nil {
return datas, nil
func (h *HostRepo) ListFirewallRecord(opts ...DBOption) ([]model.Firewall, error) {
var firewalls []model.Firewall
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return datas, nil
if err := global.DB.Find(&firewalls).Error; err != nil {
return firewalls, nil
}
return firewalls, nil
}
func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
@@ -51,16 +57,27 @@ func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
return global.DB.Save(firewall).Error
}
var data model.Firewall
if firewall.Type == "port" {
_ = global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", "port", firewall.Port, firewall.Protocol, firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
} else {
_ = global.DB.Where("type = ? AND address = ? AND strategy = ?", "address", firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
switch firewall.Type {
case "port":
_ = global.DB.Where("type = ? AND dst_port = ? AND protocol = ? AND src_ip = ? AND strategy = ?", "port",
firewall.DstPort,
firewall.Protocol,
firewall.SrcIP,
firewall.Strategy,
).First(&data).Error
case "ip":
_ = global.DB.Where("type = ? AND src_ip = ? AND strategy = ?", "address", firewall.SrcIP, firewall.Strategy).First(&data)
default:
_ = global.DB.Where("type = ? AND chain = ? AND src_port = ? AND dst_port = ? AND protocol = ? AND src_ip = ? AND dst_ip = ? AND strategy = ?",
firewall.Type,
firewall.Chain,
firewall.SrcPort,
firewall.DstPort,
firewall.Protocol,
firewall.SrcIP,
firewall.DstIP,
firewall.Strategy,
).First(&data).Error
}
return global.DB.Save(firewall).Error
}
@@ -69,10 +86,6 @@ func (h *HostRepo) DeleteFirewallRecordByID(id uint) error {
return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error
}
func (h *HostRepo) DeleteFirewallRecord(fType, port, protocol, address, strategy string) error {
return global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", fType, port, protocol, address, strategy).Delete(&model.Firewall{}).Error
}
func (u *HostRepo) GetCert(opts ...DBOption) (model.RootCert, error) {
var cert model.RootCert
db := global.DB
@@ -151,3 +164,9 @@ func (u *HostRepo) SyncCert(data []model.RootCert) error {
tx.Commit()
return nil
}
func (u *HostRepo) WithByChain(chain string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("chain = ?", chain)
}
}
+4 -6
View File
@@ -134,9 +134,8 @@ func (u *AIToolService) Close(name string) error {
if err != nil {
return err
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s ollama stop %s", containerName, name)
if err != nil {
return fmt.Errorf("handle ollama stop %s failed, stdout: %s, err: %v", name, stdout, err)
if err := cmd.RunDefaultBashCf("docker exec %s ollama stop %s", containerName, name); err != nil {
return fmt.Errorf("handle ollama stop %s failed, %v", name, err)
}
return nil
}
@@ -193,9 +192,8 @@ func (u *AIToolService) Delete(req dto.ForceDelete) error {
}
for _, item := range ollamaList {
if item.Status != constant.StatusDeleted {
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s ollama rm %s", containerName, item.Name)
if err != nil && !req.ForceDelete {
return fmt.Errorf("handle ollama rm %s failed, stdout: %s, err: %v", item.Name, stdout, err)
if err := cmd.RunDefaultBashCf("docker exec %s ollama rm %s", containerName, item.Name); err != nil && !req.ForceDelete {
return fmt.Errorf("handle ollama rm %s failed, %v", item.Name, err)
}
}
_ = aiRepo.Delete(repo.WithByID(item.ID))
+2 -1
View File
@@ -486,9 +486,10 @@ func (a AlertService) TestAlertConfig(req dto.AlertConfigTest) (bool, error) {
cfg := email.SMTPConfig{
Host: req.Host,
Port: req.Port,
Sender: req.Sender,
Username: username,
Password: req.Password,
From: fmt.Sprintf("%s <%s>", req.DisplayName, req.Sender),
From: fmt.Sprintf(`"%s" <%s>`, req.DisplayName, req.Sender),
Encryption: req.Encryption,
Recipient: req.Recipient,
}
+4 -3
View File
@@ -450,10 +450,11 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
}
index++
}
if app.Limit == 0 && appInstall.Name != serviceName && len(servicesMap) == 1 {
servicesMap[appInstall.Name] = servicesMap[serviceName]
newServiceName := strings.ToLower(appInstall.Name)
if app.Limit == 0 && newServiceName != serviceName && len(servicesMap) == 1 {
servicesMap[newServiceName] = servicesMap[serviceName]
delete(servicesMap, serviceName)
serviceName = appInstall.Name
serviceName = newServiceName
}
appInstall.ServiceName = serviceName
+21
View File
@@ -796,6 +796,9 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
res.RestartPolicy = getRestartPolicy(install.DockerCompose)
res.WebUI = install.WebUI
res.Type = install.App.Type
if rawCompose, err := getUpgradeCompose(install, detail); err == nil {
res.RawCompose = rawCompose
}
return &res, nil
}
@@ -940,8 +943,26 @@ func (a *AppInstallService) GetAppInstallInfo(installID uint) (*response.AppInst
HttpPort: appInstall.HttpPort,
Status: appInstall.Status,
Message: appInstall.Message,
AppKey: appInstall.App.Key,
Env: envMap,
ComposePath: appInstall.GetComposePath(),
}
for k, v := range envMap {
if strings.Contains(strings.ToUpper(k), "PANEL_APP_PORT") {
var port int
switch val := v.(type) {
case int:
port = val
case string:
port, err = strconv.Atoi(val)
if err != nil {
continue
}
default:
continue
}
res.AppPorts = append(res.AppPorts, port)
}
}
return res, nil
}
+156 -124
View File
@@ -15,7 +15,6 @@ import (
"path"
"path/filepath"
"reflect"
"regexp"
"strconv"
"strings"
"time"
@@ -40,6 +39,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/compose-spec/compose-go/v2/types"
@@ -134,6 +134,76 @@ var ToolKeys = map[string]uint{
"minio": 9001,
}
func CreateDB(ctx context.Context, app model.App, appInstall *model.AppInstall, params map[string]interface{}) error {
database := &model.Database{
AppInstallID: appInstall.ID,
Name: appInstall.Name,
Type: app.Key,
Version: appInstall.Version,
From: "local",
Address: appInstall.ServiceName,
Port: DatabaseKeys[app.Key],
}
detail, err := appDetailRepo.GetFirst(repo.WithByID(appInstall.AppDetailId))
if err != nil {
return err
}
formFields := &dto.AppForm{}
if err := json.Unmarshal([]byte(detail.Params), formFields); err != nil {
return err
}
for _, form := range formFields.FormFields {
if form.EnvKey == "PANEL_APP_PORT_HTTP" {
portFloat, ok := form.Default.(float64)
if ok {
database.Port = uint(int(portFloat))
}
break
}
}
switch app.Key {
case constant.AppMysql, constant.AppMariaDB, constant.AppPostgresql, constant.AppMongodb, constant.AppMysqlCluster, constant.AppPostgresqlCluster:
if password, ok := params["PANEL_DB_ROOT_PASSWORD"]; ok {
if password != "" {
database.Password = password.(string)
if app.Key == "mysql" || app.Key == "mariadb" || app.Key == constant.AppMysqlCluster {
database.Username = "root"
}
if rootUser, ok := params["PANEL_DB_ROOT_USER"]; ok {
database.Username = rootUser.(string)
}
authParam := dto.AuthParam{
RootPassword: password.(string),
RootUser: database.Username,
}
authByte, err := json.Marshal(authParam)
if err != nil {
return err
}
appInstall.Param = string(authByte)
}
}
case constant.AppRedis, constant.AppRedisCluster:
if password, ok := params["PANEL_REDIS_ROOT_PASSWORD"]; ok {
authParam := dto.RedisAuthParam{
RootPassword: "",
}
if password != "" {
authParam.RootPassword = password.(string)
database.Password = password.(string)
}
authByte, err := json.Marshal(authParam)
if err != nil {
return err
}
appInstall.Param = string(authByte)
}
}
return databaseRepo.Create(ctx, database)
}
func createLink(ctx context.Context, installTask *task.Task, app model.App, appInstall *model.AppInstall, params map[string]interface{}) error {
deleteAppLink := func(t *task.Task) {
del := dto.DelAppLink{
@@ -145,74 +215,7 @@ func createLink(ctx context.Context, installTask *task.Task, app model.App, appI
}
if DatabaseKeys[app.Key] > 0 {
handleDataBaseApp := func(task *task.Task) error {
database := &model.Database{
AppInstallID: appInstall.ID,
Name: appInstall.Name,
Type: app.Key,
Version: appInstall.Version,
From: "local",
Address: appInstall.ServiceName,
Port: DatabaseKeys[app.Key],
}
detail, err := appDetailRepo.GetFirst(repo.WithByID(appInstall.AppDetailId))
if err != nil {
return err
}
formFields := &dto.AppForm{}
if err := json.Unmarshal([]byte(detail.Params), formFields); err != nil {
return err
}
for _, form := range formFields.FormFields {
if form.EnvKey == "PANEL_APP_PORT_HTTP" {
portFloat, ok := form.Default.(float64)
if ok {
database.Port = uint(int(portFloat))
}
break
}
}
switch app.Key {
case constant.AppMysql, constant.AppMariaDB, constant.AppPostgresql, constant.AppMongodb, constant.AppMysqlCluster, constant.AppPostgresqlCluster:
if password, ok := params["PANEL_DB_ROOT_PASSWORD"]; ok {
if password != "" {
database.Password = password.(string)
if app.Key == "mysql" || app.Key == "mariadb" || app.Key == constant.AppMysqlCluster {
database.Username = "root"
}
if rootUser, ok := params["PANEL_DB_ROOT_USER"]; ok {
database.Username = rootUser.(string)
}
authParam := dto.AuthParam{
RootPassword: password.(string),
RootUser: database.Username,
}
authByte, err := json.Marshal(authParam)
if err != nil {
return err
}
appInstall.Param = string(authByte)
}
}
case constant.AppRedis, constant.AppRedisCluster:
if password, ok := params["PANEL_REDIS_ROOT_PASSWORD"]; ok {
authParam := dto.RedisAuthParam{
RootPassword: "",
}
if password != "" {
authParam.RootPassword = password.(string)
database.Password = password.(string)
}
authByte, err := json.Marshal(authParam)
if err != nil {
return err
}
appInstall.Param = string(authByte)
}
}
return databaseRepo.Create(ctx, database)
return CreateDB(ctx, app, appInstall, params)
}
installTask.AddSubTask(i18n.GetMsgByKey("HandleDatabaseApp"), handleDataBaseApp, deleteAppLink)
}
@@ -1082,11 +1085,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.RunWithStdoutBashC(scriptPath)
if err != nil {
if out != "" {
err = errors.New(out)
}
if err := cmdMgr.RunBashC(scriptPath); err != nil {
task.LogFailedWithErr(logStr, err)
return err
}
@@ -1413,6 +1412,8 @@ func handleLocalApp(appDir string) (app *model.App, err error) {
desc, _ := json.Marshal(appDefine.Description)
app.Description = string(desc)
app.Key = "local" + appDefine.Key
app.Architectures = strings.Join(appDefine.Architectures, ",")
app.GpuSupport = appDefine.GpuSupport
app.Resource = constant.AppResourceLocal
app.Status = constant.AppNormal
@@ -1566,41 +1567,41 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
Website: installed.App.Website,
Document: installed.App.Document,
},
Favorite: installed.Favorite,
Container: installed.ContainerName,
Favorite: installed.Favorite,
Container: installed.ContainerName,
ServiceName: strings.ToLower(installed.ServiceName),
}
if updated {
installDTO.DockerCompose = installed.DockerCompose
if !updated {
installDTO.LinkDB = hasLinkDB(installed.ID)
res = append(res, installDTO)
continue
}
app, err := appRepo.GetFirst(repo.WithByID(installed.AppId))
if err != nil {
return nil, err
if installed.Version == "latest" {
continue
}
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID))
installDTO.DockerCompose = installed.DockerCompose
installDTO.IsEdit = isEditCompose(installed)
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(installed.App.ID))
if err != nil {
return nil, err
}
var versions []string
for _, detail := range details {
ignores, _ := appIgnoreUpgradeRepo.List(runtimeRepo.WithDetailId(detail.ID), appIgnoreUpgradeRepo.WithScope("version"))
if len(ignores) > 0 || installed.Version == "latest" {
for _, appDetail := range details {
ignores, _ := appIgnoreUpgradeRepo.List(runtimeRepo.WithDetailId(appDetail.ID), appIgnoreUpgradeRepo.WithScope("version"))
if len(ignores) > 0 {
continue
}
if common.IsCrossVersion(installed.Version, detail.Version) && !app.CrossVersionUpdate {
if common.IsCrossVersion(installed.Version, appDetail.Version) && !installed.App.CrossVersionUpdate {
continue
}
versions = append(versions, detail.Version)
versions = append(versions, appDetail.Version)
}
versions = common.GetSortedVersions(versions)
if len(versions) == 0 {
if !updated {
installDTO.CanUpdate = false
res = append(res, installDTO)
}
continue
}
versions = common.GetSortedVersions(versions)
lastVersion := versions[0]
if app.Key == constant.AppMysql || app.Key == constant.AppMysqlCluster {
if installed.App.Key == constant.AppMysql || installed.App.Key == constant.AppMysqlCluster {
for _, version := range versions {
majorVersion := getMajorVersion(installed.Version)
if !strings.HasPrefix(version, majorVersion) {
@@ -1612,15 +1613,11 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
}
}
if common.IsCrossVersion(installed.Version, lastVersion) {
installDTO.CanUpdate = app.CrossVersionUpdate
installDTO.CanUpdate = installed.App.CrossVersionUpdate
} else {
installDTO.CanUpdate = common.CompareVersion(lastVersion, installed.Version)
}
if updated {
if installDTO.CanUpdate {
res = append(res, installDTO)
}
} else {
if installDTO.CanUpdate {
res = append(res, installDTO)
}
}
@@ -1824,8 +1821,7 @@ func getAppCommonConfig(envs map[string]interface{}) request.AppContainerConfig
config.CpuQuota = 0
}
if memLimit, ok := envs[constant.MemoryLimit]; ok {
re := regexp.MustCompile(`(\d+)([A-Za-z]+)`)
matches := re.FindStringSubmatch(memLimit.(string))
matches := re.GetRegex(re.NumberAlphaPattern).FindStringSubmatch(memLimit.(string))
if len(matches) == 3 {
num, err := strconv.ParseFloat(matches[1], 64)
if err == nil {
@@ -1999,7 +1995,7 @@ func handleOpenrestyFile(appInstall *model.AppInstall) error {
break
}
}
if err := handleSSLConfig(appInstall, hasDefaultWebsite); err != nil {
if err := handleSSLConfig(appInstall, hasDefaultWebsite, true); err != nil {
return err
}
if len(websites) == 0 {
@@ -2028,34 +2024,37 @@ func handleDefaultServer(appInstall *model.AppInstall) error {
return nil
}
func handleSSLConfig(appInstall *model.AppInstall, hasDefaultWebsite bool) error {
func handleSSLConfig(appInstall *model.AppInstall, hasDefaultWebsite bool, sslRejectHandshake bool) error {
sslDir := path.Join(appInstall.GetPath(), "conf", "ssl")
fileOp := files.NewFileOp()
if !fileOp.Stat(sslDir) {
return errors.New("ssl dir not found")
}
ca, _ := websiteCARepo.GetFirst(repo.WithByName("1Panel"))
if ca.ID == 0 {
global.LOG.Errorf("create openresty default ssl failed ca not found")
return nil
hasDefaultSSL := fileOp.Stat(path.Join(sslDir, "fullchain.pem")) && fileOp.Stat(path.Join(sslDir, "privkey.pem")) && fileOp.Stat(path.Join(sslDir, "root_ssl.conf"))
if !hasDefaultSSL {
ca, _ := websiteCARepo.GetFirst(repo.WithByName("1Panel"))
if ca.ID == 0 {
global.LOG.Errorf("create openresty default ssl failed ca not found")
return nil
}
caService := NewIWebsiteCAService()
caRequest := request.WebsiteCAObtain{
ID: ca.ID,
Domains: "localhost",
KeyType: "4096",
Time: 99,
Unit: "year",
Dir: sslDir,
PushDir: true,
}
websiteSSL, err := caService.ObtainSSL(caRequest)
if err != nil {
return err
}
defer func() {
_ = NewIWebsiteSSLService().Delete([]uint{websiteSSL.ID})
}()
}
caService := NewIWebsiteCAService()
caRequest := request.WebsiteCAObtain{
ID: ca.ID,
Domains: "localhost",
KeyType: "4096",
Time: 99,
Unit: "year",
Dir: sslDir,
PushDir: true,
}
websiteSSL, err := caService.ObtainSSL(caRequest)
if err != nil {
return err
}
defer func() {
_ = NewIWebsiteSSLService().Delete([]uint{websiteSSL.ID})
}()
defaultConfigPath := path.Join(appInstall.GetPath(), "conf", "default", "00.default.conf")
content, err := os.ReadFile(defaultConfigPath)
if err != nil {
@@ -2070,6 +2069,11 @@ func handleSSLConfig(appInstall *model.AppInstall, hasDefaultWebsite bool) error
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 sslRejectHandshake {
defaultServer.UpdateDirective("ssl_reject_handshake", []string{"on"})
} else {
defaultServer.RemoveDirective("ssl_reject_handshake", []string{})
}
if err = nginx.WriteConfig(defaultConfig, nginx.IndentedStyle); err != nil {
return err
}
@@ -2131,3 +2135,31 @@ func needsUpdate(localTag *model.Tag, remoteTag dto.Tag, translations string) bo
localTag.Sort != remoteTag.Sort ||
localTag.Translations != translations
}
func hasLinkDB(installID uint) bool {
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(installID))
hasDB := false
if len(resources) > 0 {
for _, resource := range resources {
if resource.Key == constant.AppPostgres || resource.Key == constant.AppMysql ||
resource.Key == constant.AppMariaDB || resource.Key == constant.AppMysqlCluster ||
resource.Key == constant.AppPostgresql || resource.Key == constant.AppPostgresqlCluster {
hasDB = true
break
}
}
}
return hasDB
}
func isEditCompose(installed model.AppInstall) bool {
detail, _ := appDetailRepo.GetFirst(repo.WithByID(installed.AppDetailId))
rawCompose, err := getUpgradeCompose(installed, detail)
if rawCompose == "" || err != nil {
return false
}
if rawCompose != installed.DockerCompose {
return true
}
return false
}
+3 -3
View File
@@ -102,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, 0, 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))
@@ -113,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, 0, 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))
@@ -260,7 +260,7 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
Name: newDB.MysqlName,
DetailName: newDB.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
}, parentTask, true, ""); err != nil {
}, parentTask, true); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
+24 -9
View File
@@ -48,7 +48,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
}
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handleMysqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil {
if err := handleMysqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID, req.Secret); err != nil {
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return err
}
@@ -56,7 +56,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
}
func (u *BackupService) MysqlRecover(req dto.CommonRecover) error {
return handleMysqlRecover(req, nil, false, req.TaskID)
return handleMysqlRecover(req, nil, false)
}
func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
@@ -66,13 +66,13 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
}
req.File = recoveFile
if err := handleMysqlRecover(req, nil, false, req.TaskID); err != nil {
if err := handleMysqlRecover(req, nil, false); err != nil {
return err
}
return nil
}
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error {
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID, secret string) error {
var (
err error
backupTask *task.Task
@@ -90,7 +90,7 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint,
}
}
itemHandler := func() error { return doMysqlBackup(db, targetDir, fileName) }
itemHandler := func() error { return doMysqlBackup(db, targetDir, fileName, secret) }
if parentTask != nil {
return itemHandler()
}
@@ -105,7 +105,7 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint,
return nil
}
func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool, taskID string) error {
func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool) error {
var (
err error
itemTask *task.Task
@@ -117,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.TaskScopeBackup, taskID, dbInfo.ID)
itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeBackup, req.TaskID, dbInfo.ID)
if err != nil {
return err
}
@@ -170,6 +170,15 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
}
}()
}
if len(req.Secret) != 0 {
err = files.OpensslDecrypt(req.File, req.Secret)
if err != nil {
return err
}
req.File = path.Join(path.Dir(req.File), "tmp_"+path.Base(req.File))
defer os.Remove(req.File)
t.LogWithStatus(i18n.GetMsgByKey("Decrypt"), err)
}
if err := cli.Recover(client.RecoverInfo{
Name: req.DetailName,
Type: req.Type,
@@ -194,7 +203,7 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
return nil
}
func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
func doMysqlBackup(db DatabaseHelper, targetDir, fileName, secret string) error {
dbInfo, err := mysqlRepo.Get(repo.WithByName(db.Name), mysqlRepo.WithByMysqlName(db.Database))
if err != nil {
return err
@@ -211,7 +220,13 @@ func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
TargetDir: targetDir,
FileName: fileName,
}
return cli.Backup(backupInfo)
if err := cli.Backup(backupInfo); err != nil {
return err
}
if len(secret) != 0 {
return files.OpensslEncrypt(path.Join(targetDir, fileName), secret)
}
return nil
}
func loadSqlFile(file string) (string, error) {
+26 -14
View File
@@ -6,21 +6,18 @@ import (
"path"
"time"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/utils/common"
pgclient "github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
"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/common"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
pgclient "github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
)
func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
@@ -46,7 +43,7 @@ func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
}
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handlePostgresqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil {
if err := handlePostgresqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID, req.Secret); err != nil {
return err
}
return nil
@@ -71,7 +68,7 @@ func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
return nil
}
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error {
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID, secret string) error {
var (
err error
backupTask *task.Task
@@ -85,7 +82,7 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID u
}
}
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName) }
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret) }
if parentTask != nil {
return itemHandler()
}
@@ -160,6 +157,15 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
}
}()
}
if len(req.Secret) != 0 {
err = files.OpensslDecrypt(req.File, req.Secret)
if err != nil {
return err
}
req.File = path.Join(path.Dir(req.File), "tmp_"+path.Base(req.File))
defer os.Remove(req.File)
t.LogWithStatus(i18n.GetMsgByKey("Decrypt"), err)
}
if err := cli.Recover(client.RecoverInfo{
Name: req.DetailName,
SourceFile: req.File,
@@ -183,7 +189,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
return nil
}
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error {
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string) error {
cli, err := LoadPostgresqlClientByFrom(db.Database)
if err != nil {
return err
@@ -196,5 +202,11 @@ func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error {
Timeout: 300,
}
return cli.Backup(backupInfo)
if err := cli.Backup(backupInfo); err != nil {
return err
}
if len(secret) != 0 {
return files.OpensslEncrypt(path.Join(targetDir, fileName), secret)
}
return nil
}
+6 -10
View File
@@ -19,7 +19,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/pkg/errors"
)
func (u *BackupService) RedisBackup(req dto.CommonBackup) error {
@@ -98,9 +97,8 @@ func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, recordID
}
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec %s redis-cli -a %s --no-auth-warning save", redisInfo.ContainerName, redisInfo.Password)
if err != nil {
return errors.New(string(stdout))
if err := cmd.RunDefaultBashCf("docker exec %s redis-cli -a %s --no-auth-warning save", redisInfo.ContainerName, redisInfo.Password); err != nil {
return err
}
if strings.HasSuffix(fileName, ".tar.gz") {
@@ -111,16 +109,14 @@ func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, recordID
return nil
}
if strings.HasSuffix(fileName, ".aof") {
stdout1, err := cmd.RunDefaultWithStdoutBashCf("docker cp %s:/data/appendonly.aof %s/%s", redisInfo.ContainerName, backupDir, fileName)
if err != nil {
return errors.New(stdout1)
if err := cmd.RunDefaultBashCf("docker cp %s:/data/appendonly.aof %s/%s", redisInfo.ContainerName, backupDir, fileName); err != nil {
return err
}
return nil
}
stdout1, err1 := cmd.RunDefaultWithStdoutBashCf("docker cp %s:/data/dump.rdb %s/%s", redisInfo.ContainerName, backupDir, fileName)
if err1 != nil {
return errors.New(stdout1)
if err := cmd.RunDefaultBashCf("docker cp %s:/data/dump.rdb %s/%s", redisInfo.ContainerName, backupDir, fileName); err != nil {
return err
}
return nil
}
+3 -5
View File
@@ -16,7 +16,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/pkg/errors"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
@@ -179,9 +178,8 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
if err = fileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), GetOpenrestyDir(SitesRootDir), ""); err != nil {
return err
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName)
if err != nil {
return errors.New(stdout)
if err := cmd.RunDefaultBashCf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName); err != nil {
return err
}
oldWebsite.ID = website.ID
if err := websiteRepo.SaveWithoutCtx(&oldWebsite); err != nil {
@@ -365,7 +363,7 @@ func recoverWebsiteDatabase(t *task.Task, dbID uint, dbType, tmpPath, websiteKey
Name: db.MysqlName,
DetailName: db.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, websiteKey),
}, t, true, ""); err != nil {
}, t, true); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
+76 -90
View File
@@ -21,14 +21,15 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/clam"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/systemctl"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/jinzhu/copier"
"github.com/robfig/cron/v3"
)
type ClamService struct {
serviceName string
serviceName string
freshClamService string
}
type IClamService interface {
@@ -56,23 +57,31 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
var baseInfo dto.ClamBaseInfo
baseInfo.Version = "-"
baseInfo.FreshVersion = "-"
exist1, _ := systemctl.IsExist(constant.ClamServiceNameCentOs)
if exist1 {
c.serviceName = constant.ClamServiceNameCentOs
baseInfo.IsExist = true
baseInfo.IsActive, _ = systemctl.IsActive(constant.ClamServiceNameCentOs)
clamSvc, err := controller.LoadServiceName("clam")
if err != nil {
baseInfo.IsExist = false
return baseInfo, nil
}
exist2, _ := systemctl.IsExist(constant.ClamServiceNameUbuntu)
if exist2 {
c.serviceName = constant.ClamServiceNameUbuntu
c.serviceName = clamSvc
exist, _ := controller.CheckExist(clamSvc)
if exist {
baseInfo.IsExist = true
baseInfo.IsActive, _ = systemctl.IsActive(constant.ClamServiceNameUbuntu)
baseInfo.IsActive, _ = controller.CheckActive(clamSvc)
}
freshExist, _ := systemctl.IsExist(constant.FreshClamService)
freshSvc, err := controller.LoadServiceName("freshclam")
if err != nil {
baseInfo.FreshIsExist = false
return baseInfo, nil
}
c.freshClamService = freshSvc
freshExist, _ := controller.CheckExist(freshSvc)
if freshExist {
baseInfo.FreshIsExist = true
baseInfo.FreshIsActive, _ = systemctl.IsActive(constant.FreshClamService)
baseInfo.FreshIsActive, _ = controller.CheckActive(freshSvc)
}
if !cmd.Which("clamdscan") {
baseInfo.IsActive = false
}
@@ -87,7 +96,7 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
}
}
} else {
_ = clam.CheckClamIsActive(false, clamRepo)
_ = clam.StopAllClamJob(false, clamRepo)
}
if baseInfo.FreshIsActive {
version, err := cmd.RunDefaultWithStdoutBashC("freshclam --version")
@@ -105,15 +114,13 @@ func (c *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
func (c *ClamService) Operate(operate string) error {
switch operate {
case "start", "restart", "stop":
stdout, err := cmd.RunDefaultWithStdoutBashCf("systemctl %s %s", operate, c.serviceName)
if err != nil {
return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, stdout)
if err := controller.Handle(operate, c.serviceName); err != nil {
return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, err)
}
return nil
case "fresh-start", "fresh-restart", "fresh-stop":
stdout, err := cmd.RunDefaultWithStdoutBashCf("systemctl %s %s", strings.TrimPrefix(operate, "fresh-"), constant.FreshClamService)
if err != nil {
return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, stdout)
if err := controller.Handle(strings.TrimPrefix(operate, "fresh-"), c.freshClamService); err != nil {
return fmt.Errorf("%s the %s failed, err: %s", operate, c.serviceName, err)
}
return nil
default:
@@ -306,7 +313,7 @@ func (c *ClamService) Delete(req dto.ClamDelete) error {
}
func (c *ClamService) HandleOnce(id uint) error {
if active := clam.CheckClamIsActive(true, clamRepo); !active {
if active := clam.StopAllClamJob(true, clamRepo); !active {
return buserr.New("ErrClamdscanNotFound")
}
clamItem, _ := clamRepo.Get(repo.WithByID(id))
@@ -379,37 +386,13 @@ func (c *ClamService) LoadFile(req dto.ClamFileReq) (string, error) {
filePath := ""
switch req.Name {
case "clamd":
if c.serviceName == constant.ClamServiceNameUbuntu {
filePath = "/etc/clamav/clamd.conf"
} else {
filePath = "/etc/clamd.d/scan.conf"
}
filePath = c.loadConfigPath("clamd")
case "clamd-log":
filePath = c.loadLogPath("clamd-log")
if len(filePath) != 0 {
break
}
if c.serviceName == constant.ClamServiceNameUbuntu {
filePath = "/var/log/clamav/clamav.log"
} else {
filePath = "/var/log/clamd.scan"
}
case "freshclam":
if c.serviceName == constant.ClamServiceNameUbuntu {
filePath = "/etc/clamav/freshclam.conf"
} else {
filePath = "/etc/freshclam.conf"
}
filePath = c.loadConfigPath("freshclam")
case "freshclam-log":
filePath = c.loadLogPath("freshclam-log")
if len(filePath) != 0 {
break
}
if c.serviceName == constant.ClamServiceNameUbuntu {
filePath = "/var/log/clamav/freshclam.log"
} else {
filePath = "/var/log/freshclam.log"
}
default:
return "", fmt.Errorf("not support such type")
}
@@ -432,23 +415,11 @@ func (c *ClamService) LoadFile(req dto.ClamFileReq) (string, error) {
func (c *ClamService) UpdateFile(req dto.UpdateByNameAndFile) error {
filePath := ""
service := ""
switch req.Name {
case "clamd":
if c.serviceName == constant.ClamServiceNameUbuntu {
service = constant.ClamServiceNameUbuntu
filePath = "/etc/clamav/clamd.conf"
} else {
service = constant.ClamServiceNameCentOs
filePath = "/etc/clamd.d/scan.conf"
}
filePath = c.loadConfigPath("clamd")
case "freshclam":
if c.serviceName == constant.ClamServiceNameUbuntu {
filePath = "/etc/clamav/freshclam.conf"
} else {
filePath = "/etc/freshclam.conf"
}
service = "clamav-freshclam.service"
filePath = c.loadConfigPath("freshclam")
default:
return fmt.Errorf("not support such type")
}
@@ -461,50 +432,65 @@ func (c *ClamService) UpdateFile(req dto.UpdateByNameAndFile) error {
_, _ = write.WriteString(req.File)
write.Flush()
_ = systemctl.Restart(service)
_ = controller.HandleRestart(c.serviceName)
return nil
}
func (c *ClamService) loadLogPath(name string) string {
confPath := ""
if name == "clamd-log" {
if c.serviceName == constant.ClamServiceNameUbuntu {
confPath = "/etc/clamav/clamd.conf"
} else {
confPath = "/etc/clamd.d/scan.conf"
}
} else {
if c.serviceName == constant.ClamServiceNameUbuntu {
confPath = "/etc/clamav/freshclam.conf"
} else {
confPath = "/etc/freshclam.conf"
}
}
if _, err := os.Stat(confPath); err != nil {
return ""
configKey := "clamd"
searchPrefix := "LogFile "
if name != "clamd-log" {
configKey = "freshclam"
searchPrefix = "UpdateLogFile "
}
confPath := c.loadConfigPath(configKey)
content, err := os.ReadFile(confPath)
if err != nil {
global.LOG.Debugf("read config of %s failed, err: %v", configKey, err)
return ""
}
lines := strings.Split(string(content), "\n")
if name == "clamd-log" {
for _, line := range lines {
if strings.HasPrefix(line, "LogFile ") {
return strings.Trim(strings.ReplaceAll(line, "LogFile ", ""), " ")
}
}
} else {
for _, line := range lines {
if strings.HasPrefix(line, "UpdateLogFile ") {
return strings.Trim(strings.ReplaceAll(line, "UpdateLogFile ", ""), " ")
}
for _, line := range lines {
if strings.HasPrefix(line, searchPrefix) {
return strings.Trim(strings.ReplaceAll(line, searchPrefix, ""), " ")
}
}
if configKey == "clamd" {
if _, err := os.Stat("/var/log/clamav/clamav.log"); err == nil {
return "/var/log/clamav/clamav.log"
}
if _, err := os.Stat("/var/log/clamd.scan"); err == nil {
return "/var/log/clamd.scan"
}
}
if configKey == "freshclam" {
if _, err := os.Stat("/var/log/clamav/freshclam.log"); err == nil {
return "/var/log/clamav/freshclam.log"
}
if _, err := os.Stat("/var/log/freshclam.log"); err == nil {
return "/var/log/freshclam.log"
}
}
return ""
}
func (c *ClamService) loadConfigPath(confType string) string {
switch confType {
case "clamd":
if _, err := os.Stat("/etc/clamav/clamd.conf"); err == nil {
return "/etc/clamav/clamd.conf"
}
return "/etc/clamd.d/scan.conf"
case "freshclam":
if _, err := os.Stat("/etc/clamav/freshclam.conf"); err == nil {
return "/etc/clamav/freshclam.conf"
}
return "/etc/freshclam.conf"
default:
return ""
}
}
func handleAlert(infectedFiles, clamName string, clamId uint) {
itemInfected, _ := strconv.Atoi(strings.TrimSpace(infectedFiles))
if itemInfected < 0 {
+19 -1
View File
@@ -2,6 +2,7 @@ package service
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/buserr"
"github.com/jinzhu/copier"
@@ -12,8 +13,9 @@ type ComposeTemplateService struct{}
type IComposeTemplateService interface {
List() ([]dto.ComposeTemplateInfo, error)
SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error)
Create(composeDto dto.ComposeTemplateCreate) error
Create(req dto.ComposeTemplateCreate) error
Update(id uint, upMap map[string]interface{}) error
Batch(req dto.ComposeTemplateBatch) error
Delete(ids []uint) error
}
@@ -64,6 +66,22 @@ func (u *ComposeTemplateService) Create(composeDto dto.ComposeTemplateCreate) er
return nil
}
func (u *ComposeTemplateService) Batch(req dto.ComposeTemplateBatch) error {
for _, item := range req.Templates {
template, _ := composeRepo.Get(repo.WithByName(item.Name))
if template.ID == 0 {
if err := composeRepo.Create(&model.ComposeTemplate{Name: item.Name, Content: item.Content, Description: item.Description}); err != nil {
return err
}
} else {
if err := composeRepo.Update(template.ID, map[string]interface{}{"content": item.Content, "description": item.Description}); err != nil {
return err
}
}
}
return nil
}
func (u *ComposeTemplateService) Delete(ids []uint) error {
if len(ids) == 1 {
compose, _ := composeRepo.Get(repo.WithByID(ids[0]))
+77 -32
View File
@@ -12,7 +12,6 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
@@ -34,6 +33,8 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
@@ -105,7 +106,8 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
}
defer client.Close()
options := container.ListOptions{
All: true,
All: true,
Size: true,
}
if len(req.Filters) != 0 {
options.Filters = filters.NewArgs()
@@ -199,6 +201,8 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
Ports: exposePorts,
IsFromApp: IsFromApp,
IsFromCompose: IsFromCompose,
SizeRw: item.SizeRw,
SizeRootFs: item.SizeRootFs,
}
install, _ := appInstallRepo.GetFirst(appInstallRepo.WithContainerName(info.Name))
if install.ID > 0 {
@@ -282,11 +286,35 @@ func (u *ContainerService) LoadStatus() (dto.ContainerStatus, error) {
}
defer client.Close()
c := context.Background()
images, _ := client.ImageList(c, image.ListOptions{})
for _, image := range images {
data.ImageSize += uint64(image.Size)
usage, err := client.DiskUsage(c, types.DiskUsageOptions{})
if err != nil {
return data, err
}
data.ImageCount = len(usage.Images)
data.VolumeCount = len(usage.Volumes)
for _, item := range usage.Images {
data.ImageUsage += item.Size
if item.Containers < 1 {
data.ImageReclaimable += item.Size
}
}
for _, item := range usage.Containers {
data.ContainerUsage += item.SizeRw
if item.State != "running" {
data.ContainerReclaimable += item.SizeRw
}
}
for _, item := range usage.Volumes {
data.VolumeUsage += item.UsageData.Size
if item.UsageData.RefCount == 0 {
data.VolumeReclaimable += item.UsageData.Size
}
}
for _, item := range usage.BuildCache {
data.BuildCacheUsage += item.Size
}
data.ImageCount = len(images)
repo, _ := imageRepoRepo.List()
data.RepoCount = len(repo)
templates, _ := composeRepo.List()
@@ -296,12 +324,8 @@ func (u *ContainerService) LoadStatus() (dto.ContainerStatus, error) {
volumes, _ := client.VolumeList(c, volume.ListOptions{})
data.VolumeCount = len(volumes.Volumes)
data.ComposeCount = loadComposeCount(client)
containers, err := client.ContainerList(c, container.ListOptions{All: true})
if err != nil {
return data, err
}
data.All = uint(len(containers))
for _, item := range containers {
data.ContainerCount = len(usage.Containers)
for _, item := range usage.Containers {
switch item.State {
case "created":
data.Created++
@@ -319,7 +343,6 @@ func (u *ContainerService) LoadStatus() (dto.ContainerStatus, error) {
data.Removing++
}
}
data.ContainerCount = int(data.All)
return data, nil
}
func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error) {
@@ -478,6 +501,7 @@ func (u *ContainerService) Prune(req dto.ContainerPrune) error {
pruneFilters.Add("until", "24h")
}
}
taskItem.Log(i18n.GetMsgByKey("PruneStart"))
DeletedNumber := 0
SpaceReclaimed := 0
switch req.PruneType {
@@ -895,25 +919,36 @@ func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error
return err
}
defer client.Close()
for _, item := range req.Names {
global.LOG.Infof("start container %s operation %s", item, req.Operation)
switch req.Operation {
case constant.ContainerOpStart:
err = client.ContainerStart(ctx, item, container.StartOptions{})
case constant.ContainerOpStop:
err = client.ContainerStop(ctx, item, container.StopOptions{})
case constant.ContainerOpRestart:
err = client.ContainerRestart(ctx, item, container.StopOptions{})
case constant.ContainerOpKill:
err = client.ContainerKill(ctx, item, "SIGKILL")
case constant.ContainerOpPause:
err = client.ContainerPause(ctx, item)
case constant.ContainerOpUnpause:
err = client.ContainerUnpause(ctx, item)
case constant.ContainerOpRemove:
err = client.ContainerRemove(ctx, item, container.RemoveOptions{RemoveVolumes: true, Force: true})
}
taskItem, err := task.NewTaskWithOps(strings.Join(req.Names, " "), req.Operation, task.TaskScopeContainer, req.TaskID, 1)
if err != nil {
return fmt.Errorf("new task for container commit failed, err: %v", err)
}
for _, item := range req.Names {
taskItem.AddSubTask(item, func(t *task.Task) error {
switch req.Operation {
case constant.ContainerOpStart:
err = client.ContainerStart(ctx, item, container.StartOptions{})
case constant.ContainerOpStop:
err = client.ContainerStop(ctx, item, container.StopOptions{})
case constant.ContainerOpRestart:
err = client.ContainerRestart(ctx, item, container.StopOptions{})
case constant.ContainerOpKill:
err = client.ContainerKill(ctx, item, "SIGKILL")
case constant.ContainerOpPause:
err = client.ContainerPause(ctx, item)
case constant.ContainerOpUnpause:
err = client.ContainerUnpause(ctx, item)
case constant.ContainerOpRemove:
err = client.ContainerRemove(ctx, item, container.RemoveOptions{RemoveVolumes: true, Force: true})
}
return err
}, nil)
}
go func() {
_ = taskItem.Execute()
}()
return err
}
@@ -1132,7 +1167,7 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
errCh := make(chan error)
go func() {
scanner := bufio.NewScanner(stdout)
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;?]*[A-Za-z]|\x1b=|\x1b>`)
var ansiRegex = re.GetRegex(re.AnsiEscapePattern)
for scanner.Scan() {
line := scanner.Text()
cleanLine := ansiRegex.ReplaceAllString(line, "")
@@ -1222,6 +1257,16 @@ func stringsToMap(list []string) map[string]string {
}
return labelMap
}
func stringsToMap2(list []string) map[string]*string {
var labelMap = make(map[string]*string)
for _, label := range list {
if strings.Contains(label, "=") {
sps := strings.SplitN(label, "=", 2)
labelMap[sps[0]] = &sps[1]
}
}
return labelMap
}
func calculateCPUPercentUnix(stats *container.StatsResponse) float64 {
cpuPercent := 0.0
+7
View File
@@ -108,6 +108,9 @@ func (u *CronjobService) LoadInfo(req dto.OperateByID) (*dto.CronjobOperate, err
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
if cronjob.Type == "cleanLog" {
_ = json.Unmarshal([]byte(cronjob.Config), &item.CleanLogConfig)
}
return &item, err
}
@@ -577,6 +580,10 @@ func (u *CronjobService) Create(req dto.CronjobOperate) error {
}
cronjob.Spec = spec
cronjob.EntryIDs = entryIDs
if req.Type == "cleanLog" {
config, _ := json.Marshal(req.CleanLogConfig)
cronjob.Config = string(config)
}
if err := cronjobRepo.Create(&cronjob); err != nil {
return err
}
+2 -2
View File
@@ -167,7 +167,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
backupDir := path.Join(global.Dir.LocalBackupDir, fmt.Sprintf("tmp/database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name))
record.FileName = simplifiedFileName(fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)))
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" || cronjob.DBType == "mysql-cluster" {
if err := doMysqlBackup(dbInfo, backupDir, record.FileName); err != nil {
if err := doMysqlBackup(dbInfo, backupDir, record.FileName, cronjob.Secret); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
@@ -178,7 +178,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
}
}
} else {
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName); err != nil {
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
+126 -1
View File
@@ -1,11 +1,16 @@
package service
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path"
pathUtils "path"
"path/filepath"
"strings"
"time"
@@ -127,6 +132,10 @@ func (u *CronjobService) loadTask(cronjob *model.Cronjob, record *model.JobRecor
err = u.handleDirectory(*cronjob, record.StartTime, taskItem)
case "log":
err = u.handleSystemLog(*cronjob, record.StartTime, taskItem)
case "syncIpGroup":
u.handleSyncIpGroup(*cronjob, taskItem)
case "cleanLog":
u.handleCleanLog(*cronjob, taskItem)
}
return err
}
@@ -210,6 +219,116 @@ func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskItem *task.Tas
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
}
func (u *CronjobService) handleCleanLog(cronjob model.Cronjob, taskItem *task.Task) {
taskItem.AddSubTaskWithOps(i18n.GetWithName("CleanLog", cronjob.Name), func(t *task.Task) error {
config := GetCleanLogConfig(cronjob)
for _, scope := range config.Scopes {
switch scope {
case "website":
websites, _ := websiteRepo.List()
for _, website := range websites {
curStr := i18n.GetWithName("CleanLogByName", website.PrimaryDomain)
t.LogStart(curStr)
accessLogPath := GetSitePath(website, SiteAccessLog)
if err := os.Truncate(accessLogPath, 0); err != nil {
t.LogFailedWithErr(curStr, err)
continue
}
errLogPath := GetSitePath(website, SiteErrorLog)
if err := os.Truncate(errLogPath, 0); err != nil {
t.LogFailedWithErr(curStr, err)
continue
}
t.LogSuccess(curStr)
}
appInstall, _ := getAppInstallByKey(constant.AppOpenresty)
if appInstall.ID > 0 {
curStr := i18n.GetWithName("CleanLogByName", "OpenResty")
t.LogStart(curStr)
accessLogPath := path.Join(appInstall.GetPath(), "log", "access.log")
if err := os.Truncate(accessLogPath, 0); err != nil {
t.LogFailedWithErr(curStr, err)
}
errLogPath := path.Join(appInstall.GetPath(), "log", "error.log")
if err := os.Truncate(errLogPath, 0); err != nil {
t.LogFailedWithErr(curStr, err)
}
t.LogSuccess(curStr)
}
}
}
return nil
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
}
func (u *CronjobService) handleSyncIpGroup(cronjob model.Cronjob, taskItem *task.Task) {
taskItem.AddSubTaskWithOps(i18n.GetWithName("SyncIpGroup", cronjob.Name), func(t *task.Task) error {
appInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
ipGroupDir := path.Join(appInstall.GetPath(), "1pwaf", "data", "rules", "ip_group")
urlDir := path.Join(ipGroupDir, "ip_group_url")
urlsFiles, err := os.ReadDir(urlDir)
if err != nil {
return err
}
for _, file := range urlsFiles {
if file.IsDir() || !strings.HasSuffix(file.Name(), "_url") {
continue
}
urlFilePath := filepath.Join(urlDir, file.Name())
urlContent, err := os.ReadFile(urlFilePath)
if err != nil {
continue
}
remoteURL := strings.TrimSpace(string(urlContent))
if remoteURL == "" {
continue
}
resp, err := http.Get(remoteURL)
if err != nil {
continue
}
ipGroupFile := strings.TrimSuffix(file.Name(), "_url")
ipGroupPath := filepath.Join(ipGroupDir, ipGroupFile)
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
taskItem.Logf("get remote ip group %s failed %s status code %d", ipGroupFile, remoteURL, resp.StatusCode)
continue
}
outFile, err := os.OpenFile(ipGroupPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
resp.Body.Close()
taskItem.Logf("sync %s failed %v", ipGroupFile, err)
continue
}
writer := bufio.NewWriter(outFile)
_, err = io.Copy(writer, resp.Body)
if err != nil {
outFile.Close()
resp.Body.Close()
taskItem.Logf("sync %s failed , write file failed %v", ipGroupFile, err)
continue
}
writer.Flush()
outFile.Close()
resp.Body.Close()
taskItem.LogSuccess(i18n.Get("TaskSync") + " " + ipGroupFile)
}
if err := opNginx(appInstall.ContainerName, constant.NginxReload); err != nil {
return err
}
return nil
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
}
func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time, taskItem *task.Task) error {
clientMap := NewBackupClientMap([]string{fmt.Sprintf("%v", cronjob.DownloadAccountID)})
if !clientMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
@@ -343,7 +462,7 @@ func (u *CronjobService) removeExpiredLog(cronjob model.Cronjob) {
_ = os.Remove(file)
}
}
_ = cronjobRepo.DeleteRecord(repo.WithByID(uint(records[i].ID)))
_ = cronjobRepo.DeleteRecord(repo.WithByID(records[i].ID))
_ = taskRepo.Delete(taskRepo.WithByID(records[i].TaskID))
_ = os.Remove(path.Join(global.CONF.Base.InstallDir, "1panel/log/task/Cronjob", records[i].TaskID+".log"))
}
@@ -362,3 +481,9 @@ func handleCronJobAlert(cronjob *model.Cronjob) {
}
_ = alert_push.PushAlert(pushAlert)
}
func GetCleanLogConfig(cronJob model.Cronjob) dto.CleanLogConfig {
config := &dto.CleanLogConfig{}
_ = json.Unmarshal([]byte(cronJob.Config), config)
return *config
}
+27 -20
View File
@@ -21,6 +21,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/xpu"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/copier"
"github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v4/cpu"
@@ -53,23 +54,25 @@ func NewIDashboardService() IDashboardService {
}
func (u *DashboardService) Restart(operation string) error {
if operation != "1panel" && operation != "system" && operation != "1panel-agent" {
switch operation {
case "system":
{
go func() {
if err := cmd.RunDefaultBashCf("%s reboot", cmd.SudoHandleCmd()); err != nil {
global.LOG.Errorf("handle reboot failed, %v", err)
}
}()
return nil
}
case "1panel-agent":
controller.RestartPanel(false, true, false)
return nil
case "1panel":
controller.RestartPanel(true, true, false)
return nil
default:
return fmt.Errorf("handle restart operation %s failed, err: nonsupport such operation", operation)
}
itemCmd := fmt.Sprintf("%s systemctl restart 1panel-agent.service && %s systemctl restart 1panel-core.service", cmd.SudoHandleCmd(), cmd.SudoHandleCmd())
if operation == "system" {
itemCmd = fmt.Sprintf("%s reboot", cmd.SudoHandleCmd())
}
if operation == "1panel-agent" {
itemCmd = fmt.Sprintf("%s systemctl restart 1panel-agent.service", cmd.SudoHandleCmd())
}
go func() {
stdout, err := cmd.RunDefaultWithStdoutBashC(itemCmd)
if err != nil {
global.LOG.Errorf("handle %s failed, err: %v", itemCmd, stdout)
}
}()
return nil
}
func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) {
@@ -117,7 +120,7 @@ func (u *DashboardService) LoadCurrentInfoForNode() *dto.NodeCurrent {
memoryInfo, _ := mem.VirtualMemory()
currentInfo.MemoryTotal = memoryInfo.Total
currentInfo.MemoryAvailable = memoryInfo.Available
currentInfo.MemoryUsed = memoryInfo.Used + memoryInfo.Shared
currentInfo.MemoryUsed = memoryInfo.Used
currentInfo.MemoryUsedPercent = memoryInfo.UsedPercent
swapInfo, _ := mem.SwapMemory()
@@ -191,7 +194,7 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
memoryInfo, _ := mem.VirtualMemory()
currentInfo.MemoryTotal = memoryInfo.Total
currentInfo.MemoryUsed = memoryInfo.Used + memoryInfo.Shared
currentInfo.MemoryUsed = memoryInfo.Used
currentInfo.MemoryFree = memoryInfo.Free
currentInfo.MemoryCache = memoryInfo.Cached + memoryInfo.Buffers
currentInfo.MemoryShard = memoryInfo.Shared
@@ -208,6 +211,9 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
currentInfo.GPUData = loadGPUInfo()
currentInfo.XPUData = loadXpuInfo()
currentInfo.TopCPUItems = loadTopCPU()
currentInfo.TopMemItems = loadTopMem()
if ioOption == "all" {
diskInfo, _ := disk.IOCounters()
for _, state := range diskInfo {
@@ -401,10 +407,11 @@ type diskInfo struct {
func loadDiskInfo() []dto.DiskInfo {
var datas []dto.DiskInfo
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second))
stdout, err := cmdMgr.RunWithStdoutBashC("timeout 2 df -hT -P | awk 'NR>1 && !/tmpfs|snap\\/core|udev/ {print}'")
format := `awk 'NR>1 && !/tmpfs|snap\/core|udev/ {printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7}'`
stdout, err := cmdMgr.RunWithStdout("bash", "-c", `timeout 2 df -hT -P | `+format)
if err != nil {
cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
stdout, err = cmdMgr2.RunWithStdoutBashC("timeout 1 df -lhT -P | awk 'NR>1 && !/tmpfs|snap\\/core|udev/ {print}'")
stdout, err = cmdMgr2.RunWithStdout("bash", "-c", `timeout 1 df -lhT -P | `+format)
if err != nil {
return datas
}
@@ -414,7 +421,7 @@ func loadDiskInfo() []dto.DiskInfo {
var mounts []diskInfo
var excludes = []string{"/mnt/cdrom", "/boot", "/boot/efi", "/dev", "/dev/shm", "/run/lock", "/run", "/run/shm", "/run/user"}
for _, line := range lines {
fields := strings.Fields(line)
fields := strings.Split(line, "\t")
if len(fields) < 7 {
continue
}
+7 -6
View File
@@ -122,12 +122,13 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
switch req.Type {
case constant.AppPostgresql:
_, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{
From: "remote",
Address: req.Address,
Port: req.Port,
Username: req.Username,
Password: req.Password,
Timeout: req.Timeout,
From: "remote",
Address: req.Address,
Port: req.Port,
InitialDB: req.InitialDB,
Username: req.Username,
Password: req.Password,
Timeout: req.Timeout,
})
return err == nil
case constant.AppRedis:
+2 -2
View File
@@ -7,7 +7,6 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
@@ -24,6 +23,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"github.com/1Panel-dev/1Panel/agent/utils/mysql"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/1Panel-dev/1Panel/agent/utils/mysql/client"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/copier"
@@ -623,7 +623,7 @@ func updateMyCnf(oldFiles []string, group string, param string, value interface{
isOn := false
hasGroup := false
hasKey := false
regItem, _ := regexp.Compile(`\[*\]`)
regItem := re.GetRegex(re.MysqlGroupPattern)
var newFiles []string
i := 0
for _, line := range oldFiles {
+17 -24
View File
@@ -2,7 +2,6 @@ package service
import (
"bufio"
"errors"
"fmt"
"net"
"os"
@@ -19,6 +18,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/ntp"
"github.com/shirou/gopsutil/v4/mem"
)
@@ -122,7 +122,7 @@ func (u *DeviceService) Update(key, value string) error {
if err := ntp.UpdateSystemTimeZone(value); err != nil {
return err
}
go common.RestartService(global.IsMaster, true, false)
go controller.RestartPanel(global.IsMaster, true, false)
case "DNS":
if err := updateDNS(strings.Split(value, ",")); err != nil {
return err
@@ -131,9 +131,8 @@ func (u *DeviceService) Update(key, value string) error {
if cmd.CheckIllegal(value) {
return buserr.New("ErrCmdIllegal")
}
std, err := cmd.RunDefaultWithStdoutBashCf("%s hostnamectl set-hostname %s", cmd.SudoHandleCmd(), value)
if err != nil {
return errors.New(std)
if err := cmd.RunDefaultBashCf("%s hostnamectl set-hostname %s", cmd.SudoHandleCmd(), value); err != nil {
return err
}
case "Ntp", "LocalTime":
if cmd.CheckIllegal(value) {
@@ -222,12 +221,11 @@ func (u *DeviceService) UpdatePasswd(req dto.ChangePasswd) error {
if cmd.CheckIllegal(req.User, req.Passwd) {
return buserr.New("ErrCmdIllegal")
}
std, err := cmd.RunDefaultWithStdoutBashCf("%s echo '%s:%s' | %s chpasswd", cmd.SudoHandleCmd(), req.User, req.Passwd, cmd.SudoHandleCmd())
if err != nil {
if err := cmd.RunDefaultBashCf("%s echo '%s:%s' | %s chpasswd", cmd.SudoHandleCmd(), req.User, req.Passwd, cmd.SudoHandleCmd()); err != nil {
if strings.Contains(err.Error(), "does not exist") {
return buserr.New("ErrNotExistUser")
}
return errors.New(std)
return err
}
return nil
}
@@ -245,9 +243,8 @@ func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error {
}
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
if !req.IsNew {
std, err := cmdMgr.RunWithStdoutBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle swapoff %s failed, err: %s", req.Path, std)
if err := cmdMgr.RunBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path); err != nil {
return fmt.Errorf("handle swapoff %s failed, %v", req.Path, err)
}
}
if req.Size == 0 {
@@ -257,27 +254,23 @@ func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error {
return operateSwapWithFile(true, req)
}
taskItem.LogStart(i18n.GetMsgByKey("CreateSwap"))
stdDD, err := cmdMgr.RunWithStdoutBashCf("%s dd if=/dev/zero of=%s bs=1024 count=%d", cmd.SudoHandleCmd(), req.Path, req.Size)
if err != nil {
return fmt.Errorf("handle dd %s failed, std: %s, err: %s", req.Path, stdDD, err)
if err := cmdMgr.RunBashCf("%s dd if=/dev/zero of=%s bs=1024 count=%d", cmd.SudoHandleCmd(), req.Path, req.Size); err != nil {
return fmt.Errorf("handle dd %s failed, %v", req.Path, err)
}
taskItem.Log("chmod 0600 " + req.Path)
stdChmod, err := cmdMgr.RunWithStdoutBashCf("%s chmod 0600 %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle chmod 0600 %s failed,std: %s, err: %s", req.Path, stdChmod, err)
if err := cmdMgr.RunBashCf("%s chmod 0600 %s", cmd.SudoHandleCmd(), req.Path); err != nil {
return fmt.Errorf("handle chmod 0600 %s failed, %v", req.Path, err)
}
taskItem.LogStart(i18n.GetMsgByKey("FormatSwap"))
stdMkswap, err := cmdMgr.RunWithStdoutBashCf("%s mkswap -f %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle mkswap -f %s failed, std: %s, err: %s", req.Path, stdMkswap, err)
if err := cmdMgr.RunBashCf("%s mkswap -f %s", cmd.SudoHandleCmd(), req.Path); err != nil {
return fmt.Errorf("handle mkswap -f %s failed, %v", req.Path, err)
}
taskItem.LogStart(i18n.GetMsgByKey("EnableSwap"))
stdSwapon, err := cmdMgr.RunWithStdoutBashCf("%s swapon %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
_, _ = cmdMgr.RunWithStdoutBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
return fmt.Errorf("handle swapoff %s failed,std: %s, err: %s", req.Path, stdSwapon, err)
if err := cmdMgr.RunBashCf("%s swapon %s", cmd.SudoHandleCmd(), req.Path); err != nil {
_ = cmdMgr.RunBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
return fmt.Errorf("handle swapoff %s failed, %v", req.Path, err)
}
return operateSwapWithFile(false, req)
}, nil)
+2 -1
View File
@@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build"
@@ -260,7 +261,7 @@ func (u *DeviceService) Clean(req []dto.Clean) {
_ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", len(req)))
if restart {
go common.RestartService(false, true, false)
go controller.RestartPanel(false, true, false)
}
}
+16 -8
View File
@@ -28,14 +28,22 @@ func NewIDiskService() IDiskService {
}
func (s *DiskService) GetCompleteDiskInfo() (*response.CompleteDiskInfo, error) {
output, err := cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
if err != nil {
return nil, fmt.Errorf("failed to execute lsblk command: %v", err)
}
diskInfos, err := parseLsblkOutput(output)
if err != nil {
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
var diskInfos []response.DiskBasicInfo
output, err := cmd.RunDefaultWithStdoutBashC("lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
if err == nil {
diskInfos, err = parseLsblkJsonOutput(output)
if err != nil {
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
}
} else {
output, err = cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
if err != nil {
return nil, fmt.Errorf("failed to run lsblk command: %v", err)
}
diskInfos, err = parseLsblkOutput(output)
if err != nil {
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
}
}
result := organizeDiskInfo(diskInfos)
+151 -21
View File
@@ -2,21 +2,146 @@ package service
import (
"bufio"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"os"
"os/exec"
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
)
type LsblkRaw struct {
Blockdevices []LsblkDevice `json:"blockdevices"`
}
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"`
}
func parseDevice(dev LsblkDevice) []response.DiskBasicInfo {
var list []response.DiskBasicInfo
if strings.HasPrefix(dev.Name, "loop") || strings.HasPrefix(dev.Name, "dm-") || dev.Type == "rom" {
return list
}
if dev.Type == "lvm" {
return list
}
diskType := "Unknown"
if dev.Type == "disk" || dev.Type == "part" {
if dev.Rota {
diskType = "HDD"
} else {
diskType = "SSD"
}
}
mountPoint := dev.Mountpoint
filesystem := dev.Fstype
size := dev.Size
var used, avail, totalSize string
var usePercent int
isMounted := mountPoint != ""
isSystem := false
if dev.Fstype == "LVM2_member" && len(dev.Children) > 0 {
for _, child := range dev.Children {
if child.Type == "lvm" && child.Mountpoint != "" {
devicePath := "/dev/mapper/" + child.Name
totalSize, used, avail, usePercent, _ := getDiskUsageInfo(devicePath)
childInfo := response.DiskBasicInfo{
Device: dev.Name,
Size: totalSize,
Model: dev.Model,
DiskType: diskType,
Filesystem: child.Fstype,
MountPoint: child.Mountpoint,
IsMounted: true,
UsePercent: usePercent,
Used: used,
Avail: avail,
Serial: dev.Serial,
IsRemovable: dev.Tran == "usb",
IsSystem: isSystemDisk(child.Mountpoint),
}
list = append(list, childInfo)
}
}
return list
} else if isMounted {
isSystem = isSystemDisk(mountPoint)
devicePath := "/dev/" + dev.Name
totalSize, used, avail, usePercent, _ = getDiskUsageInfo(devicePath)
if totalSize != "" {
size = totalSize
}
}
info := response.DiskBasicInfo{
Device: dev.Name,
Size: size,
Model: dev.Model,
DiskType: diskType,
Filesystem: filesystem,
MountPoint: mountPoint,
IsMounted: isMounted,
UsePercent: usePercent,
Used: used,
Avail: avail,
Serial: dev.Serial,
IsRemovable: dev.Tran == "usb",
IsSystem: isSystem,
}
list = append(list, info)
for _, child := range dev.Children {
childList := parseDevice(child)
list = append(list, childList...)
}
return list
}
func parseLsblkJsonOutput(output string) ([]response.DiskBasicInfo, error) {
raw := &LsblkRaw{}
if err := json.Unmarshal([]byte(output), raw); err != nil {
return nil, fmt.Errorf("failed to parse lsblk json output: %v", err)
}
var disks []response.DiskBasicInfo
for _, dev := range raw.Blockdevices {
if strings.HasPrefix(dev.Name, "loop") ||
strings.HasPrefix(dev.Name, "dm-") {
continue
}
devList := parseDevice(dev)
disks = append(disks, devList...)
}
return disks, nil
}
func organizeDiskInfo(diskInfos []response.DiskBasicInfo) response.CompleteDiskInfo {
var result response.CompleteDiskInfo
var systemDisk *response.DiskInfo
diskMap := make(map[string]*response.DiskInfo)
partitions := make(map[string][]response.DiskBasicInfo)
@@ -54,7 +179,7 @@ func organizeDiskInfo(diskInfos []response.DiskBasicInfo) response.CompleteDiskI
totalCapacity += capacity
if disk.IsSystem {
systemDisk = disk
result.SystemDisks = append(result.SystemDisks, *disk)
} else if len(disk.Partitions) == 0 {
result.UnpartitionedDisks = append(result.UnpartitionedDisks, disk.DiskBasicInfo)
} else {
@@ -62,7 +187,6 @@ func organizeDiskInfo(diskInfos []response.DiskBasicInfo) response.CompleteDiskI
}
}
result.SystemDisk = systemDisk
result.TotalDisks = len(diskMap)
result.TotalCapacity = totalCapacity
@@ -161,17 +285,25 @@ func parseLsblkOutput(output string) ([]response.DiskBasicInfo, error) {
if fsType == "LVM2_member" {
for _, lvmInfo := range lvmMap {
if lvmInfo.IsMounted {
actualMountPoint = lvmInfo.MountPoint
actualFsType = lvmInfo.Filesystem
actualUsed = lvmInfo.Used
size = lvmInfo.Size
actualAvail = lvmInfo.Avail
actualUsePercent = lvmInfo.UsePercent
isMounted = true
isSystemPartition = lvmInfo.IsSystem
break
lvmDiskInfo := response.DiskBasicInfo{
Device: name,
Size: lvmInfo.Size,
Model: model,
DiskType: "LVM",
IsRemovable: tran == "usb",
IsSystem: lvmInfo.IsSystem,
Filesystem: lvmInfo.Filesystem,
Used: lvmInfo.Used,
Avail: lvmInfo.Avail,
UsePercent: lvmInfo.UsePercent,
MountPoint: lvmInfo.MountPoint,
IsMounted: true,
Serial: serial,
}
diskInfos = append(diskInfos, lvmDiskInfo)
}
}
continue
}
info := response.DiskBasicInfo{
@@ -205,12 +337,10 @@ func getDiskType(rota string) string {
return "Unknown"
}
var kvRe = regexp.MustCompile(`([A-Za-z0-9_]+)=("([^"\\]|\\.)*"|[^ \t]+)`)
func parseKeyValuePairs(line string) map[string]string {
fields := make(map[string]string)
matches := kvRe.FindAllStringSubmatch(line, -1)
matches := re.GetRegex(re.DiskKeyValuePattern).FindAllStringSubmatch(line, -1)
for _, m := range matches {
key := m[1]
raw := m[2]
@@ -394,7 +524,7 @@ func isSystemDisk(mountPoint string) bool {
"/boot/efi",
"/usr",
"/var",
"/home",
"/etc",
}
for _, sysMount := range systemMountPoints {
+16 -48
View File
@@ -8,15 +8,13 @@ import (
"os"
"path"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/systemctl"
"github.com/pkg/errors"
)
type DockerService struct{}
@@ -236,7 +234,9 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate, withRestart bool) erro
}
if withRestart {
return restartDocker()
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
}
return nil
}
@@ -280,8 +280,8 @@ func (u *DockerService) UpdateLogOption(req dto.LogOption) error {
return err
}
if err := restartDocker(); err != nil {
return err
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
return nil
}
@@ -319,8 +319,8 @@ func (u *DockerService) UpdateIpv6Option(req dto.Ipv6Option) error {
return err
}
if err := restartDocker(); err != nil {
return err
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
return nil
}
@@ -343,25 +343,19 @@ func (u *DockerService) UpdateConfByFile(req dto.DaemonJsonUpdateByFile) error {
return err
}
if err := restartDocker(); err != nil {
return err
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
return nil
}
func (u *DockerService) OperateDocker(req dto.DockerOperation) error {
service := "docker"
sudo := cmd.SudoHandleCmd()
dockerCmd, err := getDockerRestartCommand()
if err != nil {
return err
}
if req.Operation == "stop" {
isSocketActive, _ := systemctl.IsActive("docker.socket")
isSocketActive, _ := controller.CheckExist("docker.socket")
if isSocketActive {
std, err := cmd.RunDefaultWithStdoutBashCf("%s systemctl stop docker.socket", sudo)
if err != nil {
global.LOG.Errorf("handle systemctl stop docker.socket failed, err: %v", std)
if err := controller.HandleStop("docker.socket"); err != nil {
global.LOG.Errorf("handle stop docker.socket failed, err: %v", err)
}
}
}
@@ -370,9 +364,8 @@ func (u *DockerService) OperateDocker(req dto.DockerOperation) error {
return err
}
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s %s %s ", dockerCmd, req.Operation, service)
if err != nil {
return errors.New(string(stdout))
if err := controller.Handle(req.Operation, service); err != nil {
return err
}
return nil
}
@@ -435,32 +428,7 @@ func validateDockerConfig() error {
return nil
}
if err != nil || (stdout != "" && strings.TrimSpace(stdout) != "configuration OK") {
return fmt.Errorf("Docker configuration validation failed, err: %v", stdout)
}
return nil
}
func getDockerRestartCommand() (string, error) {
stdout, err := cmd.RunDefaultWithStdoutBashC("which docker")
if err != nil {
return "", fmt.Errorf("failed to find docker: %v", err)
}
dockerPath := stdout
if strings.Contains(dockerPath, "snap") {
return "snap", nil
}
return "systemctl", nil
}
func restartDocker() error {
global.LOG.Info("restart docker")
restartCmd, err := getDockerRestartCommand()
if err != nil {
return err
}
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(3*time.Minute)).RunWithStdoutBashCf("%s restart docker", restartCmd)
if err != nil {
return fmt.Errorf("failed to restart Docker: %s", stdout)
return fmt.Errorf("Docker configuration validation failed, %v", err)
}
return nil
}
+238 -70
View File
@@ -16,17 +16,20 @@ import (
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/firewall"
fireClient "github.com/1Panel-dev/1Panel/agent/utils/firewall/client"
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
"github.com/jinzhu/copier"
)
const confPath = "/etc/sysctl.conf"
const panelSysctlPath = "/etc/sysctl.d/98-onepanel.conf"
type FirewallService struct{}
type IFirewallService interface {
LoadBaseInfo() (dto.FirewallBaseInfo, error)
LoadBaseInfo(tab string) (dto.FirewallBaseInfo, error)
SearchWithPage(search dto.RuleSearch) (int64, interface{}, error)
OperateFirewall(req dto.FirewallOperation) error
OperatePortRule(req dto.PortRuleOperate, reload bool) error
@@ -42,7 +45,7 @@ func NewIFirewallService() IFirewallService {
return &FirewallService{}
}
func (u *FirewallService) LoadBaseInfo() (dto.FirewallBaseInfo, error) {
func (u *FirewallService) LoadBaseInfo(tab string) (dto.FirewallBaseInfo, error) {
var baseInfo dto.FirewallBaseInfo
baseInfo.Version = "-"
baseInfo.Name = "-"
@@ -56,18 +59,16 @@ func (u *FirewallService) LoadBaseInfo() (dto.FirewallBaseInfo, error) {
baseInfo.Name = client.Name()
var wg sync.WaitGroup
wg.Add(3)
wg.Add(2)
go func() {
defer wg.Done()
baseInfo.PingStatus = u.pingStatus()
baseInfo.Version, _ = client.Version()
}()
go func() {
defer wg.Done()
baseInfo.IsActive, _ = client.Status()
}()
go func() {
defer wg.Done()
baseInfo.Version, _ = client.Version()
baseInfo.IsInit, baseInfo.IsBind = loadInitStatus(baseInfo.Name, tab)
}()
wg.Wait()
return baseInfo, nil
@@ -157,15 +158,17 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
if req.Type != des.Type {
continue
}
if backDatas[i].Port == des.Port &&
if backDatas[i].Port == des.DstPort &&
req.Type == "port" &&
backDatas[i].Protocol == des.Protocol &&
backDatas[i].Strategy == des.Strategy &&
backDatas[i].Address == des.Address {
backDatas[i].Address == des.SrcIP {
backDatas[i].ID = des.ID
backDatas[i].Description = des.Description
break
}
if req.Type == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address {
if req.Type == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.SrcIP {
backDatas[i].ID = des.ID
backDatas[i].Description = des.Description
break
}
@@ -211,8 +214,8 @@ func (u *FirewallService) OperateFirewall(req dto.FirewallOperation) error {
return fmt.Errorf("not supported operation: %s", req.Operation)
}
if needRestartDocker && req.WithDockerRestart {
if err := restartDocker(); err != nil {
return err
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
}
return nil
@@ -223,6 +226,9 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
if err != nil {
return err
}
if len(req.Chain) == 0 && client.Name() == "iptables" {
req.Chain = iptables.Chain1PanelBasic
}
protos := strings.Split(req.Protocol, "/")
itemAddress := strings.Split(strings.TrimSuffix(req.Address, ","), ",")
@@ -403,7 +409,10 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
if err != nil {
return err
}
chain := ""
if client.Name() == "iptables" {
chain = iptables.Chain1PanelBasic
}
var fireInfo fireClient.FireInfo
if err := copier.Copy(&fireInfo, &req); err != nil {
return err
@@ -419,7 +428,7 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
return err
}
req.Address = addressList[i]
if err := u.addAddressRecord(req); err != nil {
if err := u.addAddressRecord(chain, req); err != nil {
return err
}
}
@@ -458,10 +467,18 @@ func (u *FirewallService) UpdateAddrRule(req dto.AddrRuleUpdate) error {
}
func (u *FirewallService) UpdateDescription(req dto.UpdateFirewallDescription) error {
var firewall model.Firewall
if err := copier.Copy(&firewall, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
firewall := model.Firewall{
Type: req.Type,
Chain: req.Chain,
SrcIP: req.SrcIP,
DstIP: req.DstIP,
SrcPort: req.SrcPort,
DstPort: req.DstPort,
Protocol: req.Protocol,
Strategy: req.Strategy,
Description: req.Description,
}
return hostRepo.SaveFirewallRecord(&firewall)
}
@@ -561,7 +578,7 @@ func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) {
}
for _, item := range list {
for i := 0; i < len(records); i++ {
if records[i].Port == item.Port && records[i].Protocol == item.Protocol && records[i].Strategy == item.Strategy && records[i].Address == item.Address {
if records[i].DstPort == item.Port && records[i].Protocol == item.Protocol && records[i].Strategy == item.Strategy && records[i].SrcIP == item.Address {
records = append(records[:i], records[i+1:]...)
}
}
@@ -571,62 +588,101 @@ func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) {
_ = hostRepo.DeleteFirewallRecordByID(record.ID)
}
}
func (u *FirewallService) pingStatus() string {
if _, err := os.Stat("/etc/sysctl.conf"); err != nil {
data, err := os.ReadFile("/proc/sys/net/ipv4/icmp_echo_ignore_all")
if err != nil {
return constant.StatusNone
}
stdout, _ := cmd.RunDefaultWithStdoutBashCf("%s sysctl -a 2>/dev/null | grep 'net.ipv4.icmp.echo_ignore_all'", cmd.SudoHandleCmd())
if stdout == "net.ipv4.icmp_echo_ignore_all = 1\n" {
return constant.StatusEnable
v6Data, v6err := os.ReadFile("/proc/sys/net/ipv6/icmp/echo_ignore_all")
if v6err != nil {
if strings.TrimSpace(string(data)) == "1" {
return constant.StatusEnable
}
return constant.StatusDisable
} else {
if strings.TrimSpace(string(data)) == "1" && strings.TrimSpace(string(v6Data)) == "1" {
return constant.StatusEnable
}
return constant.StatusDisable
}
return constant.StatusDisable
}
func (u *FirewallService) updatePingStatus(enable string) error {
lineBytes, err := os.ReadFile(confPath)
if err != nil {
return err
var targetPath string
var applyCmd string
if _, err := os.Stat(confPath); os.IsNotExist(err) {
// Debian 13
targetPath = panelSysctlPath
applyCmd = fmt.Sprintf("%s sysctl --system", cmd.SudoHandleCmd())
if err := cmd.RunDefaultBashCf("%s mkdir -p /etc/sysctl.d", cmd.SudoHandleCmd()); err != nil {
return fmt.Errorf("failed to create directory /etc/sysctl.d: %v", err)
}
} else {
targetPath = confPath
applyCmd = fmt.Sprintf("%s sysctl -p", cmd.SudoHandleCmd())
}
files := strings.Split(string(lineBytes), "\n")
var newFiles []string
lineBytes, err := os.ReadFile(targetPath)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to read %s: %v", targetPath, err)
}
if err := cmd.RunDefaultBashCf("echo %s | %s tee /proc/sys/net/ipv4/icmp_echo_ignore_all > /dev/null", enable, cmd.SudoHandleCmd()); err != nil {
return fmt.Errorf("failed to apply ipv4 ping status temporarily: %v", err)
}
var hasIpv6 bool
ipv6Status, _ := cmd.RunDefaultWithStdoutBashC("sysctl -a 2>/dev/null | grep 'net.ipv6.icmp.echo_ignore_all'")
if len(strings.ReplaceAll(ipv6Status, "\n", "")) != 0 {
if _, err := os.Stat("/proc/sys/net/ipv6/icmp/echo_ignore_all"); err == nil {
hasIpv6 = true
if err := cmd.RunDefaultBashCf("echo %s | %s tee /proc/sys/net/ipv6/icmp/echo_ignore_all > /dev/null", enable, cmd.SudoHandleCmd()); err != nil {
global.LOG.Warnf("failed to apply ipv6 ping status temporarily: %v", err)
}
}
var files []string
if err == nil {
files = strings.Split(string(lineBytes), "\n")
}
var newFiles []string
hasIPv4Line, hasIPv6Line := false, false
for _, line := range files {
if strings.Contains(line, "net/ipv4/icmp_echo_ignore_all") || strings.Contains(line, "net.ipv4.icmp_echo_ignore_all") {
if strings.HasPrefix(strings.TrimSpace(line), "net.ipv4.icmp_echo_ignore_all") {
newFiles = append(newFiles, "net.ipv4.icmp_echo_ignore_all="+enable)
hasIPv4Line = true
continue
}
if hasIpv6 && strings.Contains(line, "net/ipv6/icmp/echo_ignore_all") || strings.Contains(line, "net.ipv6.icmp.echo_ignore_all") {
if strings.HasPrefix(strings.TrimSpace(line), "net.ipv6.icmp.echo_ignore_all") {
newFiles = append(newFiles, "net.ipv6.icmp.echo_ignore_all="+enable)
hasIPv6Line = true
continue
}
newFiles = append(newFiles, line)
}
if !hasIPv4Line {
newFiles = append(newFiles, "net.ipv4.icmp_echo_ignore_all="+enable)
}
if !hasIPv6Line {
if hasIpv6 && !hasIPv6Line {
newFiles = append(newFiles, "net.ipv6.icmp.echo_ignore_all="+enable)
}
file, err := os.OpenFile(confPath, os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
file, err := os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, constant.FilePerm)
if err != nil {
return err
return fmt.Errorf("failed to open %s: %v", targetPath, err)
}
defer file.Close()
_, err = file.WriteString(strings.Join(newFiles, "\n"))
if err != nil {
return err
if _, err = file.WriteString(strings.Join(newFiles, "\n")); err != nil {
return fmt.Errorf("failed to write to %s: %v", targetPath, err)
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s sysctl -p", cmd.SudoHandleCmd())
if err != nil {
return fmt.Errorf("update ping status failed, err: %v", stdout)
if err := cmd.RunDefaultBashC(applyCmd); err != nil {
global.LOG.Warnf("failed to apply persistent config with '%s': %v", applyCmd, err)
}
return nil
@@ -646,7 +702,7 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er
}
}
}
if err := client.Port(fireClient.FireInfo{Port: "22", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
if err := client.Port(fireClient.FireInfo{Port: loadSSHPort(), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
return err
}
if err := client.Port(fireClient.FireInfo{Port: "80", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
@@ -661,14 +717,21 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er
func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord("port", req.Port, req.Protocol, req.Address, req.Strategy)
if req.ID != 0 {
return hostRepo.DeleteFirewallRecordByID(req.ID)
}
return nil
}
if len(req.Description) == 0 {
return nil
}
if err := hostRepo.SaveFirewallRecord(&model.Firewall{
Type: "port",
Port: req.Port,
Chain: req.Chain,
DstPort: req.Port,
Protocol: req.Protocol,
Address: req.Address,
SrcIP: req.Address,
Strategy: req.Strategy,
Description: req.Description,
}); err != nil {
@@ -678,13 +741,18 @@ func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
return nil
}
func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
func (u *FirewallService) addAddressRecord(chain string, req dto.AddrRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord("address", "", "", req.Address, req.Strategy)
if req.ID != 0 {
return hostRepo.DeleteFirewallRecordByID(req.ID)
}
return nil
}
if err := hostRepo.SaveFirewallRecord(&model.Firewall{
Type: "address",
Address: req.Address,
Chain: chain,
SrcIP: req.Address,
Strategy: req.Strategy,
Description: req.Description,
}); err != nil {
@@ -695,29 +763,36 @@ func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
func checkPortUsed(ports, proto string, apps []portOfApp) string {
var portList []int
if strings.Contains(ports, "-") || strings.Contains(ports, ",") {
if strings.Contains(ports, "-") {
port1, err := strconv.Atoi(strings.Split(ports, "-")[0])
if err != nil {
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[0], err)
return ""
}
port2, err := strconv.Atoi(strings.Split(ports, "-")[1])
if err != nil {
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[1], err)
return ""
}
for i := port1; i <= port2; i++ {
portList = append(portList, i)
}
} else {
portLists := strings.Split(ports, ",")
for _, item := range portLists {
portItem, _ := strconv.Atoi(item)
portList = append(portList, portItem)
}
rangeSplit := ""
if strings.Contains(ports, "-") {
rangeSplit = "-"
}
if strings.Contains(ports, ":") {
rangeSplit = ":"
}
if len(rangeSplit) != 0 {
port1, err := strconv.Atoi(strings.Split(ports, rangeSplit)[0])
if err != nil {
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, rangeSplit)[0], err)
return ""
}
port2, err := strconv.Atoi(strings.Split(ports, rangeSplit)[1])
if err != nil {
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, rangeSplit)[1], err)
return ""
}
for i := port1; i <= port2; i++ {
portList = append(portList, i)
}
}
if strings.Contains(ports, ",") {
portLists := strings.Split(ports, ",")
for _, item := range portLists {
portItem, _ := strconv.Atoi(item)
portList = append(portList, portItem)
}
}
if len(portList) != 0 {
var usedPorts []string
for _, port := range portList {
portItem := fmt.Sprintf("%v", port)
@@ -751,3 +826,96 @@ func checkPortUsed(ports, proto string, apps []portOfApp) string {
}
return ""
}
func loadInitStatus(clientName, tab string) (bool, bool) {
if clientName == "firewalld" {
return true, true
}
if clientName == "ufw" && tab != "forward" {
return true, true
}
switch tab {
case "base":
if isExist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore); !isExist {
return false, false
}
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.IoRuleIn); !exist {
return false, false
}
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); !exist {
return false, false
}
if exist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasic); !exist {
return false, false
}
if exist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasicAfter); !exist {
return false, false
}
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllTcp); !exist {
return false, false
}
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllUdp); !exist {
return false, false
}
if bind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore); !bind {
return true, false
}
if bind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic); !bind {
return true, false
}
if bind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter); !bind {
return true, false
}
return true, true
case "advance":
isExist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelInput)
if !isExist {
return false, false
}
isExist, _ = iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelOutput)
if !isExist {
return false, false
}
isBind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput)
if !isBind {
return true, false
}
isBind, _ = iptables.CheckChainBind(iptables.FilterTab, iptables.ChainOutput, iptables.Chain1PanelOutput)
return true, isBind
case "forward":
stdout, err := cmd.RunDefaultWithStdoutBashC("cat /proc/sys/net/ipv4/ip_forward")
if err != nil {
global.LOG.Errorf("check /proc/sys/net/ipv4/ip_forward failed, err: %v", err)
return false, false
}
if strings.TrimSpace(stdout) == "0" {
return false, false
}
exist, _ := iptables.CheckChainExist(iptables.NatTab, iptables.Chain1PanelPreRouting)
if !exist {
return false, false
}
exist, _ = iptables.CheckChainExist(iptables.NatTab, iptables.Chain1PanelPostRouting)
if !exist {
return false, false
}
exist, _ = iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelForward)
if !exist {
return false, false
}
isBind, _ := iptables.CheckChainBind(iptables.NatTab, "PREROUTING", iptables.Chain1PanelPreRouting)
if !isBind {
return false, false
}
isBind, _ = iptables.CheckChainBind(iptables.NatTab, "POSTROUTING", iptables.Chain1PanelPostRouting)
if !isBind {
return false, false
}
isBind, _ = iptables.CheckChainBind(iptables.FilterTab, "FORWARD", iptables.Chain1PanelForward)
return true, isBind
default:
return false, false
}
}
+7 -7
View File
@@ -17,9 +17,9 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/ini_conf"
"github.com/1Panel-dev/1Panel/agent/utils/systemctl"
"github.com/pkg/errors"
"gopkg.in/ini.v1"
)
@@ -52,9 +52,9 @@ func (h *HostToolService) GetToolStatus(req request.HostToolReq) (*response.Host
return res, nil
}
supervisorConfig.IsExist = true
serviceExist, _ := systemctl.IsExist(constant.Supervisord)
serviceExist, _ := controller.CheckExist(constant.Supervisord)
if !serviceExist {
serviceExist, _ = systemctl.IsExist(constant.Supervisor)
serviceExist, _ = controller.CheckExist(constant.Supervisor)
if !serviceExist {
supervisorConfig.IsExist = false
res.Config = supervisorConfig
@@ -76,7 +76,7 @@ func (h *HostToolService) GetToolStatus(req request.HostToolReq) (*response.Host
_, ctlRrr := exec.LookPath("supervisorctl")
supervisorConfig.CtlExist = ctlRrr == nil
active, _ := systemctl.IsActive(supervisorConfig.ServiceName)
active, _ := controller.CheckActive(supervisorConfig.ServiceName)
if active {
supervisorConfig.Status = "running"
} else {
@@ -193,7 +193,7 @@ func (h *HostToolService) CreateToolConfig(req request.HostToolCreate) error {
return err
}
}
if err = systemctl.Restart(req.ServiceName); err != nil {
if err = controller.HandleRestart(req.ServiceName); err != nil {
global.LOG.Errorf("[init] restart %s failed err %s", req.ServiceName, err.Error())
return err
}
@@ -209,7 +209,7 @@ func (h *HostToolService) OperateTool(req request.HostToolReq) error {
serviceName = serviceNameSet.Value
}
}
return systemctl.Operate(req.Operate, serviceName)
return controller.Handle(req.Operate, serviceName)
}
func (h *HostToolService) OperateToolConfig(req request.HostToolConfig) (*response.HostToolConfig, error) {
@@ -251,7 +251,7 @@ func (h *HostToolService) OperateToolConfig(req request.HostToolConfig) (*respon
if err = fileOp.WriteFile(configPath, strings.NewReader(req.Content), fileInfo.Mode()); err != nil {
return nil, err
}
if err = systemctl.Restart(serviceName); err != nil {
if err = controller.HandleRestart(serviceName); err != nil {
_ = fileOp.WriteFile(configPath, bytes.NewReader(oldContent), fileInfo.Mode())
return nil, err
}
+58 -36
View File
@@ -228,6 +228,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) error {
Tags: []string{req.Name},
Remove: true,
Labels: stringsToMap(req.Tags),
BuildArgs: stringsToMap2(req.Args),
}
taskItem, err := task.NewTaskWithOps(req.Name, task.TaskBuild, task.TaskScopeImage, req.TaskID, 1)
if err != nil {
@@ -308,51 +309,72 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
}
func (u *ImageService) ImageLoad(req dto.ImageLoad) error {
file, err := os.Open(req.Path)
taskItem, err := task.NewTaskWithOps(req.Path, task.TaskImport, task.TaskScopeImage, req.TaskID, 1)
if err != nil {
return err
}
defer file.Close()
client, err := docker.NewDockerClient()
if err != nil {
return err
}
defer client.Close()
res, err := client.ImageLoad(context.TODO(), file)
if err != nil {
return err
}
defer res.Body.Close()
content, err := io.ReadAll(res.Body)
if err != nil {
return err
}
if strings.Contains(string(content), "Error") {
return errors.New(string(content))
return fmt.Errorf("new task for image import failed, err: %v", err)
}
taskItem.AddSubTask(i18n.GetWithName("TaskImport", req.Path), func(t *task.Task) error {
file, err := os.Open(req.Path)
if err != nil {
return err
}
defer file.Close()
client, err := docker.NewDockerClient()
if err != nil {
return err
}
defer client.Close()
res, err := client.ImageLoad(context.TODO(), file)
if err != nil {
return err
}
defer res.Body.Close()
content, err := io.ReadAll(res.Body)
if err != nil {
return err
}
if strings.Contains(string(content), "Error") {
return errors.New(string(content))
}
return nil
}, nil)
go func() {
_ = taskItem.Execute()
}()
return nil
}
func (u *ImageService) ImageSave(req dto.ImageSave) error {
client, err := docker.NewDockerClient()
taskItem, err := task.NewTaskWithOps(req.Name, task.TaskExport, task.TaskScopeImage, req.TaskID, 1)
if err != nil {
return err
return fmt.Errorf("new task for image export failed, err: %v", err)
}
defer client.Close()
taskItem.AddSubTask(i18n.GetWithName("TaskExport", req.Name), func(t *task.Task) error {
taskItem.Log(req.TagName)
client, err := docker.NewDockerClient()
if err != nil {
return err
}
defer client.Close()
out, err := client.ImageSave(context.TODO(), []string{req.TagName})
if err != nil {
return err
}
defer out.Close()
file, err := os.OpenFile(fmt.Sprintf("%s/%s.tar", req.Path, req.Name), os.O_WRONLY|os.O_CREATE|os.O_EXCL, constant.FilePerm)
if err != nil {
return err
}
defer file.Close()
if _, err = io.Copy(file, out); err != nil {
return err
}
out, err := client.ImageSave(context.TODO(), []string{req.TagName})
if err != nil {
return err
}
defer out.Close()
file, err := os.OpenFile(fmt.Sprintf("%s/%s.tar", req.Path, req.Name), os.O_WRONLY|os.O_CREATE|os.O_EXCL, constant.FilePerm)
if err != nil {
return err
}
defer file.Close()
if _, err = io.Copy(file, out); err != nil {
return err
}
return nil
}, nil)
go func() {
_ = taskItem.Execute()
}()
return nil
}
+6 -5
View File
@@ -16,6 +16,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
)
@@ -134,7 +135,7 @@ func (u *ImageRepoService) Delete(req dto.OperateByID) error {
return err
}
go func() {
_ = restartDocker()
_ = controller.HandleRestart("docker")
}()
return nil
}
@@ -262,8 +263,8 @@ func stopBeforeUpdateRepo() error {
if err := validateDockerConfig(); err != nil {
return err
}
if err := restartDocker(); err != nil {
return err
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
@@ -275,8 +276,8 @@ func stopBeforeUpdateRepo() error {
cancel()
return errors.New("the docker service cannot be restarted")
default:
stdout, err := cmd.RunDefaultWithStdoutBashC("systemctl is-active docker")
if string(stdout) == "active\n" && err == nil {
active, err := controller.CheckActive("docker")
if active && err != nil {
global.LOG.Info("docker restart with new conf successful!")
return nil
}
+339
View File
@@ -0,0 +1,339 @@
package service
import (
"errors"
"fmt"
"net"
"strings"
"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/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client"
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
)
type IIptablesService interface {
Search(req dto.SearchPageWithType) (int64, interface{}, error)
OperateRule(req dto.IptablesRuleOp) error
BatchOperate(req dto.IptablesBatchOperate) error
LoadChainStatus(req dto.OperationWithName) dto.IptablesChainStatus
Operate(req dto.IptablesOp) error
}
type IptablesService struct{}
func NewIIptablesService() IIptablesService {
return &IptablesService{}
}
func (s *IptablesService) Search(req dto.SearchPageWithType) (int64, interface{}, error) {
rules, err := iptables.ReadFilterRulesByChain(req.Type)
if err != nil {
return 0, nil, fmt.Errorf("failed to read iptables rules: %w", err)
}
var records []iptables.FilterRules
total, start, end := len(rules), (req.Page-1)*req.PageSize, req.Page*req.PageSize
if start > total {
records = make([]iptables.FilterRules, 0)
} else {
if end >= total {
end = total
}
records = rules[start:end]
}
rulesInDB, _ := hostRepo.ListFirewallRecord(hostRepo.WithByChain(req.Type))
for i := 0; i < len(records); i++ {
for _, item := range rulesInDB {
if records[i].Strategy == item.Strategy &&
records[i].DstIP == item.DstIP &&
fmt.Sprintf("%v", records[i].DstPort) == item.DstPort &&
records[i].Protocol == item.Protocol &&
records[i].SrcIP == item.SrcIP &&
fmt.Sprintf("%v", records[i].SrcPort) == item.SrcPort {
records[i].ID = item.ID
records[i].Description = item.Description
}
}
}
return int64(total), records, nil
}
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
action := "ACCEPT"
if req.Strategy == "drop" {
action = "DROP"
}
policy := iptables.FilterRules{
Protocol: req.Protocol,
SrcIP: req.SrcIP,
DstIP: req.DstIP,
Strategy: action,
}
if req.SrcPort != 0 {
policy.SrcPort = fmt.Sprintf("%v", req.SrcPort)
}
if req.DstPort != 0 {
policy.DstPort = fmt.Sprintf("%v", req.DstPort)
}
name := iptables.InputFileName
if req.Chain == iptables.Chain1PanelOutput {
name = iptables.OutputFileName
}
switch req.Operation {
case "add":
if err := s.validateRuleInput(&req); err != nil {
return err
}
if err := iptables.AddFilterRule(req.Chain, policy); err != nil {
return fmt.Errorf("failed to add iptables rule: %w", err)
}
if len(req.Description) != 0 {
rule := &model.Firewall{
Chain: req.Chain,
Protocol: req.Protocol,
SrcIP: req.SrcIP,
SrcPort: policy.SrcPort,
DstIP: req.DstIP,
DstPort: policy.DstPort,
Strategy: req.Strategy,
Description: req.Description,
}
if err := hostRepo.SaveFirewallRecord(rule); err != nil {
return fmt.Errorf("failed to save rule to database: %w", err)
}
}
case "remove":
if err := iptables.DeleteFilterRule(req.Chain, policy); err != nil {
return fmt.Errorf("failed to remove iptables rule: %w", err)
}
if req.ID != 0 {
if err := hostRepo.DeleteFirewallRecordByID(req.ID); err != nil {
return fmt.Errorf("failed to delete rule from database: %w", err)
}
}
}
if err := iptables.SaveRulesToFile(iptables.FilterTab, req.Chain, name); err != nil {
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
}
return nil
}
func (s *IptablesService) BatchOperate(req dto.IptablesBatchOperate) error {
for _, rule := range req.Rules {
if err := s.OperateRule(rule); err != nil {
return err
}
}
return nil
}
func (s *IptablesService) Operate(req dto.IptablesOp) error {
targetChain := iptables.ChainInput
if req.Name == iptables.Chain1PanelOutput {
targetChain = iptables.ChainOutput
}
switch req.Operate {
case "init-base":
if ok := cmd.Which("iptables"); !ok {
return fmt.Errorf("failed to find iptables")
}
if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelBasicBefore); err != nil {
return err
}
if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelBasic); err != nil {
return err
}
if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelBasicAfter); err != nil {
return err
}
if err := initPreRules(); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore, 1); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic, 2); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil {
return err
}
return nil
case "init-forward":
return client.EnableIptablesForward()
case "init-advance":
if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelInput); err != nil {
return err
}
if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelOutput); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainOutput, iptables.Chain1PanelOutput, 1); err != nil {
return err
}
number := loadBindNumber(iptables.Chain1PanelInput)
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput, number); err != nil {
return err
}
return nil
case "bind-base":
if err := initPreRules(); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore, 1); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic, 2); err != nil {
return err
}
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil {
return err
}
return nil
case "unbind-base":
if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter); err != nil {
return err
}
if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore); err != nil {
return err
}
if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic); err != nil {
return err
}
return nil
case "bind":
if err := iptables.BindChain(iptables.FilterTab, targetChain, req.Name, loadBindNumber(req.Name)); err != nil {
return err
}
return nil
case "unbind":
if err := iptables.UnbindChain(iptables.FilterTab, targetChain, req.Name); err != nil {
return err
}
return nil
}
return nil
}
func (s *IptablesService) LoadChainStatus(req dto.OperationWithName) dto.IptablesChainStatus {
var data dto.IptablesChainStatus
var err error
data.DefaultStrategy, err = iptables.LoadDefaultStrategy(req.Name)
if err != nil {
global.LOG.Error(err)
}
switch req.Name {
case iptables.Chain1PanelBasic:
data.IsBind, err = iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, req.Name)
case iptables.Chain1PanelInput:
data.IsBind, err = iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, req.Name)
case iptables.Chain1PanelOutput:
data.IsBind, err = iptables.CheckChainBind(iptables.FilterTab, iptables.ChainOutput, req.Name)
}
return data
}
func (s *IptablesService) validateRuleInput(req *dto.IptablesRuleOp) error {
if req.Protocol != "" {
validProtocols := map[string]bool{"tcp": true, "udp": true, "icmp": true, "all": true}
if !validProtocols[strings.ToLower(req.Protocol)] {
return fmt.Errorf("invalid protocol: %s, must be tcp, udp, icmp or all", req.Protocol)
}
}
if req.SrcIP != "" {
if err := s.validateIPOrCIDR(req.SrcIP); err != nil {
return fmt.Errorf("invalid source IP: %w", err)
}
}
if req.DstIP != "" {
if err := s.validateIPOrCIDR(req.DstIP); err != nil {
return fmt.Errorf("invalid destination IP: %w", err)
}
}
if req.SrcPort > 65535 {
return fmt.Errorf("invalid source port: %d, must be between 1 and 65535", req.SrcPort)
}
if req.DstPort > 65535 {
return fmt.Errorf("invalid destination port: %d, must be between 1 and 65535", req.DstPort)
}
if (req.SrcPort > 0 || req.DstPort > 0) && req.Protocol == "" {
return fmt.Errorf("port specification requires protocol (tcp/udp)")
}
return nil
}
func (s *IptablesService) validateIPOrCIDR(ipStr string) error {
if strings.Contains(ipStr, "/") {
_, _, err := net.ParseCIDR(ipStr)
if err != nil {
return fmt.Errorf("invalid CIDR format: %w", err)
}
return nil
}
ip := net.ParseIP(ipStr)
if ip == nil {
return fmt.Errorf("invalid IP address format")
}
return nil
}
func loadBindNumber(chain string) int {
if chain == iptables.Chain1PanelOutput {
return 1
}
number := 1
if exist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore); exist {
number++
}
if exist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasic); exist {
number++
}
return number
}
func initPreRules() error {
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.IoRuleIn); err != nil {
return err
}
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); err != nil {
return err
}
panelPort := ""
if !global.IsMaster {
panelPort = global.CONF.Base.Port
} else {
var portSetting model.Setting
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
if len(portSetting.Value) != 0 {
panelPort = portSetting.Value
}
}
if len(panelPort) == 0 {
return errors.New("find 1panel service port failed")
}
ports := []string{"80", "443", panelPort, loadSSHPort()}
for _, item := range ports {
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", item)); err != nil {
return err
}
}
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllTcp); err != nil {
return err
}
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllUdp); err != nil {
return err
}
return nil
}
+150 -12
View File
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"sort"
"strconv"
"time"
@@ -21,6 +22,7 @@ import (
"github.com/shirou/gopsutil/v4/load"
"github.com/shirou/gopsutil/v4/mem"
"github.com/shirou/gopsutil/v4/net"
"github.com/shirou/gopsutil/v4/process"
)
type MonitorService struct {
@@ -64,12 +66,24 @@ func (m *MonitorService) LoadMonitorData(req dto.MonitorSearch) ([]dto.MonitorDa
itemData.Param = "base"
for _, base := range bases {
itemData.Date = append(itemData.Date, base.CreatedAt)
if req.Param == "all" || req.Param == "cpu" {
var processes []dto.Process
_ = json.Unmarshal([]byte(base.TopCPU), &processes)
base.TopCPUItems = processes
base.TopCPU = ""
}
if req.Param == "all" || req.Param == "mem" {
var processes []dto.Process
_ = json.Unmarshal([]byte(base.TopMem), &processes)
base.TopMemItems = processes
base.TopMem = ""
}
itemData.Value = append(itemData.Value, base)
}
data = append(data, itemData)
}
if req.Param == "all" || req.Param == "io" {
bases, err := monitorRepo.GetIO(repo.WithByCreatedAt(req.StartTime, req.EndTime))
bases, err := monitorRepo.GetIO(repo.WithByName(req.IO), repo.WithByCreatedAt(req.StartTime, req.EndTime))
if err != nil {
return nil, err
}
@@ -83,7 +97,7 @@ func (m *MonitorService) LoadMonitorData(req dto.MonitorSearch) ([]dto.MonitorDa
data = append(data, itemData)
}
if req.Param == "all" || req.Param == "network" {
bases, err := monitorRepo.GetNetwork(repo.WithByName(req.Info), repo.WithByCreatedAt(req.StartTime, req.EndTime))
bases, err := monitorRepo.GetNetwork(repo.WithByName(req.Network), repo.WithByCreatedAt(req.StartTime, req.EndTime))
if err != nil {
return nil, err
}
@@ -169,8 +183,14 @@ func (m *MonitorService) Run() {
if len(totalPercent) == 1 {
itemModel.Cpu = totalPercent[0]
}
topCPU := loadTopCPU()
if len(topCPU) != 0 {
topItemCPU, err := json.Marshal(topCPU)
if err == nil {
itemModel.TopCPU = string(topItemCPU)
}
}
cpuCount, _ := cpu.Counts(false)
loadInfo, _ := load.Avg()
itemModel.CpuLoad1 = loadInfo.Load1
itemModel.CpuLoad5 = loadInfo.Load5
@@ -179,6 +199,13 @@ func (m *MonitorService) Run() {
memoryInfo, _ := mem.VirtualMemory()
itemModel.Memory = memoryInfo.UsedPercent
topMem := loadTopMem()
if len(topMem) != 0 {
topMemItem, err := json.Marshal(topMem)
if err == nil {
itemModel.TopMem = string(topMemItem)
}
}
if err := settingRepo.CreateMonitorBase(itemModel); err != nil {
global.LOG.Errorf("Insert basic monitoring data failed, err: %v", err)
@@ -201,9 +228,18 @@ func (m *MonitorService) Run() {
func (m *MonitorService) loadDiskIO() {
ioStat, _ := disk.IOCounters()
var diskIOList []disk.IOCountersStat
var ioStatAll disk.IOCountersStat
for _, io := range ioStat {
ioStatAll.Name = "all"
ioStatAll.ReadBytes += io.ReadBytes
ioStatAll.WriteBytes += io.WriteBytes
ioStatAll.ReadTime += io.ReadTime
ioStatAll.WriteTime += io.WriteTime
ioStatAll.WriteCount += io.WriteCount
ioStatAll.ReadCount += io.ReadCount
diskIOList = append(diskIOList, io)
}
diskIOList = append(diskIOList, ioStatAll)
m.DiskIO <- diskIOList
}
@@ -234,29 +270,29 @@ func (m *MonitorService) saveIODataToDB(ctx context.Context, interval float64) {
var itemIO model.MonitorIO
itemIO.Name = io1.Name
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / interval / 60)
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / interval)
}
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60)
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / interval)
}
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / interval / 60)
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / interval)
}
writeCount := uint64(0)
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / interval * 60)
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / interval)
}
if writeCount > itemIO.Count {
itemIO.Count = writeCount
}
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / interval / 60)
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / interval)
}
writeTime := uint64(0)
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / interval / 60)
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / interval)
}
if writeTime > itemIO.Time {
itemIO.Time = writeTime
@@ -294,10 +330,10 @@ func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64)
itemNet.Name = net1.Name
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval
}
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval
}
netList = append(netList, itemNet)
break
@@ -314,6 +350,108 @@ func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64)
}
}
func loadTopCPU() []dto.Process {
processes, err := process.Processes()
if err != nil {
return nil
}
top5 := make([]dto.Process, 0, 5)
for _, p := range processes {
percent, err := p.CPUPercent()
if err != nil {
continue
}
minIndex := 0
if len(top5) >= 5 {
minCPU := top5[0].Percent
for i := 1; i < len(top5); i++ {
if top5[i].Percent < minCPU {
minCPU = top5[i].Percent
minIndex = i
}
}
if percent < minCPU {
continue
}
}
name, err := p.Name()
if err != nil {
name = "undifine"
}
cmd, err := p.Cmdline()
if err != nil {
cmd = "undifine"
}
user, err := p.Username()
if err != nil {
user = "undifine"
}
if len(top5) == 5 {
top5[minIndex] = dto.Process{Percent: percent, Pid: p.Pid, User: user, Name: name, Cmd: cmd}
} else {
top5 = append(top5, dto.Process{Percent: percent, Pid: p.Pid, User: user, Name: name, Cmd: cmd})
}
}
sort.Slice(top5, func(i, j int) bool {
return top5[i].Percent > top5[j].Percent
})
return top5
}
func loadTopMem() []dto.Process {
processes, err := process.Processes()
if err != nil {
return nil
}
top5 := make([]dto.Process, 0, 5)
for _, p := range processes {
stat, err := p.MemoryInfo()
if err != nil {
continue
}
memItem := stat.RSS
minIndex := 0
if len(top5) >= 5 {
min := top5[0].Memory
for i := 1; i < len(top5); i++ {
if top5[i].Memory < min {
min = top5[i].Memory
minIndex = i
}
}
if memItem < min {
continue
}
}
name, err := p.Name()
if err != nil {
name = "undifine"
}
cmd, err := p.Cmdline()
if err != nil {
cmd = "undifine"
}
user, err := p.Username()
if err != nil {
user = "undifine"
}
percent, _ := p.MemoryPercent()
if len(top5) == 5 {
top5[minIndex] = dto.Process{Percent: float64(percent), Pid: p.Pid, User: user, Name: name, Cmd: cmd, Memory: memItem}
} else {
top5 = append(top5, dto.Process{Percent: float64(percent), Pid: p.Pid, User: user, Name: name, Cmd: cmd, Memory: memItem})
}
}
sort.Slice(top5, func(i, j int) bool {
return top5[i].Memory > top5[j].Memory
})
return top5
}
func StartMonitor(removeBefore bool, interval string) error {
if removeBefore {
monitorCancel()
@@ -330,7 +468,7 @@ func StartMonitor(removeBefore bool, interval string) error {
now := time.Now()
nextMinute := now.Truncate(time.Minute).Add(time.Minute)
time.AfterFunc(time.Until(nextMinute), func() {
monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %sm", interval), service)
monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %ss", interval), service)
if err != nil {
return
}
+18 -8
View File
@@ -45,7 +45,7 @@ type INginxService interface {
GetModules() (*response.NginxBuildConfig, error)
UpdateModule(req request.NginxModuleUpdate) error
OperateDefaultHTTPs(req request.NginxOperateReq) error
OperateDefaultHTTPs(req request.NginxDefaultHTTPSUpdate) error
GetDefaultHttpsStatus() (*response.NginxConfigRes, error)
}
@@ -354,7 +354,7 @@ func (n NginxService) UpdateModule(req request.NginxModuleUpdate) error {
return fileOp.SaveFileWithByte(moduleConfigPath, moduleByte, constant.DirPerm)
}
func (n NginxService) OperateDefaultHTTPs(req request.NginxOperateReq) error {
func (n NginxService) OperateDefaultHTTPs(req request.NginxDefaultHTTPSUpdate) error {
appInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
@@ -372,11 +372,18 @@ func (n NginxService) OperateDefaultHTTPs(req request.NginxOperateReq) error {
if err != nil {
return err
}
if req.Operate == "enable" {
if err := handleSSLConfig(&appInstall, hasDefaultWebsite); err != nil {
switch req.Operate {
case "enable":
if req.SSLRejectHandshake {
defaultWebsite, _ := websiteRepo.GetFirst(websiteRepo.WithDefaultServer())
if defaultWebsite.ID > 0 {
return buserr.New("ErrDefaultWebsite")
}
}
if err := handleSSLConfig(&appInstall, hasDefaultWebsite, req.SSLRejectHandshake); err != nil {
return err
}
} else if req.Operate == "disable" {
case "disable":
defaultConfig, err := parser.NewStringParser(string(content)).Parse()
if err != nil {
return err
@@ -387,6 +394,7 @@ func (n NginxService) OperateDefaultHTTPs(req request.NginxOperateReq) error {
defaultServer.RemoveListen(fmt.Sprintf("[::]:%d", appInstall.HttpsPort))
defaultServer.RemoveDirective("include", []string{"/usr/local/openresty/nginx/conf/ssl/root_ssl.conf"})
defaultServer.RemoveDirective("http2", []string{"on"})
defaultServer.RemoveDirective("ssl_reject_handshake", []string{"on"})
if err = nginx.WriteConfig(defaultConfig, nginx.IndentedStyle); err != nil {
return err
}
@@ -413,9 +421,11 @@ func (n NginxService) GetDefaultHttpsStatus() (*response.NginxConfigRes, error)
res := &response.NginxConfigRes{}
for _, directive := range defaultServer.GetDirectives() {
if directive.GetName() == "include" && directive.GetParameters()[0] == "/usr/local/openresty/nginx/conf/ssl/root_ssl.conf" {
return &response.NginxConfigRes{
Https: true,
}, nil
res.Https = true
}
if directive.GetName() == "ssl_reject_handshake" && directive.GetParameters()[0] == "on" {
res.Https = true
res.SSLRejectHandshake = true
}
}
return res, nil
+4 -11
View File
@@ -1,7 +1,6 @@
package service
import (
"errors"
"fmt"
"os"
"path"
@@ -122,9 +121,11 @@ func updateDefaultServerConfig(enable bool) error {
includeSSL := false
for _, dir := range defaultServer.GetDirectives() {
if dir.GetName() == "ssl_reject_handshake" && dir.GetParameters()[0] == "on" {
defaultServer.RemoveDirective("ssl_reject_handshake", []string{"on"})
}
if dir.GetName() == "include" && dir.GetParameters()[0] == "/usr/local/openresty/nginx/conf/ssl/root_ssl.conf" {
includeSSL = true
break
}
}
updateDefaultServer(defaultServer, nginxInstall.HttpPort, nginxInstall.HttpsPort, enable, includeSSL)
@@ -238,10 +239,6 @@ func getNginxParamsFromStaticFile(scope dto.NginxKey, newParams []dto.NginxParam
}
func opNginx(containerName, operate string) error {
var (
out string
err error
)
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
cmdStr := fmt.Sprintf("docker exec -i %s nginx ", containerName)
if operate == constant.NginxCheck {
@@ -249,11 +246,7 @@ func opNginx(containerName, operate string) error {
} else {
cmdStr = cmdStr + "-s reload"
}
out, err = cmdMgr.RunWithStdoutBashC(cmdStr)
if err != nil {
if out != "" {
return errors.New(out)
}
if err := cmdMgr.RunBashC(cmdStr); err != nil {
return err
}
return nil
+2 -3
View File
@@ -5,7 +5,6 @@ import (
"math"
"os"
"path"
"regexp"
"strconv"
"strings"
"time"
@@ -17,6 +16,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/shirou/gopsutil/v4/disk"
)
@@ -184,8 +184,7 @@ func createClashDir(clashDir string) error {
}
func getRecycleBinDTOFromName(filename string) (*response.RecycleBinDTO, error) {
r := regexp.MustCompile(`_1p_file_1p_(.+)_p_(\d+)_(\d+)`)
matches := r.FindStringSubmatch(filename)
matches := re.GetRegex(re.RecycleBinFilePattern).FindStringSubmatch(filename)
if len(matches) != 4 {
return nil, fmt.Errorf("invalid filename format")
}
+42 -38
View File
@@ -5,18 +5,18 @@ import (
"context"
"encoding/json"
"fmt"
fcgiclient "github.com/tomasen/fcgi_client"
"maps"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"time"
fcgiclient "github.com/tomasen/fcgi_client"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
"gopkg.in/ini.v1"
@@ -30,11 +30,11 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/pkg/errors"
"github.com/subosito/gotenv"
)
@@ -244,8 +244,10 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt
runtimeDTO.Params[k] = v
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
if strings.Contains(k, "CONTAINER_PORT") {
r := regexp.MustCompile(`_(\d+)$`)
matches := r.FindStringSubmatch(k)
matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k)
if len(matches) < 2 {
continue
}
containerPort, err := strconv.Atoi(v)
if err != nil {
continue
@@ -255,9 +257,6 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt
continue
}
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
if hostIP == "" {
hostIP = "0.0.0.0"
}
runtimeDTO.ExposedPorts = append(runtimeDTO.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
@@ -483,6 +482,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
ExposedPorts: req.ExposedPorts,
Environments: req.Environments,
Volumes: req.Volumes,
ExtraHosts: req.ExtraHosts,
},
}
composeContent, envContent, _, err := handleParams(create, projectDir)
@@ -679,9 +679,6 @@ func (r *RuntimeService) GetPHPExtensions(runtimeID uint) (response.PHPExtension
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second))
out, err := cmdMgr.RunWithStdoutBashCf("docker exec -i %s php -m", runtime.ContainerName)
if err != nil {
if out != "" {
return res, errors.New(out)
}
return res, err
}
extensions := strings.Split(out, "\n")
@@ -723,9 +720,9 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
if err != nil {
return err
}
cmdMgr := cmd2.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(15*time.Minute))
installTask.AddSubTask("", func(t *task.Task) error {
err = cmdMgr.RunBashCf("docker exec -i %s install-ext %s", runtime.ContainerName, req.Name)
err = cmd.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(20*time.Minute)).
RunBashCf("docker exec -i %s install-ext %s", runtime.ContainerName, req.Name)
if err != nil {
return err
}
@@ -738,22 +735,23 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
if err != nil {
return err
}
err = cmdMgr.RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image)
err = cmd.NewCommandMgr(cmd.WithTask(*installTask), cmd.WithTimeout(15*time.Minute)).
RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image)
if err != nil {
return err
}
handlePHPDir(*runtime)
if err = restartRuntime(runtime); err != nil {
return err
}
newImageID, err := client.GetImageIDByName(runtime.Image)
if err == nil && newImageID != oldImageID {
if err := client.DeleteImage(oldImageID); err != nil {
t.Log(fmt.Sprintf("delete old image error %v", err))
t.Log(fmt.Sprintf("delete old image %s failed %v", oldImageID, err))
} else {
t.Log("delete old image success")
}
}
handlePHPDir(*runtime)
if err = restartRuntime(runtime); err != nil {
return err
}
return nil
}, nil)
go func() {
@@ -833,7 +831,7 @@ func (r *RuntimeService) GetPHPConfig(id uint) (*response.PHPConfig, error) {
if strings.HasPrefix(line, ";") {
continue
}
matches := regexp.MustCompile(`^\s*([a-z_]+)\s*=\s*(.*)$`).FindStringSubmatch(line)
matches := re.GetRegex(re.PhpAssignmentPattern).FindStringSubmatch(line)
if len(matches) == 3 {
params[matches[1]] = matches[2]
}
@@ -895,33 +893,27 @@ func (r *RuntimeService) UpdatePHPConfig(req request.PHPConfigUpdate) (err error
switch req.Scope {
case "params":
for key, value := range req.Params {
pattern := "^" + regexp.QuoteMeta(key) + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = key + " = " + value
if phpConfigLineMatchesKey(line, key) {
lines[i] = fmt.Sprintf("%s = %s", key, value)
}
}
case "disable_functions":
pattern := "^" + regexp.QuoteMeta("disable_functions") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = "disable_functions" + " = " + strings.Join(req.DisableFunctions, ",")
if phpConfigLineMatchesKey(line, "disable_functions") {
lines[i] = fmt.Sprintf("disable_functions = %s", strings.Join(req.DisableFunctions, ","))
}
case "upload_max_filesize":
pattern := "^" + regexp.QuoteMeta("post_max_size") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = "post_max_size" + " = " + req.UploadMaxSize
if phpConfigLineMatchesKey(line, "post_max_size") {
lines[i] = fmt.Sprintf("post_max_size = %s", req.UploadMaxSize)
}
patternUpload := "^" + regexp.QuoteMeta("upload_max_filesize") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(patternUpload, line); matched {
lines[i] = "upload_max_filesize" + " = " + req.UploadMaxSize
if phpConfigLineMatchesKey(line, "upload_max_filesize") {
lines[i] = fmt.Sprintf("upload_max_filesize = %s", req.UploadMaxSize)
}
case "max_execution_time":
pattern := "^" + regexp.QuoteMeta("max_execution_time") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = "max_execution_time" + " = " + req.MaxExecutionTime
if phpConfigLineMatchesKey(line, "max_execution_time") {
lines[i] = fmt.Sprintf("max_execution_time = %s", req.MaxExecutionTime)
}
patternInput := "^" + regexp.QuoteMeta("max_input_time") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(patternInput, line); matched {
lines[i] = "max_input_time" + " = " + req.MaxExecutionTime
if phpConfigLineMatchesKey(line, "max_input_time") {
lines[i] = fmt.Sprintf("max_input_time = %s", req.MaxExecutionTime)
}
}
}
@@ -960,6 +952,17 @@ func (r *RuntimeService) GetPHPConfigFile(req request.PHPFileReq) (*response.Fil
return &response.FileInfo{FileInfo: *info}, nil
}
func phpConfigLineMatchesKey(line, key string) bool {
trim := strings.TrimSpace(line)
idx := strings.Index(trim, "=")
if idx == -1 {
return false
}
currentKey := strings.TrimSpace(trim[:idx])
return currentKey == key
}
func (r *RuntimeService) UpdatePHPConfigFile(req request.PHPFileUpdate) error {
runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(req.ID))
if err != nil {
@@ -1137,6 +1140,7 @@ func (r *RuntimeService) GetPHPContainerConfig(id uint) (*request.PHPContainerCo
ExposedPorts: runtimeDTO.ExposedPorts,
Environments: runtimeDTO.Environments,
Volumes: runtimeDTO.Volumes,
ExtraHosts: runtimeDTO.ExtraHosts,
}
return res, nil
}
+47 -6
View File
@@ -12,7 +12,6 @@ import (
"os/exec"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
@@ -34,6 +33,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/pkg/errors"
"github.com/subosito/gotenv"
"gopkg.in/yaml.v3"
@@ -635,6 +635,16 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
for _, volume := range create.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target))
}
var extraHosts []interface{}
for _, host := range create.ExtraHosts {
extraHosts = append(extraHosts, fmt.Sprintf("%s:%s", host.Hostname, host.IP))
}
delete(serviceValue, "extraHosts")
if len(extraHosts) > 0 {
serviceValue["extra_hosts"] = extraHosts
}
serviceValue["volumes"] = volumes
break
}
@@ -842,6 +852,33 @@ func getDockerComposeVolumes(yml []byte) ([]request.Volume, error) {
return res, nil
}
func getDockerComposeExtraHosts(yml []byte) ([]request.ExtraHost, error) {
var (
composeProject docker.ComposeProject
err error
)
err = yaml.Unmarshal(yml, &composeProject)
if err != nil {
return nil, err
}
var res []request.ExtraHost
for _, service := range composeProject.Services {
for _, extraHosts := range service.ExtraHosts {
envArray := strings.Split(extraHosts, ":")
source := envArray[0]
target := ""
if len(envArray) > 1 {
target = envArray[1]
}
res = append(res, request.ExtraHost{
Hostname: source,
IP: target,
})
}
}
return res, nil
}
func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error {
errMap := make(map[string]interface{})
errMap["port"] = port
@@ -942,8 +979,10 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error {
for k, v := range envs {
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
if strings.Contains(k, "CONTAINER_PORT") {
r := regexp.MustCompile(`_(\d+)$`)
matches := r.FindStringSubmatch(k)
matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k)
if len(matches) < 2 {
return fmt.Errorf("invalid container port key: %s", k)
}
containerPort, err := strconv.Atoi(v)
if err != nil {
return err
@@ -953,9 +992,6 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error {
return err
}
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
if hostIP == "" {
hostIP = "0.0.0.0"
}
res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
@@ -982,6 +1018,11 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error {
return err
}
res.ExtraHosts, err = getDockerComposeExtraHosts(composeByte)
if err != nil {
return err
}
defaultVolumes := make(map[string]string)
switch runtime.Type {
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimePython, constant.RuntimeDotNet:
+18 -11
View File
@@ -21,9 +21,9 @@ import (
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/copier"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/pkg/errors"
"gorm.io/gorm"
)
@@ -307,19 +307,27 @@ func snapBaseData(snap snapHelper, targetDir string, withDockerConf bool) error
}
if global.IsMaster {
err = snap.FileOp.CopyFile("/etc/systemd/system/1panel-core.service", targetDir)
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-core.service"), err)
svcCorePath, _ := controller.GetServicePath("1panel-core")
err = snap.FileOp.CopyFile(svcCorePath, targetDir)
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", svcCorePath), err)
if err != nil {
return err
}
}
err = snap.FileOp.CopyFile("/etc/systemd/system/1panel-agent.service", targetDir)
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"), err)
svcAgentName, _ := controller.GetServicePath("1panel-agent")
err = snap.FileOp.CopyFile(svcAgentName, targetDir)
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", svcAgentName), err)
if err != nil {
return err
}
initScriptPath := path.Join(global.Dir.ResourceDir, "initscript")
if _, err := os.Stat(initScriptPath); err == nil {
err = snap.FileOp.CopyDirWithNewName(initScriptPath, targetDir, ".")
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", initScriptPath), err)
if err != nil {
return err
}
}
if withDockerConf {
if snap.FileOp.Stat(constant.DaemonJsonPath) {
err = snap.FileOp.CopyFile(constant.DaemonJsonPath, targetDir)
@@ -381,10 +389,9 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
if len(imageList) != 0 {
snap.Task.Log(strings.Join(imageList, " "))
snap.Task.Logf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz"))
std, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdoutBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz"))
if err != nil {
snap.Task.LogFailedWithErr(i18n.GetMsgByKey("SnapDockerSave"), errors.New(std))
return errors.New(std)
if err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz")); err != nil {
snap.Task.LogFailedWithErr(i18n.GetMsgByKey("SnapDockerSave"), err)
return err
}
snap.Task.LogSuccess(i18n.GetMsgByKey("SnapDockerSave"))
} else {
+49 -23
View File
@@ -17,11 +17,21 @@ import (
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/pkg/errors"
)
var (
svcBasePath, _ = controller.GetServicePath("")
svcCoreName, _ = controller.LoadServiceName("1panel-core")
selCoreName, _ = controller.SelectInitScript("1panel-core")
scriptCoreName, _ = controller.GetScriptName("1panel-core")
svcAgentName, _ = controller.LoadServiceName("1panel-agent")
selAgentName, _ = controller.SelectInitScript("1panel-agent")
scriptAgentName, _ = controller.GetScriptName("1panel-agent")
)
type snapRecoverHelper struct {
FileOp files.FileOp
Task *task.Task
@@ -226,7 +236,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
return
}
_ = os.RemoveAll(rootDir)
common.RestartService(true, true, true)
controller.RestartPanel(true, true, true)
}()
return nil
}
@@ -259,7 +269,14 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
if _, err := os.Stat(baseDir); err != nil {
_ = os.MkdirAll(baseDir, os.ModePerm)
}
initScriptPath := path.Join(global.Dir.ResourceDir, "initscript")
if _, err := os.Stat(initScriptPath); err == nil {
err = itemHelper.FileOp.CopyDirWithNewName(initScriptPath, baseDir, ".")
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", initScriptPath), err)
if err != nil {
return err
}
}
err := itemHelper.FileOp.CopyDirWithExclude(global.Dir.DataDir, rootDir, []string{"cache", "tmp"})
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", global.Dir.DataDir), err)
if err != nil {
@@ -294,8 +311,9 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
if err != nil {
return err
}
err = itemHelper.FileOp.CopyFile("/etc/systemd/system/1panel-core.service", baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-core.service"), err)
svcCorePath, _ := controller.GetServicePath("1panel-core")
err = itemHelper.FileOp.CopyFile(svcCorePath, baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", svcCorePath), err)
if err != nil {
return err
}
@@ -305,8 +323,9 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
if err != nil {
return err
}
err = itemHelper.FileOp.CopyFile("/etc/systemd/system/1panel-agent.service", baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"), err)
svcAgentPath, _ := controller.GetServicePath("1panel-agent")
err = itemHelper.FileOp.CopyFile(svcAgentPath, baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", svcAgentPath), err)
if err != nil {
return err
}
@@ -352,10 +371,9 @@ func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log(i18n.GetMsgByKey("RecoverAppEmpty"))
return nil
}
std, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdoutBashCf("docker load < %s", path.Join(src, "images.tar.gz"))
if err != nil {
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverAppImage"), errors.New(std))
return fmt.Errorf("docker load images failed, err: %v", err)
if err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunBashCf("docker load < %s", path.Join(src, "images.tar.gz")); err != nil {
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverAppImage"), err)
return fmt.Errorf("docker load images failed, %v", err)
}
itemHelper.Task.LogSuccess(i18n.GetMsgByKey("RecoverAppImage"))
return nil
@@ -364,7 +382,6 @@ func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 6 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
if global.IsMaster {
err := itemHelper.FileOp.CopyFile(path.Join(src, "1pctl"), "/usr/local/bin")
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/usr/local/bin/1pctl"), err)
@@ -376,10 +393,15 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
if err != nil {
return err
}
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel-core.service"), "/etc/systemd/system")
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-core.service"), err)
svcCoreName, _ := controller.LoadServiceName("1panel-core")
err = itemHelper.FileOp.CopyFile(path.Join(src, svcCoreName), svcBasePath)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", path.Join(svcBasePath, svcCoreName)), err)
if err != nil {
return err
err = itemHelper.FileOp.CopyFile(path.Join(src, selCoreName), path.Join(svcBasePath, scriptCoreName))
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", path.Join(svcBasePath, scriptCoreName)), err)
if err != nil {
return err
}
}
}
err := itemHelper.FileOp.CopyFile(path.Join(src, "1panel-agent"), "/usr/local/bin")
@@ -387,10 +409,15 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
if err != nil {
return err
}
err = itemHelper.FileOp.CopyFile(path.Join(src, "1panel-agent.service"), "/etc/systemd/system")
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"), err)
svcAgentName, _ := controller.LoadServiceName("1panel-agent")
err = itemHelper.FileOp.CopyFile(path.Join(src, svcAgentName), svcBasePath)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", path.Join(svcBasePath, svcAgentName)), err)
if err != nil {
return err
err = itemHelper.FileOp.CopyFile(path.Join(src, selAgentName), path.Join(svcBasePath, scriptAgentName))
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", path.Join(svcBasePath, scriptAgentName)), err)
if err != nil {
return err
}
}
if !itemHelper.FileOp.Stat(path.Join(src, "daemon.json")) {
@@ -404,8 +431,8 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
}
}
if err := restartDocker(); err != nil {
return err
if err := controller.HandleRestart("docker"); err != nil {
return fmt.Errorf("failed to restart Docker: %v", err)
}
return nil
}
@@ -435,9 +462,8 @@ func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
continue
}
upCmd := fmt.Sprintf("docker compose -f %s up -d", pathItem)
stdout, err := cmd.RunDefaultWithStdoutBashC(upCmd)
if err != nil {
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverCompose"), errors.New(stdout))
if err := cmd.RunDefaultBashC(upCmd); err != nil {
itemHelper.Task.LogFailedWithErr(i18n.GetMsgByKey("RecoverCompose"), err)
continue
}
itemHelper.Task.LogSuccess(i18n.GetWithName("RecoverComposeItem", pathItem))
+4 -4
View File
@@ -61,17 +61,17 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
)
if global.IsMaster {
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-core.service"),
i18n.GetWithName("SnapCopy", path.Join(svcBasePath, svcCoreName)),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1panel-core.service"), "/etc/systemd/system")
return FileOp.CopyFile(path.Join(baseDir, svcCoreName), svcBasePath)
},
nil,
)
}
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/systemd/system/1panel-agent.service"),
i18n.GetWithName("SnapCopy", path.Join(svcBasePath, svcAgentName)),
func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "1panel-agent.service"), "/etc/systemd/system")
return FileOp.CopyFile(path.Join(baseDir, svcAgentName), svcBasePath)
},
nil,
)
+44 -39
View File
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"net"
"os"
"os/user"
"path"
@@ -13,6 +14,7 @@ import (
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/copier"
csvexport "github.com/1Panel-dev/1Panel/agent/utils/csv_export"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
@@ -27,7 +29,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/systemctl"
"github.com/pkg/errors"
)
@@ -74,22 +75,18 @@ func (u *SSHService) GetSSHInfo() (*dto.SSHInfo, error) {
data.IsExist = false
data.Message = err.Error()
} else {
active, err := systemctl.IsActive(serviceName)
active, err := controller.CheckActive(serviceName)
data.IsActive = active
if !active && err != nil {
data.Message = err.Error()
}
}
out, err := systemctl.RunSystemCtl("is-enabled", serviceName)
enable, err := controller.CheckEnable(serviceName)
if err != nil {
data.AutoStart = false
} else {
if out == "alias\n" {
data.AutoStart, _ = systemctl.IsEnable("ssh")
} else {
data.AutoStart = out == "enabled\n"
}
data.AutoStart = enable
}
sshConf, err := os.ReadFile(sshPath)
@@ -139,29 +136,20 @@ func (u *SSHService) OperateSSH(operation string) error {
if err != nil {
return err
}
sudo := cmd.SudoHandleCmd()
if operation == "enable" || operation == "disable" {
serviceName += ".service"
}
if operation == "stop" {
isSocketActive, _ := systemctl.IsActive(serviceName + ".socket")
isSocketActive, _ := controller.CheckActive(serviceName + ".socket")
if isSocketActive {
std, err := cmd.RunDefaultWithStdoutBashCf("%s systemctl stop %s", sudo, serviceName+".socket")
if err != nil {
global.LOG.Errorf("handle systemctl stop %s.socket failed, err: %v", serviceName, std)
if err := controller.HandleStop(serviceName + ".socket"); err != nil {
global.LOG.Errorf("handle stop %s.socket failed, err: %v", serviceName, err)
}
}
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s systemctl %s %s", sudo, operation, serviceName)
if err != nil {
if strings.Contains(stdout, "alias name or linked unit file") {
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s systemctl %s ssh", sudo, operation)
if err != nil {
return fmt.Errorf("%s ssh(alias name or linked unit file) failed, stdout: %s, err: %v", operation, stdout, err)
}
}
return fmt.Errorf("%s %s failed, stdout: %s, err: %v", operation, serviceName, stdout, err)
if err := controller.Handle(operation, serviceName); err != nil {
return fmt.Errorf("%s %s failed, err: %v", operation, serviceName, err)
}
return nil
}
@@ -190,7 +178,7 @@ func (u *SSHService) Update(req dto.SSHUpdate) error {
if req.Key == "Port" {
stdout, _ := cmd.RunDefaultWithStdoutBashCf("%s getenforce", sudo)
if stdout == "Enforcing\n" {
_, _ = cmd.RunDefaultWithStdoutBashCf("%s semanage port -a -t ssh_port_t -p tcp %s", sudo, req.NewValue)
_ = cmd.RunDefaultBashCf("%s semanage port -a -t ssh_port_t -p tcp %s", sudo, req.NewValue)
}
ruleItem := dto.PortRuleUpdate{
@@ -220,7 +208,7 @@ func (u *SSHService) Update(req dto.SSHUpdate) error {
}
}
_, _ = cmd.RunDefaultWithStdoutBashCf("%s systemctl restart %s", sudo, serviceName)
_ = controller.HandleRestart(serviceName)
return nil
}
@@ -306,15 +294,13 @@ func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
if len(req.PassPhrase) != 0 {
command = fmt.Sprintf("ssh-keygen -t %s -P %s -f %s/.ssh/%s | echo y", req.EncryptionMode, req.PassPhrase, currentUser.HomeDir, req.Name)
}
stdout, err := cmd.RunDefaultWithStdoutBashC(command)
if err != nil {
return fmt.Errorf("generate failed, err: %v, message: %s", err, stdout)
if err := cmd.RunDefaultBashC(command); err != nil {
return fmt.Errorf("generate failed, %v", err)
}
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("cat %s >> %s", publicPath, authFilePath)
if err != nil {
return fmt.Errorf("generate failed, err: %v, message: %s", err, stdout)
if err := cmd.RunDefaultBashCf("cat %s >> %s", publicPath, authFilePath); err != nil {
return fmt.Errorf("generate failed, %v", err)
}
cert.PrivateKeyPath = privatePath
@@ -599,8 +585,7 @@ func (u *SSHService) UpdateByFile(req dto.SettingUpdate) error {
if err != nil {
return err
}
sudo := cmd.SudoHandleCmd()
_, _ = cmd.RunDefaultWithStdoutBashCf("%s systemctl restart %s", sudo, serviceName)
_ = controller.HandleRestart(serviceName)
return nil
}
@@ -772,24 +757,24 @@ func loadFailedSecureDatas(line string) dto.SSHHistory {
}
func checkIsStandard(item dto.SSHHistory) bool {
if len(item.Address) == 0 {
if len(item.Address) == 0 || net.ParseIP(item.Address) == nil {
return false
}
portItem, _ := strconv.Atoi(item.Port)
return portItem != 0
return portItem > 0 && portItem < 65536
}
func handleGunzip(path string) error {
if _, err := cmd.RunDefaultWithStdoutBashCf("gunzip %s", path); err != nil {
if err := cmd.RunDefaultBashCf("gunzip %s", path); err != nil {
return err
}
return nil
}
func loadServiceName() (string, error) {
if exist, _ := systemctl.IsExist("sshd"); exist {
if exist, _ := controller.CheckExist("sshd"); exist {
return "sshd", nil
} else if exist, _ := systemctl.IsExist("ssh"); exist {
} else if exist, _ := controller.CheckExist("ssh"); exist {
return "ssh", nil
}
return "", errors.New("The ssh or sshd service is unavailable")
@@ -867,7 +852,7 @@ func updateLocalConn(newPort uint) error {
}
func updateSSHSocketFile(newPort string) error {
active, _ := systemctl.IsActive("ssh.socket")
active, _ := controller.CheckActive("ssh.socket")
if !active {
return nil
}
@@ -898,6 +883,26 @@ func updateSSHSocketFile(newPort string) error {
if _, err = fileItem.WriteString(strings.Join(lines, "\n")); err != nil {
return err
}
_ = cmd.RunDefaultBashC("systemctl daemon-reload && systemctl restart ssh.socket")
_ = controller.Reload()
_ = controller.HandleRestart("ssh.socket")
return nil
}
func loadSSHPort() string {
port := "22"
sshConf, err := os.ReadFile(sshPath)
if err != nil {
return port
}
lines := strings.Split(string(sshConf), "\n")
for _, line := range lines {
if strings.HasPrefix(line, "Port ") {
portStr := strings.ReplaceAll(line, "Port ", "")
portItem, _ := strconv.Atoi(portStr)
if portItem > 0 && portItem < 65535 {
return portStr
}
}
}
return port
}
+99 -35
View File
@@ -2,6 +2,15 @@ package service
import (
"fmt"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"github.com/subosito/gotenv"
"gopkg.in/yaml.v3"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model"
@@ -12,13 +21,9 @@ import (
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/subosito/gotenv"
"gopkg.in/yaml.v3"
"path"
"regexp"
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/agent/utils/re"
)
type TensorRTLLMService struct{}
@@ -52,13 +57,15 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR
serverDTO.ModelDir = envs["MODEL_PATH"]
serverDTO.Dir = path.Join(global.Dir.TensorRTLLMDir, item.Name)
serverDTO.Image = envs["IMAGE"]
serverDTO.Command = envs["COMMAND"]
serverDTO.Command = getCommand(item.Env)
for k, v := range envs {
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
if strings.Contains(k, "CONTAINER_PORT") {
r := regexp.MustCompile(`_(\d+)$`)
matches := r.FindStringSubmatch(k)
matches := re.GetRegex(re.TrailingDigitsPattern).FindStringSubmatch(k)
if len(matches) < 2 {
continue
}
containerPort, err := strconv.Atoi(v)
if err != nil {
continue
@@ -94,7 +101,7 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR
}
var defaultVolumes = map[string]string{
"${MODEL_PATH}": "/models",
"${MODEL_PATH}": "${MODEL_PATH}",
}
for _, volume := range volumes {
exist := false
@@ -159,16 +166,15 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e
delete(serviceValue, "environment")
var environments []interface{}
environments = append(environments, fmt.Sprintf("MODEL_PATH=%s", create.ModelDir))
for _, e := range create.Environments {
environments = append(environments, fmt.Sprintf("%s=%s", e.Key, e.Value))
}
if len(environments) > 0 {
serviceValue["environment"] = environments
}
serviceValue["environment"] = environments
var volumes []interface{}
var defaultVolumes = map[string]string{
"${MODEL_PATH}": "/models",
"${MODEL_PATH}": "${MODEL_PATH}",
}
for k, v := range defaultVolumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", k, v))
@@ -188,23 +194,24 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e
}
func handleLLMEnv(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) gotenv.Env {
env := make(gotenv.Env)
env["CONTAINER_NAME"] = create.ContainerName
env["MODEL_PATH"] = create.ModelDir
env["VERSION"] = create.Version
env["IMAGE"] = create.Image
env["COMMAND"] = create.Command
envMap := make(gotenv.Env)
envMap["CONTAINER_NAME"] = create.ContainerName
envMap["MODEL_PATH"] = create.ModelDir
envMap["VERSION"] = create.Version
envMap["IMAGE"] = create.Image
envMap["COMMAND"] = create.Command
for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
env[containerPortStr] = strconv.Itoa(port.ContainerPort)
env[hostPortStr] = strconv.Itoa(port.HostPort)
env[hostIPStr] = port.HostIP
envMap[containerPortStr] = strconv.Itoa(port.ContainerPort)
envMap[hostPortStr] = strconv.Itoa(port.HostPort)
envMap[hostIPStr] = port.HostIP
}
envStr, _ := gotenv.Marshal(env)
orders := []string{"MODEL_PATH", "COMMAND"}
envStr, _ := env.MarshalWithOrder(envMap, orders)
llm.Env = envStr
return env
return envMap
}
func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error {
@@ -227,27 +234,34 @@ func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error {
}
tensorrtLLMDir := path.Join(global.Dir.TensorRTLLMDir, create.Name)
filesOP := files.NewFileOp()
if !filesOP.Stat(tensorrtLLMDir) {
_ = filesOP.CreateDir(tensorrtLLMDir, 0644)
filesOp := files.NewFileOp()
if !filesOp.Stat(tensorrtLLMDir) {
_ = filesOp.CreateDir(tensorrtLLMDir, 0644)
}
if create.ModelSpeedup {
if err := handleModelArchive(create.ModelType, create.ModelDir); err != nil {
return err
}
}
tensorrtLLM := &model.TensorRTLLM{
Name: create.Name,
ContainerName: create.ContainerName,
Status: constant.StatusStarting,
ModelType: create.ModelType,
ModelSpeedup: create.ModelSpeedup,
}
if err := handleLLMParams(tensorrtLLM, create); err != nil {
return err
}
env := handleLLMEnv(tensorrtLLM, create)
envMap := handleLLMEnv(tensorrtLLM, create)
llmDir := path.Join(global.Dir.TensorRTLLMDir, create.Name)
envPath := path.Join(llmDir, ".env")
if err := gotenv.Write(env, envPath); err != nil {
if err := env.WriteWithOrder(envMap, envPath, []string{"MODEL_PATH", "COMMAND"}); err != nil {
return err
}
dockerComposePath := path.Join(llmDir, "docker-compose.yml")
if err := filesOP.SaveFile(dockerComposePath, tensorrtLLM.DockerCompose, 0644); err != nil {
if err := filesOp.SaveFile(dockerComposePath, tensorrtLLM.DockerCompose, 0644); err != nil {
return err
}
tensorrtLLM.Status = constant.StatusStarting
@@ -269,18 +283,20 @@ func (t TensorRTLLMService) Update(req request.TensorRTLLMUpdate) error {
return err
}
}
tensorrtLLM.ModelType = req.ModelType
tensorrtLLM.ModelSpeedup = req.ModelSpeedup
tensorrtLLM.ContainerName = req.ContainerName
if err := handleLLMParams(tensorrtLLM, req.TensorRTLLMCreate); err != nil {
return err
}
env := handleLLMEnv(tensorrtLLM, req.TensorRTLLMCreate)
envStr, _ := gotenv.Marshal(env)
envMap := handleLLMEnv(tensorrtLLM, req.TensorRTLLMCreate)
envStr, _ := gotenv.Marshal(envMap)
tensorrtLLM.Env = envStr
llmDir := path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name)
envPath := path.Join(llmDir, ".env")
if err := gotenv.Write(env, envPath); err != nil {
if err := env.WriteWithOrder(envMap, envPath, []string{"MODEL_PATH", "COMMAND"}); err != nil {
return err
}
dockerComposePath := path.Join(llmDir, "docker-compose.yml")
@@ -381,3 +397,51 @@ func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM) error {
}
return tensorrtLLMRepo.Save(tensorrtLLM)
}
func findModelArchive(modelType string) (string, error) {
const baseDir = "/home/models"
prefix := fmt.Sprintf("FusionXplay_%s_Accelerator", modelType)
entries, err := os.ReadDir(baseDir)
if err != nil {
return "", fmt.Errorf("failed to read %s: %w", baseDir, err)
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
if strings.HasPrefix(name, prefix) && strings.HasSuffix(name, ".tar.gz") {
return filepath.Join(baseDir, name), nil
}
}
return "", fmt.Errorf("no FusionXplay_%s_Accelerator*.tar.gz found in /home/models", modelType)
}
func handleModelArchive(modelType string, modelDir string) error {
filePath, err := findModelArchive(modelType)
if err != nil {
return err
}
fileOp := files.NewFileOp()
if err = fileOp.TarGzExtractPro(filePath, modelDir, ""); err != nil {
return err
}
if err = fileOp.ChmodR(path.Join(modelDir, "fusionxpark_accelerator"), 0755, false); err != nil {
return err
}
return nil
}
func getCommand(envStr string) string {
lines := strings.Split(envStr, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "COMMAND=") {
return strings.TrimPrefix(line, "COMMAND=")
}
}
return ""
}
+48 -105
View File
@@ -14,7 +14,7 @@ import (
"os"
"path"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"syscall"
@@ -45,6 +45,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"golang.org/x/crypto/bcrypt"
)
@@ -61,6 +62,7 @@ type IWebsiteService interface {
DeleteWebsite(req request.WebsiteDelete) error
GetWebsite(id uint) (response.WebsiteDTO, error)
BatchOpWebsite(req request.BatchWebsiteOp) error
BatchSetGroup(req request.BatchWebsiteGroup) error
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
@@ -521,12 +523,32 @@ func (w WebsiteService) OpWebsite(req request.WebsiteOp) error {
return websiteRepo.Save(context.Background(), &website)
}
func (w WebsiteService) BatchSetGroup(req request.BatchWebsiteGroup) error {
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
for _, web := range websites {
web.WebsiteGroupID = req.GroupID
if err := websiteRepo.Save(context.Background(), &web); err != nil {
return err
}
}
return nil
}
func (w WebsiteService) BatchOpWebsite(req request.BatchWebsiteOp) error {
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("Status"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
if err != nil {
return err
}
sort.SliceStable(websites, func(i, j int) bool {
if websites[i].Type == constant.Subsite && websites[j].Type != constant.Subsite {
return true
}
if websites[i].Type != constant.Subsite && websites[j].Type == constant.Subsite {
return false
}
return false
})
opWebsiteTask := func(t *task.Task) error {
for _, web := range websites {
msg := fmt.Sprintf("%s %s", i18n.GetMsgByKey(req.Operate), web.PrimaryDomain)
@@ -1632,10 +1654,7 @@ func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermiss
}
absoluteIndexPath := GetSitePath(website, SiteIndexDir)
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(10 * time.Second))
if out, err := cmdMgr.RunWithStdoutBashCf("%s chown -R %s:%s %s", cmd.SudoHandleCmd(), req.User, req.Group, absoluteIndexPath); err != nil {
if out != "" {
return errors.New(out)
}
if err := cmdMgr.RunBashCf("%s chown -R %s:%s %s", cmd.SudoHandleCmd(), req.User, req.Group, absoluteIndexPath); err != nil {
return err
}
website.User = req.User
@@ -1730,19 +1749,28 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
location.UpdateDirective("proxy_pass", []string{req.ProxyPass})
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost})
location.ChangePath(req.Modifier, req.Match)
// Server Cache Settings
if req.Cache {
if err = openProxyCache(website); err != nil {
return
}
location.AddCache(req.CacheTime, req.CacheUnit, fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias), req.ServerCacheTime, req.ServerCacheUnit)
location.AddServerCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias), req.ServerCacheTime, req.ServerCacheUnit)
} else {
location.RemoveCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias))
location.RemoveServerCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias))
}
// Browser Cache Settings
if req.CacheTime != 0 {
location.AddBrowserCache(req.CacheTime, req.CacheUnit)
} else {
location.RemoveBrowserCache()
}
// Content Replace Settings
if len(req.Replaces) > 0 {
location.AddSubFilter(req.Replaces)
} else {
location.RemoveSubFilter()
}
// SSL Settings
if req.SNI {
location.UpdateDirective("proxy_ssl_server_name", []string{"on"})
if req.ProxySSLName != "" {
@@ -1751,6 +1779,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
} else {
location.UpdateDirective("proxy_ssl_server_name", []string{"off"})
}
// CORS Settings
if req.Cors {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", req.AllowOrigins, "always"})
if req.AllowMethods != "" {
@@ -1771,14 +1800,14 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
if req.Preflight {
location.AddCorsOption()
} else {
location.RemoveDirective("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
location.RemoveCorsOption()
}
} else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Origin"})
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"})
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"})
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Credentials"})
location.RemoveDirective("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
location.RemoveDirectiveByFullParams("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
}
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr("ErrUpdateBuWebsite", err)
@@ -1830,27 +1859,24 @@ func (w WebsiteService) GetProxyCache(id uint) (res response.NginxProxyCache, er
if len(params) == 0 {
return
}
zoneRegexp := regexp.MustCompile(`keys_zone=proxy_cache_zone_of_[\w.]+:(\d+)([kmgt]?)`)
sizeRegexp := regexp.MustCompile(`max_size=([0-9.]+)([kmgt]?)`)
inactiveRegexp := regexp.MustCompile(`inactive=(\d+)([smhd])`)
for _, param := range params {
if match, _ := regexp.MatchString(`keys_zone=proxy_cache_zone_of_[\w.]+:\d+[kmgt]?`, param); match {
matches := zoneRegexp.FindStringSubmatch(param)
if re.GetRegex(re.ProxyCacheZonePattern).MatchString(param) {
matches := re.GetRegex(re.ProxyCacheZonePattern).FindStringSubmatch(param)
if len(matches) > 0 {
res.ShareCache, _ = strconv.Atoi(matches[1])
res.ShareCacheUnit = matches[2]
}
}
if match, _ := regexp.MatchString(`max_size=\d+(\.\d+)?[kmgt]?`, param); match {
matches := sizeRegexp.FindStringSubmatch(param)
if re.GetRegex(re.ProxyCacheMaxSizeValidationPattern).MatchString(param) {
matches := re.GetRegex(re.ProxyCacheMaxSizePattern).FindStringSubmatch(param)
if len(matches) > 0 {
res.CacheLimit, _ = strconv.ParseFloat(matches[1], 64)
res.CacheLimitUnit = matches[2]
}
}
if match, _ := regexp.MatchString(`inactive=\d+[smhd]`, param); match {
matches := inactiveRegexp.FindStringSubmatch(param)
if re.GetRegex(re.ProxyCacheInactivePattern).MatchString(param) {
matches := re.GetRegex(re.ProxyCacheInactivePattern).FindStringSubmatch(param)
if len(matches) > 0 {
res.CacheExpire, _ = strconv.Atoi(matches[1])
res.CacheExpireUnit = matches[2]
@@ -2569,8 +2595,7 @@ func (w WebsiteService) GetAntiLeech(id uint) (*response.NginxAntiLeechRes, erro
}
if lDir.GetName() == "expires" {
res.Cache = true
re := regexp.MustCompile(`^(\d+)(\w+)$`)
matches := re.FindStringSubmatch(lDir.GetParameters()[0])
matches := re.GetRegex(re.NumberWordPattern).FindStringSubmatch(lDir.GetParameters()[0])
if matches == nil {
continue
}
@@ -3075,39 +3100,7 @@ func (w WebsiteService) GetLoadBalances(id uint) ([]dto.NginxUpstream, error) {
upstream.Algorithm = dName
}
}
var servers []dto.NginxUpstreamServer
for _, ups := range up.UpstreamServers {
server := dto.NginxUpstreamServer{
Server: ups.Address,
}
parameters := ups.Parameters
if weight, ok := parameters["weight"]; ok {
num, err := strconv.Atoi(weight)
if err == nil {
server.Weight = num
}
}
if maxFails, ok := parameters["max_fails"]; ok {
num, err := strconv.Atoi(maxFails)
if err == nil {
server.MaxFails = num
}
}
if failTimeout, ok := parameters["fail_timeout"]; ok {
server.FailTimeout = failTimeout
}
if maxConns, ok := parameters["max_conns"]; ok {
num, err := strconv.Atoi(maxConns)
if err == nil {
server.MaxConns = num
}
}
for _, flag := range ups.Flags {
server.Flag = flag
}
servers = append(servers, server)
}
upstream.Servers = servers
upstream.Servers = getNginxUpstreamServers(up.UpstreamServers)
}
}
res = append(res, upstream)
@@ -3141,33 +3134,7 @@ func (w WebsiteService) CreateLoadBalance(req request.WebsiteLBCreate) error {
if req.Algorithm != "default" {
upstream.UpdateDirective(req.Algorithm, []string{})
}
servers := make([]*components.UpstreamServer, 0)
for _, server := range req.Servers {
upstreamServer := &components.UpstreamServer{
Address: server.Server,
}
parameters := make(map[string]string)
if server.Weight > 0 {
parameters["weight"] = strconv.Itoa(server.Weight)
}
if server.MaxFails > 0 {
parameters["max_fails"] = strconv.Itoa(server.MaxFails)
}
if server.FailTimeout != "" {
parameters["fail_timeout"] = server.FailTimeout
}
if server.MaxConns > 0 {
parameters["max_conns"] = strconv.Itoa(server.MaxConns)
}
if server.Flag != "" {
upstreamServer.Flags = []string{server.Flag}
}
upstreamServer.Parameters = parameters
servers = append(servers, upstreamServer)
}
upstream.UpstreamServers = servers
upstream.UpstreamServers = parseUpstreamServers(req.Servers)
config.Block.Directives = append(config.Block.Directives, &upstream)
defer func() {
@@ -3226,31 +3193,7 @@ func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
if req.Algorithm != "default" {
up.UpdateDirective(req.Algorithm, []string{})
}
var servers []*components.UpstreamServer
for _, server := range req.Servers {
upstreamServer := &components.UpstreamServer{
Address: server.Server,
}
parameters := make(map[string]string)
if server.Weight > 0 {
parameters["weight"] = strconv.Itoa(server.Weight)
}
if server.MaxFails > 0 {
parameters["max_fails"] = strconv.Itoa(server.MaxFails)
}
if server.FailTimeout != "" {
parameters["fail_timeout"] = server.FailTimeout
}
if server.MaxConns > 0 {
parameters["max_conns"] = strconv.Itoa(server.MaxConns)
}
if server.Flag != "" {
upstreamServer.Flags = []string{server.Flag}
}
upstreamServer.Parameters = parameters
servers = append(servers, upstreamServer)
}
up.UpstreamServers = servers
up.UpstreamServers = parseUpstreamServers(req.Servers)
}
}
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
+1
View File
@@ -756,6 +756,7 @@ func (w WebsiteSSLService) ImportMasterSSL(create model.WebsiteSSL) error {
websiteSSL.Type = create.Type
websiteSSL.Organization = create.Organization
websiteSSL.MasterSSLID = create.ID
websiteSSL.Domains = create.Domains
if err := websiteSSLRepo.Save(websiteSSL); err != nil {
return err
}
+87 -2
View File
@@ -33,6 +33,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/1Panel-dev/1Panel/agent/utils/re"
"github.com/pkg/errors"
"gorm.io/gorm"
)
@@ -1032,8 +1033,7 @@ func checkIsLinkApp(website model.Website) bool {
func chownRootDir(path string) error {
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
_, err := cmdMgr.RunWithStdoutBashCf(`chown -R 1000:1000 "%s"`, path)
if err != nil {
if err := cmdMgr.RunBashCf(`chown -R 1000:1000 "%s"`, path); err != nil {
return err
}
return nil
@@ -1534,3 +1534,88 @@ func getServer(website model.Website) (*components.Server, error) {
server := servers[0]
return server, nil
}
func parseTimeString(input string) (int, string, error) {
input = strings.TrimSpace(input)
matches := re.GetRegex(re.DurationWithOptionalUnitPattern).FindStringSubmatch(input)
if len(matches) < 2 {
return 0, "", fmt.Errorf("invalid time format: %s", input)
}
value, err := strconv.Atoi(matches[1])
if err != nil {
return 0, "", fmt.Errorf("invalid number: %s", matches[1])
}
unit := matches[2]
if unit == "" {
unit = "s"
}
return value, unit, nil
}
func parseUpstreamServers(reqServers []dto.NginxUpstreamServer) []*components.UpstreamServer {
var servers []*components.UpstreamServer
for _, server := range reqServers {
upstreamServer := &components.UpstreamServer{
Address: server.Server,
}
parameters := make(map[string]string)
if server.Weight > 0 {
parameters["weight"] = strconv.Itoa(server.Weight)
}
if server.MaxFails > 0 {
parameters["max_fails"] = strconv.Itoa(server.MaxFails)
}
if server.FailTimeout > 0 {
parameters["fail_timeout"] = fmt.Sprintf("%d%s", server.FailTimeout, server.FailTimeoutUnit)
}
if server.MaxConns > 0 {
parameters["max_conns"] = strconv.Itoa(server.MaxConns)
}
if server.Flag != "" {
upstreamServer.Flags = []string{server.Flag}
}
upstreamServer.Parameters = parameters
servers = append(servers, upstreamServer)
}
return servers
}
func getNginxUpstreamServers(upstreamServers []*components.UpstreamServer) []dto.NginxUpstreamServer {
var servers []dto.NginxUpstreamServer
for _, ups := range upstreamServers {
server := dto.NginxUpstreamServer{
Server: ups.Address,
}
parameters := ups.Parameters
if weight, ok := parameters["weight"]; ok {
num, err := strconv.Atoi(weight)
if err == nil {
server.Weight = num
}
}
if maxFails, ok := parameters["max_fails"]; ok {
num, err := strconv.Atoi(maxFails)
if err == nil {
server.MaxFails = num
}
}
if failTimeout, ok := parameters["fail_timeout"]; ok {
server.FailTimeout, server.FailTimeoutUnit, _ = parseTimeString(failTimeout)
}
if maxConns, ok := parameters["max_conns"]; ok {
num, err := strconv.Atoi(maxConns)
if err == nil {
server.MaxConns = num
}
}
for _, flag := range ups.Flags {
server.Flag = flag
}
servers = append(servers, server)
}
return servers
}
+2
View File
@@ -65,6 +65,8 @@ const (
TaskSync = "TaskSync"
TaskBuild = "TaskBuild"
TaskPull = "TaskPull"
TaskImport = "TaskImport"
TaskExport = "TaskExport"
TaskCommit = "TaskCommit"
TaskPush = "TaskPush"
TaskClean = "TaskClean"
+1 -1
View File
@@ -14,7 +14,7 @@ services:
networks:
- 1panel-network
volumes:
- ${MODEL_PATH}:/models
- ${MODEL_PATH}:${MODEL_PATH}
ipc: host
ulimits:
memlock:
-4
View File
@@ -5,8 +5,4 @@ const (
Supervisor = "supervisor"
SupervisorConfigPath = "SupervisorConfigPath"
SupervisorServiceName = "SupervisorServiceName"
ClamServiceNameCentOs = "clamd@scan.service"
ClamServiceNameUbuntu = "clamav-daemon.service"
FreshClamService = "clamav-freshclam.service"
)
+1
View File
@@ -36,6 +36,7 @@ const (
StatusInstallErr = "InstallErr"
StatusUninstalling = "Uninstalling"
StatusWaitingRestart = "WaitingRestart"
StatusUnexecuted = "Unexecuted"
OrderDesc = "descending"
OrderAsc = "ascending"
+1
View File
@@ -47,6 +47,7 @@ type SystemDir struct {
McpDir string
ConvertLogDir string
TensorRTLLMDir string
FirewallDir string
}
type LogConfig struct {
+64 -64
View File
@@ -1,21 +1,20 @@
module github.com/1Panel-dev/1Panel/agent
go 1.24.0
toolchain go1.24.6
go 1.24.9
require (
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/aws/aws-sdk-go v1.55.0
github.com/compose-spec/compose-go/v2 v2.6.4
github.com/compose-spec/compose-go/v2 v2.9.0
github.com/creack/pty v1.1.24
github.com/docker/compose/v2 v2.37.0
github.com/docker/docker v28.3.3+incompatible
github.com/docker/go-connections v0.5.0
github.com/docker/cli v28.5.1+incompatible
github.com/docker/compose/v2 v2.40.2
github.com/docker/docker v28.5.1+incompatible
github.com/docker/go-connections v0.6.0
github.com/fsnotify/fsnotify v1.9.0
github.com/gin-gonic/gin v1.10.0
github.com/glebarez/sqlite v1.11.0
github.com/go-acme/lego/v4 v4.25.2
github.com/go-acme/lego/v4 v4.27.0
github.com/go-gormigrate/gormigrate/v2 v2.1.2
github.com/go-playground/validator/v10 v10.26.0
github.com/go-redis/redis v6.15.9+incompatible
@@ -23,12 +22,12 @@ require (
github.com/go-sql-driver/mysql v1.8.1
github.com/goh-chunlin/go-onedrive v1.1.1
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
github.com/jackc/pgx/v5 v5.6.0
github.com/jinzhu/copier v0.4.0
github.com/jinzhu/gorm v1.9.16
github.com/joho/godotenv v1.5.1
github.com/klauspost/compress v1.18.0
github.com/klauspost/compress v1.18.1
github.com/mholt/archiver/v4 v4.0.0-alpha.8
github.com/minio/minio-go/v7 v7.0.74
github.com/nicksnyder/go-i18n/v2 v2.4.0
@@ -42,17 +41,17 @@ require (
github.com/shirou/gopsutil/v4 v4.25.7
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.9.1
github.com/spf13/cobra v1.10.1
github.com/spf13/viper v1.19.0
github.com/subosito/gotenv v1.6.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.54
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19
github.com/upyun/go-sdk v2.1.0+incompatible
golang.org/x/crypto v0.40.0
golang.org/x/net v0.42.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sys v0.34.0
golang.org/x/text v0.27.0
golang.org/x/crypto v0.43.0
golang.org/x/net v0.46.0
golang.org/x/oauth2 v0.32.0
golang.org/x/sys v0.37.0
golang.org/x/text v0.30.0
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
@@ -66,61 +65,61 @@ require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.8 // indirect
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 // indirect
github.com/alibabacloud-go/debug v1.0.1 // indirect
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
github.com/alibabacloud-go/openapi-util v0.1.1 // indirect
github.com/alibabacloud-go/tea v1.3.9 // indirect
github.com/alibabacloud-go/tea v1.3.13 // indirect
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
github.com/aliyun/credentials-go v1.4.6 // indirect
github.com/aliyun/credentials-go v1.4.7 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/baidubce/bce-sdk-go v0.9.235 // indirect
github.com/baidubce/bce-sdk-go v0.9.248 // indirect
github.com/bodgit/plumbing v1.2.0 // indirect
github.com/bodgit/sevenzip v1.3.0 // indirect
github.com/bodgit/windows v1.0.0 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/connesc/cipherio v0.2.1 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/containerd/containerd/api v1.9.0 // indirect
github.com/containerd/containerd/v2 v2.1.1 // indirect
github.com/containerd/console v1.0.5 // indirect
github.com/containerd/containerd/api v1.10.0 // indirect
github.com/containerd/containerd/v2 v2.2.0 // indirect
github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v1.0.0-rc.1 // indirect
github.com/containerd/platforms v1.0.0-rc.2 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/buildx v0.24.0 // indirect
github.com/docker/cli v28.2.2+incompatible // indirect
github.com/docker/buildx v0.29.1 // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-acme/alidns-20150109/v4 v4.5.10 // indirect
github.com/go-acme/tencentclouddnspod v1.0.1208 // indirect
github.com/go-acme/alidns-20150109/v4 v4.6.1 // indirect
github.com/go-acme/tencentclouddnspod v1.1.10 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.9.8 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
@@ -134,8 +133,8 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.159 // indirect
github.com/in-toto/in-toto-golang v0.5.0 // indirect
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.172 // indirect
github.com/in-toto/in-toto-golang v0.9.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
@@ -143,7 +142,7 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kr/fs v0.1.0 // indirect
@@ -151,14 +150,15 @@ require (
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.9 // indirect
github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/miekg/dns v1.1.67 // indirect
github.com/miekg/dns v1.1.68 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/buildkit v0.22.0 // indirect
github.com/moby/buildkit v0.25.1 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/locker v1.0.1 // indirect
@@ -170,7 +170,7 @@ require (
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/namedotcom/go/v4 v4.0.2 // indirect
@@ -179,7 +179,7 @@ require (
github.com/nrdcg/freemyip v0.3.0 // indirect
github.com/nrdcg/goacmedns v0.2.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/namesilo v0.5.0 // indirect
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/ovh/go-ovh v1.9.0 // indirect
@@ -193,56 +193,56 @@ require (
github.com/rs/xid v1.5.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1210 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.41 // indirect
github.com/therootcompany/xz v1.0.1 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect
github.com/tonistiigi/fsutil v0.0.0-20250417144416-3f76f8130144 // indirect
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect
github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f // indirect
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/volcengine/volc-sdk-golang v1.0.216 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/volcengine/volc-sdk-golang v1.0.223 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.mongodb.org/mongo-driver v1.13.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/sdk v1.36.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.34.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.37.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
modernc.org/libc v1.66.1 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
+165 -126
View File
@@ -50,6 +50,7 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
@@ -78,9 +79,9 @@ github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC
github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.11/go.mod h1:wHxkgZT1ClZdcwEVP/pDgYK/9HucsnCfMipmJgCz4xY=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.8 h1:AL+nH363NJFS1NXIjCdmj5MOElgKEqgFeoq7vjje350=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.8/go.mod h1:d+z3ScRqc7PFzg4h9oqE3h8yunRZvAvU7u+iuPYEhpU=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.12/go.mod h1:f2wDpbM7hK9SvLIH09zSKVU1TsyemUNOqErMscMMl7c=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 h1:Q00FU3H94Ts0ZIHDmY+fYGgB7dV9D/YX6FGsgorQPgw=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13/go.mod h1:lxFGfobinVsQ49ntjpgWghXmIF0/Sm4+wvBJ1h5RtaE=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
@@ -101,22 +102,21 @@ github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/Ke
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
github.com/alibabacloud-go/tea v1.3.9 h1:bjgt1bvdY780vz/17iWNNtbXl4A77HWntWMeaUF3So0=
github.com/alibabacloud-go/tea v1.3.9/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea v1.3.12/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea v1.3.13 h1:WhGy6LIXaMbBM6VBYcsDCz6K/TPsT1Ri2hPmmZffZ94=
github.com/alibabacloud-go/tea v1.3.13/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/aliyun/credentials-go v1.4.6 h1:CG8rc/nxCNKfXbZWpWDzI9GjF4Tuu3Es14qT8Y0ClOk=
github.com/aliyun/credentials-go v1.4.6/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/aliyun/credentials-go v1.4.7 h1:T17dLqEtPUFvjDRRb5giVvLh6dFT8IcNFJJb7MeyCxw=
github.com/aliyun/credentials-go v1.4.7/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
@@ -135,8 +135,8 @@ github.com/aws/aws-sdk-go v1.55.0/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQ
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/baidubce/bce-sdk-go v0.9.235 h1:iAi+seH9w1Go2szFNzyGumahLGDsuYZ3i8hduX3qiM8=
github.com/baidubce/bce-sdk-go v0.9.235/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/baidubce/bce-sdk-go v0.9.248 h1:vB5OMuEC2xnO197M6OWUi24C8mYOZHKXT/8HuKQJUhU=
github.com/baidubce/bce-sdk-go v0.9.248/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -158,6 +158,8 @@ github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -172,7 +174,6 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -185,18 +186,23 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.6.4 h1:Gjv6x8eAhqwwWvoXIo0oZ4bDQBh0OMwdU7LUL9PDLiM=
github.com/compose-spec/compose-go/v2 v2.6.4/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
github.com/compose-spec/compose-go/v2 v2.9.0 h1:UHSv/QHlo6QJtrT4igF1rdORgIUhDo1gWuyJUoiNNIM=
github.com/compose-spec/compose-go/v2 v2.9.0/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE=
github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw=
github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoVrWGGJZcA=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/cgroups/v3 v3.1.0 h1:azxYVj+91ZgSnIBp2eI3k9y2iYQSR/ZQIgh9vKO+HSY=
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
github.com/containerd/containerd/v2 v2.1.1 h1:znnkm7Ajz8lg8BcIPMhc/9yjBRN3B+OkNKqKisKfwwM=
github.com/containerd/containerd/v2 v2.1.1/go.mod h1:zIfkQj4RIodclYQkX7GSSswSwgP8d/XxDOtOAoSDIGU=
github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
github.com/containerd/containerd/v2 v2.2.0 h1:K7TqcXy+LnFmZaui2DgHsnp2gAHhVNWYaHlx7HXfys8=
github.com/containerd/containerd/v2 v2.2.0/go.mod h1:YCMjKjA4ZA7egdHNi3/93bJR1+2oniYlnS+c0N62HdE=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -207,10 +213,12 @@ github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/nydus-snapshotter v0.15.0 h1:RqZRs1GPeM6T3wmuxJV9u+2Rg4YETVMwTmiDeX+iWC8=
github.com/containerd/nydus-snapshotter v0.15.0/go.mod h1:biq0ijpeZe0I5yZFSJyHzFSjjRZQ7P7y/OuHyd7hYOw=
github.com/containerd/nydus-snapshotter v0.15.2 h1:qsHI4M+Wwrf6Jr4eBqhNx8qh+YU0dSiJ+WPmcLFWNcg=
github.com/containerd/nydus-snapshotter v0.15.2/go.mod h1:FfwH2KBkNYoisK/e+KsmNr7xTU53DmnavQHMFOcXwfM=
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/stargz-snapshotter v0.16.3 h1:zbQMm8dRuPHEOD4OqAYGajJJUwCeUzt4j7w9Iaw58u4=
@@ -238,22 +246,24 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xb
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/buildx v0.24.0 h1:qiD+xktY+Fs3R79oz8M+7pbhip78qGLx6LBuVmyb+64=
github.com/docker/buildx v0.24.0/go.mod h1:vYkdBUBjFo/i5vUE0mkajGlk03gE0T/HaGXXhgIxo8E=
github.com/docker/cli v28.2.2+incompatible h1:qzx5BNUDFqlvyq4AHzdNB7gSyVTmU4cgsyN9SdInc1A=
github.com/docker/cli v28.2.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/compose/v2 v2.37.0 h1:R8Yik9ssiRz7T9BRfdOZy0xHDzOFPIJX40DrxzJ62dQ=
github.com/docker/compose/v2 v2.37.0/go.mod h1:twDoqUBFO2L5+vccJjkR6shQOH8C50V8AAQPxlkFr2Q=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/buildx v0.29.1 h1:58hxM5Z4mnNje3G5NKfULT9xCr8ooM8XFtlfUK9bKaA=
github.com/docker/buildx v0.29.1/go.mod h1:J4EFv6oxlPiV1MjO0VyJx2u5tLM7ImDEl9zyB8d4wPI=
github.com/docker/cli v28.5.1+incompatible h1:ESutzBALAD6qyCLqbQSEf1a/U8Ybms5agw59yGVc+yY=
github.com/docker/cli v28.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/compose/v2 v2.40.2 h1:h2bDBJkOuqmj93XvT2oI0ArPQonE0lGtWiILXdiXvbA=
github.com/docker/compose/v2 v2.40.2/go.mod h1:CbSJpKGw20LInVsPjglZ8z7Squ3OBQOD7Ux5nkjGfIU=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -282,7 +292,10 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DP
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@@ -309,12 +322,12 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-acme/alidns-20150109/v4 v4.5.10 h1:epLD0VaHR5XUpiM6mjm4MzQFICrk+zpuqDz2aO1/R/k=
github.com/go-acme/alidns-20150109/v4 v4.5.10/go.mod h1:qGRq8kD0xVgn82qRSQmhHwh/oWxKRjF4Db5OI4ScV5g=
github.com/go-acme/lego/v4 v4.25.2 h1:+D1Q+VnZrD+WJdlkgUEGHFFTcDrwGlE7q24IFtMmHDI=
github.com/go-acme/lego/v4 v4.25.2/go.mod h1:OORYyVNZPaNdIdVYCGSBNRNZDIjhQbPuFxwGDgWj/yM=
github.com/go-acme/tencentclouddnspod v1.0.1208 h1:xAVy1lmg2KcKKeYmFSBQUttwc1o1S++9QTjAotGC+BM=
github.com/go-acme/tencentclouddnspod v1.0.1208/go.mod h1:yxG02mkbbVd7lTb97nOn7oj09djhm7hAwxNQw4B9dpQ=
github.com/go-acme/alidns-20150109/v4 v4.6.1 h1:Dch3aWRcw4U62+jKPjPQN3iW3TPvgIywATbvHzojXeo=
github.com/go-acme/alidns-20150109/v4 v4.6.1/go.mod h1:RBcqBA5IvUWtlpjx6dC6EkPVyBNLQ+mR18XoaP38BFY=
github.com/go-acme/lego/v4 v4.27.0 h1:cIhWd7Uj4BNFLEF3IpwuMkukVVRs5qjlp4KdUGa75yU=
github.com/go-acme/lego/v4 v4.27.0/go.mod h1:9FfNZHZmg6hf5CWOp4Lzo4gU8aBEvqZvrwdkBboa+4g=
github.com/go-acme/tencentclouddnspod v1.1.10 h1:ERVJ4mc3cT4Nb3+n6H/c1AwZnChGBqLoymE0NVYscKI=
github.com/go-acme/tencentclouddnspod v1.1.10/go.mod h1:Bo/0YQJ/99FM+44HmCQkByuptX1tJsJ9V14MGV/2Qco=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -322,8 +335,8 @@ github.com/go-gormigrate/gormigrate/v2 v2.1.2 h1:F/d1hpHbRAvKezziV2CC5KUE82cVe9z
github.com/go-gormigrate/gormigrate/v2 v2.1.2/go.mod h1:9nHVX6z3FCMCQPA7PThGcA55t22yKQfK/Dnsf5i7hUo=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
@@ -334,8 +347,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@@ -351,6 +364,7 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
@@ -368,6 +382,8 @@ github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlnd
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.9.8 h1:5gMyLUeU1/6zl+WFfR1hN7D2kf+1/eRGa7DFtToiBvQ=
github.com/goccy/go-yaml v1.9.8/go.mod h1:JubOolP3gh0HpiBc4BLRD4YmjEjHAmIIB2aaXKkTfoE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
@@ -387,6 +403,7 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -448,8 +465,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
@@ -471,6 +488,8 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grafov/m3u8 v0.12.0/go.mod h1:nqzOkfBiZJENr52zTVd/Dcl03yzphIMbJqkXGu+u080=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
@@ -514,13 +533,13 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.159 h1:6LZysc4iyO4cHB1aJsRklWfSEJr8CEhW7BmcM0SkYcU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.159/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.172 h1:68VUVbLKwBxPh8tjCXwnLO/d8/thdZ+ExpxdFMEdK5A=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.172/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY=
github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1GdHMCq8+WPxw8/BE=
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
@@ -560,8 +579,9 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 h1:9Nu54bhS/H/Kgo2/7xNSUuC5G28VR8ljfrLKU2G4IjU=
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12/go.mod h1:TBzl5BIHNXfS9+C35ZyJaklL7mLDbgUkcgXzSLa8Tk0=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -575,6 +595,8 @@ github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@@ -598,6 +620,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
@@ -613,12 +636,15 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
@@ -635,8 +661,8 @@ github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60V
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/miekg/dns v1.1.67 h1:kg0EHj0G4bfT5/oOys6HhZw4vmMlnoZ+gDu8tJ/AlI0=
github.com/miekg/dns v1.1.67/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
@@ -656,8 +682,8 @@ github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.22.0 h1:aWN06w1YGSVN1XfeZbj2ZbgY+zi5xDAjEFI8Cy9fTjA=
github.com/moby/buildkit v0.22.0/go.mod h1:j4pP5hxiTWcz7xuTK2cyxQislHl/N2WWHzOy43DlLJw=
github.com/moby/buildkit v0.25.1 h1:j7IlVkeNbEo+ZLoxdudYCHpmTsbwKvhgc/6UJ/mY/o8=
github.com/moby/buildkit v0.25.1/go.mod h1:phM8sdqnvgK2y1dPDnbwI6veUCXHOZ6KFSl6E164tkc=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
@@ -687,6 +713,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
@@ -718,10 +746,8 @@ github.com/nrdcg/goacmedns v0.2.0 h1:ADMbThobzEMnr6kg2ohs4KGa3LFqmgiBA22/6jUWJR0
github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg=
github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk=
github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc=
github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
github.com/nrdcg/namesilo v0.5.0 h1:6QNxT/XxE+f5B+7QlfWorthNzOzcGlBLRQxqi6YeBrE=
github.com/nrdcg/namesilo v0.5.0/go.mod h1:4UkwlwQfDt74kSGmhLaDylnBrD94IfflnpoEaj6T2qw=
github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A=
github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -789,12 +815,14 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
@@ -802,6 +830,7 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
@@ -810,6 +839,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
github.com/qiniu/go-sdk/v7 v7.21.1 h1:D/IjVOlg5pTw0jeDjqTo6H5QM73Obb1AYfPOHmIFN+Q=
github.com/qiniu/go-sdk/v7 v7.21.1/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLOdp6yMpco=
@@ -838,13 +868,16 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs=
github.com/secure-systems-lab/go-securesystemslib v0.6.0 h1:T65atpAVCJQK14UA57LMdZGpHi4QYSH/9FZyNGqMYIA=
github.com/secure-systems-lab/go-securesystemslib v0.6.0/go.mod h1:8Mtpo9JKks/qhPG4HGZ2LGMvrPbzuxwfz/f/zLfEWkk=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM=
github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -859,16 +892,17 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spdx/tools-golang v0.5.3 h1:ialnHeEYUC4+hkm5vJm4qz2x+oEJbS0mAMFrNXdQraY=
github.com/spdx/tools-golang v0.5.3/go.mod h1:/ETOahiAo96Ob0/RAIBmFZw6XN0yTnyr/uFZm2NTMhI=
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@@ -886,17 +920,17 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1208/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1210 h1:waSk2KyI2VvXtR+XQJm0v1lWfgbJg51iSWJh4hWnyeo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1210/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.10/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.41 h1:XQDGrLX6v4McMP+2myhgQcy5JaPqSgwpLM1qa7ngUII=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.41/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0=
github.com/tencentyun/cos-go-sdk-v5 v0.7.54 h1:FRamEhNBbSeggyYfWfzFejTLftgbICocSYFk4PKTSV4=
github.com/tencentyun/cos-go-sdk-v5 v0.7.54/go.mod h1:UN+VdbCl1hg+kKi5RXqZgaP+Boqfmk+D04GRc4XFk70=
@@ -915,10 +949,10 @@ github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19 h1:ZCmSnT6CLGh
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19/go.mod h1:SXTY+QvI+KTTKXQdg0zZ7nx0u94QWh8ZAwBQYsW9cqk=
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4=
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=
github.com/tonistiigi/fsutil v0.0.0-20250417144416-3f76f8130144 h1:k9tdF32oJYwtjzMx+D26M6eYiCaAPdJ7tyN7tF1oU5Q=
github.com/tonistiigi/fsutil v0.0.0-20250417144416-3f76f8130144/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=
github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f h1:MoxeMfHAe5Qj/ySSBfL8A7l1V+hxuluj8owsIEEZipI=
github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98=
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 h1:2f304B10LaZdB8kkVEaoXvAMVan2tl9AiK4G0odjQtE=
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw=
@@ -936,20 +970,13 @@ github.com/upyun/go-sdk v2.1.0+incompatible/go.mod h1:eu3F5Uz4b9ZE5bE5QsCL6mgSNW
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/volcengine/volc-sdk-golang v1.0.216 h1:+wAq8RvxpGECveRJaAXZFpzrZoQ33WjMuRyd9iY2Oc0=
github.com/volcengine/volc-sdk-golang v1.0.216/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=
github.com/volcengine/volc-sdk-golang v1.0.223 h1:1EEK6VOUaA2Tu0VBD4VC5iSTTFag+KuNo+Vix469Tz4=
github.com/volcengine/volc-sdk-golang v1.0.223/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
@@ -980,28 +1007,28 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0 h1:4BZHA+B1wXEQoGNHxW8mURaLhcdGwvRnmhGbm+odRbc=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0/go.mod h1:3qi2EEwMgB4xnKgPLqsDP3j9qxnHDZeHsnAxfjQqTko=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 h1:0tY123n7CdWMem7MOVdKOt0YfshufLCwfE5Bob+hQuM=
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 h1:FZ6ei8GFW7kyPYdxJaV2rgI6M+4tvZzhYsQ2wgyVC08=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0/go.mod h1:MdEu/mC6j3D+tTEfvI15b5Ci2Fn7NneJ71YMoiS3tpI=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
@@ -1016,6 +1043,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU=
go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
@@ -1052,8 +1081,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1097,8 +1126,10 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1155,8 +1186,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1164,8 +1195,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1182,8 +1213,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1246,9 +1277,11 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1261,8 +1294,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1277,8 +1310,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1296,15 +1329,15 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1359,14 +1392,18 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -1425,10 +1462,10 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4=
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ=
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1446,8 +1483,10 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1462,8 +1501,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+13 -1
View File
@@ -36,6 +36,7 @@ Failed: 'Failed'
SystemRestart: 'Task interrupted due to system restart'
ErrGroupIsDefault: 'Default group, cannot be deleted'
ErrGroupIsInWebsiteUse: 'The group is being used by another website and cannot be deleted.'
Decrypt: "Decrypt"
#backup
Localhost: 'Local Machine'
@@ -78,7 +79,7 @@ ErrAppWarn: 'Abnormal status, please check the log'
ErrAppParamKey: 'Parameter {{ .name }} field is abnormal'
ErrAppUpgrade: 'Application {{ .name }} upgrade failed {{ .err }}'
AppRecover: 'Rollback application {{ .name }}'
PullImageStart: 'Start pulling image {{ .name }}'
PullImageStart: 'Start pulling image [{{ .name }}]'
PullImageSuccess: 'Image pull successful'
AppStoreIsLastVersion: 'The App Store is already the latest version'
AppStoreSyncSuccess: 'App Store synchronization successful'
@@ -146,7 +147,13 @@ ErrRuntimeNoPort: "The runtime environment is not set with a port, please edit t
Status: 'Status'
start: 'Start'
stop: 'Stop'
restart: 'Restart'
kill: 'Force Stop'
pause: 'Pause'
unpause: 'Resume'
remove: 'Delete'
delete: 'Delete'
ErrDefaultWebsite: 'Default website has been set, please cancel it before setting!'
#ssl
ErrSSLCannotDelete: 'The {{ .name }} certificate is being used by a website and cannot be deleted'
@@ -205,6 +212,7 @@ ImageRemoveHelper: "Deleted image {{ .name }}, freeing {{ .size }} disk space"
BuildCache: "Build cache"
Volume: "Storage volume"
Network: "Network"
PruneStart: "Cleaning in progress, please wait..."
#runtime
ErrFileNotExist: '{{ .detail }} file does not exist! Please check the integrity of the source file!'
@@ -243,6 +251,8 @@ IgnoreUploadErr: "Upload failed, error: {{ .detail }}, ignoring this error..."
LoadBackupFailed: "Failed to get backup account connection, error: {{ .detail }}"
InExecuting: "The current task is being executed, please do not repeat the execution!"
NoSuchResource: "No backup content found in the database, skipping..."
CleanLog: "Clean Log",
CleanLogByName: "Clean {{.name}} Log"
#toolbox
ErrNotExistUser: 'The current user does not exist, please modify and try again!'
@@ -342,6 +352,8 @@ TaskBuild: 'Build'
TaskPush: 'Push'
TaskClean: "Cleanup"
TaskHandle: 'Execute'
TaskImport: "Import"
TaskExport: "Export"
Website: 'Website'
App: 'Application'
Runtime: 'Runtime environment'
+13 -1
View File
@@ -36,6 +36,7 @@ Failed: 'Error'
SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema'
ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar'
ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.'
Decrypt: "Descifrar"
#backup
ErrBackupInUsed: 'La cuenta de respaldo está siendo utilizada en una tarea programada y no se puede eliminar.'
@@ -78,7 +79,7 @@ ErrAppWarn: 'Estado anómalo, revise el log'
ErrAppParamKey: 'El campo de parámetro {{ .name }} es anómalo'
ErrAppUpgrade: 'La actualización de la aplicación {{ .name }} falló {{ .err }}'
AppRecover: 'Revertir la aplicación {{ .name }}'
PullImageStart: 'Iniciar descarga de la imagen {{ .name }}'
PullImageStart: 'Iniciar descarga de la imagen [{{ .name }}]'
PullImageSuccess: 'Descarga de imagen exitosa'
AppStoreIsLastVersion: 'La tienda de aplicaciones ya está en la última versión'
AppStoreSyncSuccess: 'Sincronización de la tienda de aplicaciones exitosa'
@@ -145,7 +146,13 @@ ErrRuntimeNoPort: "El entorno de ejecución no tiene configurado un puerto, edí
Status: 'Estado'
start: 'Iniciar'
stop: 'Detener'
restart: 'Reiniciar'
kill: 'Detener Forzosamente'
pause: 'Pausar'
unpause: 'Reanudar'
remove: 'Eliminar'
delete: 'Eliminar'
ErrDefaultWebsite: 'El sitio web predeterminado ya está configurado, ¡cancélelo antes de configurar!'
#ssl
ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse'
@@ -204,6 +211,7 @@ ImageRemoveHelper: "Imagen {{ .name }} eliminada, liberando {{ .size }} de espac
BuildCache: "Caché de compilación"
Volume: "Volumen de almacenamiento"
Network: "Red"
PruneStart: "Limpiando en progreso, por favor espere..."
#runtime
ErrFileNotExist: 'El archivo {{ .detail }} no existe, ¡verifique la integridad!'
@@ -242,6 +250,8 @@ Upload: "Subir"
LoadBackupFailed: "Error al obtener la conexión de la cuenta de respaldo, error: {{ .detail }}"
InExecuting: "La tarea actual se está ejecutando, por favor no la repita"
NoSuchResource: "No se encontraron contenidos de respaldo en la base de datos, omitiendo..."
CleanLog: "Limpiar registro"
CleanLogByName: "Limpiar registro de {{.name}}"
#toolbox
ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo'
@@ -340,6 +350,8 @@ TaskCommit: 'Commit'
TaskBuild: 'Construir'
TaskPush: 'Subir'
TaskHandle: 'Ejecutar'
TaskImport: "Importar"
TaskExport: "Exportar"
Website: 'Sitio web'
App: 'Aplicación'
Runtime: 'Entorno de ejecución'
+13 -1
View File
@@ -35,6 +35,7 @@ Failed: '失敗'
SystemRestart: 'システムの再起動によりタスクが中断されました'
ErrGroupIsDefault: 'デフォルト グループ、削除できません'
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
Decrypt: "復号化"
#backup
Localhost: 'ローカルマシン'
@@ -77,7 +78,7 @@ ErrAppWarn: '異常な状態です。ログを確認してください'
ErrAppParamKey: 'パラメータ {{ .name }} フィールドが異常です'
ErrAppUpgrade: 'アプリケーション {{ .name }} のアップグレードに失敗しました {{ .err }}'
AppRecover: 'アプリケーション {{ .name }} をロールバックします'
PullImageStart: "イメージ {{ .name }} のプルを開始します"
PullImageStart: "イメージ [{{ .name }}] のプルを開始します"
PullImageSuccess: 'イメージのプルが成功しました'
AppStoreIsLastVersion: 'App Store はすでに最新バージョンです'
AppStoreSyncSuccess: 'App Store の同期が成功しました'
@@ -145,7 +146,13 @@ ErrRuntimeNoPort: "ランタイム環境にポートが設定されていませ
Status: 'ステータス'
start: '開始'
stop: '停止'
restart: '再起動'
kill: '強制停止'
pause: '一時停止'
unpause: '再開'
remove: '削除'
delete: '削除'
ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!'
#ssl
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'
@@ -204,6 +211,7 @@ ImageRemoveHelper: "イメージ{{ .name }}を削除し、{{ .size }}のディ
BuildCache: "ビルドキャッシュ"
Volume: "ストレージボリューム"
Network: "ネットワーク"
PruneStart: "クリーンアップ中、しばらくお待ちください..."
#runtime
ErrFileNotExist: '{{ .detail }} ファイルが存在しません。ソース ファイルの整合性を確認してください。'
@@ -242,6 +250,8 @@ IgnoreUploadErr: "アップロード失敗、エラー: {{ .detail }}、この
LoadBackupFailed: "バックアップアカウントの接続取得に失敗、エラー: {{ .detail }}"
InExecuting: "現在のタスクは実行中です。重複して実行しないでください!"
NoSuchResource: "データベースにバックアップ内容が見つかりませんでした。スキップします..."
CleanLog: "ログをクリーン"
CleanLogByName: "{{.name}} のログをクリーン"
#toolbox
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
@@ -341,6 +351,8 @@ TaskBuild: 'ビルド'
TaskPush: 'プッシュ'
TaskClean: "クリーンアップ"
TaskHandle: '実行'
TaskImport: "インポート"
TaskExport: "エクスポート"
Website: 'ウェブサイト'
App: 'アプリケーション'
Runtime: 'ランタイム環境'
+13 -1
View File
@@ -36,6 +36,7 @@ Failed: '실패했습니다'
SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다'
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
Decrypt: "복호화"
#지원
Localhost: '로컬 머신'
@@ -78,7 +79,7 @@ ErrAppWarn: '비정상적인 상태입니다. 로그를 확인해 주세요.'
ErrAppParamKey: '매개변수 {{ .name }} 필드가 비정상입니다.'
ErrAppUpgrade: '애플리케이션 {{ .name }} 업그레이드에 실패했습니다 {{ .err }}'
AppRecover: '롤백 애플리케이션 {{ .name }}'
PullImageStart: '이미지 {{ .name }} 가져오기 시작'
PullImageStart: '이미지 [{{ .name }}] 가져오기 시작'
PullImageSuccess: '이미지 가져오기 성공'
AppStoreIsLastVersion: '앱스토어가 이미 최신 버전입니다'
AppStoreSyncSuccess: '앱스토어 동기화 성공'
@@ -146,7 +147,13 @@ ErrRuntimeNoPort: "런타임 환경에 포트가 설정되지 않았습니다.
Status: '상태'
start: '시작'
stop: '중지'
restart: '재시작'
kill: '강제 중지'
pause: '일시 정지'
unpause: '재개'
remove: '삭제'
delete: '삭제'
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요!'
#SSL인증
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
@@ -205,6 +212,7 @@ ImageRemoveHelper: "이미지 {{ .name }} 삭제, {{ .size }} 디스크 공간
BuildCache: "빌드 캐시"
Volume: "스토리지 볼륨"
Network: "네트워크"
PruneStart: "정리 중입니다. 잠시만 기다려주세요..."
#실행 시간
ErrFileNotExist: '{{ .detail }} 파일이 존재하지 않습니다! 소스 파일의 무결성을 확인하세요!'
@@ -243,6 +251,8 @@ IgnoreUploadErr: "업로드 실패, 오류: {{ .detail }}, 이 오류를 무시
LoadBackupFailed: "백업 계정 연결 획득 실패, 오류: {{ .detail }}"
InExecuting: "현재 작업이 실행 중입니다. 중복 실행하지 마세요!"
NoSuchResource: "데이터베이스에서 백업 내용을 찾을 수 없어 건너뜁니다..."
CleanLog: "로그 정리"
CleanLogByName: "{{.name}} 로그 정리"
#도구상자
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!'
@@ -342,6 +352,8 @@ TaskBuild: '빌드'
TaskPush: '푸시'
TaskClean: "정리"
TaskHandle: '실행'
TaskImport: "가져오기"
TaskExport: "내보내기"
Website: '웹사이트'
App: '애플리케이션'
Runtime: '런타임 환경'
+13 -1
View File
@@ -39,6 +39,7 @@ Failed: 'Gagal'
SystemRestart: 'Tugas terganggu kerana sistem mula semula'
ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan'
ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.'
Decrypt: "Dekripsi"
#sandaran
Localhost: 'Mesin Tempatan'
@@ -81,7 +82,7 @@ ErrAppWarn: 'Status tidak normal, sila semak log'
ErrAppParamKey: 'Parameter {{ .name }} medan tidak normal'
ErrAppUpgrade: 'Peningkatan {{ .name }} aplikasi gagal {{ .err }}'
AppRecover: 'Aplikasi tarik balik {{ .name }}'
PullImageStart: 'Mula tarik imej {{ .name }}'
PullImageStart: 'Mula tarik imej [{{ .name }}]'
PullImageSuccess: 'Tarik imej berjaya'
AppStoreIsLastVersion: 'App Store sudah pun versi terkini'
AppStoreSyncSuccess: 'Penyegerakan App Store berjaya'
@@ -149,7 +150,13 @@ ErrRuntimeNoPort: "Persekitaran runtime tidak diset dengan port, sila edit perse
Status: 'Status'
start: 'Mulakan'
stop: 'Berhenti'
restart: 'Mulakan Semula'
kill: 'Hentikan Paksa'
pause: 'Jeda'
unpause: 'Sambung Semula'
remove: 'Padam'
delete: 'Padam'
ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan!'
#ssl
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'
@@ -205,6 +212,7 @@ ImageRemoveHelper: "Padam imej {{ .name }}, membebaskan {{ .size }} ruang cakera
BuildCache: "Cache binaan"
Volume: "Jilid storan"
Network: "Rangkaian"
PruneStart: "Pembersihan sedang dijalankan, sila tunggu..."
#masa berjalan
ErrFileNotExist: 'Fail {{ .detail }} tidak wujud! Sila semak integriti fail sumber!'
@@ -243,6 +251,8 @@ IgnoreUploadErr: "Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini..."
LoadBackupFailed: "Gagal mendapatkan sambungan akaun sandaran, ralat: {{ .detail }}"
InExecuting: "Tugas semasa sedang dilaksanakan, jangan ulangi pelaksanaan!"
NoSuchResource: "Tiada kandungan sandaran ditemui dalam pangkalan data, dilangkau..."
CleanLog: "Bersihkan log"
CleanLogByName: "Bersihkan log {{.name}}"
#kotak alat
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!'
@@ -342,6 +352,8 @@ TaskBuild: 'Bina'
TaskPush: 'Tolak'
TaskClean: "Pembersihan"
TaskHandle: 'Laksanakan'
TaskImport: "Import"
TaskExport: "Eksport"
Website: 'Laman web'
App: 'Aplikasi'
Runtime: 'Persekitaran masa jalan'
+13 -1
View File
@@ -39,6 +39,7 @@ Failed: 'Falhou'
SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema'
ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído'
ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.'
Decrypt: "Descriptografar"
#backup
Localhost: 'Máquina Local'
@@ -81,7 +82,7 @@ ErrAppWarn: 'Status anormal, verifique o log'
ErrAppParamKey: 'O campo de parâmetro {{ .name }} está anormal'
ErrAppUpgrade: 'Falha na atualização do aplicativo {{ .name }} {{ .err }}'
AppRecover: 'Reverter aplicativo {{ .name }}'
PullImageStart: 'Comece a extrair a imagem {{ .name }}'
PullImageStart: 'Comece a extrair a imagem [{{ .name }}]'
PullImageSuccess: 'Imagem retirada com sucesso'
AppStoreIsLastVersion: 'A App Store já é a versão mais recente'
AppStoreSyncSuccess: 'Sincronização da App Store bem-sucedida'
@@ -149,7 +150,13 @@ ErrRuntimeNoPort: "O ambiente de tempo de execução não está configurado com
Status: 'Status'
start: 'Iniciar'
stop: 'Parar'
restart: 'Reiniciar'
kill: 'Parar Forçadamente'
pause: 'Pausar'
unpause: 'Retomar'
remove: 'Excluir'
delete: 'Excluir'
ErrDefaultWebsite: 'O site padrão já foi definido, cancele-o antes de definir!'
#ssl
ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído'
@@ -205,6 +212,7 @@ ImageRemoveHelper: "Excluída a imagem {{ .name }}, liberando {{ .size }} de esp
BuildCache: "Cache de construção"
Volume: "Volume de armazenamento"
Network: "Rede"
PruneStart: "Limpando em andamento, por favor aguarde..."
#tempo de execução
ErrFileNotExist: 'O arquivo {{ .detail }} não existe! Verifique a integridade do arquivo de origem!'
@@ -243,6 +251,8 @@ IgnoreUploadErr: "Upload falhou, erro: {{ .detail }}, ignorando este erro..."
LoadBackupFailed: "Falha ao obter conexão da conta de backup, erro: {{ .detail }}"
InExecuting: "A tarefa atual está sendo executada, não repita a execução!"
NoSuchResource: "Nenhum conteúdo de backup encontrado no banco de dados, ignorando..."
CleanLog: "Limpar log"
CleanLogByName: "Limpar log de {{.name}}"
#caixa de ferramentas
ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!'
@@ -342,6 +352,8 @@ TaskBuild: 'Construir'
TaskPush: 'Empurrar'
TaskClean: "Limpeza"
TaskHandle: 'Executar'
TaskImport: "Importar"
TaskExport: "Exportar"
Website: 'Site'
App: 'Aplicativo'
Runtime: 'Ambiente de tempo de execução'
+13 -1
View File
@@ -39,6 +39,7 @@ Failed: 'Не удалось'
SystemRestart: 'Задача прервана из-за перезапуска системы'
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
Decrypt: "Расшифровать"
#резервное копирование
Localhost: 'Локальная машина'
@@ -81,7 +82,7 @@ ErrAppWarn: 'Ненормальное состояние, проверьте ж
ErrAppParamKey: 'Поле параметра {{ .name }} ненормально'
ErrAppUpgrade: 'Обновление приложения {{ .name }} не удалось {{ .err }}'
AppRecover: 'Откатить приложение {{ .name }}'
PullImageStart: 'Начать извлечение изображения {{ .name }}'
PullImageStart: 'Начать извлечение изображения [{{ .name }}]'
PullImageSuccess: 'Изображение извлечено успешно'
AppStoreIsLastVersion: 'В App Store уже установлена последняя версия'
AppStoreSyncSuccess: 'Синхронизация с App Store прошла успешно'
@@ -149,7 +150,13 @@ ErrRuntimeNoPort: "Среда выполнения не настроена с п
Status: 'Статус'
start: 'Запустить'
stop: 'Остановить'
restart: 'Перезапустить'
kill: 'Принудительно Остановить'
pause: 'Приостановить'
unpause: 'Возобновить'
remove: 'Удалить'
delete: 'Удалить'
ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой!'
#ssl
ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален'
@@ -205,6 +212,7 @@ ImageRemoveHelper: "Удалён образ {{ .name }}, освобождено
BuildCache: "Кэш сборки"
Volume: "Том хранилища"
Network: "Сеть"
PruneStart: "Очистка выполняется, пожалуйста, подождите..."
#время выполнения
ErrFileNotExist: 'Файл {{ .detail }} не существует! Проверьте целостность исходного файла!'
@@ -243,6 +251,8 @@ IgnoreUploadErr: "Ошибка загрузки: {{ .detail }}, игнориру
LoadBackupFailed: "Не удалось получить подключение к учетной записи резервной копии, ошибка: {{ .detail }}"
InExecuting: "Текущая задача выполняется, не повторяйте выполнение!"
NoSuchResource: "В базе данных не найдено содержимое резервной копии, пропускаем..."
CleanLog: "Очистить журнал"
CleanLogByName: "Очистить журнал {{.name}}"
#ящик для инструментов
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!'
@@ -342,6 +352,8 @@ TaskCommit: 'Kоммит'
TaskPush: 'Push'
TaskClean: "Очистка"
TaskHandle: 'Выполнить'
TaskImport: "Импорт"
TaskExport: "Экспорт"
Website: 'Be6-сайт'
App: 'Приложение'
Runtime: 'Среда выполнения'
+13 -1
View File
@@ -39,6 +39,7 @@ Failed: 'Başarısız'
SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi'
ErrGroupIsDefault: 'Varsayılan grup, silinemez'
ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.'
Decrypt: "Şifre Çöz"
#backup
Localhost: 'Yerel Makine'
@@ -81,7 +82,7 @@ ErrAppWarn: 'Anormal durum, lütfen günlüğü kontrol edin'
ErrAppParamKey: 'Parametre {{ .name }} alanı anormal'
ErrAppUpgrade: 'Uygulama {{ .name }} yükseltmesi başarısız {{ .err }}'
AppRecover: 'Uygulama {{ .name }} geri alma'
PullImageStart: 'Image {{ .name }} çekmeye başla'
PullImageStart: 'Image [{{ .name }}] çekmeye başla'
PullImageSuccess: 'Image çekme başarılı'
AppStoreIsLastVersion: 'Uygulama Mağazası zaten en son sürüm'
AppStoreSyncSuccess: 'Uygulama Mağazası senkronizasyonu başarılı'
@@ -150,7 +151,13 @@ ErrRuntimeNoPort: "Çalışma zamanı ortamı bir porta sahip değil, lütfen ö
Status: 'Durum'
start: 'Başlat'
stop: 'Durdur'
restart: 'Yeniden Başlat'
kill: 'Zorla Durdur'
pause: 'Duraklat'
unpause: 'Devam Et'
remove: 'Sil'
delete: 'Sil'
ErrDefaultWebsite: "Varsayılan bir web sitesi zaten ayarlanmış. Yeni bir tane ayarlamadan önce lütfen iptal edin!"
#ssl
ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor ve silinemez'
@@ -206,6 +213,7 @@ ImageRemoveHelper: "{{ .name }} imajı silindi, {{ .size }} disk alanı boşaltt
BuildCache: "Derleme önbelleği"
Volume: "Depolama hacmi"
Network: "Ağ"
PruneStart: "Temizlik devam ediyor, lütfen bekleyin..."
#runtime
ErrFileNotExist: '{{ .detail }} dosyası mevcut değil! Lütfen kaynak dosyanın bütünlüğünü kontrol edin!'
@@ -244,6 +252,8 @@ IgnoreUploadErr: "Yükleme başarısız, hata: {{ .detail }}, bu hata yoksayıl
LoadBackupFailed: "Yedek hesap bağlantısı alınamadı, hata: {{ .detail }}"
InExecuting: "Mevcut görev yürütülüyor, lütfen tekrar yürütmeyin!"
NoSuchResource: "Veritabanında yedek içeriği bulunamadı, atlanıyor..."
CleanLog: "Günlüğü temizle"
CleanLogByName: "{{.name}} günlüğünü temizle"
#toolbox
ErrNotExistUser: 'Mevcut kullanıcı mevcut değil, lütfen değiştirin ve tekrar deneyin!'
@@ -343,6 +353,8 @@ TaskBuild: 'Yapı'
TaskPush: 'Gönder'
TaskClean: "Temizleme"
TaskHandle: 'Yürüt'
TaskImport: "İçe Aktar"
TaskExport: "Dışa Aktar"
Website: 'Web Sitesi'
App: 'Uygulama'
Runtime: 'Çalışma ortamı'
+13 -1
View File
@@ -36,6 +36,7 @@ Failed: '失敗'
SystemRestart: '系統重新啟動導致任務中斷'
ErrGroupIsDefault: '預設分組,無法刪除'
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
Decrypt: "解密"
#backup
Localhost: '本機'
@@ -78,7 +79,7 @@ ErrAppWarn: '狀態異常,請檢視日誌'
ErrAppParamKey: '參數{{ .name }} 欄位異常'
ErrAppUpgrade: '應用程式{{ .name }} 升級失敗{{ .err }}'
AppRecover: '應用程式{{ .name }} 回滾'
PullImageStart: '開始拉取鏡像{{ .name }}'
PullImageStart: '開始拉取鏡像 [{{ .name }}]'
PullImageSuccess: '鏡像拉取成功'
AppStoreSyncSuccess: '應用程式商店同步成功'
SyncAppDetail: '同步應用程式設定'
@@ -145,7 +146,13 @@ ErrRuntimeNoPort: "執行環境未設定埠,請先編輯執行環境"
Status: '狀態'
start: '開啟'
stop: '關閉'
restart: '重啟'
kill: '強制停止'
pause: '暫停'
unpause: '恢復'
remove: '刪除'
delete: '刪除'
ErrDefaultWebsite: '已經設置默認網站,請取消後再設置!'
#ssl
ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除'
@@ -204,6 +211,7 @@ ImageRemoveHelper: "刪除鏡像 {{ .name }} ,釋放磁碟空間 {{ .size }}"
BuildCache: "構建快取"
Volume: "磁碟區"
Network: "網路"
PruneStart: "清理中,請稍候..."
#runtime
ErrFileNotExist: '{{ .detail }} 檔案不存在!請檢查來源檔案完整性!'
@@ -242,6 +250,8 @@ IgnoreUploadErr: "上傳失敗,錯誤:{{ .detail }},忽略本次錯誤..."
LoadBackupFailed: "取得備份帳號連線失敗,錯誤:{{ .detail }}"
InExecuting: "目前任務正在執行中,請勿重複執行!"
NoSuchResource: "資料庫中未能查詢到備份內容,跳過..."
CleanLog: "清理日誌"
CleanLogByName: "清理 {{.name}} 日誌"
#toolbox
ErrNotExistUser: '目前使用者不存在,請修改後重試!'
@@ -341,6 +351,8 @@ TaskBuild: '建置'
TaskPush: '推送'
TaskClean: "清理"
TaskHandle: '執行'
TaskImport: "導入"
TaskExport: "導出"
Website: '網站'
App: '應用程式'
Runtime: '運作環境'
+14 -1
View File
@@ -36,6 +36,7 @@ Failed: "失败"
SystemRestart: "系统重启导致任务中断"
ErrGroupIsDefault: "默认分组,无法删除"
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
Decrypt: "解密"
#backup
Localhost: '本机'
@@ -78,7 +79,7 @@ ErrAppWarn: "状态异常,请查看日志"
ErrAppParamKey: "参数 {{ .name }} 字段异常"
ErrAppUpgrade: "应用 {{ .name }} 升级失败 {{ .err }}"
AppRecover: "应用 {{ .name }} 回滚 "
PullImageStart: "开始拉取镜像 {{ .name }}"
PullImageStart: "开始拉取镜像 [{{ .name }}]"
PullImageSuccess: "镜像拉取成功"
AppStoreSyncSuccess: "应用商店同步成功"
SyncAppDetail: "同步应用配置"
@@ -95,6 +96,7 @@ ErrAppVersionDeprecated: " {{ .name }} 应用不适配当前 1Panel 版本,跳
ErrDockerFailed: "Docker 状态异常,请检查服务状态"
ErrDockerComposeCmdNotFound: "Docker Compose 命令不存在,请先在宿主机安装此命令"
UseExistImage: "拉取镜像失败,使用存量镜像"
ErrDatabaseNotFound: "数据库 {{ .name }} 不存在"
#ssh
ExportIP: "登录 IP"
@@ -145,7 +147,13 @@ ErrRuntimeNoPort: '运行环境未设置端口,请先编辑运行环境'
Status: '状态'
start: '开启'
stop: '关闭'
restart: '重启'
kill: '强制停止'
pause: '暂停'
unpause: '恢复'
remove: '删除'
delete: '删除'
ErrDefaultWebsite: "已经设置默认网站,请取消后再设置!"
#ssl
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
@@ -204,6 +212,7 @@ ImageRemoveHelper: "删除镜像 {{ .name }} ,释放磁盘空间 {{ .size }}"
BuildCache: "构建缓存"
Volume: "存储卷"
Network: "网络"
PruneStart: "清理中,请稍候..."
#runtime
ErrFileNotExist: "{{ .detail }} 文件不存在!请检查源文件完整性!"
@@ -242,6 +251,8 @@ IgnoreUploadErr: "上传失败,错误:{{ .detail }},忽略本次错误..."
LoadBackupFailed: "获取备份账号连接失败,错误:{{ .detail }}"
InExecuting: "当前任务正在执行中,请勿重复执行!"
NoSuchResource: "数据库中未能查询到备份内容,跳过..."
CleanLog: "清理日志"
CleanLogByName: "清理 {{.name}} 日志"
#toolbox
ErrNotExistUser: "当前用户不存在,请修改后重试!"
@@ -342,6 +353,8 @@ TaskBuild: "构建"
TaskPush: "推送"
TaskClean: "清理"
TaskHandle: "执行"
TaskImport: "导入"
TaskExport: "导出"
Website: "网站"
App: "应用"
Runtime: "运行环境"

Some files were not shown because too many files have changed in this diff Show More