diff --git a/apiserver/docs/docs.go b/apiserver/docs/docs.go index ae951dd03..9c8edeec6 100644 --- a/apiserver/docs/docs.go +++ b/apiserver/docs/docs.go @@ -20,6 +20,63 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/bff/icon": { + "get": { + "description": "Get app image", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "MinioAPI" + ], + "summary": "Get app image", + "parameters": [ + { + "type": "string", + "description": "application name", + "name": "application", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "Name of the bucket", + "name": "namespace", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, "/bff/model/files": { "delete": { "description": "Delete files", diff --git a/apiserver/docs/swagger.json b/apiserver/docs/swagger.json index 7333d0cad..a32a33ea3 100644 --- a/apiserver/docs/swagger.json +++ b/apiserver/docs/swagger.json @@ -14,6 +14,63 @@ "host": "localhost:8081", "basePath": "/", "paths": { + "/bff/icon": { + "get": { + "description": "Get app image", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "MinioAPI" + ], + "summary": "Get app image", + "parameters": [ + { + "type": "string", + "description": "application name", + "name": "application", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "Name of the bucket", + "name": "namespace", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + } + }, "/bff/model/files": { "delete": { "description": "Delete files", diff --git a/apiserver/docs/swagger.yaml b/apiserver/docs/swagger.yaml index d9a49f4d8..b34ee1a20 100644 --- a/apiserver/docs/swagger.yaml +++ b/apiserver/docs/swagger.yaml @@ -515,6 +515,44 @@ info: title: ApiServer Swagger API version: "1.0" paths: + /bff/icon: + get: + consumes: + - application/json + description: Get app image + parameters: + - description: application name + in: query + name: application + required: true + type: string + - description: Name of the bucket + in: query + name: namespace + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "400": + description: Bad Request + schema: + additionalProperties: + type: string + type: object + "500": + description: Internal Server Error + schema: + additionalProperties: + type: string + type: object + summary: Get app image + tags: + - MinioAPI /bff/model/files: delete: consumes: diff --git a/apiserver/pkg/application/application.go b/apiserver/pkg/application/application.go index 212a2b7ff..0b8c926e0 100644 --- a/apiserver/pkg/application/application.go +++ b/apiserver/pkg/application/application.go @@ -39,6 +39,7 @@ import ( apiprompt "github.com/kubeagi/arcadia/api/app-node/prompt/v1alpha1" apiretriever "github.com/kubeagi/arcadia/api/app-node/retriever/v1alpha1" "github.com/kubeagi/arcadia/api/base/v1alpha1" + pkgconf "github.com/kubeagi/arcadia/apiserver/config" "github.com/kubeagi/arcadia/apiserver/graph/generated" "github.com/kubeagi/arcadia/apiserver/pkg/common" "github.com/kubeagi/arcadia/apiserver/pkg/utils" @@ -73,7 +74,7 @@ func addDefaultValue(gApp *generated.Application, app *v1alpha1.Application) { gApp.ConversionWindowSize = pointer.Int(5) } -func cr2app(ctx context.Context, c client.Client, prompt *apiprompt.Prompt, chainConfig *apichain.CommonChainConfig, retriever *apiretriever.CommonRetrieverConfig, app *v1alpha1.Application, agent *apiagent.Agent, doc *apidocumentloader.DocumentLoader, enableRerank, enableMultiQuery *bool, rerankModel *string) (*generated.Application, error) { +func cr2app(prompt *apiprompt.Prompt, chainConfig *apichain.CommonChainConfig, retriever *apiretriever.CommonRetrieverConfig, app *v1alpha1.Application, agent *apiagent.Agent, doc *apidocumentloader.DocumentLoader, enableRerank, enableMultiQuery *bool, rerankModel *string) (*generated.Application, error) { if app == nil { return nil, errors.New("no app found") } @@ -81,7 +82,7 @@ func cr2app(ctx context.Context, c client.Client, prompt *apiprompt.Prompt, chai UpdateTimestamp := &condition.LastTransitionTime.Time status := common.GetObjStatus(app) - icon, _ := common.AppIconLink(ctx, app, c) + icon := common.AppIconLink(app, pkgconf.GetConfig().PlaygroundEndpointPrefix) gApp := &generated.Application{ Metadata: &generated.ApplicationMetadata{ Name: app.Name, @@ -153,22 +154,20 @@ func cr2app(ctx context.Context, c client.Client, prompt *apiprompt.Prompt, chai return gApp, nil } -func appConverterHelper(ctx context.Context, c client.Client) common.ResourceConverter { - return func(objApp client.Object) (generated.PageNode, error) { - app, ok := objApp.(*v1alpha1.Application) - if !ok { - return nil, errors.New("can't convert client.Object to Application") - } - return app2metadata(ctx, c, app) +func app2metadataConverter(objApp client.Object) (generated.PageNode, error) { + app, ok := objApp.(*v1alpha1.Application) + if !ok { + return nil, errors.New("can't convert client.Object to Application") } + return app2metadata(app) } -func app2metadata(ctx context.Context, c client.Client, app *v1alpha1.Application) (*generated.ApplicationMetadata, error) { +func app2metadata(app *v1alpha1.Application) (*generated.ApplicationMetadata, error) { condition := app.Status.GetCondition(v1alpha1.TypeReady) UpdateTimestamp := &condition.LastTransitionTime.Time status := common.GetObjStatus(app) - icon, _ := common.AppIconLink(ctx, app, c) + icon := common.AppIconLink(app, pkgconf.GetConfig().PlaygroundEndpointPrefix) return &generated.ApplicationMetadata{ Name: app.Name, Namespace: app.Namespace, @@ -219,7 +218,7 @@ func CreateApplication(ctx context.Context, c client.Client, input generated.Cre if err := c.Create(ctx, app); err != nil { return nil, err } - return app2metadata(ctx, c, app) + return app2metadata(app) } func UpdateApplication(ctx context.Context, c client.Client, input generated.UpdateApplicationMetadataInput) (*generated.ApplicationMetadata, error) { @@ -250,7 +249,7 @@ func UpdateApplication(ctx context.Context, c client.Client, input generated.Upd return nil, err } } - return app2metadata(ctx, c, app) + return app2metadata(app) } func DeleteApplication(ctx context.Context, c client.Client, input generated.DeleteCommonInput) (*string, error) { @@ -402,7 +401,7 @@ func GetApplication(ctx context.Context, c client.Client, name, namespace string return nil, err } - return cr2app(ctx, c, prompt, chainConfig, retriever, app, agent, doc, pointer.Bool(enableRerankRetriever), pointer.Bool(enableMultiQueryRetriever), pointer.String(rerankModel)) + return cr2app(prompt, chainConfig, retriever, app, agent, doc, pointer.Bool(enableRerankRetriever), pointer.Bool(enableMultiQueryRetriever), pointer.String(rerankModel)) } func ListApplicationMeatadatas(ctx context.Context, c client.Client, input generated.ListCommonInput) (*generated.PaginatedResult, error) { @@ -425,7 +424,7 @@ func ListApplicationMeatadatas(ctx context.Context, c client.Client, input gener for i := range res.Items { items[i] = &res.Items[i] } - return common.ListReources(items, page, pageSize, appConverterHelper(ctx, c), filter...) + return common.ListReources(items, page, pageSize, app2metadataConverter, filter...) } func UpdateApplicationConfig(ctx context.Context, c client.Client, input generated.UpdateApplicationConfigInput) (*generated.Application, error) { @@ -759,7 +758,7 @@ func UpdateApplicationConfig(ctx context.Context, c client.Client, input generat } } - return cr2app(ctx, c, prompt, chainConfig, retriever, app, agent, documentLoader, pointer.Bool(hasRerankRetriever), pointer.Bool(hasMultiQueryRetriever), pointer.String(rerankModel)) + return cr2app(prompt, chainConfig, retriever, app, agent, documentLoader, pointer.Bool(hasRerankRetriever), pointer.Bool(hasMultiQueryRetriever), pointer.String(rerankModel)) } func mutateApp(app *v1alpha1.Application, input generated.UpdateApplicationConfigInput, hasMultiQueryRetriever, hasRerankRetriever bool) error { diff --git a/apiserver/pkg/chat/chat_server.go b/apiserver/pkg/chat/chat_server.go index 05c0eab30..8725abb81 100644 --- a/apiserver/pkg/chat/chat_server.go +++ b/apiserver/pkg/chat/chat_server.go @@ -37,6 +37,7 @@ import ( apiretriever "github.com/kubeagi/arcadia/api/app-node/retriever/v1alpha1" "github.com/kubeagi/arcadia/api/base/v1alpha1" + "github.com/kubeagi/arcadia/apiserver/config" "github.com/kubeagi/arcadia/apiserver/pkg/auth" "github.com/kubeagi/arcadia/apiserver/pkg/chat/storage" "github.com/kubeagi/arcadia/apiserver/pkg/client" @@ -429,7 +430,7 @@ func (cs *ChatServer) FillAppIconToConversations(ctx context.Context, conversati i++ } result := make([]string, len(appMap)) - g, ctx := errgroup.WithContext(ctx) + g, _ := errgroup.WithContext(ctx) g.SetLimit(10) for key, index := range appMap { key, index := key, index @@ -441,13 +442,7 @@ func (cs *ChatServer) FillAppIconToConversations(ctx context.Context, conversati } app.Name = name app.Namespace = ns - link, err := common.AppIconLink(ctx, app, cs.cli) - if err != nil { - // FIXME: Currently, there is a request for an application that cannot be found in a conversation in the database, - // causing other conversations to be unable to add icons, so an error is encountered here and no error is returned. - klog.Errorf("failed to get application %s in namespace %s, error %s", name, ns, err) - return nil - } + link := common.AppIconLink(app, config.GetConfig().PlaygroundEndpointPrefix) result[index] = link return nil }) diff --git a/apiserver/pkg/common/common.go b/apiserver/pkg/common/common.go index 77dd585d4..3beb1edcc 100644 --- a/apiserver/pkg/common/common.go +++ b/apiserver/pkg/common/common.go @@ -20,9 +20,7 @@ import ( "context" "errors" "fmt" - "net/url" "strings" - "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" @@ -309,15 +307,10 @@ func NewListOptions(input generated.ListCommonInput) ([]client.ListOption, error return opts, nil } -func AppIconLink(ctx context.Context, app *v1alpha1.Application, client client.Client) (string, error) { - ds, err := SystemDatasourceOSS(ctx, client) - if err != nil { - return "", err - } - name := fmt.Sprintf("application/%s/icon/%s", app.Name, app.Name) - u, err := ds.Client.PresignedGetObject(ctx, app.Namespace, name, 24*time.Hour, url.Values{}) - if err != nil { - return "", err +func AppIconLink(app *v1alpha1.Application, endpointPrefix string) string { + base := fmt.Sprintf("/bff/icon?namespace=%s&application=%s", app.Namespace, app.Name) + if endpointPrefix != "" { + base = "/" + endpointPrefix + base } - return u.String(), nil + return base } diff --git a/apiserver/pkg/gpt/gpt.go b/apiserver/pkg/gpt/gpt.go index 7bb0d6b2c..12e59f156 100644 --- a/apiserver/pkg/gpt/gpt.go +++ b/apiserver/pkg/gpt/gpt.go @@ -29,6 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/kubeagi/arcadia/api/base/v1alpha1" + pkgconf "github.com/kubeagi/arcadia/apiserver/config" "github.com/kubeagi/arcadia/apiserver/graph/generated" "github.com/kubeagi/arcadia/apiserver/pkg/chat" "github.com/kubeagi/arcadia/apiserver/pkg/chat/storage" @@ -46,7 +47,7 @@ func app2gpt(ctx context.Context, app *v1alpha1.Application, c client.Client) (* return nil, errors.New("no app found") } - icon, _ := common.AppIconLink(ctx, app, c) + icon := common.AppIconLink(app, pkgconf.GetConfig().PlaygroundEndpointPrefix) gpt := &generated.Gpt{ Name: pointer.String(strings.Join([]string{app.Namespace, app.Name}, "/")), DisplayName: pointer.String(app.Spec.DisplayName), diff --git a/apiserver/service/minio_server.go b/apiserver/service/minio_server.go index daee7b09e..9501a76cc 100644 --- a/apiserver/service/minio_server.go +++ b/apiserver/service/minio_server.go @@ -29,6 +29,7 @@ import ( "github.com/gin-gonic/gin" "github.com/minio/minio-go/v7" + "k8s.io/apimachinery/pkg/types" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" @@ -138,21 +139,21 @@ const ( namespaceHeader = "namespace" ) -// @Summary Get success chunks of a file -// @Schemes -// @Description Get success chunks of a file -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param md5 query string true "MD5 value of the file" -// @Param fileName query string true "Name of the file" -// @Param namespace header string true "Name of the bucket" -// @Param bucketPath query string true "Path of the bucket" -// @Param etag query string true "ETag of the file" -// @Success 200 {object} SuccessChunksResult -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/chunks [get] +// @Summary Get success chunks of a file +// @Schemes +// @Description Get success chunks of a file +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param md5 query string true "MD5 value of the file" +// @Param fileName query string true "Name of the file" +// @Param namespace header string true "Name of the bucket" +// @Param bucketPath query string true "Path of the bucket" +// @Param etag query string true "ETag of the file" +// @Success 200 {object} SuccessChunksResult +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/chunks [get] func (m *minioAPI) GetSuccessChunks(ctx *gin.Context) { fildMD5 := ctx.Query(md5Query) if fildMD5 == "" { @@ -240,18 +241,18 @@ func (m *minioAPI) GetSuccessChunks(ctx *gin.Context) { ctx.JSON(http.StatusOK, r) } -// @Summary create new multipart upload -// @Schemes -// @Description create new multipart upload -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body NewMultipartBody true "query params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} map[string]string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/chunks [post] +// @Summary create new multipart upload +// @Schemes +// @Description create new multipart upload +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body NewMultipartBody true "query params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/chunks [post] func (m *minioAPI) NewMultipart(ctx *gin.Context) { var body NewMultipartBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -321,18 +322,18 @@ func (m *minioAPI) NewMultipart(ctx *gin.Context) { }) } -// @Summary Get multipart upload URL -// @Schemes -// @Description Get multipart upload URL -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body GenChunkURLBody true "query params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} GenChunkURLResult -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/chunk_url [post] +// @Summary Get multipart upload URL +// @Schemes +// @Description Get multipart upload URL +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body GenChunkURLBody true "query params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} GenChunkURLResult +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/chunk_url [post] func (m *minioAPI) GetMultipartUploadURL(ctx *gin.Context) { var body GenChunkURLBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -424,18 +425,18 @@ func (m *minioAPI) GetMultipartUploadURL(ctx *gin.Context) { }) } -// @Summary Complete multipart upload -// @Schemes -// @Description Complete multipart upload -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body CompleteBody true "query params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/chunks [put] +// @Summary Complete multipart upload +// @Schemes +// @Description Complete multipart upload +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body CompleteBody true "query params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/chunks [put] func (m *minioAPI) CompleteMultipart(ctx *gin.Context) { var body CompleteBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -470,18 +471,18 @@ func (m *minioAPI) CompleteMultipart(ctx *gin.Context) { ctx.JSON(http.StatusOK, "success") } -// @Summary Delete files -// @Schemes -// @Description Delete files -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body DelteFileBody true "query params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files [delete] +// @Summary Delete files +// @Schemes +// @Description Delete files +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body DelteFileBody true "query params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files [delete] func (m *minioAPI) DeleteFiles(ctx *gin.Context) { var body DelteFileBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -512,18 +513,18 @@ func (m *minioAPI) DeleteFiles(ctx *gin.Context) { ctx.JSON(http.StatusOK, "success") } -// @Summary Abort a file upload -// @Schemes -// @Description Abort a file upload -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body CompleteBody true "query params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/chunks/abort [put] +// @Summary Abort a file upload +// @Schemes +// @Description Abort a file upload +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body CompleteBody true "query params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/chunks/abort [put] func (m *minioAPI) Abort(ctx *gin.Context) { var body CompleteBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -555,20 +556,20 @@ func (m *minioAPI) Abort(ctx *gin.Context) { ctx.JSON(http.StatusOK, "success") } -// @Summary Statistics file information -// @Schemes -// @Description Statistics file information -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param fileName query string true "Name of the file" -// @Param namespace header string true "Name of the bucket" -// @Param bucketPath query string true "Path of the bucket" -// @Param version query string false "Download the specified version of the file, if not passed, download the latest version" -// @Success 200 {object} map[string]string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/stat [get] +// @Summary Statistics file information +// @Schemes +// @Description Statistics file information +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param fileName query string true "Name of the file" +// @Param namespace header string true "Name of the bucket" +// @Param bucketPath query string true "Path of the bucket" +// @Param version query string false "Download the specified version of the file, if not passed, download the latest version" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/stat [get] func (m *minioAPI) StatFile(ctx *gin.Context) { fileName := ctx.Query("fileName") bucket := NamespaceInHeader(ctx) @@ -606,22 +607,22 @@ func (m *minioAPI) StatFile(ctx *gin.Context) { }) } -// @Summary Download files in chunks -// @Schemes -// @Description Download files in chunks -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param from query int true "The start of the file" -// @Param end query int true "The end of the file" -// @Param namespace header string true "Name of the bucket" -// @Param bucketPath query string true "Path of the bucket" -// @Param fileName query string true "Name of the file" -// @Param version query string false "Download the specified version of the file, if not passed, download the latest version" -// @Success 200 -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/download [get] +// @Summary Download files in chunks +// @Schemes +// @Description Download files in chunks +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param from query int true "The start of the file" +// @Param end query int true "The end of the file" +// @Param namespace header string true "Name of the bucket" +// @Param bucketPath query string true "Path of the bucket" +// @Param fileName query string true "Name of the file" +// @Param version query string false "Download the specified version of the file, if not passed, download the latest version" +// @Success 200 +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/download [get] func (m *minioAPI) Download(ctx *gin.Context) { fromStr := ctx.Query("from") endStr := ctx.Query("end") @@ -666,21 +667,21 @@ func (m *minioAPI) Download(ctx *gin.Context) { _, _ = io.Copy(ctx.Writer, info) } -// @Summary Read a file line by line -// @Schemes -// @Description Read a file line by line -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param page query int true "Start page" -// @Param size query int true "The number of rows read each time" -// @Param namespace header string true "Name of the bucket" -// @Param bucketPath query string true "Path of the bucket" -// @Param fileName query string true "Name of the file" -// @Success 200 {object} common.ReadCSVResult -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/versioneddataset/files/csv [get] +// @Summary Read a file line by line +// @Schemes +// @Description Read a file line by line +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param page query int true "Start page" +// @Param size query int true "The number of rows read each time" +// @Param namespace header string true "Name of the bucket" +// @Param bucketPath query string true "Path of the bucket" +// @Param fileName query string true "Name of the file" +// @Success 200 {object} common.ReadCSVResult +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/versioneddataset/files/csv [get] func (m *minioAPI) ReadCSVLines(ctx *gin.Context) { var ( page int64 @@ -763,20 +764,20 @@ func (m *minioAPI) ReadCSVLines(ctx *gin.Context) { ctx.JSON(http.StatusOK, result) } -// @Summary Get a download link -// @Schemes -// @Description Get a download link -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param namespace header string true "Name of the bucket" -// @Param bucketPath query string true "Path of the bucket" -// @Param fileName query string true "Name of the file" -// @Param version query string false "file version" -// @Success 200 {object} map[string]string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/model/files/downloadlink [get] +// @Summary Get a download link +// @Schemes +// @Description Get a download link +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param namespace header string true "Name of the bucket" +// @Param bucketPath query string true "Path of the bucket" +// @Param fileName query string true "Name of the file" +// @Param version query string false "file version" +// @Success 200 {object} map[string]string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/model/files/downloadlink [get] func (m *minioAPI) GetDownloadLink(ctx *gin.Context) { source, err := common.SystemDatasourceOSS(ctx.Request.Context(), m.client) if err != nil { @@ -808,18 +809,18 @@ func (m *minioAPI) GetDownloadLink(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{"url": u.String()}) } -// @Summary Create web cralwer file -// @Schemes -// @Description Create a web crawler file which contains crawer params -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body WebCrawlerFileBody true "request params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/versioneddataset/files/webcrawler [post] +// @Summary Create web cralwer file +// @Schemes +// @Description Create a web crawler file which contains crawer params +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body WebCrawlerFileBody true "request params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/versioneddataset/files/webcrawler [post] func (m *minioAPI) CreateWebCrawlerFile(ctx *gin.Context) { var body WebCrawlerFileBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -893,18 +894,18 @@ func (m *minioAPI) CreateWebCrawlerFile(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{"bucket": namespace, "object": object}) } -// @Summary edit csv file online -// @Schemes -// @Description edit csv file online -// @Tags MinioAPI -// @Accept json -// @Produce json -// @Param request body common.UpdateCSVBody true "request params" -// @Param namespace header string true "Name of the bucket" -// @Success 200 {object} string -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /bff/versioneddataset/files/edit [PUT] +// @Summary edit csv file online +// @Schemes +// @Description edit csv file online +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param request body common.UpdateCSVBody true "request params" +// @Param namespace header string true "Name of the bucket" +// @Success 200 {object} string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/versioneddataset/files/edit [PUT] func (m *minioAPI) EditCSV(ctx *gin.Context) { var body common.UpdateCSVBody if err := ctx.ShouldBindJSON(&body); err != nil { @@ -1009,6 +1010,55 @@ func (m *minioAPI) EditCSV(ctx *gin.Context) { ctx.JSON(http.StatusOK, "") } +// @Summary Get app image +// @Schemes +// @Description Get app image +// @Tags MinioAPI +// @Accept json +// @Produce json +// @Param application query string true "application name" +// @Param namespace query string true "Name of the bucket" +// @Success 200 {object} string +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /bff/icon [GET] +func (m *minioAPI) Image(ctx *gin.Context) { + namespace := ctx.Query("namespace") + appName := ctx.Query("application") + app := &v1alpha1.Application{} + if err := m.client.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil { + klog.Errorf("failed to get application %s in namespace, error %s", appName, namespace, err) + ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + "message": err.Error(), + }) + return + } + + source, err := common.SystemDatasourceOSS(ctx.Request.Context(), m.client) + if err != nil { + klog.Errorf("failed to get system datasource error %s", err) + ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + "message": fmt.Sprintf("failed to get system datasource error %s", err.Error()), + }) + return + } + + objectName := fmt.Sprintf("application/%s/icon/%s", appName, appName) + info, err := source.Client.GetObject(ctx.Request.Context(), namespace, objectName, minio.GetObjectOptions{}) + if err != nil { + klog.Errorf("failed to get system datasource error %s", err) + ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + "message": fmt.Sprintf("failed to get system datasource error %s", err.Error()), + }) + return + } + + bs, _ := io.ReadAll(info) + ct := http.DetectContentType(bs) + ctx.Writer.Header().Set("Content-Type", ct) + _, _ = io.Copy(ctx.Writer, bytes.NewReader(bs)) +} + func registerMinIOAPI(group *gin.RouterGroup, conf gqlconfig.ServerConfig) { c, err := pkgclient.GetClient(nil) if err != nil { @@ -1049,4 +1099,5 @@ func registerMinIOAPI(group *gin.RouterGroup, conf gqlconfig.ServerConfig) { } group.GET("/rags/files/downloadlink", auth.AuthInterceptor(conf.EnableOIDC, oidc.Verifier, evaluationarcadiav1alpha1.GroupVersion, "get", "rags"), api.GetDownloadLink) + group.GET("/icon", api.Image) }