diff --git a/go.mod b/go.mod index 90e902c..34935a4 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.7 require ( github.com/containerd/containerd/v2 v2.0.4 github.com/containerd/platforms v1.0.0-rc.1 - github.com/docker/model-distribution v0.0.0-20250418220155-bf3bed0d69b0 + github.com/docker/model-distribution v0.0.0-20250418222450-8f6c05a5ffa4 github.com/jaypipes/ghw v0.16.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.1 diff --git a/go.sum b/go.sum index 272537f..d48d6ef 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBi github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/docker/model-distribution v0.0.0-20250418220155-bf3bed0d69b0 h1:p64u8SbT6qGcD5GcUkxkvjtm7LTHUpHUPtPE+7PBcTo= -github.com/docker/model-distribution v0.0.0-20250418220155-bf3bed0d69b0/go.mod h1:fd9H/2KAY0+ByxbohWfCkxp0rxf0pqSlHEtFTjTXbLk= +github.com/docker/model-distribution v0.0.0-20250418222450-8f6c05a5ffa4 h1:v7DyBUd08t4XQe4NC2Rb8ZSWOiWVXD0TbdgIOQZ/IQo= +github.com/docker/model-distribution v0.0.0-20250418222450-8f6c05a5ffa4/go.mod h1:fd9H/2KAY0+ByxbohWfCkxp0rxf0pqSlHEtFTjTXbLk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= diff --git a/pkg/inference/models/manager.go b/pkg/inference/models/manager.go index f795562..67f8592 100644 --- a/pkg/inference/models/manager.go +++ b/pkg/inference/models/manager.go @@ -8,6 +8,7 @@ import ( "html" "net/http" "path" + "strconv" "strings" "github.com/docker/model-distribution/distribution" @@ -210,6 +211,8 @@ func (m *Manager) handleGetModel(w http.ResponseWriter, r *http.Request) { } // handleDeleteModel handles DELETE /models/{name} requests. +// query params: +// - force: if true, delete the model even if it has multiple tags func (m *Manager) handleDeleteModel(w http.ResponseWriter, r *http.Request) { if m.distributionClient == nil { http.Error(w, "model distribution service unavailable", http.StatusServiceUnavailable) @@ -225,12 +228,24 @@ func (m *Manager) handleDeleteModel(w http.ResponseWriter, r *http.Request) { // the runner process exits (though this won't work for Windows, where we // might need some separate cleanup process). - err := m.distributionClient.DeleteModel(r.PathValue("name")) - if err != nil { + var force bool + if r.URL.Query().Has("force") { + if val, err := strconv.ParseBool(r.URL.Query().Get("force")); err != nil { + m.log.Warnln("Error while parsing force query parameter:", err) + } else { + force = val + } + } + + if err := m.distributionClient.DeleteModel(r.PathValue("name"), force); err != nil { if errors.Is(err, distribution.ErrModelNotFound) { http.Error(w, err.Error(), http.StatusNotFound) return } + if errors.Is(err, distribution.ErrConflict) { + http.Error(w, err.Error(), http.StatusConflict) + return + } m.log.Warnln("Error while deleting model:", err) http.Error(w, err.Error(), http.StatusInternalServerError) return