Skip to content

Commit 6f80734

Browse files
committed
distribution client: return untagged tags on delete (docker#104)
* distribution client: return untagged tags on delete Signed-off-by: Dorin Geman <dorin.geman@docker.com> * distribution client: check expected DeleteModel response Signed-off-by: Dorin Geman <dorin.geman@docker.com> --------- Signed-off-by: Dorin Geman <dorin.geman@docker.com>
1 parent 48320a8 commit 6f80734

File tree

5 files changed

+36
-13
lines changed

5 files changed

+36
-13
lines changed

pkg/distribution/distribution/client.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"net/http"
88
"os"
9+
"strings"
910

1011
"github.com/sirupsen/logrus"
1112

@@ -243,44 +244,50 @@ func (c *Client) GetModel(reference string) (types.Model, error) {
243244
}
244245

245246
// DeleteModel deletes a model
246-
func (c *Client) DeleteModel(reference string, force bool) error {
247+
func (c *Client) DeleteModel(reference string, force bool) (string, error) {
247248
mdl, err := c.store.Read(reference)
248249
if err != nil {
249-
return err
250+
return "", err
250251
}
251252
id, err := mdl.ID()
252253
if err != nil {
253-
return fmt.Errorf("getting model ID: %w", err)
254+
return "", fmt.Errorf("getting model ID: %w", err)
254255
}
255256
isTag := id != reference
256257

257258
if isTag {
258259
c.log.Infoln("Untagging model:", reference)
259260
if err := c.store.RemoveTags([]string{reference}); err != nil {
260261
c.log.Errorln("Failed to untag model:", err, "tag:", reference)
261-
return fmt.Errorf("untagging model: %w", err)
262+
return "", fmt.Errorf("untagging model: %w", err)
262263
}
263264
}
264265

265266
if len(mdl.Tags()) > 1 {
266267
if isTag {
267-
return nil // we are done after untagging
268+
// TODO: This should return the full matching tag.
269+
return fmt.Sprintf("Untagged: %s\n", reference), nil
268270
} else if !force {
269271
// if the reference is not a tag and there are multiple tags, return an error unless forced
270-
return fmt.Errorf(
272+
return "", fmt.Errorf(
271273
"unable to delete %q (must be forced) due to multiple tag references: %w",
272274
reference, ErrConflict,
273275
)
274276
}
275277
}
276278

279+
var untaggedInfo strings.Builder
280+
for _, tag := range mdl.Tags() {
281+
untaggedInfo.WriteString(fmt.Sprintf("Untagged: %s\n", tag))
282+
}
283+
277284
c.log.Infoln("Deleting model:", id)
278285
if err := c.store.Delete(id); err != nil {
279286
c.log.Errorln("Failed to delete model:", err, "tag:", reference)
280-
return fmt.Errorf("deleting model: %w", err)
287+
return "", fmt.Errorf("deleting model: %w", err)
281288
}
282289
c.log.Infoln("Successfully deleted model:", reference)
283-
return nil
290+
return untaggedInfo.String(), nil
284291
}
285292

286293
// Tag adds a tag to a model

pkg/distribution/distribution/client_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ func TestClientPullModel(t *testing.T) {
246246
}
247247

248248
// Delete the local model to force a pull
249-
if err := client.DeleteModel(tag, false); err != nil {
249+
if _, err := client.DeleteModel(tag, false); err != nil {
250250
t.Fatalf("Failed to delete model: %v", err)
251251
}
252252

@@ -866,7 +866,7 @@ func TestPush(t *testing.T) {
866866
}
867867

868868
// Delete local copy (so we can test pulling)
869-
if err := client.DeleteModel(tag, false); err != nil {
869+
if _, err := client.DeleteModel(tag, false); err != nil {
870870
t.Fatalf("Failed to delete model: %v", err)
871871
}
872872

pkg/distribution/distribution/delete_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package distribution
33
import (
44
"errors"
55
"os"
6+
"slices"
67
"testing"
78

89
"github.com/docker/model-distribution/internal/gguf"
@@ -122,13 +123,28 @@ func TestDeleteModel(t *testing.T) {
122123
}
123124

124125
// Attempt to delete the model and check for expected error
125-
if err := client.DeleteModel(tc.ref, tc.force); !errors.Is(err, tc.expectedErr) {
126+
out, err := client.DeleteModel(tc.ref, tc.force)
127+
if !errors.Is(err, tc.expectedErr) {
126128
t.Fatalf("Expected error %v, got: %v", tc.expectedErr, err)
127129
}
128130
if tc.expectedErr != nil {
129131
return
130132
}
131133

134+
expectedOut := ""
135+
if slices.Contains(tc.tags, tc.ref) {
136+
// tc.ref is a tag
137+
expectedOut = "Untagged: " + tc.ref + "\n"
138+
} else {
139+
// tc.ref is an ID
140+
for _, tag := range tc.tags {
141+
expectedOut += "Untagged: " + tag + "\n"
142+
}
143+
}
144+
if expectedOut != out {
145+
t.Fatalf("Expected output %q, got: %q", expectedOut, out)
146+
}
147+
132148
// Verify model ref unreachable by ref (untagged)
133149
_, err = client.GetModel(tc.ref)
134150
if !errors.Is(err, ErrModelNotFound) {

pkg/distribution/distribution/ecr_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func TestECRIntegration(t *testing.T) {
5151
if err := client.PushModel(context.Background(), ecrTag, nil); err != nil {
5252
t.Fatalf("Failed to push model to ECR: %v", err)
5353
}
54-
if err := client.DeleteModel(ecrTag, false); err != nil { // cleanup
54+
if _, err := client.DeleteModel(ecrTag, false); err != nil { // cleanup
5555
t.Fatalf("Failed to delete model from store: %v", err)
5656
}
5757
})

pkg/distribution/distribution/gar_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestGARIntegration(t *testing.T) {
5252
if err := client.PushModel(context.Background(), garTag, nil); err != nil {
5353
t.Fatalf("Failed to push model to ECR: %v", err)
5454
}
55-
if err := client.DeleteModel(garTag, false); err != nil { // cleanup
55+
if _, err := client.DeleteModel(garTag, false); err != nil { // cleanup
5656
t.Fatalf("Failed to delete model from store: %v", err)
5757
}
5858
})

0 commit comments

Comments
 (0)