Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions agent/app/api/v2/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,23 @@ func (b *BaseApi) GetAppIcon(c *gin.Context) {
c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
c.Data(http.StatusOK, "image/png", iconBytes)
}

// @Tags App
// @Summary Search app detail by appkey and version
// @Accept json
// @Param appId path integer true "app key"
// @Param version path string true "app version"
// @Success 200 {object} response.AppDetailSimpleDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/detail/node/:appKey/:version [get]
func (b *BaseApi) GetAppDetailForNode(c *gin.Context) {
appKey := c.Param("appKey")
version := c.Param("version")
appDetailDTO, err := appService.GetAppDetailByKey(appKey, version)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, appDetailDTO)
}
39 changes: 20 additions & 19 deletions agent/app/dto/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,26 @@ type ExtraProperties struct {
}

type AppProperty struct {
Name string `json:"name"`
Type string `json:"type"`
Tags []string `json:"tags"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
Description Locale `json:"description"`
Key string `json:"key"`
Required []string `json:"Required"`
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
Limit int `json:"limit" yaml:"limit"`
Recommend int `json:"recommend" yaml:"recommend"`
Website string `json:"website"`
Github string `json:"github"`
Document string `json:"document"`
Architectures []string `json:"architectures"`
MemoryRequired int `json:"memoryRequired" yaml:"memoryRequired"`
GpuSupport bool `json:"gpuSupport" yaml:"gpuSupport"`
Version float64 `json:"version"`
Deprecated float64 `json:"deprecated"`
Name string `json:"name"`
Type string `json:"type"`
Tags []string `json:"tags"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
Description Locale `json:"description"`
Key string `json:"key"`
Required []string `json:"Required"`
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
Limit int `json:"limit" yaml:"limit"`
Recommend int `json:"recommend" yaml:"recommend"`
Website string `json:"website"`
Github string `json:"github"`
Document string `json:"document"`
Architectures []string `json:"architectures"`
MemoryRequired int `json:"memoryRequired" yaml:"memoryRequired"`
GpuSupport bool `json:"gpuSupport" yaml:"gpuSupport"`
Version float64 `json:"version"`
Deprecated float64 `json:"deprecated"`
BatchInstallSupport bool `json:"batchInstallSupport"`
}

