diff --git a/agent/app/api/v2/entry.go b/agent/app/api/v2/entry.go index 1970bd5c2..0f0258799 100644 --- a/agent/app/api/v2/entry.go +++ b/agent/app/api/v2/entry.go @@ -38,6 +38,7 @@ var ( sshService = service.NewISSHService() firewallService = service.NewIFirewallService() monitorService = service.NewIMonitorService() + systemService = service.NewISystemService() deviceService = service.NewIDeviceService() fail2banService = service.NewIFail2BanService() diff --git a/agent/app/api/v2/system.go b/agent/app/api/v2/system.go new file mode 100644 index 000000000..544ac0226 --- /dev/null +++ b/agent/app/api/v2/system.go @@ -0,0 +1,26 @@ +package v2 + +import ( + "errors" + "github.com/1Panel-dev/1Panel/agent/app/api/v2/helper" + "github.com/gin-gonic/gin" +) + +// @Tags Host +// @Summary Check if a system component exists +// @Accept json +// @Param name query string true "Component name to check (e.g., rsync, docker)" +// @Success 200 {object} response.ComponentInfo +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /hosts/components/{name} [get] +func (b *BaseApi) CheckComponentExistence(c *gin.Context) { + name := c.Param("name") + if name == "" { + helper.BadRequest(c, errors.New("empty component name")) + return + } + + info := systemService.IsComponentExist(name) + helper.SuccessWithData(c, info) +} diff --git a/agent/app/dto/response/system.go b/agent/app/dto/response/system.go new file mode 100644 index 000000000..8088f18d6 --- /dev/null +++ b/agent/app/dto/response/system.go @@ -0,0 +1,8 @@ +package response + +type ComponentInfo struct { + Exists bool `json:"exists"` + Version string `json:"version"` + Path string `json:"path"` + Error string `json:"error"` +} diff --git a/agent/app/service/system.go b/agent/app/service/system.go new file mode 100644 index 000000000..9b0ca451b --- /dev/null +++ b/agent/app/service/system.go @@ -0,0 +1,29 @@ +package service + +import ( + "github.com/1Panel-dev/1Panel/agent/app/dto/response" + "os/exec" +) + +type SystemService struct{} + +type ISystemService interface { + IsComponentExist(name string) response.ComponentInfo +} + +func NewISystemService() ISystemService { + return &SystemService{} +} + +func (s *SystemService) IsComponentExist(name string) response.ComponentInfo { + info := response.ComponentInfo{} + path, err := exec.LookPath(name) + if err != nil { + info.Exists = false + info.Error = err.Error() + return info + } + info.Exists = true + info.Path = path + return info +} diff --git a/agent/router/ro_host.go b/agent/router/ro_host.go index 102132ce7..59a5ae725 100644 --- a/agent/router/ro_host.go +++ b/agent/router/ro_host.go @@ -57,5 +57,7 @@ func (s *HostRouter) InitRouter(Router *gin.RouterGroup) { hostRouter.POST("/disks/partition", baseApi.PartitionDisk) hostRouter.POST("/disks/mount", baseApi.MountDisk) hostRouter.POST("/disks/unmount", baseApi.UnmountDisk) + + hostRouter.GET("/components/:name", baseApi.CheckComponentExistence) } } diff --git a/frontend/src/api/interface/host.ts b/frontend/src/api/interface/host.ts index 5a0f7f0a8..4baabfb2a 100644 --- a/frontend/src/api/interface/host.ts +++ b/frontend/src/api/interface/host.ts @@ -251,4 +251,11 @@ export namespace Host { export interface DiskUmount { mountPoint: string; } + + export interface ComponentInfo { + exists: boolean; + version: string; + path: string; + error: string; + } } diff --git a/frontend/src/api/modules/host.ts b/frontend/src/api/modules/host.ts index cb8714a83..13befa61c 100644 --- a/frontend/src/api/modules/host.ts +++ b/frontend/src/api/modules/host.ts @@ -124,3 +124,12 @@ export const mountDisk = (params: Host.DiskMount) => { export const unmountDisk = (params: Host.DiskUmount) => { return http.post(`/hosts/disks/unmount`, params, TimeoutEnum.T_60S); }; + +export const getComponentInfo = (name: string, operateNode?: string) => { + if (operateNode) { + return http.get(`/hosts/components/${name}`, { + CurrentNode: operateNode, + }); + } + return http.get(`/hosts/components/${name}`); +};