diff --git a/.github/workflows/create-pr-from-push.yml b/.github/workflows/create-pr-from-push.yml deleted file mode 100644 index 7c0e8a5a0..000000000 --- a/.github/workflows/create-pr-from-push.yml +++ /dev/null @@ -1,17 +0,0 @@ -on: - push: - branches: - - 'pr@**' - - 'repr@**' - -name: 针对特定分支名自动创建 PR - -jobs: - generic_handler: - name: 自动创建 PR - runs-on: ubuntu-latest - steps: - - name: Create pull request - uses: jumpserver/action-generic-handler@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }} diff --git a/.github/workflows/issue-close.yml b/.github/workflows/issue-close.yml deleted file mode 100644 index bb49b5877..000000000 --- a/.github/workflows/issue-close.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Issue Close Check - -on: - issues: - types: [closed] - -jobs: - issue-close-remove-labels: - runs-on: ubuntu-latest - steps: - - name: Remove labels - uses: actions-cool/issues-helper@v2 - if: ${{ !github.event.issue.pull_request }} - with: - actions: 'remove-labels' - labels: '状态:待处理' \ No newline at end of file diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml deleted file mode 100644 index e9e3fbc79..000000000 --- a/.github/workflows/issue-comment.yml +++ /dev/null @@ -1,38 +0,0 @@ -on: - issue_comment: - types: [created] - -name: Add issues workflow labels - -jobs: - add-label-if-is-author: - runs-on: ubuntu-latest - if: ${{ (github.event.issue.user.id == github.event.comment.user.id) && (!github.event.issue.pull_request) }} - steps: - - name: Add require handle label - uses: actions-cool/issues-helper@v2 - with: - actions: 'add-labels' - labels: '状态:待处理' - - - name: Remove require reply label - uses: actions-cool/issues-helper@v2 - with: - actions: 'remove-labels' - labels: '状态:待用户反馈' - - add-label-if-not-author: - runs-on: ubuntu-latest - if: ${{ (github.event.issue.user.id != github.event.comment.user.id) && (!github.event.issue.pull_request) && (github.event.issue.state == 'open') }} - steps: - - name: Add require replay label - uses: actions-cool/issues-helper@v2 - with: - actions: 'add-labels' - labels: '状态:待用户反馈' - - - name: Remove require handle label - uses: actions-cool/issues-helper@v2 - with: - actions: 'remove-labels' - labels: '状态:待处理' diff --git a/.github/workflows/issue-open.yml b/.github/workflows/issue-open.yml deleted file mode 100644 index 232d5da29..000000000 --- a/.github/workflows/issue-open.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Issue Open Check - -on: - issues: - types: [opened] - -jobs: - issue-open-add-labels: - runs-on: ubuntu-latest - steps: - - name: Add labels - uses: actions-cool/issues-helper@v2 - if: ${{ !github.event.issue.pull_request }} - with: - actions: 'add-labels' - labels: '状态:待处理' \ No newline at end of file diff --git a/.github/workflows/sync2gitee.yml b/.github/workflows/sync2gitee.yml new file mode 100644 index 000000000..637a22b9e --- /dev/null +++ b/.github/workflows/sync2gitee.yml @@ -0,0 +1,16 @@ +name: sync2gitee +on: [push] + +jobs: + repo-sync: + runs-on: ubuntu-latest + steps: + - name: Mirror the Github organization repos to Gitee. + uses: Yikun/hub-mirror-action@master + with: + src: 'github/1Panel-dev' + dst: 'gitee/fit2cloud-xlab' + dst_key: ${{ secrets.GITEE_PRIVATE_KEY }} + dst_token: ${{ secrets.GITEE_TOKEN }} + static_list: "1Panel" + force_update: true diff --git a/Makefile b/Makefile index 3793067a5..a01cd7bf1 100644 --- a/Makefile +++ b/Makefile @@ -11,15 +11,19 @@ SERVER_PATH=$(BASE_PAH)/backend MAIN= $(BASE_PAH)/cmd/server/main.go APP_NAME=1panel -build_web: +build_frontend: cd $(WEB_PATH) && npm install && npm run build:dev -build_bin: +build_backend_on_linux: cd $(SERVER_PATH) \ - && CGO_ENABLED=1 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w --extldflags "-static -fpic"' -tags osusergo -o $(BUILD_PATH)/$(APP_NAME) $(MAIN) + && CGO_ENABLED=1 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w --extldflags "-static -fpic"' -tags 'osusergo,netgo' -o $(BUILD_PATH)/$(APP_NAME) $(MAIN) -build_linux_on_mac: +build_backend_on_darwin: cd $(SERVER_PATH) \ && CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ $(GOBUILD) -trimpath -ldflags '-s -w --extldflags "-static -fpic"' -o $(BUILD_PATH)/$(APP_NAME) $(MAIN) -build_all: build_web build_bin \ No newline at end of file +build_backend_on_archlinux: + cd $(SERVER_PATH) \ + && CGO_ENABLED=1 GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -trimpath -ldflags '-s -w --extldflags "-fpic"' -tags osusergo -o $(BUILD_PATH)/$(APP_NAME) $(MAIN) + +build_all: build_frontend build_backend_on_linux diff --git a/README.md b/README.md index ae6b8585a..aae8c1758 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[README_EN.md](README_EN.md)

1Panel

现代化、开源的 Linux 服务器运维管理面板

@@ -18,7 +19,7 @@ ## UI 展示 -![UI展示](https://1panel.oss-cn-hangzhou.aliyuncs.com/img/overview.png) +![UI展示](https://resource.fit2cloud.com/1panel/img/overview.png) ## 快速开始 @@ -47,13 +48,13 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_ **微信交流群** - + ## 安全说明 如果您在使用过程中发现任何安全问题,请通过以下方式直接联系我们: -- 邮箱:support@fit2cloud.com +- 邮箱:support@fit2cloud.com - 电话:400-052-0755 ## Star History @@ -62,7 +63,7 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_ ## License -Copyright (c) 2014-2023 飞致云 FIT2CLOUD, All rights reserved. +Copyright (c) 2014-2023 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved. Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 000000000..7f8b6733c --- /dev/null +++ b/README_EN.md @@ -0,0 +1,72 @@ +[中文 README.md](README.md) +

1Panel

+

Modern and Open-Source Linux Server Operation and Management Panel

+

+ License: GPL v3 + Codacy + GitHub release + Stars +

+ +------------------------------ + +1Panel is a modern and Open-Source linux server operation and management panel, the functions and advantages of 1Panel include: + +- **Quick website building**: Deeply integrated with Wordpress and [Halo](https://github.com/halo-dev/halo/), with one-click solutions for domain name binding, SSL certificate configuration, and more; +- **Efficient management**: Easily manage Linux servers through the web interface, including application management, host monitoring, file management, database management, container management, and more; +- **Secure and reliable**: Minimal vulnerability exposure, with firewall and security audit functions provided; +- **One-click backup**: Support for one-click backup and restore, with backup data stored in the cloud and never lost. + +## UI Display + +![UI Display](https://resource.fit2cloud.com/1panel/img/overview_en.png) + +## Quick Start + +**Online Demo** + +- Address: +- Username: demo +- Password: 1panel + +**One-Click Installation** + +Execute the following command to install 1Panel with one click: + +```sh +curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh +``` + +**Learning Materials** + +- [Online Documentation](https://1panel.cn/docs/) +- [Teaching Videos](https://space.bilibili.com/510493147/channel/collectiondetail?sid=1199760) + +## Community + +If you have any questions or suggestions, please submit a GitHub Issue or join our WeChat group for communication. + +**WeChat Group** + + + +## Security Information + +If you discover any security issues, please contact us through: + +- Email: support@fit2cloud.com +- Phone: 400-052-0755 + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=1Panel-dev/1Panel&type=Date)](https://star-history.com/#1Panel-dev/1Panel&Date) + +## License + +Copyright (c) 2014-2023 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved. + +Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..08a8ca521 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,19 @@ +# 安全说明 + +如果您发现安全问题,请直接联系我们: + +- wanghe@fit2cloud.com +- support@fit2cloud.com +- 400-052-0755 + +感谢您的支持! + +# Security Policy + +All security bugs should be reported to the contact as below: + +- wanghe@fit2cloud.com +- support@fit2cloud.com +- 400-052-0755 + +Thanks for your support! diff --git a/backend/app/api/v1/app.go b/backend/app/api/v1/app.go index 4e2d1ffe2..1ed5b009a 100644 --- a/backend/app/api/v1/app.go +++ b/backend/app/api/v1/app.go @@ -38,8 +38,9 @@ func (b *BaseApi) SearchApp(c *gin.Context) { // @Router /apps/sync [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"} func (b *BaseApi) SyncApp(c *gin.Context) { + appService.SyncAppListFromLocal() global.LOG.Infof("sync app list start ...") - if err := appService.SyncAppList(); err != nil { + if err := appService.SyncAppListFromRemote(); err != nil { global.LOG.Errorf("sync app list error [%s]", err.Error()) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -71,14 +72,15 @@ func (b *BaseApi) GetApp(c *gin.Context) { } // @Tags App -// @Summary Search app detail by id -// @Description 通过 id 获取应用详情 +// @Summary Search app detail by appid +// @Description 通过 appid 获取应用详情 // @Accept json // @Param appId path integer true "app id" // @Param version path string true "app 版本" +// @Param version path string true "app 类型" // @Success 200 {object} response.AppDetailDTO // @Security ApiKeyAuth -// @Router /apps/detail/:appId/:version [get] +// @Router /apps/detail/:appId/:version/:type [get] func (b *BaseApi) GetAppDetail(c *gin.Context) { appId, err := helper.GetIntParamByKey(c, "appId") if err != nil { @@ -86,7 +88,30 @@ func (b *BaseApi) GetAppDetail(c *gin.Context) { return } version := c.Param("version") - appDetailDTO, err := appService.GetAppDetail(appId, version) + appType := c.Param("type") + appDetailDTO, err := appService.GetAppDetail(appId, version, appType) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, appDetailDTO) +} + +// @Tags App +// @Summary Get app detail by id +// @Description 通过 id 获取应用详情 +// @Accept json +// @Param appId path integer true "id" +// @Success 200 {object} response.AppDetailDTO +// @Security ApiKeyAuth +// @Router /apps/details/:id [get] +func (b *BaseApi) GetAppDetailByID(c *gin.Context) { + appDetailID, err := helper.GetIntParamByKey(c, "id") + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) + return + } + appDetailDTO, err := appService.GetAppDetailByID(appDetailID) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/app_install.go b/backend/app/api/v1/app_install.go index a7acd74ee..928a80bc9 100644 --- a/backend/app/api/v1/app_install.go +++ b/backend/app/api/v1/app_install.go @@ -93,24 +93,24 @@ func (b *BaseApi) LoadPort(c *gin.Context) { // @Tags App // @Summary Search app password by key -// @Description 获取应用密码 +// @Description 获取应用连接信息 // @Accept json // @Param key path string true "request" -// @Success 200 {string} password +// @Success 200 {string} response.DatabaseConn // @Security ApiKeyAuth -// @Router /apps/installed/loadpassword/:key [get] -func (b *BaseApi) LoadPassword(c *gin.Context) { +// @Router /apps/installed/conninfo/:key [get] +func (b *BaseApi) LoadConnInfo(c *gin.Context) { key, ok := c.Params.Get("key") if !ok { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error key in path")) return } - password, err := appInstallService.LoadPassword(key) + conn, err := appInstallService.LoadConnInfo(key) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, password) + helper.SuccessWithData(c, conn) } // @Tags App @@ -144,7 +144,7 @@ func (b *BaseApi) DeleteCheck(c *gin.Context) { // @Router /apps/installed/sync [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"同步已安装应用列表","formatEN":"Sync the list of installed apps"} func (b *BaseApi) SyncInstalled(c *gin.Context) { - if err := appInstallService.SyncAll(); err != nil { + if err := appInstallService.SyncAll(false); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/api/v1/auth.go b/backend/app/api/v1/auth.go index 981957b5c..a06479d8e 100644 --- a/backend/app/api/v1/auth.go +++ b/backend/app/api/v1/auth.go @@ -28,9 +28,11 @@ func (b *BaseApi) Login(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := captcha.VerifyCode(req.CaptchaID, req.Captcha); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return + if req.AuthMethod != "jwt" { + if err := captcha.VerifyCode(req.CaptchaID, req.Captcha); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } } user, err := authService.Login(c, req) diff --git a/backend/app/api/v1/backup.go b/backend/app/api/v1/backup.go index d1334d7d9..e3da49673 100644 --- a/backend/app/api/v1/backup.go +++ b/backend/app/api/v1/backup.go @@ -104,9 +104,9 @@ func (b *BaseApi) ListBuckets(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Router /settings/backup/del [post] -// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"ids","isList":true,"db":"backup_accounts","output_colume":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"} +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":true,"db":"backup_accounts","output_colume":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"} func (b *BaseApi) DeleteBackup(c *gin.Context) { - var req dto.BatchDeleteReq + var req dto.OperateByID if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -116,7 +116,7 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) { return } - if err := backupService.BatchDelete(req.Ids); err != nil { + if err := backupService.Delete(req.ID); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -175,7 +175,7 @@ func (b *BaseApi) DownloadRecord(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - c.File(filePath) + helper.SuccessWithData(c, filePath) } // @Tags Backup Account diff --git a/backend/app/api/v1/container.go b/backend/app/api/v1/container.go index 2d78af06a..542abbd25 100644 --- a/backend/app/api/v1/container.go +++ b/backend/app/api/v1/container.go @@ -70,6 +70,34 @@ func (b *BaseApi) SearchCompose(c *gin.Context) { }) } +// @Tags Container Compose +// @Summary Test compose +// @Description 测试 compose 是否可用 +// @Accept json +// @Param request body dto.ComposeCreate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /containers/compose/test [post] +// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测 compose [name] 格式","formatEN":"check compose [name]"} +func (b *BaseApi) TestCompose(c *gin.Context) { + var req dto.ComposeCreate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + isOK, err := containerService.TestCompose(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, isOK) +} + // @Tags Container Compose // @Summary Create compose // @Description 创建容器编排 @@ -90,11 +118,12 @@ func (b *BaseApi) CreateCompose(c *gin.Context) { return } - if err := containerService.CreateCompose(req); err != nil { + log, err := containerService.CreateCompose(req) + if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - helper.SuccessWithData(c, nil) + helper.SuccessWithData(c, log) } // @Tags Container Compose diff --git a/backend/app/api/v1/cronjob.go b/backend/app/api/v1/cronjob.go index 16896b1b6..433654d50 100644 --- a/backend/app/api/v1/cronjob.go +++ b/backend/app/api/v1/cronjob.go @@ -92,17 +92,41 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) { }) } +// @Tags Cronjob +// @Summary Clean job records +// @Description 清空计划任务记录 +// @Accept json +// @Param request body dto.CronjobClean true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /cronjobs/records/clean [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"cronjobs","output_colume":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"} +func (b *BaseApi) CleanRecord(c *gin.Context) { + var req dto.CronjobClean + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + if err := cronjobService.CleanRecord(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, nil) +} + // @Tags Cronjob // @Summary Delete cronjob // @Description 删除计划任务 // @Accept json -// @Param request body dto.BatchDeleteReq true "request" +// @Param request body dto.CronjobBatchDelete true "request" // @Success 200 // @Security ApiKeyAuth // @Router /cronjobs/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"ids","isList":true,"db":"cronjobs","output_colume":"name","output_value":"names"}],"formatZH":"删除计划任务 [names]","formatEN":"delete cronjob [names]"} func (b *BaseApi) DeleteCronjob(c *gin.Context) { - var req dto.BatchDeleteReq + var req dto.CronjobBatchDelete if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -112,7 +136,7 @@ func (b *BaseApi) DeleteCronjob(c *gin.Context) { return } - if err := cronjobService.Delete(req.Ids); err != nil { + if err := cronjobService.Delete(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -198,7 +222,7 @@ func (b *BaseApi) TargetDownload(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - c.File(filePath) + helper.SuccessWithData(c, filePath) } // @Tags Cronjob diff --git a/backend/app/api/v1/docker.go b/backend/app/api/v1/docker.go index 8160f4b3c..87a575ae9 100644 --- a/backend/app/api/v1/docker.go +++ b/backend/app/api/v1/docker.go @@ -1,7 +1,6 @@ package v1 import ( - "io/ioutil" "os" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" @@ -35,7 +34,7 @@ func (b *BaseApi) LoadDaemonJsonFile(c *gin.Context) { helper.SuccessWithData(c, "daemon.json is not find in path") return } - content, err := ioutil.ReadFile(constant.DaemonJsonPath) + content, err := os.ReadFile(constant.DaemonJsonPath) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/entry.go b/backend/app/api/v1/entry.go index 1879a9d5a..082d85d41 100644 --- a/backend/app/api/v1/entry.go +++ b/backend/app/api/v1/entry.go @@ -9,41 +9,43 @@ type ApiGroup struct { var ApiGroupApp = new(ApiGroup) var ( - authService = service.ServiceGroupApp.AuthService - dashboardService = service.ServiceGroupApp.DashboardService + authService = service.NewIAuthService() + dashboardService = service.NewIDashboardService() appService = service.NewIAppService() - appInstallService = service.ServiceGroupApp.AppInstallService + appInstallService = service.NewIAppInstalledService() - containerService = service.ServiceGroupApp.ContainerService - composeTemplateService = service.ServiceGroupApp.ComposeTemplateService - imageRepoService = service.ServiceGroupApp.ImageRepoService - imageService = service.ServiceGroupApp.ImageService - dockerService = service.ServiceGroupApp.DockerService + containerService = service.NewIContainerService() + composeTemplateService = service.NewIComposeTemplateService() + imageRepoService = service.NewIImageRepoService() + imageService = service.NewIImageService() + dockerService = service.NewIDockerService() - mysqlService = service.ServiceGroupApp.MysqlService - redisService = service.ServiceGroupApp.RedisService + mysqlService = service.NewIMysqlService() + redisService = service.NewIRedisService() - cronjobService = service.ServiceGroupApp.CronjobService + cronjobService = service.NewICronjobService() - hostService = service.ServiceGroupApp.HostService - groupService = service.ServiceGroupApp.GroupService - fileService = service.ServiceGroupApp.FileService + hostService = service.NewIHostService() + groupService = service.NewIGroupService() + fileService = service.NewIFileService() + firewallService = service.NewIFirewallService() - settingService = service.ServiceGroupApp.SettingService - backupService = service.ServiceGroupApp.BackupService + settingService = service.NewISettingService() + backupService = service.NewIBackupService() - commandService = service.ServiceGroupApp.CommandService + commandService = service.NewICommandService() - websiteGroupService = service.ServiceGroupApp.WebsiteGroupService - websiteService = service.ServiceGroupApp.WebsiteService - websiteDnsAccountService = service.ServiceGroupApp.WebsiteDnsAccountService - websiteSSLService = service.ServiceGroupApp.WebsiteSSLService - websiteAcmeAccountService = service.ServiceGroupApp.WebsiteAcmeAccountService + websiteService = service.NewIWebsiteService() + websiteDnsAccountService = service.NewIWebsiteDnsAccountService() + websiteSSLService = service.NewIWebsiteSSLService() + websiteAcmeAccountService = service.NewIWebsiteAcmeAccountService() - nginxService = service.ServiceGroupApp.NginxService + nginxService = service.NewINginxService() - logService = service.ServiceGroupApp.LogService - snapshotService = service.ServiceGroupApp.SnapshotService - upgradeService = service.ServiceGroupApp.UpgradeService + logService = service.NewILogService() + snapshotService = service.NewISnapshotService() + upgradeService = service.NewIUpgradeService() + + runtimeService = service.NewRuntimeService() ) diff --git a/backend/app/api/v1/file.go b/backend/app/api/v1/file.go index c0ff30769..2a6276372 100644 --- a/backend/app/api/v1/file.go +++ b/backend/app/api/v1/file.go @@ -3,7 +3,7 @@ package v1 import ( "errors" "fmt" - "io/ioutil" + "io" "net/http" "os" "path" @@ -445,6 +445,28 @@ func (b *BaseApi) Download(c *gin.Context) { c.File(filePath) } +// @Tags File +// @Summary Download file with path +// @Description 下载指定文件 +// @Accept json +// @Param request body dto.FilePath true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /files/download/bypath [post] +// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载文件 [path]","formatEN":"Download file [path]"} +func (b *BaseApi) DownloadFile(c *gin.Context) { + var req dto.FilePath + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + c.File(req.Path) +} + // @Tags File // @Summary Load file size // @Description 获取文件夹大小 @@ -488,7 +510,7 @@ func (b *BaseApi) LoadFromFile(c *gin.Context) { return } - content, err := ioutil.ReadFile(req.Path) + content, err := os.ReadFile(req.Path) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -497,6 +519,12 @@ func (b *BaseApi) LoadFromFile(c *gin.Context) { } func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error { + if _, err := os.Stat(path.Dir(dstDir)); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(path.Dir(dstDir), os.ModePerm); err != nil { + return err + } + } + targetFile, err := os.Create(filepath.Join(dstDir, fileName)) if err != nil { return err @@ -505,7 +533,7 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) for i := 0; i < chunkCount; i++ { chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", fileName, i)) - chunkData, err := ioutil.ReadFile(chunkPath) + chunkData, err := os.ReadFile(chunkPath) if err != nil { return err } @@ -525,7 +553,6 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) // @Success 200 // @Security ApiKeyAuth // @Router /files/chunkupload [post] -// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"} func (b *BaseApi) UploadChunkFiles(c *gin.Context) { fileForm, err := c.FormFile("chunk") if err != nil { @@ -551,13 +578,16 @@ func (b *BaseApi) UploadChunkFiles(c *gin.Context) { } fileOp := files.NewFileOp() - if err := fileOp.CreateDir("uploads", 0755); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return + tmpDir := path.Join(global.CONF.System.TmpDir, "upload") + if !fileOp.Stat(tmpDir) { + if err := fileOp.CreateDir(tmpDir, 0755); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } } - //fileID := uuid.New().String() + filename := c.PostForm("filename") - fileDir := filepath.Join(global.CONF.System.DataDir, "upload", filename) + fileDir := filepath.Join(tmpDir, filename) _ = os.MkdirAll(fileDir, 0755) filePath := filepath.Join(fileDir, filename) @@ -567,25 +597,25 @@ func (b *BaseApi) UploadChunkFiles(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - emptyFile.Close() + defer emptyFile.Close() - chunkData, err := ioutil.ReadAll(uploadFile) + chunkData, err := io.ReadAll(uploadFile) if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrFileUpload, err) return } chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", filename, chunkIndex)) - err = ioutil.WriteFile(chunkPath, chunkData, 0644) + err = os.WriteFile(chunkPath, chunkData, 0644) if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrFileUpload, err) return } if chunkIndex+1 == chunkCount { err = mergeChunks(filename, fileDir, c.PostForm("path"), chunkCount) if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrAppDelete, err) + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrFileUpload, err) return } helper.SuccessWithData(c, true) diff --git a/backend/app/api/v1/firewall.go b/backend/app/api/v1/firewall.go new file mode 100644 index 000000000..6606df675 --- /dev/null +++ b/backend/app/api/v1/firewall.go @@ -0,0 +1,207 @@ +package v1 + +import ( + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/global" + "github.com/gin-gonic/gin" +) + +// @Tags Firewall +// @Summary Load firewall base info +// @Description 获取防火墙基础信息 +// @Success 200 {object} dto.FirewallBaseInfo +// @Security ApiKeyAuth +// @Router /hosts/firewall/base [get] +func (b *BaseApi) LoadFirewallBaseInfo(c *gin.Context) { + data, err := firewallService.LoadBaseInfo() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, data) +} + +// @Tags Firewall +// @Summary Page firewall rules +// @Description 获取防火墙规则列表分页 +// @Accept json +// @Param request body dto.SearchWithPage true "request" +// @Success 200 {object} dto.PageResult +// @Security ApiKeyAuth +// @Router /hosts/firewall/search [post] +func (b *BaseApi) SearchFirewallRule(c *gin.Context) { + var req dto.RuleSearch + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + total, list, err := firewallService.SearchWithPage(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, dto.PageResult{ + Items: list, + Total: total, + }) +} + +// @Tags Firewall +// @Summary Page firewall status +// @Description 修改防火墙状态 +// @Accept json +// @Param request body dto.FirewallOperation true "request" +// @Success 200 {object} dto.PageResult +// @Security ApiKeyAuth +// @Router /hosts/firewall/operate [post] +// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"} +func (b *BaseApi) OperateFirewall(c *gin.Context) { + var req dto.FirewallOperation + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + + if err := firewallService.OperateFirewall(req.Operation); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 创建防火墙端口规则 +// @Accept json +// @Param request body dto.PortRuleOperate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/port [post] +// @x-panel-log {"bodyKeys":["port","strategy"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"添加端口规则 [strategy] [port]","formatEN":"create port rules [strategy][port]"} +func (b *BaseApi) OperatePortRule(c *gin.Context) { + var req dto.PortRuleOperate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.OperatePortRule(req, true); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 创建防火墙 IP 规则 +// @Accept json +// @Param request body dto.AddrRuleOperate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/ip [post] +// @x-panel-log {"bodyKeys":["strategy","address"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"添加 ip 规则 [strategy] [address]","formatEN":"create address rules [strategy][address]"} +func (b *BaseApi) OperateIPRule(c *gin.Context) { + var req dto.AddrRuleOperate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.OperateAddressRule(req, true); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 批量删除防火墙规则 +// @Accept json +// @Param request body dto.BatchRuleOperate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/ip [post] +func (b *BaseApi) BatchOperateRule(c *gin.Context) { + var req dto.BatchRuleOperate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.BacthOperateRule(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 更新端口防火墙规则 +// @Accept json +// @Param request body dto.PortRuleUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/update/port [post] +func (b *BaseApi) UpdatePortRule(c *gin.Context) { + var req dto.PortRuleUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.UpdatePortRule(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 更新 ip 防火墙规则 +// @Accept json +// @Param request body dto.AddrRuleUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/update/ip [post] +func (b *BaseApi) UpdateAddrRule(c *gin.Context) { + var req dto.AddrRuleUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.UpdateAddrRule(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/api/v1/group.go b/backend/app/api/v1/group.go index d8027fe11..42a89135c 100644 --- a/backend/app/api/v1/group.go +++ b/backend/app/api/v1/group.go @@ -15,7 +15,7 @@ import ( // @Param request body dto.GroupCreate true "request" // @Success 200 // @Security ApiKeyAuth -// @Router /hosts/group [post] +// @Router /groups [post] // @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"} func (b *BaseApi) CreateGroup(c *gin.Context) { var req dto.GroupCreate @@ -41,7 +41,7 @@ func (b *BaseApi) CreateGroup(c *gin.Context) { // @Param request body dto.OperateByID true "request" // @Success 200 // @Security ApiKeyAuth -// @Router /hosts/group/del [post] +// @Router /groups/del [post] // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"groups","output_colume":"name","output_value":"name"},{"input_colume":"id","input_value":"id","isList":false,"db":"groups","output_colume":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"} func (b *BaseApi) DeleteGroup(c *gin.Context) { var req dto.OperateByID @@ -68,7 +68,7 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) { // @Param request body dto.GroupUpdate true "request" // @Success 200 // @Security ApiKeyAuth -// @Router /hosts/group/update [post] +// @Router /groups/update [post] // @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"} func (b *BaseApi) UpdateGroup(c *gin.Context) { var req dto.GroupUpdate @@ -94,7 +94,7 @@ func (b *BaseApi) UpdateGroup(c *gin.Context) { // @Param request body dto.GroupSearch true "request" // @Success 200 {anrry} dto.GroupInfo // @Security ApiKeyAuth -// @Router /hosts/group/search [post] +// @Router /groups/search [post] func (b *BaseApi) ListGroup(c *gin.Context) { var req dto.GroupSearch if err := c.ShouldBindJSON(&req); err != nil { diff --git a/backend/app/api/v1/helper/helper.go b/backend/app/api/v1/helper/helper.go index 1afe59610..831d516e6 100644 --- a/backend/app/api/v1/helper/helper.go +++ b/backend/app/api/v1/helper/helper.go @@ -83,6 +83,15 @@ func SuccessWithData(ctx *gin.Context, data interface{}) { ctx.Abort() } +func SuccessWithOutData(ctx *gin.Context) { + res := dto.Response{ + Code: constant.CodeSuccess, + Message: "success", + } + ctx.JSON(http.StatusOK, res) + ctx.Abort() +} + func SuccessWithMsg(ctx *gin.Context, msg string) { res := dto.Response{ Code: constant.CodeSuccess, diff --git a/backend/app/api/v1/host.go b/backend/app/api/v1/host.go index bae25a3fc..3dc2a0aba 100644 --- a/backend/app/api/v1/host.go +++ b/backend/app/api/v1/host.go @@ -8,7 +8,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/copier" - "github.com/1Panel-dev/1Panel/backend/utils/ssh" "github.com/gin-gonic/gin" ) @@ -74,33 +73,9 @@ func (b *BaseApi) TestByInfo(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if req.AuthMode == "password" && len(req.Password) != 0 { - password, err := base64.StdEncoding.DecodeString(req.Password) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.Password = string(password) - } - if req.AuthMode == "key" && len(req.PrivateKey) != 0 { - privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - req.PrivateKey = string(privateKey) - } - var connInfo ssh.ConnInfo - _ = copier.Copy(&connInfo, &req) - connInfo.PrivateKey = []byte(req.PrivateKey) - client, err := connInfo.NewClient() - if err != nil { - helper.SuccessWithData(c, false) - return - } - defer client.Close() - helper.SuccessWithData(c, true) + connStatus := hostService.TestByInfo(req) + helper.SuccessWithData(c, connStatus) } // @Tags Host @@ -270,11 +245,13 @@ func (b *BaseApi) UpdateHost(c *gin.Context) { upMap["port"] = req.Port upMap["user"] = req.User upMap["auth_mode"] = req.AuthMode + upMap["remember_password"] = req.RememberPassword if len(req.Password) != 0 { upMap["password"] = req.Password } if len(req.PrivateKey) != 0 { upMap["private_key"] = req.PrivateKey + upMap["pass_phrase"] = req.PassPhrase } upMap["description"] = req.Description if err := hostService.Update(req.ID, upMap); err != nil { @@ -291,7 +268,7 @@ func (b *BaseApi) UpdateHost(c *gin.Context) { // @Param request body dto.ChangeHostGroup true "request" // @Success 200 // @Security ApiKeyAuth -// @Router /hosts/update [post] +// @Router /hosts/update/group [post] // @x-panel-log {"bodyKeys":["id","group"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"hosts","output_colume":"addr","output_value":"addr"}],"formatZH":"切换主机[addr]分组 => [group]","formatEN":"change host [addr] group => [group]"} func (b *BaseApi) UpdateHostGroup(c *gin.Context) { var req dto.ChangeHostGroup diff --git a/backend/app/api/v1/monitor.go b/backend/app/api/v1/monitor.go index 1eb5a6d7f..b1d12e11c 100644 --- a/backend/app/api/v1/monitor.go +++ b/backend/app/api/v1/monitor.go @@ -1,6 +1,7 @@ package v1 import ( + "sort" "time" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" @@ -88,6 +89,7 @@ func (b *BaseApi) GetNetworkOptions(c *gin.Context) { for _, net := range netStat { options = append(options, net.Name) } + sort.Strings(options) helper.SuccessWithData(c, options) } @@ -98,5 +100,6 @@ func (b *BaseApi) GetIOOptions(c *gin.Context) { for _, net := range diskStat { options = append(options, net.Name) } + sort.Strings(options) helper.SuccessWithData(c, options) } diff --git a/backend/app/api/v1/runtime.go b/backend/app/api/v1/runtime.go new file mode 100644 index 000000000..0a5a73256 --- /dev/null +++ b/backend/app/api/v1/runtime.go @@ -0,0 +1,123 @@ +package v1 + +import ( + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/gin-gonic/gin" +) + +// @Tags Runtime +// @Summary List runtimes +// @Description 获取运行环境列表 +// @Accept json +// @Param request body request.RuntimeSearch true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/search [post] +func (b *BaseApi) SearchRuntimes(c *gin.Context) { + var req request.RuntimeSearch + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + total, items, err := runtimeService.Page(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, dto.PageResult{ + Total: total, + Items: items, + }) +} + +// @Tags Runtime +// @Summary Create runtime +// @Description 创建运行环境 +// @Accept json +// @Param request body request.RuntimeCreate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes [post] +// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建运行环境 [name]","formatEN":"Create runtime [name]"} +func (b *BaseApi) CreateRuntime(c *gin.Context) { + var req request.RuntimeCreate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := runtimeService.Create(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} + +// @Tags Website +// @Summary Delete runtime +// @Description 删除运行环境 +// @Accept json +// @Param request body request.RuntimeDelete true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/del [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"删除网站 [name]","formatEN":"Delete website [name]"} +func (b *BaseApi) DeleteRuntime(c *gin.Context) { + var req request.RuntimeDelete + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + err := runtimeService.Delete(req.ID) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} + +// @Tags Runtime +// @Summary Update runtime +// @Description 更新运行环境 +// @Accept json +// @Param request body request.RuntimeUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/update [post] +// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新运行环境 [name]","formatEN":"Update runtime [name]"} +func (b *BaseApi) UpdateRuntime(c *gin.Context) { + var req request.RuntimeUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := runtimeService.Update(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} + +// @Tags Runtime +// @Summary Get runtime +// @Description 获取运行环境 +// @Accept json +// @Param id path string true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/:id [get] +func (b *BaseApi) GetRuntime(c *gin.Context) { + id, err := helper.GetIntParamByKey(c, "id") + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) + return + } + res, err := runtimeService.Get(id) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, res) +} diff --git a/backend/app/api/v1/terminal.go b/backend/app/api/v1/terminal.go index 7f6e74aec..736d16338 100644 --- a/backend/app/api/v1/terminal.go +++ b/backend/app/api/v1/terminal.go @@ -1,6 +1,8 @@ package v1 import ( + "encoding/base64" + "encoding/json" "fmt" "net/http" "strconv" @@ -42,6 +44,9 @@ func (b *BaseApi) WsSsh(c *gin.Context) { var connInfo ssh.ConnInfo _ = copier.Copy(&connInfo, &host) connInfo.PrivateKey = []byte(host.PrivateKey) + if len(host.PassPhrase) != 0 { + connInfo.PassPhrase = []byte(host.PassPhrase) + } wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) if err != nil { @@ -196,7 +201,15 @@ func wshandleError(ws *websocket.Conn, err error) bool { global.LOG.Errorf("handler ws faled:, err: %v", err) dt := time.Now().Add(time.Second) if ctlerr := ws.WriteControl(websocket.CloseMessage, []byte(err.Error()), dt); ctlerr != nil { - _ = ws.WriteMessage(websocket.TextMessage, []byte(err.Error())) + wsData, err := json.Marshal(terminal.WsMsg{ + Type: terminal.WsMsgCmd, + Data: base64.StdEncoding.EncodeToString([]byte(err.Error())), + }) + if err != nil { + _ = ws.WriteMessage(websocket.TextMessage, []byte("{\"type\":\"cmd\",\"data\":\"failed to encoding to json\"}")) + } else { + _ = ws.WriteMessage(websocket.TextMessage, wsData) + } } return true } diff --git a/backend/app/api/v1/upgrade.go b/backend/app/api/v1/upgrade.go index 997342542..7cd7567a3 100644 --- a/backend/app/api/v1/upgrade.go +++ b/backend/app/api/v1/upgrade.go @@ -22,6 +22,28 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) { helper.SuccessWithData(c, info) } +// @Tags System Setting +// @Summary Load release notes by version +// @Description 获取版本 release notes +// @Accept json +// @Param request body dto.Upgrade true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /settings/upgrade [get] +func (b *BaseApi) GetNotesByVersion(c *gin.Context) { + var req dto.Upgrade + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + notes, err := upgradeService.LoadNotes(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, notes) +} + // @Tags System Setting // @Summary Upgrade // @Description 系统更新 diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go index dd4e36480..5c7089523 100644 --- a/backend/app/api/v1/website.go +++ b/backend/app/api/v1/website.go @@ -78,14 +78,12 @@ func (b *BaseApi) CreateWebsite(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - tx, ctx := helper.GetTxAndContext() - err := websiteService.CreateWebsite(ctx, req) + + err := websiteService.CreateWebsite(req) if err != nil { - tx.Rollback() helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - tx.Commit() helper.SuccessWithData(c, nil) } @@ -127,14 +125,12 @@ func (b *BaseApi) DeleteWebsite(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - tx, ctx := helper.GetTxAndContext() - err := websiteService.DeleteWebsite(ctx, req) + + err := websiteService.DeleteWebsite(req) if err != nil { - tx.Rollback() helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - tx.Commit() helper.SuccessWithData(c, nil) } @@ -189,14 +185,16 @@ func (b *BaseApi) GetWebsite(c *gin.Context) { // @Param id path integer true "request" // @Success 200 {object} response.FileInfo // @Security ApiKeyAuth -// @Router /websites/:id/nginx [get] +// @Router /websites/:id/config/:type [get] func (b *BaseApi) GetWebsiteNginx(c *gin.Context) { id, err := helper.GetParamID(c) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) return } - fileInfo, err := websiteService.GetWebsiteNginxConfig(id) + configType := c.Param("type") + + fileInfo, err := websiteService.GetWebsiteNginxConfig(id, configType) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -496,3 +494,157 @@ func (b *BaseApi) ChangeDefaultServer(c *gin.Context) { } helper.SuccessWithData(c, nil) } + +// @Tags Website +// @Summary Load websit php conf +// @Description 获取网站 php 配置 +// @Accept json +// @Param id path integer true "request" +// @Success 200 {object} response.PHPConfig +// @Security ApiKeyAuth +// @Router /websites/php/config/:id [get] +func (b *BaseApi) GetWebsitePHPConfig(c *gin.Context) { + id, err := helper.GetParamID(c) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) + return + } + data, err := websiteService.GetPHPConfig(id) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, data) +} + +// @Tags Website PHP +// @Summary Update website php conf +// @Description 更新 网站 PHP 配置 +// @Accept json +// @Param request body request.WebsitePHPConfigUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/php/config [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"[domain] PHP 配置修改","formatEN":"[domain] PHP conf update"} +func (b *BaseApi) UpdateWebsitePHPConfig(c *gin.Context) { + var req request.WebsitePHPConfigUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := websiteService.UpdatePHPConfig(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Website PHP +// @Summary Update php conf +// @Description 更新 php 配置 +// @Accept json +// @Param request body request.WebsitePHPFileUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/php/update [post] +// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"websiteId","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"php 配置修改 [domain]","formatEN":"Nginx conf update [domain]"} +func (b *BaseApi) UpdatePHPFile(c *gin.Context) { + var req request.WebsitePHPFileUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := websiteService.UpdatePHPConfigFile(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Website +// @Summary Get rewrite conf +// @Description 获取伪静态配置 +// @Accept json +// @Param request body request.NginxRewriteReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/rewrite [post] +func (b *BaseApi) GetRewriteConfig(c *gin.Context) { + var req request.NginxRewriteReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + res, err := websiteService.GetRewriteConfig(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, res) +} + +// @Tags Website +// @Summary Update rewrite conf +// @Description 更新伪静态配置 +// @Accept json +// @Param request body request.NginxRewriteUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/rewrite/update [post] +// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"websiteID","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"伪静态配置修改 [domain]","formatEN":"Nginx conf rewrite update [domain]"} +func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) { + var req request.NginxRewriteUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := websiteService.UpdateRewriteConfig(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Website +// @Summary Update Site Dir +// @Description 更新网站目录 +// @Accept json +// @Param request body request.WebsiteUpdateDir true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/dir/update [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录","formatEN":"Update domain [domain] dir"} +func (b *BaseApi) UpdateSiteDir(c *gin.Context) { + var req request.WebsiteUpdateDir + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := websiteService.UpdateSiteDir(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} + +// @Tags Website +// @Summary Update Site Dir permission +// @Description 更新网站目录权限 +// @Accept json +// @Param request body request.WebsiteUpdateDirPermission true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/dir/permission [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录权限","formatEN":"Update domain [domain] dir permission"} +func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) { + var req request.WebsiteUpdateDirPermission + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := websiteService.UpdateSitePermission(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} diff --git a/backend/app/api/v1/website_group.go b/backend/app/api/v1/website_group.go deleted file mode 100644 index 92d3bbdf2..000000000 --- a/backend/app/api/v1/website_group.go +++ /dev/null @@ -1,89 +0,0 @@ -package v1 - -import ( - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/gin-gonic/gin" -) - -// @Tags Website Group -// @Summary List website groups -// @Description 获取网站组 -// @Success 200 {anrry} model.WebsiteGroup -// @Security ApiKeyAuth -// @Router /websites/groups [get] -func (b *BaseApi) GetWebGroups(c *gin.Context) { - list, err := websiteGroupService.GetGroups() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, list) -} - -// @Tags Website Group -// @Summary Create website group -// @Description 创建网站组 -// @Accept json -// @Param request body request.WebsiteGroupCreate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/groups [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建网站组 [name]","formatEN":"Create website groups [name]"} -func (b *BaseApi) CreateWebGroup(c *gin.Context) { - var req request.WebsiteGroupCreate - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - if err := websiteGroupService.CreateGroup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website Group -// @Summary Update website group -// @Description 更新网站组 -// @Accept json -// @Param request body request.WebsiteGroupUpdate true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/groups/update [post] -// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新网站组 [name]","formatEN":"Update website groups [name]"} -func (b *BaseApi) UpdateWebGroup(c *gin.Context) { - var req request.WebsiteGroupUpdate - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - if err := websiteGroupService.UpdateGroup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - -// @Tags Website Group -// @Summary Delete website group -// @Description 删除网站组 -// @Accept json -// @Param request body request.WebsiteResourceReq true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /websites/groups/del [post] -// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"website_groups","output_colume":"name","output_value":"name"}],"formatZH":"删除网站组 [name]","formatEN":"Delete website group [name]"} -func (b *BaseApi) DeleteWebGroup(c *gin.Context) { - var req request.WebsiteResourceReq - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - if err := websiteGroupService.DeleteGroup(req.ID); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} diff --git a/backend/app/api/v1/website_ssl.go b/backend/app/api/v1/website_ssl.go index dde6e9a9b..ca8f4e4b8 100644 --- a/backend/app/api/v1/website_ssl.go +++ b/backend/app/api/v1/website_ssl.go @@ -176,3 +176,25 @@ func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) { } helper.SuccessWithData(c, websiteSSL) } + +// @Tags Website SSL +// @Summary Update ssl +// @Description 更新 ssl +// @Accept json +// @Param request body request.WebsiteSSLUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/ssl/update [post] +// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"website_ssls","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"更新证书设置 [domain]","formatEN":"Update ssl config [domain]"} +func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) { + var req request.WebsiteSSLUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := websiteSSLService.Update(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/dto/app.go b/backend/app/dto/app.go index f8245e994..0f77a03f3 100644 --- a/backend/app/dto/app.go +++ b/backend/app/dto/app.go @@ -69,15 +69,22 @@ type AppForm struct { } type AppFormFields struct { - Type string `json:"type"` - LabelZh string `json:"labelZh"` - LabelEn string `json:"labelEn"` - Required bool `json:"required"` - Default interface{} `json:"default"` - EnvKey string `json:"envKey"` - Disabled bool `json:"disabled"` - Edit bool `json:"edit"` - Rule string `json:"rule"` + Type string `json:"type"` + LabelZh string `json:"labelZh"` + LabelEn string `json:"labelEn"` + Required bool `json:"required"` + Default interface{} `json:"default"` + EnvKey string `json:"envKey"` + Disabled bool `json:"disabled"` + Edit bool `json:"edit"` + Rule string `json:"rule"` + Multiple bool `json:"multiple"` + Values []AppFormValue `json:"values"` +} + +type AppFormValue struct { + Label string `json:"label"` + Value string `json:"value"` } type AppResource struct { diff --git a/backend/app/dto/auth.go b/backend/app/dto/auth.go index 467bfa55f..1b385f378 100644 --- a/backend/app/dto/auth.go +++ b/backend/app/dto/auth.go @@ -9,7 +9,6 @@ type UserLoginInfo struct { Name string `json:"name"` Token string `json:"token"` MfaStatus string `json:"mfaStatus"` - MfaSecret string `json:"mfaSecret"` } type MfaCredential struct { @@ -28,7 +27,6 @@ type Login struct { type MFALogin struct { Name string `json:"name"` Password string `json:"password"` - Secret string `json:"secret"` Code string `json:"code"` AuthMethod string `json:"authMethod"` } diff --git a/backend/app/dto/backup.go b/backend/app/dto/backup.go index 9e1685ddb..a180d1586 100644 --- a/backend/app/dto/backup.go +++ b/backend/app/dto/backup.go @@ -59,7 +59,7 @@ type BackupRecords struct { } type DownloadRecord struct { - Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL"` + Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO"` FileDir string `json:"fileDir" validate:"required"` FileName string `json:"fileName" validate:"required"` } diff --git a/backend/app/dto/cronjob.go b/backend/app/dto/cronjob.go index 8739a8197..e72efb983 100644 --- a/backend/app/dto/cronjob.go +++ b/backend/app/dto/cronjob.go @@ -52,6 +52,16 @@ type CronjobDownload struct { BackupAccountID uint `json:"backupAccountID" validate:"required"` } +type CronjobClean struct { + CleanData bool `json:"cleanData"` + CronjobID uint `json:"cronjobID" validate:"required"` +} + +type CronjobBatchDelete struct { + CleanData bool `json:"cleanData"` + IDs []uint `json:"ids"` +} + type CronjobInfo struct { ID uint `json:"id"` Name string `json:"name"` diff --git a/backend/app/dto/dashboard.go b/backend/app/dto/dashboard.go index 565d03009..1efcd72a0 100644 --- a/backend/app/dto/dashboard.go +++ b/backend/app/dto/dashboard.go @@ -3,13 +3,6 @@ package dto import "time" type DashboardBase struct { - HaloID uint `json:"haloID"` - DateeaseID uint `json:"dateeaseID"` - JumpServerID uint `json:"jumpserverID"` - MeterSphereID uint `json:"metersphereID"` - KubeoperatorID uint `json:"kubeoperatorID"` - KubepiID uint `json:"kubepiID"` - WebsiteNumber int `json:"websiteNumber"` DatabaseNumber int `json:"databaseNumber"` CronjobNumber int `json:"cronjobNumber"` @@ -55,8 +48,21 @@ type DashboardCurrent struct { IOReadBytes uint64 `json:"ioReadBytes"` IOWriteBytes uint64 `json:"ioWriteBytes"` IOCount uint64 `json:"ioCount"` - IOTime uint64 `json:"ioTime"` + IOReadTime uint64 `json:"ioReadTime"` + IOWriteTime uint64 `json:"ioWriteTime"` + DiskData []DiskInfo `json:"diskData"` + + NetBytesSent uint64 `json:"netBytesSent"` + NetBytesRecv uint64 `json:"netBytesRecv"` + + ShotTime time.Time `json:"shotTime"` +} + +type DiskInfo struct { + Path string `json:"path"` + Type string `json:"type"` + Device string `json:"device"` Total uint64 `json:"total"` Free uint64 `json:"free"` Used uint64 `json:"used"` @@ -66,9 +72,4 @@ type DashboardCurrent struct { InodesUsed uint64 `json:"inodesUsed"` InodesFree uint64 `json:"inodesFree"` InodesUsedPercent float64 `json:"inodesUsedPercent"` - - NetBytesSent uint64 `json:"netBytesSent"` - NetBytesRecv uint64 `json:"netBytesRecv"` - - ShotTime time.Time `json:"shotTime"` } diff --git a/backend/app/dto/docker.go b/backend/app/dto/docker.go index 42bddcc15..240794d9e 100644 --- a/backend/app/dto/docker.go +++ b/backend/app/dto/docker.go @@ -5,11 +5,13 @@ type DaemonJsonUpdateByFile struct { } type DaemonJsonConf struct { + IsSwarm bool `json:"isSwarm"` Status string `json:"status"` Version string `json:"version"` Mirrors []string `json:"registryMirrors"` Registries []string `json:"insecureRegistries"` LiveRestore bool `json:"liveRestore"` + IPTables bool `json:"iptables"` CgroupDriver string `json:"cgroupDriver"` } diff --git a/backend/app/dto/firewall.go b/backend/app/dto/firewall.go new file mode 100644 index 000000000..9f534a09a --- /dev/null +++ b/backend/app/dto/firewall.go @@ -0,0 +1,47 @@ +package dto + +type FirewallBaseInfo struct { + Name string `json:"name"` + Status string `json:"status"` + Version string `json:"version"` + PingStatus string `json:"pingStatus"` +} + +type RuleSearch struct { + PageInfo + Info string `json:"info"` + Type string `json:"type" validate:"required"` +} + +type FirewallOperation struct { + Operation string `json:"operation" validate:"required,oneof=start stop disablePing enablePing"` +} + +type PortRuleOperate struct { + Operation string `json:"operation" validate:"required,oneof=add remove"` + Address string `json:"address"` + Port string `json:"port" validate:"required"` + Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"` + Strategy string `json:"strategy" validate:"required,oneof=accept drop"` +} + +type AddrRuleOperate struct { + Operation string `json:"operation" validate:"required,oneof=add remove"` + Address string `json:"address" validate:"required"` + Strategy string `json:"strategy" validate:"required,oneof=accept drop"` +} + +type PortRuleUpdate struct { + OldRule PortRuleOperate `json:"oldRule"` + NewRule PortRuleOperate `json:"newRule"` +} + +type AddrRuleUpdate struct { + OldRule AddrRuleOperate `json:"oldRule"` + NewRule AddrRuleOperate `json:"newRule"` +} + +type BatchRuleOperate struct { + Type string `json:"type" validate:"required"` + Rules []PortRuleOperate `json:"rules"` +} diff --git a/backend/app/dto/group.go b/backend/app/dto/group.go index 387d492a2..60179d7ac 100644 --- a/backend/app/dto/group.go +++ b/backend/app/dto/group.go @@ -13,6 +13,7 @@ type GroupSearch struct { type GroupUpdate struct { ID uint `json:"id"` Name string `json:"name"` + Type string `json:"type" validate:"required"` IsDefault bool `json:"isDefault"` } diff --git a/backend/app/dto/host.go b/backend/app/dto/host.go index 3d510404f..9853d8f34 100644 --- a/backend/app/dto/host.go +++ b/backend/app/dto/host.go @@ -5,15 +5,17 @@ import ( ) type HostOperate struct { - ID uint `json:"id"` - GroupID uint `json:"groupID"` - Name string `json:"name"` - Addr string `json:"addr" validate:"required"` - Port uint `json:"port" validate:"required,number,max=65535,min=1"` - User string `json:"user" validate:"required"` - AuthMode string `json:"authMode" validate:"oneof=password key"` - PrivateKey string `json:"privateKey"` - Password string `json:"password"` + ID uint `json:"id"` + GroupID uint `json:"groupID"` + Name string `json:"name"` + Addr string `json:"addr" validate:"required"` + Port uint `json:"port" validate:"required,number,max=65535,min=1"` + User string `json:"user" validate:"required"` + AuthMode string `json:"authMode" validate:"oneof=password key"` + Password string `json:"password"` + PrivateKey string `json:"privateKey"` + PassPhrase string `json:"passPhrase"` + RememberPassword bool `json:"rememberPassword"` Description string `json:"description"` } @@ -23,8 +25,9 @@ type HostConnTest struct { Port uint `json:"port" validate:"required,number,max=65535,min=1"` User string `json:"user" validate:"required"` AuthMode string `json:"authMode" validate:"oneof=password key"` - PrivateKey string `json:"privateKey"` Password string `json:"password"` + PrivateKey string `json:"privateKey"` + PassPhrase string `json:"passPhrase"` } type SearchHostWithPage struct { @@ -43,15 +46,19 @@ type ChangeHostGroup struct { } type HostInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - GroupID uint `json:"groupID"` - GroupBelong string `json:"groupBelong"` - Name string `json:"name"` - Addr string `json:"addr"` - Port uint `json:"port"` - User string `json:"user"` - AuthMode string `json:"authMode"` + ID uint `json:"id"` + CreatedAt time.Time `json:"createdAt"` + GroupID uint `json:"groupID"` + GroupBelong string `json:"groupBelong"` + Name string `json:"name"` + Addr string `json:"addr"` + Port uint `json:"port"` + User string `json:"user"` + AuthMode string `json:"authMode"` + Password string `json:"password"` + PrivateKey string `json:"privateKey"` + PassPhrase string `json:"passPhrase"` + RememberPassword bool `json:"rememberPassword"` Description string `json:"description"` } diff --git a/backend/app/dto/request/nginx.go b/backend/app/dto/request/nginx.go index 7e2b0f18a..0fa085b0a 100644 --- a/backend/app/dto/request/nginx.go +++ b/backend/app/dto/request/nginx.go @@ -19,3 +19,14 @@ type NginxConfigUpdate struct { WebsiteID uint `json:"websiteId" validate:"required"` Params interface{} `json:"params"` } + +type NginxRewriteReq struct { + WebsiteID uint `json:"websiteId" validate:"required"` + Name string `json:"name" validate:"required"` +} + +type NginxRewriteUpdate struct { + WebsiteID uint `json:"websiteId" validate:"required"` + Name string `json:"name" validate:"required"` + Content string `json:"content" validate:"required"` +} diff --git a/backend/app/dto/request/runtime.go b/backend/app/dto/request/runtime.go new file mode 100644 index 000000000..96b838453 --- /dev/null +++ b/backend/app/dto/request/runtime.go @@ -0,0 +1,32 @@ +package request + +import "github.com/1Panel-dev/1Panel/backend/app/dto" + +type RuntimeSearch struct { + dto.PageInfo + Type string `json:"type"` + Name string `json:"name"` + Status string `json:"status"` +} + +type RuntimeCreate struct { + AppDetailID uint `json:"appDetailId"` + Name string `json:"name"` + Params map[string]interface{} `json:"params"` + Resource string `json:"resource"` + Image string `json:"image"` + Type string `json:"type"` + Version string `json:"version"` +} + +type RuntimeDelete struct { + ID uint `json:"id"` +} + +type RuntimeUpdate struct { + Name string `json:"name"` + ID uint `json:"id"` + Params map[string]interface{} `json:"params"` + Image string `json:"image"` + Version string `json:"version"` +} diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go index 22c67a6a3..9e7b4f4a1 100644 --- a/backend/app/dto/request/website.go +++ b/backend/app/dto/request/website.go @@ -23,6 +23,14 @@ type WebsiteCreate struct { AppInstall NewAppInstall `json:"appInstall"` AppID uint `json:"appID"` AppInstallID uint `json:"appInstallID"` + + RuntimeID uint `json:"runtimeID"` + RuntimeConfig +} + +type RuntimeConfig struct { + ProxyType string `json:"proxyType"` + Port int `json:"port"` } type NewAppInstall struct { @@ -126,3 +134,25 @@ type WebsiteLogReq struct { type WebsiteDefaultUpdate struct { ID uint `json:"id" validate:"required"` } + +type WebsitePHPConfigUpdate struct { + ID uint `json:"id" validate:"required"` + Params map[string]string `json:"params" validate:"required"` +} + +type WebsitePHPFileUpdate struct { + ID uint `json:"id" validate:"required"` + Type string `json:"type" validate:"required"` + Content string `json:"content" validate:"required"` +} + +type WebsiteUpdateDir struct { + ID uint `json:"id" validate:"required"` + SiteDir string `json:"siteDir" validate:"required"` +} + +type WebsiteUpdateDirPermission struct { + ID uint `json:"id" validate:"required"` + User string `json:"user" validate:"required"` + Group string `json:"group" validate:"required"` +} diff --git a/backend/app/dto/request/website_ssl.go b/backend/app/dto/request/website_ssl.go index f4d125104..b385006ca 100644 --- a/backend/app/dto/request/website_ssl.go +++ b/backend/app/dto/request/website_ssl.go @@ -44,3 +44,8 @@ type WebsiteDnsAccountUpdate struct { type WebsiteResourceReq struct { ID uint `json:"id" validate:"required"` } + +type WebsiteSSLUpdate struct { + ID uint `json:"id" validate:"required"` + AutoRenew bool `json:"autoRenew" validate:"required"` +} diff --git a/backend/app/dto/response/app.go b/backend/app/dto/response/app.go index 338865dd5..f9ac0b3de 100644 --- a/backend/app/dto/response/app.go +++ b/backend/app/dto/response/app.go @@ -1,8 +1,9 @@ package response import ( - "github.com/1Panel-dev/1Panel/backend/app/model" "time" + + "github.com/1Panel-dev/1Panel/backend/app/model" ) type AppRes struct { @@ -43,6 +44,7 @@ type AppDetailDTO struct { model.AppDetail Enable bool `json:"enable"` Params interface{} `json:"params"` + Image string `json:"image"` } type AppInstalledDTO struct { @@ -54,6 +56,12 @@ type AppInstalledDTO struct { CanUpdate bool `json:"canUpdate"` } +type DatabaseConn struct { + Password string `json:"password"` + ServiceName string `json:"serviceName"` + Port int64 `json:"port"` +} + type AppService struct { Label string `json:"label"` Value string `json:"value"` @@ -61,11 +69,15 @@ type AppService struct { } type AppParam struct { - Value interface{} `json:"value"` - Edit bool `json:"edit"` - Key string `json:"key"` - Rule string `json:"rule"` - LabelZh string `json:"labelZh"` - LabelEn string `json:"labelEn"` - Type string `json:"type"` + Value interface{} `json:"value"` + Edit bool `json:"edit"` + Key string `json:"key"` + Rule string `json:"rule"` + LabelZh string `json:"labelZh"` + LabelEn string `json:"labelEn"` + Type string `json:"type"` + Values interface{} `json:"values"` + ShowValue string `json:"showValue"` + Required bool `json:"required"` + Multiple bool `json:"multiple"` } diff --git a/backend/app/dto/response/runtime.go b/backend/app/dto/response/runtime.go new file mode 100644 index 000000000..b6674d284 --- /dev/null +++ b/backend/app/dto/response/runtime.go @@ -0,0 +1,9 @@ +package response + +import "github.com/1Panel-dev/1Panel/backend/app/model" + +type RuntimeRes struct { + model.Runtime + AppParams []AppParam `json:"appParams"` + AppID uint `json:"appId"` +} diff --git a/backend/app/dto/response/website.go b/backend/app/dto/response/website.go index 206deea81..699a53de3 100644 --- a/backend/app/dto/response/website.go +++ b/backend/app/dto/response/website.go @@ -10,6 +10,7 @@ type WebsiteDTO struct { AccessLogPath string `json:"accessLogPath"` SitePath string `json:"sitePath"` AppName string `json:"appName"` + RuntimeName string `json:"runtimeName"` } type WebsitePreInstallCheck struct { @@ -42,3 +43,11 @@ type WebsiteLog struct { Enable bool `json:"enable"` Content string `json:"content"` } + +type PHPConfig struct { + Params map[string]string `json:"params"` +} + +type NginxRewriteRes struct { + Content string `json:"content"` +} diff --git a/backend/app/dto/setting.go b/backend/app/dto/setting.go index 6290f3203..ee399ccbe 100644 --- a/backend/app/dto/setting.go +++ b/backend/app/dto/setting.go @@ -49,7 +49,7 @@ type PortUpdate struct { } type SnapshotCreate struct { - From string `json:"from" validate:"required,oneof=OSS S3 SFTP MINIO"` + From string `json:"from" validate:"required,oneof=OSS S3 SFTP MINIO COS KODO"` Description string `json:"description"` } type SnapshotRecover struct { @@ -82,9 +82,11 @@ type SnapshotInfo struct { } type UpgradeInfo struct { - NewVersion string `json:"newVersion"` - ReleaseNote string `json:"releaseNote"` + NewVersion string `json:"newVersion"` + LatestVersion string `json:"latestVersion"` + ReleaseNote string `json:"releaseNote"` } + type Upgrade struct { Version string `json:"version"` } diff --git a/backend/app/model/app.go b/backend/app/model/app.go index 58b4b834f..1772d4042 100644 --- a/backend/app/model/app.go +++ b/backend/app/model/app.go @@ -16,6 +16,7 @@ type App struct { Github string `json:"github" gorm:"type:varchar(64);not null"` Document string `json:"document" gorm:"type:varchar(64);not null"` Recommend int `json:"recommend" gorm:"type:Integer;not null"` + Resource string `json:"resource" gorm:"type:varchar;not null;default:remote"` Details []AppDetail `json:"-" gorm:"-:migration"` TagsKey []string `json:"-" gorm:"-"` AppTags []AppTag `json:"-" gorm:"-:migration"` diff --git a/backend/app/model/app_install.go b/backend/app/model/app_install.go index dbc9e1423..0049b637d 100644 --- a/backend/app/model/app_install.go +++ b/backend/app/model/app_install.go @@ -2,6 +2,7 @@ package model import ( "path" + "strings" "github.com/1Panel-dev/1Panel/backend/constant" ) @@ -26,9 +27,21 @@ type AppInstall struct { } func (i *AppInstall) GetPath() string { - return path.Join(constant.AppInstallDir, i.App.Key, i.Name) + return path.Join(i.getAppPath(), i.Name) } func (i *AppInstall) GetComposePath() string { - return path.Join(constant.AppInstallDir, i.App.Key, i.Name, "docker-compose.yml") + return path.Join(i.getAppPath(), i.Name, "docker-compose.yml") +} + +func (i *AppInstall) GetEnvPath() string { + return path.Join(i.getAppPath(), i.Name, ".env") +} + +func (i *AppInstall) getAppPath() string { + if i.App.Resource == constant.AppResourceLocal { + return path.Join(constant.LocalAppInstallDir, strings.TrimPrefix(i.App.Key, constant.AppResourceLocal)) + } else { + return path.Join(constant.AppInstallDir, i.App.Key) + } } diff --git a/backend/app/model/host.go b/backend/app/model/host.go index b25a57b82..a4fe6aedd 100644 --- a/backend/app/model/host.go +++ b/backend/app/model/host.go @@ -2,14 +2,17 @@ package model type Host struct { BaseModel - GroupID uint `gorm:"type:decimal;not null" json:"group_id"` - Name string `gorm:"type:varchar(64);not null" json:"name"` - Addr string `gorm:"type:varchar(16);not null" json:"addr"` - Port int `gorm:"type:decimal;not null" json:"port"` - User string `gorm:"type:varchar(64);not null" json:"user"` - AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"` - Password string `gorm:"type:varchar(64)" json:"password"` - PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"` + + GroupID uint `gorm:"type:decimal;not null" json:"group_id"` + Name string `gorm:"type:varchar(64);not null" json:"name"` + Addr string `gorm:"type:varchar(16);not null" json:"addr"` + Port int `gorm:"type:decimal;not null" json:"port"` + User string `gorm:"type:varchar(64);not null" json:"user"` + AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"` + Password string `gorm:"type:varchar(64)" json:"password"` + PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"` + PassPhrase string `gorm:"type:varchar(256)" json:"passPhrase"` + RememberPassword bool `json:"rememberPassword"` Description string `gorm:"type:varchar(256)" json:"description"` } diff --git a/backend/app/model/runtime.go b/backend/app/model/runtime.go new file mode 100644 index 000000000..de2e002f6 --- /dev/null +++ b/backend/app/model/runtime.go @@ -0,0 +1,17 @@ +package model + +type Runtime struct { + BaseModel + Name string `gorm:"type:varchar;not null" json:"name"` + AppDetailID uint `gorm:"type:integer" json:"appDetailId"` + Image string `gorm:"type:varchar" json:"image"` + WorkDir string `gorm:"type:varchar" json:"workDir"` + DockerCompose string `gorm:"type:varchar" json:"dockerCompose"` + Env string `gorm:"type:varchar" json:"env"` + Params string `gorm:"type:varchar" json:"params"` + Version string `gorm:"type:varchar;not null" json:"version"` + Type string `gorm:"type:varchar;not null" json:"type"` + Status string `gorm:"type:varchar;not null" json:"status"` + Resource string `gorm:"type:varchar;not null" json:"resource"` + Message string `gorm:"type:longtext;" json:"message"` +} diff --git a/backend/app/model/website.go b/backend/app/model/website.go index 7f3a7a099..08d2754c4 100644 --- a/backend/app/model/website.go +++ b/backend/app/model/website.go @@ -4,23 +4,33 @@ import "time" type Website struct { BaseModel - Protocol string `gorm:"type:varchar(64);not null" json:"protocol"` - PrimaryDomain string `gorm:"type:varchar(128);not null" json:"primaryDomain"` - Type string `gorm:"type:varchar(64);not null" json:"type"` - Alias string `gorm:"type:varchar(128);not null" json:"alias"` - Remark string `gorm:"type:longtext;" json:"remark"` - Status string `gorm:"type:varchar(64);not null" json:"status"` - HttpConfig string `gorm:"type:varchar(64);not null" json:"httpConfig"` - ExpireDate time.Time `json:"expireDate"` - AppInstallID uint `gorm:"type:integer" json:"appInstallId"` - WebsiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"` - WebsiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"` - Proxy string `gorm:"type:varchar(128);not null" json:"proxy"` - ErrorLog bool `json:"errorLog"` - AccessLog bool `json:"accessLog"` - DefaultServer bool `json:"defaultServer"` - Domains []WebsiteDomain `json:"domains" gorm:"-:migration"` - WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"` + Protocol string `gorm:"type:varchar;not null" json:"protocol"` + PrimaryDomain string `gorm:"type:varchar;not null" json:"primaryDomain"` + Type string `gorm:"type:varchar;not null" json:"type"` + Alias string `gorm:"type:varchar;not null" json:"alias"` + Remark string `gorm:"type:longtext;" json:"remark"` + Status string `gorm:"type:varchar;not null" json:"status"` + HttpConfig string `gorm:"type:varchar;not null" json:"httpConfig"` + ExpireDate time.Time `json:"expireDate"` + + Proxy string `gorm:"type:varchar;" json:"proxy"` + ProxyType string `gorm:"type:varchar;" json:"proxyType"` + SiteDir string `gorm:"type:varchar;" json:"siteDir"` + ErrorLog bool `json:"errorLog"` + AccessLog bool `json:"accessLog"` + DefaultServer bool `json:"defaultServer"` + Rewrite string `gorm:"type:varchar" json:"rewrite"` + + WebsiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"` + WebsiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"` + RuntimeID uint `gorm:"type:integer" json:"runtimeID"` + AppInstallID uint `gorm:"type:integer" json:"appInstallId"` + + User string `gorm:"type:varchar;" json:"user"` + Group string `gorm:"type:varchar;" json:"group"` + + Domains []WebsiteDomain `json:"domains" gorm:"-:migration"` + WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"` } func (w Website) TableName() string { diff --git a/backend/app/model/website_group.go b/backend/app/model/website_group.go deleted file mode 100644 index f0634c619..000000000 --- a/backend/app/model/website_group.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type WebsiteGroup struct { - BaseModel - Name string `gorm:"type:varchar(64);not null" json:"name"` - Default bool `json:"default"` -} - -func (w WebsiteGroup) TableName() string { - return "website_groups" -} diff --git a/backend/app/repo/app.go b/backend/app/repo/app.go index 01e6cde2b..0e9ca1af9 100644 --- a/backend/app/repo/app.go +++ b/backend/app/repo/app.go @@ -11,6 +11,25 @@ import ( type AppRepo struct { } +type IAppRepo interface { + WithKey(key string) DBOption + WithType(typeStr string) DBOption + OrderByRecommend() DBOption + GetRecommend() DBOption + WithResource(resource string) DBOption + Page(page, size int, opts ...DBOption) (int64, []model.App, error) + 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 +} + +func NewIAppRepo() IAppRepo { + return &AppRepo{} +} + func (a AppRepo) WithKey(key string) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("key = ?", key) @@ -35,12 +54,18 @@ func (a AppRepo) GetRecommend() DBOption { } } +func (a AppRepo) WithResource(resource string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("resource = ?", resource) + } +} + func (a AppRepo) Page(page, size int, opts ...DBOption) (int64, []model.App, error) { var apps []model.App db := getDb(opts...).Model(&model.App{}) count := int64(0) db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Preload("AppTags").Find(&apps).Error + err := db.Debug().Limit(size).Offset(size * (page - 1)).Preload("AppTags").Find(&apps).Error return count, apps, err } diff --git a/backend/app/repo/app_detail.go b/backend/app/repo/app_detail.go index 9ad076af5..66e2647a4 100644 --- a/backend/app/repo/app_detail.go +++ b/backend/app/repo/app_detail.go @@ -9,6 +9,21 @@ import ( type AppDetailRepo struct { } +type IAppDetailRepo interface { + WithVersion(version string) DBOption + WithAppId(id uint) DBOption + GetFirst(opts ...DBOption) (model.AppDetail, error) + Update(ctx context.Context, detail model.AppDetail) error + BatchCreate(ctx context.Context, details []model.AppDetail) error + DeleteByAppIds(ctx context.Context, appIds []uint) error + GetBy(opts ...DBOption) ([]model.AppDetail, error) + BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error +} + +func NewIAppDetailRepo() IAppDetailRepo { + return &AppDetailRepo{} +} + func (a AppDetailRepo) WithVersion(version string) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("version = ?", version) diff --git a/backend/app/repo/app_install.go b/backend/app/repo/app_install.go index 79b526cff..e863eebd7 100644 --- a/backend/app/repo/app_install.go +++ b/backend/app/repo/app_install.go @@ -3,6 +3,7 @@ package repo import ( "context" "encoding/json" + "gorm.io/gorm/clause" "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/global" @@ -11,6 +12,31 @@ import ( type AppInstallRepo struct{} +type IAppInstallRepo interface { + WithDetailIdsIn(detailIds []uint) DBOption + WithDetailIdNotIn(detailIds []uint) DBOption + WithAppId(appId uint) DBOption + WithAppIdsIn(appIds []uint) DBOption + WithStatus(status string) DBOption + WithServiceName(serviceName string) DBOption + WithPort(port int) DBOption + WithIdNotInWebsite() DBOption + ListBy(opts ...DBOption) ([]model.AppInstall, error) + GetFirst(opts ...DBOption) (model.AppInstall, error) + Create(ctx context.Context, install *model.AppInstall) error + Save(ctx context.Context, install *model.AppInstall) error + DeleteBy(opts ...DBOption) error + Delete(ctx context.Context, install model.AppInstall) error + Page(page, size int, opts ...DBOption) (int64, []model.AppInstall, error) + BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error + LoadBaseInfo(key string, name string) (*RootInfo, error) + GetFirstByCtx(ctx context.Context, opts ...DBOption) (model.AppInstall, error) +} + +func NewIAppInstallRepo() IAppInstallRepo { + return &AppInstallRepo{} +} + func (a *AppInstallRepo) WithDetailIdsIn(detailIds []uint) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("app_detail_id in (?)", detailIds) @@ -73,13 +99,20 @@ func (a *AppInstallRepo) GetFirst(opts ...DBOption) (model.AppInstall, error) { return install, err } -func (a *AppInstallRepo) Create(ctx context.Context, install *model.AppInstall) error { - db := getTx(ctx).Model(&model.AppInstall{}) - return db.Create(&install).Error +func (a *AppInstallRepo) GetFirstByCtx(ctx context.Context, opts ...DBOption) (model.AppInstall, error) { + var install model.AppInstall + db := getTx(ctx, opts...).Model(&model.AppInstall{}) + err := db.Preload("App").First(&install).Error + return install, err } -func (a *AppInstallRepo) Save(install *model.AppInstall) error { - return getDb().Save(&install).Error +func (a *AppInstallRepo) Create(ctx context.Context, install *model.AppInstall) error { + db := getTx(ctx).Model(&model.AppInstall{}) + return db.Omit(clause.Associations).Create(&install).Error +} + +func (a *AppInstallRepo) Save(ctx context.Context, install *model.AppInstall) error { + return getTx(ctx).Omit(clause.Associations).Save(&install).Error } func (a *AppInstallRepo) DeleteBy(opts ...DBOption) error { @@ -112,8 +145,11 @@ type RootInfo struct { ID uint `json:"id"` Name string `json:"name"` Port int64 `json:"port"` + HttpsPort int64 `json:"httpsPort"` Password string `json:"password"` + UserPassword string `json:"userPassword"` ContainerName string `json:"containerName"` + ServiceName string `json:"serviceName"` Param string `json:"param"` Env string `json:"env"` Key string `json:"key"` @@ -146,8 +182,14 @@ func (a *AppInstallRepo) LoadBaseInfo(key string, name string) (*RootInfo, error if ok { info.Password = password } + userPassword, ok := envMap["PANEL_DB_USER_PASSWORD"].(string) + if ok { + info.UserPassword = userPassword + } info.Port = int64(appInstall.HttpPort) + info.HttpsPort = int64(appInstall.HttpsPort) info.ID = appInstall.ID + info.ServiceName = appInstall.ServiceName info.ContainerName = appInstall.ContainerName info.Name = appInstall.Name info.Env = appInstall.Env diff --git a/backend/app/repo/app_install_resource.go b/backend/app/repo/app_install_resource.go index bb81f5b16..f0718aba4 100644 --- a/backend/app/repo/app_install_resource.go +++ b/backend/app/repo/app_install_resource.go @@ -11,6 +11,20 @@ import ( type AppInstallResourceRpo struct { } +type IAppInstallResourceRpo interface { + WithAppInstallId(appInstallId uint) DBOption + WithLinkId(linkId uint) DBOption + WithResourceId(resourceId uint) DBOption + GetBy(opts ...DBOption) ([]model.AppInstallResource, error) + GetFirst(opts ...DBOption) (model.AppInstallResource, error) + Create(ctx context.Context, resource *model.AppInstallResource) error + DeleteBy(ctx context.Context, opts ...DBOption) error +} + +func NewIAppInstallResourceRpo() IAppInstallResourceRpo { + return &AppInstallResourceRpo{} +} + func (a AppInstallResourceRpo) WithAppInstallId(appInstallId uint) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("app_install_id = ?", appInstallId) diff --git a/backend/app/repo/app_tag.go b/backend/app/repo/app_tag.go index 785fdb203..0f65c91a3 100644 --- a/backend/app/repo/app_tag.go +++ b/backend/app/repo/app_tag.go @@ -8,6 +8,18 @@ import ( type AppTagRepo struct { } +type IAppTagRepo interface { + BatchCreate(ctx context.Context, tags []*model.AppTag) error + DeleteByAppIds(ctx context.Context, appIds []uint) error + DeleteAll(ctx context.Context) error + GetByAppId(appId uint) ([]model.AppTag, error) + GetByTagIds(tagIds []uint) ([]model.AppTag, error) +} + +func NewIAppTagRepo() IAppTagRepo { + return &AppTagRepo{} +} + func (a AppTagRepo) BatchCreate(ctx context.Context, tags []*model.AppTag) error { return getTx(ctx).Create(&tags).Error } diff --git a/backend/app/repo/backup.go b/backend/app/repo/backup.go index 498227e57..28d6f4a6c 100644 --- a/backend/app/repo/backup.go +++ b/backend/app/repo/backup.go @@ -20,6 +20,8 @@ type IBackupRepo interface { Delete(opts ...DBOption) error DeleteRecord(ctx context.Context, opts ...DBOption) error WithByDetailName(detailName string) DBOption + WithByFileName(fileName string) DBOption + WithByType(backupType string) DBOption } func NewIBackupRepo() IBackupRepo { diff --git a/backend/app/repo/command.go b/backend/app/repo/command.go index 4f7fee3f5..a61809617 100644 --- a/backend/app/repo/command.go +++ b/backend/app/repo/command.go @@ -15,6 +15,7 @@ type ICommandRepo interface { Create(command *model.Command) error Update(id uint, vars map[string]interface{}) error Delete(opts ...DBOption) error + Get(opts ...DBOption) (model.Command, error) } func NewICommandRepo() ICommandRepo { diff --git a/backend/app/repo/common.go b/backend/app/repo/common.go index b7563eb6a..8be9ee4ed 100644 --- a/backend/app/repo/common.go +++ b/backend/app/repo/common.go @@ -21,10 +21,15 @@ type ICommonRepo interface { WithIdsIn(ids []uint) DBOption WithByDate(startTime, endTime time.Time) DBOption WithByStartDate(startTime time.Time) DBOption + WithByStatus(status string) DBOption } type CommonRepo struct{} +func NewCommonRepo() ICommonRepo { + return &CommonRepo{} +} + func (c *CommonRepo) WithByID(id uint) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("id = ?", id) diff --git a/backend/app/repo/compose_template.go b/backend/app/repo/compose_template.go index b72f98062..934b1bc34 100644 --- a/backend/app/repo/compose_template.go +++ b/backend/app/repo/compose_template.go @@ -17,6 +17,7 @@ type IComposeTemplateRepo interface { CreateRecord(compose *model.Compose) error DeleteRecord(opts ...DBOption) error + ListRecord() ([]model.Compose, error) } func NewIComposeTemplateRepo() IComposeTemplateRepo { diff --git a/backend/app/repo/cronjob.go b/backend/app/repo/cronjob.go index daa53f167..29f42b545 100644 --- a/backend/app/repo/cronjob.go +++ b/backend/app/repo/cronjob.go @@ -20,12 +20,15 @@ type ICronjobRepo interface { Page(limit, offset int, opts ...DBOption) (int64, []model.Cronjob, error) Create(cronjob *model.Cronjob) error WithByJobID(id int) DBOption + WithByBackupID(id uint) DBOption + WithByRecordDropID(id int) DBOption Save(id uint, cronjob model.Cronjob) error Update(id uint, vars map[string]interface{}) error Delete(opts ...DBOption) error DeleteRecord(opts ...DBOption) error - StartRecords(cronjobID uint, targetPath string) model.JobRecords + StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords EndRecords(record model.JobRecords, status, message, records string) + PageRecords(page, size int, opts ...DBOption) (int64, []model.JobRecords, error) } func NewICronjobRepo() ICronjobRepo { @@ -112,10 +115,23 @@ func (c *CronjobRepo) WithByJobID(id int) DBOption { } } -func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath string) model.JobRecords { +func (c *CronjobRepo) WithByBackupID(id uint) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("target_dir_id = ?", id) + } +} + +func (c *CronjobRepo) WithByRecordDropID(id int) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("id < ?", id) + } +} + +func (u *CronjobRepo) StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords { var record model.JobRecords record.StartTime = time.Now() record.CronjobID = cronjobID + record.FromLocal = fromLocal record.Status = constant.StatusWaiting if err := global.DB.Create(&record).Error; err != nil { global.LOG.Errorf("create record status failed, err: %v", err) diff --git a/backend/app/repo/entry.go b/backend/app/repo/entry.go deleted file mode 100644 index bbdd155bf..000000000 --- a/backend/app/repo/entry.go +++ /dev/null @@ -1,30 +0,0 @@ -package repo - -type RepoGroup struct { - CommonRepo - AppRepo - AppTagRepo - TagRepo - AppDetailRepo - AppInstallRepo - AppInstallResourceRpo - ImageRepoRepo - ComposeTemplateRepo - MysqlRepo - CronjobRepo - HostRepo - CommandRepo - GroupRepo - SettingRepo - BackupRepo - WebsiteRepo - WebsiteDomainRepo - WebsiteGroupRepo - WebsiteDnsAccountRepo - WebsiteSSLRepo - WebsiteAcmeAccountRepo - LogRepo - SnapshotRepo -} - -var RepoGroupApp = new(RepoGroup) diff --git a/backend/app/repo/group.go b/backend/app/repo/group.go index 4a4baff90..de154e02b 100644 --- a/backend/app/repo/group.go +++ b/backend/app/repo/group.go @@ -14,7 +14,7 @@ type IGroupRepo interface { Create(group *model.Group) error Update(id uint, vars map[string]interface{}) error Delete(opts ...DBOption) error - CancelDefault() error + CancelDefault(groupType string) error WithByIsDefault(isDefault bool) DBOption } @@ -64,6 +64,6 @@ func (u *GroupRepo) Delete(opts ...DBOption) error { return db.Delete(&model.Group{}).Error } -func (w GroupRepo) CancelDefault() error { - return global.DB.Model(&model.Group{}).Where("`is_default` = 1").Updates(map[string]interface{}{"is_default": 0}).Error +func (u *GroupRepo) CancelDefault(groupType string) error { + return global.DB.Model(&model.Group{}).Where("is_default = ? AND type = ?", 1, groupType).Updates(map[string]interface{}{"is_default": 0}).Error } diff --git a/backend/app/repo/host.go b/backend/app/repo/host.go index 2edc7c5e7..863f72090 100644 --- a/backend/app/repo/host.go +++ b/backend/app/repo/host.go @@ -25,7 +25,7 @@ func NewIHostRepo() IHostRepo { return &HostRepo{} } -func (u *HostRepo) Get(opts ...DBOption) (model.Host, error) { +func (h *HostRepo) Get(opts ...DBOption) (model.Host, error) { var host model.Host db := global.DB for _, opt := range opts { @@ -35,7 +35,7 @@ func (u *HostRepo) Get(opts ...DBOption) (model.Host, error) { return host, err } -func (u *HostRepo) GetList(opts ...DBOption) ([]model.Host, error) { +func (h *HostRepo) GetList(opts ...DBOption) ([]model.Host, error) { var hosts []model.Host db := global.DB.Model(&model.Host{}) for _, opt := range opts { @@ -45,7 +45,7 @@ func (u *HostRepo) GetList(opts ...DBOption) ([]model.Host, error) { return hosts, err } -func (u *HostRepo) Page(page, size int, opts ...DBOption) (int64, []model.Host, error) { +func (h *HostRepo) Page(page, size int, opts ...DBOption) (int64, []model.Host, error) { var users []model.Host db := global.DB.Model(&model.Host{}) for _, opt := range opts { @@ -57,7 +57,7 @@ func (u *HostRepo) Page(page, size int, opts ...DBOption) (int64, []model.Host, return count, users, err } -func (c *HostRepo) WithByInfo(info string) DBOption { +func (h *HostRepo) WithByInfo(info string) DBOption { return func(g *gorm.DB) *gorm.DB { if len(info) == 0 { return g @@ -67,22 +67,22 @@ func (c *HostRepo) WithByInfo(info string) DBOption { } } -func (u *HostRepo) WithByPort(port uint) DBOption { +func (h *HostRepo) WithByPort(port uint) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("port = ?", port) } } -func (u *HostRepo) WithByUser(user string) DBOption { +func (h *HostRepo) WithByUser(user string) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("user = ?", user) } } -func (u *HostRepo) WithByAddr(addr string) DBOption { +func (h *HostRepo) WithByAddr(addr string) DBOption { return func(g *gorm.DB) *gorm.DB { return g.Where("addr = ?", addr) } } -func (u *HostRepo) WithByGroup(group string) DBOption { +func (h *HostRepo) WithByGroup(group string) DBOption { return func(g *gorm.DB) *gorm.DB { if len(group) == 0 { return g @@ -91,15 +91,15 @@ func (u *HostRepo) WithByGroup(group string) DBOption { } } -func (u *HostRepo) Create(host *model.Host) error { +func (h *HostRepo) Create(host *model.Host) error { return global.DB.Create(host).Error } -func (u *HostRepo) Update(id uint, vars map[string]interface{}) error { +func (h *HostRepo) Update(id uint, vars map[string]interface{}) error { return global.DB.Model(&model.Host{}).Where("id = ?", id).Updates(vars).Error } -func (u *HostRepo) Delete(opts ...DBOption) error { +func (h *HostRepo) Delete(opts ...DBOption) error { db := global.DB for _, opt := range opts { db = opt(db) diff --git a/backend/app/repo/runtime.go b/backend/app/repo/runtime.go new file mode 100644 index 000000000..59ed29e0c --- /dev/null +++ b/backend/app/repo/runtime.go @@ -0,0 +1,80 @@ +package repo + +import ( + "context" + "github.com/1Panel-dev/1Panel/backend/app/model" + "gorm.io/gorm" +) + +type RuntimeRepo struct { +} + +type IRuntimeRepo interface { + WithName(name string) DBOption + WithImage(image string) DBOption + WithNotId(id uint) DBOption + WithStatus(status string) DBOption + Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) + Create(ctx context.Context, runtime *model.Runtime) error + Save(runtime *model.Runtime) error + DeleteBy(opts ...DBOption) error + GetFirst(opts ...DBOption) (*model.Runtime, error) +} + +func NewIRunTimeRepo() IRuntimeRepo { + return &RuntimeRepo{} +} + +func (r *RuntimeRepo) WithName(name string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("name = ?", name) + } +} + +func (r *RuntimeRepo) WithStatus(status string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("status = ?", status) + } +} + +func (r *RuntimeRepo) WithImage(image string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("image = ?", image) + } +} + +func (r *RuntimeRepo) WithNotId(id uint) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("id != ?", id) + } +} + +func (r *RuntimeRepo) Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) { + var runtimes []model.Runtime + db := getDb(opts...).Model(&model.Runtime{}) + count := int64(0) + db = db.Count(&count) + err := db.Limit(size).Offset(size * (page - 1)).Find(&runtimes).Error + return count, runtimes, err +} + +func (r *RuntimeRepo) Create(ctx context.Context, runtime *model.Runtime) error { + db := getTx(ctx).Model(&model.Runtime{}) + return db.Create(&runtime).Error +} + +func (r *RuntimeRepo) Save(runtime *model.Runtime) error { + return getDb().Save(&runtime).Error +} + +func (r *RuntimeRepo) DeleteBy(opts ...DBOption) error { + return getDb(opts...).Delete(&model.Runtime{}).Error +} + +func (r *RuntimeRepo) GetFirst(opts ...DBOption) (*model.Runtime, error) { + var runtime model.Runtime + if err := getDb(opts...).First(&runtime).Error; err != nil { + return nil, err + } + return &runtime, nil +} diff --git a/backend/app/repo/tag.go b/backend/app/repo/tag.go index cdc31bcca..36da32193 100644 --- a/backend/app/repo/tag.go +++ b/backend/app/repo/tag.go @@ -8,6 +8,19 @@ import ( type TagRepo struct { } +type ITagRepo interface { + BatchCreate(ctx context.Context, tags []*model.Tag) error + DeleteAll(ctx context.Context) error + All() ([]model.Tag, error) + GetByIds(ids []uint) ([]model.Tag, error) + GetByKeys(keys []string) ([]model.Tag, error) + GetByAppId(appId uint) ([]model.Tag, error) +} + +func NewITagRepo() ITagRepo { + return &TagRepo{} +} + func (t TagRepo) BatchCreate(ctx context.Context, tags []*model.Tag) error { return getTx(ctx).Create(&tags).Error } diff --git a/backend/app/repo/website.go b/backend/app/repo/website.go index ef4eb37eb..ef24838ef 100644 --- a/backend/app/repo/website.go +++ b/backend/app/repo/website.go @@ -17,6 +17,7 @@ type IWebsiteRepo interface { WithGroupID(groupId uint) DBOption WithDefaultServer() DBOption WithDomainLike(domain string) DBOption + WithRuntimeID(runtimeID uint) DBOption Page(page, size int, opts ...DBOption) (int64, []model.Website, error) List(opts ...DBOption) ([]model.Website, error) GetFirst(opts ...DBOption) (model.Website, error) @@ -40,6 +41,12 @@ func (w *WebsiteRepo) WithAppInstallId(appInstallId uint) DBOption { } } +func (w *WebsiteRepo) WithRuntimeID(runtimeID uint) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("runtime_id = ?", runtimeID) + } +} + func (w *WebsiteRepo) WithDomain(domain string) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("primary_domain = ?", domain) diff --git a/backend/app/repo/website_dns_account.go b/backend/app/repo/website_dns_account.go index 9d553549e..56811b975 100644 --- a/backend/app/repo/website_dns_account.go +++ b/backend/app/repo/website_dns_account.go @@ -7,6 +7,19 @@ import ( type WebsiteDnsAccountRepo struct { } +type IWebsiteDnsAccountRepo interface { + Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDnsAccount, error) + GetFirst(opts ...DBOption) (*model.WebsiteDnsAccount, error) + List(opts ...DBOption) ([]model.WebsiteDnsAccount, error) + Create(account model.WebsiteDnsAccount) error + Save(account model.WebsiteDnsAccount) error + DeleteBy(opts ...DBOption) error +} + +func NewIWebsiteDnsAccountRepo() IWebsiteDnsAccountRepo { + return &WebsiteDnsAccountRepo{} +} + func (w WebsiteDnsAccountRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDnsAccount, error) { var accounts []model.WebsiteDnsAccount db := getDb(opts...).Model(&model.WebsiteDnsAccount{}) diff --git a/backend/app/repo/website_domain.go b/backend/app/repo/website_domain.go index 34612451b..0b3ad5b63 100644 --- a/backend/app/repo/website_domain.go +++ b/backend/app/repo/website_domain.go @@ -10,6 +10,23 @@ import ( type WebsiteDomainRepo struct { } +type IWebsiteDomainRepo interface { + WithWebsiteId(websiteId uint) DBOption + WithPort(port int) DBOption + WithDomain(domain string) DBOption + Page(page, size int, opts ...DBOption) (int64, []model.WebsiteDomain, error) + GetFirst(opts ...DBOption) (model.WebsiteDomain, error) + GetBy(opts ...DBOption) ([]model.WebsiteDomain, error) + BatchCreate(ctx context.Context, domains []model.WebsiteDomain) error + Create(ctx context.Context, app *model.WebsiteDomain) error + Save(ctx context.Context, app *model.WebsiteDomain) error + DeleteBy(ctx context.Context, opts ...DBOption) error +} + +func NewIWebsiteDomainRepo() IWebsiteDomainRepo { + return &WebsiteDomainRepo{} +} + func (w WebsiteDomainRepo) WithWebsiteId(websiteId uint) DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("website_id = ?", websiteId) diff --git a/backend/app/repo/website_group.go b/backend/app/repo/website_group.go deleted file mode 100644 index 241e8ade6..000000000 --- a/backend/app/repo/website_group.go +++ /dev/null @@ -1,44 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm/clause" -) - -type WebsiteGroupRepo struct { -} - -func (w WebsiteGroupRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteGroup, error) { - var groups []model.WebsiteGroup - db := getDb(opts...).Model(&model.WebsiteGroup{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Order("`default` desc").Find(&groups).Error - return count, groups, err -} - -func (w WebsiteGroupRepo) GetBy(opts ...DBOption) ([]model.WebsiteGroup, error) { - var groups []model.WebsiteGroup - db := getDb(opts...).Model(&model.WebsiteGroup{}) - if err := db.Order("`default` desc").Find(&groups).Error; err != nil { - return groups, err - } - return groups, nil -} - -func (w WebsiteGroupRepo) Create(app *model.WebsiteGroup) error { - return getDb().Omit(clause.Associations).Create(app).Error -} - -func (w WebsiteGroupRepo) Save(app *model.WebsiteGroup) error { - return getDb().Omit(clause.Associations).Save(app).Error -} - -func (w WebsiteGroupRepo) DeleteBy(opts ...DBOption) error { - return getDb(opts...).Delete(&model.WebsiteGroup{}).Error -} - -func (w WebsiteGroupRepo) CancelDefault() error { - return global.DB.Model(&model.WebsiteGroup{}).Where("`default` = 1").Updates(map[string]interface{}{"default": 0}).Error -} diff --git a/backend/app/service/app.go b/backend/app/service/app.go index 1d5e52ef8..eb617b2f2 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -5,13 +5,15 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/1Panel-dev/1Panel/backend/buserr" - "io/ioutil" + "io" "net/http" "os" "path" "strings" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/utils/docker" + "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto/request" "github.com/1Panel-dev/1Panel/backend/app/dto/response" @@ -31,10 +33,12 @@ type IAppService interface { PageApp(req request.AppSearch) (interface{}, error) GetAppTags() ([]response.TagDTO, error) GetApp(key string) (*response.AppDTO, error) - GetAppDetail(appId uint, version string) (response.AppDetailDTO, error) + GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) - SyncAppList() error + SyncAppListFromRemote() error GetAppUpdate() (*response.AppUpdateRes, error) + GetAppDetailByID(id uint) (*response.AppDetailDTO, error) + SyncAppListFromLocal() } func NewIAppService() IAppService { @@ -137,7 +141,7 @@ func (a AppService) GetApp(key string) (*response.AppDTO, error) { return &appDTO, nil } -func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetailDTO, error) { +func (a AppService) GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error) { var ( appDetailDTO response.AppDetailDTO opts []repo.DBOption @@ -147,14 +151,55 @@ func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetail if err != nil { return appDetailDTO, err } - paramMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(detail.Params), ¶mMap); err != nil { - return appDetailDTO, err - } appDetailDTO.AppDetail = detail - appDetailDTO.Params = paramMap appDetailDTO.Enable = true + if appType == "runtime" { + app, err := appRepo.GetFirst(commonRepo.WithByID(appId)) + if err != nil { + return appDetailDTO, err + } + fileOp := files.NewFileOp() + buildPath := path.Join(constant.AppResourceDir, app.Key, "versions", detail.Version, "build") + paramsPath := path.Join(buildPath, "config.json") + if !fileOp.Stat(paramsPath) { + return appDetailDTO, buserr.New(constant.ErrFileNotExist) + } + param, err := fileOp.GetContent(paramsPath) + if err != nil { + return appDetailDTO, err + } + paramMap := make(map[string]interface{}) + if err := json.Unmarshal(param, ¶mMap); err != nil { + return appDetailDTO, err + } + appDetailDTO.Params = paramMap + composePath := path.Join(buildPath, "docker-compose.yml") + if !fileOp.Stat(composePath) { + return appDetailDTO, buserr.New(constant.ErrFileNotExist) + } + compose, err := fileOp.GetContent(composePath) + if err != nil { + return appDetailDTO, err + } + composeMap := make(map[string]interface{}) + if err := yaml.Unmarshal(compose, &composeMap); err != nil { + return appDetailDTO, err + } + if service, ok := composeMap["services"]; ok { + servicesMap := service.(map[string]interface{}) + for k := range servicesMap { + appDetailDTO.Image = k + } + } + } else { + paramMap := make(map[string]interface{}) + if err := json.Unmarshal([]byte(detail.Params), ¶mMap); err != nil { + return appDetailDTO, err + } + appDetailDTO.Params = paramMap + } + app, err := appRepo.GetFirst(commonRepo.WithByID(detail.AppId)) if err != nil { return appDetailDTO, err @@ -164,54 +209,75 @@ func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetail } return appDetailDTO, nil } +func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) { + res := &response.AppDetailDTO{} + appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(id)) + if err != nil { + return nil, err + } + res.AppDetail = appDetail + paramMap := make(map[string]interface{}) + if err := json.Unmarshal([]byte(appDetail.Params), ¶mMap); err != nil { + return nil, err + } + res.Params = paramMap + return res, nil +} -func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) { +func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (appInstall *model.AppInstall, err error) { + if err = docker.CreateDefaultDockerNetwork(); err != nil { + err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil) + return + } if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 { - return nil, buserr.New(constant.ErrNameIsExist) + err = buserr.New(constant.ErrNameIsExist) + return } - httpPort, err := checkPort("PANEL_APP_PORT_HTTP", req.Params) + var ( + httpPort int + httpsPort int + appDetail model.AppDetail + app model.App + ) + httpPort, err = checkPort("PANEL_APP_PORT_HTTP", req.Params) + if err != nil { + return + } + httpsPort, err = checkPort("PANEL_APP_PORT_HTTPS", req.Params) + if err != nil { + return + } + appDetail, err = appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId)) + if err != nil { + return + } + app, err = appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId)) if err != nil { return nil, err } - httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", req.Params) - if err != nil { - return nil, err - } - appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId)) - if err != nil { - return nil, err - } - app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId)) - if err != nil { - return nil, err - } - if err := checkRequiredAndLimit(app); err != nil { - return nil, err + if err = checkRequiredAndLimit(app); err != nil { + return } - paramByte, err := json.Marshal(req.Params) - if err != nil { - return nil, err - } - appInstall := model.AppInstall{ + appInstall = &model.AppInstall{ Name: req.Name, AppId: appDetail.AppId, AppDetailId: appDetail.ID, Version: appDetail.Version, Status: constant.Installing, - Env: string(paramByte), HttpPort: httpPort, HttpsPort: httpsPort, App: app, } composeMap := make(map[string]interface{}) - if err := yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil { - return nil, err + if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil { + return } value, ok := composeMap["services"] if !ok { - return nil, buserr.New("") + err = buserr.New("") + return } servicesMap := value.(map[string]interface{}) changeKeys := make(map[string]string, len(servicesMap)) @@ -232,30 +298,59 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) ( servicesMap[v] = servicesMap[k] delete(servicesMap, k) } - composeByte, err := yaml.Marshal(composeMap) + + var ( + composeByte []byte + paramByte []byte + ) + + composeByte, err = yaml.Marshal(composeMap) if err != nil { - return nil, err + return } appInstall.DockerCompose = string(composeByte) - if err := copyAppData(app.Key, appDetail.Version, req.Name, req.Params); err != nil { - return nil, err - } + defer func() { + if err != nil { + hErr := handleAppInstallErr(ctx, appInstall) + if hErr != nil { + global.LOG.Errorf("delete app dir error %s", hErr.Error()) + } + } + }() + if err = copyAppData(app.Key, appDetail.Version, req.Name, req.Params, app.Resource == constant.AppResourceLocal); err != nil { + return + } fileOp := files.NewFileOp() - if err := fileOp.WriteFile(appInstall.GetComposePath(), strings.NewReader(string(composeByte)), 0775); err != nil { - return nil, err + if err = fileOp.WriteFile(appInstall.GetComposePath(), strings.NewReader(string(composeByte)), 0775); err != nil { + return } + paramByte, err = json.Marshal(req.Params) + if err != nil { + return + } + appInstall.Env = string(paramByte) - if err := appInstallRepo.Create(ctx, &appInstall); err != nil { - return nil, err + if err = appInstallRepo.Create(ctx, appInstall); err != nil { + return } - if err := createLink(ctx, app, &appInstall, req.Params); err != nil { - return nil, err + if err = createLink(ctx, app, appInstall, req.Params); err != nil { + return } - go upApp(appInstall.GetComposePath(), appInstall) + if err = upAppPre(app, appInstall); err != nil { + return + } + go upApp(appInstall) go updateToolApp(appInstall) - return &appInstall, nil + ports := []int{appInstall.HttpPort} + if appInstall.HttpsPort > 0 { + ports = append(ports, appInstall.HttpsPort) + } + go func() { + _ = OperateFirewallPort(nil, ports) + }() + return } func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { @@ -268,12 +363,11 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { } versionUrl := fmt.Sprintf("%s/%s/%s/appstore/apps.json", global.CONF.System.RepoUrl, global.CONF.System.Mode, setting.SystemVersion) versionRes, err := http.Get(versionUrl) - global.LOG.Infof("get current version from [%s]", versionUrl) if err != nil { return nil, err } defer versionRes.Body.Close() - body, err := ioutil.ReadAll(versionRes.Body) + body, err := io.ReadAll(versionRes.Body) if err != nil { return nil, err } @@ -290,7 +384,155 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { return res, nil } -func (a AppService) SyncAppList() error { +func (a AppService) SyncAppListFromLocal() { + fileOp := files.NewFileOp() + appDir := constant.LocalAppResourceDir + listFile := path.Join(appDir, "list.json") + if !fileOp.Stat(listFile) { + return + } + global.LOG.Infof("start sync local apps...") + content, err := fileOp.GetContent(listFile) + if err != nil { + global.LOG.Errorf("get list.json content failed %s", err.Error()) + return + } + list := &dto.AppList{} + if err := json.Unmarshal(content, list); err != nil { + global.LOG.Errorf("unmarshal list.json failed %s", err.Error()) + return + } + oldApps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceLocal)) + appsMap := getApps(oldApps, list.Items, true) + for _, l := range list.Items { + localKey := "local" + l.Key + app := appsMap[localKey] + icon, err := os.ReadFile(path.Join(appDir, l.Key, "metadata", "logo.png")) + if err != nil { + global.LOG.Errorf("get [%s] icon error: %s", l.Name, err.Error()) + continue + } + iconStr := base64.StdEncoding.EncodeToString(icon) + app.Icon = iconStr + app.TagsKey = append(l.Tags, "Local") + app.Recommend = 9999 + versions := l.Versions + detailsMap := getAppDetails(app.Details, versions) + + for _, v := range versions { + detail := detailsMap[v] + detailPath := path.Join(appDir, l.Key, "versions", v) + if _, err := os.Stat(detailPath); err != nil { + global.LOG.Errorf("get [%s] folder error: %s", detailPath, err.Error()) + continue + } + readmeStr, err := os.ReadFile(path.Join(detailPath, "README.md")) + if err != nil { + global.LOG.Errorf("get [%s] README error: %s", detailPath, err.Error()) + } + detail.Readme = string(readmeStr) + dockerComposeStr, err := os.ReadFile(path.Join(detailPath, "docker-compose.yml")) + if err != nil { + global.LOG.Errorf("get [%s] docker-compose.yml error: %s", detailPath, err.Error()) + continue + } + detail.DockerCompose = string(dockerComposeStr) + paramStr, err := os.ReadFile(path.Join(detailPath, "config.json")) + if err != nil { + global.LOG.Errorf("get [%s] form.json error: %s", detailPath, err.Error()) + } + detail.Params = string(paramStr) + detailsMap[v] = detail + } + var newDetails []model.AppDetail + for _, v := range detailsMap { + newDetails = append(newDetails, v) + } + app.Details = newDetails + appsMap[localKey] = app + } + var ( + addAppArray []model.App + updateArray []model.App + appIds []uint + ) + for _, v := range appsMap { + if v.ID == 0 { + addAppArray = append(addAppArray, v) + } else { + updateArray = append(updateArray, v) + appIds = append(appIds, v.ID) + } + } + tx, ctx := getTxAndContext() + if len(addAppArray) > 0 { + if err := appRepo.BatchCreate(ctx, addAppArray); err != nil { + tx.Rollback() + return + } + } + for _, update := range updateArray { + if err := appRepo.Save(ctx, &update); err != nil { + tx.Rollback() + return + } + } + if err := appTagRepo.DeleteByAppIds(ctx, appIds); err != nil { + tx.Rollback() + return + } + apps := append(addAppArray, updateArray...) + var ( + addDetails []model.AppDetail + updateDetails []model.AppDetail + appTags []*model.AppTag + ) + tags, _ := tagRepo.All() + tagMap := make(map[string]uint, len(tags)) + for _, app := range tags { + tagMap[app.Key] = app.ID + } + for _, a := range apps { + for _, t := range a.TagsKey { + tagId, ok := tagMap[t] + if ok { + appTags = append(appTags, &model.AppTag{ + AppId: a.ID, + TagId: tagId, + }) + } + } + for _, d := range a.Details { + d.AppId = a.ID + if d.ID == 0 { + addDetails = append(addDetails, d) + } else { + updateDetails = append(updateDetails, d) + } + } + } + if len(addDetails) > 0 { + if err := appDetailRepo.BatchCreate(ctx, addDetails); err != nil { + tx.Rollback() + return + } + } + for _, u := range updateDetails { + if err := appDetailRepo.Update(ctx, u); err != nil { + tx.Rollback() + return + } + } + if len(appTags) > 0 { + if err := appTagRepo.BatchCreate(ctx, appTags); err != nil { + tx.Rollback() + return + } + } + tx.Commit() + global.LOG.Infof("sync local apps success") +} +func (a AppService) SyncAppListFromRemote() error { updateRes, err := a.GetAppUpdate() if err != nil { return err @@ -323,11 +565,11 @@ func (a AppService) SyncAppList() error { Name: t.Name, }) } - oldApps, err := appRepo.GetBy() + oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote)) if err != nil { return err } - appsMap := getApps(oldApps, list.Items) + appsMap := getApps(oldApps, list.Items, false) for _, l := range list.Items { app := appsMap[l.Key] icon, err := os.ReadFile(path.Join(appDir, l.Key, "metadata", "logo.png")) @@ -383,8 +625,9 @@ func (a AppService) SyncAppList() error { var ( addAppArray []model.App updateArray []model.App + tagMap = make(map[string]uint, len(tags)) ) - tagMap := make(map[string]uint, len(tags)) + for _, v := range appsMap { if v.ID == 0 { addAppArray = append(addAppArray, v) diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go index a6ef4cf95..95cf4b43d 100644 --- a/backend/app/service/app_install.go +++ b/backend/app/service/app_install.go @@ -1,12 +1,9 @@ package service import ( + "context" "encoding/json" "fmt" - "github.com/1Panel-dev/1Panel/backend/utils/env" - "github.com/1Panel-dev/1Panel/backend/utils/nginx" - "github.com/joho/godotenv" - "io/ioutil" "math" "os" "path" @@ -14,6 +11,10 @@ import ( "strconv" "strings" + "github.com/1Panel-dev/1Panel/backend/utils/env" + "github.com/1Panel-dev/1Panel/backend/utils/nginx" + "github.com/joho/godotenv" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" "github.com/1Panel-dev/1Panel/backend/app/dto/response" "github.com/1Panel-dev/1Panel/backend/buserr" @@ -33,7 +34,28 @@ import ( type AppInstallService struct { } -func (a AppInstallService) Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error) { +type IAppInstallService interface { + Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error) + CheckExist(key string) (*response.AppInstalledCheck, error) + LoadPort(key string) (int64, error) + LoadConnInfo(key string) (response.DatabaseConn, error) + SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error) + Operate(req request.AppInstalledOperate) error + Update(req request.AppInstalledUpdate) error + SyncAll(systemInit bool) error + GetServices(key string) ([]response.AppService, error) + GetUpdateVersions(installId uint) ([]dto.AppVersion, error) + GetParams(id uint) ([]response.AppParam, error) + ChangeAppPort(req request.PortUpdate) error + GetDefaultConfigByKey(key string) (string, error) + DeleteCheck(installId uint) ([]dto.AppResource, error) +} + +func NewIAppInstalledService() IAppInstallService { + return &AppInstallService{} +} + +func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error) { var opts []repo.DBOption if req.Name != "" { @@ -73,7 +95,7 @@ func (a AppInstallService) Page(req request.AppInstalledSearch) (int64, []respon return total, installDTOs, nil } -func (a AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, error) { +func (a *AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, error) { res := &response.AppInstalledCheck{ IsExist: false, } @@ -103,7 +125,7 @@ func (a AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, return res, nil } -func (a AppInstallService) LoadPort(key string) (int64, error) { +func (a *AppInstallService) LoadPort(key string) (int64, error) { app, err := appInstallRepo.LoadBaseInfo(key, "") if err != nil { return int64(0), nil @@ -111,15 +133,19 @@ func (a AppInstallService) LoadPort(key string) (int64, error) { return app.Port, nil } -func (a AppInstallService) LoadPassword(key string) (string, error) { +func (a *AppInstallService) LoadConnInfo(key string) (response.DatabaseConn, error) { + var data response.DatabaseConn app, err := appInstallRepo.LoadBaseInfo(key, "") if err != nil { - return "", nil + return data, nil } - return app.Password, nil + data.Password = app.Password + data.ServiceName = app.ServiceName + data.Port = app.Port + return data, nil } -func (a AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error) { +func (a *AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error) { var ( installs []model.AppInstall err error @@ -152,8 +178,8 @@ func (a AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]r return handleInstalled(installs, false) } -func (a AppInstallService) Operate(req request.AppInstalledOperate) error { - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId)) +func (a *AppInstallService) Operate(req request.AppInstalledOperate) error { + install, err := appInstallRepo.GetFirstByCtx(context.Background(), commonRepo.WithByID(req.InstallId)) if err != nil { return err } @@ -180,49 +206,54 @@ func (a AppInstallService) Operate(req request.AppInstalledOperate) error { } return syncById(install.ID) case constant.Delete: - tx, ctx := getTxAndContext() - if err := deleteAppInstall(ctx, install, req.DeleteBackup, req.ForceDelete, req.DeleteDB); err != nil && !req.ForceDelete { - tx.Rollback() + if err := deleteAppInstall(install, req.DeleteBackup, req.ForceDelete, req.DeleteDB); err != nil && !req.ForceDelete { return err } - tx.Commit() return nil case constant.Sync: return syncById(install.ID) case constant.Upgrade: - return updateInstall(install.ID, req.DetailId) + return upgradeInstall(install.ID, req.DetailId) default: return errors.New("operate not support") } } -func (a AppInstallService) Update(req request.AppInstalledUpdate) error { +func (a *AppInstallService) Update(req request.AppInstalledUpdate) error { installed, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId)) if err != nil { return err } changePort := false + var ( + oldPorts []int + newPorts []int + ) port, ok := req.Params["PANEL_APP_PORT_HTTP"] if ok { portN := int(math.Ceil(port.(float64))) if portN != installed.HttpPort { + oldPorts = append(oldPorts, installed.HttpPort) changePort = true httpPort, err := checkPort("PANEL_APP_PORT_HTTP", req.Params) if err != nil { return err } installed.HttpPort = httpPort + newPorts = append(newPorts, httpPort) } } ports, ok := req.Params["PANEL_APP_PORT_HTTPS"] if ok { portN := int(math.Ceil(ports.(float64))) if portN != installed.HttpsPort { + oldPorts = append(oldPorts, installed.HttpsPort) httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", req.Params) if err != nil { return err } installed.HttpsPort = httpsPort + newPorts = append(newPorts, httpsPort) } } @@ -240,7 +271,7 @@ func (a AppInstallService) Update(req request.AppInstalledUpdate) error { if err := env.Write(oldEnvMaps, envPath); err != nil { return err } - _ = appInstallRepo.Save(&installed) + _ = appInstallRepo.Save(context.Background(), &installed) if err := rebuildApp(installed); err != nil { return err @@ -267,16 +298,26 @@ func (a AppInstallService) Update(req request.AppInstalledUpdate) error { return buserr.WithErr(constant.ErrUpdateBuWebsite, err) } } + if changePort { + go func() { + _ = OperateFirewallPort(oldPorts, newPorts) + }() + } return nil } -func (a AppInstallService) SyncAll() error { +func (a *AppInstallService) SyncAll(systemInit bool) error { allList, err := appInstallRepo.ListBy() if err != nil { return err } for _, i := range allList { if i.Status == constant.Installing { + if systemInit { + i.Status = constant.Error + i.Message = "System restart causes application exception" + _ = appInstallRepo.Save(context.Background(), &i) + } continue } if err := syncById(i.ID); err != nil { @@ -286,7 +327,7 @@ func (a AppInstallService) SyncAll() error { return nil } -func (a AppInstallService) GetServices(key string) ([]response.AppService, error) { +func (a *AppInstallService) GetServices(key string) ([]response.AppService, error) { app, err := appRepo.GetFirst(appRepo.WithKey(key)) if err != nil { return nil, err @@ -310,7 +351,7 @@ func (a AppInstallService) GetServices(key string) ([]response.AppService, error return res, nil } -func (a AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion, error) { +func (a *AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion, error) { install, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId)) var versions []dto.AppVersion if err != nil { @@ -335,7 +376,7 @@ func (a AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion, return versions, nil } -func (a AppInstallService) ChangeAppPort(req request.PortUpdate) error { +func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error { if common.ScanPort(int(req.Port)) { return buserr.WithDetail(constant.ErrPortInUsed, req.Port, nil) } @@ -360,10 +401,14 @@ func (a AppInstallService) ChangeAppPort(req request.PortUpdate) error { } } + if err := OperateFirewallPort([]int{int(appInstall.Port)}, []int{int(req.Port)}); err != nil { + global.LOG.Errorf("allow firewall failed, err: %v", err) + } + return nil } -func (a AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error) { +func (a *AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error) { var res []dto.AppResource appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId)) if err != nil { @@ -373,14 +418,12 @@ func (a AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error if err != nil { return nil, err } - if app.Type == "website" { - websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(appInstall.ID)) - for _, website := range websites { - res = append(res, dto.AppResource{ - Type: "website", - Name: website.PrimaryDomain, - }) - } + websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(appInstall.ID)) + for _, website := range websites { + res = append(res, dto.AppResource{ + Type: "website", + Name: website.PrimaryDomain, + }) } if app.Key == constant.AppOpenresty { websites, _ := websiteRepo.GetBy() @@ -404,7 +447,7 @@ func (a AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error return res, nil } -func (a AppInstallService) GetDefaultConfigByKey(key string) (string, error) { +func (a *AppInstallService) GetDefaultConfigByKey(key string) (string, error) { appInstall, err := getAppInstallByKey(key) if err != nil { return "", err @@ -426,7 +469,7 @@ func (a AppInstallService) GetDefaultConfigByKey(key string) (string, error) { return string(contentByte), nil } -func (a AppInstallService) GetParams(id uint) ([]response.AppParam, error) { +func (a *AppInstallService) GetParams(id uint) ([]response.AppParam, error) { var ( res []response.AppParam appForm dto.AppForm @@ -459,14 +502,20 @@ func (a AppInstallService) GetParams(id uint) ([]response.AppParam, error) { } appParam.LabelZh = form.LabelZh appParam.LabelEn = form.LabelEn + appParam.Value = v if form.Type == "service" { appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithServiceName(v.(string))) - appParam.Value = appInstall.Name - res = append(res, appParam) - } else { - appParam.Value = v - res = append(res, appParam) + appParam.ShowValue = appInstall.Name + } else if form.Type == "select" { + for _, fv := range form.Values { + if fv.Value == v { + appParam.ShowValue = fv.Label + break + } + } + appParam.Values = form.Values } + res = append(res, appParam) } } return res, nil @@ -534,15 +583,15 @@ func syncById(installId uint) error { if containerCount == 0 { appInstall.Status = constant.Error appInstall.Message = "container is not found" - return appInstallRepo.Save(&appInstall) + return appInstallRepo.Save(context.Background(), &appInstall) } if errCount == 0 && existedCount == 0 { appInstall.Status = constant.Running - return appInstallRepo.Save(&appInstall) + return appInstallRepo.Save(context.Background(), &appInstall) } if existedCount == normalCount { appInstall.Status = constant.Stopped - return appInstallRepo.Save(&appInstall) + return appInstallRepo.Save(context.Background(), &appInstall) } if errCount == normalCount { appInstall.Status = constant.Error @@ -567,7 +616,7 @@ func syncById(installId uint) error { errMsg.Write([]byte("\n")) } appInstall.Message = errMsg.String() - return appInstallRepo.Save(&appInstall) + return appInstallRepo.Save(context.Background(), &appInstall) } func updateInstallInfoInDB(appKey, appName, param string, isRestart bool, value interface{}) error { @@ -579,7 +628,7 @@ func updateInstallInfoInDB(appKey, appName, param string, isRestart bool, value return nil } envPath := fmt.Sprintf("%s/%s/%s/.env", constant.AppInstallDir, appKey, appInstall.Name) - lineBytes, err := ioutil.ReadFile(envPath) + lineBytes, err := os.ReadFile(envPath) if err != nil { return err } @@ -622,7 +671,7 @@ func updateInstallInfoInDB(appKey, appName, param string, isRestart bool, value }, commonRepo.WithByID(appInstall.ID)) } if param == "user-password" { - oldVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", appInstall.Password) + oldVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", appInstall.UserPassword) newVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", value) _ = appInstallRepo.BatchUpdateBy(map[string]interface{}{ "param": strings.ReplaceAll(appInstall.Param, oldVal, newVal), diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 181974030..5fb53ccf9 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -4,8 +4,12 @@ import ( "context" "encoding/json" "fmt" + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/compose-spec/compose-go/types" + "github.com/subosito/gotenv" "math" "os" + "os/exec" "path" "reflect" "strconv" @@ -23,6 +27,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/compose" + composeV2 "github.com/1Panel-dev/1Panel/backend/utils/docker" "github.com/1Panel-dev/1Panel/backend/utils/files" "github.com/pkg/errors" ) @@ -125,7 +130,23 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall return nil } -func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool, deleteDB bool) error { +func handleAppInstallErr(ctx context.Context, install *model.AppInstall) error { + op := files.NewFileOp() + appDir := install.GetPath() + dir, _ := os.Stat(appDir) + if dir != nil { + _, _ = compose.Down(install.GetComposePath()) + if err := op.DeleteDir(appDir); err != nil { + return err + } + } + if err := deleteLink(ctx, install, true, true); err != nil { + return err + } + return nil +} + +func deleteAppInstall(install model.AppInstall, deleteBackup bool, forceDelete bool, deleteDB bool) error { op := files.NewFileOp() appDir := install.GetPath() dir, _ := os.Stat(appDir) @@ -134,36 +155,34 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku if err != nil && !forceDelete { return handleErr(install, err, out) } - if err := op.DeleteDir(appDir); err != nil && !forceDelete { - return err - } } + tx, ctx := helper.GetTxAndContext() + defer tx.Rollback() if err := appInstallRepo.Delete(ctx, install); err != nil { return err } if err := deleteLink(ctx, &install, deleteDB, forceDelete); err != nil && !forceDelete { return err } + _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("app"), commonRepo.WithByName(install.App.Key), backupRepo.WithByDetailName(install.Name)) + _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(install.App.Key)) + if install.App.Key == constant.AppMysql { + _ = mysqlRepo.DeleteAll(ctx) + } uploadDir := fmt.Sprintf("%s/1panel/uploads/app/%s/%s", global.CONF.System.BaseDir, install.App.Key, install.Name) if _, err := os.Stat(uploadDir); err == nil { _ = os.RemoveAll(uploadDir) } if deleteBackup { - localDir, err := loadLocalDir() - if err != nil && !forceDelete { - return err - } + localDir, _ := loadLocalDir() backupDir := fmt.Sprintf("%s/app/%s/%s", localDir, install.App.Key, install.Name) if _, err := os.Stat(backupDir); err == nil { _ = os.RemoveAll(backupDir) } global.LOG.Infof("delete app %s-%s backups successful", install.App.Key, install.Name) } - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("app"), commonRepo.WithByName(install.App.Key), backupRepo.WithByDetailName(install.Name)) - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(install.App.Key)) - if install.App.Key == constant.AppMysql { - _ = mysqlRepo.DeleteAll(ctx) - } + _ = op.DeleteDir(appDir) + tx.Commit() return nil } @@ -190,7 +209,7 @@ func deleteLink(ctx context.Context, install *model.AppInstall, deleteDB bool, f return appInstallResourceRepo.DeleteBy(ctx, appInstallResourceRepo.WithAppInstallId(install.ID)) } -func updateInstall(installId uint, detailId uint) error { +func upgradeInstall(installId uint, detailId uint) error { install, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId)) if err != nil { return err @@ -205,7 +224,21 @@ func updateInstall(installId uint, detailId uint) error { if err := NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name}); err != nil { return err } - if _, err = compose.Down(install.GetComposePath()); err != nil { + + detailDir := path.Join(constant.ResourceDir, "apps", install.App.Key, "versions", detail.Version) + cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("cp -rf %s/* %s", detailDir, install.GetPath())) + stdout, err := cmd.CombinedOutput() + if err != nil { + if stdout != nil { + return errors.New(string(stdout)) + } + return err + } + + if out, err := compose.Down(install.GetComposePath()); err != nil { + if out != "" { + return errors.New(out) + } return err } install.DockerCompose = detail.DockerCompose @@ -216,32 +249,51 @@ func updateInstall(installId uint, detailId uint) error { if err := fileOp.WriteFile(install.GetComposePath(), strings.NewReader(install.DockerCompose), 0775); err != nil { return err } - if _, err = compose.Up(install.GetComposePath()); err != nil { + if out, err := compose.Up(install.GetComposePath()); err != nil { + if out != "" { + return errors.New(out) + } return err } - return appInstallRepo.Save(&install) + return appInstallRepo.Save(context.Background(), &install) } func getContainerNames(install model.AppInstall) ([]string, error) { - composeMap := install.DockerCompose - envMap := make(map[string]interface{}) - _ = json.Unmarshal([]byte(install.Env), &envMap) - newEnvMap := make(map[string]string, len(envMap)) - handleMap(envMap, newEnvMap) - project, err := compose.GetComposeProject([]byte(composeMap), newEnvMap) + envStr, err := coverEnvJsonToStr(install.Env) if err != nil { return nil, err } - containerNames := []string{install.ContainerName} + project, err := composeV2.GetComposeProject(install.Name, install.GetPath(), []byte(install.DockerCompose), []byte(envStr), true) + if err != nil { + return nil, err + } + containerMap := make(map[string]struct{}) + containerMap[install.ContainerName] = struct{}{} for _, service := range project.AllServices() { if service.ContainerName == "${CONTAINER_NAME}" || service.ContainerName == "" { continue } - containerNames = append(containerNames, service.ContainerName) + containerMap[service.ContainerName] = struct{}{} + } + var containerNames []string + for k := range containerMap { + containerNames = append(containerNames, k) } return containerNames, nil } +func coverEnvJsonToStr(envJson string) (string, error) { + envMap := make(map[string]interface{}) + _ = json.Unmarshal([]byte(envJson), &envMap) + newEnvMap := make(map[string]string, len(envMap)) + handleMap(envMap, newEnvMap) + envStr, err := gotenv.Marshal(newEnvMap) + if err != nil { + return "", err + } + return envStr, nil +} + func checkLimit(app model.App) error { if app.Limit > 0 { installs, err := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID)) @@ -256,11 +308,9 @@ func checkLimit(app model.App) error { } func checkRequiredAndLimit(app model.App) error { - if err := checkLimit(app); err != nil { return err } - if app.Required != "" { var requiredArray []string if err := json.Unmarshal([]byte(app.Required), &requiredArray); err != nil { @@ -289,7 +339,6 @@ func checkRequiredAndLimit(app model.App) error { } } } - return nil } @@ -306,10 +355,17 @@ func handleMap(params map[string]interface{}, envParams map[string]string) { } } -func copyAppData(key, version, installName string, params map[string]interface{}) (err error) { +func copyAppData(key, version, installName string, params map[string]interface{}, isLocal bool) (err error) { fileOp := files.NewFileOp() - resourceDir := path.Join(constant.AppResourceDir, key, "versions", version) + appResourceDir := constant.AppResourceDir installAppDir := path.Join(constant.AppInstallDir, key) + appKey := key + if isLocal { + appResourceDir = constant.LocalAppResourceDir + appKey = strings.TrimPrefix(key, "local") + installAppDir = path.Join(constant.LocalAppInstallDir, appKey) + } + resourceDir := path.Join(appResourceDir, appKey, "versions", version) if !fileOp.Stat(installAppDir) { if err = fileOp.CreateDir(installAppDir, 0755); err != nil { @@ -339,19 +395,64 @@ func copyAppData(key, version, installName string, params map[string]interface{} return } -func upApp(composeFilePath string, appInstall model.AppInstall) { - out, err := compose.Up(composeFilePath) - if err != nil { - if out != "" { - appInstall.Message = out - } else { - appInstall.Message = err.Error() +// 处理文件夹权限等问题 +func upAppPre(app model.App, appInstall *model.AppInstall) error { + if app.Key == "nexus" { + dataPath := path.Join(appInstall.GetPath(), "data") + if err := files.NewFileOp().Chown(dataPath, 200, 0); err != nil { + return err } + } + return nil +} + +func getServiceFromInstall(appInstall *model.AppInstall) (service *composeV2.ComposeService, err error) { + var ( + project *types.Project + envStr string + ) + envStr, err = coverEnvJsonToStr(appInstall.Env) + if err != nil { + return + } + project, err = composeV2.GetComposeProject(appInstall.Name, appInstall.GetPath(), []byte(appInstall.DockerCompose), []byte(envStr), true) + if err != nil { + return + } + service, err = composeV2.NewComposeService() + if err != nil { + return + } + service.SetProject(project) + return +} + +func upApp(appInstall *model.AppInstall) { + upProject := func(appInstall *model.AppInstall) (err error) { + if err == nil { + var composeService *composeV2.ComposeService + composeService, err = getServiceFromInstall(appInstall) + if err != nil { + return err + } + err = composeService.ComposeUp() + if err != nil { + return err + } + return + } else { + return + } + } + if err := upProject(appInstall); err != nil { appInstall.Status = constant.Error - _ = appInstallRepo.Save(&appInstall) + appInstall.Message = err.Error() } else { appInstall.Status = constant.Running - _ = appInstallRepo.Save(&appInstall) + } + exist, _ := appInstallRepo.GetFirst(commonRepo.WithByID(appInstall.ID)) + if exist.ID > 0 { + _ = appInstallRepo.Save(context.Background(), appInstall) } } @@ -390,20 +491,29 @@ func getAppDetails(details []model.AppDetail, versions []string) map[string]mode return appDetails } -func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App { +func getApps(oldApps []model.App, items []dto.AppDefine, isLocal bool) map[string]model.App { apps := make(map[string]model.App, len(oldApps)) for _, old := range oldApps { old.Status = constant.AppTakeDown apps[old.Key] = old } for _, item := range items { - app, ok := apps[item.Key] + key := item.Key + if isLocal { + key = "local" + key + } + app, ok := apps[key] if !ok { app = model.App{} } + if isLocal { + app.Resource = constant.AppResourceLocal + } else { + app.Resource = constant.AppResourceRemote + } app.Name = item.Name app.Limit = item.Limit - app.Key = item.Key + app.Key = key app.ShortDescZh = item.ShortDescZh app.ShortDescEn = item.ShortDescEn app.Website = item.Website @@ -413,7 +523,7 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App { app.CrossVersionUpdate = item.CrossVersionUpdate app.Required = item.GetRequired() app.Status = constant.AppNormal - apps[item.Key] = app + apps[key] = app } return apps } @@ -426,7 +536,7 @@ func handleErr(install model.AppInstall, err error, out string) error { reErr = errors.New(out) install.Status = constant.Error } - _ = appInstallRepo.Save(&install) + _ = appInstallRepo.Save(context.Background(), &install) return reErr } @@ -501,7 +611,7 @@ func getAppInstallByKey(key string) (model.AppInstall, error) { return appInstall, nil } -func updateToolApp(installed model.AppInstall) { +func updateToolApp(installed *model.AppInstall) { tooKey, ok := dto.AppToolMap[installed.App.Key] if !ok { return @@ -537,7 +647,7 @@ func updateToolApp(installed model.AppInstall) { return } toolInstall.Env = string(contentByte) - if err := appInstallRepo.Save(&toolInstall); err != nil { + if err := appInstallRepo.Save(context.Background(), &toolInstall); err != nil { global.LOG.Errorf("update tool app [%s] error : %s", toolInstall.Name, err.Error()) return } diff --git a/backend/app/service/auth.go b/backend/app/service/auth.go index bc6e64110..b45dcad37 100644 --- a/backend/app/service/auth.go +++ b/backend/app/service/auth.go @@ -26,6 +26,7 @@ type IAuthService interface { SafeEntrance(c *gin.Context, code string) error Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo, error) LogOut(c *gin.Context) error + MFALogin(c *gin.Context, info dto.MFALogin) (*dto.UserLoginInfo, error) } func NewIAuthService() IAuthService { @@ -86,9 +87,9 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin) (*dto.UserLogi } pass, err := encrypt.StringDecrypt(passwrodSetting.Value) if err != nil { - return nil, constant.ErrAuth + return nil, err } - if info.Password != pass && nameSetting.Value != info.Name { + if info.Password != pass || nameSetting.Value != info.Name { return nil, constant.ErrAuth } @@ -118,7 +119,7 @@ func (u *AuthService) generateSession(c *gin.Context, name, authMethod string) ( j := jwt.NewJWT() claims := j.CreateClaims(jwt.BaseClaims{ Name: name, - }, lifeTime) + }) token, err := j.CreateToken(claims) if err != nil { return nil, err diff --git a/backend/app/service/backup.go b/backend/app/service/backup.go index fcca836e8..3daa3be36 100644 --- a/backend/app/service/backup.go +++ b/backend/app/service/backup.go @@ -9,6 +9,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage" @@ -26,7 +27,7 @@ type IBackupService interface { Create(backupDto dto.BackupOperate) error GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error) Update(ireq dto.BackupOperate) error - BatchDelete(ids []uint) error + Delete(id uint) error BatchDeleteRecord(ids []uint) error NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) @@ -53,36 +54,13 @@ func NewIBackupService() IBackupService { func (u *BackupService) List() ([]dto.BackupInfo, error) { ops, err := backupRepo.List(commonRepo.WithOrderBy("created_at desc")) var dtobas []dto.BackupInfo - ossExist, s3Exist, sftpExist, minioExist := false, false, false, false - for _, group := range ops { - switch group.Type { - case "OSS": - ossExist = true - case "S3": - s3Exist = true - case "SFTP": - sftpExist = true - case "MINIO": - minioExist = true - } - var item dto.BackupInfo - if err := copier.Copy(&item, &group); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } - dtobas = append(dtobas, item) - } - if !ossExist { - dtobas = append(dtobas, dto.BackupInfo{Type: "OSS"}) - } - if !s3Exist { - dtobas = append(dtobas, dto.BackupInfo{Type: "S3"}) - } - if !sftpExist { - dtobas = append(dtobas, dto.BackupInfo{Type: "SFTP"}) - } - if !minioExist { - dtobas = append(dtobas, dto.BackupInfo{Type: "MINIO"}) - } + dtobas = append(dtobas, u.loadByType("LOCAL", ops)) + dtobas = append(dtobas, u.loadByType("OSS", ops)) + dtobas = append(dtobas, u.loadByType("S3", ops)) + dtobas = append(dtobas, u.loadByType("SFTP", ops)) + dtobas = append(dtobas, u.loadByType("MINIO", ops)) + dtobas = append(dtobas, u.loadByType("COS", ops)) + dtobas = append(dtobas, u.loadByType("KODO", ops)) return dtobas, err } @@ -123,7 +101,7 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error) case constant.Sftp: varMap["username"] = backup.AccessKey varMap["password"] = backup.Credential - case constant.OSS, constant.S3, constant.MinIo: + case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: varMap["accessKey"] = backup.AccessKey varMap["secretKey"] = backup.Credential } @@ -171,7 +149,7 @@ func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, err case constant.Sftp: varMap["username"] = backupDto.AccessKey varMap["password"] = backupDto.Credential - case constant.OSS, constant.S3, constant.MinIo: + case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: varMap["accessKey"] = backupDto.AccessKey varMap["secretKey"] = backupDto.Credential } @@ -182,8 +160,12 @@ func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, err return client.ListBuckets() } -func (u *BackupService) BatchDelete(ids []uint) error { - return backupRepo.Delete(commonRepo.WithIdsIn(ids)) +func (u *BackupService) Delete(id uint) error { + cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByBackupID(id)) + if len(cronjobs) != 0 { + return buserr.New(constant.ErrBackupInUsed) + } + return backupRepo.Delete(commonRepo.WithByID(id)) } func (u *BackupService) BatchDeleteRecord(ids []uint) error { @@ -277,7 +259,7 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl case constant.Sftp: varMap["username"] = backup.AccessKey varMap["password"] = backup.Credential - case constant.OSS, constant.S3, constant.MinIo: + case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: varMap["accessKey"] = backup.AccessKey varMap["secretKey"] = backup.Credential } @@ -290,6 +272,19 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl return backClient, nil } +func (u *BackupService) loadByType(accountType string, accounts []model.BackupAccount) dto.BackupInfo { + for _, account := range accounts { + if account.Type == accountType { + var item dto.BackupInfo + if err := copier.Copy(&item, &account); err != nil { + global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err) + } + return item + } + } + return dto.BackupInfo{Type: accountType} +} + func loadLocalDir() (string, error) { backup, err := backupRepo.Get(commonRepo.WithByType("LOCAL")) if err != nil { diff --git a/backend/app/service/backup_app.go b/backend/app/service/backup_app.go index aeed9f0c4..c8ef87ce9 100644 --- a/backend/app/service/backup_app.go +++ b/backend/app/service/backup_app.go @@ -1,6 +1,7 @@ package service import ( + "context" "encoding/json" "fmt" "io/fs" @@ -32,6 +33,7 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) error { return err } timeNow := time.Now().Format("20060102150405") + backupDir := fmt.Sprintf("%s/app/%s/%s", localDir, req.Name, req.DetailName) fileName := fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow) @@ -97,7 +99,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro return err } - appPath := fmt.Sprintf("%s/%s/%s", constant.AppInstallDir, install.App.Key, install.Name) + appPath := fmt.Sprintf("%s/%s", install.GetPath(), install.Name) if err := handleTar(appPath, tmpDir, "app.tar.gz", ""); err != nil { return err } @@ -192,7 +194,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback } oldInstall.Status = constant.Running - if err := appInstallRepo.Save(install); err != nil { + if err := appInstallRepo.Save(context.Background(), install); err != nil { global.LOG.Errorf("save db app install failed, err: %v", err) return err } diff --git a/backend/app/service/backup_redis.go b/backend/app/service/backup_redis.go index e71f75540..93b63fbae 100644 --- a/backend/app/service/backup_redis.go +++ b/backend/app/service/backup_redis.go @@ -2,7 +2,6 @@ package service import ( "fmt" - "io/ioutil" "os" "path" "strings" @@ -176,11 +175,11 @@ func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback if appendonly == "yes" && redisInfo.Version == "6.0.16" { itemName = "appendonly.aof" } - input, err := ioutil.ReadFile(recoverFile) + input, err := os.ReadFile(recoverFile) if err != nil { return err } - if err = ioutil.WriteFile(composeDir+"/data/"+itemName, input, 0640); err != nil { + if err = os.WriteFile(composeDir+"/data/"+itemName, input, 0640); err != nil { return err } } diff --git a/backend/app/service/container.go b/backend/app/service/container.go index 9f54045a1..41b2c9a3b 100644 --- a/backend/app/service/container.go +++ b/backend/app/service/container.go @@ -3,8 +3,9 @@ package service import ( "context" "encoding/json" + "errors" "fmt" - "io/ioutil" + "io" "os/exec" "sort" "strconv" @@ -21,6 +22,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" "github.com/docker/go-connections/nat" v1 "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -33,7 +35,7 @@ type IContainerService interface { PageVolume(req dto.SearchWithPage) (int64, interface{}, error) ListVolume() ([]dto.Options, error) PageCompose(req dto.SearchWithPage) (int64, interface{}, error) - CreateCompose(req dto.ComposeCreate) error + CreateCompose(req dto.ComposeCreate) (string, error) ComposeOperation(req dto.ComposeOperation) error ContainerCreate(req dto.ContainerCreate) error ContainerOperation(req dto.ContainerOperation) error @@ -44,6 +46,8 @@ type IContainerService interface { CreateNetwork(req dto.NetworkCreat) error DeleteVolume(req dto.BatchDelete) error CreateVolume(req dto.VolumeCreat) error + TestCompose(req dto.ComposeCreate) (bool, error) + ComposeUpdate(req dto.ComposeUpdate) error } func NewIContainerService() IContainerService { @@ -155,10 +159,12 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerCreate) error { return err } config := &container.Config{ - Image: req.Image, - Cmd: req.Cmd, - Env: req.Env, - Labels: stringsToMap(req.Labels), + Image: req.Image, + Cmd: req.Cmd, + Env: req.Env, + Labels: stringsToMap(req.Labels), + Tty: true, + OpenStdin: true, } hostConf := &container.HostConfig{ AutoRemove: req.AutoRemove, @@ -190,14 +196,21 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerCreate) error { } global.LOG.Infof("new container info %s has been made, now start to create", req.Name) - container, err := client.ContainerCreate(context.TODO(), config, hostConf, &network.NetworkingConfig{}, &v1.Platform{}, req.Name) + + ctx := context.Background() + if !checkImageExist(client, req.Image) { + if err := pullImages(ctx, client, req.Image); err != nil { + return err + } + } + container, err := client.ContainerCreate(ctx, config, hostConf, &network.NetworkingConfig{}, &v1.Platform{}, req.Name) if err != nil { - _ = client.ContainerRemove(context.Background(), req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) + _ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) return err } global.LOG.Infof("create container %s successful! now check if the container is started and delete the container information if it is not.", req.Name) - if err := client.ContainerStart(context.TODO(), container.ID, types.ContainerStartOptions{}); err != nil { - _ = client.ContainerRemove(context.Background(), req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) + if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil { + _ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}) return fmt.Errorf("create successful but start failed, err: %v", err) } return nil @@ -215,9 +228,9 @@ func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error case constant.ContainerOpStart: err = client.ContainerStart(ctx, req.Name, types.ContainerStartOptions{}) case constant.ContainerOpStop: - err = client.ContainerStop(ctx, req.Name, nil) + err = client.ContainerStop(ctx, req.Name, container.StopOptions{}) case constant.ContainerOpRestart: - err = client.ContainerRestart(ctx, req.Name, nil) + err = client.ContainerRestart(ctx, req.Name, container.StopOptions{}) case constant.ContainerOpKill: err = client.ContainerKill(ctx, req.Name, "SIGKILL") case constant.ContainerOpPause: @@ -239,7 +252,7 @@ func (u *ContainerService) ContainerLogs(req dto.ContainerLog) (string, error) { } stdout, err := cmd.CombinedOutput() if err != nil { - return "", err + return "", errors.New(string(stdout)) } return string(stdout), nil } @@ -255,7 +268,7 @@ func (u *ContainerService) ContainerStats(id string) (*dto.ContainterStats, erro } defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { return nil, err } @@ -320,3 +333,33 @@ func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) } return rx, tx } + +func checkImageExist(client *client.Client, image string) bool { + images, err := client.ImageList(context.Background(), types.ImageListOptions{}) + if err != nil { + fmt.Println(err) + return false + } + + for _, img := range images { + for _, tag := range img.RepoTags { + if tag == image || tag == image+":latest" { + return true + } + } + } + return false +} + +func pullImages(ctx context.Context, client *client.Client, image string) error { + out, err := client.ImagePull(ctx, image, types.ImagePullOptions{}) + if err != nil { + return err + } + defer out.Close() + _, err = io.Copy(io.Discard, out) + if err != nil { + return err + } + return nil +} diff --git a/backend/app/service/container_compose.go b/backend/app/service/container_compose.go index d0a384385..e415ec9e7 100644 --- a/backend/app/service/container_compose.go +++ b/backend/app/service/container_compose.go @@ -5,6 +5,8 @@ import ( "errors" "fmt" "os" + "os/exec" + "path" "sort" "strings" "time" @@ -123,41 +125,49 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface return int64(total), BackDatas, nil } -func (u *ContainerService) CreateCompose(req dto.ComposeCreate) error { - if req.From == "template" { - template, err := composeRepo.Get(commonRepo.WithByID(req.Template)) - if err != nil { - return err - } - req.From = "edit" - req.File = template.Content +func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) { + if err := u.loadPath(&req); err != nil { + return false, err } - if req.From == "edit" { - dir := fmt.Sprintf("%s/docker/compose/%s", constant.DataDir, req.Name) - if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(dir, os.ModePerm); err != nil { - return err - } - } + cmd := exec.Command("docker-compose", "-f", req.Path, "config") + stdout, err := cmd.CombinedOutput() + if err != nil { + return false, errors.New(string(stdout)) + } + return true, nil +} - path := fmt.Sprintf("%s/docker-compose.yml", dir) - file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return err - } - defer file.Close() - write := bufio.NewWriter(file) - _, _ = write.WriteString(string(req.File)) - write.Flush() - req.Path = path +func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) { + if err := u.loadPath(&req); err != nil { + return "", err } global.LOG.Infof("docker-compose.yml %s create successful, start to docker-compose up", req.Name) - if stdout, err := compose.Up(req.Path); err != nil { - return errors.New(string(stdout)) - } - _ = composeRepo.CreateRecord(&model.Compose{Name: req.Name}) - return nil + if req.From == "path" { + req.Name = path.Base(strings.ReplaceAll(req.Path, "/"+path.Base(req.Path), "")) + } + logName := path.Dir(req.Path) + "/compose.log" + file, err := os.OpenFile(logName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return "", err + } + go func() { + defer file.Close() + cmd := exec.Command("docker-compose", "-f", req.Path, "up", "-d") + stdout, err := cmd.CombinedOutput() + _, _ = file.Write(stdout) + if err != nil { + global.LOG.Errorf("docker-compose up %s failed, err: %v", req.Name, err) + _, _ = compose.Down(req.Path) + _, _ = file.WriteString("docker-compose up failed!") + return + } + global.LOG.Infof("docker-compose up %s successful!", req.Name) + _ = composeRepo.CreateRecord(&model.Compose{Name: req.Name}) + _, _ = file.WriteString("docker-compose up successful!") + }() + + return logName, nil } func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error { @@ -199,3 +209,34 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error { return nil } + +func (u *ContainerService) loadPath(req *dto.ComposeCreate) error { + if req.From == "template" { + template, err := composeRepo.Get(commonRepo.WithByID(req.Template)) + if err != nil { + return err + } + req.From = "edit" + req.File = template.Content + } + if req.From == "edit" { + dir := fmt.Sprintf("%s/docker/compose/%s", constant.DataDir, req.Name) + if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(dir, os.ModePerm); err != nil { + return err + } + } + + path := fmt.Sprintf("%s/docker-compose.yml", dir) + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(string(req.File)) + write.Flush() + req.Path = path + } + return nil +} diff --git a/backend/app/service/container_volume.go b/backend/app/service/container_volume.go index 0dc42739b..fb8193482 100644 --- a/backend/app/service/container_volume.go +++ b/backend/app/service/container_volume.go @@ -10,7 +10,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/volume" ) @@ -37,14 +36,14 @@ func (u *ContainerService) PageVolume(req dto.SearchWithPage) (int64, interface{ } var ( data []dto.Volume - records []*types.Volume + records []*volume.Volume ) sort.Slice(list.Volumes, func(i, j int) bool { return list.Volumes[i].CreatedAt > list.Volumes[j].CreatedAt }) total, start, end := len(list.Volumes), (req.Page-1)*req.PageSize, req.Page*req.PageSize if start > total { - records = make([]*types.Volume, 0) + records = make([]*volume.Volume, 0) } else { if end >= total { end = total @@ -119,7 +118,7 @@ func (u *ContainerService) CreateVolume(req dto.VolumeCreat) error { } } } - options := volume.VolumeCreateBody{ + options := volume.CreateOptions{ Name: req.Name, Driver: req.Driver, DriverOpts: stringsToMap(req.Options), diff --git a/backend/app/service/cornjob.go b/backend/app/service/cornjob.go index 712d07217..0a76ef48e 100644 --- a/backend/app/service/cornjob.go +++ b/backend/app/service/cornjob.go @@ -2,17 +2,15 @@ package service import ( "bufio" - "encoding/json" "fmt" "os" - "strings" + "path" "time" "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage" "github.com/jinzhu/copier" "github.com/pkg/errors" "github.com/robfig/cron/v3" @@ -27,7 +25,10 @@ type ICronjobService interface { HandleOnce(id uint) error Update(id uint, req dto.CronjobUpdate) error UpdateStatus(id uint, status string) error - Delete(ids []uint) error + Delete(req dto.CronjobBatchDelete) error + Download(down dto.CronjobDownload) (string, error) + StartJob(cronjob *model.Cronjob) (int, error) + CleanRecord(req dto.CronjobClean) error } func NewICronjobService() ICronjobService { @@ -79,6 +80,44 @@ func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interfac return total, dtoCronjobs, err } +func (u *CronjobService) CleanRecord(req dto.CronjobClean) error { + cronjob, err := cronjobRepo.Get(commonRepo.WithByID(req.CronjobID)) + if err != nil { + return err + } + if req.CleanData && cronjob.Type != "shell" && cronjob.Type != "curl" { + cronjob.RetainCopies = 0 + backup, err := backupRepo.Get(commonRepo.WithByID(uint(cronjob.TargetDirID))) + if err != nil { + return err + } + if backup.Type != "LOCAL" { + localDir, err := loadLocalDir() + if err != nil { + return err + } + client, err := NewIBackupService().NewClient(&backup) + if err != nil { + return err + } + u.HandleRmExpired(backup.Type, localDir, &cronjob, client) + } else { + u.HandleRmExpired(backup.Type, "", &cronjob, nil) + } + } + delRecords, err := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(req.CronjobID))) + if err != nil { + return err + } + for _, del := range delRecords { + _ = os.RemoveAll(del.Records) + } + if err := cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(req.CronjobID))); err != nil { + return err + } + return nil +} + func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) { record, _ := cronjobRepo.GetRecord(commonRepo.WithByID(down.RecordID)) if record.ID == 0 { @@ -92,69 +131,23 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) { if cronjob.ID == 0 { return "", constant.ErrRecordNotFound } - - global.LOG.Infof("start to download records %s from %s", cronjob.Type, backup.Type) - varMap := make(map[string]interface{}) - if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { + if backup.Type == "LOCAL" || record.FromLocal { + if _, err := os.Stat(record.File); err != nil && os.IsNotExist(err) { + return "", constant.ErrRecordNotFound + } + return record.File, nil + } + client, err := NewIBackupService().NewClient(&backup) + if err != nil { return "", err } - varMap["type"] = backup.Type - if backup.Type != "LOCAL" { - varMap["bucket"] = backup.Bucket - switch backup.Type { - case constant.Sftp: - varMap["username"] = backup.AccessKey - varMap["password"] = backup.Credential - case constant.OSS, constant.S3, constant.MinIo: - varMap["accessKey"] = backup.AccessKey - varMap["secretKey"] = backup.Credential - } - backClient, err := cloud_storage.NewCloudStorageClient(varMap) - if err != nil { - return "", fmt.Errorf("new cloud storage client failed, err: %v", err) - } - global.LOG.Info("new backup client successful") - commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name) - name := fmt.Sprintf("%s%s.tar.gz", commonDir, record.StartTime.Format("20060102150405")) - if cronjob.Type == "database" { - name = fmt.Sprintf("%s%s.gz", commonDir, record.StartTime.Format("20060102150405")) - } - tempPath := fmt.Sprintf("%s/download/%s", constant.DataDir, commonDir) - if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) { - if err = os.MkdirAll(tempPath, os.ModePerm); err != nil { - global.LOG.Errorf("mkdir %s failed, err: %v", tempPath, err) - } - } - - global.LOG.Infof("download records %s from %s to %s", name, commonDir, tempPath) - targetPath := tempPath + strings.ReplaceAll(name, commonDir, "") - if _, err = os.Stat(targetPath); err != nil && os.IsNotExist(err) { - isOK, err := backClient.Download(name, targetPath) - if !isOK { - return "", fmt.Errorf("cloud storage download failed, err: %v", err) - } - } - return targetPath, nil - } - if _, ok := varMap["dir"]; !ok { - return "", errors.New("load local backup dir failed") - } - global.LOG.Infof("record is save in local dir %s", varMap["dir"]) - - switch cronjob.Type { - case "website": - return fmt.Sprintf("%v/website/%s/website_%s_%s.tar.gz", varMap["dir"], cronjob.Website, cronjob.Website, record.StartTime.Format("20060102150405")), nil - case "database": - mysqlInfo, err := appInstallRepo.LoadBaseInfo("mysql", "") - if err != nil { - return "", fmt.Errorf("load mysqlInfo failed, err: %v", err) - } - return fmt.Sprintf("%v/database/mysql/%s/%s/db_%s_%s.sql.gz", varMap["dir"], mysqlInfo.Name, cronjob.DBName, cronjob.DBName, record.StartTime.Format("20060102150405")), nil - case "directory": - return fmt.Sprintf("%v/%s/%s/directory%s_%s.tar.gz", varMap["dir"], cronjob.Type, cronjob.Name, strings.ReplaceAll(cronjob.SourceDir, "/", "_"), record.StartTime.Format("20060102150405")), nil - default: - return "", fmt.Errorf("not support type %s", cronjob.Type) + tempPath := fmt.Sprintf("%s/download/%s", constant.DataDir, record.File) + _ = os.MkdirAll(path.Dir(tempPath), os.ModePerm) + isOK, err := client.Download(record.File, tempPath) + if !isOK || err != nil { + return "", constant.ErrRecordNotFound } + return tempPath, nil } func (u *CronjobService) HandleOnce(id uint) error { @@ -201,21 +194,23 @@ func (u *CronjobService) StartJob(cronjob *model.Cronjob) (int, error) { return entryID, nil } -func (u *CronjobService) Delete(ids []uint) error { - if len(ids) == 1 { - if err := u.HandleDelete(ids[0]); err != nil { +func (u *CronjobService) Delete(req dto.CronjobBatchDelete) error { + for _, id := range req.IDs { + cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(id)) + if cronjob.ID == 0 { + return errors.New("find cronjob in db failed") + } + global.Cron.Remove(cron.EntryID(cronjob.EntryID)) + global.LOG.Infof("stop cronjob entryID: %d", cronjob.EntryID) + if err := u.CleanRecord(dto.CronjobClean{CronjobID: id, CleanData: req.CleanData}); err != nil { + return err + } + if err := cronjobRepo.Delete(commonRepo.WithByID(id)); err != nil { return err } - return cronjobRepo.Delete(commonRepo.WithByID(ids[0])) } - cronjobs, err := cronjobRepo.List(commonRepo.WithIdsIn(ids)) - if err != nil { - return err - } - for i := range cronjobs { - _ = u.HandleDelete(ids[i]) - } - return cronjobRepo.Delete(commonRepo.WithIdsIn(ids)) + + return nil } func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error { @@ -238,6 +233,7 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error { upMap := make(map[string]interface{}) upMap["entry_id"] = newEntryID upMap["name"] = req.Name + upMap["spec"] = cronjob.Spec upMap["script"] = req.Script upMap["spec_type"] = req.SpecType upMap["week"] = req.Week diff --git a/backend/app/service/cronjob_helper.go b/backend/app/service/cronjob_helper.go index 375fe96a4..8fe5cee1a 100644 --- a/backend/app/service/cronjob_helper.go +++ b/backend/app/service/cronjob_helper.go @@ -3,18 +3,18 @@ package service import ( "context" "fmt" - "io/ioutil" "os" + "path" "strings" "time" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/app/repo" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cloud_storage" "github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/pkg/errors" - "github.com/robfig/cron/v3" ) func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { @@ -22,19 +22,19 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { message []byte err error ) - record := cronjobRepo.StartRecords(cronjob.ID, "") - record.FromLocal = cronjob.KeepLocal + record := cronjobRepo.StartRecords(cronjob.ID, cronjob.KeepLocal, "") go func() { switch cronjob.Type { case "shell": if len(cronjob.Script) == 0 { return } - stdout, errExec := cmd.Exec(cronjob.Script) + stdout, errExec := cmd.ExecWithTimeOut(cronjob.Script, 5*time.Minute) if errExec != nil { err = errExec } message = []byte(stdout) + u.HandleRmExpired("LOCAL", "", cronjob, nil) case "website": record.File, err = u.HandleBackup(cronjob, record.StartTime) case "database": @@ -48,11 +48,12 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { if len(cronjob.URL) == 0 { return } - stdout, errCurl := cmd.Exec("curl " + cronjob.URL) + stdout, errCurl := cmd.ExecWithTimeOut("curl "+cronjob.URL, 5*time.Minute) if err != nil { err = errCurl } message = []byte(stdout) + u.HandleRmExpired("LOCAL", "", cronjob, nil) } if err != nil { cronjobRepo.EndRecords(record, constant.StatusFailed, err.Error(), string(message)) @@ -69,11 +70,6 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) { } func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Time) (string, error) { - var ( - backupDir string - fileName string - record model.BackupRecord - ) backup, err := backupRepo.Get(commonRepo.WithByID(uint(cronjob.TargetDirID))) if err != nil { return "", err @@ -90,141 +86,60 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim if err != nil { return "", err } - fileName = fmt.Sprintf("db_%s_%s.sql.gz", cronjob.DBName, startTime.Format("20060102150405")) - backupDir = fmt.Sprintf("%s/database/mysql/%s/%s", localDir, app.Name, cronjob.DBName) - if err = handleMysqlBackup(app, backupDir, cronjob.DBName, fileName); err != nil { - return "", err - } - record.Type = "mysql" - record.Name = app.Name - record.DetailName = cronjob.DBName + paths, err := u.handleDatabase(*cronjob, app, backup, startTime) + return strings.Join(paths, ","), err case "website": - fileName = fmt.Sprintf("website_%s_%s.tar.gz", cronjob.Website, startTime.Format("20060102150405")) - backupDir = fmt.Sprintf("%s/website/%s", localDir, cronjob.Website) - website, err := websiteRepo.GetFirst(websiteRepo.WithDomain(cronjob.Website)) - if err != nil { - return "", err - } - if err := handleWebsiteBackup(&website, backupDir, fileName); err != nil { - return "", err - } - record.Type = "website" - record.Name = website.PrimaryDomain + paths, err := u.handleWebsite(*cronjob, backup, startTime) + return strings.Join(paths, ","), err default: - fileName = fmt.Sprintf("directory%s_%s.tar.gz", strings.ReplaceAll(cronjob.SourceDir, "/", "_"), startTime.Format("20060102150405")) - backupDir = fmt.Sprintf("%s/%s/%s", localDir, cronjob.Type, cronjob.Name) + fileName := fmt.Sprintf("directory%s_%s.tar.gz", strings.ReplaceAll(cronjob.SourceDir, "/", "_"), startTime.Format("20060102150405")) + backupDir := fmt.Sprintf("%s/%s/%s", localDir, cronjob.Type, cronjob.Name) + itemFileDir := fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name) global.LOG.Infof("handle tar %s to %s", backupDir, fileName) if err := handleTar(cronjob.SourceDir, backupDir, fileName, cronjob.ExclusionRules); err != nil { return "", err } - } - - itemFileDir := strings.ReplaceAll(backupDir, localDir+"/", "") - if len(record.Name) != 0 { - record.FileName = fileName - record.FileDir = backupDir - record.Source = "LOCAL" - record.BackupType = backup.Type - if !cronjob.KeepLocal && backup.Type != "LOCAL" { - record.Source = backup.Type - record.FileDir = itemFileDir - } - if err := backupRepo.CreateRecord(&record); err != nil { - global.LOG.Errorf("save backup record failed, err: %v", err) - return "", err - } - } - - fullPath := fmt.Sprintf("%s/%s", record.FileDir, fileName) - if backup.Type == "LOCAL" { - u.HandleRmExpired(backup.Type, backupDir, cronjob, nil) - return fullPath, nil - } - - if !cronjob.KeepLocal { - defer func() { - _ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, fileName)) - }() - } - client, err := NewIBackupService().NewClient(&backup) - if err != nil { - return fullPath, err - } - if _, err = client.Upload(backupDir+"/"+fileName, itemFileDir+"/"+fileName); err != nil { - return fullPath, err - } - u.HandleRmExpired(backup.Type, itemFileDir, cronjob, client) - if cronjob.KeepLocal { - u.HandleRmExpired("LOCAL", backupDir, cronjob, client) - } - return fullPath, nil -} - -func (u *CronjobService) HandleDelete(id uint) error { - cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(id)) - if cronjob.ID == 0 { - return errors.New("find cronjob in db failed") - } - commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name) - global.Cron.Remove(cron.EntryID(cronjob.EntryID)) - global.LOG.Infof("stop cronjob entryID: %d", cronjob.EntryID) - _ = cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(id))) - - dir := fmt.Sprintf("%s/task/%s/%s", constant.DataDir, cronjob.Type, cronjob.Name) - if _, err := os.Stat(dir); err == nil { - if err := os.RemoveAll(dir); err != nil { - global.LOG.Errorf("rm file %s/task/%s failed, err: %v", constant.DataDir, commonDir, err) - } - } - return nil -} - -func (u *CronjobService) HandleRmExpired(backType, backupDir string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) { - global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies) - if backType != "LOCAL" { - currentObjs, err := backClient.ListObjects(backupDir + "/") - if err != nil { - global.LOG.Errorf("list bucket object %s failed, err: %v", backupDir, err) - return - } - for i := 0; i < len(currentObjs)-int(cronjob.RetainCopies); i++ { - _, _ = backClient.Delete(currentObjs[i].(string)) - } - return - } - files, err := ioutil.ReadDir(backupDir) - if err != nil { - global.LOG.Errorf("read dir %s failed, err: %v", backupDir, err) - return - } - if len(files) == 0 { - return - } - - prefix := "" - switch cronjob.Type { - case "database": - prefix = "db_" - case "website": - prefix = "website_" - case "directory": - prefix = "directory_" - } - - dbCopies := uint64(0) - for i := len(files) - 1; i >= 0; i-- { - if strings.HasPrefix(files[i].Name(), prefix) { - dbCopies++ - if dbCopies > cronjob.RetainCopies { - _ = os.Remove(backupDir + "/" + files[i].Name()) - _ = backupRepo.DeleteRecord(context.Background(), backupRepo.WithByFileName(files[i].Name())) + var client cloud_storage.CloudStorageClient + if backup.Type != "LOCAL" { + if !cronjob.KeepLocal { + defer func() { + _ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, fileName)) + }() + } + client, err = NewIBackupService().NewClient(&backup) + if err != nil { + return "", err + } + if _, err = client.Upload(backupDir+"/"+fileName, itemFileDir+"/"+fileName); err != nil { + return "", err } } + u.HandleRmExpired(backup.Type, localDir, cronjob, client) + if backup.Type == "LOCAL" || cronjob.KeepLocal { + return fmt.Sprintf("%s/%s/%s/%s", localDir, cronjob.Type, cronjob.Name, fileName), nil + } + return fmt.Sprintf("%s/%s/%s", cronjob.Type, cronjob.Name, fileName), nil } - records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID))) +} + +func (u *CronjobService) HandleRmExpired(backType, localDir string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) { + global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies) + records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID)), commonRepo.WithOrderBy("created_at desc")) if len(records) > int(cronjob.RetainCopies) { for i := int(cronjob.RetainCopies); i < len(records); i++ { - _ = cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(records[i].ID))) + files := strings.Split(records[i].File, ",") + for _, file := range files { + if backType != "LOCAL" { + _, _ = backClient.Delete(strings.ReplaceAll(file, localDir+"/", "")) + _ = os.Remove(file) + } else { + _ = os.Remove(file) + } + _ = backupRepo.DeleteRecord(context.TODO(), backupRepo.WithByFileName(path.Base(file))) + } + + _ = cronjobRepo.DeleteRecord(commonRepo.WithByID(uint(records[i].ID))) + _ = os.Remove(records[i].Records) } } } @@ -255,7 +170,7 @@ func handleTar(sourceDir, targetDir, name, exclusionRules string) error { commands := fmt.Sprintf("tar zcvf %s %s %s", targetDir+"/"+name, excludeRules, path) global.LOG.Debug(commands) - stdout, err := cmd.Exec(commands) + stdout, err := cmd.ExecWithTimeOut(commands, 5*time.Minute) if err != nil { global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) return errors.New(stdout) @@ -272,10 +187,144 @@ func handleUnTar(sourceFile, targetDir string) error { commands := fmt.Sprintf("tar zxvfC %s %s", sourceFile, targetDir) global.LOG.Debug(commands) - stdout, err := cmd.Exec(commands) + stdout, err := cmd.ExecWithTimeOut(commands, 5*time.Minute) if err != nil { global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) return errors.New(stdout) } return nil } + +func (u *CronjobService) handleDatabase(cronjob model.Cronjob, app *repo.RootInfo, backup model.BackupAccount, startTime time.Time) ([]string, error) { + var paths []string + localDir, err := loadLocalDir() + if err != nil { + return paths, err + } + + var dblist []string + if cronjob.DBName == "all" { + mysqlService := NewIMysqlService() + dblist, err = mysqlService.ListDBName() + if err != nil { + return paths, err + } + } else { + dblist = append(dblist, cronjob.DBName) + } + + var client cloud_storage.CloudStorageClient + if backup.Type != "LOCAL" { + client, err = NewIBackupService().NewClient(&backup) + if err != nil { + return paths, err + } + } + + for _, dbName := range dblist { + var record model.BackupRecord + + record.Type = "mysql" + record.Name = app.Name + record.Source = "LOCAL" + record.BackupType = backup.Type + + backupDir := fmt.Sprintf("%s/database/mysql/%s/%s", localDir, app.Name, dbName) + record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbName, startTime.Format("20060102150405")) + if err = handleMysqlBackup(app, backupDir, dbName, record.FileName); err != nil { + return paths, err + } + record.DetailName = dbName + record.FileDir = backupDir + itemFileDir := strings.ReplaceAll(backupDir, localDir+"/", "") + if !cronjob.KeepLocal && backup.Type != "LOCAL" { + record.Source = backup.Type + record.FileDir = itemFileDir + } + paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName)) + + if err := backupRepo.CreateRecord(&record); err != nil { + global.LOG.Errorf("save backup record failed, err: %v", err) + return paths, err + } + if backup.Type != "LOCAL" { + if !cronjob.KeepLocal { + defer func() { + _ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, record.FileName)) + }() + } + if _, err = client.Upload(backupDir+"/"+record.FileName, itemFileDir+"/"+record.FileName); err != nil { + return paths, err + } + } + } + u.HandleRmExpired(backup.Type, localDir, &cronjob, client) + return paths, nil +} + +func (u *CronjobService) handleWebsite(cronjob model.Cronjob, backup model.BackupAccount, startTime time.Time) ([]string, error) { + var paths []string + localDir, err := loadLocalDir() + if err != nil { + return paths, err + } + + var weblist []string + if cronjob.Website == "all" { + weblist, err = NewIWebsiteService().GetWebsiteOptions() + if err != nil { + return paths, err + } + } else { + weblist = append(weblist, cronjob.Website) + } + + var client cloud_storage.CloudStorageClient + if backup.Type != "LOCAL" { + client, err = NewIBackupService().NewClient(&backup) + if err != nil { + return paths, err + } + } + + for _, websiteItem := range weblist { + var record model.BackupRecord + record.Type = "website" + record.Name = cronjob.Website + record.Source = "LOCAL" + record.BackupType = backup.Type + website, err := websiteRepo.GetFirst(websiteRepo.WithDomain(websiteItem)) + if err != nil { + return paths, err + } + backupDir := fmt.Sprintf("%s/website/%s", localDir, website.PrimaryDomain) + record.FileDir = backupDir + itemFileDir := strings.ReplaceAll(backupDir, localDir+"/", "") + if !cronjob.KeepLocal && backup.Type != "LOCAL" { + record.Source = backup.Type + record.FileDir = strings.ReplaceAll(backupDir, localDir+"/", "") + } + record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", website.PrimaryDomain, startTime.Format("20060102150405")) + paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName)) + if err := handleWebsiteBackup(&website, backupDir, record.FileName); err != nil { + return paths, err + } + record.Name = website.PrimaryDomain + if err := backupRepo.CreateRecord(&record); err != nil { + global.LOG.Errorf("save backup record failed, err: %v", err) + return paths, err + } + if backup.Type != "LOCAL" { + if !cronjob.KeepLocal { + defer func() { + _ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, record.FileName)) + }() + } + if _, err = client.Upload(backupDir+"/"+record.FileName, itemFileDir+"/"+record.FileName); err != nil { + return paths, err + } + } + } + u.HandleRmExpired(backup.Type, localDir, &cronjob, client) + return paths, nil +} diff --git a/backend/app/service/dashboard.go b/backend/app/service/dashboard.go index d40cf0e55..69a0fb9b1 100644 --- a/backend/app/service/dashboard.go +++ b/backend/app/service/dashboard.go @@ -2,9 +2,11 @@ package service import ( "encoding/json" + "strings" "time" "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/host" @@ -39,27 +41,6 @@ func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto ss, _ := json.Marshal(hostInfo) baseInfo.VirtualizationSystem = string(ss) - apps, err := appRepo.GetBy() - if err != nil { - return nil, err - } - for _, app := range apps { - switch app.Key { - case "dateease": - baseInfo.DateeaseID = app.ID - case "halo": - baseInfo.HaloID = app.ID - case "metersphere": - baseInfo.MeterSphereID = app.ID - case "jumpserver": - baseInfo.JumpServerID = app.ID - case "kubeoperator": - baseInfo.KubeoperatorID = app.ID - case "kubepi": - baseInfo.KubepiID = app.ID - } - } - appInstall, err := appInstallRepo.ListBy() if err != nil { return nil, err @@ -120,15 +101,7 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d currentInfo.MemoryUsed = memoryInfo.Used currentInfo.MemoryUsedPercent = memoryInfo.UsedPercent - state, _ := disk.Usage("/") - currentInfo.Total = state.Total - currentInfo.Free = state.Free - currentInfo.Used = state.Used - currentInfo.UsedPercent = state.UsedPercent - currentInfo.InodesTotal = state.InodesTotal - currentInfo.InodesUsed = state.InodesUsed - currentInfo.InodesFree = state.InodesFree - currentInfo.InodesUsedPercent = state.InodesUsedPercent + currentInfo.DiskData = loadDiskInfo() if ioOption == "all" { diskInfo, _ := disk.IOCounters() @@ -136,20 +109,17 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d currentInfo.IOReadBytes += state.ReadBytes currentInfo.IOWriteBytes += state.WriteBytes currentInfo.IOCount += (state.ReadCount + state.WriteCount) - currentInfo.IOTime += state.ReadTime / 1000 / 1000 - if state.WriteTime > state.ReadTime { - currentInfo.IOTime += state.WriteTime / 1000 / 1000 - } + currentInfo.IOReadTime += state.ReadTime + currentInfo.IOWriteTime += state.WriteTime } } else { diskInfo, _ := disk.IOCounters(ioOption) for _, state := range diskInfo { currentInfo.IOReadBytes += state.ReadBytes currentInfo.IOWriteBytes += state.WriteBytes - currentInfo.IOTime += state.ReadTime / 1000 / 1000 - if state.WriteTime > state.ReadTime { - currentInfo.IOTime += state.WriteTime / 1000 / 1000 - } + currentInfo.IOCount += (state.ReadCount + state.WriteCount) + currentInfo.IOReadTime += state.ReadTime + currentInfo.IOWriteTime += state.WriteTime } } @@ -172,3 +142,67 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d currentInfo.ShotTime = time.Now() return ¤tInfo } + +type diskInfo struct { + Type string + Mount string + Device string +} + +func loadDiskInfo() []dto.DiskInfo { + var datas []dto.DiskInfo + stdout, err := cmd.Exec("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev") + if err != nil { + return datas + } + lines := strings.Split(stdout, "\n") + + 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) + if len(fields) < 7 { + continue + } + if fields[1] == "tmpfs" { + continue + } + if strings.Contains(fields[2], "M") || strings.Contains(fields[2], "K") { + continue + } + if strings.Contains(fields[6], "docker") { + continue + } + isExclude := false + for _, exclude := range excludes { + if exclude == fields[6] { + isExclude = true + } + } + if isExclude { + continue + } + mounts = append(mounts, diskInfo{Type: fields[1], Device: fields[0], Mount: fields[6]}) + } + + for i := 0; i < len(mounts); i++ { + state, err := disk.Usage(mounts[i].Mount) + if err != nil { + continue + } + var itemData dto.DiskInfo + itemData.Path = mounts[i].Mount + itemData.Type = mounts[i].Type + itemData.Device = mounts[i].Device + itemData.Total = state.Total + itemData.Free = state.Free + itemData.Used = state.Used + itemData.UsedPercent = state.UsedPercent + itemData.InodesTotal = state.InodesTotal + itemData.InodesUsed = state.InodesUsed + itemData.InodesFree = state.InodesFree + itemData.InodesUsedPercent = state.InodesUsedPercent + datas = append(datas, itemData) + } + return datas +} diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index 673adff2c..5984628b3 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -5,7 +5,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "os" "os/exec" "regexp" @@ -94,25 +93,28 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode } createSql := fmt.Sprintf("create database `%s` default character set %s collate %s", req.Name, req.Format, formatMap[req.Format]) - if err := excuteSql(app.ContainerName, app.Password, createSql); err != nil { + if err := excSQL(app.ContainerName, app.Password, createSql); err != nil { if strings.Contains(err.Error(), "ERROR 1007") { return nil, buserr.New(constant.ErrDatabaseIsExist) } return nil, err } tmpPermission := req.Permission - if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user '%s'@'%s' identified by '%s';", req.Username, tmpPermission, req.Password)); err != nil { - _ = excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", req.Name)) + if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("create user '%s'@'%s' identified by '%s';", req.Username, tmpPermission, req.Password)); err != nil { + _ = excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", req.Name)) if strings.Contains(err.Error(), "ERROR 1396") { return nil, buserr.New(constant.ErrUserIsExist) } return nil, err } grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", req.Name, req.Username, tmpPermission) + if req.Name == "*" { + grantStr = fmt.Sprintf("grant all privileges on *.* to '%s'@'%s'", mysql.Username, tmpPermission) + } if app.Version == "5.7.39" { grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password) } - if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil { + if err := excSQL(app.ContainerName, app.Password, grantStr); err != nil { return nil, err } @@ -161,10 +163,10 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error return err } - if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", db.Username, db.Permission)); err != nil && !req.ForceDelete { + if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", db.Username, db.Permission)); err != nil && !req.ForceDelete { return err } - if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil && !req.ForceDelete { + if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil && !req.ForceDelete { return err } global.LOG.Info("execute delete database sql successful, now start to drop uploads and records") @@ -292,7 +294,10 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error { if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", mysql.Username, info.Value, mysql.Password)); err != nil { return err } - grantStr := fmt.Sprintf("grant all privileges on %s.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value) + grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value) + if mysql.Name == "*" { + grantStr = fmt.Sprintf("grant all privileges on *.* to '%s'@'%s'", mysql.Username, info.Value) + } if app.Version == "5.7.39" { grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysql.Password) } @@ -339,7 +344,7 @@ func (u *MysqlService) UpdateVariables(updatas []dto.MysqlVariablesUpdate) error var files []string path := fmt.Sprintf("%s/mysql/%s/conf/my.cnf", constant.AppInstallDir, app.Name) - lineBytes, err := ioutil.ReadFile(path) + lineBytes, err := os.ReadFile(path) if err != nil { return err } @@ -509,6 +514,21 @@ func excuteSql(containerName, password, command string) error { return nil } +func excSQL(containerName, password, command string) error { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + cmd := exec.CommandContext(ctx, "docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command) + err := cmd.Run() + if ctx.Err() == context.DeadlineExceeded { + return buserr.WithDetail(constant.ErrExecTimeOut, containerName, nil) + } + if err != nil { + stdStr := strings.ReplaceAll(err.Error(), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "") + return errors.New(stdStr) + } + return nil +} + func updateMyCnf(oldFiles []string, group string, param string, value interface{}) []string { isOn := false hasGroup := false diff --git a/backend/app/service/database_redis.go b/backend/app/service/database_redis.go index f51abc660..18b13a9e5 100644 --- a/backend/app/service/database_redis.go +++ b/backend/app/service/database_redis.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -215,7 +214,7 @@ type redisConfig struct { func confSet(redisName string, changeConf []redisConfig) error { path := fmt.Sprintf("%s/redis/%s/conf/redis.conf", constant.AppInstallDir, redisName) - lineBytes, err := ioutil.ReadFile(path) + lineBytes, err := os.ReadFile(path) if err != nil { return err } diff --git a/backend/app/service/docker.go b/backend/app/service/docker.go index 4fd1fd7c2..55efbffa5 100644 --- a/backend/app/service/docker.go +++ b/backend/app/service/docker.go @@ -4,7 +4,6 @@ import ( "bufio" "context" "encoding/json" - "io/ioutil" "os" "path" "strings" @@ -35,6 +34,7 @@ type daemonJsonItem struct { Mirrors []string `json:"registry-mirrors"` Registries []string `json:"insecure-registries"` LiveRestore bool `json:"live-restore"` + IPTables bool `json:"iptables"` ExecOpts []string `json:"exec-opts"` } @@ -49,55 +49,60 @@ func (u *DockerService) LoadDockerStatus() string { } func (u *DockerService) LoadDockerConf() *dto.DaemonJsonConf { - status := constant.StatusRunning + var data dto.DaemonJsonConf + data.IPTables = true + data.Status = constant.StatusRunning stdout, err := cmd.Exec("systemctl is-active docker") if string(stdout) != "active\n" || err != nil { - status = constant.Stopped + data.Status = constant.Stopped } - version := "-" + data.IsSwarm = false + stdout2, _ := cmd.Exec("docker info | grep Swarm") + if string(stdout2) == " Swarm: active\n" { + data.IsSwarm = true + } + data.Version = "-" client, err := docker.NewDockerClient() if err == nil { ctx := context.Background() itemVersion, err := client.ServerVersion(ctx) if err == nil { - version = itemVersion.Version + data.Version = itemVersion.Version } } if _, err := os.Stat(constant.DaemonJsonPath); err != nil { - return &dto.DaemonJsonConf{Status: status, Version: version} + return &data } - file, err := ioutil.ReadFile(constant.DaemonJsonPath) + file, err := os.ReadFile(constant.DaemonJsonPath) if err != nil { - return &dto.DaemonJsonConf{Status: status, Version: version} + return &data } var conf daemonJsonItem deamonMap := make(map[string]interface{}) if err := json.Unmarshal(file, &deamonMap); err != nil { - return &dto.DaemonJsonConf{Status: status, Version: version} + return &data } arr, err := json.Marshal(deamonMap) if err != nil { - return &dto.DaemonJsonConf{Status: status, Version: version} + return &data } if err := json.Unmarshal(arr, &conf); err != nil { - return &dto.DaemonJsonConf{Status: status, Version: version} + return &data } - driver := "cgroupfs" + if _, ok := deamonMap["iptables"]; !ok { + conf.IPTables = true + } + data.CgroupDriver = "cgroupfs" for _, opt := range conf.ExecOpts { if strings.HasPrefix(opt, "native.cgroupdriver=") { - driver = strings.ReplaceAll(opt, "native.cgroupdriver=", "") + data.CgroupDriver = strings.ReplaceAll(opt, "native.cgroupdriver=", "") break } } - data := dto.DaemonJsonConf{ - Status: status, - Version: version, - Mirrors: conf.Mirrors, - Registries: conf.Registries, - LiveRestore: conf.LiveRestore, - CgroupDriver: driver, - } - + data.Mirrors = conf.Mirrors + data.Registries = conf.Registries + data.IPTables = conf.IPTables + data.LiveRestore = conf.LiveRestore return &data } @@ -109,7 +114,7 @@ func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error { _, _ = os.Create(constant.DaemonJsonPath) } - file, err := ioutil.ReadFile(constant.DaemonJsonPath) + file, err := os.ReadFile(constant.DaemonJsonPath) if err != nil { return err } @@ -131,6 +136,11 @@ func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error { } else { deamonMap["live-restore"] = req.LiveRestore } + if req.IPTables { + delete(deamonMap, "iptables") + } else { + deamonMap["iptables"] = false + } if opts, ok := deamonMap["exec-opts"]; ok { if optsValue, isArray := opts.([]interface{}); isArray { for i := 0; i < len(optsValue); i++ { @@ -147,11 +157,15 @@ func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error { deamonMap["exec-opts"] = []string{"native.cgroupdriver=systemd"} } } + if len(deamonMap) == 0 { + _ = os.Remove(constant.DaemonJsonPath) + return nil + } newJson, err := json.MarshalIndent(deamonMap, "", "\t") if err != nil { return err } - if err := ioutil.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { + if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { return err } @@ -163,6 +177,16 @@ func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error { } func (u *DockerService) UpdateConfByFile(req dto.DaemonJsonUpdateByFile) error { + if len(req.File) == 0 { + _ = os.Remove(constant.DaemonJsonPath) + return nil + } + if _, err := os.Stat(constant.DaemonJsonPath); err != nil && os.IsNotExist(err) { + if err = os.MkdirAll(path.Dir(constant.DaemonJsonPath), os.ModePerm); err != nil { + return err + } + _, _ = os.Create(constant.DaemonJsonPath) + } file, err := os.OpenFile(constant.DaemonJsonPath, os.O_WRONLY|os.O_TRUNC, 0640) if err != nil { return err diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index b022f8731..64f3bf25e 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -2,78 +2,38 @@ package service import "github.com/1Panel-dev/1Panel/backend/app/repo" -type ServiceGroup struct { - AuthService - DashboardService - - AppService - AppInstallService - - ContainerService - ImageService - ImageRepoService - ComposeTemplateService - DockerService - - MysqlService - RedisService - - CronjobService - - HostService - GroupService - CommandService - FileService - - SettingService - BackupService - - WebsiteGroupService - WebsiteService - WebsiteDnsAccountService - WebsiteSSLService - WebsiteAcmeAccountService - - NginxService - - LogService - SnapshotService - UpgradeService -} - -var ServiceGroupApp = new(ServiceGroup) - var ( - commonRepo = repo.RepoGroupApp.CommonRepo + commonRepo = repo.NewCommonRepo() - appRepo = repo.RepoGroupApp.AppRepo - appTagRepo = repo.RepoGroupApp.AppTagRepo - appDetailRepo = repo.RepoGroupApp.AppDetailRepo - tagRepo = repo.RepoGroupApp.TagRepo - appInstallRepo = repo.RepoGroupApp.AppInstallRepo - appInstallResourceRepo = repo.RepoGroupApp.AppInstallResourceRpo + appRepo = repo.NewIAppRepo() + appTagRepo = repo.NewIAppTagRepo() + appDetailRepo = repo.NewIAppDetailRepo() + tagRepo = repo.NewITagRepo() + appInstallRepo = repo.NewIAppInstallRepo() + appInstallResourceRepo = repo.NewIAppInstallResourceRpo() - mysqlRepo = repo.RepoGroupApp.MysqlRepo + mysqlRepo = repo.NewIMysqlRepo() - imageRepoRepo = repo.RepoGroupApp.ImageRepoRepo - composeRepo = repo.RepoGroupApp.ComposeTemplateRepo + imageRepoRepo = repo.NewIImageRepoRepo() + composeRepo = repo.NewIComposeTemplateRepo() - cronjobRepo = repo.RepoGroupApp.CronjobRepo + cronjobRepo = repo.NewICronjobRepo() - hostRepo = repo.RepoGroupApp.HostRepo - groupRepo = repo.RepoGroupApp.GroupRepo - commandRepo = repo.RepoGroupApp.CommandRepo + hostRepo = repo.NewIHostRepo() + groupRepo = repo.NewIGroupRepo() + commandRepo = repo.NewICommandRepo() - settingRepo = repo.RepoGroupApp.SettingRepo - backupRepo = repo.RepoGroupApp.BackupRepo + settingRepo = repo.NewISettingRepo() + backupRepo = repo.NewIBackupRepo() websiteRepo = repo.NewIWebsiteRepo() - websiteGroupRepo = repo.RepoGroupApp.WebsiteGroupRepo - websiteDomainRepo = repo.RepoGroupApp.WebsiteDomainRepo - websiteDnsRepo = repo.RepoGroupApp.WebsiteDnsAccountRepo + websiteDomainRepo = repo.NewIWebsiteDomainRepo() + websiteDnsRepo = repo.NewIWebsiteDnsAccountRepo() websiteSSLRepo = repo.NewISSLRepo() websiteAcmeRepo = repo.NewIAcmeAccountRepo() - logRepo = repo.RepoGroupApp.LogRepo + logRepo = repo.NewILogRepo() snapshotRepo = repo.NewISnapshotRepo() + + runtimeRepo = repo.NewIRunTimeRepo() ) diff --git a/backend/app/service/file.go b/backend/app/service/file.go index 218f3ee57..e26fe8e23 100644 --- a/backend/app/service/file.go +++ b/backend/app/service/file.go @@ -22,7 +22,30 @@ import ( type FileService struct { } -func (f FileService) GetFileList(op request.FileOption) (response.FileInfo, error) { +type IFileService interface { + GetFileList(op request.FileOption) (response.FileInfo, error) + SearchUploadWithPage(req request.SearchUploadWithPage) (int64, interface{}, error) + GetFileTree(op request.FileOption) ([]response.FileTree, error) + Create(op request.FileCreate) error + Delete(op request.FileDelete) error + BatchDelete(op request.FileBatchDelete) error + ChangeMode(op request.FileCreate) error + Compress(c request.FileCompress) error + DeCompress(c request.FileDeCompress) error + GetContent(op request.FileOption) (response.FileInfo, error) + SaveContent(edit request.FileEdit) error + FileDownload(d request.FileDownload) (string, error) + DirSize(req request.DirSizeReq) (response.DirSizeRes, error) + ChangeName(req request.FileRename) error + Wget(w request.FileWget) (string, error) + MvFile(m request.FileMove) error +} + +func NewIFileService() IFileService { + return &FileService{} +} + +func (f *FileService) GetFileList(op request.FileOption) (response.FileInfo, error) { var fileInfo response.FileInfo if _, err := os.Stat(op.Path); err != nil && os.IsNotExist(err) { return fileInfo, nil @@ -35,7 +58,7 @@ func (f FileService) GetFileList(op request.FileOption) (response.FileInfo, erro return fileInfo, nil } -func (f FileService) SearchUploadWithPage(req request.SearchUploadWithPage) (int64, interface{}, error) { +func (f *FileService) SearchUploadWithPage(req request.SearchUploadWithPage) (int64, interface{}, error) { var ( files []response.UploadInfo backData []response.UploadInfo @@ -65,7 +88,7 @@ func (f FileService) SearchUploadWithPage(req request.SearchUploadWithPage) (int return int64(total), backData, nil } -func (f FileService) GetFileTree(op request.FileOption) ([]response.FileTree, error) { +func (f *FileService) GetFileTree(op request.FileOption) ([]response.FileTree, error) { var treeArray []response.FileTree info, err := files.NewFileInfo(op.FileOption) if err != nil { @@ -88,7 +111,7 @@ func (f FileService) GetFileTree(op request.FileOption) ([]response.FileTree, er return append(treeArray, node), nil } -func (f FileService) Create(op request.FileCreate) error { +func (f *FileService) Create(op request.FileCreate) error { fo := files.NewFileOp() if fo.Stat(op.Path) { return buserr.New(constant.ErrFileIsExit) @@ -107,7 +130,7 @@ func (f FileService) Create(op request.FileCreate) error { } } -func (f FileService) Delete(op request.FileDelete) error { +func (f *FileService) Delete(op request.FileDelete) error { fo := files.NewFileOp() if op.IsDir { return fo.DeleteDir(op.Path) @@ -116,7 +139,7 @@ func (f FileService) Delete(op request.FileDelete) error { } } -func (f FileService) BatchDelete(op request.FileBatchDelete) error { +func (f *FileService) BatchDelete(op request.FileBatchDelete) error { fo := files.NewFileOp() if op.IsDir { for _, file := range op.Paths { @@ -134,12 +157,12 @@ func (f FileService) BatchDelete(op request.FileBatchDelete) error { return nil } -func (f FileService) ChangeMode(op request.FileCreate) error { +func (f *FileService) ChangeMode(op request.FileCreate) error { fo := files.NewFileOp() return fo.Chmod(op.Path, fs.FileMode(op.Mode)) } -func (f FileService) Compress(c request.FileCompress) error { +func (f *FileService) Compress(c request.FileCompress) error { fo := files.NewFileOp() if !c.Replace && fo.Stat(filepath.Join(c.Dst, c.Name)) { return buserr.New(constant.ErrFileIsExit) @@ -147,12 +170,12 @@ func (f FileService) Compress(c request.FileCompress) error { return fo.Compress(c.Files, c.Dst, c.Name, files.CompressType(c.Type)) } -func (f FileService) DeCompress(c request.FileDeCompress) error { +func (f *FileService) DeCompress(c request.FileDeCompress) error { fo := files.NewFileOp() return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type)) } -func (f FileService) GetContent(op request.FileOption) (response.FileInfo, error) { +func (f *FileService) GetContent(op request.FileOption) (response.FileInfo, error) { info, err := files.NewFileInfo(op.FileOption) if err != nil { return response.FileInfo{}, err @@ -160,7 +183,7 @@ func (f FileService) GetContent(op request.FileOption) (response.FileInfo, error return response.FileInfo{FileInfo: *info}, nil } -func (f FileService) SaveContent(edit request.FileEdit) error { +func (f *FileService) SaveContent(edit request.FileEdit) error { info, err := files.NewFileInfo(files.FileOption{ Path: edit.Path, Expand: false, @@ -173,18 +196,18 @@ func (f FileService) SaveContent(edit request.FileEdit) error { return fo.WriteFile(edit.Path, strings.NewReader(edit.Content), info.FileMode) } -func (f FileService) ChangeName(req request.FileRename) error { +func (f *FileService) ChangeName(req request.FileRename) error { fo := files.NewFileOp() return fo.Rename(req.OldName, req.NewName) } -func (f FileService) Wget(w request.FileWget) (string, error) { +func (f *FileService) Wget(w request.FileWget) (string, error) { fo := files.NewFileOp() key := "file-wget-" + common.GetUuid() return key, fo.DownloadFileWithProcess(w.Url, filepath.Join(w.Path, w.Name), key) } -func (f FileService) MvFile(m request.FileMove) error { +func (f *FileService) MvFile(m request.FileMove) error { fo := files.NewFileOp() if !fo.Stat(m.NewPath) { return buserr.New(constant.ErrPathNotFound) @@ -217,7 +240,7 @@ func (f FileService) MvFile(m request.FileMove) error { return nil } -func (f FileService) FileDownload(d request.FileDownload) (string, error) { +func (f *FileService) FileDownload(d request.FileDownload) (string, error) { filePath := d.Paths[0] if d.Compress { tempPath := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().UnixNano())) @@ -233,7 +256,7 @@ func (f FileService) FileDownload(d request.FileDownload) (string, error) { return filePath, nil } -func (f FileService) DirSize(req request.DirSizeReq) (response.DirSizeRes, error) { +func (f *FileService) DirSize(req request.DirSizeReq) (response.DirSizeRes, error) { fo := files.NewFileOp() size, err := fo.GetDirSize(req.Path) if err != nil { diff --git a/backend/app/service/firewall.go b/backend/app/service/firewall.go new file mode 100644 index 000000000..d5cb6be12 --- /dev/null +++ b/backend/app/service/firewall.go @@ -0,0 +1,448 @@ +package service + +import ( + "fmt" + "os" + "strconv" + "strings" + + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/backend/utils/common" + "github.com/1Panel-dev/1Panel/backend/utils/firewall" + fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client" + "github.com/jinzhu/copier" +) + +const confPath = "/etc/sysctl.conf" + +type FirewallService struct{} + +type IFirewallService interface { + LoadBaseInfo() (dto.FirewallBaseInfo, error) + SearchWithPage(search dto.RuleSearch) (int64, interface{}, error) + OperateFirewall(operation string) error + OperatePortRule(req dto.PortRuleOperate, reload bool) error + OperateAddressRule(req dto.AddrRuleOperate, reload bool) error + UpdatePortRule(req dto.PortRuleUpdate) error + UpdateAddrRule(req dto.AddrRuleUpdate) error + BacthOperateRule(req dto.BatchRuleOperate) error +} + +func NewIFirewallService() IFirewallService { + return &FirewallService{} +} + +func (u *FirewallService) LoadBaseInfo() (dto.FirewallBaseInfo, error) { + var baseInfo dto.FirewallBaseInfo + baseInfo.PingStatus = u.pingStatus() + baseInfo.Status = "not running" + baseInfo.Version = "-" + baseInfo.Name = "-" + client, err := firewall.NewFirewallClient() + if err != nil { + if err.Error() == "no such type" { + return baseInfo, nil + } + return baseInfo, err + } + baseInfo.Name = client.Name() + baseInfo.Status, err = client.Status() + if err != nil { + return baseInfo, err + } + if baseInfo.Status == "not running" { + return baseInfo, err + } + baseInfo.Version, err = client.Version() + if err != nil { + return baseInfo, err + } + return baseInfo, nil +} + +func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}, error) { + var ( + datas []fireClient.FireInfo + backDatas []fireClient.FireInfo + ) + client, err := firewall.NewFirewallClient() + if err != nil { + return 0, nil, err + } + if req.Type == "port" { + ports, err := client.ListPort() + if err != nil { + return 0, nil, err + } + if len(req.Info) != 0 { + for _, port := range ports { + if strings.Contains(port.Port, req.Info) { + datas = append(datas, port) + } + } + } else { + datas = ports + } + } else { + addrs, err := client.ListAddress() + if err != nil { + return 0, nil, err + } + if len(req.Info) != 0 { + for _, addr := range addrs { + if strings.Contains(addr.Address, req.Info) { + datas = append(datas, addr) + } + } + } else { + datas = addrs + } + } + total, start, end := len(datas), (req.Page-1)*req.PageSize, req.Page*req.PageSize + if start > total { + backDatas = make([]fireClient.FireInfo, 0) + } else { + if end >= total { + end = total + } + backDatas = datas[start:end] + } + + if req.Type == "port" { + apps := u.loadPortByApp() + for i := 0; i < len(backDatas); i++ { + port, _ := strconv.Atoi(backDatas[i].Port) + backDatas[i].IsUsed = common.ScanPort(port) + if backDatas[i].Protocol == "udp" { + backDatas[i].IsUsed = common.ScanUDPPort(port) + continue + } + for _, app := range apps { + if app.HttpPort == backDatas[i].Port || app.HttpsPort == backDatas[i].Port { + backDatas[i].APPName = app.AppName + break + } + } + } + } + + return int64(total), backDatas, nil +} + +func (u *FirewallService) OperateFirewall(operation string) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + switch operation { + case "start": + if err := client.Start(); err != nil { + return err + } + if err := u.addPortsBeforeStart(client); err != nil { + _ = client.Stop() + return err + } + _, _ = cmd.Exec("systemctl restart docker") + return nil + case "stop": + if err := client.Stop(); err != nil { + return err + } + _, _ = cmd.Exec("systemctl restart docker") + return nil + case "disablePing": + return u.updatePingStatus("0") + case "enablePing": + return u.updatePingStatus("1") + } + return fmt.Errorf("not support such operation: %s", operation) +} + +func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if client.Name() == "ufw" { + req.Port = strings.ReplaceAll(req.Port, "-", ":") + if req.Operation == "remove" && req.Protocol == "tcp/udp" { + req.Protocol = "" + return u.operatePort(client, req) + } + } + if req.Protocol == "tcp/udp" { + if client.Name() == "firewalld" && strings.Contains(req.Port, ",") { + ports := strings.Split(req.Port, ",") + for _, port := range ports { + if len(port) == 0 { + continue + } + req.Port = port + req.Protocol = "tcp" + if err := u.operatePort(client, req); err != nil { + return err + } + req.Protocol = "udp" + if err := u.operatePort(client, req); err != nil { + return err + } + } + } else { + req.Protocol = "tcp" + if err := u.operatePort(client, req); err != nil { + return err + } + req.Protocol = "udp" + if err := u.operatePort(client, req); err != nil { + return err + } + } + } else { + if strings.Contains(req.Port, ",") { + ports := strings.Split(req.Port, ",") + for _, port := range ports { + req.Port = port + if err := u.operatePort(client, req); err != nil { + return err + } + } + } else { + if err := u.operatePort(client, req); err != nil { + return err + } + } + } + if reload { + return client.Reload() + } + return nil +} + +func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload bool) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + + var fireInfo fireClient.FireInfo + if err := copier.Copy(&fireInfo, &req); err != nil { + return err + } + + addressList := strings.Split(req.Address, ",") + for _, addr := range addressList { + if len(addr) == 0 { + continue + } + fireInfo.Address = addr + if err := client.RichRules(fireInfo, req.Operation); err != nil { + return err + } + } + if reload { + return client.Reload() + } + return nil +} + +func (u *FirewallService) UpdatePortRule(req dto.PortRuleUpdate) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if err := u.OperatePortRule(req.OldRule, false); err != nil { + return err + } + if err := u.OperatePortRule(req.NewRule, false); err != nil { + return err + } + return client.Reload() +} + +func (u *FirewallService) UpdateAddrRule(req dto.AddrRuleUpdate) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if err := u.OperateAddressRule(req.OldRule, false); err != nil { + return err + } + if err := u.OperateAddressRule(req.NewRule, false); err != nil { + return err + } + return client.Reload() +} + +func (u *FirewallService) BacthOperateRule(req dto.BatchRuleOperate) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if req.Type == "port" { + for _, rule := range req.Rules { + if err := u.OperatePortRule(rule, false); err != nil { + return err + } + } + return client.Reload() + } + for _, rule := range req.Rules { + itemRule := dto.AddrRuleOperate{Operation: rule.Operation, Address: rule.Address, Strategy: rule.Strategy} + if err := u.OperateAddressRule(itemRule, false); err != nil { + return err + } + } + return client.Reload() +} + +func OperateFirewallPort(oldPorts, newPorts []int) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + for _, port := range newPorts { + + if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + return err + } + } + for _, port := range oldPorts { + if err := client.Port(fireClient.FireInfo{Port: strconv.Itoa(port), Protocol: "tcp", Strategy: "accept"}, "remove"); err != nil { + return err + } + } + return client.Reload() +} + +func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.PortRuleOperate) error { + var fireInfo fireClient.FireInfo + if err := copier.Copy(&fireInfo, &req); err != nil { + return err + } + + if client.Name() == "ufw" { + if len(fireInfo.Address) != 0 && fireInfo.Address != "Anywhere" { + return client.RichRules(fireInfo, req.Operation) + } + return client.Port(fireInfo, req.Operation) + } + + if len(fireInfo.Address) != 0 || fireInfo.Strategy == "drop" { + return client.RichRules(fireInfo, req.Operation) + } + return client.Port(fireInfo, req.Operation) +} + +type portOfApp struct { + AppName string + HttpPort string + HttpsPort string +} + +func (u *FirewallService) loadPortByApp() []portOfApp { + var datas []portOfApp + apps, err := appInstallRepo.ListBy() + if err != nil { + return datas + } + for i := 0; i < len(apps); i++ { + datas = append(datas, portOfApp{ + AppName: apps[i].App.Key, + HttpPort: strconv.Itoa(apps[i].HttpPort), + HttpsPort: strconv.Itoa(apps[i].HttpsPort), + }) + } + systemPort, err := settingRepo.Get(settingRepo.WithByKey("ServerPort")) + if err != nil { + return datas + } + datas = append(datas, portOfApp{AppName: "1panel", HttpPort: systemPort.Value}) + + return datas +} + +func (u *FirewallService) pingStatus() string { + if _, err := os.Stat("/etc/sysctl.conf"); err != nil { + return constant.StatusNone + } + commond := "cat /etc/sysctl.conf | grep net/ipv4/icmp_echo_ignore_all= " + if cmd.HasNoPasswordSudo() { + commond = "sudo cat /etc/sysctl.conf | grep net/ipv4/icmp_echo_ignore_all= " + } + stdout, _ := cmd.Exec(commond) + if stdout == "net/ipv4/icmp_echo_ignore_all=1\n" { + return constant.StatusEnable + } + return constant.StatusDisable +} + +func (u *FirewallService) updatePingStatus(enabel string) error { + lineBytes, err := os.ReadFile(confPath) + if err != nil { + return err + } + files := strings.Split(string(lineBytes), "\n") + var newFiles []string + hasLine := false + for _, line := range files { + if strings.Contains(line, "net/ipv4/icmp_echo_ignore_all") || strings.HasPrefix(line, "net/ipv4/icmp_echo_ignore_all") { + newFiles = append(newFiles, "net/ipv4/icmp_echo_ignore_all="+enabel) + hasLine = true + } else { + newFiles = append(newFiles, line) + } + } + if !hasLine { + newFiles = append(newFiles, "net/ipv4/icmp_echo_ignore_all="+enabel) + } + file, err := os.OpenFile(confPath, os.O_WRONLY|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer file.Close() + _, err = file.WriteString(strings.Join(newFiles, "\n")) + if err != nil { + return err + } + + commond := "sysctl -p" + if cmd.HasNoPasswordSudo() { + commond = "sudo sysctl -p" + } + stdout, err := cmd.Exec(commond) + if err != nil { + return fmt.Errorf("update ping status failed, err: %v", stdout) + } + + return nil +} + +func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) error { + serverPort, err := settingRepo.Get(settingRepo.WithByKey("ServerPort")) + if err != nil { + return err + } + if err := client.Port(fireClient.FireInfo{Port: serverPort.Value, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + return err + } + if err := client.Port(fireClient.FireInfo{Port: "22", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + return err + } + if err := client.Port(fireClient.FireInfo{Port: "80", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + return err + } + if err := client.Port(fireClient.FireInfo{Port: "443", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + return err + } + apps := u.loadPortByApp() + for _, app := range apps { + if err := client.Port(fireClient.FireInfo{Port: app.HttpPort, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + return err + } + } + + return client.Reload() +} diff --git a/backend/app/service/group.go b/backend/app/service/group.go index 9247eb161..11c5f87c4 100644 --- a/backend/app/service/group.go +++ b/backend/app/service/group.go @@ -22,7 +22,7 @@ func NewIGroupService() IGroupService { } func (u *GroupService) List(req dto.GroupSearch) ([]dto.GroupInfo, error) { - groups, err := groupRepo.GetList(commonRepo.WithByType(req.Type)) + groups, err := groupRepo.GetList(commonRepo.WithByType(req.Type), commonRepo.WithOrderBy("is_default desc"), commonRepo.WithOrderBy("created_at desc")) if err != nil { return nil, constant.ErrRecordNotFound } @@ -38,7 +38,7 @@ func (u *GroupService) List(req dto.GroupSearch) ([]dto.GroupInfo, error) { } func (u *GroupService) Create(req dto.GroupCreate) error { - group, _ := groupRepo.Get(commonRepo.WithByName(req.Name), commonRepo.WithByName(req.Name)) + group, _ := groupRepo.Get(commonRepo.WithByName(req.Name), commonRepo.WithByType(req.Type)) if group.ID != 0 { return constant.ErrRecordExist } @@ -58,7 +58,7 @@ func (u *GroupService) Delete(id uint) error { } switch group.Type { case "website": - websites, _ := websiteRepo.GetBy(commonRepo.WithByGroupID(id)) + websites, _ := websiteRepo.GetBy(websiteRepo.WithGroupID(id)) if len(websites) > 0 { return buserr.New(constant.ErrGroupIsUsed) } @@ -73,7 +73,7 @@ func (u *GroupService) Delete(id uint) error { func (u *GroupService) Update(req dto.GroupUpdate) error { if req.IsDefault { - if err := groupRepo.CancelDefault(); err != nil { + if err := groupRepo.CancelDefault(req.Type); err != nil { return err } } diff --git a/backend/app/service/host.go b/backend/app/service/host.go index 6ad56e7be..d928f16ba 100644 --- a/backend/app/service/host.go +++ b/backend/app/service/host.go @@ -1,6 +1,7 @@ package service import ( + "encoding/base64" "fmt" "github.com/1Panel-dev/1Panel/backend/app/dto" @@ -15,6 +16,7 @@ type HostService struct{} type IHostService interface { TestLocalConn(id uint) bool + TestByInfo(req dto.HostConnTest) bool GetHostInfo(id uint) (*model.Host, error) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) SearchWithPage(search dto.SearchHostWithPage) (int64, interface{}, error) @@ -27,6 +29,46 @@ func NewIHostService() IHostService { return &HostService{} } +func (u *HostService) TestByInfo(req dto.HostConnTest) bool { + if req.AuthMode == "password" && len(req.Password) != 0 { + password, err := base64.StdEncoding.DecodeString(req.Password) + if err != nil { + return false + } + req.Password = string(password) + } + if req.AuthMode == "key" && len(req.PrivateKey) != 0 { + privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey) + if err != nil { + return false + } + req.PrivateKey = string(privateKey) + } + if len(req.Password) == 0 && len(req.PrivateKey) == 0 { + host, err := hostRepo.Get(hostRepo.WithByAddr(req.Addr)) + if err != nil { + return false + } + req.Password = host.Password + req.AuthMode = host.AuthMode + req.PrivateKey = host.PrivateKey + req.PassPhrase = host.PassPhrase + } + + var connInfo ssh.ConnInfo + _ = copier.Copy(&connInfo, &req) + connInfo.PrivateKey = []byte(req.PrivateKey) + if len(req.PassPhrase) != 0 { + connInfo.PassPhrase = []byte(req.PassPhrase) + } + client, err := connInfo.NewClient() + if err != nil { + return false + } + defer client.Close() + return true +} + func (u *HostService) TestLocalConn(id uint) bool { var ( host model.Host @@ -47,6 +89,10 @@ func (u *HostService) TestLocalConn(id uint) bool { if err := copier.Copy(&connInfo, &host); err != nil { return false } + connInfo.PrivateKey = []byte(host.PrivateKey) + if len(host.PassPhrase) != 0 { + connInfo.PassPhrase = []byte(host.PassPhrase) + } client, err := connInfo.NewClient() if err != nil { return false @@ -77,6 +123,11 @@ func (u *HostService) SearchWithPage(search dto.SearchHostWithPage) (int64, inte } group, _ := groupRepo.Get(commonRepo.WithByID(host.GroupID)) item.GroupBelong = group.Name + if !item.RememberPassword { + item.Password = "" + item.PrivateKey = "" + item.PassPhrase = "" + } dtoHosts = append(dtoHosts, item) } return total, dtoHosts, err @@ -144,6 +195,8 @@ func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) { upMap["auth_mode"] = req.AuthMode upMap["password"] = req.Password upMap["private_key"] = req.PrivateKey + upMap["pass_phrase"] = req.PassPhrase + upMap["remember_password"] = req.RememberPassword upMap["description"] = req.Description if err := hostRepo.Update(sameHostID, upMap); err != nil { return nil, err diff --git a/backend/app/service/image.go b/backend/app/service/image.go index 2618beeb4..58c5c198e 100644 --- a/backend/app/service/image.go +++ b/backend/app/service/image.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path" "strings" @@ -34,6 +33,7 @@ type IImageService interface { ImageSave(req dto.ImageSave) error ImagePush(req dto.ImagePush) (string, error) ImageRemove(req dto.BatchDelete) error + ImageTag(req dto.ImageTag) error } func NewIImageService() IImageService { @@ -54,8 +54,8 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error) return 0, nil, err } if len(req.Info) != 0 { - lenth, count := len(list), 0 - for count < lenth { + length, count := len(list), 0 + for count < length { hasTag := false for _, tag := range list[count].RepoTags { if strings.Contains(tag, req.Info) { @@ -65,7 +65,7 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error) } if !hasTag { list = append(list[:count], list[(count+1):]...) - lenth-- + length-- } else { count++ } @@ -122,6 +122,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { if err != nil { return "", err } + fileName := "Dockerfile" if req.From == "edit" { dir := fmt.Sprintf("%s/docker/build/%s", constant.DataDir, strings.ReplaceAll(req.Name, ":", "_")) if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { @@ -141,7 +142,8 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { write.Flush() req.Dockerfile = dir } else { - req.Dockerfile = strings.ReplaceAll(req.Dockerfile, "/Dockerfile", "") + fileName = path.Base(req.Dockerfile) + req.Dockerfile = path.Dir(req.Dockerfile) } tar, err := archive.TarWithOptions(req.Dockerfile+"/", &archive.TarOptions{}) if err != nil { @@ -149,7 +151,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { } opts := types.ImageBuildOptions{ - Dockerfile: "Dockerfile", + Dockerfile: fileName, Tags: []string{req.Name}, Remove: true, Labels: stringsToMap(req.Tags), @@ -171,7 +173,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { return } defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { global.LOG.Errorf("build image %s failed, err: %v", req.Name, err) _, _ = file.WriteString(fmt.Sprintf("build image %s failed, err: %v", req.Name, err)) @@ -179,14 +181,14 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) { return } - if strings.Contains(string(body), "error") && strings.Contains(string(body), "failed:") { + if strings.Contains(string(body), "errorDetail") || strings.Contains(string(body), "error:") { global.LOG.Errorf("build image %s failed", req.Name) _, _ = file.Write(body) _, _ = file.WriteString("image build failed!") return } global.LOG.Infof("build image %s successful!", req.Name) - _, _ = io.Copy(file, res.Body) + _, _ = file.Write(body) _, _ = file.WriteString("image build successful!") }() @@ -272,7 +274,7 @@ func (u *ImageService) ImageLoad(req dto.ImageLoad) error { if err != nil { return err } - content, err := ioutil.ReadAll(res.Body) + content, err := io.ReadAll(res.Body) if err != nil { return err } diff --git a/backend/app/service/image_repo.go b/backend/app/service/image_repo.go index 693c3fd3f..2714821c2 100644 --- a/backend/app/service/image_repo.go +++ b/backend/app/service/image_repo.go @@ -3,7 +3,6 @@ package service import ( "context" "encoding/json" - "io/ioutil" "os" "path" "strings" @@ -190,7 +189,7 @@ func (u *ImageRepoService) handleRegistries(newHost, delHost, handle string) err } deamonMap := make(map[string]interface{}) - file, err := ioutil.ReadFile(constant.DaemonJsonPath) + file, err := os.ReadFile(constant.DaemonJsonPath) if err != nil { return err } @@ -226,7 +225,7 @@ func (u *ImageRepoService) handleRegistries(newHost, delHost, handle string) err if err != nil { return err } - if err := ioutil.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { + if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { return err } return nil diff --git a/backend/app/service/nginx.go b/backend/app/service/nginx.go index b7bb10257..046c5a949 100644 --- a/backend/app/service/nginx.go +++ b/backend/app/service/nginx.go @@ -1,15 +1,16 @@ package service import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "io/ioutil" + "io" "net/http" "os" "path" "strings" "time" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/app/dto/response" + "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/utils/files" @@ -18,6 +19,18 @@ import ( type NginxService struct { } +type INginxService interface { + GetNginxConfig() (response.FileInfo, error) + GetConfigByScope(req request.NginxScopeReq) ([]response.NginxParam, error) + UpdateConfigByScope(req request.NginxConfigUpdate) error + GetStatus() (response.NginxStatus, error) + UpdateConfigFile(req request.NginxConfigFileUpdate) error +} + +func NewINginxService() INginxService { + return &NginxService{} +} + func (n NginxService) GetNginxConfig() (response.FileInfo, error) { nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) if err != nil { @@ -55,7 +68,7 @@ func (n NginxService) GetStatus() (response.NginxStatus, error) { if err != nil { return response.NginxStatus{}, err } - content, err := ioutil.ReadAll(res.Body) + content, err := io.ReadAll(res.Body) if err != nil { return response.NginxStatus{}, err } diff --git a/backend/app/service/nginx_utils.go b/backend/app/service/nginx_utils.go index 51156f6d4..9eb87d466 100644 --- a/backend/app/service/nginx_utils.go +++ b/backend/app/service/nginx_utils.go @@ -16,6 +16,7 @@ import ( "os" "path" "strings" + "time" ) func getNginxFull(website *model.Website) (dto.NginxFull, error) { @@ -191,7 +192,7 @@ func opNginx(containerName, operate string) error { if operate == constant.NginxCheck { nginxCmd = fmt.Sprintf("docker exec -i %s %s", containerName, "nginx -t") } - if out, err := cmd.Exec(nginxCmd); err != nil { + if out, err := cmd.ExecWithTimeOut(nginxCmd, 2*time.Second); err != nil { return errors.New(out) } return nil diff --git a/backend/app/service/runtime.go b/backend/app/service/runtime.go new file mode 100644 index 000000000..8e3e427bc --- /dev/null +++ b/backend/app/service/runtime.go @@ -0,0 +1,276 @@ +package service + +import ( + "context" + "encoding/json" + "fmt" + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/app/dto/response" + "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/app/repo" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/global" + "github.com/1Panel-dev/1Panel/backend/utils/docker" + "github.com/1Panel-dev/1Panel/backend/utils/files" + "github.com/subosito/gotenv" + "path" + "path/filepath" + "strings" + "time" +) + +type RuntimeService struct { +} + +type IRuntimeService interface { + Page(req request.RuntimeSearch) (int64, []response.RuntimeRes, error) + Create(create request.RuntimeCreate) error + Delete(id uint) error + Update(req request.RuntimeUpdate) error + Get(id uint) (res *response.RuntimeRes, err error) +} + +func NewRuntimeService() IRuntimeService { + return &RuntimeService{} +} + +func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) { + exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithName(create.Name)) + if exist != nil { + return buserr.New(constant.ErrNameIsExist) + } + if create.Resource == constant.ResourceLocal { + runtime := &model.Runtime{ + Name: create.Name, + Resource: create.Resource, + Type: create.Type, + Version: create.Version, + Status: constant.RuntimeNormal, + } + return runtimeRepo.Create(context.Background(), runtime) + } + exist, _ = runtimeRepo.GetFirst(runtimeRepo.WithImage(create.Image)) + if exist != nil { + return buserr.New(constant.ErrImageExist) + } + appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(create.AppDetailID)) + if err != nil { + return err + } + app, err := appRepo.GetFirst(commonRepo.WithByID(appDetail.AppId)) + if err != nil { + return err + } + fileOp := files.NewFileOp() + buildDir := path.Join(constant.AppResourceDir, app.Key, "versions", appDetail.Version, "build") + if !fileOp.Stat(buildDir) { + return buserr.New(constant.ErrDirNotFound) + } + runtimeDir := path.Join(constant.RuntimeDir, create.Type) + tempDir := filepath.Join(runtimeDir, fmt.Sprintf("%d", time.Now().UnixNano())) + if err = fileOp.CopyDir(buildDir, tempDir); err != nil { + return + } + oldDir := path.Join(tempDir, "build") + newNameDir := path.Join(runtimeDir, create.Name) + defer func() { + if err != nil { + _ = fileOp.DeleteDir(newNameDir) + } + }() + if oldDir != newNameDir { + if err = fileOp.Rename(oldDir, newNameDir); err != nil { + return + } + if err = fileOp.DeleteDir(tempDir); err != nil { + return + } + } + composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Params) + if err != nil { + return + } + composeService, err := getComposeService(create.Name, newNameDir, composeContent, envContent, false) + if err != nil { + return + } + runtime := &model.Runtime{ + Name: create.Name, + DockerCompose: string(composeContent), + Env: string(envContent), + AppDetailID: create.AppDetailID, + Type: create.Type, + Image: create.Image, + Resource: create.Resource, + Status: constant.RuntimeBuildIng, + Version: create.Version, + Params: string(forms), + } + if err = runtimeRepo.Create(context.Background(), runtime); err != nil { + return + } + go buildRuntime(runtime, composeService, "") + return +} + +func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeRes, error) { + var ( + opts []repo.DBOption + res []response.RuntimeRes + ) + if req.Name != "" { + opts = append(opts, commonRepo.WithLikeName(req.Name)) + } + if req.Status != "" { + opts = append(opts, runtimeRepo.WithStatus(req.Status)) + } + total, runtimes, err := runtimeRepo.Page(req.Page, req.PageSize, opts...) + if err != nil { + return 0, nil, err + } + for _, runtime := range runtimes { + res = append(res, response.RuntimeRes{ + Runtime: runtime, + }) + } + return total, res, nil +} + +func (r *RuntimeService) Delete(id uint) error { + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id)) + if err != nil { + return err + } + website, _ := websiteRepo.GetFirst(websiteRepo.WithRuntimeID(id)) + if website.ID > 0 { + return buserr.New(constant.ErrDelWithWebsite) + } + if runtime.Resource == constant.ResourceAppstore { + client, err := docker.NewClient() + if err != nil { + return err + } + imageID, err := client.GetImageIDByName(runtime.Image) + if err != nil { + return err + } + if imageID != "" { + if err := client.DeleteImage(imageID); err != nil { + global.LOG.Errorf("delete image id [%s] error %v", imageID, err) + } + } + runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) + if err := files.NewFileOp().DeleteDir(runtimeDir); err != nil { + return err + } + } + return runtimeRepo.DeleteBy(commonRepo.WithByID(id)) +} + +func (r *RuntimeService) Get(id uint) (*response.RuntimeRes, error) { + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id)) + if err != nil { + return nil, err + } + res := &response.RuntimeRes{} + res.Runtime = *runtime + if runtime.Resource == constant.ResourceLocal { + return res, nil + } + appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID)) + if err != nil { + return nil, err + } + res.AppID = appDetail.AppId + var ( + appForm dto.AppForm + appParams []response.AppParam + ) + if err := json.Unmarshal([]byte(runtime.Params), &appForm); err != nil { + return nil, err + } + envs, err := gotenv.Unmarshal(runtime.Env) + if err != nil { + return nil, err + } + for _, form := range appForm.FormFields { + if v, ok := envs[form.EnvKey]; ok { + appParam := response.AppParam{ + Edit: false, + Key: form.EnvKey, + Rule: form.Rule, + Type: form.Type, + Required: form.Required, + } + if form.Edit { + appParam.Edit = true + } + appParam.LabelZh = form.LabelZh + appParam.LabelEn = form.LabelEn + appParam.Multiple = form.Multiple + appParam.Value = v + if form.Type == "select" { + if form.Multiple { + if v == "" { + appParam.Value = []string{} + } else { + appParam.Value = strings.Split(v, ",") + } + } else { + for _, fv := range form.Values { + if fv.Value == v { + appParam.ShowValue = fv.Label + break + } + } + } + appParam.Values = form.Values + } + appParams = append(appParams, appParam) + } + } + res.AppParams = appParams + return res, nil +} + +func (r *RuntimeService) Update(req request.RuntimeUpdate) error { + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + oldImage := runtime.Image + if runtime.Resource == constant.ResourceLocal { + runtime.Version = req.Version + return runtimeRepo.Save(runtime) + } + exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID)) + if exist != nil { + return buserr.New(constant.ErrImageExist) + } + runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) + composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Params) + if err != nil { + return err + } + composeService, err := getComposeService(runtime.Name, runtimeDir, composeContent, envContent, false) + if err != nil { + return err + } + runtime.Image = req.Image + runtime.Env = string(envContent) + runtime.DockerCompose = string(composeContent) + runtime.Status = constant.RuntimeBuildIng + _ = runtimeRepo.Save(runtime) + client, err := docker.NewClient() + if err != nil { + return err + } + imageID, err := client.GetImageIDByName(oldImage) + if err != nil { + return err + } + go buildRuntime(runtime, composeService, imageID) + return nil +} diff --git a/backend/app/service/runtime_utils.go b/backend/app/service/runtime_utils.go new file mode 100644 index 000000000..2b5bfca7a --- /dev/null +++ b/backend/app/service/runtime_utils.go @@ -0,0 +1,107 @@ +package service + +import ( + "fmt" + "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/global" + "github.com/1Panel-dev/1Panel/backend/utils/docker" + "github.com/1Panel-dev/1Panel/backend/utils/files" + "github.com/docker/cli/cli/command" + "github.com/subosito/gotenv" + "os" + "path" + "strings" +) + +func buildRuntime(runtime *model.Runtime, service *docker.ComposeService, oldImageID string) { + err := service.ComposeBuild() + if err != nil { + runtime.Status = constant.RuntimeError + runtime.Message = buserr.New(constant.ErrImageBuildErr).Error() + ":" + err.Error() + } else { + runtime.Status = constant.RuntimeNormal + if oldImageID != "" { + client, err := docker.NewClient() + if err == nil { + newImageID, err := client.GetImageIDByName(runtime.Image) + if err == nil && newImageID != oldImageID { + global.LOG.Infof("delete imageID [%s] ", oldImageID) + if err := client.DeleteImage(oldImageID); err != nil { + global.LOG.Errorf("delete imageID [%s] error %v", oldImageID, err) + } else { + global.LOG.Infof("delete old image success") + } + } + } else { + global.LOG.Errorf("delete imageID [%s] error %v", oldImageID, err) + } + } + } + _ = runtimeRepo.Save(runtime) +} + +func handleParams(image, runtimeType, runtimeDir string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) { + fileOp := files.NewFileOp() + composeContent, err = fileOp.GetContent(path.Join(runtimeDir, "docker-compose.yml")) + if err != nil { + return + } + env, err := gotenv.Read(path.Join(runtimeDir, ".env")) + if err != nil { + return + } + forms, err = fileOp.GetContent(path.Join(runtimeDir, "config.json")) + if err != nil { + return + } + params["IMAGE_NAME"] = image + if runtimeType == constant.RuntimePHP { + if extends, ok := params["PHP_EXTENSIONS"]; ok { + if extendsArray, ok := extends.([]interface{}); ok { + strArray := make([]string, len(extendsArray)) + for i, v := range extendsArray { + strArray[i] = fmt.Sprintf("%v", v) + } + params["PHP_EXTENSIONS"] = strings.Join(strArray, ",") + } + } + } + newMap := make(map[string]string) + handleMap(params, newMap) + for k, v := range newMap { + env[k] = v + } + envStr, err := gotenv.Marshal(env) + if err != nil { + return + } + if err = gotenv.Write(env, path.Join(runtimeDir, ".env")); err != nil { + return + } + envContent = []byte(envStr) + return +} + +func getComposeService(name, runtimeDir string, composeFile, env []byte, skipNormalization bool) (*docker.ComposeService, error) { + project, err := docker.GetComposeProject(name, runtimeDir, composeFile, env, skipNormalization) + if err != nil { + return nil, err + } + logPath := path.Join(runtimeDir, "build.log") + fileOp := files.NewFileOp() + if fileOp.Stat(logPath) { + _ = fileOp.DeleteFile(logPath) + } + file, err := os.Create(logPath) + if err != nil { + return nil, err + } + composeService, err := docker.NewComposeService(command.WithOutputStream(file)) + if err != nil { + return nil, err + } + composeService.SetProject(project) + return composeService, nil +} diff --git a/backend/app/service/setting.go b/backend/app/service/setting.go index 93ef774d5..454023805 100644 --- a/backend/app/service/setting.go +++ b/backend/app/service/setting.go @@ -70,7 +70,14 @@ func (u *SettingService) UpdatePort(port uint) error { if common.ScanPort(int(port)) { return buserr.WithDetail(constant.ErrPortInUsed, port, nil) } - + serverPort, err := settingRepo.Get(settingRepo.WithByKey("ServerPort")) + if err != nil { + return err + } + portValue, _ := strconv.Atoi(serverPort.Value) + if err := OperateFirewallPort([]int{portValue}, []int{int(port)}); err != nil { + global.LOG.Errorf("set system firewall ports failed, err: %v", err) + } if err := settingRepo.Update("ServerPort", strconv.Itoa(int(port))); err != nil { return err } diff --git a/backend/app/service/snapshot.go b/backend/app/service/snapshot.go index 0654ebb9a..41e8523aa 100644 --- a/backend/app/service/snapshot.go +++ b/backend/app/service/snapshot.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "os" "strings" "time" @@ -66,6 +65,9 @@ func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error { if err != nil { return fmt.Errorf("incorrect snapshot name format of %s", snap) } + if strings.HasSuffix(snap, ".tar.gz") { + snap = strings.ReplaceAll(snap, ".tar.gz", "") + } itemSnap := model.Snapshot{ Name: snap, From: req.From, @@ -481,7 +483,7 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error { func (u *SnapshotService) saveJson(snapJson SnapshotJson, path string) error { remarkInfo, _ := json.MarshalIndent(snapJson, "", "\t") - if err := ioutil.WriteFile(fmt.Sprintf("%s/snapshot.json", path), remarkInfo, 0640); err != nil { + if err := os.WriteFile(fmt.Sprintf("%s/snapshot.json", path), remarkInfo, 0640); err != nil { return err } return nil @@ -790,7 +792,7 @@ func (u *SnapshotService) updateLiveRestore(enabled bool) error { if _, err := os.Stat(constant.DaemonJsonPath); err != nil { return fmt.Errorf("load docker daemon.json conf failed, err: %v", err) } - file, err := ioutil.ReadFile(constant.DaemonJsonPath) + file, err := os.ReadFile(constant.DaemonJsonPath) if err != nil { return err } @@ -806,7 +808,7 @@ func (u *SnapshotService) updateLiveRestore(enabled bool) error { if err != nil { return err } - if err := ioutil.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { + if err := os.WriteFile(constant.DaemonJsonPath, newJson, 0640); err != nil { return err } @@ -852,7 +854,7 @@ func (u *SnapshotService) handleTar(sourceDir, targetDir, name, exclusionRules s commands := fmt.Sprintf("tar --warning=no-file-changed -zcf %s %s -C %s .", targetDir+"/"+name, exStr, sourceDir) global.LOG.Debug(commands) - stdout, err := cmd.Exec(commands) + stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute) if err != nil { global.LOG.Errorf("do handle tar failed, stdout: %s, err: %v", stdout, err) return errors.New(stdout) @@ -869,7 +871,7 @@ func (u *SnapshotService) handleUnTar(sourceDir, targetDir string) error { commands := fmt.Sprintf("tar -zxf %s -C %s .", sourceDir, targetDir) global.LOG.Debug(commands) - stdout, err := cmd.Exec(commands) + stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute) if err != nil { global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err) return errors.New(stdout) diff --git a/backend/app/service/upgrade.go b/backend/app/service/upgrade.go index 49ed4b9d6..1e2264b4c 100644 --- a/backend/app/service/upgrade.go +++ b/backend/app/service/upgrade.go @@ -1,18 +1,20 @@ package service import ( + "encoding/json" + "errors" "fmt" - "io/ioutil" + "io" "net/http" "os" "runtime" - "strconv" "strings" "time" "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/files" ) @@ -20,6 +22,7 @@ type UpgradeService struct{} type IUpgradeService interface { Upgrade(req dto.Upgrade) error + LoadNotes(req dto.Upgrade) (string, error) SearchUpgrade() (*dto.UpgradeInfo, error) } @@ -34,36 +37,50 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) { return nil, err } - versionRes, err := http.Get(fmt.Sprintf("%s/%s/latest", global.CONF.System.RepoUrl, global.CONF.System.Mode)) + latestVersion, err := u.loadVersion(true, currentVersion.Value) if err != nil { + global.LOG.Infof("load latest version failed, err: %v", err) return nil, err } - defer versionRes.Body.Close() - version, err := ioutil.ReadAll(versionRes.Body) - if err != nil { + if !common.CompareVersion(string(latestVersion), currentVersion.Value) { return nil, err } - isNew, err := compareVersion(currentVersion.Value, string(version)) - if !isNew || err != nil { - return nil, err + upgrade.LatestVersion = latestVersion + if latestVersion[0:4] == currentVersion.Value[0:4] { + upgrade.NewVersion = "" + } else { + newerVersion, err := u.loadVersion(false, currentVersion.Value) + if err != nil { + global.LOG.Infof("load newer version failed, err: %v", err) + return nil, err + } + if newerVersion == currentVersion.Value { + upgrade.NewVersion = "" + } else { + upgrade.NewVersion = newerVersion + } } + itemVersion := upgrade.LatestVersion + if upgrade.NewVersion != "" { + itemVersion = upgrade.NewVersion + } + notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, itemVersion, itemVersion)) - upgrade.NewVersion = string(version) - - releaseNotes, err := http.Get(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, upgrade.NewVersion, upgrade.NewVersion)) if err != nil { - return nil, err + return nil, fmt.Errorf("load relase-notes of version %s failed, err: %v", latestVersion, err) } - defer releaseNotes.Body.Close() - release, err := ioutil.ReadAll(releaseNotes.Body) - if err != nil { - return nil, err - } - upgrade.ReleaseNote = string(release) - + upgrade.ReleaseNote = notes return &upgrade, nil } +func (u *UpgradeService) LoadNotes(req dto.Upgrade) (string, error) { + notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, req.Version, req.Version)) + if err != nil { + return "", fmt.Errorf("load relase-notes of version %s failed, err: %v", req.Version, err) + } + return notes, nil +} + func (u *UpgradeService) Upgrade(req dto.Upgrade) error { global.LOG.Info("start to upgrade now...") fileOp := files.NewFileOp() @@ -131,7 +148,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error { go writeLogs(req.Version) _ = settingRepo.Update("SystemVersion", req.Version) _ = settingRepo.Update("SystemStatus", "Free") - _, _ = cmd.Exec("systemctl daemon-reload && systemctl restart 1panel.service") + _, _ = cmd.ExecWithTimeOut("systemctl daemon-reload && systemctl restart 1panel.service", 1*time.Minute) }() return nil } @@ -174,45 +191,49 @@ func (u *UpgradeService) handleRollback(fileOp files.FileOp, originalDir string, if err := cpBinary(originalDir+"/1panel.service", "/etc/systemd/system/1panel.service"); err != nil { global.LOG.Errorf("rollback 1panel failed, err: %v", err) } - } -func compareVersion(version, newVersion string) (bool, error) { - if version == newVersion { - return false, nil +func (u *UpgradeService) loadVersion(isLatest bool, currentVersion string) (string, error) { + path := fmt.Sprintf("%s/%s/latest", global.CONF.System.RepoUrl, global.CONF.System.Mode) + if !isLatest { + path = fmt.Sprintf("%s/%s/latest.current", global.CONF.System.RepoUrl, global.CONF.System.Mode) } - if len(version) == 0 || len(newVersion) == 0 { - return false, fmt.Errorf("incorrect version or new version entered %v -- %v", version, newVersion) + latestVersionRes, err := http.Get(path) + if err != nil { + return "", err } - versions := strings.Split(strings.ReplaceAll(version, "v", ""), ".") - if len(versions) != 3 { - return false, fmt.Errorf("incorrect version input %v", version) + defer latestVersionRes.Body.Close() + version, err := io.ReadAll(latestVersionRes.Body) + if err != nil { + return "", err } - newVersions := strings.Split(strings.ReplaceAll(newVersion, "v", ""), ".") - if len(newVersions) != 3 { - return false, fmt.Errorf("incorrect newVersions input %v", version) + if isLatest { + return string(version), nil } - version1, _ := strconv.Atoi(versions[0]) - newVersion1, _ := strconv.Atoi(newVersions[0]) - if newVersion1 > version1 { - return true, nil - } else if newVersion1 == version1 { - version2, _ := strconv.Atoi(versions[1]) - newVersion2, _ := strconv.Atoi(newVersions[1]) - if newVersion2 > version2 { - return true, nil - } else if newVersion2 == version2 { - version3, _ := strconv.Atoi(versions[2]) - newVersion3, _ := strconv.Atoi(newVersions[2]) - if newVersion3 > version3 { - return true, nil - } else { - return false, nil - } - } else { - return false, nil - } - } else { - return false, nil + + versionMap := make(map[string]string) + if err := json.Unmarshal(version, &versionMap); err != nil { + return "", fmt.Errorf("load version map failed, err: %v", err) } + + if len(currentVersion) < 4 { + return "", fmt.Errorf("current version is error format: %s", currentVersion) + } + if version, ok := versionMap[currentVersion[0:4]]; ok { + return version, nil + } + return "", errors.New("load version failed in latest.current") +} + +func (u *UpgradeService) loadReleaseNotes(path string) (string, error) { + releaseNotes, err := http.Get(path) + if err != nil { + return "", err + } + defer releaseNotes.Body.Close() + release, err := io.ReadAll(releaseNotes.Body) + if err != nil { + return "", err + } + return string(release), nil } diff --git a/backend/app/service/website.go b/backend/app/service/website.go index fe6ea1d08..863247781 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -1,13 +1,21 @@ package service import ( + "bufio" + "bytes" "context" "crypto/x509" "encoding/pem" + "errors" "fmt" + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" + "gorm.io/gorm" "os" "path" "reflect" + "regexp" "strings" "time" @@ -21,8 +29,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/pkg/errors" - "gorm.io/gorm" ) type WebsiteService struct { @@ -31,18 +37,18 @@ type WebsiteService struct { type IWebsiteService interface { PageWebsite(req request.WebsiteSearch) (int64, []response.WebsiteDTO, error) GetWebsites() ([]response.WebsiteDTO, error) - CreateWebsite(ctx context.Context, create request.WebsiteCreate) error + CreateWebsite(create request.WebsiteCreate) error OpWebsite(req request.WebsiteOp) error GetWebsiteOptions() ([]string, error) UpdateWebsite(req request.WebsiteUpdate) error - DeleteWebsite(ctx context.Context, req request.WebsiteDelete) error + DeleteWebsite(req request.WebsiteDelete) error GetWebsite(id uint) (response.WebsiteDTO, error) CreateWebsiteDomain(create request.WebsiteDomainCreate) (model.WebsiteDomain, error) GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error) DeleteWebsiteDomain(domainId uint) error GetNginxConfigByScope(req request.NginxScopeReq) (*response.WebsiteNginxConfig, error) UpdateNginxConfigByScope(req request.NginxConfigUpdate) error - GetWebsiteNginxConfig(websiteId uint) (response.FileInfo, error) + GetWebsiteNginxConfig(websiteId uint, configType string) (response.FileInfo, error) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS, error) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteHTTPSOp) (response.WebsiteHTTPS, error) PreInstallCheck(req request.WebsiteInstallCheckReq) ([]response.WebsitePreInstallCheck, error) @@ -50,9 +56,17 @@ type IWebsiteService interface { UpdateWafConfig(req request.WebsiteWafUpdate) error UpdateNginxConfigFile(req request.WebsiteNginxUpdate) error OpWebsiteLog(req request.WebsiteLogReq) (*response.WebsiteLog, error) + ChangeDefaultServer(id uint) error + GetPHPConfig(id uint) (*response.PHPConfig, error) + UpdatePHPConfig(req request.WebsitePHPConfigUpdate) error + UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) error + GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error) + UpdateRewriteConfig(req request.NginxRewriteUpdate) error + UpdateSiteDir(req request.WebsiteUpdateDir) error + UpdateSitePermission(req request.WebsiteUpdateDirPermission) error } -func NewWebsiteService() IWebsiteService { +func NewIWebsiteService() IWebsiteService { return &WebsiteService{} } @@ -73,17 +87,28 @@ func (w WebsiteService) PageWebsite(req request.WebsiteSearch) (int64, []respons return 0, nil, err } for _, web := range websites { - var appName string - if web.Type == constant.Deployment { + var ( + appName string + runtimeName string + ) + switch web.Type { + case constant.Deployment: appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(web.AppInstallID)) if err != nil { return 0, nil, err } appName = appInstall.Name + case constant.Runtime: + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(web.RuntimeID)) + if err != nil { + return 0, nil, err + } + runtimeName = runtime.Name } websiteDTOs = append(websiteDTOs, response.WebsiteDTO{ - Website: web, - AppName: appName, + Website: web, + AppName: appName, + RuntimeName: runtimeName, }) } return total, websiteDTOs, nil @@ -103,7 +128,7 @@ func (w WebsiteService) GetWebsites() ([]response.WebsiteDTO, error) { return websiteDTOs, nil } -func (w WebsiteService) CreateWebsite(ctx context.Context, create request.WebsiteCreate) error { +func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) { if exist, _ := websiteRepo.GetBy(websiteRepo.WithDomain(create.PrimaryDomain)); len(exist) > 0 { return buserr.New(constant.ErrDomainIsExist) } @@ -122,50 +147,117 @@ func (w WebsiteService) CreateWebsite(ctx context.Context, create request.Websit Remark: create.Remark, Status: constant.WebRunning, ExpireDate: defaultDate, - AppInstallID: create.AppInstallID, WebsiteGroupID: create.WebsiteGroupID, Protocol: constant.ProtocolHTTP, Proxy: create.Proxy, + SiteDir: "/", AccessLog: true, ErrorLog: true, } - var appInstall *model.AppInstall + var ( + appInstall *model.AppInstall + runtime *model.Runtime + ) + + defer func() { + if err != nil { + if website.AppInstallID > 0 { + req := request.AppInstalledOperate{ + InstallId: website.AppInstallID, + Operate: constant.Delete, + ForceDelete: true, + } + if err := NewIAppInstalledService().Operate(req); err != nil { + global.LOG.Errorf(err.Error()) + } + } + } + }() + var proxy string + switch create.Type { case constant.Deployment: if create.AppType == constant.NewApp { - var req request.AppInstallCreate + var ( + req request.AppInstallCreate + install *model.AppInstall + ) req.Name = create.AppInstall.Name req.AppDetailId = create.AppInstall.AppDetailId req.Params = create.AppInstall.Params - install, err := ServiceGroupApp.Install(ctx, req) + tx, installCtx := getTxAndContext() + install, err = NewIAppService().Install(installCtx, req) if err != nil { + tx.Rollback() return err } - website.AppInstallID = install.ID + tx.Commit() appInstall = install + website.AppInstallID = install.ID + website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort) } else { - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(create.AppInstallID)) + var install model.AppInstall + install, err = appInstallRepo.GetFirst(commonRepo.WithByID(create.AppInstallID)) if err != nil { return err } appInstall = &install website.AppInstallID = appInstall.ID + website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort) + } + case constant.Runtime: + runtime, err = runtimeRepo.GetFirst(commonRepo.WithByID(create.RuntimeID)) + if err != nil { + return err + } + website.RuntimeID = runtime.ID + if runtime.Resource == constant.ResourceAppstore { + var ( + req request.AppInstallCreate + nginxInstall model.AppInstall + install *model.AppInstall + ) + reg, _ := regexp.Compile(`[^a-z0-9_-]+`) + req.Name = reg.ReplaceAllString(strings.ToLower(create.PrimaryDomain), "") + req.AppDetailId = create.AppInstall.AppDetailId + req.Params = create.AppInstall.Params + req.Params["IMAGE_NAME"] = runtime.Image + nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return err + } + req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www") + tx, installCtx := getTxAndContext() + install, err = NewIAppService().Install(installCtx, req) + if err != nil { + tx.Rollback() + return err + } + tx.Commit() + website.AppInstallID = install.ID + appInstall = install + website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort) + } else { + website.ProxyType = create.ProxyType + if website.ProxyType == constant.RuntimeProxyUnix { + proxy = fmt.Sprintf("unix:%s", path.Join("/www/sites", website.Alias, "php-pool", "php-fpm.sock")) + } + if website.ProxyType == constant.RuntimeProxyTcp { + proxy = fmt.Sprintf("127.0.0.1:%d", create.Port) + } + website.Proxy = proxy } } - if err := websiteRepo.Create(ctx, website); err != nil { - return err - } var domains []model.WebsiteDomain - domains = append(domains, model.WebsiteDomain{Domain: website.PrimaryDomain, WebsiteID: website.ID, Port: 80}) - + domains = append(domains, model.WebsiteDomain{Domain: website.PrimaryDomain, Port: 80}) otherDomainArray := strings.Split(create.OtherDomains, "\n") for _, domain := range otherDomainArray { if domain == "" { continue } - domainModel, err := getDomain(domain, website.ID) + domainModel, err := getDomain(domain) if err != nil { return err } @@ -174,12 +266,22 @@ func (w WebsiteService) CreateWebsite(ctx context.Context, create request.Websit } domains = append(domains, domainModel) } - if len(domains) > 0 { - if err := websiteDomainRepo.BatchCreate(ctx, domains); err != nil { - return err - } + if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil { + return err } - return configDefaultNginx(website, domains, appInstall) + tx, ctx := helper.GetTxAndContext() + defer tx.Rollback() + if err = websiteRepo.Create(ctx, website); err != nil { + return err + } + for i := range domains { + domains[i].WebsiteID = website.ID + } + if err = websiteDomainRepo.BatchCreate(ctx, domains); err != nil { + return err + } + tx.Commit() + return nil } func (w WebsiteService) OpWebsite(req request.WebsiteOp) error { @@ -243,7 +345,7 @@ func (w WebsiteService) GetWebsite(id uint) (response.WebsiteDTO, error) { return res, nil } -func (w WebsiteService) DeleteWebsite(ctx context.Context, req request.WebsiteDelete) error { +func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error { website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) if err != nil { return err @@ -252,44 +354,40 @@ func (w WebsiteService) DeleteWebsite(ctx context.Context, req request.WebsiteDe return err } - if req.DeleteApp { - websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(website.AppInstallID)) - if len(websites) > 1 { - return buserr.New(constant.ErrAppDelete) - } + if checkIsLinkApp(website) && req.DeleteApp { appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } if !reflect.DeepEqual(model.AppInstall{}, appInstall) { - if err := deleteAppInstall(ctx, appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete { + if err := deleteAppInstall(appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete { return err } } } - uploadDir := fmt.Sprintf("%s/1panel/uploads/website/%s", global.CONF.System.BaseDir, website.Alias) - if _, err := os.Stat(uploadDir); err == nil { - _ = os.RemoveAll(uploadDir) + tx, ctx := helper.GetTxAndContext() + defer tx.Rollback() + _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("website"), commonRepo.WithByName(website.Alias)) + if err := websiteRepo.DeleteBy(ctx, commonRepo.WithByID(req.ID)); err != nil { + return err } + if err := websiteDomainRepo.DeleteBy(ctx, websiteDomainRepo.WithWebsiteId(req.ID)); err != nil { + return err + } + tx.Commit() + if req.DeleteBackup { - localDir, err := loadLocalDir() - if err != nil && !req.ForceDelete { - return err - } + localDir, _ := loadLocalDir() backupDir := fmt.Sprintf("%s/website/%s", localDir, website.Alias) if _, err := os.Stat(backupDir); err == nil { _ = os.RemoveAll(backupDir) } global.LOG.Infof("delete website %s backups successful", website.Alias) } - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("website"), commonRepo.WithByName(website.Alias)) - - if err := websiteRepo.DeleteBy(ctx, commonRepo.WithByID(req.ID)); err != nil { - return err - } - if err := websiteDomainRepo.DeleteBy(ctx, websiteDomainRepo.WithWebsiteId(req.ID)); err != nil { - return err + uploadDir := fmt.Sprintf("%s/1panel/uploads/website/%s", global.CONF.System.BaseDir, website.Alias) + if _, err := os.Stat(uploadDir); err == nil { + _ = os.RemoveAll(uploadDir) } return nil } @@ -401,23 +499,36 @@ func (w WebsiteService) UpdateNginxConfigByScope(req request.NginxConfigUpdate) return updateNginxConfig(constant.NginxScopeServer, params, &website) } -func (w WebsiteService) GetWebsiteNginxConfig(websiteId uint) (response.FileInfo, error) { +func (w WebsiteService) GetWebsiteNginxConfig(websiteId uint, configType string) (response.FileInfo, error) { website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId)) if err != nil { return response.FileInfo{}, err } - - nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) - if err != nil { - return response.FileInfo{}, err + configPath := "" + switch configType { + case constant.AppOpenresty: + nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) + if err != nil { + return response.FileInfo{}, err + } + nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) + if err != nil { + return response.FileInfo{}, err + } + configPath = path.Join(nginxInstall.GetPath(), "conf", "conf.d", website.Alias+".conf") + case constant.ConfigFPM: + runtimeInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) + if err != nil { + return response.FileInfo{}, err + } + configPath = path.Join(runtimeInstall.GetPath(), "conf", "php-fpm.conf") + case constant.ConfigPHP: + runtimeInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) + if err != nil { + return response.FileInfo{}, err + } + configPath = path.Join(runtimeInstall.GetPath(), "conf", "php.ini") } - nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID)) - if err != nil { - return response.FileInfo{}, err - } - - configPath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "conf", "conf.d", website.Alias+".conf") - info, err := files.NewFileInfo(files.FileOption{ Path: configPath, Expand: true, @@ -764,3 +875,233 @@ func (w WebsiteService) ChangeDefaultServer(id uint) error { } return nil } + +func (w WebsiteService) GetPHPConfig(id uint) (*response.PHPConfig, error) { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(id)) + if err != nil { + return nil, err + } + appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) + if err != nil { + return nil, err + } + phpConfigPath := path.Join(appInstall.GetPath(), "conf", "php.ini") + fileOp := files.NewFileOp() + if !fileOp.Stat(phpConfigPath) { + return nil, buserr.WithDetail(constant.ErrFileCanNotRead, "php.ini", nil) + } + params := make(map[string]string) + configFile, err := fileOp.OpenFile(phpConfigPath) + if err != nil { + return nil, err + } + defer configFile.Close() + scanner := bufio.NewScanner(configFile) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, ";") { + continue + } + matches := regexp.MustCompile(`^\s*([a-z_]+)\s*=\s*(.*)$`).FindStringSubmatch(line) + if len(matches) == 3 { + params[matches[1]] = matches[2] + } + } + return &response.PHPConfig{Params: params}, nil +} + +func (w WebsiteService) UpdatePHPConfig(req request.WebsitePHPConfigUpdate) (err error) { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) + if err != nil { + return err + } + phpConfigPath := path.Join(appInstall.GetPath(), "conf", "php.ini") + fileOp := files.NewFileOp() + if !fileOp.Stat(phpConfigPath) { + return buserr.WithDetail(constant.ErrFileCanNotRead, "php.ini", nil) + } + configFile, err := fileOp.OpenFile(phpConfigPath) + if err != nil { + return err + } + defer configFile.Close() + + contentBytes, err := fileOp.GetContent(phpConfigPath) + content := string(contentBytes) + lines := strings.Split(content, "\n") + for i, line := range lines { + if strings.HasPrefix(line, ";") { + continue + } + for key, value := range req.Params { + pattern := "^" + regexp.QuoteMeta(key) + "\\s*=\\s*.*$" + if matched, _ := regexp.MatchString(pattern, line); matched { + lines[i] = key + " = " + value + } + } + } + updatedContent := strings.Join(lines, "\n") + if err := fileOp.WriteFile(phpConfigPath, strings.NewReader(updatedContent), 0755); err != nil { + return err + } + appInstallReq := request.AppInstalledOperate{ + InstallId: appInstall.ID, + Operate: constant.Restart, + } + if err = NewIAppInstalledService().Operate(appInstallReq); err != nil { + _ = fileOp.WriteFile(phpConfigPath, strings.NewReader(string(contentBytes)), 0755) + return err + } + return nil +} + +func (w WebsiteService) UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) error { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + if website.Type != constant.Runtime { + return nil + } + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) + if err != nil { + return err + } + if runtime.Resource != constant.ResourceAppstore { + return nil + } + runtimeInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) + if err != nil { + return err + } + configPath := "" + if req.Type == constant.ConfigFPM { + configPath = path.Join(runtimeInstall.GetPath(), "conf", "php-fpm.conf") + } else { + configPath = path.Join(runtimeInstall.GetPath(), "conf", "php.ini") + } + if err := files.NewFileOp().WriteFile(configPath, strings.NewReader(req.Content), 0755); err != nil { + return err + } + return nil +} + +func (w WebsiteService) UpdateRewriteConfig(req request.NginxRewriteUpdate) error { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) + if err != nil { + return err + } + nginxFull, err := getNginxFull(&website) + if err != nil { + return err + } + includePath := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.PrimaryDomain) + absolutePath := path.Join(nginxFull.Install.GetPath(), includePath) + fileOp := files.NewFileOp() + var oldRewriteContent []byte + if !fileOp.Stat(path.Dir(absolutePath)) { + if err := fileOp.CreateDir(path.Dir(absolutePath), 0755); err != nil { + return err + } + } + if !fileOp.Stat(absolutePath) { + if err := fileOp.CreateFile(absolutePath); err != nil { + return err + } + } else { + oldRewriteContent, err = fileOp.GetContent(absolutePath) + if err != nil { + return err + } + } + if err := fileOp.WriteFile(absolutePath, strings.NewReader(req.Content), 0755); err != nil { + return err + } + + if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{includePath}}}, &website); err != nil { + _ = fileOp.WriteFile(absolutePath, bytes.NewReader(oldRewriteContent), 0755) + return err + } + website.Rewrite = req.Name + return websiteRepo.Save(context.Background(), &website) +} + +func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error) { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID)) + if err != nil { + return nil, err + } + var contentByte []byte + if req.Name == "current" { + nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return nil, err + } + rewriteConfPath := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "rewrite", fmt.Sprintf("%s.conf", website.PrimaryDomain)) + fileOp := files.NewFileOp() + if fileOp.Stat(rewriteConfPath) { + contentByte, err = fileOp.GetContent(rewriteConfPath) + if err != nil { + return nil, err + } + } + } else { + rewriteFile := fmt.Sprintf("rewrite/%s.conf", strings.ToLower(req.Name)) + contentByte, err = nginx_conf.Rewrites.ReadFile(rewriteFile) + if err != nil { + return nil, err + } + } + return &response.NginxRewriteRes{ + Content: string(contentByte), + }, err +} + +func (w WebsiteService) UpdateSiteDir(req request.WebsiteUpdateDir) error { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + runDir := req.SiteDir + siteDir := path.Join("/www/sites", website.Alias, "index") + if req.SiteDir != "/" { + siteDir = fmt.Sprintf("%s/%s", siteDir, req.SiteDir) + } + if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "root", Params: []string{siteDir}}}, &website); err != nil { + return err + } + website.SiteDir = runDir + return websiteRepo.Save(context.Background(), &website) +} + +func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermission) error { + website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return err + } + absoluteIndexPath := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "index") + if website.SiteDir != "/" { + absoluteIndexPath = path.Join(absoluteIndexPath, website.SiteDir) + } + chownCmd := fmt.Sprintf("chown -R %s:%s %s", req.User, req.Group, absoluteIndexPath) + if cmd.HasNoPasswordSudo() { + chownCmd = fmt.Sprintf("sudo %s", chownCmd) + } + if out, err := cmd.ExecWithTimeOut(chownCmd, 1*time.Second); err != nil { + if out != "" { + return errors.New(out) + } + return err + } + website.User = req.User + website.Group = req.Group + return websiteRepo.Save(context.Background(), &website) +} diff --git a/backend/app/service/website_acme_account.go b/backend/app/service/website_acme_account.go index 85278254d..0b166c34d 100644 --- a/backend/app/service/website_acme_account.go +++ b/backend/app/service/website_acme_account.go @@ -13,6 +13,16 @@ import ( type WebsiteAcmeAccountService struct { } +type IWebsiteAcmeAccountService interface { + Page(search dto.PageInfo) (int64, []response.WebsiteAcmeAccountDTO, error) + Create(create request.WebsiteAcmeAccountCreate) (response.WebsiteAcmeAccountDTO, error) + Delete(id uint) error +} + +func NewIWebsiteAcmeAccountService() IWebsiteAcmeAccountService { + return &WebsiteAcmeAccountService{} +} + func (w WebsiteAcmeAccountService) Page(search dto.PageInfo) (int64, []response.WebsiteAcmeAccountDTO, error) { total, accounts, err := websiteAcmeRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) var accountDTOs []response.WebsiteAcmeAccountDTO diff --git a/backend/app/service/website_dns_account.go b/backend/app/service/website_dns_account.go index 45aca3e4e..2ab03a31f 100644 --- a/backend/app/service/website_dns_account.go +++ b/backend/app/service/website_dns_account.go @@ -13,6 +13,17 @@ import ( type WebsiteDnsAccountService struct { } +type IWebsiteDnsAccountService interface { + Page(search dto.PageInfo) (int64, []response.WebsiteDnsAccountDTO, error) + Create(create request.WebsiteDnsAccountCreate) (request.WebsiteDnsAccountCreate, error) + Update(update request.WebsiteDnsAccountUpdate) (request.WebsiteDnsAccountUpdate, error) + Delete(id uint) error +} + +func NewIWebsiteDnsAccountService() IWebsiteDnsAccountService { + return &WebsiteDnsAccountService{} +} + func (w WebsiteDnsAccountService) Page(search dto.PageInfo) (int64, []response.WebsiteDnsAccountDTO, error) { total, accounts, err := websiteDnsRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) var accountDTOs []response.WebsiteDnsAccountDTO diff --git a/backend/app/service/website_group.go b/backend/app/service/website_group.go deleted file mode 100644 index ba1143717..000000000 --- a/backend/app/service/website_group.go +++ /dev/null @@ -1,61 +0,0 @@ -package service - -import ( - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" -) - -type WebsiteGroupService struct { -} - -func (w WebsiteGroupService) CreateGroup(create request.WebsiteGroupCreate) error { - groups, _ := websiteGroupRepo.GetBy(commonRepo.WithByName(create.Name)) - if len(groups) > 0 { - return buserr.New(constant.ErrNameIsExist) - } - return websiteGroupRepo.Create(&model.WebsiteGroup{ - Name: create.Name, - }) -} - -func (w WebsiteGroupService) GetGroups() ([]model.WebsiteGroup, error) { - return websiteGroupRepo.GetBy() -} - -func (w WebsiteGroupService) UpdateGroup(update request.WebsiteGroupUpdate) error { - if update.Default { - if err := websiteGroupRepo.CancelDefault(); err != nil { - return err - } - return websiteGroupRepo.Save(&model.WebsiteGroup{ - BaseModel: model.BaseModel{ - ID: update.ID, - }, - Name: update.Name, - Default: true, - }) - } else { - exists, _ := websiteGroupRepo.GetBy(commonRepo.WithByName(update.Name)) - for _, exist := range exists { - if exist.ID != update.ID { - return buserr.New(constant.ErrNameIsExist) - } - } - return websiteGroupRepo.Save(&model.WebsiteGroup{ - BaseModel: model.BaseModel{ - ID: update.ID, - }, - Name: update.Name, - }) - } -} - -func (w WebsiteGroupService) DeleteGroup(id uint) error { - websites, _ := websiteRepo.GetBy(websiteRepo.WithGroupID(id)) - if len(websites) > 0 { - return buserr.New(constant.ErrGroupIsUsed) - } - return websiteGroupRepo.DeleteBy(commonRepo.WithByID(id)) -} diff --git a/backend/app/service/website_ssl.go b/backend/app/service/website_ssl.go index 576d5c5d9..2be4ec514 100644 --- a/backend/app/service/website_ssl.go +++ b/backend/app/service/website_ssl.go @@ -27,6 +27,7 @@ type IWebsiteSSLService interface { GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) Delete(id uint) error + Update(update request.WebsiteSSLUpdate) error } func NewIWebsiteSSLService() IWebsiteSSLService { @@ -82,6 +83,8 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs return res, err } + var websiteSSL model.WebsiteSSL + switch create.Provider { case constant.DNSAccount: dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(create.DnsAccountID)) @@ -91,6 +94,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs if err := client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization); err != nil { return res, err } + websiteSSL.AutoRenew = create.AutoRenew case constant.Http: appInstall, err := getAppInstallByKey(constant.AppOpenresty) if err != nil { @@ -99,6 +103,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs if err := client.UseHTTP(path.Join(constant.AppInstallDir, constant.AppOpenresty, appInstall.Name, "root")); err != nil { return res, err } + websiteSSL.AutoRenew = create.AutoRenew case constant.DnsManual: if err := client.UseManualDns(); err != nil { return res, err @@ -114,7 +119,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs if err != nil { return res, err } - var websiteSSL model.WebsiteSSL + websiteSSL.DnsAccountID = create.DnsAccountID websiteSSL.AcmeAccountID = acmeAccount.ID websiteSSL.Provider = create.Provider @@ -258,3 +263,12 @@ func (w WebsiteSSLService) Delete(id uint) error { } return websiteSSLRepo.DeleteBy(commonRepo.WithByID(id)) } + +func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error { + websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(update.ID)) + if err != nil { + return err + } + websiteSSL.AutoRenew = update.AutoRenew + return websiteSSLRepo.Save(websiteSSL) +} diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go index 08a8b3d27..e581b4139 100644 --- a/backend/app/service/website_utils.go +++ b/backend/app/service/website_utils.go @@ -2,6 +2,7 @@ package service import ( "fmt" + "github.com/1Panel-dev/1Panel/backend/utils/cmd" "path" "strconv" "strings" @@ -20,10 +21,8 @@ import ( "gorm.io/gorm" ) -func getDomain(domainStr string, websiteID uint) (model.WebsiteDomain, error) { - domain := model.WebsiteDomain{ - WebsiteID: websiteID, - } +func getDomain(domainStr string) (model.WebsiteDomain, error) { + domain := model.WebsiteDomain{} domainArray := strings.Split(domainStr, ":") if len(domainArray) == 1 { domain.Domain = domainArray[0] @@ -43,15 +42,26 @@ func getDomain(domainStr string, websiteID uint) (model.WebsiteDomain, error) { return model.WebsiteDomain{}, nil } -func createStaticHtml(website *model.Website) error { +func createIndexFile(website *model.Website, runtime *model.Runtime) error { nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) if err != nil { return err } indexFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias, "index") - indexPath := path.Join(indexFolder, "index.html") - indexContent := string(nginx_conf.Index) + indexPath := "" + indexContent := "" + switch website.Type { + case constant.Static: + indexPath = path.Join(indexFolder, "index.html") + indexContent = string(nginx_conf.Index) + case constant.Runtime: + if runtime.Type == constant.RuntimePHP { + indexPath = path.Join(indexFolder, "index.php") + indexContent = string(nginx_conf.IndexPHP) + } + } + fileOp := files.NewFileOp() if !fileOp.Stat(indexFolder) { if err := fileOp.CreateDir(indexFolder, 0755); err != nil { @@ -63,13 +73,18 @@ func createStaticHtml(website *model.Website) error { return err } } + if website.Type == constant.Runtime && runtime.Resource == constant.ResourceAppstore { + if err := chownRootDir(indexFolder); err != nil { + return err + } + } if err := fileOp.WriteFile(indexPath, strings.NewReader(indexContent), 0755); err != nil { return err } return nil } -func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website) error { +func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website, runtime *model.Runtime) error { nginxFolder := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name) siteFolder := path.Join(nginxFolder, "www", "sites", website.Alias) fileOp := files.NewFileOp() @@ -86,14 +101,25 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website) if err := fileOp.CreateFile(path.Join(siteFolder, "log", "error.log")); err != nil { return err } - if err := fileOp.CreateDir(path.Join(siteFolder, "index"), 0755); err != nil { + if err := fileOp.CreateDir(path.Join(siteFolder, "index"), 0775); err != nil { return err } if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), 0755); err != nil { return err } - if website.Type == constant.Static { - if err := createStaticHtml(website); err != nil { + if website.Type == constant.Runtime { + if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal { + phpPoolDir := path.Join(siteFolder, "php-pool") + if err := fileOp.CreateDir(phpPoolDir, 0755); err != nil { + return err + } + if err := fileOp.CreateFile(path.Join(phpPoolDir, "php-fpm.sock")); err != nil { + return err + } + } + } + if website.Type == constant.Static || website.Type == constant.Runtime { + if err := createIndexFile(website, runtime); err != nil { return err } } @@ -101,12 +127,12 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website) return fileOp.CopyDir(path.Join(nginxFolder, "www", "common", "waf", "rules"), path.Join(siteFolder, "waf")) } -func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall) error { +func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error { nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) if err != nil { return err } - if err := createWebsiteFolder(nginxInstall, website); err != nil { + if err := createWebsiteFolder(nginxInstall, website, runtime); err != nil { return err } @@ -134,15 +160,32 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a server.UpdateDirective("set", []string{"$RulePath", path.Join(siteFolder, "waf", "rules")}) server.UpdateDirective("set", []string{"$logdir", path.Join(siteFolder, "log")}) + rootIndex := path.Join("/www/sites", website.Alias, "index") switch website.Type { case constant.Deployment: proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort) server.UpdateRootProxy([]string{proxy}) case constant.Static: - server.UpdateRoot(path.Join("/www/sites", website.Alias, "index")) - server.UpdateRootLocation() + server.UpdateRoot(rootIndex) + //server.UpdateRootLocation() case constant.Proxy: server.UpdateRootProxy([]string{website.Proxy}) + case constant.Runtime: + if runtime.Resource == constant.ResourceLocal { + switch runtime.Type { + case constant.RuntimePHP: + server.UpdateRoot(rootIndex) + localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php") + server.UpdatePHPProxy([]string{website.Proxy}, localPath) + } + } + if runtime.Resource == constant.ResourceAppstore { + switch runtime.Type { + case constant.RuntimePHP: + server.UpdateRoot(rootIndex) + server.UpdatePHPProxy([]string{website.Proxy}, "") + } + } } config.FilePath = configPath @@ -410,8 +453,11 @@ func opWebsite(website *model.Website, operate string) error { } server := servers[0] if operate == constant.StopWeb { - if website.Type != constant.Static { - server.RemoveDirective("location", []string{"/"}) + if website.Type == constant.Deployment || website.Type == constant.Static || website.Type == constant.Proxy { + server.RemoveDirective("location", []string{"", "/"}) + } + if website.Type == constant.Runtime { + server.RemoveDirective("location", []string{"~", "[^/]\\.php(/|$)"}) } server.UpdateRoot("/usr/share/nginx/html/stop") website.Status = constant.WebStopped @@ -432,6 +478,14 @@ func opWebsite(website *model.Website, operate string) error { case constant.Proxy: server.RemoveDirective("root", nil) server.UpdateRootProxy([]string{website.Proxy}) + case constant.Runtime: + rootIndex := path.Join("/www/sites", website.Alias, "index") + server.UpdateRoot(rootIndex) + localPath := "" + if website.ProxyType == constant.RuntimeProxyUnix { + localPath = path.Join(nginxInstall.Install.GetPath(), rootIndex, "index.php") + } + server.UpdatePHPProxy([]string{website.Proxy}, localPath) } website.Status = constant.WebRunning now := time.Now() @@ -446,3 +500,22 @@ func opWebsite(website *model.Website, operate string) error { } return nginxCheckAndReload(nginxInstall.SiteConfig.OldContent, config.FilePath, nginxInstall.Install.ContainerName) } + +func checkIsLinkApp(website model.Website) bool { + if website.Type == constant.Deployment { + return true + } + if website.Type == constant.Runtime { + runtime, _ := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID)) + return runtime.Resource == constant.ResourceAppstore + } + return false +} + +func chownRootDir(path string) error { + _, err := cmd.ExecWithTimeOut(fmt.Sprintf("chown -R 1000:1000 %s", path), 1*time.Second) + if err != nil { + return err + } + return nil +} diff --git a/backend/constant/app.go b/backend/constant/app.go index 526a0afb4..9ef2e59d9 100644 --- a/backend/constant/app.go +++ b/backend/constant/app.go @@ -16,6 +16,9 @@ const ( AppOpenresty = "openresty" AppMysql = "mysql" AppRedis = "redis" + + AppResourceLocal = "local" + AppResourceRemote = "remote" ) type AppOperate string diff --git a/backend/constant/backup.go b/backend/constant/backup.go index d2a688620..f2c74c9f4 100644 --- a/backend/constant/backup.go +++ b/backend/constant/backup.go @@ -8,4 +8,6 @@ const ( OSS = "OSS" Sftp = "SFTP" MinIo = "MINIO" + Cos = "COS" + Kodo = "KODO" ) diff --git a/backend/constant/dir.go b/backend/constant/dir.go index d9024992e..89615524c 100644 --- a/backend/constant/dir.go +++ b/backend/constant/dir.go @@ -7,8 +7,11 @@ import ( ) var ( - DataDir = global.CONF.System.DataDir - ResourceDir = path.Join(DataDir, "resource") - AppResourceDir = path.Join(ResourceDir, "apps") - AppInstallDir = path.Join(DataDir, "apps") + DataDir = global.CONF.System.DataDir + ResourceDir = path.Join(DataDir, "resource") + AppResourceDir = path.Join(ResourceDir, "apps") + AppInstallDir = path.Join(DataDir, "apps") + LocalAppResourceDir = path.Join(ResourceDir, "localApps") + LocalAppInstallDir = path.Join(DataDir, "localApps") + RuntimeDir = path.Join(DataDir, "runtime") ) diff --git a/backend/constant/errs.go b/backend/constant/errs.go index 2f82cc94e..de3736d02 100644 --- a/backend/constant/errs.go +++ b/backend/constant/errs.go @@ -50,18 +50,20 @@ var ( // app var ( - ErrPortInUsed = "ErrPortInUsed" - ErrAppLimit = "ErrAppLimit" - ErrAppRequired = "ErrAppRequired" - ErrFileCanNotRead = "ErrFileCanNotRead" - ErrFileToLarge = "ErrFileToLarge" - ErrNotInstall = "ErrNotInstall" - ErrPortInOtherApp = "ErrPortInOtherApp" - ErrDbUserNotValid = "ErrDbUserNotValid" - ErrUpdateBuWebsite = "ErrUpdateBuWebsite" + ErrPortInUsed = "ErrPortInUsed" + ErrAppLimit = "ErrAppLimit" + ErrAppRequired = "ErrAppRequired" + ErrFileCanNotRead = "ErrFileCanNotRead" + ErrFileToLarge = "ErrFileToLarge" + ErrNotInstall = "ErrNotInstall" + ErrPortInOtherApp = "ErrPortInOtherApp" + ErrDbUserNotValid = "ErrDbUserNotValid" + ErrUpdateBuWebsite = "ErrUpdateBuWebsite" + Err1PanelNetworkFailed = "Err1PanelNetworkFailed" + ErrCmdTimeout = "ErrCmdTimeout" ) -//website +// website var ( ErrDomainIsExist = "ErrDomainIsExist" ErrAliasIsExist = "ErrAliasIsExist" @@ -69,7 +71,7 @@ var ( ErrGroupIsUsed = "ErrGroupIsUsed" ) -//ssl +// ssl var ( ErrSSLCannotDelete = "ErrSSLCannotDelete" ErrAccountCannotDelete = "ErrAccountCannotDelete" @@ -77,27 +79,42 @@ var ( ErrEmailIsExist = "ErrEmailIsExist" ) -//file +// file var ( ErrPathNotFound = "ErrPathNotFound" ErrMovePathFailed = "ErrMovePathFailed" ErrLinkPathNotFound = "ErrLinkPathNotFound" ErrFileIsExit = "ErrFileIsExit" + ErrFileUpload = "ErrFileUpload" ) -//mysql +// mysql var ( ErrUserIsExist = "ErrUserIsExist" ErrDatabaseIsExist = "ErrDatabaseIsExist" + ErrExecTimeOut = "ErrExecTimeOut" ) -//redis +// redis var ( ErrTypeOfRedis = "ErrTypeOfRedis" ) -//container +// container var ( ErrInUsed = "ErrInUsed" ErrObjectInUsed = "ErrObjectInUsed" ) + +// runtime +var ( + ErrDirNotFound = "ErrDirNotFound" + ErrFileNotExist = "ErrFileNotExist" + ErrImageBuildErr = "ErrImageBuildErr" + ErrImageExist = "ErrImageExist" + ErrDelWithWebsite = "ErrDelWithWebsite" +) + +var ( + ErrBackupInUsed = "ErrBackupInUsed" +) diff --git a/backend/constant/runtime.go b/backend/constant/runtime.go new file mode 100644 index 000000000..e854c8648 --- /dev/null +++ b/backend/constant/runtime.go @@ -0,0 +1,15 @@ +package constant + +const ( + ResourceLocal = "local" + ResourceAppstore = "appstore" + + RuntimeNormal = "normal" + RuntimeError = "error" + RuntimeBuildIng = "building" + + RuntimePHP = "php" + + RuntimeProxyUnix = "unix" + RuntimeProxyTcp = "tcp" +) diff --git a/backend/constant/session.go b/backend/constant/session.go index 1a55cbf83..446ddfe6a 100644 --- a/backend/constant/session.go +++ b/backend/constant/session.go @@ -6,7 +6,7 @@ const ( AuthMethodJWT = "jwt" JWTHeaderName = "Authorization" - JWTBufferTime = 86400 + JWTBufferTime = 3600 JWTIssuer = "1Panel" PasswordExpiredName = "expired" diff --git a/backend/constant/status.go b/backend/constant/status.go index 864be16c3..a7bdab663 100644 --- a/backend/constant/status.go +++ b/backend/constant/status.go @@ -9,4 +9,5 @@ const ( StatusUploading = "Uploading" StatusEnable = "Enable" StatusDisable = "Disable" + StatusNone = "None" ) diff --git a/backend/constant/website.go b/backend/constant/website.go index ea400ce96..354909de2 100644 --- a/backend/constant/website.go +++ b/backend/constant/website.go @@ -4,8 +4,9 @@ const ( WebRunning = "Running" WebStopped = "Stopped" - DateLayout = "2006-01-02" - DefaultDate = "1970-01-01" + DateLayout = "2006-01-02" + DateTimeLayout = "2006-01-02 15:04:05" + DefaultDate = "1970-01-01" ProtocolHTTP = "HTTP" ProtocolHTTPS = "HTTPS" @@ -16,6 +17,7 @@ const ( Deployment = "deployment" Static = "static" Proxy = "proxy" + Runtime = "runtime" SSLExisted = "existed" SSLAuto = "auto" @@ -39,4 +41,7 @@ const ( AccessLog = "access.log" ErrorLog = "error.log" + + ConfigPHP = "php" + ConfigFPM = "fpm" ) diff --git a/backend/cron/cron.go b/backend/cron/cron.go index 4369aadf0..0fe21b1f2 100644 --- a/backend/cron/cron.go +++ b/backend/cron/cron.go @@ -15,7 +15,7 @@ import ( func Run() { nyc, _ := time.LoadLocation("Asia/Shanghai") Cron := cron.New(cron.WithLocation(nyc), cron.WithChain(cron.Recover(cron.DefaultLogger)), cron.WithChain(cron.DelayIfStillRunning(cron.DefaultLogger))) - _, err := Cron.AddJob("@every 1m", job.NewMonitorJob()) + _, err := Cron.AddJob("@every 5m", job.NewMonitorJob()) if err != nil { global.LOG.Errorf("can not add monitor corn job: %s", err.Error()) } @@ -44,13 +44,13 @@ func Run() { }).Error; err != nil { global.LOG.Errorf("start my cronjob failed, err: %v", err) } - for _, cronjob := range cronJobs { - entryID, err := service.ServiceGroupApp.StartJob(&cronjob) + for i := 0; i < len(cronJobs); i++ { + entryID, err := service.NewICronjobService().StartJob(&cronJobs[i]) if err != nil { - global.LOG.Errorf("start %s job %s failed, err: %v", cronjob.Type, cronjob.Name, err) + global.LOG.Errorf("start %s job %s failed, err: %v", cronJobs[i].Type, cronJobs[i].Name, err) } - if err := repo.NewICronjobRepo().Update(cronjob.ID, map[string]interface{}{"entry_id": entryID}); err != nil { - global.LOG.Errorf("update cronjob %s %s failed, err: %v", cronjob.Type, cronjob.Name, err) + if err := repo.NewICronjobRepo().Update(cronJobs[i].ID, map[string]interface{}{"entry_id": entryID}); err != nil { + global.LOG.Errorf("update cronjob %s %s failed, err: %v", cronJobs[i].Type, cronJobs[i].Name, err) } } } diff --git a/backend/cron/job/monitor.go b/backend/cron/job/monitor.go index be27e9cb4..8df90e176 100644 --- a/backend/cron/job/monitor.go +++ b/backend/cron/job/monitor.go @@ -66,6 +66,7 @@ func loadDiskIO() { time.Sleep(60 * time.Second) ioStat2, _ := disk.IOCounters() + var ioList []model.MonitorIO for _, io2 := range ioStat2 { for _, io1 := range ioStat { if io2.Name == io1.Name { @@ -85,13 +86,14 @@ func loadDiskIO() { if writeTime > itemIO.Time { itemIO.Time = writeTime } - if err := global.DB.Create(&itemIO).Error; err != nil { - global.LOG.Errorf("Insert io monitoring data failed, err: %v", err) - } + ioList = append(ioList, itemIO) break } } } + if err := global.DB.CreateInBatches(ioList, len(ioList)).Error; err != nil { + global.LOG.Errorf("Insert io monitoring data failed, err: %v", err) + } } func loadNetIO() { @@ -101,6 +103,7 @@ func loadNetIO() { time.Sleep(60 * time.Second) netStat2, _ := net.IOCounters(true) + var netList []model.MonitorNetwork for _, net2 := range netStat2 { for _, net1 := range netStat { if net2.Name == net1.Name { @@ -108,9 +111,7 @@ func loadNetIO() { itemNet.Name = net1.Name itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60 itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60 - if err := global.DB.Create(&itemNet).Error; err != nil { - global.LOG.Errorf("Insert network monitoring data failed, err: %v", err) - } + netList = append(netList, itemNet) break } } @@ -118,16 +119,21 @@ func loadNetIO() { netStatAll2, _ := net.IOCounters(false) for _, net2 := range netStatAll2 { for _, net1 := range netStatAll { + if net1.BytesSent == 0 || net1.BytesRecv == 0 { + continue + } if net2.Name == net1.Name { var itemNet model.MonitorNetwork itemNet.Name = net1.Name itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60 itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60 - if err := global.DB.Create(&itemNet).Error; err != nil { - global.LOG.Errorf("Insert network all monitoring data failed, err: %v", err) - } + netList = append(netList, itemNet) break } } } + + if err := global.DB.CreateInBatches(netList, len(netList)).Error; err != nil { + global.LOG.Errorf("Insert network monitoring data failed, err: %v", err) + } } diff --git a/backend/cron/job/ssl.go b/backend/cron/job/ssl.go index 8792cbc06..5deb05fda 100644 --- a/backend/cron/job/ssl.go +++ b/backend/cron/job/ssl.go @@ -18,19 +18,22 @@ func (ssl *ssl) Run() { sslRepo := repo.NewISSLRepo() sslService := service.NewIWebsiteSSLService() sslList, _ := sslRepo.List() - global.LOG.Info("ssl renew cron job start...") - now := time.Now() + global.LOG.Info("The scheduled certificate update task is currently in progress ...") + now := time.Now().Add(10 * time.Second) for _, s := range sslList { if !s.AutoRenew || s.Provider == "manual" || s.Provider == "dnsManual" { continue } - sum := s.ExpireDate.Sub(now) - if sum.Hours() < 168 { + expireDate := s.ExpireDate.In(time.Now().Location()) + sub := expireDate.Sub(now) + if sub.Hours() < 720 { + global.LOG.Errorf("Update the SSL certificate for the [%s] domain", s.PrimaryDomain) if err := sslService.Renew(s.ID); err != nil { - global.LOG.Errorf("renew doamin [%s] ssl failed err:%s", s.PrimaryDomain, err.Error()) + global.LOG.Errorf("Failed to update the SSL certificate for the [%s] domain , err:%s", s.PrimaryDomain, err.Error()) + continue } + global.LOG.Errorf("The SSL certificate for the [%s] domain has been successfully updated", s.PrimaryDomain) } } - - global.LOG.Info("ssl renew cron job end...") + global.LOG.Info("The scheduled certificate update task has completed") } diff --git a/backend/cron/job/website.go b/backend/cron/job/website.go index 291a94fe8..a338a42be 100644 --- a/backend/cron/job/website.go +++ b/backend/cron/job/website.go @@ -20,7 +20,7 @@ func NewWebsiteJob() *website { func (w *website) Run() { websites, _ := repo.NewIWebsiteRepo().List() global.LOG.Info("website cron job start...") - now := time.Now() + now := time.Now().Add(10 * time.Second) if len(websites) > 0 { neverExpireDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate) var wg sync.WaitGroup @@ -28,7 +28,8 @@ func (w *website) Run() { if site.Status != constant.WebRunning || neverExpireDate.Equal(site.ExpireDate) { continue } - if site.ExpireDate.Before(now) { + expireDate, _ := time.ParseInLocation(constant.DateTimeLayout, site.ExpireDate.String(), time.Now().Location()) + if expireDate.Before(now) { wg.Add(1) go func(ws model.Website) { stopWebsite(ws.ID, &wg) @@ -41,7 +42,7 @@ func (w *website) Run() { } func stopWebsite(websiteId uint, wg *sync.WaitGroup) { - websiteService := service.NewWebsiteService() + websiteService := service.NewIWebsiteService() req := request.WebsiteOp{ ID: websiteId, Operate: constant.StopWeb, diff --git a/backend/i18n/i18n.go b/backend/i18n/i18n.go index 7ff4c6acb..f6f76007f 100644 --- a/backend/i18n/i18n.go +++ b/backend/i18n/i18n.go @@ -11,35 +11,35 @@ import ( "gopkg.in/yaml.v3" ) -func GetMsgWithMap(msg string, maps map[string]interface{}) string { +func GetMsgWithMap(key string, maps map[string]interface{}) string { content := "" if maps == nil { content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{ - MessageID: msg, + MessageID: key, }) } else { content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{ - MessageID: msg, + MessageID: key, TemplateData: maps, }) } content = strings.ReplaceAll(content, ": ", "") if content == "" { - return msg + return key } else { return content } } -func GetErrMsg(msg string, maps map[string]interface{}) string { +func GetErrMsg(key string, maps map[string]interface{}) string { content := "" if maps == nil { content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{ - MessageID: msg, + MessageID: key, }) } else { content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{ - MessageID: msg, + MessageID: key, TemplateData: maps, }) } diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index 2b272cc61..96da38a07 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -16,6 +16,7 @@ ErrRepoNotValid: "Remote repository verification failed!" #common ErrNameIsExist: "Name is already exist" ErrDemoEnvironment: "Demo server, prohibit this operation!" +ErrCmdTimeout: "Command execution timed out!" #app ErrPortInUsed: "{{ .detail }} port already in use" @@ -26,6 +27,7 @@ ErrPortInOtherApp: "{{ .port }} port already in use by {{ .apps }}" ErrDbUserNotValid: "Stock database, username and password do not match!" ErrDockerComposeNotValid: "docker-compose file format error!" ErrUpdateBuWebsite: 'The application was updated successfully, but the modification of the website configuration file failed, please check the configuration!' +Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}' #file ErrFileCanNotRead: "File can not read" @@ -34,6 +36,7 @@ ErrPathNotFound: "Path is not found" ErrMovePathFailed: "The target path cannot contain the original path!" ErrLinkPathNotFound: "Target path does not exist!" ErrFileIsExit: "File already exists!" +ErrFileUpload: "Failed to upload file" #website ErrDomainIsExist: "Domain is already exist" @@ -50,10 +53,21 @@ ErrEmailIsExist: 'Email is already exist' #mysql ErrUserIsExist: "The current user already exists. Please enter a new user" ErrDatabaseIsExist: "The current database already exists. Please enter a new database" +ErrExecTimeOut: "SQL execution timed out, please check the {{ .detail }} container" #redis ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again" #container ErrInUsed: "{{ .detail }} is in use and cannot be deleted" -ErrObjectInUsed: "This object is in use and cannot be deleted" \ No newline at end of file +ErrObjectInUsed: "This object is in use and cannot be deleted" + +#runtime +ErrDirNotFound: "The build folder does not exist! Please check file integrity!" +ErrFileNotExist: "{{ .detail }} file does not exist! Please check source file integrity!" +ErrImageBuildErr: "Image build failed" +ErrImageExist: "Image is already exist!" +ErrDelWithWebsite: "The operating environment has been associated with a website and cannot be deleted" + +#setting +ErrBackupInUsed: "The backup account is already being used in a cronjob and cannot be deleted." \ No newline at end of file diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 8f69e1f12..1fce0f5dc 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -16,6 +16,7 @@ ErrRepoNotValid: "远程仓库校验失败!" #common ErrNameIsExist: "名称已存在" ErrDemoEnvironment: "演示服务器,禁止此操作!" +ErrCmdTimeout: "命令执行超时!" #app ErrPortInUsed: "{{ .detail }} 端口已被占用!" @@ -26,6 +27,7 @@ ErrPortInOtherApp: "{{ .port }} 端口已被 {{ .apps }}占用!" ErrDbUserNotValid: "存量数据库,用户名密码不匹配!" ErrDockerComposeNotValid: "docker-compose 文件格式错误" ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败,请检查配置!' +Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}' #file ErrFileCanNotRead: "此文件不支持预览" @@ -34,6 +36,7 @@ ErrPathNotFound: "目录不存在" ErrMovePathFailed: "目标路径不能包含原路径!" ErrLinkPathNotFound: "目标路径不存在!" ErrFileIsExit: "文件已存在!" +ErrFileUpload: "上传文件失败" #website ErrDomainIsExist: "域名已存在" @@ -50,10 +53,21 @@ ErrEmailIsExist: '邮箱已存在' #mysql ErrUserIsExist: "当前用户已存在,请重新输入" ErrDatabaseIsExist: "当前数据库已存在,请重新输入" +ErrExecTimeOut: "SQL 执行超时,请检查{{ .detail }}容器" #redis ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试" #container ErrInUsed: "{{ .detail }} 正被使用,无法删除" -ErrObjectInUsed: "该对象正被使用,无法删除" \ No newline at end of file +ErrObjectInUsed: "该对象正被使用,无法删除" + +#runtime +ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!" +ErrFileNotExist: "{{ .detail }} 文件不存在!请检查源文件完整性!" +ErrImageBuildErr: "镜像 build 失败" +ErrImageExist: "镜像已存在!" +ErrDelWithWebsite: "运行环境已经关联网站,无法删除" + +#setting +ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除" diff --git a/backend/init/app/app.go b/backend/init/app/app.go index 03a963284..a02812521 100644 --- a/backend/init/app/app.go +++ b/backend/init/app/app.go @@ -1,11 +1,11 @@ package app import ( + "github.com/1Panel-dev/1Panel/backend/utils/docker" "path" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" - "github.com/1Panel-dev/1Panel/backend/utils/docker" "github.com/1Panel-dev/1Panel/backend/utils/files" ) @@ -14,15 +14,18 @@ func Init() { constant.ResourceDir = path.Join(constant.DataDir, "resource") constant.AppResourceDir = path.Join(constant.ResourceDir, "apps") constant.AppInstallDir = path.Join(constant.DataDir, "apps") + constant.RuntimeDir = path.Join(constant.DataDir, "runtime") + constant.LocalAppResourceDir = path.Join(constant.ResourceDir, "localApps") + constant.LocalAppInstallDir = path.Join(constant.DataDir, "localApps") - dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup} + dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup, constant.RuntimeDir, constant.LocalAppResourceDir} fileOp := files.NewFileOp() for _, dir := range dirs { createDir(fileOp, dir) } - createDefaultDockerNetwork() + _ = docker.CreateDefaultDockerNetwork() } func createDir(fileOp files.FileOp, dirPath string) { @@ -30,17 +33,3 @@ func createDir(fileOp files.FileOp, dirPath string) { _ = fileOp.CreateDir(dirPath, 0755) } } - -func createDefaultDockerNetwork() { - cli, err := docker.NewClient() - if err != nil { - global.LOG.Errorf("init docker client error", err.Error()) - return - } - if !cli.NetworkExist("1panel-network") { - if err := cli.CreateNetwork("1panel-network"); err != nil { - global.LOG.Errorf("init docker client error", err.Error()) - return - } - } -} diff --git a/backend/init/business/business.go b/backend/init/business/business.go index 79567ea23..a1520b8ff 100644 --- a/backend/init/business/business.go +++ b/backend/init/business/business.go @@ -6,18 +6,30 @@ import ( ) func Init() { + syncApp() + syncInstalledApp() +} + +func syncApp() { setting, err := service.NewISettingService().GetSettingInfo() if err != nil { global.LOG.Errorf("sync app error: %s", err.Error()) return } if setting.AppStoreVersion != "" { - global.LOG.Info("do not sync") + global.LOG.Info("no need to sync") return } global.LOG.Info("sync app start...") - if err := service.NewIAppService().SyncAppList(); err != nil { + if err := service.NewIAppService().SyncAppListFromRemote(); err != nil { global.LOG.Errorf("sync app error: %s", err.Error()) + return + } + global.LOG.Info("sync app successful") +} + +func syncInstalledApp() { + if err := service.NewIAppInstalledService().SyncAll(true); err != nil { + global.LOG.Errorf("sync instaled app error: %s", err.Error()) } - global.LOG.Info("sync app success") } diff --git a/backend/init/db/db.go b/backend/init/db/db.go index f1fccda73..4f081c37f 100644 --- a/backend/init/db/db.go +++ b/backend/init/db/db.go @@ -2,9 +2,13 @@ package db import ( "fmt" + "gorm.io/gorm/logger" + "log" + "os" + "time" + "gorm.io/driver/sqlite" "gorm.io/gorm" - "os" "github.com/1Panel-dev/1Panel/backend/global" ) @@ -22,12 +26,32 @@ func Init() { } } + newLogger := logger.New( + log.New(os.Stdout, "\r\n", log.LstdFlags), + logger.Config{ + SlowThreshold: time.Second, + LogLevel: logger.Silent, + IgnoreRecordNotFoundError: true, + Colorful: false, + }, + ) + db, err := gorm.Open(sqlite.Open(fullPath), &gorm.Config{ DisableForeignKeyConstraintWhenMigrating: true, + Logger: newLogger, }) if err != nil { panic(err) } + _ = db.Exec("PRAGMA journal_mode = WAL;") + sqlDB, dbError := db.DB() + if dbError != nil { + panic(err) + } + sqlDB.SetConnMaxIdleTime(10) + sqlDB.SetMaxOpenConns(100) + sqlDB.SetConnMaxLifetime(time.Hour) + global.DB = db global.LOG.Info("init db successfully") } diff --git a/backend/init/migration/migrate.go b/backend/init/migration/migrate.go index 001ab56f6..597519e0f 100644 --- a/backend/init/migration/migrate.go +++ b/backend/init/migration/migrate.go @@ -20,6 +20,11 @@ func Init() { migrations.AddTableWebsite, migrations.AddTableDatabaseMysql, migrations.AddTableSnap, + migrations.AddDefaultGroup, + migrations.AddTableRuntime, + migrations.UpdateTableApp, + migrations.UpdateTableHost, + migrations.UpdateTableWebsite, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index 40bea7364..bf934a602 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -140,7 +140,6 @@ var AddTableSetting = &gormigrate.Migration{ return err } if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil { - tx.Rollback() return err } if err := tx.Create(&model.Setting{Key: "AppStoreVersion", Value: ""}).Error; err != nil { @@ -211,14 +210,7 @@ var AddTableDatabaseMysql = &gormigrate.Migration{ var AddTableWebsite = &gormigrate.Migration{ ID: "20201009-add-table-website", Migrate: func(tx *gorm.DB) error { - if err := tx.AutoMigrate(&model.Website{}, &model.WebsiteDomain{}, &model.WebsiteGroup{}, &model.WebsiteDnsAccount{}, &model.WebsiteSSL{}, &model.WebsiteAcmeAccount{}); err != nil { - return err - } - item := &model.WebsiteGroup{ - Name: "默认", - Default: true, - } - if err := tx.Create(item).Error; err != nil { + if err := tx.AutoMigrate(&model.Website{}, &model.WebsiteDomain{}, &model.WebsiteDnsAccount{}, &model.WebsiteSSL{}, &model.WebsiteAcmeAccount{}); err != nil { return err } return nil @@ -234,3 +226,64 @@ var AddTableSnap = &gormigrate.Migration{ return nil }, } + +var AddDefaultGroup = &gormigrate.Migration{ + ID: "2023022-change-default-group", + Migrate: func(tx *gorm.DB) error { + defaultGroup := &model.Group{ + Name: "默认", + IsDefault: true, + Type: "website", + } + if err := tx.Create(defaultGroup).Error; err != nil { + return err + } + if err := tx.Model(&model.Group{}).Where("name = ? AND type = ?", "default", "host").Update("name", "默认").Error; err != nil { + return err + } + if err := tx.Model(&model.Website{}).Where("1 = 1").Update("website_group_id", defaultGroup.ID).Error; err != nil { + return err + } + return tx.Migrator().DropTable("website_groups") + }, +} + +var AddTableRuntime = &gormigrate.Migration{ + ID: "20230406-add-table-runtime", + Migrate: func(tx *gorm.DB) error { + return tx.AutoMigrate(&model.Runtime{}) + }, +} + +var UpdateTableApp = &gormigrate.Migration{ + ID: "20230408-update-table-app", + Migrate: func(tx *gorm.DB) error { + if err := tx.AutoMigrate(&model.App{}); err != nil { + return err + } + return nil + }, +} + +var UpdateTableHost = &gormigrate.Migration{ + ID: "20230410-update-table-host", + Migrate: func(tx *gorm.DB) error { + if err := tx.AutoMigrate(&model.Host{}); err != nil { + return err + } + return nil + }, +} + +var UpdateTableWebsite = &gormigrate.Migration{ + ID: "20230418-update-table-website", + Migrate: func(tx *gorm.DB) error { + if err := tx.AutoMigrate(&model.Website{}); err != nil { + return err + } + if err := tx.Model(&model.Website{}).Where("1 = 1").Update("site_dir", "/").Error; err != nil { + return err + } + return nil + }, +} diff --git a/backend/init/router/router.go b/backend/init/router/router.go index fe0a35aff..4e106e5b3 100644 --- a/backend/init/router/router.go +++ b/backend/init/router/router.go @@ -4,6 +4,8 @@ import ( "html/template" "net/http" + "github.com/gin-contrib/gzip" + v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/i18n" @@ -39,9 +41,6 @@ func setWebStatic(rootRouter *gin.Engine) { func Routers() *gin.Engine { Router := gin.Default() - docs.SwaggerInfo.BasePath = "/api/v1" - Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) - Router.Use(middleware.OperationLog()) // Router.Use(middleware.CSRF()) // Router.Use(middleware.LoadCsrfToken()) @@ -50,6 +49,7 @@ func Routers() *gin.Engine { Router.Use(middleware.DemoHandle()) } + Router.Use(gzip.Gzip(gzip.DefaultCompression)) setWebStatic(Router) Router.Use(i18n.GinI18nLocalize()) @@ -63,6 +63,10 @@ func Routers() *gin.Engine { systemRouter := rou.RouterGroupApp + swaggerRouter := Router.Group("1panel") + docs.SwaggerInfo.BasePath = "/api/v1" + swaggerRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) + PublicGroup := Router.Group("") { PublicGroup.GET("/health", func(c *gin.Context) { @@ -92,6 +96,7 @@ func Routers() *gin.Engine { systemRouter.InitWebsiteSSLRouter(PrivateGroup) systemRouter.InitWebsiteAcmeAccountRouter(PrivateGroup) systemRouter.InitNginxRouter(PrivateGroup) + systemRouter.InitRuntimeRouter(PrivateGroup) } return Router diff --git a/backend/init/viper/viper.go b/backend/init/viper/viper.go index 3172e0764..bc6b90300 100644 --- a/backend/init/viper/viper.go +++ b/backend/init/viper/viper.go @@ -20,7 +20,7 @@ func Init() { baseDir := "/opt" port := "9999" mode := "" - version := "" + version := "v1.0.0" fileOp := files.NewFileOp() v := viper.NewWithOptions() v.SetConfigType("yaml") diff --git a/backend/log/writer.go b/backend/log/writer.go index 9d028b7a5..979c31d77 100644 --- a/backend/log/writer.go +++ b/backend/log/writer.go @@ -1,7 +1,6 @@ package log import ( - "io/ioutil" "log" "os" "path" @@ -108,7 +107,7 @@ func NewWriterFromConfig(c *Config) (RollingWriter, error) { } if c.MaxRemain > 0 { writer.rollingfilech = make(chan string, c.MaxRemain) - dir, err := ioutil.ReadDir(c.LogPath) + dir, err := os.ReadDir(c.LogPath) if err != nil { mng.Close() return nil, err diff --git a/backend/middleware/jwt.go b/backend/middleware/jwt.go index a381286d6..8adb851d9 100644 --- a/backend/middleware/jwt.go +++ b/backend/middleware/jwt.go @@ -1,22 +1,15 @@ package middleware import ( - "strconv" - "time" - "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" - "github.com/1Panel-dev/1Panel/backend/app/repo" "github.com/1Panel-dev/1Panel/backend/constant" - "github.com/1Panel-dev/1Panel/backend/global" jwtUtils "github.com/1Panel-dev/1Panel/backend/utils/jwt" - "github.com/golang-jwt/jwt/v4" "github.com/gin-gonic/gin" ) func JwtAuth() gin.HandlerFunc { return func(c *gin.Context) { - c.Set("authMethod", "") token := c.Request.Header.Get(constant.JWTHeaderName) if token == "" { c.Next() @@ -28,15 +21,6 @@ func JwtAuth() gin.HandlerFunc { helper.ErrorWithDetail(c, constant.CodeErrUnauthorized, constant.ErrTypeInternalServer, err) return } - if claims.ExpiresAt.Unix()-time.Now().Unix() < claims.BufferTime { - settingRepo := repo.NewISettingRepo() - setting, err := settingRepo.Get(settingRepo.WithByKey("SessionTimeout")) - if err != nil { - global.LOG.Errorf("create operation record failed, err: %v", err) - } - lifeTime, _ := strconv.Atoi(setting.Value) - claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(lifeTime))) - } c.Set("claims", claims) c.Set("authMethod", constant.AuthMethodJWT) c.Next() diff --git a/backend/middleware/operation.go b/backend/middleware/operation.go index 3332f7f44..7ed07b2ea 100644 --- a/backend/middleware/operation.go +++ b/backend/middleware/operation.go @@ -2,9 +2,10 @@ package middleware import ( "bytes" + "compress/gzip" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "strings" "time" @@ -77,9 +78,9 @@ func OperationLog() gin.HandlerFunc { formatMap := make(map[string]interface{}) if len(operationDic.BodyKeys) != 0 { - body, err := ioutil.ReadAll(c.Request.Body) + body, err := io.ReadAll(c.Request.Body) if err == nil { - c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + c.Request.Body = io.NopCloser(bytes.NewBuffer(body)) } bodyMap := make(map[string]interface{}) _ = json.Unmarshal(body, &bodyMap) @@ -129,8 +130,23 @@ func OperationLog() gin.HandlerFunc { c.Next() + buf := bytes.NewReader(writer.body.Bytes()) + reader, err := gzip.NewReader(buf) + if err != nil { + record.Status = constant.StatusFailed + record.Message = fmt.Sprintf("gzip new reader failed, err: %v", err) + latency := time.Since(now) + record.Latency = latency + + if err := service.NewILogService().CreateOperationLog(record); err != nil { + global.LOG.Errorf("create operation record failed, err: %v", err) + } + return + } + defer reader.Close() + datas, _ := io.ReadAll(reader) var res response - _ = json.Unmarshal(writer.body.Bytes(), &res) + _ = json.Unmarshal(datas, &res) if res.Code == 200 { record.Status = constant.StatusSuccess } else { diff --git a/backend/middleware/session.go b/backend/middleware/session.go index 1df01429b..5bffb1cb9 100644 --- a/backend/middleware/session.go +++ b/backend/middleware/session.go @@ -14,6 +14,7 @@ func SessionAuth() gin.HandlerFunc { return func(c *gin.Context) { if method, exist := c.Get("authMethod"); exist && method == constant.AuthMethodJWT { c.Next() + return } sId, err := c.Cookie(constant.SessionName) if err != nil { diff --git a/backend/router/entry.go b/backend/router/entry.go index 07febf122..9898932e6 100644 --- a/backend/router/entry.go +++ b/backend/router/entry.go @@ -19,6 +19,7 @@ type RouterGroup struct { WebsiteSSLRouter DatabaseRouter NginxRouter + RuntimeRouter } var RouterGroupApp = new(RouterGroup) diff --git a/backend/router/ro_app.go b/backend/router/ro_app.go index 66bc9e251..1f734fb95 100644 --- a/backend/router/ro_app.go +++ b/backend/router/ro_app.go @@ -19,13 +19,14 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) { appRouter.GET("/checkupdate", baseApi.GetAppListUpdate) appRouter.POST("/search", baseApi.SearchApp) appRouter.GET("/:key", baseApi.GetApp) - appRouter.GET("/detail/:appId/:version", baseApi.GetAppDetail) + appRouter.GET("/detail/:appId/:version/:type", baseApi.GetAppDetail) + appRouter.GET("/details/:id", baseApi.GetAppDetailByID) appRouter.POST("/install", baseApi.InstallApp) appRouter.GET("/tags", baseApi.GetAppTags) appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions) appRouter.GET("/installed/check/:key", baseApi.CheckAppInstalled) appRouter.GET("/installed/loadport/:key", baseApi.LoadPort) - appRouter.GET("/installed/loadpassword/:key", baseApi.LoadPassword) + appRouter.GET("/installed/conninfo/:key", baseApi.LoadConnInfo) appRouter.GET("/installed/delete/check/:appInstallId", baseApi.DeleteCheck) appRouter.POST("/installed/search", baseApi.SearchAppInstalled) appRouter.POST("/installed/op", baseApi.OperateInstalled) diff --git a/backend/router/ro_container.go b/backend/router/ro_container.go index 2e8008bda..213264780 100644 --- a/backend/router/ro_container.go +++ b/backend/router/ro_container.go @@ -33,6 +33,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) { baRouter.POST("/compose/search", baseApi.SearchCompose) baRouter.POST("/compose", baseApi.CreateCompose) + baRouter.POST("/compose/test", baseApi.TestCompose) baRouter.POST("/compose/operate", baseApi.OperatorCompose) baRouter.POST("/compose/update", baseApi.ComposeUpdate) diff --git a/backend/router/ro_cronjob.go b/backend/router/ro_cronjob.go index 8dd3befc6..a56ea390b 100644 --- a/backend/router/ro_cronjob.go +++ b/backend/router/ro_cronjob.go @@ -24,5 +24,6 @@ func (s *CronjobRouter) InitCronjobRouter(Router *gin.RouterGroup) { cmdRouter.POST("/download", baseApi.TargetDownload) cmdRouter.POST("/search", baseApi.SearchCronjob) cmdRouter.POST("/search/records", baseApi.SearchJobRecords) + cmdRouter.POST("/records/clean", baseApi.CleanRecord) } } diff --git a/backend/router/ro_file.go b/backend/router/ro_file.go index 22628c4bb..8a552c844 100644 --- a/backend/router/ro_file.go +++ b/backend/router/ro_file.go @@ -32,6 +32,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) { fileRouter.POST("/wget", baseApi.WgetFile) fileRouter.POST("/move", baseApi.MoveFile) fileRouter.POST("/download", baseApi.Download) + fileRouter.POST("/download/bypath", baseApi.DownloadFile) fileRouter.POST("/size", baseApi.Size) fileRouter.GET("/ws", baseApi.Ws) fileRouter.GET("/keys", baseApi.Keys) diff --git a/backend/router/ro_website_group.go b/backend/router/ro_group.go similarity index 63% rename from backend/router/ro_website_group.go rename to backend/router/ro_group.go index b2f548010..133dc60a6 100644 --- a/backend/router/ro_website_group.go +++ b/backend/router/ro_group.go @@ -10,14 +10,14 @@ type WebsiteGroupRouter struct { } func (a *WebsiteGroupRouter) InitWebsiteGroupRouter(Router *gin.RouterGroup) { - groupRouter := Router.Group("websites/groups") + groupRouter := Router.Group("groups") groupRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.PasswordExpired()) baseApi := v1.ApiGroupApp.BaseApi { - groupRouter.GET("", baseApi.GetWebGroups) - groupRouter.POST("", baseApi.CreateWebGroup) - groupRouter.POST("/update", baseApi.UpdateWebGroup) - groupRouter.POST("/del", baseApi.DeleteWebGroup) + groupRouter.POST("", baseApi.CreateGroup) + groupRouter.POST("/del", baseApi.DeleteGroup) + groupRouter.POST("/update", baseApi.UpdateGroup) + groupRouter.POST("/search", baseApi.ListGroup) } } diff --git a/backend/router/ro_host.go b/backend/router/ro_host.go index f0439a256..fe3c38767 100644 --- a/backend/router/ro_host.go +++ b/backend/router/ro_host.go @@ -26,10 +26,14 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) { hostRouter.POST("/test/byid/:id", baseApi.TestByID) hostRouter.GET(":id", baseApi.GetHostInfo) - hostRouter.POST("/group", baseApi.CreateGroup) - hostRouter.POST("/group/del", baseApi.DeleteGroup) - hostRouter.POST("/group/update", baseApi.UpdateGroup) - hostRouter.POST("/group/search", baseApi.ListGroup) + hostRouter.GET("/firewall/base", baseApi.LoadFirewallBaseInfo) + hostRouter.POST("/firewall/search", baseApi.SearchFirewallRule) + hostRouter.POST("/firewall/operate", baseApi.OperateFirewall) + hostRouter.POST("/firewall/port", baseApi.OperatePortRule) + hostRouter.POST("/firewall/ip", baseApi.OperateIPRule) + hostRouter.POST("/firewall/batch", baseApi.BatchOperateRule) + hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule) + hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule) hostRouter.GET("/command", baseApi.ListCommand) hostRouter.POST("/command", baseApi.CreateCommand) diff --git a/backend/router/ro_runtime.go b/backend/router/ro_runtime.go new file mode 100644 index 000000000..1c01298e3 --- /dev/null +++ b/backend/router/ro_runtime.go @@ -0,0 +1,24 @@ +package router + +import ( + v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1" + "github.com/1Panel-dev/1Panel/backend/middleware" + "github.com/gin-gonic/gin" +) + +type RuntimeRouter struct { +} + +func (r *RuntimeRouter) InitRuntimeRouter(Router *gin.RouterGroup) { + groupRouter := Router.Group("runtimes") + groupRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.PasswordExpired()) + + baseApi := v1.ApiGroupApp.BaseApi + { + groupRouter.POST("/search", baseApi.SearchRuntimes) + groupRouter.POST("", baseApi.CreateRuntime) + groupRouter.POST("/del", baseApi.DeleteRuntime) + groupRouter.POST("/update", baseApi.UpdateRuntime) + groupRouter.GET("/:id", baseApi.GetRuntime) + } +} diff --git a/backend/router/ro_setting.go b/backend/router/ro_setting.go index 544e21b1f..1493acca1 100644 --- a/backend/router/ro_setting.go +++ b/backend/router/ro_setting.go @@ -51,6 +51,7 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) { settingRouter.POST("/backup/record/del", baseApi.DeleteBackupRecord) settingRouter.POST("/upgrade", baseApi.Upgrade) + settingRouter.POST("/upgrade/notes", baseApi.GetNotesByVersion) settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo) settingRouter.GET("/basedir", baseApi.LoadBaseDir) } diff --git a/backend/router/ro_website.go b/backend/router/ro_website.go index 079b5eaed..0bdb73f47 100644 --- a/backend/router/ro_website.go +++ b/backend/router/ro_website.go @@ -31,7 +31,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) { groupRouter.POST("/domains/del", baseApi.DeleteWebDomain) groupRouter.POST("/domains", baseApi.CreateWebDomain) - groupRouter.GET("/:id/nginx", baseApi.GetWebsiteNginx) + groupRouter.GET("/:id/config/:type", baseApi.GetWebsiteNginx) groupRouter.POST("/config", baseApi.GetNginxConfig) groupRouter.POST("/config/update", baseApi.UpdateNginxConfig) groupRouter.POST("/nginx/update", baseApi.UpdateWebsiteNginxConfig) @@ -41,5 +41,15 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) { groupRouter.POST("/waf/config", baseApi.GetWebsiteWafConfig) groupRouter.POST("/waf/update", baseApi.UpdateWebsiteWafConfig) + + groupRouter.GET("/php/config/:id", baseApi.GetWebsitePHPConfig) + groupRouter.POST("/php/config", baseApi.UpdateWebsitePHPConfig) + groupRouter.POST("/php/update", baseApi.UpdatePHPFile) + + groupRouter.POST("/rewrite", baseApi.GetRewriteConfig) + groupRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig) + + groupRouter.POST("/dir/update", baseApi.UpdateSiteDir) + groupRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission) } } diff --git a/backend/router/ro_website_ssl.go b/backend/router/ro_website_ssl.go index a70701212..82e8a21ed 100644 --- a/backend/router/ro_website_ssl.go +++ b/backend/router/ro_website_ssl.go @@ -22,5 +22,6 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) { groupRouter.POST("/del", baseApi.DeleteWebsiteSSL) groupRouter.GET("/website/:websiteId", baseApi.GetWebsiteSSLByWebsiteId) groupRouter.GET("/:id", baseApi.GetWebsiteSSLById) + groupRouter.POST("/update", baseApi.UpdateWebsiteSSL) } } diff --git a/backend/utils/cloud_storage/client/cos.go b/backend/utils/cloud_storage/client/cos.go new file mode 100644 index 000000000..232099d61 --- /dev/null +++ b/backend/utils/cloud_storage/client/cos.go @@ -0,0 +1,148 @@ +package client + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/1Panel-dev/1Panel/backend/constant" + cosSDK "github.com/tencentyun/cos-go-sdk-v5" +) + +type cosClient struct { + region string + accessKey string + secretKey string + Vars map[string]interface{} + client *cosSDK.Client +} + +func NewCosClient(vars map[string]interface{}) (*cosClient, error) { + var accessKey string + var secretKey string + var region string + if _, ok := vars["region"]; ok { + region = vars["region"].(string) + } else { + return nil, constant.ErrInvalidParams + } + if _, ok := vars["accessKey"]; ok { + accessKey = vars["accessKey"].(string) + } else { + return nil, constant.ErrInvalidParams + } + if _, ok := vars["secretKey"]; ok { + secretKey = vars["secretKey"].(string) + } else { + return nil, constant.ErrInvalidParams + } + + u, _ := url.Parse(fmt.Sprintf("https://cos.%s.myqcloud.com", region)) + b := &cosSDK.BaseURL{BucketURL: u} + client := cosSDK.NewClient(b, &http.Client{ + Transport: &cosSDK.AuthorizationTransport{ + SecretID: accessKey, + SecretKey: secretKey, + }, + }) + + return &cosClient{Vars: vars, client: client, accessKey: accessKey, secretKey: secretKey, region: region}, nil +} + +func (cos cosClient) ListBuckets() ([]interface{}, error) { + buckets, _, err := cos.client.Service.Get(context.Background()) + if err != nil { + return nil, err + } + var datas []interface{} + for _, bucket := range buckets.Buckets { + datas = append(datas, bucket.Name) + } + return datas, nil +} + +func (cos cosClient) Exist(path string) (bool, error) { + client, err := cos.newClientWithBucket() + if err != nil { + return false, err + } + if _, err := client.Object.IsExist(context.Background(), path); err != nil { + return true, err + } + return false, nil +} + +func (cos cosClient) Delete(path string) (bool, error) { + client, err := cos.newClientWithBucket() + if err != nil { + return false, err + } + if _, err := client.Object.Delete(context.Background(), path); err != nil { + return false, err + } + return true, nil +} + +func (cos cosClient) Upload(src, target string) (bool, error) { + client, err := cos.newClientWithBucket() + if err != nil { + return false, err + } + if _, err := client.Object.PutFromFile(context.Background(), target, src, &cosSDK.ObjectPutOptions{}); err != nil { + return false, err + } + return true, nil +} + +func (cos cosClient) Download(src, target string) (bool, error) { + client, err := cos.newClientWithBucket() + if err != nil { + return false, err + } + if _, err := client.Object.Download(context.Background(), src, target, &cosSDK.MultiDownloadOptions{}); err != nil { + return false, err + } + return true, nil +} + +func (cos *cosClient) GetBucket() (string, error) { + if _, ok := cos.Vars["bucket"]; ok { + return cos.Vars["bucket"].(string), nil + } else { + return "", constant.ErrInvalidParams + } +} + +func (cos cosClient) ListObjects(prefix string) ([]interface{}, error) { + client, err := cos.newClientWithBucket() + if err != nil { + return nil, err + } + datas, _, err := client.Bucket.Get(context.Background(), &cosSDK.BucketGetOptions{Prefix: prefix}) + if err != nil { + return nil, err + } + + var result []interface{} + for _, item := range datas.Contents { + result = append(result, item.Key) + } + return result, nil +} + +func (cos cosClient) newClientWithBucket() (*cosSDK.Client, error) { + bucket, err := cos.GetBucket() + if err != nil { + return nil, err + } + u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, cos.region)) + b := &cosSDK.BaseURL{BucketURL: u} + client := cosSDK.NewClient(b, &http.Client{ + Transport: &cosSDK.AuthorizationTransport{ + SecretID: cos.accessKey, + SecretKey: cos.secretKey, + }, + }) + return client, nil +} diff --git a/backend/utils/cloud_storage/client/kodo.go b/backend/utils/cloud_storage/client/kodo.go new file mode 100644 index 000000000..4aba74c08 --- /dev/null +++ b/backend/utils/cloud_storage/client/kodo.go @@ -0,0 +1,145 @@ +package client + +import ( + "context" + "time" + + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/utils/files" + "github.com/qiniu/go-sdk/v7/auth" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/storage" +) + +type kodoClient struct { + accessKey string + secretKey string + Vars map[string]interface{} + client *storage.BucketManager +} + +func NewKodoClient(vars map[string]interface{}) (*kodoClient, error) { + var accessKey string + var secretKey string + if _, ok := vars["accessKey"]; ok { + accessKey = vars["accessKey"].(string) + } else { + return nil, constant.ErrInvalidParams + } + if _, ok := vars["secretKey"]; ok { + secretKey = vars["secretKey"].(string) + } else { + return nil, constant.ErrInvalidParams + } + + conn := qbox.NewMac(accessKey, secretKey) + cfg := storage.Config{ + UseHTTPS: false, + } + bucketManager := storage.NewBucketManager(conn, &cfg) + + return &kodoClient{Vars: vars, client: bucketManager, accessKey: accessKey, secretKey: secretKey}, nil +} + +func (kodo kodoClient) ListBuckets() ([]interface{}, error) { + buckets, err := kodo.client.Buckets(true) + if err != nil { + return nil, err + } + var datas []interface{} + for _, bucket := range buckets { + datas = append(datas, bucket) + } + return datas, nil +} + +func (kodo kodoClient) Exist(path string) (bool, error) { + bucket, err := kodo.GetBucket() + if err != nil { + return false, err + } + if _, err := kodo.client.Stat(bucket, path); err != nil { + return true, err + } + return false, nil +} + +func (kodo kodoClient) Delete(path string) (bool, error) { + bucket, err := kodo.GetBucket() + if err != nil { + return false, err + } + if err := kodo.client.Delete(bucket, path); err != nil { + return false, err + } + return true, nil +} + +func (kodo kodoClient) Upload(src, target string) (bool, error) { + bucket, err := kodo.GetBucket() + if err != nil { + return false, err + } + putPolicy := storage.PutPolicy{ + Scope: bucket, + } + mac := qbox.NewMac(kodo.accessKey, kodo.secretKey) + upToken := putPolicy.UploadToken(mac) + cfg := storage.Config{UseHTTPS: true, UseCdnDomains: false} + resumeUploader := storage.NewResumeUploaderV2(&cfg) + ret := storage.PutRet{} + putExtra := storage.RputV2Extra{} + if err := resumeUploader.PutFile(context.Background(), &ret, upToken, target, src, &putExtra); err != nil { + return false, err + } + return true, nil +} + +func (kodo kodoClient) Download(src, target string) (bool, error) { + mac := auth.New(kodo.accessKey, kodo.secretKey) + if _, ok := kodo.Vars["domain"]; !ok { + return false, constant.ErrInvalidParams + } + domain := kodo.Vars["domain"].(string) + deadline := time.Now().Add(time.Second * 3600).Unix() + privateAccessURL := storage.MakePrivateURL(mac, domain, src, deadline) + + fo := files.NewFileOp() + if err := fo.DownloadFile(privateAccessURL, target); err != nil { + return false, err + } + return true, nil +} + +func (kodo *kodoClient) GetBucket() (string, error) { + if _, ok := kodo.Vars["bucket"]; ok { + return kodo.Vars["bucket"].(string), nil + } else { + return "", constant.ErrInvalidParams + } +} + +func (kodo kodoClient) ListObjects(prefix string) ([]interface{}, error) { + bucket, err := kodo.GetBucket() + if err != nil { + return nil, constant.ErrInvalidParams + } + + var result []interface{} + marker := "" + for { + entries, _, nextMarker, hashNext, err := kodo.client.ListFiles(bucket, prefix, "", marker, 1000) + if err != nil { + return nil, err + } + for _, entry := range entries { + result = append(result, entry.Key) + } + if hashNext { + marker = nextMarker + } else { + break + } + } + return result, nil +} diff --git a/backend/utils/cloud_storage/client/sftp.go b/backend/utils/cloud_storage/client/sftp.go index 4d40d34bf..7f8d999a9 100644 --- a/backend/utils/cloud_storage/client/sftp.go +++ b/backend/utils/cloud_storage/client/sftp.go @@ -2,7 +2,7 @@ package client import ( "fmt" - "io/ioutil" + "io" "net" "os" "path" @@ -75,7 +75,7 @@ func (s sftpClient) Upload(src, target string) (bool, error) { return false, err } defer dstFile.Close() - ff, err := ioutil.ReadAll(srcFile) + ff, err := io.ReadAll(srcFile) if err != nil { return false, err } diff --git a/backend/utils/cloud_storage/cloud_storage_client.go b/backend/utils/cloud_storage/cloud_storage_client.go index 88267818e..ec5af713e 100644 --- a/backend/utils/cloud_storage/cloud_storage_client.go +++ b/backend/utils/cloud_storage/cloud_storage_client.go @@ -27,5 +27,11 @@ func NewCloudStorageClient(vars map[string]interface{}) (CloudStorageClient, err if vars["type"] == constant.MinIo { return client.NewMinIoClient(vars) } + if vars["type"] == constant.Cos { + return client.NewCosClient(vars) + } + if vars["type"] == constant.Kodo { + return client.NewKodoClient(vars) + } return nil, constant.ErrNotSupportType } diff --git a/backend/utils/cmd/cmd.go b/backend/utils/cmd/cmd.go index e56f4c087..9425d4851 100644 --- a/backend/utils/cmd/cmd.go +++ b/backend/utils/cmd/cmd.go @@ -2,16 +2,54 @@ package cmd import ( "bytes" + "context" "fmt" "os/exec" + "time" + + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" ) func Exec(cmdStr string) (string, error) { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() cmd := exec.Command("bash", "-c", cmdStr) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr err := cmd.Run() + if ctx.Err() == context.DeadlineExceeded { + return "", buserr.New(constant.ErrCmdTimeout) + } + if err != nil { + errMsg := "" + if len(stderr.String()) != 0 { + errMsg = fmt.Sprintf("stderr: %s", stderr.String()) + } + if len(stdout.String()) != 0 { + if len(errMsg) != 0 { + errMsg = fmt.Sprintf("%s; stdout: %s", errMsg, stdout.String()) + } else { + errMsg = fmt.Sprintf("stdout: %s", stdout.String()) + } + } + return errMsg, err + } + return stdout.String(), nil +} + +func ExecWithTimeOut(cmdStr string, timeout time.Duration) (string, error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + cmd := exec.Command("bash", "-c", cmdStr) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + err := cmd.Run() + if ctx.Err() == context.DeadlineExceeded { + return "", buserr.New(constant.ErrCmdTimeout) + } if err != nil { errMsg := "" if len(stderr.String()) != 0 { @@ -51,3 +89,14 @@ func Execf(cmdStr string, a ...interface{}) (string, error) { } return stdout.String(), nil } + +func HasNoPasswordSudo() bool { + cmd := exec.Command("sudo", "-v") + err := cmd.Run() + if err != nil { + return false + } + cmd2 := exec.Command("sudo", "-n", "ls") + err2 := cmd2.Run() + return err2 == nil +} diff --git a/backend/utils/common/common.go b/backend/utils/common/common.go index b29dc42cc..312fd6c10 100644 --- a/backend/utils/common/common.go +++ b/backend/utils/common/common.go @@ -83,7 +83,6 @@ func RandStr(n int) string { } func ScanPort(port int) bool { - ln, err := net.Listen("tcp", ":"+strconv.Itoa(port)) if err != nil { return true @@ -92,6 +91,15 @@ func ScanPort(port int) bool { return false } +func ScanUDPPort(port int) bool { + ln, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: port}) + if err != nil { + return true + } + defer ln.Close() + return false +} + func ExistWithStrArray(str string, arr []string) bool { for _, a := range arr { if strings.Contains(a, str) { diff --git a/backend/utils/compose/compose.go b/backend/utils/compose/compose.go index b990275f0..022c68525 100644 --- a/backend/utils/compose/compose.go +++ b/backend/utils/compose/compose.go @@ -2,8 +2,6 @@ package compose import ( "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "github.com/compose-spec/compose-go/loader" - "github.com/compose-spec/compose-go/types" ) func Up(filePath string) (string, error) { @@ -12,7 +10,7 @@ func Up(filePath string) (string, error) { } func Down(filePath string) (string, error) { - stdout, err := cmd.Execf("docker-compose -f %s down", filePath) + stdout, err := cmd.Execf("docker-compose -f %s down --remove-orphans", filePath) return stdout, err } @@ -35,24 +33,3 @@ func Operate(filePath, operation string) (string, error) { stdout, err := cmd.Execf("docker-compose -f %s %s", filePath, operation) return stdout, err } - -func GetComposeProject(yml []byte, env map[string]string) (*types.Project, error) { - var configFiles []types.ConfigFile - configFiles = append(configFiles, types.ConfigFile{ - Filename: "docker-compose.yml", - Content: yml}, - ) - details := types.ConfigDetails{ - WorkingDir: "", - ConfigFiles: configFiles, - Environment: env, - } - - project, err := loader.Load(details, func(options *loader.Options) { - - }) - if err != nil { - return nil, err - } - return project, nil -} diff --git a/backend/utils/docker/compose.go b/backend/utils/docker/compose.go new file mode 100644 index 000000000..fea310e56 --- /dev/null +++ b/backend/utils/docker/compose.go @@ -0,0 +1,125 @@ +package docker + +import ( + "context" + "github.com/compose-spec/compose-go/loader" + "github.com/compose-spec/compose-go/types" + "github.com/docker/cli/cli/command" + "github.com/docker/cli/cli/flags" + "github.com/docker/compose/v2/pkg/api" + "github.com/docker/compose/v2/pkg/compose" + "github.com/docker/docker/client" + "github.com/joho/godotenv" + "path" + "regexp" + "strings" + "time" +) + +type ComposeService struct { + api.Service + project *types.Project +} + +func NewComposeService(ops ...command.DockerCliOption) (*ComposeService, error) { + apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return nil, err + } + ops = append(ops, command.WithAPIClient(apiClient), command.WithDefaultContextStoreConfig()) + cli, err := command.NewDockerCli(ops...) + if err != nil { + return nil, err + } + cliOp := flags.NewClientOptions() + if err := cli.Initialize(cliOp); err != nil { + return nil, err + } + service := compose.NewComposeService(cli) + return &ComposeService{service, nil}, nil +} + +func (s *ComposeService) SetProject(project *types.Project) { + s.project = project + for i, s := range project.Services { + s.CustomLabels = map[string]string{ + api.ProjectLabel: project.Name, + api.ServiceLabel: s.Name, + api.VersionLabel: api.ComposeVersion, + api.WorkingDirLabel: project.WorkingDir, + api.ConfigFilesLabel: strings.Join(project.ComposeFiles, ","), + api.OneoffLabel: "False", + } + project.Services[i] = s + } +} + +func (s *ComposeService) ComposeUp() error { + return s.Up(context.Background(), s.project, api.UpOptions{ + Create: api.CreateOptions{ + Timeout: getComposeTimeout(), + }, + Start: api.StartOptions{ + WaitTimeout: *getComposeTimeout(), + }, + }) +} + +func (s *ComposeService) ComposeDown() error { + return s.Down(context.Background(), s.project.Name, api.DownOptions{}) +} + +func (s *ComposeService) ComposeStart() error { + return s.Start(context.Background(), s.project.Name, api.StartOptions{}) +} + +func (s *ComposeService) ComposeRestart() error { + return s.Restart(context.Background(), s.project.Name, api.RestartOptions{}) +} + +func (s *ComposeService) ComposeStop() error { + return s.Stop(context.Background(), s.project.Name, api.StopOptions{}) +} + +func (s *ComposeService) ComposeCreate() error { + return s.Create(context.Background(), s.project, api.CreateOptions{}) +} + +func (s *ComposeService) ComposeBuild() error { + return s.Build(context.Background(), s.project, api.BuildOptions{}) +} + +func GetComposeProject(projectName, workDir string, yml []byte, env []byte, skipNormalization bool) (*types.Project, error) { + var configFiles []types.ConfigFile + configFiles = append(configFiles, types.ConfigFile{ + Filename: "docker-compose.yml", + Content: yml}, + ) + envMap, err := godotenv.UnmarshalBytes(env) + if err != nil { + return nil, err + } + details := types.ConfigDetails{ + WorkingDir: workDir, + ConfigFiles: configFiles, + Environment: envMap, + } + projectName = strings.ToLower(projectName) + reg, _ := regexp.Compile(`[^a-z0-9_-]+`) + projectName = reg.ReplaceAllString(projectName, "") + project, err := loader.Load(details, func(options *loader.Options) { + options.SetProjectName(projectName, true) + options.ResolvePaths = true + options.SkipNormalization = skipNormalization + }) + if err != nil { + return nil, err + } + project.ComposeFiles = []string{path.Join(workDir, "docker-compose.yml")} + return project, nil +} + +func getComposeTimeout() *time.Duration { + timeout := time.Minute * time.Duration(10) + return &timeout +} diff --git a/backend/utils/docker/docker.go b/backend/utils/docker/docker.go index 8e9ca32db..1c436c420 100644 --- a/backend/utils/docker/docker.go +++ b/backend/utils/docker/docker.go @@ -2,6 +2,7 @@ package docker import ( "context" + "github.com/1Panel-dev/1Panel/backend/global" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" @@ -64,6 +65,28 @@ func (c Client) CreateNetwork(name string) error { return err } +func (c Client) DeleteImage(imageID string) error { + if _, err := c.cli.ImageRemove(context.Background(), imageID, types.ImageRemoveOptions{Force: true}); err != nil { + return err + } + return nil +} + +func (c Client) GetImageIDByName(imageName string) (string, error) { + filter := filters.NewArgs() + filter.Add("reference", imageName) + list, err := c.cli.ImageList(context.Background(), types.ImageListOptions{ + Filters: filter, + }) + if err != nil { + return "", err + } + if len(list) > 0 { + return list[0].ID, nil + } + return "", nil +} + func (c Client) NetworkExist(name string) bool { var options types.NetworkListOptions options.Filters = filters.NewArgs(filters.Arg("name", name)) @@ -73,3 +96,18 @@ func (c Client) NetworkExist(name string) bool { } return len(networks) > 0 } + +func CreateDefaultDockerNetwork() error { + cli, err := NewClient() + if err != nil { + global.LOG.Errorf("init docker client error %s", err.Error()) + return err + } + if !cli.NetworkExist("1panel-network") { + if err := cli.CreateNetwork("1panel-network"); err != nil { + global.LOG.Errorf("create default docker network error %s", err.Error()) + return err + } + } + return nil +} diff --git a/backend/utils/files/file_op.go b/backend/utils/files/file_op.go index ae450f8d9..9b85138a4 100644 --- a/backend/utils/files/file_op.go +++ b/backend/utils/files/file_op.go @@ -37,6 +37,15 @@ func (f FileOp) OpenFile(dst string) (fs.File, error) { return f.Fs.Open(dst) } +func (f FileOp) GetContent(dst string) ([]byte, error) { + afs := &afero.Afero{Fs: f.Fs} + cByte, err := afs.ReadFile(dst) + if err != nil { + return nil, err + } + return cByte, nil +} + func (f FileOp) CreateDir(dst string, mode fs.FileMode) error { return f.Fs.MkdirAll(dst, mode) } @@ -106,6 +115,10 @@ func (f FileOp) Chmod(dst string, mode fs.FileMode) error { return f.Fs.Chmod(dst, mode) } +func (f FileOp) Chown(dst string, uid int, gid int) error { + return f.Fs.Chown(dst, uid, gid) +} + func (f FileOp) Rename(oldName string, newName string) error { return f.Fs.Rename(oldName, newName) } @@ -239,19 +252,15 @@ func (f FileOp) Copy(src, dst string) error { if src = path.Clean("/" + src); src == "" { return os.ErrNotExist } - if dst = path.Clean("/" + dst); dst == "" { return os.ErrNotExist } - if src == "/" || dst == "/" { return os.ErrInvalid } - if dst == src { return os.ErrInvalid } - info, err := f.Fs.Stat(src) if err != nil { return err @@ -259,7 +268,6 @@ func (f FileOp) Copy(src, dst string) error { if info.IsDir() { return f.CopyDir(src, dst) } - return f.CopyFile(src, dst) } @@ -429,7 +437,6 @@ func (f FileOp) Compress(srcRiles []string, dst string, name string, cType Compr _ = f.DeleteFile(dstFile) return err } - break } return nil } diff --git a/backend/utils/firewall/client.go b/backend/utils/firewall/client.go new file mode 100644 index 000000000..9080b657d --- /dev/null +++ b/backend/utils/firewall/client.go @@ -0,0 +1,34 @@ +package firewall + +import ( + "errors" + "os" + + "github.com/1Panel-dev/1Panel/backend/utils/firewall/client" +) + +type FirewallClient interface { + Name() string // ufw firewalld + Start() error + Stop() error + Reload() error + Status() (string, error) // running not running + Version() (string, error) + + ListPort() ([]client.FireInfo, error) + ListAddress() ([]client.FireInfo, error) + + Port(port client.FireInfo, operation string) error + RichRules(rule client.FireInfo, operation string) error + PortForward(info client.Forward, operation string) error +} + +func NewFirewallClient() (FirewallClient, error) { + if _, err := os.Stat("/usr/sbin/firewalld"); err == nil { + return client.NewFirewalld() + } + if _, err := os.Stat("/usr/sbin/ufw"); err == nil { + return client.NewUfw() + } + return nil, errors.New("no such type") +} diff --git a/backend/utils/firewall/client/firewalld.go b/backend/utils/firewall/client/firewalld.go new file mode 100644 index 000000000..3f61b67ce --- /dev/null +++ b/backend/utils/firewall/client/firewalld.go @@ -0,0 +1,192 @@ +package client + +import ( + "fmt" + "strings" + + "github.com/1Panel-dev/1Panel/backend/utils/cmd" +) + +type Firewall struct{} + +func NewFirewalld() (*Firewall, error) { + return &Firewall{}, nil +} + +func (f *Firewall) Name() string { + return "firewalld" +} + +func (f *Firewall) Status() (string, error) { + stdout, _ := cmd.Exec("firewall-cmd --state") + if stdout == "running\n" { + return "running", nil + } + return "not running", nil +} + +func (f *Firewall) Version() (string, error) { + stdout, err := cmd.Exec("firewall-cmd --version") + if err != nil { + return "", fmt.Errorf("load the firewall version failed, err: %s", stdout) + } + return strings.ReplaceAll(stdout, "\n ", ""), nil +} + +func (f *Firewall) Start() error { + stdout, err := cmd.Exec("systemctl start firewalld") + if err != nil { + return fmt.Errorf("enable the firewall failed, err: %s", stdout) + } + return nil +} + +func (f *Firewall) Stop() error { + stdout, err := cmd.Exec("systemctl stop firewalld") + if err != nil { + return fmt.Errorf("stop the firewall failed, err: %s", stdout) + } + return nil +} + +func (f *Firewall) Reload() error { + stdout, err := cmd.Exec("firewall-cmd --reload") + if err != nil { + return fmt.Errorf("reload firewall failed, err: %s", stdout) + } + return nil +} + +func (f *Firewall) ListPort() ([]FireInfo, error) { + stdout, err := cmd.Exec("firewall-cmd --zone=public --list-ports") + if err != nil { + return nil, err + } + ports := strings.Split(strings.ReplaceAll(stdout, "\n", ""), " ") + var datas []FireInfo + for _, port := range ports { + if len(port) == 0 { + continue + } + var itemPort FireInfo + if strings.Contains(port, "/") { + itemPort.Port = strings.Split(port, "/")[0] + itemPort.Protocol = strings.Split(port, "/")[1] + } + itemPort.Strategy = "accept" + datas = append(datas, itemPort) + } + + stdout1, err := cmd.Exec("firewall-cmd --zone=public --list-rich-rules") + if err != nil { + return nil, err + } + rules := strings.Split(stdout1, "\n") + for _, rule := range rules { + if len(rule) == 0 { + continue + } + itemRule := f.loadInfo(rule) + if len(itemRule.Port) != 0 && itemRule.Family == "ipv4" { + datas = append(datas, itemRule) + } + } + return datas, nil +} + +func (f *Firewall) ListAddress() ([]FireInfo, error) { + stdout, err := cmd.Exec("firewall-cmd --zone=public --list-rich-rules") + if err != nil { + return nil, err + } + var datas []FireInfo + rules := strings.Split(stdout, "\n") + for _, rule := range rules { + if len(rule) == 0 { + continue + } + itemRule := f.loadInfo(rule) + if len(itemRule.Port) == 0 && len(itemRule.Address) != 0 { + datas = append(datas, itemRule) + } + } + return datas, nil +} + +func (f *Firewall) Port(port FireInfo, operation string) error { + stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol) + if err != nil { + return fmt.Errorf("%s port failed, err: %s", operation, stdout) + } + return nil +} + +func (f *Firewall) RichRules(rule FireInfo, operation string) error { + ruleStr := "" + if strings.Contains(rule.Address, "-") { + std, err := cmd.Execf("firewall-cmd --permanent --new-ipset=%s --type=hash:ip", rule.Address) + if err != nil { + return fmt.Errorf("add new ipset failed, err: %s", std) + } + std2, err := cmd.Execf("firewall-cmd --permanent --ipset=%s --add-entry=%s", rule.Address, rule.Address) + if err != nil { + return fmt.Errorf("add entry to ipset failed, err: %s", std2) + } + if err := f.Reload(); err != nil { + return err + } + ruleStr = fmt.Sprintf("rule source ipset=%s %s", rule.Address, rule.Strategy) + } else { + ruleStr = "rule family=ipv4 " + if len(rule.Address) != 0 { + ruleStr += fmt.Sprintf("source address=%s ", rule.Address) + } + if len(rule.Port) != 0 { + ruleStr += fmt.Sprintf("port port=%s ", rule.Port) + } + if len(rule.Protocol) != 0 { + ruleStr += fmt.Sprintf("protocol=%s ", rule.Protocol) + } + ruleStr += rule.Strategy + } + stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent", operation, ruleStr) + if err != nil { + return fmt.Errorf("%s rich rules failed, err: %s", operation, stdout) + } + return nil +} + +func (f *Firewall) PortForward(info Forward, operation string) error { + ruleStr := fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Target) + if len(info.Address) != 0 { + ruleStr = fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Address, info.Target) + } + + stdout, err := cmd.Exec(ruleStr) + if err != nil { + return fmt.Errorf("%s port forward failed, err: %s", operation, stdout) + } + return nil +} + +func (f *Firewall) loadInfo(line string) FireInfo { + var itemRule FireInfo + ruleInfo := strings.Split(strings.ReplaceAll(line, "\"", ""), " ") + for _, item := range ruleInfo { + switch { + case strings.Contains(item, "family="): + itemRule.Family = strings.ReplaceAll(item, "family=", "") + case strings.Contains(item, "ipset="): + itemRule.Address = strings.ReplaceAll(item, "ipset=", "") + case strings.Contains(item, "address="): + itemRule.Address = strings.ReplaceAll(item, "address=", "") + case strings.Contains(item, "port="): + itemRule.Port = strings.ReplaceAll(item, "port=", "") + case strings.Contains(item, "protocol="): + itemRule.Protocol = strings.ReplaceAll(item, "protocol=", "") + case item == "accept" || item == "drop" || item == "reject": + itemRule.Strategy = item + } + } + return itemRule +} diff --git a/backend/utils/firewall/client/info.go b/backend/utils/firewall/client/info.go new file mode 100644 index 000000000..d9b507b0d --- /dev/null +++ b/backend/utils/firewall/client/info.go @@ -0,0 +1,19 @@ +package client + +type FireInfo struct { + Family string `json:"family"` // ipv4 ipv6 + Address string `json:"address"` // Anywhere + Port string `json:"port"` + Protocol string `json:"protocol"` // tcp udp tcp/udp + Strategy string `json:"strategy"` // accept drop + + APPName string `json:"appName"` + IsUsed bool `json:"isUsed"` +} + +type Forward struct { + Protocol string `json:"protocol"` + Address string `json:"address"` + Port string `json:"port"` + Target string `json:"target"` +} diff --git a/backend/utils/firewall/client/ufw.go b/backend/utils/firewall/client/ufw.go new file mode 100644 index 000000000..4bbb592e3 --- /dev/null +++ b/backend/utils/firewall/client/ufw.go @@ -0,0 +1,231 @@ +package client + +import ( + "fmt" + "strings" + + "github.com/1Panel-dev/1Panel/backend/utils/cmd" +) + +type Ufw struct { + CmdStr string +} + +func NewUfw() (*Ufw, error) { + var ufw Ufw + if cmd.HasNoPasswordSudo() { + ufw.CmdStr = "sudo ufw" + } else { + ufw.CmdStr = "ufw" + } + return &ufw, nil +} + +func (f *Ufw) Name() string { + return "ufw" +} + +func (f *Ufw) Status() (string, error) { + stdout, _ := cmd.Execf("%s status | grep Status", f.CmdStr) + if stdout == "Status: active\n" { + return "running", nil + } + stdout1, _ := cmd.Execf("%s status | grep 状态", f.CmdStr) + if stdout1 == "状态: 激活\n" { + return "running", nil + } + return "not running", nil +} + +func (f *Ufw) Version() (string, error) { + stdout, err := cmd.Execf("%s version | grep ufwHasNoPasswordSudo", f.CmdStr) + if err != nil { + return "", fmt.Errorf("load the firewall status failed, err: %s", stdout) + } + info := strings.ReplaceAll(stdout, "\n", "") + return strings.ReplaceAll(info, "ufw ", ""), nil +} + +func (f *Ufw) Start() error { + stdout, err := cmd.Execf("echo y | %s enable", f.CmdStr) + if err != nil { + return fmt.Errorf("enable the firewall failed, err: %s", stdout) + } + return nil +} + +func (f *Ufw) Stop() error { + stdout, err := cmd.Execf("%s disable", f.CmdStr) + if err != nil { + return fmt.Errorf("stop the firewall failed, err: %s", stdout) + } + return nil +} + +func (f *Ufw) Reload() error { + return nil +} + +func (f *Ufw) ListPort() ([]FireInfo, error) { + stdout, err := cmd.Execf("%s status verbose", f.CmdStr) + if err != nil { + return nil, err + } + portInfos := strings.Split(stdout, "\n") + var datas []FireInfo + isStart := false + for _, line := range portInfos { + if strings.HasPrefix(line, "--") { + isStart = true + continue + } + if !isStart { + continue + } + itemFire := f.loadInfo(line, "port") + if len(itemFire.Port) != 0 && itemFire.Port != "Anywhere" && !strings.Contains(itemFire.Port, ".") { + itemFire.Port = strings.ReplaceAll(itemFire.Port, ":", "-") + datas = append(datas, itemFire) + } + } + return datas, nil +} + +func (f *Ufw) ListAddress() ([]FireInfo, error) { + stdout, err := cmd.Execf("%s status verbose", f.CmdStr) + if err != nil { + return nil, err + } + portInfos := strings.Split(stdout, "\n") + var datas []FireInfo + isStart := false + for _, line := range portInfos { + if strings.HasPrefix(line, "--") { + isStart = true + continue + } + if !isStart { + continue + } + if !strings.Contains(line, " IN") { + continue + } + itemFire := f.loadInfo(line, "address") + if strings.Contains(itemFire.Port, ".") { + itemFire.Address += ("-" + itemFire.Port) + itemFire.Port = "" + } + if len(itemFire.Port) == 0 && len(itemFire.Address) != 0 { + datas = append(datas, itemFire) + } + } + return datas, nil +} + +func (f *Ufw) Port(port FireInfo, operation string) error { + switch port.Strategy { + case "accept": + port.Strategy = "allow" + case "drop": + port.Strategy = "deny" + default: + return fmt.Errorf("unsupport strategy %s", port.Strategy) + } + + command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port) + if operation == "remove" { + command = fmt.Sprintf("%s delete %s %s", f.CmdStr, port.Strategy, port.Port) + } + if len(port.Protocol) != 0 { + command += fmt.Sprintf("/%s", port.Protocol) + } + stdout, err := cmd.Exec(command) + if err != nil { + return fmt.Errorf("%s port failed, err: %s", operation, stdout) + } + return nil +} + +func (f *Ufw) RichRules(rule FireInfo, operation string) error { + switch rule.Strategy { + case "accept": + rule.Strategy = "allow" + case "drop": + rule.Strategy = "deny" + default: + return fmt.Errorf("unsupport strategy %s", rule.Strategy) + } + + ruleStr := fmt.Sprintf("%s %s ", f.CmdStr, rule.Strategy) + if operation == "remove" { + ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy) + } + if len(rule.Protocol) != 0 { + ruleStr += fmt.Sprintf("proto %s ", rule.Protocol) + } + if strings.Contains(rule.Address, "-") { + ruleStr += fmt.Sprintf("from %s to %s ", strings.Split(rule.Address, "-")[0], strings.Split(rule.Address, "-")[1]) + } else { + ruleStr += fmt.Sprintf("from %s ", rule.Address) + } + if len(rule.Port) != 0 { + ruleStr += fmt.Sprintf("to any port %s ", rule.Port) + } + + stdout, err := cmd.Exec(ruleStr) + if err != nil { + return fmt.Errorf("%s rich rules failed, err: %s", operation, stdout) + } + return nil +} + +func (f *Ufw) PortForward(info Forward, operation string) error { + ruleStr := fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Target) + if len(info.Address) != 0 { + ruleStr = fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Address, info.Target) + } + + stdout, err := cmd.Exec(ruleStr) + if err != nil { + return fmt.Errorf("%s port forward failed, err: %s", operation, stdout) + } + if err := f.Reload(); err != nil { + return err + } + return nil +} + +func (f *Ufw) loadInfo(line string, fireType string) FireInfo { + fields := strings.Fields(line) + var itemInfo FireInfo + if len(fields) < 4 { + return itemInfo + } + if fields[1] == "(v6)" { + return itemInfo + } + if fields[0] == "Anywhere" && fireType != "port" { + itemInfo.Strategy = "drop" + if fields[1] == "ALLOW" { + itemInfo.Strategy = "accept" + } + itemInfo.Address = fields[3] + return itemInfo + } + if strings.Contains(fields[0], "/") { + itemInfo.Port = strings.Split(fields[0], "/")[0] + itemInfo.Protocol = strings.Split(fields[0], "/")[1] + } else { + itemInfo.Port = fields[0] + itemInfo.Protocol = "tcp/udp" + } + itemInfo.Family = "ipv4" + if fields[1] == "ALLOW" { + itemInfo.Strategy = "accept" + } else { + itemInfo.Strategy = "drop" + } + itemInfo.Address = fields[3] + + return itemInfo +} diff --git a/backend/utils/jwt/jwt.go b/backend/utils/jwt/jwt.go index 5ebe26f0b..f8c1c1529 100644 --- a/backend/utils/jwt/jwt.go +++ b/backend/utils/jwt/jwt.go @@ -38,12 +38,12 @@ func NewJWT() *JWT { } } -func (j *JWT) CreateClaims(baseClaims BaseClaims, ttl int) CustomClaims { +func (j *JWT) CreateClaims(baseClaims BaseClaims) CustomClaims { claims := CustomClaims{ BaseClaims: baseClaims, BufferTime: constant.JWTBufferTime, RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(ttl))), + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(constant.JWTBufferTime))), Issuer: constant.JWTIssuer, }, } diff --git a/backend/utils/nginx/components/config.go b/backend/utils/nginx/components/config.go index 7592895e7..5399fbb20 100644 --- a/backend/utils/nginx/components/config.go +++ b/backend/utils/nginx/components/config.go @@ -44,6 +44,8 @@ var repeatKeys = map[string]struct { "set": {}, "if": {}, "proxy_set_header": {}, + "location": {}, + "include": {}, } func IsRepeatKey(key string) bool { diff --git a/backend/utils/nginx/components/location.go b/backend/utils/nginx/components/location.go index f3d585af0..784ff8c34 100644 --- a/backend/utils/nginx/components/location.go +++ b/backend/utils/nginx/components/location.go @@ -24,8 +24,8 @@ func NewLocation(directive *Directive) *Location { location.Match = directive.Parameters[0] return location } else if len(directive.Parameters) == 2 { - location.Modifier = directive.Parameters[0] location.Match = directive.Parameters[1] + location.Modifier = directive.Parameters[0] return location } return nil diff --git a/backend/utils/nginx/components/server.go b/backend/utils/nginx/components/server.go index 961b71859..a7b6da79d 100644 --- a/backend/utils/nginx/components/server.go +++ b/backend/utils/nginx/components/server.go @@ -116,14 +116,22 @@ func (s *Server) RemoveDirective(key string, params []string) { directives := s.Directives var newDirectives []IDirective for _, dir := range directives { - if dir.GetName() == key { - if IsRepeatKey(key) && len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { + if key == "location" { + if location, ok := dir.(*Location); ok { + if len(params) == 2 && location.Match == params[1] && location.Modifier == params[0] { + continue + } + } + } else { + if dir.GetName() == key { + if len(params) > 0 { + oldParams := dir.GetParameters() + if oldParams[0] == params[0] { + continue + } + } else { continue } - } else { - continue } } newDirectives = append(newDirectives, dir) @@ -237,6 +245,40 @@ func (s *Server) UpdateRootProxy(proxy []string) { s.UpdateDirectiveBySecondKey("location", "/", newDir) } +func (s *Server) UpdatePHPProxy(proxy []string, localPath string) { + newDir := Directive{ + Name: "location", + Parameters: []string{"~ [^/]\\.php(/|$)"}, + Block: &Block{}, + } + block := &Block{} + block.Directives = append(block.Directives, &Directive{ + Name: "fastcgi_pass", + Parameters: proxy, + }) + block.Directives = append(block.Directives, &Directive{ + Name: "include", + Parameters: []string{"fastcgi-php.conf"}, + }) + block.Directives = append(block.Directives, &Directive{ + Name: "include", + Parameters: []string{"fastcgi_params"}, + }) + if localPath == "" { + block.Directives = append(block.Directives, &Directive{ + Name: "fastcgi_param", + Parameters: []string{"SCRIPT_FILENAME", "$document_root$fastcgi_script_name"}, + }) + } else { + block.Directives = append(block.Directives, &Directive{ + Name: "fastcgi_param", + Parameters: []string{"SCRIPT_FILENAME", localPath}, + }) + } + newDir.Block = block + s.UpdateDirectiveBySecondKey("location", "~ [^/]\\.php(/|$)", newDir) +} + func (s *Server) UpdateDirectiveBySecondKey(name string, key string, directive Directive) { directives := s.Directives index := -1 diff --git a/backend/utils/nginx/dumper.go b/backend/utils/nginx/dumper.go index 45455d518..757eef665 100644 --- a/backend/utils/nginx/dumper.go +++ b/backend/utils/nginx/dumper.go @@ -3,9 +3,10 @@ package nginx import ( "bytes" "fmt" - "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" - "io/ioutil" + "os" "strings" + + "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" ) var ( @@ -96,5 +97,5 @@ func DumpConfig(c *components.Config, style *Style) string { } func WriteConfig(c *components.Config, style *Style) error { - return ioutil.WriteFile(c.FilePath, []byte(DumpConfig(c, style)), 0644) + return os.WriteFile(c.FilePath, []byte(DumpConfig(c, style)), 0644) } diff --git a/backend/utils/nginx/private.key b/backend/utils/nginx/private.key deleted file mode 100644 index 32f7366f7..000000000 --- a/backend/utils/nginx/private.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN privateKey----- -MIIEoAIBAAKCAQEAvZRFbJcXQSIyhfbl9ZiulTgwFUNsqO3YOZgpRa0T0dgbg6BO -0nnPvlcZvR8TcdDc1B/kplps3O9QkV2d8AzutYWOG/TkZ8ywVuwni1yWqfyy7msV -GyhAqNI2lE6AMY5QJ7/GXX7vuN2jwUWBKSjYTXhyyWOMXmeijI0j3FPCtCN6G9x6 -+oV0chtNTtDpz1lOw7g+b7cVqDD0MKMaFMl5EhbjSkw5E0GDPLIYRmctXRdFBTow -UcPxpMM0yuKksLROUccLRUIazHi+19HTlVx7sPYCTrFhh0N4xuPrv0pyfBUWInE0 -Yza2ESpym6AlQLzSpOQji9IKdh8uIAZyShpFgwIDAQABAoIBAAzkjYgiCmHSmo8D -yIXYWV8qkBKSIEyoyEC6eWwUpjlqMgzUlSe5QwiV0dlLyL2/z5TZimpJ0geAewE3 -1aripkVQDOcX04S/pepzawkORezPk7elLq1HIoaYrT+OyycTn53ka/Al1tXCtQVK -3crXzUYPf/b0PzKYZ7SZUKwGQkKP3QoHfFB+zVr0ZczHhWhdyk3rqNbblVR0OPJE -QCDQRqe7pS2wxs2Br3lNUnCqHqThtRu2sQK3UTBRP37AxrRd+gplB+QS+vPpgIFs -kVEoOdtuox7U5OOHj3WwhDosMLvXgK359g30olVL7ZTuLregFwhaidZcF4fI8A69 -MX0YyLkCgYEAy4MQNELXWFJpTwova/RFEnczdP34rtcg/Z5Zvwq6Th4SbbMrVudM -BGEUVUHQbV4unD6T722FtQhfLrQXxgrLlHu7KkcnkciQd6iZCStAAH+XpnVvlj6k -THvnJxN1H1b4kimsxTuc+/96BqkpkHnbb0KBbHPdz3rGKtWKfIYBRhcCgYEA7nlK -vAGnOdVFKa5MPkdWeuwym3bjjZXBQB7/aRucqt3URi9XTl4/EwxHGmGpzTTSmpCN -+SDg5+lGVtivyk6QiRuKvhB9uohj3C6krHKjZtJz+ydtzrSi6DcAGrsWdu1EsSXR -s1aLhetrrPmKpayzK6TsUzcW3yVdgIYXFhY3y3UCfzR3lbXjhaE/nebCuXcbgrNA -CAQhdfudeuPn7ztRiLabCiU+C+5bsz1tydAxJ4sKvPmLKJiRo+cIQYHI7FgicFnX -jGlZ7tmm25f933Z9sAJw4qgHnr0daT5Os0lfutJZmbwVAnXW6KIPO2Z8NjsJL4l/ -m95aANV80Zo5c3qnEa0CgYBvw8Ll6DRyo2Sdy0WKbq62P5rcR9UQF16R6bU0kq9T -WVHSbv+RCBSxnbB5ScpmFVqa/CK93s3pgufnbfi9bSLKT3Ev8NSsJp3+pJGjDLtO -RlX7IJiTJw+um5Bd9s7pf/wQtjPYxDfx1MsLL4zuZsk2LD5iJdB/VqjCwpVxUYpm -vQKBgFtmL0pSbd6433YwY+vR5sZ8uMSXqaS9imisW42fAj7v3W1Td0yi1WwNTNqr -zXQVMspNVBXf5fyzh8gAW4gzD7JLBsxA5sr4gPFpxwJTfbvrIR0K8jr+1yxviGAb -eJcEigsnUfhZrVEa1am+mRaumjkZBdS+xCClS7auY2raxQ5x ------END privateKey----- diff --git a/backend/utils/ssh/ssh.go b/backend/utils/ssh/ssh.go index a1cd69659..bbe6d2377 100644 --- a/backend/utils/ssh/ssh.go +++ b/backend/utils/ssh/ssh.go @@ -127,20 +127,8 @@ func (w *wsBufferWriter) Write(p []byte) (int, error) { } func makePrivateKeySigner(privateKey []byte, passPhrase []byte) (gossh.Signer, error) { - var signer gossh.Signer - if passPhrase != nil { - s, err := gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase) - if err != nil { - return nil, fmt.Errorf("error parsing SSH key: '%v'", err) - } - signer = s - } else { - s, err := gossh.ParsePrivateKey(privateKey) - if err != nil { - return nil, fmt.Errorf("error parsing SSH key: '%v'", err) - } - signer = s + if len(passPhrase) != 0 { + return gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase) } - - return signer, nil + return gossh.ParsePrivateKey(privateKey) } diff --git a/backend/utils/ssl/acme_test.go b/backend/utils/ssl/acme_test.go index af9b05129..681f6eb8c 100644 --- a/backend/utils/ssl/acme_test.go +++ b/backend/utils/ssl/acme_test.go @@ -6,7 +6,6 @@ import ( "crypto/x509" "encoding/pem" "fmt" - "io/ioutil" "os" "testing" "time" @@ -68,7 +67,7 @@ func TestSSL(t *testing.T) { // return //} - key, err := ioutil.ReadFile("private.key") + key, err := os.ReadFile("private.key") if err != nil { panic(err) } diff --git a/backend/utils/terminal/ws_local_session.go b/backend/utils/terminal/ws_local_session.go index 0ecbabb7f..d9221b6cc 100644 --- a/backend/utils/terminal/ws_local_session.go +++ b/backend/utils/terminal/ws_local_session.go @@ -52,11 +52,17 @@ func (sws *LocalWsSession) handleSlaveEvent(exitCh chan bool) { func (sws *LocalWsSession) masterWrite(data []byte) error { sws.writeMutex.Lock() defer sws.writeMutex.Unlock() - err := sws.wsConn.WriteMessage(websocket.TextMessage, data) + wsData, err := json.Marshal(WsMsg{ + Type: WsMsgCmd, + Data: base64.StdEncoding.EncodeToString(data), + }) + if err != nil { + return errors.Wrapf(err, "failed to encoding to json") + } + err = sws.wsConn.WriteMessage(websocket.TextMessage, wsData) if err != nil { return errors.Wrapf(err, "failed to write to master") } - return nil } @@ -74,21 +80,27 @@ func (sws *LocalWsSession) receiveWsMsg(exitCh chan bool) { global.LOG.Errorf("reading webSocket message failed, err: %v", err) return } - msgObj := wsMsg{} + msgObj := WsMsg{} _ = json.Unmarshal(wsData, &msgObj) switch msgObj.Type { - case wsMsgResize: + case WsMsgResize: if msgObj.Cols > 0 && msgObj.Rows > 0 { if err := sws.slave.ResizeTerminal(msgObj.Cols, msgObj.Rows); err != nil { global.LOG.Errorf("ssh pty change windows size failed, err: %v", err) } } - case wsMsgCmd: - decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + case WsMsgCmd: + decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Data) if err != nil { global.LOG.Errorf("websock cmd string base64 decoding failed, err: %v", err) } sws.sendWebsocketInputCommandToSshSessionStdinPipe(decodeBytes) + case WsMsgHeartbeat: + // 接收到心跳包后将心跳包原样返回,可以用于网络延迟检测等情况 + err = wsConn.WriteMessage(websocket.TextMessage, wsData) + if err != nil { + global.LOG.Errorf("ssh sending heartbeat to webSocket failed, err: %v", err) + } } } } diff --git a/backend/utils/terminal/ws_session.go b/backend/utils/terminal/ws_session.go index dde12a5dd..7c30c65ab 100644 --- a/backend/utils/terminal/ws_session.go +++ b/backend/utils/terminal/ws_session.go @@ -35,15 +35,17 @@ func (w *safeBuffer) Reset() { } const ( - wsMsgCmd = "cmd" - wsMsgResize = "resize" + WsMsgCmd = "cmd" + WsMsgResize = "resize" + WsMsgHeartbeat = "heartbeat" ) -type wsMsg struct { - Type string `json:"type"` - Cmd string `json:"cmd"` - Cols int `json:"cols"` - Rows int `json:"rows"` +type WsMsg struct { + Type string `json:"type"` + Data string `json:"data,omitempty"` // WsMsgCmd + Cols int `json:"cols,omitempty"` // WsMsgResize + Rows int `json:"rows,omitempty"` // WsMsgResize + Timestamp int `json:"timestamp,omitempty"` // WsMsgHeartbeat } type LogicSshWsSession struct { @@ -125,21 +127,27 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) { if err != nil { return } - msgObj := wsMsg{} + msgObj := WsMsg{} _ = json.Unmarshal(wsData, &msgObj) switch msgObj.Type { - case wsMsgResize: + case WsMsgResize: if msgObj.Cols > 0 && msgObj.Rows > 0 { if err := sws.session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil { global.LOG.Errorf("ssh pty change windows size failed, err: %v", err) } } - case wsMsgCmd: - decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd) + case WsMsgCmd: + decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Data) if err != nil { global.LOG.Errorf("websock cmd string base64 decoding failed, err: %v", err) } sws.sendWebsocketInputCommandToSshSessionStdinPipe(decodeBytes) + case WsMsgHeartbeat: + // 接收到心跳包后将心跳包原样返回,可以用于网络延迟检测等情况 + err = wsConn.WriteMessage(websocket.TextMessage, wsData) + if err != nil { + global.LOG.Errorf("ssh sending heartbeat to webSocket failed, err: %v", err) + } } } } @@ -164,8 +172,16 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { return } bs := sws.comboOutput.Bytes() - if string(bs) == string([]byte{13, 10, 108, 111, 103, 111, 117, 116, 13, 10}) { - err := wsConn.WriteMessage(websocket.TextMessage, bs) + if len(bs) > 0 { + wsData, err := json.Marshal(WsMsg{ + Type: WsMsgCmd, + Data: base64.StdEncoding.EncodeToString(bs), + }) + if err != nil { + global.LOG.Errorf("encoding combo output to json failed, err: %v", err) + continue + } + err = wsConn.WriteMessage(websocket.TextMessage, wsData) if err != nil { global.LOG.Errorf("ssh sending combo output to webSocket failed, err: %v", err) } @@ -174,20 +190,11 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) { global.LOG.Errorf("combo output to log buffer failed, err: %v", err) } sws.comboOutput.buffer.Reset() + } + if string(bs) == string([]byte{13, 10, 108, 111, 103, 111, 117, 116, 13, 10}) { sws.Close() return } - if len(bs) > 0 { - err := wsConn.WriteMessage(websocket.TextMessage, bs) - if err != nil { - global.LOG.Errorf("ssh sending combo output to webSocket failed, err: %v", err) - } - _, err = sws.logBuff.Write(bs) - if err != nil { - global.LOG.Errorf("combo output to log buffer failed, err: %v", err) - } - sws.comboOutput.buffer.Reset() - } case <-exitCh: return diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 5144d9f4d..e943bb767 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -62,7 +62,74 @@ var doc = `{ } } }, - "/apps/detail/:appId/:version": { + "/apps/checkupdate": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取应用更新版本", + "tags": [ + "App" + ], + "summary": "Get app list update", + "responses": { + "200": { + "description": "" + } + } + } + }, + "/apps/detail/:appId/:version/:type": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "通过 appid 获取应用详情", + "consumes": [ + "application/json" + ], + "tags": [ + "App" + ], + "summary": "Search app detail by appid", + "parameters": [ + { + "type": "integer", + "description": "app id", + "name": "appId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "app 版本", + "name": "version", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "app 类型", + "name": "version", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.AppDetailDTO" + } + } + } + } + }, + "/apps/details/:id": { "get": { "security": [ { @@ -76,21 +143,14 @@ var doc = `{ "tags": [ "App" ], - "summary": "Search app detail by id", + "summary": "Get app detail by id", "parameters": [ { "type": "integer", - "description": "app id", + "description": "id", "name": "appId", "in": "path", "required": true - }, - { - "type": "string", - "description": "app 版本", - "name": "version", - "in": "path", - "required": true } ], "responses": { @@ -266,6 +326,40 @@ var doc = `{ } } }, + "/apps/installed/conninfo/:key": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取应用连接信息", + "consumes": [ + "application/json" + ], + "tags": [ + "App" + ], + "summary": "Search app password by key", + "parameters": [ + { + "type": "string", + "description": "request", + "name": "key", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/apps/installed/delete/check/:appInstallId": { "get": { "security": [ @@ -300,40 +394,6 @@ var doc = `{ } } }, - "/apps/installed/loadpassword/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用密码", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app password by key", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "key", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/apps/installed/loadport/:key": { "get": { "security": [ @@ -470,6 +530,48 @@ var doc = `{ } } }, + "/apps/installed/params/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改应用参数", + "consumes": [ + "application/json" + ], + "tags": [ + "App" + ], + "summary": "Change app params", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AppInstalledUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "installId" + ], + "formatEN": "Application param update [installId]", + "formatZH": "应用参数修改 [installId]", + "paramKeys": [] + } + } + }, "/apps/installed/port/change": { "post": { "security": [ @@ -683,6 +785,20 @@ var doc = `{ } } }, + "/auth/demo": { + "get": { + "description": "判断是否为demo环境", + "tags": [ + "Auth" + ], + "summary": "Check System isDemo", + "responses": { + "200": { + "description": "" + } + } + } + }, "/auth/init": { "post": { "description": "初始化用户", @@ -970,6 +1086,48 @@ var doc = `{ } } }, + "/containers/compose/test": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "测试 compose 是否可用", + "consumes": [ + "application/json" + ], + "tags": [ + "Container Compose" + ], + "summary": "Test compose", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ComposeCreate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name" + ], + "formatEN": "check compose [name]", + "formatZH": "检测 compose [name] 格式", + "paramKeys": [] + } + } + }, "/containers/compose/update": { "post": { "security": [ @@ -2600,7 +2758,7 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" + "$ref": "#/definitions/dto.CronjobBatchDelete" } } ], @@ -2731,6 +2889,57 @@ var doc = `{ } } }, + "/cronjobs/records/clean": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "清空计划任务记录", + "consumes": [ + "application/json" + ], + "tags": [ + "Cronjob" + ], + "summary": "Clean job records", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CronjobClean" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "cronjobs", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "name", + "output_value": "name" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "clean cronjob [name] records", + "formatZH": "清空计划任务记录 [name]", + "paramKeys": [] + } + } + }, "/cronjobs/search": { "post": { "security": [ @@ -3899,6 +4108,34 @@ var doc = `{ } } }, + "/files/chunkupload": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "分片上传文件", + "tags": [ + "File" + ], + "summary": "ChunkUpload file", + "parameters": [ + { + "type": "file", + "description": "request", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/files/compress": { "post": { "security": [ @@ -4112,6 +4349,48 @@ var doc = `{ } } }, + "/files/download/bypath": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "下载指定文件", + "consumes": [ + "application/json" + ], + "tags": [ + "File" + ], + "summary": "Download file with path", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.FilePath" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "path" + ], + "formatEN": "Download file [path]", + "formatZH": "下载文件 [path]", + "paramKeys": [] + } + } + }, "/files/loadfile": { "post": { "security": [ @@ -4559,6 +4838,187 @@ var doc = `{ } } }, + "/groups": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "创建系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "Create group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.GroupCreate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name", + "type" + ], + "formatEN": "create group [name][type]", + "formatZH": "创建组 [name][type]", + "paramKeys": [] + } + } + }, + "/groups/del": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "删除系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "Delete group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "groups", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "name", + "output_value": "name" + }, + { + "db": "groups", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "type", + "output_value": "type" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "delete group [type][name]", + "formatZH": "删除组 [type][name]", + "paramKeys": [] + } + } + }, + "/groups/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "查询系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "List groups", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.GroupSearch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "anrry" + } + } + } + } + }, + "/groups/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "Update group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.GroupUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name", + "type" + ], + "formatEN": "update group [name][type]", + "formatZH": "更新组 [name][type]", + "paramKeys": [] + } + } + }, "/hosts": { "post": { "security": [ @@ -4879,19 +5339,41 @@ var doc = `{ } } }, - "/hosts/group": { + "/hosts/firewall/base": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取防火墙基础信息", + "tags": [ + "Firewall" + ], + "summary": "Load firewall base info", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.FirewallBaseInfo" + } + } + } + } + }, + "/hosts/firewall/ip": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "创建系统组", + "description": "批量删除防火墙规则", "consumes": [ "application/json" ], "tags": [ - "System Group" + "Firewall" ], "summary": "Create group", "parameters": [ @@ -4901,7 +5383,7 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.GroupCreate" + "$ref": "#/definitions/dto.BatchRuleOperate" } } ], @@ -4909,34 +5391,24 @@ var doc = `{ "200": { "description": "" } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create group [name][type]", - "formatZH": "创建组 [name][type]", - "paramKeys": [] } } }, - "/hosts/group/del": { + "/hosts/firewall/operate": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "删除系统组", + "description": "修改防火墙状态", "consumes": [ "application/json" ], "tags": [ - "System Group" + "Firewall" ], - "summary": "Delete group", + "summary": "Page firewall status", "parameters": [ { "description": "request", @@ -4944,66 +5416,7 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [ - { - "db": "groups", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "name", - "output_value": "name" - }, - { - "db": "groups", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "type", - "output_value": "type" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete group [type][name]", - "formatZH": "删除组 [type][name]", - "paramKeys": [] - } - } - }, - "/hosts/group/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "查询系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "List groups", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupSearch" + "$ref": "#/definitions/dto.FirewallOperation" } } ], @@ -5011,27 +5424,36 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "anrry" + "$ref": "#/definitions/dto.PageResult" } } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "operation" + ], + "formatEN": "[operation] firewall", + "formatZH": "[operation] 防火墙", + "paramKeys": [] } } }, - "/hosts/group/update": { + "/hosts/firewall/port": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "更新系统组", + "description": "创建防火墙端口规则", "consumes": [ "application/json" ], "tags": [ - "System Group" + "Firewall" ], - "summary": "Update group", + "summary": "Create group", "parameters": [ { "description": "request", @@ -5039,7 +5461,7 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.GroupUpdate" + "$ref": "#/definitions/dto.PortRuleOperate" } } ], @@ -5051,15 +5473,117 @@ var doc = `{ "x-panel-log": { "BeforeFuntions": [], "bodyKeys": [ - "name", - "type" + "port", + "strategy" ], - "formatEN": "update group [name][type]", - "formatZH": "更新组 [name][type]", + "formatEN": "create port rules [strategy][port]", + "formatZH": "添加端口规则 [strategy] [port]", "paramKeys": [] } } }, + "/hosts/firewall/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取防火墙规则列表分页", + "consumes": [ + "application/json" + ], + "tags": [ + "Firewall" + ], + "summary": "Page firewall rules", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SearchWithPage" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.PageResult" + } + } + } + } + }, + "/hosts/firewall/update/ip": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 ip 防火墙规则", + "consumes": [ + "application/json" + ], + "tags": [ + "Firewall" + ], + "summary": "Create group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddrRuleUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/hosts/firewall/update/port": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新端口防火墙规则", + "consumes": [ + "application/json" + ], + "tags": [ + "Firewall" + ], + "summary": "Create group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.PortRuleUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/hosts/search": { "post": { "security": [ @@ -5200,6 +5724,49 @@ var doc = `{ } }, "/hosts/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新主机", + "consumes": [ + "application/json" + ], + "tags": [ + "Host" + ], + "summary": "Update host", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.HostOperate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name", + "addr" + ], + "formatEN": "update host [name][addr]", + "formatZH": "更新主机信息 [name][addr]", + "paramKeys": [] + } + } + }, + "/hosts/update/group": { "post": { "security": [ { @@ -5539,6 +6106,196 @@ var doc = `{ } } }, + "/runtimes": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "创建运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "Create runtime", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeCreate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name" + ], + "formatEN": "Create runtime [name]", + "formatZH": "创建运行环境 [name]", + "paramKeys": [] + } + } + }, + "/runtimes/:id": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "Get runtime", + "parameters": [ + { + "type": "string", + "description": "request", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/runtimes/del": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "删除运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Delete runtime", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeDelete" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "id" + ], + "formatEN": "Delete website [name]", + "formatZH": "删除网站 [name]", + "paramKeys": [] + } + } + }, + "/runtimes/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取运行环境列表", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "List runtimes", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeSearch" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/runtimes/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "Update runtime", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name" + ], + "formatEN": "Update runtime [name]", + "formatZH": "更新运行环境 [name]", + "paramKeys": [] + } + } + }, "/settings/backup": { "post": { "security": [ @@ -5661,14 +6418,14 @@ var doc = `{ { "db": "backup_accounts", "input_colume": "id", - "input_value": "ids", + "input_value": "id", "isList": true, "output_colume": "type", "output_value": "types" } ], "bodyKeys": [ - "ids" + "id" ], "formatEN": "delete backup account [types]", "formatZH": "删除备份账号 [types]", @@ -6706,17 +7463,28 @@ var doc = `{ "ApiKeyAuth": [] } ], - "description": "系统更新信息", + "description": "获取版本 release notes", + "consumes": [ + "application/json" + ], "tags": [ "System Setting" ], - "summary": "Load upgrade info", + "summary": "Load release notes by version", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.Upgrade" + } + } + ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.UpgradeInfo" - } + "description": "" } } }, @@ -6837,6 +7605,40 @@ var doc = `{ } } }, + "/websites/:id/config/:type": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "通过 id 查询网站 nginx", + "consumes": [ + "application/json" + ], + "tags": [ + "Website Nginx" + ], + "summary": "Search website nginx by id", + "parameters": [ + { + "type": "integer", + "description": "request", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.FileInfo" + } + } + } + } + }, "/websites/:id/https": { "get": { "security": [ @@ -6923,40 +7725,6 @@ var doc = `{ } } }, - "/websites/:id/nginx": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询网站 nginx", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Search website nginx by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, "/websites/acme": { "post": { "security": [ @@ -7315,6 +8083,57 @@ var doc = `{ } } }, + "/websites/dir/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新网站目录", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Update Site Dir", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsiteUpdateDir" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "Update domain [domain] dir", + "formatZH": "更新网站 [domain] 目录", + "paramKeys": [] + } + } + }, "/websites/dns": { "post": { "security": [ @@ -7616,161 +8435,6 @@ var doc = `{ } } }, - "/websites/groups": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站组", - "tags": [ - "Website Group" - ], - "summary": "List website groups", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "anrry" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站组", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Group" - ], - "summary": "Create website group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteGroupCreate" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create website groups [name]", - "formatZH": "创建网站组 [name]", - "paramKeys": [] - } - } - }, - "/websites/groups/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站组", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Group" - ], - "summary": "Delete website group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [ - { - "db": "website_groups", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website group [name]", - "formatZH": "删除网站组 [name]", - "paramKeys": [] - } - } - }, - "/websites/groups/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站组", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Group" - ], - "summary": "Update website group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteGroupUpdate" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Update website groups [name]", - "formatZH": "更新网站组 [name]", - "paramKeys": [] - } - } - }, "/websites/list": { "get": { "security": [ @@ -7973,6 +8637,226 @@ var doc = `{ } } }, + "/websites/php/config": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 网站 PHP 配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website PHP" + ], + "summary": "Update website php conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsitePHPConfigUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "[domain] PHP conf update", + "formatZH": "[domain] PHP 配置修改", + "paramKeys": [] + } + } + }, + "/websites/php/config/:id": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取网站 php 配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Load websit php conf", + "parameters": [ + { + "type": "integer", + "description": "request", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.PHPConfig" + } + } + } + } + }, + "/websites/php/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 php 配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website PHP" + ], + "summary": "Update php conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsitePHPFileUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "websiteId", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "websiteId" + ], + "formatEN": "Nginx conf update [domain]", + "formatZH": "php 配置修改 [domain]", + "paramKeys": [] + } + } + }, + "/websites/rewrite": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取伪静态配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Get rewrite conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.NginxRewriteReq" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/websites/rewrite/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新伪静态配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Update rewrite conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.NginxRewriteUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "websiteID", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "websiteID" + ], + "formatEN": "Nginx conf rewrite update [domain]", + "formatZH": "伪静态配置修改 [domain]", + "paramKeys": [] + } + } + }, "/websites/search": { "post": { "security": [ @@ -8256,6 +9140,57 @@ var doc = `{ } } }, + "/websites/ssl/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 ssl", + "consumes": [ + "application/json" + ], + "tags": [ + "Website SSL" + ], + "summary": "Update ssl", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsiteSSLUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "website_ssls", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "Update ssl config [domain]", + "formatZH": "更新证书设置 [domain]", + "paramKeys": [] + } + } + }, "/websites/ssl/website/:websiteId": { "get": { "security": [ @@ -8418,6 +9353,44 @@ var doc = `{ } }, "definitions": { + "dto.AddrRuleOperate": { + "type": "object", + "required": [ + "address", + "operation", + "strategy" + ], + "properties": { + "address": { + "type": "string" + }, + "operation": { + "type": "string", + "enum": [ + "add", + "remove" + ] + }, + "strategy": { + "type": "string", + "enum": [ + "accept", + "drop" + ] + } + } + }, + "dto.AddrRuleUpdate": { + "type": "object", + "properties": { + "newRule": { + "$ref": "#/definitions/dto.AddrRuleOperate" + }, + "oldRule": { + "$ref": "#/definitions/dto.AddrRuleOperate" + } + } + }, "dto.BackupOperate": { "type": "object", "required": [ @@ -8484,6 +9457,23 @@ var doc = `{ } } }, + "dto.BatchRuleOperate": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "rules": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.PortRuleOperate" + } + }, + "type": { + "type": "string" + } + } + }, "dto.CaptchaResponse": { "type": "object", "properties": { @@ -8623,8 +9613,7 @@ var doc = `{ "dto.ComposeCreate": { "type": "object", "required": [ - "from", - "name" + "from" ], "properties": { "file": { @@ -8851,6 +9840,34 @@ var doc = `{ } } }, + "dto.CronjobBatchDelete": { + "type": "object", + "properties": { + "cleanData": { + "type": "boolean" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.CronjobClean": { + "type": "object", + "required": [ + "cronjobID" + ], + "properties": { + "cleanData": { + "type": "boolean" + }, + "cronjobID": { + "type": "integer" + } + } + }, "dto.CronjobCreate": { "type": "object", "required": [ @@ -8860,9 +9877,7 @@ var doc = `{ ], "properties": { "day": { - "type": "integer", - "maximum": 31, - "minimum": 1 + "type": "integer" }, "dbName": { "type": "string" @@ -8871,17 +9886,13 @@ var doc = `{ "type": "string" }, "hour": { - "type": "integer", - "maximum": 23, - "minimum": 0 + "type": "integer" }, "keepLocal": { "type": "boolean" }, "minute": { - "type": "integer", - "maximum": 59, - "minimum": 0 + "type": "integer" }, "name": { "type": "string" @@ -8942,9 +9953,7 @@ var doc = `{ ], "properties": { "day": { - "type": "integer", - "maximum": 31, - "minimum": 1 + "type": "integer" }, "dbName": { "type": "string" @@ -8953,9 +9962,7 @@ var doc = `{ "type": "string" }, "hour": { - "type": "integer", - "maximum": 23, - "minimum": 0 + "type": "integer" }, "id": { "type": "integer" @@ -8964,9 +9971,7 @@ var doc = `{ "type": "boolean" }, "minute": { - "type": "integer", - "maximum": 59, - "minimum": 0 + "type": "integer" }, "name": { "type": "string" @@ -9041,6 +10046,12 @@ var doc = `{ "type": "string" } }, + "iptables": { + "type": "boolean" + }, + "isSwarm": { + "type": "boolean" + }, "liveRestore": { "type": "boolean" }, @@ -9060,15 +10071,9 @@ var doc = `{ }, "dto.DaemonJsonUpdateByFile": { "type": "object", - "required": [ - "path" - ], "properties": { "file": { "type": "string" - }, - "path": { - "type": "string" } } }, @@ -9096,33 +10101,15 @@ var doc = `{ "databaseNumber": { "type": "integer" }, - "dateeaseID": { - "type": "integer" - }, - "haloID": { - "type": "integer" - }, "hostname": { "type": "string" }, - "jumpserverID": { - "type": "integer" - }, "kernelArch": { "type": "string" }, "kernelVersion": { "type": "string" }, - "kubeoperatorID": { - "type": "integer" - }, - "kubepiID": { - "type": "integer" - }, - "metersphereID": { - "type": "integer" - }, "os": { "type": "string" }, @@ -9164,20 +10151,11 @@ var doc = `{ "cpuUsedPercent": { "type": "number" }, - "free": { - "type": "integer" - }, - "inodesFree": { - "type": "integer" - }, - "inodesTotal": { - "type": "integer" - }, - "inodesUsed": { - "type": "integer" - }, - "inodesUsedPercent": { - "type": "number" + "diskData": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.DiskInfo" + } }, "ioCount": { "type": "integer" @@ -9185,12 +10163,15 @@ var doc = `{ "ioReadBytes": { "type": "integer" }, - "ioTime": { + "ioReadTime": { "type": "integer" }, "ioWriteBytes": { "type": "integer" }, + "ioWriteTime": { + "type": "integer" + }, "load1": { "type": "number" }, @@ -9227,11 +10208,40 @@ var doc = `{ "timeSinceUptime": { "type": "string" }, + "uptime": { + "type": "integer" + } + } + }, + "dto.DiskInfo": { + "type": "object", + "properties": { + "device": { + "type": "string" + }, + "free": { + "type": "integer" + }, + "inodesFree": { + "type": "integer" + }, + "inodesTotal": { + "type": "integer" + }, + "inodesUsed": { + "type": "integer" + }, + "inodesUsedPercent": { + "type": "number" + }, + "path": { + "type": "string" + }, "total": { "type": "integer" }, - "uptime": { - "type": "integer" + "type": { + "type": "string" }, "used": { "type": "integer" @@ -9254,6 +10264,12 @@ var doc = `{ "restart", "stop" ] + }, + "stopService": { + "type": "boolean" + }, + "stopSocket": { + "type": "boolean" } } }, @@ -9278,7 +10294,9 @@ var doc = `{ "S3", "SFTP", "MINIO", - "LOCAL" + "LOCAL", + "COS", + "KODO" ] } } @@ -9294,6 +10312,40 @@ var doc = `{ } } }, + "dto.FirewallBaseInfo": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pingStatus": { + "type": "string" + }, + "status": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.FirewallOperation": { + "type": "object", + "required": [ + "operation" + ], + "properties": { + "operation": { + "type": "string", + "enum": [ + "start", + "stop", + "disablePing", + "enablePing" + ] + } + } + }, "dto.ForBuckets": { "type": "object", "required": [ @@ -9347,6 +10399,9 @@ var doc = `{ }, "dto.GroupUpdate": { "type": "object", + "required": [ + "type" + ], "properties": { "id": { "type": "integer" @@ -9356,6 +10411,9 @@ var doc = `{ }, "name": { "type": "string" + }, + "type": { + "type": "string" } } }, @@ -9377,6 +10435,9 @@ var doc = `{ "key" ] }, + "passPhrase": { + "type": "string" + }, "password": { "type": "string" }, @@ -9420,9 +10481,21 @@ var doc = `{ "name": { "type": "string" }, + "passPhrase": { + "type": "string" + }, + "password": { + "type": "string" + }, "port": { "type": "integer" }, + "privateKey": { + "type": "string" + }, + "rememberPassword": { + "type": "boolean" + }, "user": { "type": "string" } @@ -9458,6 +10531,9 @@ var doc = `{ "name": { "type": "string" }, + "passPhrase": { + "type": "string" + }, "password": { "type": "string" }, @@ -9469,6 +10545,9 @@ var doc = `{ "privateKey": { "type": "string" }, + "rememberPassword": { + "type": "boolean" + }, "user": { "type": "string" } @@ -9677,9 +10756,6 @@ var doc = `{ }, "password": { "type": "string" - }, - "secret": { - "type": "string" } } }, @@ -10053,6 +11129,56 @@ var doc = `{ } } }, + "dto.PortRuleOperate": { + "type": "object", + "required": [ + "operation", + "port", + "protocol", + "strategy" + ], + "properties": { + "address": { + "type": "string" + }, + "operation": { + "type": "string", + "enum": [ + "add", + "remove" + ] + }, + "port": { + "type": "string" + }, + "protocol": { + "type": "string", + "enum": [ + "tcp", + "udp", + "tcp/udp" + ] + }, + "strategy": { + "type": "string", + "enum": [ + "accept", + "drop" + ] + } + } + }, + "dto.PortRuleUpdate": { + "type": "object", + "properties": { + "newRule": { + "$ref": "#/definitions/dto.PortRuleOperate" + }, + "oldRule": { + "$ref": "#/definitions/dto.PortRuleOperate" + } + } + }, "dto.PortUpdate": { "type": "object", "required": [ @@ -10447,7 +11573,9 @@ var doc = `{ "OSS", "S3", "SFTP", - "MINIO" + "MINIO", + "COS", + "KODO" ] } } @@ -10511,6 +11639,9 @@ var doc = `{ "dto.UpgradeInfo": { "type": "object", "properties": { + "latestVersion": { + "type": "string" + }, "newVersion": { "type": "string" }, @@ -10522,9 +11653,6 @@ var doc = `{ "dto.UserLoginInfo": { "type": "object", "properties": { - "mfaSecret": { - "type": "string" - }, "mfaStatus": { "type": "string" }, @@ -10682,6 +11810,9 @@ var doc = `{ "required": { "type": "string" }, + "resource": { + "type": "string" + }, "shortDescEn": { "type": "string" }, @@ -10826,9 +11957,21 @@ var doc = `{ "proxy": { "type": "string" }, + "proxyType": { + "type": "string" + }, "remark": { "type": "string" }, + "rewrite": { + "type": "string" + }, + "runtimeID": { + "type": "integer" + }, + "siteDir": { + "type": "string" + }, "status": { "type": "string" }, @@ -11042,6 +12185,22 @@ var doc = `{ } } }, + "request.AppInstalledUpdate": { + "type": "object", + "required": [ + "installId", + "params" + ], + "properties": { + "installId": { + "type": "integer" + }, + "params": { + "type": "object", + "additionalProperties": true + } + } + }, "request.AppSearch": { "type": "object", "required": [ @@ -11381,6 +12540,40 @@ var doc = `{ } } }, + "request.NginxRewriteReq": { + "type": "object", + "required": [ + "name", + "websiteId" + ], + "properties": { + "name": { + "type": "string" + }, + "websiteId": { + "type": "integer" + } + } + }, + "request.NginxRewriteUpdate": { + "type": "object", + "required": [ + "content", + "name", + "websiteId" + ], + "properties": { + "content": { + "type": "string" + }, + "name": { + "type": "string" + }, + "websiteId": { + "type": "integer" + } + } + }, "request.NginxScopeReq": { "type": "object", "required": [ @@ -11409,6 +12602,86 @@ var doc = `{ } } }, + "request.RuntimeCreate": { + "type": "object", + "properties": { + "appDetailId": { + "type": "integer" + }, + "image": { + "type": "string" + }, + "name": { + "type": "string" + }, + "params": { + "type": "object", + "additionalProperties": true + }, + "resource": { + "type": "string" + }, + "type": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "request.RuntimeDelete": { + "type": "object", + "properties": { + "id": { + "type": "integer" + } + } + }, + "request.RuntimeSearch": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "name": { + "type": "string" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "request.RuntimeUpdate": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image": { + "type": "string" + }, + "name": { + "type": "string" + }, + "params": { + "type": "object", + "additionalProperties": true + }, + "version": { + "type": "string" + } + } + }, "request.SearchUploadWithPage": { "type": "object", "required": [ @@ -11470,15 +12743,24 @@ var doc = `{ "otherDomains": { "type": "string" }, + "port": { + "type": "integer" + }, "primaryDomain": { "type": "string" }, "proxy": { "type": "string" }, + "proxyType": { + "type": "string" + }, "remark": { "type": "string" }, + "runtimeID": { + "type": "integer" + }, "type": { "type": "string" }, @@ -11614,34 +12896,6 @@ var doc = `{ } } }, - "request.WebsiteGroupCreate": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - } - } - }, - "request.WebsiteGroupUpdate": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "default": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, "request.WebsiteHTTPSOp": { "type": "object", "required": [ @@ -11753,6 +13007,43 @@ var doc = `{ } } }, + "request.WebsitePHPConfigUpdate": { + "type": "object", + "required": [ + "id", + "params" + ], + "properties": { + "id": { + "type": "integer" + }, + "params": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "request.WebsitePHPFileUpdate": { + "type": "object", + "required": [ + "content", + "id", + "type" + ], + "properties": { + "content": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, "request.WebsiteResourceReq": { "type": "object", "required": [ @@ -11819,6 +13110,21 @@ var doc = `{ } } }, + "request.WebsiteSSLUpdate": { + "type": "object", + "required": [ + "autoRenew", + "id" + ], + "properties": { + "autoRenew": { + "type": "boolean" + }, + "id": { + "type": "integer" + } + } + }, "request.WebsiteSearch": { "type": "object", "required": [ @@ -11865,6 +13171,21 @@ var doc = `{ } } }, + "request.WebsiteUpdateDir": { + "type": "object", + "required": [ + "id", + "siteDir" + ], + "properties": { + "id": { + "type": "integer" + }, + "siteDir": { + "type": "string" + } + } + }, "request.WebsiteWafReq": { "type": "object", "required": [ @@ -11939,6 +13260,9 @@ var doc = `{ "required": { "type": "string" }, + "resource": { + "type": "string" + }, "shortDescEn": { "type": "string" }, @@ -11986,6 +13310,9 @@ var doc = `{ "id": { "type": "integer" }, + "image": { + "type": "string" + }, "lastVersion": { "type": "string" }, @@ -12042,10 +13369,35 @@ var doc = `{ "response.AppParam": { "type": "object", "properties": { - "label": { + "edit": { + "type": "boolean" + }, + "key": { "type": "string" }, - "value": {} + "labelEn": { + "type": "string" + }, + "labelZh": { + "type": "string" + }, + "multiple": { + "type": "boolean" + }, + "required": { + "type": "boolean" + }, + "rule": { + "type": "string" + }, + "showValue": { + "type": "string" + }, + "type": { + "type": "string" + }, + "value": {}, + "values": {} } }, "response.FileInfo": { @@ -12150,6 +13502,17 @@ var doc = `{ } } }, + "response.PHPConfig": { + "type": "object", + "properties": { + "params": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, "response.WebsiteAcmeAccountDTO": { "type": "object", "properties": { @@ -12185,6 +13548,9 @@ var doc = `{ "appInstallId": { "type": "integer" }, + "appName": { + "type": "string" + }, "createdAt": { "type": "string" }, @@ -12221,9 +13587,24 @@ var doc = `{ "proxy": { "type": "string" }, + "proxyType": { + "type": "string" + }, "remark": { "type": "string" }, + "rewrite": { + "type": "string" + }, + "runtimeID": { + "type": "integer" + }, + "runtimeName": { + "type": "string" + }, + "siteDir": { + "type": "string" + }, "sitePath": { "type": "string" }, diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 62a61e568..e30d0ebfe 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -48,7 +48,74 @@ } } }, - "/apps/detail/:appId/:version": { + "/apps/checkupdate": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取应用更新版本", + "tags": [ + "App" + ], + "summary": "Get app list update", + "responses": { + "200": { + "description": "" + } + } + } + }, + "/apps/detail/:appId/:version/:type": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "通过 appid 获取应用详情", + "consumes": [ + "application/json" + ], + "tags": [ + "App" + ], + "summary": "Search app detail by appid", + "parameters": [ + { + "type": "integer", + "description": "app id", + "name": "appId", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "app 版本", + "name": "version", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "app 类型", + "name": "version", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.AppDetailDTO" + } + } + } + } + }, + "/apps/details/:id": { "get": { "security": [ { @@ -62,21 +129,14 @@ "tags": [ "App" ], - "summary": "Search app detail by id", + "summary": "Get app detail by id", "parameters": [ { "type": "integer", - "description": "app id", + "description": "id", "name": "appId", "in": "path", "required": true - }, - { - "type": "string", - "description": "app 版本", - "name": "version", - "in": "path", - "required": true } ], "responses": { @@ -252,6 +312,40 @@ } } }, + "/apps/installed/conninfo/:key": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取应用连接信息", + "consumes": [ + "application/json" + ], + "tags": [ + "App" + ], + "summary": "Search app password by key", + "parameters": [ + { + "type": "string", + "description": "request", + "name": "key", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/apps/installed/delete/check/:appInstallId": { "get": { "security": [ @@ -286,40 +380,6 @@ } } }, - "/apps/installed/loadpassword/:key": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取应用密码", - "consumes": [ - "application/json" - ], - "tags": [ - "App" - ], - "summary": "Search app password by key", - "parameters": [ - { - "type": "string", - "description": "request", - "name": "key", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - } - } - }, "/apps/installed/loadport/:key": { "get": { "security": [ @@ -456,6 +516,48 @@ } } }, + "/apps/installed/params/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改应用参数", + "consumes": [ + "application/json" + ], + "tags": [ + "App" + ], + "summary": "Change app params", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AppInstalledUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "installId" + ], + "formatEN": "Application param update [installId]", + "formatZH": "应用参数修改 [installId]", + "paramKeys": [] + } + } + }, "/apps/installed/port/change": { "post": { "security": [ @@ -669,6 +771,20 @@ } } }, + "/auth/demo": { + "get": { + "description": "判断是否为demo环境", + "tags": [ + "Auth" + ], + "summary": "Check System isDemo", + "responses": { + "200": { + "description": "" + } + } + } + }, "/auth/init": { "post": { "description": "初始化用户", @@ -956,6 +1072,48 @@ } } }, + "/containers/compose/test": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "测试 compose 是否可用", + "consumes": [ + "application/json" + ], + "tags": [ + "Container Compose" + ], + "summary": "Test compose", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ComposeCreate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name" + ], + "formatEN": "check compose [name]", + "formatZH": "检测 compose [name] 格式", + "paramKeys": [] + } + } + }, "/containers/compose/update": { "post": { "security": [ @@ -2586,7 +2744,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.BatchDeleteReq" + "$ref": "#/definitions/dto.CronjobBatchDelete" } } ], @@ -2717,6 +2875,57 @@ } } }, + "/cronjobs/records/clean": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "清空计划任务记录", + "consumes": [ + "application/json" + ], + "tags": [ + "Cronjob" + ], + "summary": "Clean job records", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CronjobClean" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "cronjobs", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "name", + "output_value": "name" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "clean cronjob [name] records", + "formatZH": "清空计划任务记录 [name]", + "paramKeys": [] + } + } + }, "/cronjobs/search": { "post": { "security": [ @@ -3885,6 +4094,34 @@ } } }, + "/files/chunkupload": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "分片上传文件", + "tags": [ + "File" + ], + "summary": "ChunkUpload file", + "parameters": [ + { + "type": "file", + "description": "request", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/files/compress": { "post": { "security": [ @@ -4098,6 +4335,48 @@ } } }, + "/files/download/bypath": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "下载指定文件", + "consumes": [ + "application/json" + ], + "tags": [ + "File" + ], + "summary": "Download file with path", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.FilePath" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "path" + ], + "formatEN": "Download file [path]", + "formatZH": "下载文件 [path]", + "paramKeys": [] + } + } + }, "/files/loadfile": { "post": { "security": [ @@ -4545,6 +4824,187 @@ } } }, + "/groups": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "创建系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "Create group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.GroupCreate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name", + "type" + ], + "formatEN": "create group [name][type]", + "formatZH": "创建组 [name][type]", + "paramKeys": [] + } + } + }, + "/groups/del": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "删除系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "Delete group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "groups", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "name", + "output_value": "name" + }, + { + "db": "groups", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "type", + "output_value": "type" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "delete group [type][name]", + "formatZH": "删除组 [type][name]", + "paramKeys": [] + } + } + }, + "/groups/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "查询系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "List groups", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.GroupSearch" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "anrry" + } + } + } + } + }, + "/groups/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新系统组", + "consumes": [ + "application/json" + ], + "tags": [ + "System Group" + ], + "summary": "Update group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.GroupUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name", + "type" + ], + "formatEN": "update group [name][type]", + "formatZH": "更新组 [name][type]", + "paramKeys": [] + } + } + }, "/hosts": { "post": { "security": [ @@ -4865,19 +5325,41 @@ } } }, - "/hosts/group": { + "/hosts/firewall/base": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取防火墙基础信息", + "tags": [ + "Firewall" + ], + "summary": "Load firewall base info", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.FirewallBaseInfo" + } + } + } + } + }, + "/hosts/firewall/ip": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "创建系统组", + "description": "批量删除防火墙规则", "consumes": [ "application/json" ], "tags": [ - "System Group" + "Firewall" ], "summary": "Create group", "parameters": [ @@ -4887,7 +5369,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.GroupCreate" + "$ref": "#/definitions/dto.BatchRuleOperate" } } ], @@ -4895,34 +5377,24 @@ "200": { "description": "" } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create group [name][type]", - "formatZH": "创建组 [name][type]", - "paramKeys": [] } } }, - "/hosts/group/del": { + "/hosts/firewall/operate": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "删除系统组", + "description": "修改防火墙状态", "consumes": [ "application/json" ], "tags": [ - "System Group" + "Firewall" ], - "summary": "Delete group", + "summary": "Page firewall status", "parameters": [ { "description": "request", @@ -4930,66 +5402,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [ - { - "db": "groups", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "name", - "output_value": "name" - }, - { - "db": "groups", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "type", - "output_value": "type" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "delete group [type][name]", - "formatZH": "删除组 [type][name]", - "paramKeys": [] - } - } - }, - "/hosts/group/search": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "查询系统组", - "consumes": [ - "application/json" - ], - "tags": [ - "System Group" - ], - "summary": "List groups", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.GroupSearch" + "$ref": "#/definitions/dto.FirewallOperation" } } ], @@ -4997,27 +5410,36 @@ "200": { "description": "OK", "schema": { - "type": "anrry" + "$ref": "#/definitions/dto.PageResult" } } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "operation" + ], + "formatEN": "[operation] firewall", + "formatZH": "[operation] 防火墙", + "paramKeys": [] } } }, - "/hosts/group/update": { + "/hosts/firewall/port": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "更新系统组", + "description": "创建防火墙端口规则", "consumes": [ "application/json" ], "tags": [ - "System Group" + "Firewall" ], - "summary": "Update group", + "summary": "Create group", "parameters": [ { "description": "request", @@ -5025,7 +5447,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.GroupUpdate" + "$ref": "#/definitions/dto.PortRuleOperate" } } ], @@ -5037,15 +5459,117 @@ "x-panel-log": { "BeforeFuntions": [], "bodyKeys": [ - "name", - "type" + "port", + "strategy" ], - "formatEN": "update group [name][type]", - "formatZH": "更新组 [name][type]", + "formatEN": "create port rules [strategy][port]", + "formatZH": "添加端口规则 [strategy] [port]", "paramKeys": [] } } }, + "/hosts/firewall/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取防火墙规则列表分页", + "consumes": [ + "application/json" + ], + "tags": [ + "Firewall" + ], + "summary": "Page firewall rules", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SearchWithPage" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.PageResult" + } + } + } + } + }, + "/hosts/firewall/update/ip": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 ip 防火墙规则", + "consumes": [ + "application/json" + ], + "tags": [ + "Firewall" + ], + "summary": "Create group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.AddrRuleUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/hosts/firewall/update/port": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新端口防火墙规则", + "consumes": [ + "application/json" + ], + "tags": [ + "Firewall" + ], + "summary": "Create group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.PortRuleUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/hosts/search": { "post": { "security": [ @@ -5186,6 +5710,49 @@ } }, "/hosts/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新主机", + "consumes": [ + "application/json" + ], + "tags": [ + "Host" + ], + "summary": "Update host", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.HostOperate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name", + "addr" + ], + "formatEN": "update host [name][addr]", + "formatZH": "更新主机信息 [name][addr]", + "paramKeys": [] + } + } + }, + "/hosts/update/group": { "post": { "security": [ { @@ -5525,6 +6092,196 @@ } } }, + "/runtimes": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "创建运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "Create runtime", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeCreate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name" + ], + "formatEN": "Create runtime [name]", + "formatZH": "创建运行环境 [name]", + "paramKeys": [] + } + } + }, + "/runtimes/:id": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "Get runtime", + "parameters": [ + { + "type": "string", + "description": "request", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/runtimes/del": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "删除运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Delete runtime", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeDelete" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "id" + ], + "formatEN": "Delete website [name]", + "formatZH": "删除网站 [name]", + "paramKeys": [] + } + } + }, + "/runtimes/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取运行环境列表", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "List runtimes", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeSearch" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/runtimes/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新运行环境", + "consumes": [ + "application/json" + ], + "tags": [ + "Runtime" + ], + "summary": "Update runtime", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.RuntimeUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "name" + ], + "formatEN": "Update runtime [name]", + "formatZH": "更新运行环境 [name]", + "paramKeys": [] + } + } + }, "/settings/backup": { "post": { "security": [ @@ -5647,14 +6404,14 @@ { "db": "backup_accounts", "input_colume": "id", - "input_value": "ids", + "input_value": "id", "isList": true, "output_colume": "type", "output_value": "types" } ], "bodyKeys": [ - "ids" + "id" ], "formatEN": "delete backup account [types]", "formatZH": "删除备份账号 [types]", @@ -6692,17 +7449,28 @@ "ApiKeyAuth": [] } ], - "description": "系统更新信息", + "description": "获取版本 release notes", + "consumes": [ + "application/json" + ], "tags": [ "System Setting" ], - "summary": "Load upgrade info", + "summary": "Load release notes by version", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.Upgrade" + } + } + ], "responses": { "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/dto.UpgradeInfo" - } + "description": "" } } }, @@ -6823,6 +7591,40 @@ } } }, + "/websites/:id/config/:type": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "通过 id 查询网站 nginx", + "consumes": [ + "application/json" + ], + "tags": [ + "Website Nginx" + ], + "summary": "Search website nginx by id", + "parameters": [ + { + "type": "integer", + "description": "request", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.FileInfo" + } + } + } + } + }, "/websites/:id/https": { "get": { "security": [ @@ -6909,40 +7711,6 @@ } } }, - "/websites/:id/nginx": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "通过 id 查询网站 nginx", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Nginx" - ], - "summary": "Search website nginx by id", - "parameters": [ - { - "type": "integer", - "description": "request", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/response.FileInfo" - } - } - } - } - }, "/websites/acme": { "post": { "security": [ @@ -7301,6 +8069,57 @@ } } }, + "/websites/dir/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新网站目录", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Update Site Dir", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsiteUpdateDir" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "Update domain [domain] dir", + "formatZH": "更新网站 [domain] 目录", + "paramKeys": [] + } + } + }, "/websites/dns": { "post": { "security": [ @@ -7602,161 +8421,6 @@ } } }, - "/websites/groups": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取网站组", - "tags": [ - "Website Group" - ], - "summary": "List website groups", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "anrry" - } - } - } - }, - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "创建网站组", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Group" - ], - "summary": "Create website group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteGroupCreate" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Create website groups [name]", - "formatZH": "创建网站组 [name]", - "paramKeys": [] - } - } - }, - "/websites/groups/del": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "删除网站组", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Group" - ], - "summary": "Delete website group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [ - { - "db": "website_groups", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "name", - "output_value": "name" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Delete website group [name]", - "formatZH": "删除网站组 [name]", - "paramKeys": [] - } - } - }, - "/websites/groups/update": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "更新网站组", - "consumes": [ - "application/json" - ], - "tags": [ - "Website Group" - ], - "summary": "Update website group", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteGroupUpdate" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name" - ], - "formatEN": "Update website groups [name]", - "formatZH": "更新网站组 [name]", - "paramKeys": [] - } - } - }, "/websites/list": { "get": { "security": [ @@ -7959,6 +8623,226 @@ } } }, + "/websites/php/config": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 网站 PHP 配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website PHP" + ], + "summary": "Update website php conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsitePHPConfigUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "[domain] PHP conf update", + "formatZH": "[domain] PHP 配置修改", + "paramKeys": [] + } + } + }, + "/websites/php/config/:id": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取网站 php 配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Load websit php conf", + "parameters": [ + { + "type": "integer", + "description": "request", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.PHPConfig" + } + } + } + } + }, + "/websites/php/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 php 配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website PHP" + ], + "summary": "Update php conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsitePHPFileUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "websiteId", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "websiteId" + ], + "formatEN": "Nginx conf update [domain]", + "formatZH": "php 配置修改 [domain]", + "paramKeys": [] + } + } + }, + "/websites/rewrite": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取伪静态配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Get rewrite conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.NginxRewriteReq" + } + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/websites/rewrite/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新伪静态配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Website" + ], + "summary": "Update rewrite conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.NginxRewriteUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "websites", + "input_colume": "id", + "input_value": "websiteID", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "websiteID" + ], + "formatEN": "Nginx conf rewrite update [domain]", + "formatZH": "伪静态配置修改 [domain]", + "paramKeys": [] + } + } + }, "/websites/search": { "post": { "security": [ @@ -8242,6 +9126,57 @@ } } }, + "/websites/ssl/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "更新 ssl", + "consumes": [ + "application/json" + ], + "tags": [ + "Website SSL" + ], + "summary": "Update ssl", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.WebsiteSSLUpdate" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [ + { + "db": "website_ssls", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "primary_domain", + "output_value": "domain" + } + ], + "bodyKeys": [ + "id" + ], + "formatEN": "Update ssl config [domain]", + "formatZH": "更新证书设置 [domain]", + "paramKeys": [] + } + } + }, "/websites/ssl/website/:websiteId": { "get": { "security": [ @@ -8404,6 +9339,44 @@ } }, "definitions": { + "dto.AddrRuleOperate": { + "type": "object", + "required": [ + "address", + "operation", + "strategy" + ], + "properties": { + "address": { + "type": "string" + }, + "operation": { + "type": "string", + "enum": [ + "add", + "remove" + ] + }, + "strategy": { + "type": "string", + "enum": [ + "accept", + "drop" + ] + } + } + }, + "dto.AddrRuleUpdate": { + "type": "object", + "properties": { + "newRule": { + "$ref": "#/definitions/dto.AddrRuleOperate" + }, + "oldRule": { + "$ref": "#/definitions/dto.AddrRuleOperate" + } + } + }, "dto.BackupOperate": { "type": "object", "required": [ @@ -8470,6 +9443,23 @@ } } }, + "dto.BatchRuleOperate": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "rules": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.PortRuleOperate" + } + }, + "type": { + "type": "string" + } + } + }, "dto.CaptchaResponse": { "type": "object", "properties": { @@ -8609,8 +9599,7 @@ "dto.ComposeCreate": { "type": "object", "required": [ - "from", - "name" + "from" ], "properties": { "file": { @@ -8837,6 +9826,34 @@ } } }, + "dto.CronjobBatchDelete": { + "type": "object", + "properties": { + "cleanData": { + "type": "boolean" + }, + "ids": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "dto.CronjobClean": { + "type": "object", + "required": [ + "cronjobID" + ], + "properties": { + "cleanData": { + "type": "boolean" + }, + "cronjobID": { + "type": "integer" + } + } + }, "dto.CronjobCreate": { "type": "object", "required": [ @@ -8846,9 +9863,7 @@ ], "properties": { "day": { - "type": "integer", - "maximum": 31, - "minimum": 1 + "type": "integer" }, "dbName": { "type": "string" @@ -8857,17 +9872,13 @@ "type": "string" }, "hour": { - "type": "integer", - "maximum": 23, - "minimum": 0 + "type": "integer" }, "keepLocal": { "type": "boolean" }, "minute": { - "type": "integer", - "maximum": 59, - "minimum": 0 + "type": "integer" }, "name": { "type": "string" @@ -8928,9 +9939,7 @@ ], "properties": { "day": { - "type": "integer", - "maximum": 31, - "minimum": 1 + "type": "integer" }, "dbName": { "type": "string" @@ -8939,9 +9948,7 @@ "type": "string" }, "hour": { - "type": "integer", - "maximum": 23, - "minimum": 0 + "type": "integer" }, "id": { "type": "integer" @@ -8950,9 +9957,7 @@ "type": "boolean" }, "minute": { - "type": "integer", - "maximum": 59, - "minimum": 0 + "type": "integer" }, "name": { "type": "string" @@ -9027,6 +10032,12 @@ "type": "string" } }, + "iptables": { + "type": "boolean" + }, + "isSwarm": { + "type": "boolean" + }, "liveRestore": { "type": "boolean" }, @@ -9046,15 +10057,9 @@ }, "dto.DaemonJsonUpdateByFile": { "type": "object", - "required": [ - "path" - ], "properties": { "file": { "type": "string" - }, - "path": { - "type": "string" } } }, @@ -9082,33 +10087,15 @@ "databaseNumber": { "type": "integer" }, - "dateeaseID": { - "type": "integer" - }, - "haloID": { - "type": "integer" - }, "hostname": { "type": "string" }, - "jumpserverID": { - "type": "integer" - }, "kernelArch": { "type": "string" }, "kernelVersion": { "type": "string" }, - "kubeoperatorID": { - "type": "integer" - }, - "kubepiID": { - "type": "integer" - }, - "metersphereID": { - "type": "integer" - }, "os": { "type": "string" }, @@ -9150,20 +10137,11 @@ "cpuUsedPercent": { "type": "number" }, - "free": { - "type": "integer" - }, - "inodesFree": { - "type": "integer" - }, - "inodesTotal": { - "type": "integer" - }, - "inodesUsed": { - "type": "integer" - }, - "inodesUsedPercent": { - "type": "number" + "diskData": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.DiskInfo" + } }, "ioCount": { "type": "integer" @@ -9171,12 +10149,15 @@ "ioReadBytes": { "type": "integer" }, - "ioTime": { + "ioReadTime": { "type": "integer" }, "ioWriteBytes": { "type": "integer" }, + "ioWriteTime": { + "type": "integer" + }, "load1": { "type": "number" }, @@ -9213,11 +10194,40 @@ "timeSinceUptime": { "type": "string" }, + "uptime": { + "type": "integer" + } + } + }, + "dto.DiskInfo": { + "type": "object", + "properties": { + "device": { + "type": "string" + }, + "free": { + "type": "integer" + }, + "inodesFree": { + "type": "integer" + }, + "inodesTotal": { + "type": "integer" + }, + "inodesUsed": { + "type": "integer" + }, + "inodesUsedPercent": { + "type": "number" + }, + "path": { + "type": "string" + }, "total": { "type": "integer" }, - "uptime": { - "type": "integer" + "type": { + "type": "string" }, "used": { "type": "integer" @@ -9240,6 +10250,12 @@ "restart", "stop" ] + }, + "stopService": { + "type": "boolean" + }, + "stopSocket": { + "type": "boolean" } } }, @@ -9264,7 +10280,9 @@ "S3", "SFTP", "MINIO", - "LOCAL" + "LOCAL", + "COS", + "KODO" ] } } @@ -9280,6 +10298,40 @@ } } }, + "dto.FirewallBaseInfo": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "pingStatus": { + "type": "string" + }, + "status": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.FirewallOperation": { + "type": "object", + "required": [ + "operation" + ], + "properties": { + "operation": { + "type": "string", + "enum": [ + "start", + "stop", + "disablePing", + "enablePing" + ] + } + } + }, "dto.ForBuckets": { "type": "object", "required": [ @@ -9333,6 +10385,9 @@ }, "dto.GroupUpdate": { "type": "object", + "required": [ + "type" + ], "properties": { "id": { "type": "integer" @@ -9342,6 +10397,9 @@ }, "name": { "type": "string" + }, + "type": { + "type": "string" } } }, @@ -9363,6 +10421,9 @@ "key" ] }, + "passPhrase": { + "type": "string" + }, "password": { "type": "string" }, @@ -9406,9 +10467,21 @@ "name": { "type": "string" }, + "passPhrase": { + "type": "string" + }, + "password": { + "type": "string" + }, "port": { "type": "integer" }, + "privateKey": { + "type": "string" + }, + "rememberPassword": { + "type": "boolean" + }, "user": { "type": "string" } @@ -9444,6 +10517,9 @@ "name": { "type": "string" }, + "passPhrase": { + "type": "string" + }, "password": { "type": "string" }, @@ -9455,6 +10531,9 @@ "privateKey": { "type": "string" }, + "rememberPassword": { + "type": "boolean" + }, "user": { "type": "string" } @@ -9663,9 +10742,6 @@ }, "password": { "type": "string" - }, - "secret": { - "type": "string" } } }, @@ -10039,6 +11115,56 @@ } } }, + "dto.PortRuleOperate": { + "type": "object", + "required": [ + "operation", + "port", + "protocol", + "strategy" + ], + "properties": { + "address": { + "type": "string" + }, + "operation": { + "type": "string", + "enum": [ + "add", + "remove" + ] + }, + "port": { + "type": "string" + }, + "protocol": { + "type": "string", + "enum": [ + "tcp", + "udp", + "tcp/udp" + ] + }, + "strategy": { + "type": "string", + "enum": [ + "accept", + "drop" + ] + } + } + }, + "dto.PortRuleUpdate": { + "type": "object", + "properties": { + "newRule": { + "$ref": "#/definitions/dto.PortRuleOperate" + }, + "oldRule": { + "$ref": "#/definitions/dto.PortRuleOperate" + } + } + }, "dto.PortUpdate": { "type": "object", "required": [ @@ -10433,7 +11559,9 @@ "OSS", "S3", "SFTP", - "MINIO" + "MINIO", + "COS", + "KODO" ] } } @@ -10497,6 +11625,9 @@ "dto.UpgradeInfo": { "type": "object", "properties": { + "latestVersion": { + "type": "string" + }, "newVersion": { "type": "string" }, @@ -10508,9 +11639,6 @@ "dto.UserLoginInfo": { "type": "object", "properties": { - "mfaSecret": { - "type": "string" - }, "mfaStatus": { "type": "string" }, @@ -10668,6 +11796,9 @@ "required": { "type": "string" }, + "resource": { + "type": "string" + }, "shortDescEn": { "type": "string" }, @@ -10812,9 +11943,21 @@ "proxy": { "type": "string" }, + "proxyType": { + "type": "string" + }, "remark": { "type": "string" }, + "rewrite": { + "type": "string" + }, + "runtimeID": { + "type": "integer" + }, + "siteDir": { + "type": "string" + }, "status": { "type": "string" }, @@ -11028,6 +12171,22 @@ } } }, + "request.AppInstalledUpdate": { + "type": "object", + "required": [ + "installId", + "params" + ], + "properties": { + "installId": { + "type": "integer" + }, + "params": { + "type": "object", + "additionalProperties": true + } + } + }, "request.AppSearch": { "type": "object", "required": [ @@ -11367,6 +12526,40 @@ } } }, + "request.NginxRewriteReq": { + "type": "object", + "required": [ + "name", + "websiteId" + ], + "properties": { + "name": { + "type": "string" + }, + "websiteId": { + "type": "integer" + } + } + }, + "request.NginxRewriteUpdate": { + "type": "object", + "required": [ + "content", + "name", + "websiteId" + ], + "properties": { + "content": { + "type": "string" + }, + "name": { + "type": "string" + }, + "websiteId": { + "type": "integer" + } + } + }, "request.NginxScopeReq": { "type": "object", "required": [ @@ -11395,6 +12588,86 @@ } } }, + "request.RuntimeCreate": { + "type": "object", + "properties": { + "appDetailId": { + "type": "integer" + }, + "image": { + "type": "string" + }, + "name": { + "type": "string" + }, + "params": { + "type": "object", + "additionalProperties": true + }, + "resource": { + "type": "string" + }, + "type": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "request.RuntimeDelete": { + "type": "object", + "properties": { + "id": { + "type": "integer" + } + } + }, + "request.RuntimeSearch": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "name": { + "type": "string" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "request.RuntimeUpdate": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image": { + "type": "string" + }, + "name": { + "type": "string" + }, + "params": { + "type": "object", + "additionalProperties": true + }, + "version": { + "type": "string" + } + } + }, "request.SearchUploadWithPage": { "type": "object", "required": [ @@ -11456,15 +12729,24 @@ "otherDomains": { "type": "string" }, + "port": { + "type": "integer" + }, "primaryDomain": { "type": "string" }, "proxy": { "type": "string" }, + "proxyType": { + "type": "string" + }, "remark": { "type": "string" }, + "runtimeID": { + "type": "integer" + }, "type": { "type": "string" }, @@ -11600,34 +12882,6 @@ } } }, - "request.WebsiteGroupCreate": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - } - } - }, - "request.WebsiteGroupUpdate": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "default": { - "type": "boolean" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, "request.WebsiteHTTPSOp": { "type": "object", "required": [ @@ -11739,6 +12993,43 @@ } } }, + "request.WebsitePHPConfigUpdate": { + "type": "object", + "required": [ + "id", + "params" + ], + "properties": { + "id": { + "type": "integer" + }, + "params": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "request.WebsitePHPFileUpdate": { + "type": "object", + "required": [ + "content", + "id", + "type" + ], + "properties": { + "content": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, "request.WebsiteResourceReq": { "type": "object", "required": [ @@ -11805,6 +13096,21 @@ } } }, + "request.WebsiteSSLUpdate": { + "type": "object", + "required": [ + "autoRenew", + "id" + ], + "properties": { + "autoRenew": { + "type": "boolean" + }, + "id": { + "type": "integer" + } + } + }, "request.WebsiteSearch": { "type": "object", "required": [ @@ -11851,6 +13157,21 @@ } } }, + "request.WebsiteUpdateDir": { + "type": "object", + "required": [ + "id", + "siteDir" + ], + "properties": { + "id": { + "type": "integer" + }, + "siteDir": { + "type": "string" + } + } + }, "request.WebsiteWafReq": { "type": "object", "required": [ @@ -11925,6 +13246,9 @@ "required": { "type": "string" }, + "resource": { + "type": "string" + }, "shortDescEn": { "type": "string" }, @@ -11972,6 +13296,9 @@ "id": { "type": "integer" }, + "image": { + "type": "string" + }, "lastVersion": { "type": "string" }, @@ -12028,10 +13355,35 @@ "response.AppParam": { "type": "object", "properties": { - "label": { + "edit": { + "type": "boolean" + }, + "key": { "type": "string" }, - "value": {} + "labelEn": { + "type": "string" + }, + "labelZh": { + "type": "string" + }, + "multiple": { + "type": "boolean" + }, + "required": { + "type": "boolean" + }, + "rule": { + "type": "string" + }, + "showValue": { + "type": "string" + }, + "type": { + "type": "string" + }, + "value": {}, + "values": {} } }, "response.FileInfo": { @@ -12136,6 +13488,17 @@ } } }, + "response.PHPConfig": { + "type": "object", + "properties": { + "params": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, "response.WebsiteAcmeAccountDTO": { "type": "object", "properties": { @@ -12171,6 +13534,9 @@ "appInstallId": { "type": "integer" }, + "appName": { + "type": "string" + }, "createdAt": { "type": "string" }, @@ -12207,9 +13573,24 @@ "proxy": { "type": "string" }, + "proxyType": { + "type": "string" + }, "remark": { "type": "string" }, + "rewrite": { + "type": "string" + }, + "runtimeID": { + "type": "integer" + }, + "runtimeName": { + "type": "string" + }, + "siteDir": { + "type": "string" + }, "sitePath": { "type": "string" }, diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 15596eb07..2fe04f709 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -1,5 +1,31 @@ basePath: /api/v1 definitions: + dto.AddrRuleOperate: + properties: + address: + type: string + operation: + enum: + - add + - remove + type: string + strategy: + enum: + - accept + - drop + type: string + required: + - address + - operation + - strategy + type: object + dto.AddrRuleUpdate: + properties: + newRule: + $ref: '#/definitions/dto.AddrRuleOperate' + oldRule: + $ref: '#/definitions/dto.AddrRuleOperate' + type: object dto.BackupOperate: properties: accessKey: @@ -43,6 +69,17 @@ definitions: required: - ids type: object + dto.BatchRuleOperate: + properties: + rules: + items: + $ref: '#/definitions/dto.PortRuleOperate' + type: array + type: + type: string + required: + - type + type: object dto.CaptchaResponse: properties: captchaID: @@ -152,7 +189,6 @@ definitions: type: integer required: - from - - name type: object dto.ComposeOperation: properties: @@ -291,25 +327,37 @@ definitions: shotTime: type: string type: object + dto.CronjobBatchDelete: + properties: + cleanData: + type: boolean + ids: + items: + type: integer + type: array + type: object + dto.CronjobClean: + properties: + cleanData: + type: boolean + cronjobID: + type: integer + required: + - cronjobID + type: object dto.CronjobCreate: properties: day: - maximum: 31 - minimum: 1 type: integer dbName: type: string exclusionRules: type: string hour: - maximum: 23 - minimum: 0 type: integer keepLocal: type: boolean minute: - maximum: 59 - minimum: 0 type: integer name: type: string @@ -352,24 +400,18 @@ definitions: dto.CronjobUpdate: properties: day: - maximum: 31 - minimum: 1 type: integer dbName: type: string exclusionRules: type: string hour: - maximum: 23 - minimum: 0 type: integer id: type: integer keepLocal: type: boolean minute: - maximum: 59 - minimum: 0 type: integer name: type: string @@ -424,6 +466,10 @@ definitions: items: type: string type: array + iptables: + type: boolean + isSwarm: + type: boolean liveRestore: type: boolean registryMirrors: @@ -439,10 +485,6 @@ definitions: properties: file: type: string - path: - type: string - required: - - path type: object dto.DashboardBase: properties: @@ -460,24 +502,12 @@ definitions: $ref: '#/definitions/dto.DashboardCurrent' databaseNumber: type: integer - dateeaseID: - type: integer - haloID: - type: integer hostname: type: string - jumpserverID: - type: integer kernelArch: type: string kernelVersion: type: string - kubeoperatorID: - type: integer - kubepiID: - type: integer - metersphereID: - type: integer os: type: string platform: @@ -505,24 +535,20 @@ definitions: type: number cpuUsedPercent: type: number - free: - type: integer - inodesFree: - type: integer - inodesTotal: - type: integer - inodesUsed: - type: integer - inodesUsedPercent: - type: number + diskData: + items: + $ref: '#/definitions/dto.DiskInfo' + type: array ioCount: type: integer ioReadBytes: type: integer - ioTime: + ioReadTime: type: integer ioWriteBytes: type: integer + ioWriteTime: + type: integer load1: type: number load5: @@ -547,10 +573,29 @@ definitions: type: string timeSinceUptime: type: string - total: - type: integer uptime: type: integer + type: object + dto.DiskInfo: + properties: + device: + type: string + free: + type: integer + inodesFree: + type: integer + inodesTotal: + type: integer + inodesUsed: + type: integer + inodesUsedPercent: + type: number + path: + type: string + total: + type: integer + type: + type: string used: type: integer usedPercent: @@ -564,6 +609,10 @@ definitions: - restart - stop type: string + stopService: + type: boolean + stopSocket: + type: boolean required: - operation type: object @@ -580,6 +629,8 @@ definitions: - SFTP - MINIO - LOCAL + - COS + - KODO type: string required: - fileDir @@ -593,6 +644,29 @@ definitions: required: - path type: object + dto.FirewallBaseInfo: + properties: + name: + type: string + pingStatus: + type: string + status: + type: string + version: + type: string + type: object + dto.FirewallOperation: + properties: + operation: + enum: + - start + - stop + - disablePing + - enablePing + type: string + required: + - operation + type: object dto.ForBuckets: properties: accessKey: @@ -635,6 +709,10 @@ definitions: type: boolean name: type: string + type: + type: string + required: + - type type: object dto.HostConnTest: properties: @@ -645,6 +723,8 @@ definitions: - password - key type: string + passPhrase: + type: string password: type: string port: @@ -678,8 +758,16 @@ definitions: type: integer name: type: string + passPhrase: + type: string + password: + type: string port: type: integer + privateKey: + type: string + rememberPassword: + type: boolean user: type: string type: object @@ -700,6 +788,8 @@ definitions: type: integer name: type: string + passPhrase: + type: string password: type: string port: @@ -708,6 +798,8 @@ definitions: type: integer privateKey: type: string + rememberPassword: + type: boolean user: type: string required: @@ -850,8 +942,6 @@ definitions: type: string password: type: string - secret: - type: string type: object dto.MfaCredential: properties: @@ -1099,6 +1189,41 @@ definitions: hostPort: type: integer type: object + dto.PortRuleOperate: + properties: + address: + type: string + operation: + enum: + - add + - remove + type: string + port: + type: string + protocol: + enum: + - tcp + - udp + - tcp/udp + type: string + strategy: + enum: + - accept + - drop + type: string + required: + - operation + - port + - protocol + - strategy + type: object + dto.PortRuleUpdate: + properties: + newRule: + $ref: '#/definitions/dto.PortRuleOperate' + oldRule: + $ref: '#/definitions/dto.PortRuleOperate' + type: object dto.PortUpdate: properties: serverPort: @@ -1360,6 +1485,8 @@ definitions: - S3 - SFTP - MINIO + - COS + - KODO type: string required: - from @@ -1402,6 +1529,8 @@ definitions: type: object dto.UpgradeInfo: properties: + latestVersion: + type: string newVersion: type: string releaseNote: @@ -1409,8 +1538,6 @@ definitions: type: object dto.UserLoginInfo: properties: - mfaSecret: - type: string mfaStatus: type: string name: @@ -1514,6 +1641,8 @@ definitions: type: integer required: type: string + resource: + type: string shortDescEn: type: string shortDescZh: @@ -1609,8 +1738,16 @@ definitions: type: string proxy: type: string + proxyType: + type: string remark: type: string + rewrite: + type: string + runtimeID: + type: integer + siteDir: + type: string status: type: string type: @@ -1752,6 +1889,17 @@ definitions: - page - pageSize type: object + request.AppInstalledUpdate: + properties: + installId: + type: integer + params: + additionalProperties: true + type: object + required: + - installId + - params + type: object request.AppSearch: properties: name: @@ -1979,6 +2127,29 @@ definitions: required: - websiteId type: object + request.NginxRewriteReq: + properties: + name: + type: string + websiteId: + type: integer + required: + - name + - websiteId + type: object + request.NginxRewriteUpdate: + properties: + content: + type: string + name: + type: string + websiteId: + type: integer + required: + - content + - name + - websiteId + type: object request.NginxScopeReq: properties: scope: @@ -1997,6 +2168,59 @@ definitions: port: type: integer type: object + request.RuntimeCreate: + properties: + appDetailId: + type: integer + image: + type: string + name: + type: string + params: + additionalProperties: true + type: object + resource: + type: string + type: + type: string + version: + type: string + type: object + request.RuntimeDelete: + properties: + id: + type: integer + type: object + request.RuntimeSearch: + properties: + name: + type: string + page: + type: integer + pageSize: + type: integer + status: + type: string + type: + type: string + required: + - page + - pageSize + type: object + request.RuntimeUpdate: + properties: + id: + type: integer + image: + type: string + name: + type: string + params: + additionalProperties: true + type: object + version: + type: string + type: object request.SearchUploadWithPage: properties: page: @@ -2034,12 +2258,18 @@ definitions: type: string otherDomains: type: string + port: + type: integer primaryDomain: type: string proxy: type: string + proxyType: + type: string remark: type: string + runtimeID: + type: integer type: type: string webSiteGroupID: @@ -2135,24 +2365,6 @@ definitions: required: - id type: object - request.WebsiteGroupCreate: - properties: - name: - type: string - required: - - name - type: object - request.WebsiteGroupUpdate: - properties: - default: - type: boolean - id: - type: integer - name: - type: string - required: - - id - type: object request.WebsiteHTTPSOp: properties: HttpConfig: @@ -2228,6 +2440,31 @@ definitions: required: - id type: object + request.WebsitePHPConfigUpdate: + properties: + id: + type: integer + params: + additionalProperties: + type: string + type: object + required: + - id + - params + type: object + request.WebsitePHPFileUpdate: + properties: + content: + type: string + id: + type: integer + type: + type: string + required: + - content + - id + - type + type: object request.WebsiteResourceReq: properties: id: @@ -2272,6 +2509,16 @@ definitions: - page - pageSize type: object + request.WebsiteSSLUpdate: + properties: + autoRenew: + type: boolean + id: + type: integer + required: + - autoRenew + - id + type: object request.WebsiteSearch: properties: name: @@ -2303,6 +2550,16 @@ definitions: - primaryDomain - webSiteGroupID type: object + request.WebsiteUpdateDir: + properties: + id: + type: integer + siteDir: + type: string + required: + - id + - siteDir + type: object request.WebsiteWafReq: properties: key: @@ -2353,6 +2610,8 @@ definitions: type: integer required: type: string + resource: + type: string shortDescEn: type: string shortDescZh: @@ -2384,6 +2643,8 @@ definitions: type: boolean id: type: integer + image: + type: string lastVersion: type: string params: {} @@ -2421,9 +2682,26 @@ definitions: type: object response.AppParam: properties: - label: + edit: + type: boolean + key: + type: string + labelEn: + type: string + labelZh: + type: string + multiple: + type: boolean + required: + type: boolean + rule: + type: string + showValue: + type: string + type: type: string value: {} + values: {} type: object response.FileInfo: properties: @@ -2492,6 +2770,13 @@ definitions: writing: type: string type: object + response.PHPConfig: + properties: + params: + additionalProperties: + type: string + type: object + type: object response.WebsiteAcmeAccountDTO: properties: createdAt: @@ -2515,6 +2800,8 @@ definitions: type: string appInstallId: type: integer + appName: + type: string createdAt: type: string defaultServer: @@ -2539,8 +2826,18 @@ definitions: type: string proxy: type: string + proxyType: + type: string remark: type: string + rewrite: + type: string + runtimeID: + type: integer + runtimeName: + type: string + siteDir: + type: string sitePath: type: string status: @@ -2628,11 +2925,22 @@ paths: summary: Search app by key tags: - App - /apps/detail/:appId/:version: + /apps/checkupdate: + get: + description: 获取应用更新版本 + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Get app list update + tags: + - App + /apps/detail/:appId/:version/:type: get: consumes: - application/json - description: 通过 id 获取应用详情 + description: 通过 appid 获取应用详情 parameters: - description: app id in: path @@ -2644,6 +2952,11 @@ paths: name: version required: true type: string + - description: app 类型 + in: path + name: version + required: true + type: string responses: "200": description: OK @@ -2651,7 +2964,28 @@ paths: $ref: '#/definitions/response.AppDetailDTO' security: - ApiKeyAuth: [] - summary: Search app detail by id + summary: Search app detail by appid + tags: + - App + /apps/details/:id: + get: + consumes: + - application/json + description: 通过 id 获取应用详情 + parameters: + - description: id + in: path + name: appId + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.AppDetailDTO' + security: + - ApiKeyAuth: [] + summary: Get app detail by id tags: - App /apps/install: @@ -2757,6 +3091,27 @@ paths: summary: Search default config by key tags: - App + /apps/installed/conninfo/:key: + get: + consumes: + - application/json + description: 获取应用连接信息 + parameters: + - description: request + in: path + name: key + required: true + type: string + responses: + "200": + description: OK + schema: + type: string + security: + - ApiKeyAuth: [] + summary: Search app password by key + tags: + - App /apps/installed/delete/check/:appInstallId: get: consumes: @@ -2778,27 +3133,6 @@ paths: summary: Check before delete tags: - App - /apps/installed/loadpassword/:key: - get: - consumes: - - application/json - description: 获取应用密码 - parameters: - - description: request - in: path - name: key - required: true - type: string - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Search app password by key - tags: - - App /apps/installed/loadport/:key: get: consumes: @@ -2887,6 +3221,33 @@ paths: summary: Search params by appInstallId tags: - App + /apps/installed/params/update: + post: + consumes: + - application/json + description: 修改应用参数 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.AppInstalledUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Change app params + tags: + - App + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - installId + formatEN: Application param update [installId] + formatZH: 应用参数修改 [installId] + paramKeys: [] /apps/installed/port/change: post: consumes: @@ -3022,6 +3383,15 @@ paths: summary: Load captcha tags: - Auth + /auth/demo: + get: + description: 判断是否为demo环境 + responses: + "200": + description: "" + summary: Check System isDemo + tags: + - Auth /auth/init: post: consumes: @@ -3205,6 +3575,33 @@ paths: summary: Page composes tags: - Container Compose + /containers/compose/test: + post: + consumes: + - application/json + description: 测试 compose 是否可用 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.ComposeCreate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Test compose + tags: + - Container Compose + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - name + formatEN: check compose [name] + formatZH: 检测 compose [name] 格式 + paramKeys: [] /containers/compose/update: post: consumes: @@ -4238,7 +4635,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.BatchDeleteReq' + $ref: '#/definitions/dto.CronjobBatchDelete' responses: "200": description: "" @@ -4326,6 +4723,39 @@ paths: formatEN: manually execute the cronjob [name] formatZH: 手动执行计划任务 [name] paramKeys: [] + /cronjobs/records/clean: + post: + consumes: + - application/json + description: 清空计划任务记录 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.CronjobClean' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Clean job records + tags: + - Cronjob + x-panel-log: + BeforeFuntions: + - db: cronjobs + input_colume: id + input_value: id + isList: false + output_colume: name + output_value: name + bodyKeys: + - id + formatEN: clean cronjob [name] records + formatZH: 清空计划任务记录 [name] + paramKeys: [] /cronjobs/search: post: consumes: @@ -5065,6 +5495,23 @@ paths: formatEN: Check whether file [path] exists formatZH: 检测文件 [path] 是否存在 paramKeys: [] + /files/chunkupload: + post: + description: 分片上传文件 + parameters: + - description: request + in: formData + name: file + required: true + type: file + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: ChunkUpload file + tags: + - File /files/compress: post: consumes: @@ -5202,6 +5649,33 @@ paths: formatEN: Download file [name] formatZH: 下载文件 [name] paramKeys: [] + /files/download/bypath: + post: + consumes: + - application/json + description: 下载指定文件 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.FilePath' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Download file with path + tags: + - File + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - path + formatEN: Download file [path] + formatZH: 下载文件 [path] + paramKeys: [] /files/loadfile: post: consumes: @@ -5488,6 +5962,123 @@ paths: formatEN: Download url => [path]/[name] formatZH: 下载 url => [path]/[name] paramKeys: [] + /groups: + post: + consumes: + - application/json + description: 创建系统组 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.GroupCreate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Create group + tags: + - System Group + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - name + - type + formatEN: create group [name][type] + formatZH: 创建组 [name][type] + paramKeys: [] + /groups/del: + post: + consumes: + - application/json + description: 删除系统组 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperateByID' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Delete group + tags: + - System Group + x-panel-log: + BeforeFuntions: + - db: groups + input_colume: id + input_value: id + isList: false + output_colume: name + output_value: name + - db: groups + input_colume: id + input_value: id + isList: false + output_colume: type + output_value: type + bodyKeys: + - id + formatEN: delete group [type][name] + formatZH: 删除组 [type][name] + paramKeys: [] + /groups/search: + post: + consumes: + - application/json + description: 查询系统组 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.GroupSearch' + responses: + "200": + description: OK + schema: + type: anrry + security: + - ApiKeyAuth: [] + summary: List groups + tags: + - System Group + /groups/update: + post: + consumes: + - application/json + description: 更新系统组 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.GroupUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update group + tags: + - System Group + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - name + - type + formatEN: update group [name][type] + formatZH: 更新组 [name][type] + paramKeys: [] /hosts: post: consumes: @@ -5692,18 +6283,31 @@ paths: formatEN: delete host [addrs] formatZH: 删除主机 [addrs] paramKeys: [] - /hosts/group: + /hosts/firewall/base: + get: + description: 获取防火墙基础信息 + responses: + "200": + description: OK + schema: + $ref: '#/definitions/dto.FirewallBaseInfo' + security: + - ApiKeyAuth: [] + summary: Load firewall base info + tags: + - Firewall + /hosts/firewall/ip: post: consumes: - application/json - description: 创建系统组 + description: 批量删除防火墙规则 parameters: - description: request in: body name: request required: true schema: - $ref: '#/definitions/dto.GroupCreate' + $ref: '#/definitions/dto.BatchRuleOperate' responses: "200": description: "" @@ -5711,104 +6315,126 @@ paths: - ApiKeyAuth: [] summary: Create group tags: - - System Group - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - name - - type - formatEN: create group [name][type] - formatZH: 创建组 [name][type] - paramKeys: [] - /hosts/group/del: + - Firewall + /hosts/firewall/operate: post: consumes: - application/json - description: 删除系统组 + description: 修改防火墙状态 parameters: - description: request in: body name: request required: true schema: - $ref: '#/definitions/dto.OperateByID' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Delete group - tags: - - System Group - x-panel-log: - BeforeFuntions: - - db: groups - input_colume: id - input_value: id - isList: false - output_colume: name - output_value: name - - db: groups - input_colume: id - input_value: id - isList: false - output_colume: type - output_value: type - bodyKeys: - - id - formatEN: delete group [type][name] - formatZH: 删除组 [type][name] - paramKeys: [] - /hosts/group/search: - post: - consumes: - - application/json - description: 查询系统组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.GroupSearch' + $ref: '#/definitions/dto.FirewallOperation' responses: "200": description: OK schema: - type: anrry + $ref: '#/definitions/dto.PageResult' security: - ApiKeyAuth: [] - summary: List groups + summary: Page firewall status tags: - - System Group - /hosts/group/update: + - Firewall + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - operation + formatEN: '[operation] firewall' + formatZH: '[operation] 防火墙' + paramKeys: [] + /hosts/firewall/port: post: consumes: - application/json - description: 更新系统组 + description: 创建防火墙端口规则 parameters: - description: request in: body name: request required: true schema: - $ref: '#/definitions/dto.GroupUpdate' + $ref: '#/definitions/dto.PortRuleOperate' responses: "200": description: "" security: - ApiKeyAuth: [] - summary: Update group + summary: Create group tags: - - System Group + - Firewall x-panel-log: BeforeFuntions: [] bodyKeys: - - name - - type - formatEN: update group [name][type] - formatZH: 更新组 [name][type] + - port + - strategy + formatEN: create port rules [strategy][port] + formatZH: 添加端口规则 [strategy] [port] paramKeys: [] + /hosts/firewall/search: + post: + consumes: + - application/json + description: 获取防火墙规则列表分页 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.SearchWithPage' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/dto.PageResult' + security: + - ApiKeyAuth: [] + summary: Page firewall rules + tags: + - Firewall + /hosts/firewall/update/ip: + post: + consumes: + - application/json + description: 更新 ip 防火墙规则 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.AddrRuleUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Create group + tags: + - Firewall + /hosts/firewall/update/port: + post: + consumes: + - application/json + description: 更新端口防火墙规则 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.PortRuleUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Create group + tags: + - Firewall /hosts/search: post: consumes: @@ -5895,6 +6521,34 @@ paths: tags: - Host /hosts/update: + post: + consumes: + - application/json + description: 更新主机 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.HostOperate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update host + tags: + - Host + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - name + - addr + formatEN: update host [name][addr] + formatZH: 更新主机信息 [name][addr] + paramKeys: [] + /hosts/update/group: post: consumes: - application/json @@ -6108,6 +6762,126 @@ paths: formatEN: Update nginx conf [domain] formatZH: 更新 nginx 配置 [domain] paramKeys: [] + /runtimes: + post: + consumes: + - application/json + description: 创建运行环境 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.RuntimeCreate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Create runtime + tags: + - Runtime + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - name + formatEN: Create runtime [name] + formatZH: 创建运行环境 [name] + paramKeys: [] + /runtimes/:id: + get: + consumes: + - application/json + description: 获取运行环境 + parameters: + - description: request + in: path + name: id + required: true + type: string + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Get runtime + tags: + - Runtime + /runtimes/del: + post: + consumes: + - application/json + description: 删除运行环境 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.RuntimeDelete' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Delete runtime + tags: + - Website + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - id + formatEN: Delete website [name] + formatZH: 删除网站 [name] + paramKeys: [] + /runtimes/search: + post: + consumes: + - application/json + description: 获取运行环境列表 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.RuntimeSearch' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: List runtimes + tags: + - Runtime + /runtimes/update: + post: + consumes: + - application/json + description: 更新运行环境 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.RuntimeUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update runtime + tags: + - Runtime + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - name + formatEN: Update runtime [name] + formatZH: 更新运行环境 [name] + paramKeys: [] /settings/backup: post: consumes: @@ -6188,12 +6962,12 @@ paths: BeforeFuntions: - db: backup_accounts input_colume: id - input_value: ids + input_value: id isList: true output_colume: type output_value: types bodyKeys: - - ids + - id formatEN: delete backup account [types] formatZH: 删除备份账号 [types] paramKeys: [] @@ -6853,15 +7627,22 @@ paths: paramKeys: [] /settings/upgrade: get: - description: 系统更新信息 + consumes: + - application/json + description: 获取版本 release notes + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.Upgrade' responses: "200": - description: OK - schema: - $ref: '#/definitions/dto.UpgradeInfo' + description: "" security: - ApiKeyAuth: [] - summary: Load upgrade info + summary: Load release notes by version tags: - System Setting post: @@ -6938,6 +7719,27 @@ paths: summary: Search website by id tags: - Website + /websites/:id/config/:type: + get: + consumes: + - application/json + description: 通过 id 查询网站 nginx + parameters: + - description: request + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.FileInfo' + security: + - ApiKeyAuth: [] + summary: Search website nginx by id + tags: + - Website Nginx /websites/:id/https: get: consumes: @@ -6993,27 +7795,6 @@ paths: formatEN: Update website https [domain] conf formatZH: 更新网站 [domain] https 配置 paramKeys: [] - /websites/:id/nginx: - get: - consumes: - - application/json - description: 通过 id 查询网站 nginx - parameters: - - description: request - in: path - name: id - required: true - type: integer - responses: - "200": - description: OK - schema: - $ref: '#/definitions/response.FileInfo' - security: - - ApiKeyAuth: [] - summary: Search website nginx by id - tags: - - Website Nginx /websites/acme: post: consumes: @@ -7242,6 +8023,39 @@ paths: formatEN: Delete website [domain] formatZH: 删除网站 [domain] paramKeys: [] + /websites/dir/update: + post: + consumes: + - application/json + description: 更新网站目录 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.WebsiteUpdateDir' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Update Site Dir + tags: + - Website + x-panel-log: + BeforeFuntions: + - db: websites + input_colume: id + input_value: id + isList: false + output_colume: primary_domain + output_value: domain + bodyKeys: + - id + formatEN: Update domain [domain] dir + formatZH: 更新网站 [domain] 目录 + paramKeys: [] /websites/dns: post: consumes: @@ -7434,105 +8248,6 @@ paths: formatEN: Delete domain [domain] formatZH: 删除域名 [domain] paramKeys: [] - /websites/groups: - get: - description: 获取网站组 - responses: - "200": - description: OK - schema: - type: anrry - security: - - ApiKeyAuth: [] - summary: List website groups - tags: - - Website Group - post: - consumes: - - application/json - description: 创建网站组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteGroupCreate' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Create website group - tags: - - Website Group - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - name - formatEN: Create website groups [name] - formatZH: 创建网站组 [name] - paramKeys: [] - /websites/groups/del: - post: - consumes: - - application/json - description: 删除网站组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteResourceReq' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Delete website group - tags: - - Website Group - x-panel-log: - BeforeFuntions: - - db: website_groups - input_colume: id - input_value: id - isList: false - output_colume: name - output_value: name - bodyKeys: - - id - formatEN: Delete website group [name] - formatZH: 删除网站组 [name] - paramKeys: [] - /websites/groups/update: - post: - consumes: - - application/json - description: 更新网站组 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteGroupUpdate' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Update website group - tags: - - Website Group - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - name - formatEN: Update website groups [name] - formatZH: 更新网站组 [name] - paramKeys: [] /websites/list: get: description: 获取网站列表 @@ -7662,6 +8377,146 @@ paths: summary: List website names tags: - Website + /websites/php/config: + post: + consumes: + - application/json + description: 更新 网站 PHP 配置 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.WebsitePHPConfigUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update website php conf + tags: + - Website PHP + x-panel-log: + BeforeFuntions: + - db: websites + input_colume: id + input_value: id + isList: false + output_colume: primary_domain + output_value: domain + bodyKeys: + - id + formatEN: '[domain] PHP conf update' + formatZH: '[domain] PHP 配置修改' + paramKeys: [] + /websites/php/config/:id: + get: + consumes: + - application/json + description: 获取网站 php 配置 + parameters: + - description: request + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.PHPConfig' + security: + - ApiKeyAuth: [] + summary: Load websit php conf + tags: + - Website + /websites/php/update: + post: + consumes: + - application/json + description: 更新 php 配置 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.WebsitePHPFileUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update php conf + tags: + - Website PHP + x-panel-log: + BeforeFuntions: + - db: websites + input_colume: id + input_value: websiteId + isList: false + output_colume: primary_domain + output_value: domain + bodyKeys: + - websiteId + formatEN: Nginx conf update [domain] + formatZH: php 配置修改 [domain] + paramKeys: [] + /websites/rewrite: + post: + consumes: + - application/json + description: 获取伪静态配置 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.NginxRewriteReq' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Get rewrite conf + tags: + - Website + /websites/rewrite/update: + post: + consumes: + - application/json + description: 更新伪静态配置 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.NginxRewriteUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update rewrite conf + tags: + - Website + x-panel-log: + BeforeFuntions: + - db: websites + input_colume: id + input_value: websiteID + isList: false + output_colume: primary_domain + output_value: domain + bodyKeys: + - websiteID + formatEN: Nginx conf rewrite update [domain] + formatZH: 伪静态配置修改 [domain] + paramKeys: [] /websites/search: post: consumes: @@ -7840,6 +8695,39 @@ paths: summary: Page website ssl tags: - Website SSL + /websites/ssl/update: + post: + consumes: + - application/json + description: 更新 ssl + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.WebsiteSSLUpdate' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Update ssl + tags: + - Website SSL + x-panel-log: + BeforeFuntions: + - db: website_ssls + input_colume: id + input_value: id + isList: false + output_colume: primary_domain + output_value: domain + bodyKeys: + - id + formatEN: Update ssl config [domain] + formatZH: 更新证书设置 [domain] + paramKeys: [] /websites/ssl/website/:websiteId: get: consumes: diff --git a/cmd/server/nginx_conf/index.php b/cmd/server/nginx_conf/index.php new file mode 100644 index 000000000..5cd4e8c46 --- /dev/null +++ b/cmd/server/nginx_conf/index.php @@ -0,0 +1,25 @@ +欢迎使用 PHP!'; +echo '

版本信息

'; + +echo '
    '; +echo '
  • PHP版本:', PHP_VERSION, '
  • '; +echo '
'; + +echo '

已安装扩展

'; +printExtensions(); + +/** + * 获取已安装扩展列表 + */ +function printExtensions() +{ + echo '
    '; + foreach (get_loaded_extensions() as $i => $name) { + echo "
  1. ", $name, '=', phpversion($name), '
  2. '; + } + echo '
'; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/nginx_conf.go b/cmd/server/nginx_conf/nginx_conf.go index 8f396ce51..24f80d4d6 100644 --- a/cmd/server/nginx_conf/nginx_conf.go +++ b/cmd/server/nginx_conf/nginx_conf.go @@ -1,6 +1,7 @@ package nginx_conf import ( + "embed" _ "embed" ) @@ -12,3 +13,9 @@ var WebsiteDefault []byte //go:embed index.html var Index []byte + +//go:embed index.php +var IndexPHP []byte + +//go:embed rewrite/* +var Rewrites embed.FS diff --git a/cmd/server/nginx_conf/rewrite/crmeb.conf b/cmd/server/nginx_conf/rewrite/crmeb.conf new file mode 100644 index 000000000..4260774ee --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/crmeb.conf @@ -0,0 +1,6 @@ +location / { + if (!-e $request_filename) { + rewrite ^(.*)$ /index.php?s=/$1 last; + break; + } +} diff --git a/cmd/server/nginx_conf/rewrite/dabr.conf b/cmd/server/nginx_conf/rewrite/dabr.conf new file mode 100644 index 000000000..37c13132f --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/dabr.conf @@ -0,0 +1,5 @@ +location / { +if (!-e $request_filename) { +rewrite ^/(.*)$ /index.php?q=$1 last; +} +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/dbshop.conf b/cmd/server/nginx_conf/rewrite/dbshop.conf new file mode 100644 index 000000000..61d23f711 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/dbshop.conf @@ -0,0 +1,7 @@ +location /{ + try_files $uri $uri/ /index.php$is_args$args; +} + +location ~ \.htaccess{ + deny all; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/dedecms.conf b/cmd/server/nginx_conf/rewrite/dedecms.conf new file mode 100644 index 000000000..6e110cba5 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/dedecms.conf @@ -0,0 +1,10 @@ +rewrite "^/list-([0-9]+)\.html$" /plus/list.php?tid=$1 last; +rewrite "^/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$" /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last; +rewrite "^/view-([0-9]+)-1\.html$" /plus/view.php?arcID=$1 last; +rewrite "^/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last; +rewrite "^/plus/list-([0-9]+)\.html$" /plus/list.php?tid=$1 last; +rewrite "^/plus/list-([0-9]+)-([0-9]+)-([0-9]+)\.html$" /plus/list.php?tid=$1&totalresult=$2&PageNo=$3 last; +rewrite "^/plus/view-([0-9]+)-1\.html$" /plus/view.php?arcID=$1 last; +rewrite "^/plus/view-([0-9]+)-([0-9]+)\.html$" /plus/view.php?aid=$1&pageno=$2 last; +rewrite "^/tags.html$" /tags.php last; +rewrite "^/tag-([0-9]+)-([0-9]+)\.html$" /tags.php?/$1/$2/ last; diff --git a/cmd/server/nginx_conf/rewrite/default.conf b/cmd/server/nginx_conf/rewrite/default.conf new file mode 100644 index 000000000..e69de29bb diff --git a/cmd/server/nginx_conf/rewrite/discuz.conf b/cmd/server/nginx_conf/rewrite/discuz.conf new file mode 100644 index 000000000..578da7653 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/discuz.conf @@ -0,0 +1,7 @@ +location / { + rewrite ^/archiver/((fid|tid)-[\w\-]+\.html)$ /archiver/index.php?$1 last; + rewrite ^/forum-([0-9]+)-([0-9]+)\.html$ /forumdisplay.php?fid=$1&page=$2 last; + rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /viewthread.php?tid=$1&extra=page%3D$3&page=$2 last; + rewrite ^/space-(username|uid)-(.+)\.html$ /space.php?$1=$2 last; + rewrite ^/tag-(.+)\.html$ /tag.php?name=$1 last; + } \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/discuzx.conf b/cmd/server/nginx_conf/rewrite/discuzx.conf new file mode 100644 index 000000000..8058495a2 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/discuzx.conf @@ -0,0 +1,12 @@ +rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; +rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; +rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; +rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; +rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; +rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; +rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last; +rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; +rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; +if (!-e $request_filename) { + return 404; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/discuzx2.conf b/cmd/server/nginx_conf/rewrite/discuzx2.conf new file mode 100644 index 000000000..61059e21e --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/discuzx2.conf @@ -0,0 +1,14 @@ +location /bbs/ { + rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; + rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; + rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; + rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; + rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; + rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; + rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last; + rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; + rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; + if (!-e $request_filename) { + return 404; + } +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/discuzx3.conf b/cmd/server/nginx_conf/rewrite/discuzx3.conf new file mode 100644 index 000000000..661889734 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/discuzx3.conf @@ -0,0 +1,15 @@ +location / { + rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last; + rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last; + rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last; + rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last; + rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last; + rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last; + rewrite ^([^\.]*)/blog-([0-9]+)-([0-9]+)\.html$ $1/home.php?mod=space&uid=$2&do=blog&id=$3 last; + rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last; + rewrite ^([^\.]*)/([a-z]+[a-z0-9_]*)-([a-z0-9_\-]+)\.html$ $1/plugin.php?id=$2:$3 last; + if (!-e $request_filename) { + return 404; + } +} + diff --git a/cmd/server/nginx_conf/rewrite/drupal.conf b/cmd/server/nginx_conf/rewrite/drupal.conf new file mode 100644 index 000000000..460b7791d --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/drupal.conf @@ -0,0 +1,3 @@ +if (!-e $request_filename) { + rewrite ^/(.*)$ /index.php?q=$1 last; + } \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/ecshop.conf b/cmd/server/nginx_conf/rewrite/ecshop.conf new file mode 100644 index 000000000..3574daa73 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/ecshop.conf @@ -0,0 +1,32 @@ +if (!-e $request_filename) +{ +rewrite "^/index\.html" /index.php last; +rewrite "^/category$" /index.php last; +rewrite "^/feed-c([0-9]+)\.xml$" /feed.php?cat=$1 last; +rewrite "^/feed-b([0-9]+)\.xml$" /feed.php?brand=$1 last; +rewrite "^/feed\.xml$" /feed.php last; +rewrite "^/category-([0-9]+)-b([0-9]+)-min([0-9]+)-max([0-9]+)-attr([^-]*)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /category.php?id=$1&brand=$2&price_min=$3&price_max=$4&filter_attr=$5&page=$6&sort=$7&order=$8 last; +rewrite "^/category-([0-9]+)-b([0-9]+)-min([0-9]+)-max([0-9]+)-attr([^-]*)(.*)\.html$" /category.php?id=$1&brand=$2&price_min=$3&price_max=$4&filter_attr=$5 last; +rewrite "^/category-([0-9]+)-b([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /category.php?id=$1&brand=$2&page=$3&sort=$4&order=$5 last; +rewrite "^/category-([0-9]+)-b([0-9]+)-([0-9]+)(.*)\.html$" /category.php?id=$1&brand=$2&page=$3 last; +rewrite "^/category-([0-9]+)-b([0-9]+)(.*)\.html$" /category.php?id=$1&brand=$2 last; +rewrite "^/category-([0-9]+)(.*)\.html$" /category.php?id=$1 last; +rewrite "^/goods-([0-9]+)(.*)\.html" /goods.php?id=$1 last; +rewrite "^/article_cat-([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /article_cat.php?id=$1&page=$2&sort=$3&order=$4 last; +rewrite "^/article_cat-([0-9]+)-([0-9]+)(.*)\.html$" /article_cat.php?id=$1&page=$2 last; +rewrite "^/article_cat-([0-9]+)(.*)\.html$" /article_cat.php?id=$1 last; +rewrite "^/article-([0-9]+)(.*)\.html$" /article.php?id=$1 last; +rewrite "^/brand-([0-9]+)-c([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)\.html" /brand.php?id=$1&cat=$2&page=$3&sort=$4&order=$5 last; +rewrite "^/brand-([0-9]+)-c([0-9]+)-([0-9]+)(.*)\.html" /brand.php?id=$1&cat=$2&page=$3 last; +rewrite "^/brand-([0-9]+)-c([0-9]+)(.*)\.html" /brand.php?id=$1&cat=$2 last; +rewrite "^/brand-([0-9]+)(.*)\.html" /brand.php?id=$1 last; +rewrite "^/tag-(.*)\.html" /search.php?keywords=$1 last; +rewrite "^/snatch-([0-9]+)\.html$" /snatch.php?id=$1 last; +rewrite "^/group_buy-([0-9]+)\.html$" /group_buy.php?act=view&id=$1 last; +rewrite "^/auction-([0-9]+)\.html$" /auction.php?act=view&id=$1 last; +rewrite "^/exchange-id([0-9]+)(.*)\.html$" /exchange.php?id=$1&act=view last; +rewrite "^/exchange-([0-9]+)-min([0-9]+)-max([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /exchange.php?cat_id=$1&integral_min=$2&integral_max=$3&page=$4&sort=$5&order=$6 last; +rewrite ^/exchange-([0-9]+)-([0-9]+)-(.+)-([a-zA-Z]+)(.*)\.html$" /exchange.php?cat_id=$1&page=$2&sort=$3&order=$4 last; +rewrite "^/exchange-([0-9]+)-([0-9]+)(.*)\.html$" /exchange.php?cat_id=$1&page=$2 last; +rewrite "^/exchange-([0-9]+)(.*)\.html$" /exchange.php?cat_id=$1 last; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/edusoho.conf b/cmd/server/nginx_conf/rewrite/edusoho.conf new file mode 100644 index 000000000..b0099dcff --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/edusoho.conf @@ -0,0 +1,8 @@ +location / { + index app.php; + try_files $uri @rewriteapp; +} + +location @rewriteapp { + rewrite ^(.*)$ /app.php/$1 last; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/emlog.conf b/cmd/server/nginx_conf/rewrite/emlog.conf new file mode 100644 index 000000000..e122a854d --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/emlog.conf @@ -0,0 +1,7 @@ +location / { +index index.php index.html; + if (!-e $request_filename) + { + rewrite ^/(.*)$ /index.php last; + } +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/empirecms.conf b/cmd/server/nginx_conf/rewrite/empirecms.conf new file mode 100644 index 000000000..c68b92d85 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/empirecms.conf @@ -0,0 +1,8 @@ +rewrite ^([^\.]*)/listinfo-(.+?)-(.+?)\.html$ $1/e/action/ListInfo/index.php?classid=$2&page=$3 last; +rewrite ^([^\.]*)/showinfo-(.+?)-(.+?)-(.+?)\.html$ $1/e/action/ShowInfo.php?classid=$2&id=$3&page=$4 last; +rewrite ^([^\.]*)/infotype-(.+?)-(.+?)\.html$ $1/e/action/InfoType/index.php?ttid=$2&page=$3 last; +rewrite ^([^\.]*)/tags-(.+?)-(.+?)\.html$ $1/e/tags/index.php?tagname=$2&page=$3 last; +rewrite ^([^\.]*)/comment-(.+?)-(.+?)-(.+?)-(.+?)-(.+?)-(.+?)\.html$ $1/e/pl/index\.php\?doaction=$2&classid=$3&id=$4&page=$5&myorder=$6&tempid=$7 last; +if (!-e $request_filename) { + return 404; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/laravel5.conf b/cmd/server/nginx_conf/rewrite/laravel5.conf new file mode 100644 index 000000000..da4c67474 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/laravel5.conf @@ -0,0 +1,3 @@ +location / { + try_files $uri $uri/ /index.php?$query_string; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/maccms.conf b/cmd/server/nginx_conf/rewrite/maccms.conf new file mode 100644 index 000000000..3470feeba --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/maccms.conf @@ -0,0 +1,5 @@ +rewrite ^/vod-(.*)$ /index.php?m=vod-$1 break; +rewrite ^/art-(.*)$ /index.php?m=art-$1 break; +rewrite ^/gbook-(.*)$ /index.php?m=gbook-$1 break; +rewrite ^/label-(.*)$ /index.php?m=label-$1 break; +rewrite ^/map-(.*)$ /index.php?m=map-$1 break; diff --git a/cmd/server/nginx_conf/rewrite/mvc.conf b/cmd/server/nginx_conf/rewrite/mvc.conf new file mode 100644 index 000000000..bf906257b --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/mvc.conf @@ -0,0 +1,6 @@ +location /{ + if (!-e $request_filename) { + rewrite ^(.*)$ /index.php/$1 last; + break; + } +} diff --git a/cmd/server/nginx_conf/rewrite/niushop.conf b/cmd/server/nginx_conf/rewrite/niushop.conf new file mode 100644 index 000000000..c32c40c71 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/niushop.conf @@ -0,0 +1,6 @@ +location / { + if (!-e $request_filename) { + rewrite ^(.*)$ /index.php?s=$1 last; + break; + } +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/phpcms.conf b/cmd/server/nginx_conf/rewrite/phpcms.conf new file mode 100644 index 000000000..a6e0df346 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/phpcms.conf @@ -0,0 +1,9 @@ +location / { + ###以下为PHPCMS 伪静态化rewrite法则 + rewrite ^(.*)show-([0-9]+)-([0-9]+)\.html$ $1/show.php?itemid=$2&page=$3; + rewrite ^(.*)list-([0-9]+)-([0-9]+)\.html$ $1/list.php?catid=$2&page=$3; + rewrite ^(.*)show-([0-9]+)\.html$ $1/show.php?specialid=$2; + ####以下为PHPWind 伪静态化rewrite法则 + rewrite ^(.*)-htm-(.*)$ $1.php?$2 last; + rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/phpwind.conf b/cmd/server/nginx_conf/rewrite/phpwind.conf new file mode 100644 index 000000000..388af90d3 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/phpwind.conf @@ -0,0 +1,4 @@ +location / { + rewrite ^(.*)-htm-(.*)$ $1.php?$2 last; + rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last; + } \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/sablog.conf b/cmd/server/nginx_conf/rewrite/sablog.conf new file mode 100644 index 000000000..fa4f00c49 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/sablog.conf @@ -0,0 +1,16 @@ +location / { + rewrite "^/date/([0-9]{6})/?([0-9]+)?/?$" /index.php?action=article&setdate=$1&page=$2 last; + rewrite ^/page/([0-9]+)?/?$ /index.php?action=article&page=$1 last; + rewrite ^/category/([0-9]+)/?([0-9]+)?/?$ /index.php?action=article&cid=$1&page=$2 last; + rewrite ^/category/([^/]+)/?([0-9]+)?/?$ /index.php?action=article&curl=$1&page=$2 last; + rewrite ^/(archives|search|article|links)/?$ /index.php?action=$1 last; + rewrite ^/(comments|tagslist|trackbacks|article)/?([0-9]+)?/?$ /index.php?action=$1&page=$2 last; + rewrite ^/tag/([^/]+)/?([0-9]+)?/?$ /index.php?action=article&item=$1&page=$2 last; + rewrite ^/archives/([0-9]+)/?([0-9]+)?/?$ /index.php?action=show&id=$1&page=$2 last; + rewrite ^/rss/([0-9]+)?/?$ /rss.php?cid=$1 last; + rewrite ^/rss/([^/]+)/?$ /rss.php?url=$1 last; + rewrite ^/uid/([0-9]+)/?([0-9]+)?/?$ /index.php?action=article&uid=$1&page=$2 last; + rewrite ^/user/([^/]+)/?([0-9]+)?/?$ /index.php?action=article&user=$1&page=$2 last; + rewrite sitemap.xml sitemap.php last; + rewrite ^(.*)/([0-9a-zA-Z\-\_]+)/?([0-9]+)?/?$ $1/index.php?action=show&alias=$2&page=$3 last; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/seacms.conf b/cmd/server/nginx_conf/rewrite/seacms.conf new file mode 100644 index 000000000..0dc6f3612 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/seacms.conf @@ -0,0 +1,11 @@ +location / { + rewrite ^/frim/index(.+?)\.html$ /list/index.php?$1 last; + rewrite ^/movie/index(.+?)\.html$ /detail/index.php?$1 last; + rewrite ^/play/([0-9]+)-([0-9]+)-([0-9]+)\.html$ /video/index.php?$1-$2-$3 last; + rewrite ^/topic/index(.+?)\.html$ /topic/index.php?$1 last; + rewrite ^/topiclist/index(.+?).html$ /topiclist/index.php?$1 last; + rewrite ^/index\.html$ index.php permanent; + rewrite ^/news\.html$ news/ permanent; + rewrite ^/part/index(.+?)\.html$ /articlelist/index.php?$1 last; + rewrite ^/article/index(.+?)\.html$ /article/index.php?$1 last; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/shopex.conf b/cmd/server/nginx_conf/rewrite/shopex.conf new file mode 100644 index 000000000..f57463c1a --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/shopex.conf @@ -0,0 +1,5 @@ +location / { +if (!-e $request_filename) { +rewrite ^/(.+\.(html|xml|json|htm|php|jsp|asp|shtml))$ /index.php?$1 last; +} +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/shopwind.conf b/cmd/server/nginx_conf/rewrite/shopwind.conf new file mode 100644 index 000000000..0edf086c3 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/shopwind.conf @@ -0,0 +1,14 @@ +location / { + #Redirect everything that isn't a real file to index.php + try_files $uri $uri/ /index.php$is_args$args; +} +#If you want a single domain name at the front and back ends +location /admin { + try_files $uri $uri/ /admin/index.php$is_args$args; +} +location /mobile { + try_files $uri $uri/ /mobile/index.php$is_args$args; +} +location /api { + try_files $uri $uri/ /api/index.php$is_args$args; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/thinkphp.conf b/cmd/server/nginx_conf/rewrite/thinkphp.conf new file mode 100644 index 000000000..216b1dc23 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/thinkphp.conf @@ -0,0 +1,8 @@ +location ~* (runtime|application)/ { + return 403; +} +location / { + if (!-e $request_filename){ + rewrite ^(.*)$ /index.php?s=$1 last; break; + } +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/typecho.conf b/cmd/server/nginx_conf/rewrite/typecho.conf new file mode 100644 index 000000000..dae6ba9cc --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/typecho.conf @@ -0,0 +1,3 @@ + if (!-e $request_filename) { + rewrite ^(.*)$ /index.php$1 last; + } diff --git a/cmd/server/nginx_conf/rewrite/typecho2.conf b/cmd/server/nginx_conf/rewrite/typecho2.conf new file mode 100644 index 000000000..22397d847 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/typecho2.conf @@ -0,0 +1,5 @@ +location /typecho/ { + if (!-e $request_filename) { + rewrite ^(.*)$ /typecho/index.php$1 last; + } +} diff --git a/cmd/server/nginx_conf/rewrite/wordpress.conf b/cmd/server/nginx_conf/rewrite/wordpress.conf new file mode 100644 index 000000000..9fe73c1eb --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/wordpress.conf @@ -0,0 +1,6 @@ +location / +{ + try_files $uri $uri/ /index.php?$args; +} + +rewrite /wp-admin$ $scheme://$host$uri/ permanent; \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/wp2.conf b/cmd/server/nginx_conf/rewrite/wp2.conf new file mode 100644 index 000000000..0e5fbaede --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/wp2.conf @@ -0,0 +1,6 @@ +rewrite ^.*/files/(.*)$ /wp-includes/ms-files.php?file=$1 last; +if (!-e $request_filename){ + rewrite ^.+?(/wp-.*) $1 last; + rewrite ^.+?(/.*\.php)$ $1 last; + rewrite ^ /index.php last; +} \ No newline at end of file diff --git a/cmd/server/nginx_conf/rewrite/zblog.conf b/cmd/server/nginx_conf/rewrite/zblog.conf new file mode 100644 index 000000000..5d2de2b79 --- /dev/null +++ b/cmd/server/nginx_conf/rewrite/zblog.conf @@ -0,0 +1,9 @@ +if (-f $request_filename/index.html){ + rewrite (.*) $1/index.html break; +} +if (-f $request_filename/index.php){ + rewrite (.*) $1/index.php; +} +if (!-f $request_filename){ + rewrite (.*) /index.php; +} \ No newline at end of file diff --git a/frontend/.env.development b/frontend/.env.development index 9bc64bdc6..c9a106a79 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -2,4 +2,12 @@ NODE_ENV = 'development' # 本地环境接口地址 -VITE_API_URL = '/api/v1' \ No newline at end of file +VITE_API_URL = '/api/v1' + +# 是否生成包预览文件 +VITE_REPORT = true + +# 是否开启gzip压缩 +VITE_BUILD_GZIP = true + +VITE_DROP_CONSOLE = true \ No newline at end of file diff --git a/frontend/.env.production b/frontend/.env.production index 4d4d84a1b..0cafd2c11 100644 --- a/frontend/.env.production +++ b/frontend/.env.production @@ -1,5 +1,13 @@ # 线上环境 NODE_ENV = "production" -# 线上环境接口地址(easymock) -VITE_API_URL = "https://mock.mengxuegu.com/mock/629d727e6163854a32e8307e" +# 线上环境接口地址 +VITE_API_URL = '/api/v1' + +# 是否生成包预览文件 +VITE_REPORT = true + +# 是否开启gzip压缩 +VITE_BUILD_GZIP = true + +VITE_DROP_CONSOLE = true diff --git a/frontend/LICENSE b/frontend/LICENSE deleted file mode 100644 index fcf8f49be..000000000 --- a/frontend/LICENSE +++ /dev/null @@ -1,12 +0,0 @@ -Copyright (c) 2022 Halsey - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index 17ea969bd..000000000 --- a/frontend/README.md +++ /dev/null @@ -1 +0,0 @@ -1Panel 前端 diff --git a/frontend/STANDARD.md b/frontend/STANDARD.md deleted file mode 100644 index 091df9e58..000000000 --- a/frontend/STANDARD.md +++ /dev/null @@ -1,544 +0,0 @@ -# 项目规范文档 📚 - -## 一、项目文件、组件命名规范 - -> **完全采用 Vue 官方推荐的风格指南,请务必查看 💢** -> -> **Link:** https://v3.cn.vuejs.org/style-guide - -## 二、代码格式化工具(Prettier) - -### 1、下载安装 prettier: - -```text -npm install prettier -``` - -### 2、安装 Vscode 插件(Prettier): - -![Prettier](https://iamge-1259297738.cos.ap-chengdu.myqcloud.com/md/Prettier.png) - -### 3、配置 Prettier: - -```javascript -// @see: https://www.prettier.cn - -module.exports = { - // 超过最大值换行 - printWidth: 130, - // 缩进字节数 - tabWidth: 2, - // 使用制表符而不是空格缩进行 - useTabs: true, - // 结尾不用分号(true有,false没有) - semi: true, - // 使用单引号(true单双引号,false双引号) - singleQuote: false, - // 更改引用对象属性的时间 可选值"" - quoteProps: 'as-needed', - // 在对象,数组括号与文字之间加空格 "{ foo: bar }" - bracketSpacing: true, - // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"",默认none - trailingComma: 'none', - // 在JSX中使用单引号而不是双引号 - jsxSingleQuote: false, - // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号 ,always:不省略括号 - arrowParens: 'avoid', - // 如果文件顶部已经有一个 doclock,这个选项将新建一行注释,并打上@format标记。 - insertPragma: false, - // 指定要使用的解析器,不需要写文件开头的 @prettier - requirePragma: false, - // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行 - proseWrap: 'preserve', - // 在html中空格是否是敏感的 "css" - 遵守CSS显示属性的默认值, "strict" - 空格被认为是敏感的 ,"ignore" - 空格被认为是不敏感的 - htmlWhitespaceSensitivity: 'css', - // 换行符使用 lf 结尾是 可选值"" - endOfLine: 'auto', - // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码 - rangeStart: 0, - rangeEnd: Infinity, - // Vue文件脚本和样式标签缩进 - vueIndentScriptAndStyle: false, -}; -``` - -## 三、代码规范工具(ESLint) - -### 1、安装 ESLint 相关插件: - -```text -npm install eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/eslint-plugin @typescript-eslint/parser -D -``` - -| 依赖 | 作用描述 | -| :------------------------------: | :------------------------------------------------------------------: | -| eslint | ESLint 核心库 | -| eslint-config-prettier | 关掉所有和 Prettier 冲突的 ESLint 的配置 | -| eslint-plugin-prettier | 将 Prettier 的 rules 以插件的形式加入到 ESLint 里面 | -| eslint-plugin-vue | 为 Vue 使用 ESlint 的插件 | -| @typescript-eslint/eslint-plugin | ESLint 插件,包含了各类定义好的检测 TypeScript 代码的规范 | -| @typescript-eslint/parser | ESLint 的解析器,用于解析 TypeScript,从而检查和规范 TypeScript 代码 | - -### 2、安装 Vscode 插件(ESLint、TSLint): - -- **ESLint:** - -![ESLint](https://iamge-1259297738.cos.ap-chengdu.myqcloud.com/md/ESLint.png) - -### 3、配置 ESLint: - -```javascript -// @see: http://eslint.cn - -module.exports = { - root: true, - env: { - browser: true, - node: true, - es6: true, - }, - /* 指定如何解析语法 */ - parser: 'vue-eslint-parser', - /* 优先级低于 parse 的语法解析配置 */ - parserOptions: { - parser: '@typescript-eslint/parser', - ecmaVersion: 2020, - sourceType: 'module', - jsxPragma: 'React', - ecmaFeatures: { - jsx: true, - }, - }, - /* 继承某些已有的规则 */ - extends: [ - 'plugin:vue/vue3-recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier', - 'plugin:prettier/recommended', - ], - /* - * "off" 或 0 ==> 关闭规则 - * "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行) - * "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错) - */ - rules: { - // eslint (http://eslint.cn/docs/rules) - 'no-var': 'error', // 要求使用 let 或 const 而不是 var - 'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行 - 'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们 - 'prefer-const': 'off', // 此规则旨在标记使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const - 'no-irregular-whitespace': 'off', // 禁止不规则的空白 - - // typeScript (https://typescript-eslint.io/rules) - '@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量 - '@typescript-eslint/no-inferrable-types': 'off', // 可以轻松推断的显式类型可能会增加不必要的冗长 - '@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。 - '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型 - '@typescript-eslint/ban-ts-ignore': 'off', // 禁止使用 @ts-ignore - '@typescript-eslint/ban-types': 'off', // 禁止使用特定类型 - '@typescript-eslint/explicit-function-return-type': 'off', // 不允许对初始化为数字、字符串或布尔值的变量或参数进行显式类型声明 - '@typescript-eslint/no-var-requires': 'off', // 不允许在 import 语句中使用 require 语句 - '@typescript-eslint/no-empty-function': 'off', // 禁止空函数 - '@typescript-eslint/no-use-before-define': 'off', // 禁止在变量定义之前使用它们 - '@typescript-eslint/ban-ts-comment': 'off', // 禁止 @ts- 使用注释或要求在指令后进行描述 - '@typescript-eslint/no-non-null-assertion': 'off', // 不允许使用后缀运算符的非空断言(!) - '@typescript-eslint/explicit-module-boundary-types': 'off', // 要求导出函数和类的公共类方法的显式返回和参数类型 - - // vue (https://eslint.vuejs.org/rules) - 'vue/script-setup-uses-vars': 'error', // 防止 - - diff --git a/frontend/src/components/backup/index.vue b/frontend/src/components/backup/index.vue index 53dee6852..0a4098a71 100644 --- a/frontend/src/components/backup/index.vue +++ b/frontend/src/components/backup/index.vue @@ -58,6 +58,7 @@ import DrawerHeader from '@/components/drawer-header/index.vue'; import { deleteBackupRecord, downloadBackupRecord, searchBackupRecords } from '@/api/modules/setting'; import { Backup } from '@/api/interface/backup'; import { MsgSuccess } from '@/utils/message'; +import { DownloadByPath } from '@/api/modules/files'; const selects = ref([]); const loading = ref(); @@ -145,14 +146,16 @@ const onDownload = async (row: Backup.RecordInfo) => { fileDir: row.fileDir, fileName: row.fileName, }; - const res = await downloadBackupRecord(params); - const downloadUrl = window.URL.createObjectURL(new Blob([res])); - const a = document.createElement('a'); - a.style.display = 'none'; - a.href = downloadUrl; - a.download = row.fileName; - const event = new MouseEvent('click'); - a.dispatchEvent(event); + await downloadBackupRecord(params).then(async (res) => { + const file = await DownloadByPath(res.data); + const downloadUrl = window.URL.createObjectURL(new Blob([file])); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = downloadUrl; + a.download = row.fileName; + const event = new MouseEvent('click'); + a.dispatchEvent(event); + }); }; const onBatchDelete = async (row: Backup.RecordInfo | null) => { diff --git a/frontend/src/components/group/index.vue b/frontend/src/components/group/index.vue index f29b8c5f3..2c01f7123 100644 --- a/frontend/src/components/group/index.vue +++ b/frontend/src/components/group/index.vue @@ -18,9 +18,9 @@ ({{ $t('website.default') }}) - + - +
@@ -59,7 +59,7 @@ import { ref } from 'vue'; import i18n from '@/lang'; import ComplexTable from '@/components/complex-table/index.vue'; -import { CreateGroup, DeleteGroup, GetGroupList, UpdateGroup } from '@/api/modules/host'; +import { CreateGroup, DeleteGroup, GetGroupList, UpdateGroup } from '@/api/modules/group'; import Header from '@/components/drawer-header/index.vue'; import { MsgSuccess } from '@/utils/message'; import { Group } from '@/api/interface/group'; @@ -124,6 +124,7 @@ const saveGroup = async (formEl: FormInstance, group: Group.GroupInfo) => { const setDefault = (group: Group.GroupInfo) => { group.isDefault = true; + group.type = type.value; UpdateGroup(group).then(() => { MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); search(); @@ -145,7 +146,7 @@ const openCreate = () => { isDefault: false, edit: true, }; - data.value.push(g); + data.value.unshift(g); }; const deleteGroup = (index: number) => { diff --git a/frontend/src/components/status/index.vue b/frontend/src/components/status/index.vue index 6955d60c7..86801c253 100644 --- a/frontend/src/components/status/index.vue +++ b/frontend/src/components/status/index.vue @@ -1,7 +1,7 @@ - {{ param.value }} + {{ param.showValue && param.showValue != '' ? param.showValue : param.value }} - +
+ + +
@@ -116,6 +125,8 @@ const get = async () => { edit: d.edit, key: d.key, type: d.type, + values: d.values, + showValue: d.showValue, }); rules[d.key] = [Rules.requiredInput]; if (d.rule) { diff --git a/frontend/src/views/app-store/installed/index.vue b/frontend/src/views/app-store/installed/index.vue index 10058d099..ea73f93a3 100644 --- a/frontend/src/views/app-store/installed/index.vue +++ b/frontend/src/views/app-store/installed/index.vue @@ -201,17 +201,17 @@ import { getAge } from '@/utils/util'; import { useRouter } from 'vue-router'; import { MsgSuccess } from '@/utils/message'; -let data = ref(); -let loading = ref(false); -let syncLoading = ref(false); +const data = ref(); +const loading = ref(false); +const syncLoading = ref(false); let timer: NodeJS.Timer | null = null; const paginationConfig = reactive({ currentPage: 1, pageSize: 20, total: 0, }); -let open = ref(false); -let operateReq = reactive({ +const open = ref(false); +const operateReq = reactive({ installId: 0, operate: '', detailId: 0, @@ -222,9 +222,9 @@ const checkRef = ref(); const deleteRef = ref(); const appParamRef = ref(); const upgradeRef = ref(); -let tags = ref([]); -let activeTag = ref('all'); -let searchReq = reactive({ +const tags = ref([]); +const activeTag = ref('all'); +const searchReq = reactive({ page: 1, pageSize: 15, name: '', @@ -232,8 +232,8 @@ let searchReq = reactive({ update: false, }); const router = useRouter(); -let activeName = ref(i18n.global.t('app.installed')); -let mode = ref('installed'); +const activeName = ref(i18n.global.t('app.installed')); +const mode = ref('installed'); const sync = () => { syncLoading.value = true; diff --git a/frontend/src/views/app-store/installed/upgrade/index.vue b/frontend/src/views/app-store/installed/upgrade/index.vue index 3226b27f1..d624602df 100644 --- a/frontend/src/views/app-store/installed/upgrade/index.vue +++ b/frontend/src/views/app-store/installed/upgrade/index.vue @@ -5,7 +5,14 @@ - + - +
- - - + + + - + {{ $t('commons.button.edit') }} {{ $t('container.pathSelect') }} {{ $t('container.composeTemplate') }} @@ -31,7 +37,7 @@ {{ $t('container.composePathHelper', [composeFile]) }} - + - - - + + + + +
- diff --git a/frontend/src/views/home/app/index.vue b/frontend/src/views/home/app/index.vue index 2e712266c..1ec8d918a 100644 --- a/frontend/src/views/home/app/index.vue +++ b/frontend/src/views/home/app/index.vue @@ -41,7 +41,6 @@ diff --git a/frontend/src/views/host/firewall/ip/index.vue b/frontend/src/views/host/firewall/ip/index.vue new file mode 100644 index 000000000..5979ad397 --- /dev/null +++ b/frontend/src/views/host/firewall/ip/index.vue @@ -0,0 +1,283 @@ + + + diff --git a/frontend/src/views/host/firewall/ip/operate/index.vue b/frontend/src/views/host/firewall/ip/operate/index.vue new file mode 100644 index 000000000..9937b092b --- /dev/null +++ b/frontend/src/views/host/firewall/ip/operate/index.vue @@ -0,0 +1,139 @@ + + + diff --git a/frontend/src/views/host/firewall/port/index.vue b/frontend/src/views/host/firewall/port/index.vue new file mode 100644 index 000000000..3060e4a16 --- /dev/null +++ b/frontend/src/views/host/firewall/port/index.vue @@ -0,0 +1,337 @@ + + + diff --git a/frontend/src/views/host/firewall/port/operate/index.vue b/frontend/src/views/host/firewall/port/operate/index.vue new file mode 100644 index 000000000..93e1b1679 --- /dev/null +++ b/frontend/src/views/host/firewall/port/operate/index.vue @@ -0,0 +1,186 @@ + + + diff --git a/frontend/src/views/host/firewall/status/index.vue b/frontend/src/views/host/firewall/status/index.vue new file mode 100644 index 000000000..4e47a0bea --- /dev/null +++ b/frontend/src/views/host/firewall/status/index.vue @@ -0,0 +1,135 @@ + + + diff --git a/frontend/src/views/host/monitor/index.vue b/frontend/src/views/host/monitor/index.vue index 899b87d79..6a3b8d681 100644 --- a/frontend/src/views/host/monitor/index.vue +++ b/frontend/src/views/host/monitor/index.vue @@ -12,7 +12,7 @@ -
+
@@ -32,7 +32,7 @@ -
+
-
+
@@ -70,7 +70,7 @@ -
+
-
+
@@ -664,4 +664,12 @@ onBeforeUnmount(() => { cursor: pointer; color: var(--el-color-primary); } +.title { + font-size: 16px; + font-weight: 500; +} +.chart { + width: 100%; + height: 400px; +} diff --git a/frontend/src/views/host/security/index.vue b/frontend/src/views/host/security/index.vue deleted file mode 100644 index cdfc73be6..000000000 --- a/frontend/src/views/host/security/index.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/src/views/host/terminal/host/change-group/index.vue b/frontend/src/views/host/terminal/host/change-group/index.vue index 053b85d79..d750b83cd 100644 --- a/frontend/src/views/host/terminal/host/change-group/index.vue +++ b/frontend/src/views/host/terminal/host/change-group/index.vue @@ -6,16 +6,11 @@ - +
- - +
@@ -38,7 +33,8 @@ import { ref, reactive } from 'vue'; import type { ElForm } from 'element-plus'; import { Rules } from '@/global/form-rules'; -import { editHostGroup, GetGroupList } from '@/api/modules/host'; +import { editHostGroup } from '@/api/modules/host'; +import { GetGroupList } from '@/api/modules/group'; import i18n from '@/lang'; import { MsgSuccess } from '@/utils/message'; diff --git a/frontend/src/views/host/terminal/host/index.vue b/frontend/src/views/host/terminal/host/index.vue index 33e085386..2e7a5a696 100644 --- a/frontend/src/views/host/terminal/host/index.vue +++ b/frontend/src/views/host/terminal/host/index.vue @@ -34,8 +34,7 @@
- - +
@@ -84,7 +83,8 @@ import GroupDialog from '@/components/group/index.vue'; import GroupChangeDialog from '@/views/host/terminal/host/change-group/index.vue'; import OperateDialog from '@/views/host/terminal/host/operate/index.vue'; import ComplexTable from '@/components/complex-table/index.vue'; -import { deleteHost, GetGroupList, searchHosts } from '@/api/modules/host'; +import { deleteHost, searchHosts } from '@/api/modules/host'; +import { GetGroupList } from '@/api/modules/group'; import { reactive, ref } from 'vue'; import i18n from '@/lang'; import { Host } from '@/api/interface/host'; diff --git a/frontend/src/views/host/terminal/host/operate/index.vue b/frontend/src/views/host/terminal/host/operate/index.vue index db8a095cd..922d23d1f 100644 --- a/frontend/src/views/host/terminal/host/operate/index.vue +++ b/frontend/src/views/host/terminal/host/operate/index.vue @@ -36,7 +36,22 @@ > - + + + + + {{ $t('terminal.rememberPassword') }} + + @@ -64,7 +79,7 @@ {{ $t('terminal.testConn') }} - + {{ $t('commons.button.confirm') }} @@ -74,15 +89,16 @@ - diff --git a/frontend/src/views/login/components/login-form.vue b/frontend/src/views/login/components/login-form.vue index dc1b47200..6b99747f0 100644 --- a/frontend/src/views/login/components/login-form.vue +++ b/frontend/src/views/login/components/login-form.vue @@ -1,5 +1,5 @@ - + +
- + +
+ + + + + + +
+ + + + + + + + + +
+
+ + + {{ $t('runtime.openrestryWarn') }} + + diff --git a/frontend/src/views/website/website/index.vue b/frontend/src/views/website/website/index.vue index ef95efb9b..b6dc1ecd6 100644 --- a/frontend/src/views/website/website/index.vue +++ b/frontend/src/views/website/website/index.vue @@ -13,6 +13,7 @@ @@ -75,6 +76,7 @@ @@ -137,7 +139,7 @@ fix /> - + {{ $t('commons.service.serviceNotStarted', ['OpenResty']) }} @@ -145,10 +147,10 @@ - + @@ -163,8 +165,8 @@ import ComplexTable from '@/components/complex-table/index.vue'; import { onMounted, reactive, ref } from '@vue/runtime-core'; import CreateWebSite from './create/index.vue'; import DeleteWebsite from './delete/index.vue'; -import WebSiteGroup from './group/index.vue'; -import { ListGroups, OpWebsite, SearchWebsites, UpdateWebsite } from '@/api/modules/website'; +import GroupDialog from '@/components/group/index.vue'; +import { OpWebsite, SearchWebsites, UpdateWebsite } from '@/api/modules/website'; import { Website } from '@/api/interface/website'; import AppStatus from '@/components/app-status/index.vue'; import NginxConfig from './nginx/index.vue'; @@ -177,6 +179,8 @@ import { MsgSuccess } from '@/utils/message'; import { useI18n } from 'vue-i18n'; import { VideoPlay, VideoPause } from '@element-plus/icons-vue'; import MsgInfo from '@/components/msg-info/index.vue'; +import { GetGroupList } from '@/api/modules/group'; +import { Group } from '@/api/interface/group'; const shortcuts = [ { @@ -196,30 +200,31 @@ const shortcuts = [ ]; const loading = ref(false); +const maskShow = ref(true); const createRef = ref(); const deleteRef = ref(); const groupRef = ref(); -let openNginxConfig = ref(false); -let nginxIsExist = ref(false); -let containerName = ref(''); -let nginxStatus = ref(''); -let installPath = ref(''); +const openNginxConfig = ref(false); +const nginxIsExist = ref(false); +const containerName = ref(''); +const nginxStatus = ref(''); +const installPath = ref(''); const uploadRef = ref(); const dialogBackupRef = ref(); const defaultRef = ref(); const data = ref(); let dateRefs: Map = new Map(); -let groups = ref([]); +let groups = ref([]); const paginationConfig = reactive({ currentPage: 1, - pageSize: 15, + pageSize: 10, total: 0, }); let req = reactive({ name: '', page: 1, - pageSize: 15, + pageSize: 10, websiteGroupId: 0, }); @@ -238,9 +243,8 @@ const search = async () => { }; const listGroup = async () => { - await ListGroups().then((res) => { - groups.value = res.data; - }); + const res = await GetGroupList({ type: 'website' }); + groups.value = res.data; }; const setting = () => { @@ -310,6 +314,7 @@ const submitDate = (row: any) => { UpdateWebsite(req).then(() => { row.change = true; MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); + search(); }); }; @@ -359,7 +364,7 @@ const openCreate = () => { }; const openGroup = () => { - groupRef.value.acceptParams(); + groupRef.value.acceptParams({ type: 'website' }); }; const openDefault = () => { diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 94471caa4..b6c09ac24 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -31,6 +31,7 @@ }, // 跳过库检查,解决打包失败 "skipLibCheck": true, + "ignoreDeprecations": "5.0", "suppressImplicitAnyIndexErrors": true }, // "include": ["./src/views"], diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 410986c11..edbce6450 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -36,10 +36,12 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { server: { port: viteEnv.VITE_PORT, open: viteEnv.VITE_OPEN, + host: '0.0.0.0', proxy: { '/api/v1': { target: 'http://localhost:9999/', changeOrigin: true, + ws: true, }, }, }, diff --git a/go.mod b/go.mod index 993a4e97d..d43bbef10 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,21 @@ module github.com/1Panel-dev/1Panel -go 1.18 +go 1.19 require ( github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible github.com/aws/aws-sdk-go v1.44.99 - github.com/compose-spec/compose-go v1.6.0 + github.com/compose-spec/compose-go v1.13.2 github.com/creack/pty v1.1.18 github.com/dgraph-io/badger/v3 v3.2103.5 - github.com/docker/docker v20.10.18+incompatible + github.com/docker/cli v23.0.1+incompatible + github.com/docker/compose/v2 v2.17.2 + github.com/docker/docker v23.0.3+incompatible github.com/docker/go-connections v0.4.0 - github.com/fsnotify/fsnotify v1.5.4 + github.com/fsnotify/fsnotify v1.6.0 github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 github.com/gabriel-vasile/mimetype v1.4.1 + github.com/gin-contrib/gzip v0.0.6 github.com/gin-contrib/i18n v0.0.1 github.com/gin-gonic/gin v1.8.1 github.com/go-acme/lego/v4 v4.9.0 @@ -29,21 +32,24 @@ require ( github.com/minio/minio-go/v7 v7.0.36 github.com/mojocn/base64Captcha v1.3.5 github.com/nicksnyder/go-i18n/v2 v2.1.2 - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 + github.com/opencontainers/image-spec v1.1.0-rc2 github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.1 + github.com/qiniu/go-sdk/v7 v7.14.0 github.com/robfig/cron/v3 v3.0.1 github.com/shirou/gopsutil/v3 v3.23.1 github.com/sirupsen/logrus v1.9.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - github.com/spf13/afero v1.8.2 - github.com/spf13/cobra v1.0.0 - github.com/spf13/viper v1.12.0 + github.com/spf13/afero v1.9.2 + github.com/spf13/cobra v1.6.1 + github.com/spf13/viper v1.14.0 + github.com/subosito/gotenv v1.4.1 github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a github.com/swaggo/gin-swagger v1.5.3 github.com/swaggo/swag v1.8.4 + github.com/tencentyun/cos-go-sdk-v5 v0.7.41 github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa + golang.org/x/crypto v0.2.0 golang.org/x/net v0.7.0 golang.org/x/text v0.7.0 gopkg.in/square/go-jose.v2 v2.6.0 @@ -53,27 +59,55 @@ require ( ) require ( + github.com/AlecAivazis/survey/v2 v2.3.6 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/Microsoft/hcsshim v0.9.6 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect github.com/andybalholm/brotli v1.0.4 // indirect + github.com/aws/aws-sdk-go-v2 v1.16.3 // indirect + github.com/aws/aws-sdk-go-v2/config v1.15.5 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.16.4 // indirect + github.com/aws/smithy-go v1.11.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/buger/goterm v1.0.4 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect github.com/cloudflare/cloudflare-go v0.49.0 // indirect - github.com/containerd/cgroups v1.0.4 // indirect - github.com/containerd/containerd v1.6.18 // indirect + github.com/containerd/console v1.0.3 // indirect + github.com/containerd/containerd v1.6.19 // indirect + github.com/containerd/continuity v0.3.0 // indirect + github.com/containerd/ttrpc v1.1.0 // indirect + github.com/containerd/typeurl v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb // indirect + github.com/distribution/distribution/v3 v3.0.0-20230223072852-e5d5810851d1 // indirect + github.com/docker/buildx v0.10.4 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect + github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.13.0 // indirect + github.com/felixge/httpsnoop v1.0.2 // indirect + github.com/fsnotify/fsevents v0.1.1 // indirect + github.com/fvbommel/sortorder v1.0.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.19.6 // indirect @@ -82,25 +116,40 @@ require ( github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/goccy/go-json v0.9.7 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v1.12.1 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-querystring v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/googleapis/gnostic v0.5.5 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.1 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/imdario/mergo v0.3.13 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/imdario/mergo v0.3.14 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect 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/jonboulle/clockwork v0.3.1-0.20230117163003-a89700cec744 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.15.9 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/klauspost/compress v1.15.12 // indirect github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/fs v0.1.0 // indirect @@ -108,53 +157,109 @@ require ( github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mattn/go-sqlite3 v1.14.16 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/miekg/dns v1.1.50 // indirect + github.com/miekg/pkcs11 v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moby/sys/mount v0.3.3 // indirect + github.com/moby/buildkit v0.11.5 // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/patternmatcher v0.5.0 // indirect + github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect - github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/signal v0.7.0 // indirect + github.com/moby/sys/symlink v0.2.0 // indirect + github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/mozillazg/go-httpheader v0.2.1 // indirect github.com/nrdcg/dnspod-go v0.4.0 // indirect github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/runc v1.1.4 // indirect + github.com/opencontainers/runc v1.1.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pierrec/lz4/v4 v4.1.15 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/rs/xid v1.4.0 // indirect + github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.3.0 // indirect + github.com/stretchr/testify v1.8.2 // indirect github.com/therootcompany/xz v1.0.1 // indirect + github.com/theupdateframework/notary v0.7.0 // indirect + github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect + github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa // indirect + github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect + github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect github.com/ugorji/go/codec v1.2.7 // indirect github.com/ulikunitz/xz v0.5.10 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/weppos/publicsuffix-go v0.30.0 // 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/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.23.0 // indirect - go.opentelemetry.io/otel v1.3.0 // indirect - go.opentelemetry.io/otel/trace v1.3.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect + go.opentelemetry.io/otel v1.14.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 // indirect + go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect + go.opentelemetry.io/otel/metric v0.27.0 // indirect + go.opentelemetry.io/otel/sdk v1.4.1 // indirect + go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/proto/otlp v0.12.0 // indirect golang.org/x/image v0.5.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect + golang.org/x/mod v0.6.0 // indirect + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect + golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.5.0 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect - golang.org/x/tools v0.1.12 // indirect - google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/ini.v1 v1.66.6 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/time v0.1.0 // indirect + golang.org/x/tools v0.2.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect + google.golang.org/grpc v1.50.1 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/api v0.26.3 // indirect + k8s.io/apimachinery v0.26.3 // indirect + k8s.io/client-go v0.24.1 // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) -replace golang.org/x/net => golang.org/x/net v0.7.0 +replace ( + github.com/cucumber/godog => github.com/cucumber/godog v0.12.6 + golang.org/x/net => golang.org/x/net v0.7.0 + k8s.io/api => k8s.io/api v0.22.4 + k8s.io/apimachinery => k8s.io/apimachinery v0.22.4 + k8s.io/apiserver => k8s.io/apiserver v0.22.4 + k8s.io/client-go => k8s.io/client-go v0.22.4 +) diff --git a/go.sum b/go.sum index 81bf6db75..54175d1df 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -18,12 +17,15 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.104.0 h1:gSmWO7DY1vOm0MVU6DNXM11BWHHsTUmsC5cv1fuW5X8= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= +cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -37,63 +39,43 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw= +github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY= -github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/Microsoft/hcsshim v0.9.7 h1:mKNHW/Xvv1aFH87Jb6ERDzXTJTLPlmzfZ28VBFD/bfg= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= +github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU= github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible h1:QoRMR0TCctLDqBCMyOu1eXdZyMw3F7uGA9qPn2J4+R8= @@ -103,25 +85,46 @@ github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.44.99 h1:ITZ9q/fmH+Ksaz2TbyMU2d19vOOWs/hAlt8NbXAieHw= github.com/aws/aws-sdk-go v1.44.99/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/aws/aws-sdk-go-v2 v1.16.3 h1:0W1TSJ7O6OzwuEvIXAtJGvOeQ0SGAhcpxPN2/NK5EhM= +github.com/aws/aws-sdk-go-v2 v1.16.3/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU= +github.com/aws/aws-sdk-go-v2/config v1.15.5 h1:P+xwhr6kabhxDTXTVH9YoHkqjLJ0wVVpIUHtFNr2hjU= +github.com/aws/aws-sdk-go-v2/config v1.15.5/go.mod h1:ZijHHh0xd/A+ZY53az0qzC5tT46kt4JVCePf2NX9Lk4= +github.com/aws/aws-sdk-go-v2/credentials v1.12.0 h1:4R/NqlcRFSkR0wxOhgHi+agGpbEr5qMCjn7VqUIJY+E= +github.com/aws/aws-sdk-go-v2/credentials v1.12.0/go.mod h1:9YWk7VW+eyKsoIL6/CljkTrNVWBSK9pkqOPUuijid4A= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4 h1:FP8gquGeGHHdfY6G5llaMQDF+HAf20VKc8opRwmjf04= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.4/go.mod h1:u/s5/Z+ohUQOPXl00m2yJVyioWDECsbpXTQlaqSlufc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10 h1:uFWgo6mGJI1n17nbcvSc6fxVuR3xLNqvXt12JCnEcT8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.10/go.mod h1:F+EZtuIwjlv35kRJPyBGcsA4f7bnSoz15zOQ2lJq1Z4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4 h1:cnsvEKSoHN4oAN7spMMr0zhEW2MHnhAVpmqQg8E6UcM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.4/go.mod h1:8glyUqVIM4AmeenIsPo0oVh3+NUwnsQml2OFupfQW+0= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11 h1:6cZRymlLEIlDTEB0+5+An6Zj1CKt6rSE69tOmFeu1nk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.11/go.mod h1:0MR+sS1b/yxsfAPvAESrw8NfwUoxMinDyw6EYR9BS2U= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.4 h1:b16QW0XWl0jWjLABFc1A+uh145Oqv+xDcObNk0iQgUk= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.4/go.mod h1:uKkN7qmSIsNJVyMtxNQoCEYMvFEXbOg9fwCJPdfp2u8= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.4 h1:Uw5wBybFQ1UeA9ts0Y07gbv0ncZnIAyw858tDW0NP2o= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.4/go.mod h1:cPDwJwsP4Kff9mldCXAmddjJL6JGQqtA3Mzer2zyr88= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.4 h1:+xtV90n3abQmgzk1pS++FdxZTrPEDgQng6e4/56WR2A= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.4/go.mod h1:lfSYenAXtavyX2A1LsViglqlG9eEFYxNryTZS5rn3QE= +github.com/aws/smithy-go v1.11.2 h1:eG/N+CcUMAvsdffgMvjMKwfyDzIkjM6pfxMJ8Mzc6mE= +github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= +github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 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= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= +github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= +github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/bugsnag-go v1.5.0 h1:tP8hiPv1pGGW3LA6LKy5lW6WG+y9J2xWUdPd3WC452k= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -130,225 +133,135 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4= github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= +github.com/cloudflare/cfssl v1.4.1 h1:vScfU2DrIUI9VPHBVeeAQ0q5A+9yshO1Gz+3QoUQiKw= github.com/cloudflare/cloudflare-go v0.49.0 h1:KqJYk/YQ5ZhmyYz1oa4kGDskfF1gVuZfqesaJ/XDLto= github.com/cloudflare/cloudflare-go v0.49.0/go.mod h1:h0QgcIZ3qEXwFiwfBO8sQxjVdYsLX+PfD7NFEnANaKg= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/compose-spec/compose-go v1.6.0 h1:7Ol/UULMUtbPmB0EYrETASRoum821JpOh/XaEf+hN+Q= -github.com/compose-spec/compose-go v1.6.0/go.mod h1:os+Ulh2jlZxY1XT1hbciERadjSUU/BtZ6+gcN7vD7J0= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/compose-spec/compose-go v1.13.2 h1:FDfb5ddIpbGbxLRg5qjObOf5CrWbKnuHZ+zvpEdCqKc= +github.com/compose-spec/compose-go v1.13.2/go.mod h1:SQfvBkB9u8bLhrj4RQP4I777SqzNLSl9/fNnfvOOjek= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= -github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/containerd v1.6.19 h1:F0qgQPrG0P2JPgwpxWxYavrVeXAG0ezUIB9Z/4FTUAU= +github.com/containerd/containerd v1.6.19/go.mod h1:HZCDMn4v/Xl2579/MvtOC2M206i+JJ6VxFWU/NetrGY= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= +github.com/containerd/nydus-snapshotter v0.3.1 h1:b8WahTrPkt3XsabjG2o/leN4fw3HWZYr+qxo/Z8Mfzk= +github.com/containerd/stargz-snapshotter v0.13.0 h1:3zr1/IkW1aEo6cMYTQeZ4L2jSuCN+F4kgGfjnuowe4U= +github.com/containerd/stargz-snapshotter/estargz v0.13.0 h1:fD7AwuVV+B40p0d9qVkH/Au1qhp8hn/HWJHIYjpEcfw= +github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb h1:oCCuuU3kMO3sjZH/p7LamvQNW9SWoT4yQuMGcdSxGAE= -github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/distribution/distribution/v3 v3.0.0-20230223072852-e5d5810851d1 h1:OtfRoaZ54jKZ7jl9WuxqekousLR9T63iJf0y2EdC2S4= +github.com/distribution/distribution/v3 v3.0.0-20230223072852-e5d5810851d1/go.mod h1:r5XLH1cp+Wau2jxdptkYsFvvvzPPQTIe8eUuQ0vq30Q= +github.com/docker/buildx v0.10.4 h1:qsHwlUZaLu7UQkDhJDSRQ+jrvWf6mqwwtY+gWO3rzuA= +github.com/docker/buildx v0.10.4/go.mod h1:2mHDjD0QevclBGYIXDOWY/ZU71JAzx7w4CfgroYbHQw= +github.com/docker/cli v23.0.1+incompatible h1:LRyWITpGzl2C9e9uGxzisptnxAn1zfZKXy13Ul2Q5oM= +github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/compose/v2 v2.17.2 h1:MP0wtvPifrh3Ikq6XfyO3cOhya5ubTXOYn70G+ojnek= +github.com/docker/compose/v2 v2.17.2/go.mod h1:h5uld3t0RsL5h8rtkRaJtrFLJ3TJ9GOKdbxa4i1M1dY= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.18+incompatible h1:SN84VYXTBNGn92T/QwIRPlum9zfemfitN7pbsp26WSc= -github.com/docker/docker v20.10.18+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/docker v23.0.3+incompatible h1:9GhVsShNWz1hO//9BNg/dpMnZW25KydO4wtVxWAIbho= +github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +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.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +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.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsevents v0.1.1 h1:/125uxJvvoSDDBPen6yUZbil8J9ydKZnnl3TWWmvnkw= +github.com/fsnotify/fsevents v0.1.1/go.mod h1:+d+hS27T6k5J8CRaPLKFgwKYcpS7GwW3Ule9+SC2ZRc= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 h1:6VSn3hB5U5GeA6kQw4TwWIWbOhtvR2hmbBJnTOtqTWc= github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6/go.mod h1:YxOVT5+yHzKvwhsiSIWmbAYM3Dr9AEEbER2dVayfBkg= +github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= +github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q= github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= @@ -366,36 +279,32 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gormigrate/gormigrate/v2 v2.0.2 h1:YV4Lc5yMQX8ahVW0ENPq6sPhrhdkGukc6fPRYmZ1R6Y= github.com/go-gormigrate/gormigrate/v2 v2.0.2/go.mod h1:vld36QpBTfTzLealsHsmQQJK5lSwJt6wiORv+oFX8/I= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 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/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +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 v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 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= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= @@ -408,42 +317,39 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= 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.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw= github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk= github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -456,6 +362,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -481,6 +388,9 @@ github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE= github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -495,13 +405,17 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -516,62 +430,64 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0= github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/imdario/mergo v0.3.14 h1:fOqeC1+nCuuk6PKQdg9YmosXX7Y7mHX6R/0ZldI9iHo= +github.com/imdario/mergo v0.3.14/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/pgconn v1.12.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= @@ -582,45 +498,50 @@ github.com/jackc/pgtype v1.11.0 h1:u4uiGPz/1hryuXzyaBhSk6dnIyyG2683olG2OV+UUgs= github.com/jackc/pgx/v4 v4.16.1 h1:JzTglcal01DrghUqt+PmzWsZx/Yh7SC/CTQmSBMTd0Y= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= +github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE= +github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.3.1-0.20230117163003-a89700cec744 h1:fJ+REXDOpsMqA2spt3wAq3HGJJvWnNitGK2KVZTos+8= +github.com/jonboulle/clockwork v0.3.1-0.20230117163003-a89700cec744/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/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= +github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= +github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= 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.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -640,78 +561,86 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 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 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= +github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 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.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mholt/archiver/v4 v4.0.0-alpha.7 h1:xzByj8G8tj0Oq7ZYYU4+ixL/CVb5ruWCm0EZQ1PjOkE= github.com/mholt/archiver/v4 v4.0.0-alpha.7/go.mod h1:Fs8qUkO74HHaidabihzYephJH8qmGD/nCP6tE5xC9BM= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +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/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.36 h1:KPzAl8C6jcRFEUsGUHR6deRivvKATPNZThzi7D9y/sc= github.com/minio/minio-go/v7 v7.0.36/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +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/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/buildkit v0.11.5 h1:S6YrFJ0bfBT2w9e8kOxqsDV8Bw+HtfqdB6eHL17BXRI= +github.com/moby/buildkit v0.11.5/go.mod h1:P5Qi041LvCfhkfYBHry+Rwoo3Wi6H971J2ggE+PcIoo= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= -github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= +github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= +github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc= +github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -723,12 +652,13 @@ github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4Pfo github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ= +github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/nicksnyder/go-i18n/v2 v2.1.2 h1:QHYxcUJnGHBaq7XbvgunmZ2Pn0focXFqTD61CkH146c= github.com/nicksnyder/go-i18n/v2 v2.1.2/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -737,73 +667,48 @@ github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgP 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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg= -github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4= +github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= -github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -813,40 +718,47 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk= +github.com/qiniu/go-sdk/v7 v7.14.0 h1:6icihMTKHoKMmeU1mqtIoHUv7c1LrLjYm8wTQaYDqmw= +github.com/qiniu/go-sdk/v7 v7.14.0/go.mod h1:btsaOc8CA3hdVloULfFdDgDc+g4f3TDZEFsDY0BLE+w= +github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -856,66 +768,62 @@ github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE= +github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ= +github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= +github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spdx/tools-golang v0.3.1-0.20230104082527-d6f58551be3f h1:9B623Cfs+mclYK6dsae7gLSwuIBHvlgmEup87qpqsAQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -923,12 +831,12 @@ 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.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= -github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY= github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= github.com/swaggo/gin-swagger v1.5.3 h1:8mWmHLolIbrhJJTflsaFoZzRBYVmEE7JZGIq08EiC0Q= @@ -936,19 +844,27 @@ github.com/swaggo/gin-swagger v1.5.3/go.mod h1:3XJKSfHjDMB5dBo/0rrTXidPmgLeqsX89 github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/swaggo/swag v1.8.4 h1:oGB351qH1JqUqK1tsMYEE5qTBbPk394BhsZxmUfebcI= github.com/swaggo/swag v1.8.4/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4= +github.com/tencentyun/cos-go-sdk-v5 v0.7.41 h1:iU0Li/Np78H4SBna0ECQoF3mpgi6ImLXU+doGzPFXGc= +github.com/tencentyun/cos-go-sdk-v5 v0.7.41/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= +github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= +github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= +github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA= +github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa h1:XOFp/3aBXlqmOFAg3r6e0qQjPnK5I970LilqX+Is1W8= +github.com/tonistiigi/fsutil v0.0.0-20230105215944-fb433841cbfa/go.mod h1:AvLEd1LEIl64G2Jpgwo7aVV5lGH0ePcKl0ygGIHNYl8= +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-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc= +github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -958,27 +874,22 @@ github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95 github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= +github.com/weppos/publicsuffix-go v0.30.0 h1:QHPZ2GRu/YE7cvejH9iyavPOkVCB4dNxp2ZvtT+vQLY= +github.com/weppos/publicsuffix-go v0.30.0/go.mod h1:kBi8zwYnR0zrbm8RcuN1o9Fzgpnnn+btVN8uWPMyXAY= +github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE= 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 v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= 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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f h1:C8De+7emQKojPBC+mXA0fr39XN5mKjRm9IUzdxI4whI= github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -991,15 +902,8 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c h1:ufDm/IlBYZYLuiqvQuhpTKwrcAS2OlXEzWbDvTVGbSQ= +github.com/zmap/zlint v1.1.0 h1:Vyh2GmprXw5TLmKmkTa2BgFvvYAFBValBFesqkKsszM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1008,38 +912,62 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 h1:n9b7AAdbQtQ0k9dm0Dm2/KUcUqtG8i2O15KzNaDze8c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0/go.mod h1:LsankqVDx4W+RhZNA5uWarULII/MBhF5qwCYxTuyXjs= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 h1:Wjp9vsVSIEyvdiaECfqxY9xBqQ7JaSCGtvHgR4doXZk= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0/go.mod h1:vHItvsnJtp7ES++nFLLFBzUWny7fJQSvTlxFcqQGUr4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 h1:SLme4Porm+UwX0DdHMxlwRt7FzPSE0sys81bet2o0pU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII= go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= -go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk= +go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4= +go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 h1:imIM3vRDMyZK1ypQlQlO+brE22I9lRhJsBDXpDWjlz8= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1/go.mod h1:o5RW5o2pKpJLD5dNTCmjF1DorYwMeFJmb/rKr5sLaa8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 h1:AxqDiGk8CorEXStMDZF5Hz9vo9Z7ZZ+I5m8JRl/ko40= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 h1:8qOago/OqoFclMUUj/184tZyRdDZFpcejSjbk5Jrl6Y= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1/go.mod h1:VwYo0Hak6Efuy0TXsZs8o1hnV3dHDPNtDbycG0hI8+M= +go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk= +go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw= +go.opentelemetry.io/otel/metric v0.27.0 h1:HhJPsGhJoKRSegPQILFbODU56NS/L1UE4fS1sC5kIwQ= +go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g= +go.opentelemetry.io/otel/sdk v1.4.1 h1:J7EaW71E0v87qflB4cDolaqq3AcujGrtyIPGQoZOB0Y= +go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE= go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= -go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE= +go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc= +go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c= +go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= +golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1077,8 +1005,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1090,6 +1019,10 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/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.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= 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= @@ -1101,52 +1034,41 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1154,53 +1076,50 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/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-20220704084225-05e143d24a9e/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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1213,18 +1132,13 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1235,11 +1149,8 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1262,17 +1173,14 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1281,15 +1189,16 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= 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= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1315,14 +1224,13 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1331,7 +1239,6 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1340,32 +1247,31 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 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.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1380,7 +1286,10 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= 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= @@ -1394,34 +1303,32 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 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 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= +gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= +gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1434,7 +1341,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= @@ -1445,11 +1351,7 @@ gorm.io/driver/sqlserver v1.3.2 h1:yYt8f/xdAKLY7lCCyXxIUEgZ/WsURos3dHrx8MKFGAk= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE= gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1457,43 +1359,28 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/api v0.22.4 h1:UvyHW0ezB2oIgHAxlYoo6UJQObYXU7awuNarwoHEOjw= +k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk= +k8s.io/apimachinery v0.22.4 h1:9uwcvPpukBw/Ri0EUmWz+49cnFtaoiyEhQTK+xOe7Ck= +k8s.io/apimachinery v0.22.4/go.mod h1:yU6oA6Gnax9RrxGzVvPFFJ+mpnW6PBSqp0sx0I0HHW0= +k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg= +k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=