type AppConfigVersion struct {
Expand Down
9 changes: 9 additions & 0 deletions agent/app/dto/request/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ type AppInstallCreate struct {
Name string `json:"name" validate:"required"`
Services map[string]string `json:"services"`
TaskID string `json:"taskID"`

AppContainerConfig
NodePushConfig
}

type NodePushConfig struct {
Nodes []string `json:"nodes"`
PushNode bool `json:"pushNode"`
AppKey string `json:"appKey"`
Version string `json:"version"`
}

type AppContainerConfig struct {
Expand Down
27 changes: 16 additions & 11 deletions agent/app/dto/response/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@ type AppDTO struct {
}

type AppItem struct {
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
Description string `json:"description"`
Status string `json:"status"`
Installed bool `json:"installed"`
Limit int `json:"limit"`
Tags []string `json:"tags"`
GpuSupport bool `json:"gpuSupport"`
Recommend int `json:"recommend"`
Type string `json:"type"`
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
Description string `json:"description"`
Status string `json:"status"`
Installed bool `json:"installed"`
Limit int `json:"limit"`
Tags []string `json:"tags"`
GpuSupport bool `json:"gpuSupport"`
Recommend int `json:"recommend"`
Type string `json:"type"`
BatchInstallSupport bool `json:"batchInstallSupport"`
}

type TagDTO struct {
Expand Down Expand Up @@ -75,6 +76,10 @@ type AppDetailDTO struct {
GpuSupport bool `json:"gpuSupport"`
}

type AppDetailSimpleDTO struct {
ID uint `json:"id"`
}

type IgnoredApp struct {
Icon string `json:"icon"`
Name string `json:"name"`
Expand Down
1 change: 1 addition & 0 deletions agent/app/model/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type App struct {
MemoryRequired int `json:"memoryRequired"`
GpuSupport bool `json:"gpuSupport"`
RequiredPanelVersion float64 `json:"requiredPanelVersion"`
BatchInstallSupport bool `json:"batchInstallSupport" yaml:"batchInstallSupport"`

Details []AppDetail `json:"-" gorm:"-:migration"`
TagsKey []string `json:"tags" yaml:"tags" gorm:"-"`
Expand Down
42 changes: 34 additions & 8 deletions agent/app/service/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type IAppService interface {
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
SyncAppListFromLocal(taskID string)
GetAppIcon(appID uint) ([]byte, error)
GetAppDetailByKey(appKey, version string) (response.AppDetailSimpleDTO, error)
}

func NewIAppService() IAppService {
Expand Down Expand Up @@ -118,14 +119,15 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (*response.
}
}
appDTO := &response.AppItem{
ID: ap.ID,
Name: ap.Name,
Key: ap.Key,
Limit: ap.Limit,
GpuSupport: ap.GpuSupport,
Recommend: ap.Recommend,
Description: ap.GetDescription(ctx),
Type: ap.Type,
ID: ap.ID,
Name: ap.Name,
Key: ap.Key,
Limit: ap.Limit,
GpuSupport: ap.GpuSupport,
Recommend: ap.Recommend,
Description: ap.GetDescription(ctx),
Type: ap.Type,
BatchInstallSupport: ap.BatchInstallSupport,
}
appDTOs = append(appDTOs, appDTO)
tags, err := getAppTags(ap.ID, lang)
Expand Down Expand Up @@ -203,6 +205,20 @@ func (a AppService) GetApp(ctx *gin.Context, key string) (*response.AppDTO, erro
return &appDTO, nil
}

func (a AppService) GetAppDetailByKey(appKey, version string) (response.AppDetailSimpleDTO, error) {
var appDetailDTO response.AppDetailSimpleDTO
app, err := appRepo.GetFirst(appRepo.WithKey(appKey))
if err != nil {
return appDetailDTO, err
}
appDetail, err := appDetailRepo.GetFirst(appDetailRepo.WithAppId(app.ID), appDetailRepo.WithVersion(version))
if err != nil {
return appDetailDTO, err
}
appDetailDTO.ID = appDetail.ID
return appDetailDTO, nil
}

func (a AppService) GetAppDetail(appID uint, version, appType string) (response.AppDetailDTO, error) {
var (
appDetailDTO response.AppDetailDTO
Expand Down Expand Up @@ -386,11 +402,21 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
App: app,
}
composeMap := make(map[string]interface{})
var composeRes []byte
if req.EditCompose {
if err = yaml.Unmarshal([]byte(req.DockerCompose), &composeMap); err != nil {
return
}
} else {
if appDetail.DockerCompose == "" {
dockerComposeUrl := fmt.Sprintf("%s/%s/1panel/%s/%s/docker-compose.yml", global.CONF.RemoteURL.AppRepo, global.CONF.Base.Mode, app.Key, appDetail.Version)
_, composeRes, err = req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
if err != nil {
return
}
appDetail.DockerCompose = string(composeRes)
_ = appDetailRepo.Update(context.Background(), appDetail)
}
if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil {
return
}
Expand Down
1 change: 1 addition & 0 deletions agent/app/service/app_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,7 @@ func getApps(oldApps []model.App, items []dto.AppDefine, systemVersion string, t
app.MemoryRequired = config.MemoryRequired
app.Architectures = strings.Join(config.Architectures, ",")
app.GpuSupport = config.GpuSupport
app.BatchInstallSupport = config.BatchInstallSupport
apps[key] = app
}
return apps
Expand Down
1 change: 1 addition & 0 deletions agent/app/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const (
TaskScopeCustomAppstore = "CustomAppstore"
TaskScopeTamper = "Tamper"
TaskScopeFileConvert = "Convert"
TaskScopeTask = "Task"
)

func GetTaskName(resourceName, operate, scope string) string {
Expand Down
1 change: 1 addition & 0 deletions agent/init/migration/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func InitAgentDB() {
migrations.UpdateWebsite,
migrations.AddisIPtoWebsiteSSL,
migrations.InitPingStatus,
migrations.UpdateApp,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)
Expand Down
7 changes: 7 additions & 0 deletions agent/init/migration/migrations/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -800,3 +800,10 @@ var InitPingStatus = &gormigrate.Migration{
return nil
},
}

var UpdateApp = &gormigrate.Migration{
ID: "20251228-update-app",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(&model.App{})
},
}
1 change: 1 addition & 0 deletions agent/router/ro_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
appRouter.POST("/search", baseApi.SearchApp)
appRouter.GET("/:key", baseApi.GetApp)
appRouter.GET("/detail/:appId/:version/:type", baseApi.GetAppDetail)
appRouter.GET("/detail/node/:appKey/:version", baseApi.GetAppDetailForNode)
appRouter.GET("/details/:id", baseApi.GetAppDetailByID)
appRouter.POST("/install", baseApi.InstallApp)
appRouter.GET("/tags", baseApi.GetAppTags)
Expand Down
12 changes: 7 additions & 5 deletions core/app/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ const (
TaskInstallCluster = "TaskInstallCluster"
TaskCreateCluster = "TaskCreateCluster"
TaskBackup = "TaskBackup"
TaskPush = "TaskPush"
)

const (
TaskScopeSystem = "System"
TaskScopeScript = "ScriptLibrary"
TaskScopeNodeFile = "NodeFile"
TaskScopeAppBackup = "AppBackup"
TaskScopeCluster = "Cluster"
TaskScopeSystem = "System"
TaskScopeScript = "ScriptLibrary"
TaskScopeNodeFile = "NodeFile"
TaskScopeAppBackup = "AppBackup"
TaskScopeCluster = "Cluster"
TaskScopeAppInstall = "AppInstallTask"
)

func GetTaskName(resourceName, operate, scope string) string {
Expand Down
39 changes: 34 additions & 5 deletions core/buserr/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ func (e BusinessError) Error() string {
return content
}

func New(Key string) BusinessError {
return BusinessError{
Msg: Key,
Detail: nil,
Err: nil,
func New(key string, opts ...Option) BusinessError {
be := BusinessError{
Msg: key,
}

for _, opt := range opts {
opt(&be)
}

return be
}

func WithErr(Key string, err error) BusinessError {
Expand Down Expand Up @@ -76,3 +80,28 @@ func WithName(Key string, name string) BusinessError {
Map: paramMap,
}
}

type Option func(*BusinessError)

func WithNameOption(name string) Option {
return func(be *BusinessError) {
if name != "" {
if be.Map == nil {
be.Map = make(map[string]interface{})
}
be.Map["name"] = name
}
}
}

func WithErrOption(err error) Option {
return func(be *BusinessError) {
be.Err = err
if err != nil {
if be.Map == nil {
be.Map = make(map[string]interface{})
}
be.Map["err"] = err
}
}
}
5 changes: 5 additions & 0 deletions core/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ FailedStatus: "{{ .name }} failed {{ .err }}"
Start: "Start"
SubTask: "Subtask"
Skip: "Skip errors and continue..."
PushAppInstallTaskToNode: "Push app installation task to node [{{ .name }}]"
TaskPush: "Push"
AppInstallTask: "App installation task"
PushAppFailed: "Failed to push app installation task"
Success: "Success"

#script
ScriptLibrary: "Script Library"
Expand Down
5 changes: 5 additions & 0 deletions core/i18n/lang/es-ES.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ ErrApiConfigKeyInvalid: "Error de clave API: {{ .detail }}"
ErrApiConfigIPInvalid: "La IP de la solicitud API no está en la lista blanca: {{ .detail }}"
ErrApiConfigDisable: "Esta interfaz prohíbe llamadas a la API: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "Error de marca de tiempo de API: {{ .detail }}"
PushAppInstallTaskToNode: "Enviar tarea de instalación de aplicación al nodo [{{ .name }}]"
TaskPush: "Enviar"
AppInstallTask: "Tarea de instalación de aplicación"
PushAppFailed: "Error al enviar tarea de instalación de aplicación"
Success: "Éxito"

# request
ErrNoSuchHost: "No se pudo encontrar el servidor solicitado {{ .err }}"
Expand Down
5 changes: 5 additions & 0 deletions core/i18n/lang/ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ FailedStatus: "{{ .name }} 失敗 {{ .err }}"
Start: "開始"
SubTask: "サブタスク"
Skip: "エラーを無視して続行..."
PushAppInstallTaskToNode: "アプリインストールタスクをノード [{{ .name }}] にプッシュ"
TaskPush: "プッシュ"
AppInstallTask: "アプリインストールタスク"
PushAppFailed: "アプリインストールタスクのプッシュに失敗しました"
Success: "成功"

#script
ScriptLibrary: "スクリプトライブラリ"
Expand Down
5 changes: 5 additions & 0 deletions core/i18n/lang/ko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ FailedStatus: "{{ .name }} 실패 {{ .err }}"
Start: "시작"
SubTask: "서브 작업"
Skip: "오류 무시하고 계속..."
PushAppInstallTaskToNode: "노드 [{{ .name }}]에 앱 설치 작업 푸시"
TaskPush: "푸시"
AppInstallTask: "앱 설치 작업"
PushAppFailed: "앱 설치 작업 푸시 실패"
Success: "성공"

#script
ScriptLibrary: "스크립트 라이브러리"
Expand Down
5 changes: 5 additions & 0 deletions core/i18n/lang/ms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ FailedStatus: "{{ .name }} gagal {{ .err }}"
Start: "Mula"
SubTask: "Tugas Sub"
Skip: "Abaikan ralat dan teruskan..."
PushAppInstallTaskToNode: "Tolak tugas pemasangan aplikasi ke nod [{{ .name }}]"
TaskPush: "Tolak"
AppInstallTask: "Tugas pemasangan aplikasi"
PushAppFailed: "Gagal menolak tugas pemasangan aplikasi"
Success: "Berjaya"

#script
ScriptLibrary: "Pustaka Skrip"
Expand Down
5 changes: 5 additions & 0 deletions core/i18n/lang/pt-BR.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ FailedStatus: "{{ .name }} falhou {{ .err }}"
Start: "Iniciar"
SubTask: "Subtarefa"
Skip: "Ignorar erros e continuar..."
PushAppInstallTaskToNode: "Enviar tarefa de instalação de aplicativo para o nó [{{ .name }}]"
TaskPush: "Enviar"
AppInstallTask: "Tarefa de instalação de aplicativo"
PushAppFailed: "Falha ao enviar tarefa de instalação de aplicativo"
Success: "Sucesso"

#script
ScriptLibrary: "Biblioteca de Scripts"
Expand Down
Loading
Loading