diff --git a/agent/app/api/v2/dashboard.go b/agent/app/api/v2/dashboard.go index ea7d3f06c..673fb9a50 100644 --- a/agent/app/api/v2/dashboard.go +++ b/agent/app/api/v2/dashboard.go @@ -137,24 +137,3 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) { data := dashboardService.LoadCurrentInfo(ioOption, netOption) helper.SuccessWithData(c, data) } - -// @Tags Dashboard -// @Summary System restart -// @Accept json -// @Param operation path string true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Security Timestamp -// @Router /dashboard/system/restart/:operation [post] -func (b *BaseApi) SystemRestart(c *gin.Context) { - operation, ok := c.Params.Get("operation") - if !ok { - helper.BadRequest(c, errors.New("error operation in path")) - return - } - if err := dashboardService.Restart(operation); err != nil { - helper.InternalServer(c, err) - return - } - helper.SuccessWithOutData(c) -} diff --git a/agent/app/service/dashboard.go b/agent/app/service/dashboard.go index c3ea58a4b..23daceb5e 100644 --- a/agent/app/service/dashboard.go +++ b/agent/app/service/dashboard.go @@ -42,7 +42,6 @@ type IDashboardService interface { LoadAppLauncher() ([]dto.AppLauncher, error) ListLauncherOption(filter string) ([]dto.LauncherOption, error) - Restart(operation string) error } func NewIDashboardService() IDashboardService { @@ -78,23 +77,6 @@ func (u *DashboardService) Sync(req dto.SyncFromMaster) error { } } -func (u *DashboardService) Restart(operation string) error { - if operation != "1panel" && operation != "system" { - return fmt.Errorf("handle restart operation %s failed, err: nonsupport such operation", operation) - } - itemCmd := fmt.Sprintf("%s systemctl restart 1panel-agent.service", cmd.SudoHandleCmd()) - if operation == "system" { - itemCmd = fmt.Sprintf("%s reboot", cmd.SudoHandleCmd()) - } - go func() { - stdout, err := cmd.Exec(itemCmd) - if err != nil { - global.LOG.Errorf("handle %s failed, err: %v", itemCmd, stdout) - } - }() - return nil -} - func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) { var baseInfo dto.OsInfo hostInfo, err := host.Info() diff --git a/agent/router/ro_dashboard.go b/agent/router/ro_dashboard.go index 828a32a6e..da5e2677d 100644 --- a/agent/router/ro_dashboard.go +++ b/agent/router/ro_dashboard.go @@ -18,6 +18,5 @@ func (s *DashboardRouter) InitRouter(Router *gin.RouterGroup) { cmdRouter.GET("/base/:ioOption/:netOption", baseApi.LoadDashboardBaseInfo) cmdRouter.GET("/current/node", baseApi.LoadCurrentInfoForNode) cmdRouter.GET("/current/:ioOption/:netOption", baseApi.LoadDashboardCurrentInfo) - cmdRouter.POST("/system/restart/:operation", baseApi.SystemRestart) } } diff --git a/core/app/api/v2/host.go b/core/app/api/v2/host.go index 558312fe1..a299fc553 100644 --- a/core/app/api/v2/host.go +++ b/core/app/api/v2/host.go @@ -9,6 +9,7 @@ import ( "github.com/1Panel-dev/1Panel/core/app/api/v2/helper" "github.com/1Panel-dev/1Panel/core/app/dto" + "github.com/1Panel-dev/1Panel/core/app/service" "github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/utils/copier" "github.com/1Panel-dev/1Panel/core/utils/encrypt" @@ -159,7 +160,7 @@ func (b *BaseApi) DeleteHost(c *gin.Context) { // @Summary Update host // @Accept json // @Param request body dto.HostOperate true "request" -// @Success 200 +// @Success 200 {object} dto.HostInfo // @Security ApiKeyAuth // @Security Timestamp // @Router /core/hosts/update [post] @@ -214,11 +215,12 @@ func (b *BaseApi) UpdateHost(c *gin.Context) { upMap["pass_phrase"] = req.PassPhrase } upMap["description"] = req.Description - if err := hostService.Update(req.ID, upMap); err != nil { + hostItem, err := hostService.Update(req.ID, upMap) + if err != nil { helper.InternalServer(c, err) return } - helper.SuccessWithOutData(c) + helper.SuccessWithData(c, hostItem) } // @Tags Host @@ -238,13 +240,34 @@ func (b *BaseApi) UpdateHostGroup(c *gin.Context) { upMap := make(map[string]interface{}) upMap["group_id"] = req.GroupID - if err := hostService.Update(req.ID, upMap); err != nil { + if _, err := hostService.Update(req.ID, upMap); err != nil { helper.InternalServer(c, err) return } helper.SuccessWithOutData(c) } +// @Tags Host +// @Summary Get host info +// @Accept json +// @Param request body dto.OperateByID true "request" +// @Success 200 {object} dto.HostInfo +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /core/hosts/info [post] +func (b *BaseApi) GetHostByID(c *gin.Context) { + var req dto.OperateByID + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + info, err := hostService.GetHostByID(req.ID) + if err != nil { + helper.InternalServer(c, err) + return + } + helper.SuccessWithData(c, info) +} + func (b *BaseApi) WsSsh(c *gin.Context) { wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) if err != nil { @@ -265,7 +288,7 @@ func (b *BaseApi) WsSsh(c *gin.Context) { if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { return } - host, err := hostService.GetHostInfo(uint(id)) + host, err := service.GetHostInfo(uint(id)) if wshandleError(wsConn, errors.WithMessage(err, "load host info by id failed")) { return } diff --git a/core/app/service/host.go b/core/app/service/host.go index 297e9c398..0e08a9cb3 100644 --- a/core/app/service/host.go +++ b/core/app/service/host.go @@ -20,11 +20,11 @@ type HostService struct{} type IHostService interface { TestLocalConn(id uint) bool TestByInfo(req dto.HostConnTest) bool - GetHostInfo(id uint) (*model.Host, error) + GetHostByID(id uint) (*dto.HostInfo, error) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) SearchWithPage(search dto.SearchHostWithPage) (int64, interface{}, error) Create(hostDto dto.HostOperate) (*dto.HostInfo, error) - Update(id uint, upMap map[string]interface{}) error + Update(id uint, upMap map[string]interface{}) (*dto.HostInfo, error) Delete(id []uint) error EncryptHost(itemVal string) (string, error) @@ -124,33 +124,6 @@ func (u *HostService) TestLocalConn(id uint) bool { return true } -func (u *HostService) GetHostInfo(id uint) (*model.Host, error) { - host, err := hostRepo.Get(repo.WithByID(id)) - if err != nil { - return nil, buserr.New("ErrRecordNotFound") - } - if len(host.Password) != 0 { - host.Password, err = encrypt.StringDecrypt(host.Password) - if err != nil { - return nil, err - } - } - if len(host.PrivateKey) != 0 { - host.PrivateKey, err = encrypt.StringDecrypt(host.PrivateKey) - if err != nil { - return nil, err - } - } - - if len(host.PassPhrase) != 0 { - host.PassPhrase, err = encrypt.StringDecrypt(host.PassPhrase) - if err != nil { - return nil, err - } - } - return &host, err -} - func (u *HostService) SearchWithPage(req dto.SearchHostWithPage) (int64, interface{}, error) { var options []global.DBOption if len(req.Info) != 0 { @@ -230,6 +203,48 @@ func (u *HostService) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, e return datas, err } +func (u *HostService) GetHostByID(id uint) (*dto.HostInfo, error) { + var item dto.HostInfo + var host model.Host + if id == 0 { + host, _ = hostRepo.Get(repo.WithByName("local")) + } else { + host, _ = hostRepo.Get(repo.WithByID(id)) + } + if host.ID == 0 { + return nil, buserr.New("ErrRecordNotFound") + } + if err := copier.Copy(&item, &host); err != nil { + return nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) + } + if !item.RememberPassword { + item.Password = "" + item.PrivateKey = "" + item.PassPhrase = "" + return &item, nil + } + var err error + if len(host.Password) != 0 { + item.Password, err = encrypt.StringDecrypt(host.Password) + if err != nil { + return nil, err + } + } + if len(host.PrivateKey) != 0 { + item.PrivateKey, err = encrypt.StringDecrypt(host.PrivateKey) + if err != nil { + return nil, err + } + } + if len(host.PassPhrase) != 0 { + item.PassPhrase, err = encrypt.StringDecrypt(host.PassPhrase) + if err != nil { + return nil, err + } + } + return &item, err +} + func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) { if req.Name == "local" { return nil, buserr.New("ErrRecordExist") @@ -297,8 +312,16 @@ func (u *HostService) Delete(ids []uint) error { return hostRepo.Delete(repo.WithByIDs(ids)) } -func (u *HostService) Update(id uint, upMap map[string]interface{}) error { - return hostRepo.Update(id, upMap) +func (u *HostService) Update(id uint, upMap map[string]interface{}) (*dto.HostInfo, error) { + if err := hostRepo.Update(id, upMap); err != nil { + return nil, err + } + hostItem, _ := hostRepo.Get(repo.WithByID(id)) + var hostinfo dto.HostInfo + if err := copier.Copy(&hostinfo, &hostItem); err != nil { + return nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil) + } + return &hostinfo, nil } func (u *HostService) EncryptHost(itemVal string) (string, error) { @@ -309,3 +332,30 @@ func (u *HostService) EncryptHost(itemVal string) (string, error) { keyItem, err := encrypt.StringEncrypt(string(privateKey)) return keyItem, err } + +func GetHostInfo(id uint) (*model.Host, error) { + host, err := hostRepo.Get(repo.WithByID(id)) + if err != nil { + return nil, buserr.New("ErrRecordNotFound") + } + if len(host.Password) != 0 { + host.Password, err = encrypt.StringDecrypt(host.Password) + if err != nil { + return nil, err + } + } + if len(host.PrivateKey) != 0 { + host.PrivateKey, err = encrypt.StringDecrypt(host.PrivateKey) + if err != nil { + return nil, err + } + } + + if len(host.PassPhrase) != 0 { + host.PassPhrase, err = encrypt.StringDecrypt(host.PassPhrase) + if err != nil { + return nil, err + } + } + return &host, err +} diff --git a/core/constant/common.go b/core/constant/common.go index f5d395327..587bad8ba 100644 --- a/core/constant/common.go +++ b/core/constant/common.go @@ -51,17 +51,16 @@ var WebUrlMap = map[string]struct{}{ "/ai/model": {}, "/ai/gpu": {}, - "/containers": {}, - "/containers/container": {}, - "containers/container/operate": {}, - "/containers/image": {}, - "/containers/network": {}, - "/containers/volume": {}, - "/containers/repo": {}, - "/containers/compose": {}, - "/containers/template": {}, - "/containers/setting": {}, - "/containers/dashboard": {}, + "/containers": {}, + "/containers/container": {}, + "/containers/image": {}, + "/containers/network": {}, + "/containers/volume": {}, + "/containers/repo": {}, + "/containers/compose": {}, + "/containers/template": {}, + "/containers/setting": {}, + "/containers/dashboard": {}, "/cronjobs": {}, @@ -147,6 +146,7 @@ var WebUrlMap = map[string]struct{}{ } var DynamicRoutes = []string{ + `^/containers/container/operate/[^/]+$`, `^/containers/composeDetail/[^/]+$`, `^/databases/mysql/setting/[^/]+/[^/]+$`, `^/databases/postgresql/setting/[^/]+/[^/]+$`, diff --git a/core/router/ro_host.go b/core/router/ro_host.go index f96983ec8..c53e41ddc 100644 --- a/core/router/ro_host.go +++ b/core/router/ro_host.go @@ -16,6 +16,7 @@ func (s *HostRouter) InitRouter(Router *gin.RouterGroup) { baseApi := v2.ApiGroupApp.BaseApi { hostRouter.POST("", baseApi.CreateHost) + hostRouter.POST("/info", baseApi.GetHostByID) hostRouter.POST("/del", baseApi.DeleteHost) hostRouter.POST("/update", baseApi.UpdateHost) hostRouter.POST("/update/group", baseApi.UpdateHostGroup) diff --git a/core/utils/ssh/ssh.go b/core/utils/ssh/ssh.go index 1528f4379..b81cb6736 100644 --- a/core/utils/ssh/ssh.go +++ b/core/utils/ssh/ssh.go @@ -71,6 +71,13 @@ func (c *SSHClient) Run(shell string) (string, error) { return string(buf), err } +func (c *SSHClient) SudoHandleCmd() string { + if _, err := c.Run("sudo -n ls"); err == nil { + return "sudo " + } + return "" +} + func (c *SSHClient) Runf(shell string, args ...interface{}) (string, error) { session, err := c.Client.NewSession() if err != nil { diff --git a/frontend/src/api/modules/terminal.ts b/frontend/src/api/modules/terminal.ts index 3c46e12e1..1c049dfc8 100644 --- a/frontend/src/api/modules/terminal.ts +++ b/frontend/src/api/modules/terminal.ts @@ -7,6 +7,9 @@ import { deepCopy } from '@/utils/util'; export const searchHosts = (params: Host.SearchWithPage) => { return http.post>(`/core/hosts/search`, params); }; +export const getHostByID = (id: number) => { + return http.post(`/core/hosts/info`, { id: id }); +}; export const getHostTree = (params: Host.ReqSearch) => { return http.post>(`/core/hosts/tree`, params); }; diff --git a/frontend/src/components/v-charts/components/Line.vue b/frontend/src/components/v-charts/components/Line.vue index 0907d4283..ddc08498d 100644 --- a/frontend/src/components/v-charts/components/Line.vue +++ b/frontend/src/components/v-charts/components/Line.vue @@ -52,11 +52,11 @@ const seriesStyle = [ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, - color: 'rgba(0, 94, 235, .5)', + color: 'rgba(0, 94, 235, .3)', }, { offset: 1, - color: 'rgba(0, 94, 235, 0)', + color: 'rgba(0, 94, 235, .4)', }, ]), }, @@ -64,11 +64,11 @@ const seriesStyle = [ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, - color: 'rgba(27, 143, 60, .5)', + color: 'rgba(27, 143, 60, .3)', }, { offset: 1, - color: 'rgba(27, 143, 60, 0)', + color: 'rgba(27, 143, 60, .4)', }, ]), }, @@ -76,11 +76,11 @@ const seriesStyle = [ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, - color: 'rgba(249, 199, 79, .5)', + color: 'rgba(249, 199, 79, .3)', }, { offset: 1, - color: 'rgba(249, 199, 79, 0)', + color: 'rgba(249, 199, 79, .4)', }, ]), }, @@ -88,11 +88,11 @@ const seriesStyle = [ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, - color: 'rgba(255, 173, 177, 0.5)', + color: 'rgba(255, 173, 177, 0.3)', }, { offset: 1, - color: 'rgba(255, 173, 177, 0)', + color: 'rgba(255, 173, 177, .4)', }, ]), }, diff --git a/frontend/src/views/container/compose/detail/index.vue b/frontend/src/views/container/compose/detail/index.vue index 21c5571fa..31a50b3eb 100644 --- a/frontend/src/views/container/compose/detail/index.vue +++ b/frontend/src/views/container/compose/detail/index.vue @@ -8,11 +8,11 @@
- {{ $t('app.start') }} + {{ $t('commons.operate.start') }} - {{ $t('app.stop') }} + {{ $t('commons.operate.stop') }} @@ -40,10 +40,10 @@