Browse code

Merge pull request #51103 from thaJeztah/image_inspect_rm_deprecated

api/types/image: InspectResponse: remove deprecated fields

Sebastiaan van Stijn authored on 2025/10/08 20:06:09
Showing 9 changed files
... ...
@@ -2,7 +2,6 @@ package image
2 2
 
3 3
 import (
4 4
 	dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
5
-	"github.com/moby/moby/api/types/container"
6 5
 	"github.com/moby/moby/api/types/storage"
7 6
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
8 7
 )
... ...
@@ -43,15 +42,6 @@ type InspectResponse struct {
43 43
 	// the manifest is generated and its digest calculated.
44 44
 	RepoDigests []string
45 45
 
46
-	// Parent is the ID of the parent image.
47
-	//
48
-	// Depending on how the image was created, this field may be empty and
49
-	// is only set for images that were built/created locally. This field
50
-	// is omitted if the image was pulled from an image registry.
51
-	//
52
-	// Deprecated: this field is deprecated, and will be removed in the next release.
53
-	Parent string `json:",omitempty"`
54
-
55 46
 	// Comment is an optional message that can be set when committing or
56 47
 	// importing the image. This field is omitted if not set.
57 48
 	Comment string `json:",omitempty"`
... ...
@@ -63,29 +53,6 @@ type InspectResponse struct {
63 63
 	// and omitted otherwise.
64 64
 	Created string `json:",omitempty"`
65 65
 
66
-	// Container is the ID of the container that was used to create the image.
67
-	//
68
-	// Depending on how the image was created, this field may be empty.
69
-	//
70
-	// Deprecated: this field is omitted in API v1.45, but kept for backward compatibility.
71
-	Container string `json:",omitempty"`
72
-
73
-	// ContainerConfig is an optional field containing the configuration of the
74
-	// container that was last committed when creating the image.
75
-	//
76
-	// Previous versions of Docker builder used this field to store build cache,
77
-	// and it is not in active use anymore.
78
-	//
79
-	// Deprecated: this field is omitted in API v1.45, but kept for backward compatibility.
80
-	ContainerConfig *container.Config `json:",omitempty"`
81
-
82
-	// DockerVersion is the version of Docker that was used to build the image.
83
-	//
84
-	// Depending on how the image was created, this field may be omitted.
85
-	//
86
-	// Deprecated: this field is deprecated, and will be removed in the next release.
87
-	DockerVersion string `json:",omitempty"`
88
-
89 66
 	// Author is the name of the author that was specified when committing the
90 67
 	// image, or as specified through MAINTAINER (deprecated) in the Dockerfile.
91 68
 	// This field is omitted if not set.
... ...
@@ -108,12 +75,6 @@ type InspectResponse struct {
108 108
 	// Size is the total size of the image including all layers it is composed of.
109 109
 	Size int64
110 110
 
111
-	// VirtualSize is the total size of the image including all layers it is
112
-	// composed of.
113
-	//
114
-	// Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
115
-	VirtualSize int64 `json:"VirtualSize,omitempty"`
116
-
117 111
 	// GraphDriver holds information about the storage driver used to store the
118 112
 	// container's and image's filesystem.
119 113
 	GraphDriver *storage.DriverData `json:"GraphDriver,omitempty"`
... ...
@@ -18,7 +18,7 @@ import (
18 18
 	"golang.org/x/sync/semaphore"
19 19
 )
20 20
 
21
-func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagetypes.InspectResponse, error) {
21
+func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagebackend.InspectData, error) {
22 22
 	requestedPlatform := opts.Platform
23 23
 
24 24
 	c8dImg, err := i.resolveImage(ctx, refOrID)
... ...
@@ -85,17 +85,19 @@ func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts im
85 85
 		target = multi.Best.Target()
86 86
 	}
87 87
 
88
-	resp := &imagetypes.InspectResponse{
89
-		ID:          target.Digest.String(),
90
-		RepoTags:    repoTags,
91
-		Descriptor:  &target,
92
-		RepoDigests: repoDigests,
93
-		Parent:      parent, //nolint:staticcheck // ignore SA1019: field is deprecated, but still included in response when present.
94
-		Size:        size,
95
-		Manifests:   manifests,
96
-		Metadata: imagetypes.Metadata{
97
-			LastTagTime: lastUpdated,
88
+	resp := &imagebackend.InspectData{
89
+		InspectResponse: imagetypes.InspectResponse{
90
+			ID:          target.Digest.String(),
91
+			RepoTags:    repoTags,
92
+			Descriptor:  &target,
93
+			RepoDigests: repoDigests,
94
+			Size:        size,
95
+			Manifests:   manifests,
96
+			Metadata: imagetypes.Metadata{
97
+				LastTagTime: lastUpdated,
98
+			},
98 99
 		},
100
+		Parent: parent, // field is deprecated with the legacy builder, but returned by the API if present.
99 101
 	}
100 102
 
101 103
 	if multi.Best != nil {
... ...
@@ -43,7 +43,7 @@ type ImageService interface {
43 43
 	ImageHistory(ctx context.Context, name string, platform *ocispec.Platform) ([]*imagetype.HistoryResponseItem, error)
44 44
 	CommitImage(ctx context.Context, c backend.CommitConfig) (image.ID, error)
45 45
 	SquashImage(id, parent string) (string, error)
46
-	ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagetype.InspectResponse, error)
46
+	ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagebackend.InspectData, error)
47 47
 	ImageDiskUsage(ctx context.Context) (int64, error)
48 48
 
49 49
 	// Layers
... ...
@@ -12,7 +12,7 @@ import (
12 12
 	"github.com/moby/moby/v2/daemon/server/imagebackend"
13 13
 )
14 14
 
15
-func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagetypes.InspectResponse, error) {
15
+func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagebackend.InspectData, error) {
16 16
 	img, err := i.GetImage(ctx, refOrID, imagebackend.GetImageOpts{Platform: opts.Platform})
17 17
 	if err != nil {
18 18
 		return nil, err
... ...
@@ -54,34 +54,36 @@ func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts im
54 54
 	}
55 55
 
56 56
 	imgConfig := containerConfigToDockerOCIImageConfig(img.Config)
57
-	return &imagetypes.InspectResponse{
58
-		ID:              img.ID().String(),
59
-		RepoTags:        repoTags,
60
-		RepoDigests:     repoDigests,
61
-		Parent:          img.Parent.String(), //nolint:staticcheck // ignore SA1019: field is deprecated, but still included in response when present (built with legacy builder).
62
-		Comment:         comment,
63
-		Created:         created,
64
-		Container:       img.Container,        //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
65
-		ContainerConfig: &img.ContainerConfig, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
66
-		DockerVersion:   img.DockerVersion,    //nolint:staticcheck // ignore SA1019: field is deprecated, but still included in response when present.
67
-		Author:          img.Author,
68
-		Config:          &imgConfig,
69
-		Architecture:    img.Architecture,
70
-		Variant:         img.Variant,
71
-		Os:              img.OperatingSystem(),
72
-		OsVersion:       img.OSVersion,
73
-		Size:            size,
74
-		GraphDriver: &storage.DriverData{
75
-			Name: i.layerStore.DriverName(),
76
-			Data: layerMetadata,
77
-		},
78
-		RootFS: imagetypes.RootFS{
79
-			Type:   img.RootFS.Type,
80
-			Layers: layers,
81
-		},
82
-		Metadata: imagetypes.Metadata{
83
-			LastTagTime: lastUpdated,
57
+	return &imagebackend.InspectData{
58
+		InspectResponse: imagetypes.InspectResponse{
59
+			ID:           img.ID().String(),
60
+			RepoTags:     repoTags,
61
+			RepoDigests:  repoDigests,
62
+			Comment:      comment,
63
+			Created:      created,
64
+			Author:       img.Author,
65
+			Config:       &imgConfig,
66
+			Architecture: img.Architecture,
67
+			Variant:      img.Variant,
68
+			Os:           img.OperatingSystem(),
69
+			OsVersion:    img.OSVersion,
70
+			Size:         size,
71
+			GraphDriver: &storage.DriverData{
72
+				Name: i.layerStore.DriverName(),
73
+				Data: layerMetadata,
74
+			},
75
+			RootFS: imagetypes.RootFS{
76
+				Type:   img.RootFS.Type,
77
+				Layers: layers,
78
+			},
79
+			Metadata: imagetypes.Metadata{
80
+				LastTagTime: lastUpdated,
81
+			},
84 82
 		},
83
+		Parent:          img.Parent.String(),  // field is deprecated with the legacy builder, but still included in response when present (built with legacy builder).
84
+		DockerVersion:   img.DockerVersion,    // field is deprecated with the legacy builder, but still included in response when present.
85
+		Container:       img.Container,        // field is deprecated, but still set on API < v1.45.
86
+		ContainerConfig: &img.ContainerConfig, // field is deprecated, but still set on API < v1.45.
85 87
 	}, nil
86 88
 }
87 89
 
... ...
@@ -4,7 +4,9 @@ import (
4 4
 	"io"
5 5
 	"net/http"
6 6
 
7
+	"github.com/moby/moby/api/types/container"
7 8
 	"github.com/moby/moby/api/types/filters"
9
+	imagetypes "github.com/moby/moby/api/types/image"
8 10
 	"github.com/moby/moby/api/types/registry"
9 11
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
10 12
 )
... ...
@@ -55,3 +57,39 @@ type ImageInspectOpts struct {
55 55
 	Manifests bool
56 56
 	Platform  *ocispec.Platform
57 57
 }
58
+
59
+type InspectData struct {
60
+	imagetypes.InspectResponse
61
+
62
+	// Parent is the ID of the parent image.
63
+	//
64
+	// Depending on how the image was created, this field may be empty and
65
+	// is only set for images that were built/created locally. This field
66
+	// is omitted if the image was pulled from an image registry.
67
+	//
68
+	// This field is deprecated with the legacy builder, but returned by the API if present.
69
+	Parent string `json:",omitempty"`
70
+
71
+	// DockerVersion is the version of Docker that was used to build the image.
72
+	//
73
+	// Depending on how the image was created, this field may be omitted.
74
+	//
75
+	// This field is deprecated with the legacy builder, but returned by the API if present.
76
+	DockerVersion string `json:",omitempty"`
77
+
78
+	// Container is the ID of the container that was used to create the image.
79
+	//
80
+	// Depending on how the image was created, this field may be empty.
81
+	//
82
+	// This field is removed in API v1.45, but used for API <= v1.44 responses.
83
+	Container string
84
+
85
+	// ContainerConfig is an optional field containing the configuration of the
86
+	// container that was last committed when creating the image.
87
+	//
88
+	// Previous versions of Docker builder used this field to store build cache,
89
+	// and it is not in active use anymore.
90
+	//
91
+	// This field is removed in API v1.45, but used for API <= v1.44 responses.
92
+	ContainerConfig *container.Config
93
+}
... ...
@@ -26,7 +26,7 @@ type imageBackend interface {
26 26
 	ImageHistory(ctx context.Context, imageName string, platform *ocispec.Platform) ([]*image.HistoryResponseItem, error)
27 27
 	Images(ctx context.Context, opts imagebackend.ListOptions) ([]*image.Summary, error)
28 28
 	GetImage(ctx context.Context, refOrID string, options imagebackend.GetImageOpts) (*dockerimage.Image, error)
29
-	ImageInspect(ctx context.Context, refOrID string, options imagebackend.ImageInspectOpts) (*image.InspectResponse, error)
29
+	ImageInspect(ctx context.Context, refOrID string, options imagebackend.ImageInspectOpts) (*imagebackend.InspectData, error)
30 30
 	TagImage(ctx context.Context, id dockerimage.ID, newRef reference.Named) error
31 31
 	ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*image.PruneReport, error)
32 32
 }
... ...
@@ -379,13 +379,14 @@ func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWrite
379 379
 		return errdefs.InvalidParameter(errors.New("conflicting options: manifests and platform options cannot both be set"))
380 380
 	}
381 381
 
382
-	imageInspect, err := ir.backend.ImageInspect(ctx, vars["name"], imagebackend.ImageInspectOpts{
382
+	inspectData, err := ir.backend.ImageInspect(ctx, vars["name"], imagebackend.ImageInspectOpts{
383 383
 		Manifests: manifests,
384 384
 		Platform:  platform,
385 385
 	})
386 386
 	if err != nil {
387 387
 		return err
388 388
 	}
389
+	imageInspect := inspectData.InspectResponse
389 390
 
390 391
 	var legacyOptions []compat.Option
391 392
 
... ...
@@ -409,9 +410,11 @@ func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWrite
409 409
 			imageInspect.Created = time.Time{}.Format(time.RFC3339Nano)
410 410
 		}
411 411
 	}
412
-	if versions.GreaterThanOrEqualTo(version, "1.45") {
413
-		imageInspect.Container = ""        //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
414
-		imageInspect.ContainerConfig = nil //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.45.
412
+	if versions.LessThan(version, "1.45") {
413
+		legacyOptions = append(legacyOptions, compat.WithExtraFields(map[string]any{
414
+			"Container":       inspectData.Container,
415
+			"ContainerConfig": inspectData.ContainerConfig,
416
+		}))
415 417
 	}
416 418
 	if versions.LessThan(version, "1.48") {
417 419
 		imageInspect.Descriptor = nil
... ...
@@ -420,10 +423,10 @@ func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWrite
420 420
 		// These fields have "omitempty" on API v1.52 and higher,
421 421
 		// but older API versions returned them unconditionally.
422 422
 		legacyOptions = append(legacyOptions, compat.WithExtraFields(map[string]any{
423
-			"Parent":        imageInspect.Parent, //nolint:staticcheck // ignore SA1019: field is deprecated, but still included in response when present (built with legacy builder).
424
-			"Comment":       imageInspect.Comment,
425
-			"DockerVersion": imageInspect.DockerVersion, //nolint:staticcheck // ignore SA1019: field is deprecated, but still included in response when present.
426
-			"Author":        imageInspect.Author,
423
+			"Parent":        inspectData.Parent, // field is deprecated, but still included in response when present (built with legacy builder).
424
+			"Comment":       inspectData.Comment,
425
+			"DockerVersion": inspectData.DockerVersion, // field is deprecated, but still included in response when present.
426
+			"Author":        inspectData.Author,
427 427
 		}))
428 428
 
429 429
 		// preserve fields in the image Config that have an "omitempty"
... ...
@@ -437,6 +440,15 @@ func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWrite
437 437
 				"Config": legacyConfigFields["v1.50-v1.51"],
438 438
 			}))
439 439
 		}
440
+	} else {
441
+		if inspectData.Parent != "" {
442
+			// field is deprecated, but still included in response when present (built with legacy builder).
443
+			legacyOptions = append(legacyOptions, compat.WithExtraFields(map[string]any{"Parent": inspectData.Parent}))
444
+		}
445
+		if inspectData.DockerVersion != "" {
446
+			// field is deprecated, but still included in response when present.
447
+			legacyOptions = append(legacyOptions, compat.WithExtraFields(map[string]any{"DockerVersion": inspectData.DockerVersion}))
448
+		}
440 449
 	}
