@@ -3,16 +3,19 @@ package handlers
33import (
44 "context"
55 "net/http"
6+ "strings"
67
78 "github.com/danielgtaylor/huma/v2"
89 "github.com/getarcaneapp/arcane/backend/internal/common"
910 "github.com/getarcaneapp/arcane/backend/internal/services"
1011 "github.com/getarcaneapp/arcane/types/base"
12+ imagetypes "github.com/getarcaneapp/arcane/types/image"
1113 "github.com/getarcaneapp/arcane/types/imageupdate"
1214)
1315
1416type ImageUpdateHandler struct {
1517 imageUpdateService * services.ImageUpdateService
18+ imageService * services.ImageService
1619}
1720
1821type CheckImageUpdateInput struct {
@@ -51,6 +54,15 @@ type CheckAllImagesOutput struct {
5154 Body base.ApiResponse [imageupdate.BatchResponse ]
5255}
5356
57+ type GetUpdateInfoByRefsInput struct {
58+ EnvironmentID string `path:"id" doc:"Environment ID"`
59+ ImageRefs string `query:"imageRefs" doc:"Comma-separated image references"`
60+ }
61+
62+ type GetUpdateInfoByRefsOutput struct {
63+ Body base.ApiResponse [map [string ]* imagetypes.UpdateInfo ]
64+ }
65+
5466type GetUpdateSummaryInput struct {
5567 EnvironmentID string `path:"id" doc:"Environment ID"`
5668}
@@ -60,8 +72,11 @@ type GetUpdateSummaryOutput struct {
6072}
6173
6274// RegisterImageUpdates registers image update endpoints.
63- func RegisterImageUpdates (api huma.API , imageUpdateSvc * services.ImageUpdateService ) {
64- h := & ImageUpdateHandler {imageUpdateService : imageUpdateSvc }
75+ func RegisterImageUpdates (api huma.API , imageUpdateSvc * services.ImageUpdateService , imageSvc * services.ImageService ) {
76+ h := & ImageUpdateHandler {
77+ imageUpdateService : imageUpdateSvc ,
78+ imageService : imageSvc ,
79+ }
6580
6681 huma .Register (api , huma.Operation {
6782 OperationID : "check-image-update" ,
@@ -108,6 +123,15 @@ func RegisterImageUpdates(api huma.API, imageUpdateSvc *services.ImageUpdateServ
108123 Security : []map [string ][]string {{"BearerAuth" : {}}, {"ApiKeyAuth" : {}}},
109124 }, h .CheckAllImages )
110125
126+ huma .Register (api , huma.Operation {
127+ OperationID : "get-update-info-by-refs" ,
128+ Method : http .MethodGet ,
129+ Path : "/environments/{id}/image-updates/by-refs" ,
130+ Summary : "Get persisted update info for image references" ,
131+ Tags : []string {"Image Updates" },
132+ Security : []map [string ][]string {{"BearerAuth" : {}}, {"ApiKeyAuth" : {}}},
133+ }, h .GetUpdateInfoByRefs )
134+
111135 huma .Register (api , huma.Operation {
112136 OperationID : "get-update-summary" ,
113137 Method : http .MethodGet ,
@@ -192,6 +216,30 @@ func (h *ImageUpdateHandler) CheckAllImages(ctx context.Context, input *CheckAll
192216 }, nil
193217}
194218
219+ func (h * ImageUpdateHandler ) GetUpdateInfoByRefs (ctx context.Context , input * GetUpdateInfoByRefsInput ) (* GetUpdateInfoByRefsOutput , error ) {
220+ imageRefs := parseImageRefsQueryInternal (input .ImageRefs )
221+ if len (imageRefs ) == 0 {
222+ return & GetUpdateInfoByRefsOutput {
223+ Body : base.ApiResponse [map [string ]* imagetypes.UpdateInfo ]{
224+ Success : true ,
225+ Data : map [string ]* imagetypes.UpdateInfo {},
226+ },
227+ }, nil
228+ }
229+
230+ result , err := h .imageService .GetUpdateInfoByImageRefs (ctx , imageRefs )
231+ if err != nil {
232+ return nil , huma .Error500InternalServerError ((& common.BatchImageUpdateCheckError {Err : err }).Error ())
233+ }
234+
235+ return & GetUpdateInfoByRefsOutput {
236+ Body : base.ApiResponse [map [string ]* imagetypes.UpdateInfo ]{
237+ Success : true ,
238+ Data : result ,
239+ },
240+ }, nil
241+ }
242+
195243func (h * ImageUpdateHandler ) GetUpdateSummary (ctx context.Context , input * GetUpdateSummaryInput ) (* GetUpdateSummaryOutput , error ) {
196244 summary , err := h .imageUpdateService .GetUpdateSummary (ctx )
197245 if err != nil {
@@ -205,3 +253,26 @@ func (h *ImageUpdateHandler) GetUpdateSummary(ctx context.Context, input *GetUpd
205253 },
206254 }, nil
207255}
256+
257+ func parseImageRefsQueryInternal (raw string ) []string {
258+ if strings .TrimSpace (raw ) == "" {
259+ return nil
260+ }
261+
262+ parts := strings .Split (raw , "," )
263+ result := make ([]string , 0 , len (parts ))
264+ seen := make (map [string ]struct {}, len (parts ))
265+ for _ , part := range parts {
266+ ref := strings .TrimSpace (part )
267+ if ref == "" {
268+ continue
269+ }
270+ if _ , exists := seen [ref ]; exists {
271+ continue
272+ }
273+ seen [ref ] = struct {}{}
274+ result = append (result , ref )
275+ }
276+
277+ return result
278+ }
0 commit comments