441 450
 
442 451
 	if len(legacyOptions) > 0 {
... ...
@@ -319,10 +319,22 @@ func (s *DockerAPISuite) TestBuildOnBuildCache(c *testing.T) {
319 319
 	// check parentID is correct
320 320
 	// Parent is graphdriver-only
321 321
 	if !testEnv.UsingSnapshotter() {
322
-		image, err := apiClient.ImageInspect(ctx, childID)
322
+		var buf bytes.Buffer
323
+		_, err := apiClient.ImageInspect(ctx, childID, client.ImageInspectWithRawResponse(&buf))
323 324
 		assert.NilError(c, err)
324 325
 
325
-		assert.Check(c, is.Equal(parentID, image.Parent)) //nolint:staticcheck // ignore SA1019: field is deprecated, but still included in response when present.
326
+		var image struct {
327
+			// Parent is the ID of the parent image.
328
+			//
329
+			// Depending on how the image was created, this field may be empty and
330
+			// is only set for images that were built/created locally. This field
331
+			// is omitted if the image was pulled from an image registry.
332
+			Parent string `json:",omitempty"`
333
+		}
334
+		rawResponse := buf.Bytes()
335
+		err = json.Unmarshal(rawResponse, &image)
336
+		assert.NilError(c, err, string(rawResponse))
337
+		assert.Check(c, is.Equal(parentID, image.Parent), string(rawResponse))
326 338
 	}
327 339
 }
328 340
 
... ...
@@ -2,7 +2,6 @@ package image
2 2
 
3 3
 import (
4 4
 	dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
5
-	"github.com/moby/moby/api/types/container"
6 5
 	"github.com/moby/moby/api/types/storage"
7 6
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
8 7
 )
... ...
@@ -43,15 +42,6 @@ type InspectResponse struct {
43 43
 	// the manifest is generated and its digest calculated.
44 44
 	RepoDigests []string
45 45
 
46
-	// Parent is the ID of the parent image.
47
-	//
48
-	// Depending on how the image was created, this field may be empty and
49
-	// is only set for images that were built/created locally. This field
50
-	// is omitted if the image was pulled from an image registry.
51
-	//
52
-	// Deprecated: this field is deprecated, and will be removed in the next release.
53
-	Parent string `json:",omitempty"`
54
-
55 46
 	// Comment is an optional message that can be set when committing or
56 47
 	// importing the image. This field is omitted if not set.
57 48
 	Comment string `json:",omitempty"`
... ...
@@ -63,29 +53,6 @@ type InspectResponse struct {
63 63
 	// and omitted otherwise.
64 64
 	Created string `json:",omitempty"`
65 65
 
66
-	// Container is the ID of the container that was used to create the image.
67
-	//
68
-	// Depending on how the image was created, this field may be empty.
69
-	//
70
-	// Deprecated: this field is omitted in API v1.45, but kept for backward compatibility.
71
-	Container string `json:",omitempty"`
72
-
73
-	// ContainerConfig is an optional field containing the configuration of the
74
-	// container that was last committed when creating the image.
75
-	//
76
-	// Previous versions of Docker builder used this field to store build cache,
77
-	// and it is not in active use anymore.
78
-	//
79
-	// Deprecated: this field is omitted in API v1.45, but kept for backward compatibility.
80
-	ContainerConfig *container.Config `json:",omitempty"`
81
-
82
-	// DockerVersion is the version of Docker that was used to build the image.
83
-	//
84
-	// Depending on how the image was created, this field may be omitted.
85
-	//
86
-	// Deprecated: this field is deprecated, and will be removed in the next release.
87
-	DockerVersion string `json:",omitempty"`
88
-
89 66
 	// Author is the name of the author that was specified when committing the
90 67
 	// image, or as specified through MAINTAINER (deprecated) in the Dockerfile.
91 68
 	// This field is omitted if not set.
... ...
@@ -108,12 +75,6 @@ type InspectResponse struct {
108 108
 	// Size is the total size of the image including all layers it is composed of.
109 109
 	Size int64
110 110
 
111
-	// VirtualSize is the total size of the image including all layers it is
112
-	// composed of.
113
-	//
114
-	// Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
115
-	VirtualSize int64 `json:"VirtualSize,omitempty"`
116
-
117 111
 	// GraphDriver holds information about the storage driver used to store the
118 112
 	// container's and image's filesystem.
119 113
 	GraphDriver *storage.DriverData `json:"GraphDriver,omitempty"`