Browse code

Merge pull request #51437 from thaJeztah/diskusage_move_legacy

api: remove / internalize LegacyDiskUsage

Rob Murray authored on 2025/11/11 00:03:37
Showing 8 changed files
... ...
@@ -75,9 +75,11 @@ keywords: "API, Docker, rcli, REST, documentation"
75 75
   `BuildCacheUsage` fields with brief system disk usage data for each system object type.
76 76
   The endpoint supports the `?verbose=1` query to return verbose system disk usage information.
77 77
 * Deprecated: `GET /system/df` response fields `LayersSize`, `Images`, `Containers`,
78
-  `Volumes`, and `BuildCache` are deprecated in favor of the type specific usage fields.
79
-  The legacy fields will not be populated for new API versions that specify the `verbose`
80
-  query.
78
+  `Volumes`, and `BuildCache` have been removed in favor of the-type specific usage fields.
79
+  API v1.52 returns both the legacy and current fields to help existing integrations
80
+  to transition to the new response. The legacy fields are not populated if the
81
+  `verbose` query parameter is used. Starting with API v1.53, the legacy fields
82
+  will no longer be returned.
81 83
 
82 84
 ## v1.51 API changes
83 85
 
... ...
@@ -24,27 +24,8 @@ const (
24 24
 // DiskUsage contains response of Engine API:
25 25
 // GET "/system/df"
26 26
 type DiskUsage struct {
27
-	LegacyDiskUsage
28
-
29 27
 	ImageUsage      *image.DiskUsage     `json:"ImageUsage,omitempty"`
30 28
 	ContainerUsage  *container.DiskUsage `json:"ContainerUsage,omitempty"`
31 29
 	VolumeUsage     *volume.DiskUsage    `json:"VolumeUsage,omitempty"`
32 30
 	BuildCacheUsage *build.DiskUsage     `json:"BuildCacheUsage,omitempty"`
33 31
 }
34
-
35
-type LegacyDiskUsage struct {
36
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.TotalSize] instead.
37
-	LayersSize int64 `json:"LayersSize,omitempty"`
38
-
39
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.Items] instead.
40
-	Images []image.Summary `json:"Images,omitzero"`
41
-
42
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ContainersDiskUsage.Items] instead.
43
-	Containers []container.Summary `json:"Containers,omitzero"`
44
-
45
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [VolumesDiskUsage.Items] instead.
46
-	Volumes []volume.Volume `json:"Volumes,omitzero"`
47
-
48
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [BuildCacheDiskUsage.Items] instead.
49
-	BuildCache []build.CacheRecord `json:"BuildCache,omitzero"`
50
-}
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"fmt"
7 7
 	"net/url"
8 8
 	"slices"
9
-	"strings"
10 9
 
11 10
 	"github.com/moby/moby/api/types/build"
12 11
 	"github.com/moby/moby/api/types/container"
... ...
@@ -149,16 +148,21 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis
149 149
 		return DiskUsageResult{}, err
150 150
 	}
151 151
 
152
-	var du system.DiskUsage
153
-	if err := json.NewDecoder(resp.Body).Decode(&du); err != nil {
154
-		return DiskUsageResult{}, fmt.Errorf("Error retrieving disk usage: %v", err)
155
-	}
156
-
157
-	// Generate result from a legacy response.
158 152
 	if versions.LessThan(cli.version, "1.52") {
153
+		// Generate result from a legacy response.
154
+		var du legacyDiskUsage
155
+		if err := json.NewDecoder(resp.Body).Decode(&du); err != nil {
156
+			return DiskUsageResult{}, fmt.Errorf("retrieving disk usage: %v", err)
157
+		}
158
+
159 159
 		return diskUsageResultFromLegacyAPI(&du), nil
160 160
 	}
161 161
 
162
+	var du system.DiskUsage
163
+	if err := json.NewDecoder(resp.Body).Decode(&du); err != nil {
164
+		return DiskUsageResult{}, fmt.Errorf("retrieving disk usage: %v", err)
165
+	}
166
+
162 167
 	var r DiskUsageResult
163 168
 	if idu := du.ImageUsage; idu != nil {
164 169
 		r.Images = ImagesDiskUsage{
... ...
@@ -215,7 +219,16 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis
215 215
 	return r, nil
216 216
 }
217 217
 
218
-func diskUsageResultFromLegacyAPI(du *system.DiskUsage) DiskUsageResult {
218
+// legacyDiskUsage is the response as was used by API < v1.52.
219
+type legacyDiskUsage struct {
220
+	LayersSize int64               `json:"LayersSize,omitempty"`
221
+	Images     []image.Summary     `json:"Images,omitzero"`
222
+	Containers []container.Summary `json:"Containers,omitzero"`
223
+	Volumes    []volume.Volume     `json:"Volumes,omitzero"`
224
+	BuildCache []build.CacheRecord `json:"BuildCache,omitzero"`
225
+}
226
+
227
+func diskUsageResultFromLegacyAPI(du *legacyDiskUsage) DiskUsageResult {
219 228
 	return DiskUsageResult{
220 229
 		Images:     imageDiskUsageFromLegacyAPI(du),
221 230
 		Containers: containerDiskUsageFromLegacyAPI(du),
... ...
@@ -224,7 +237,7 @@ func diskUsageResultFromLegacyAPI(du *system.DiskUsage) DiskUsageResult {
224 224
 	}
225 225
 }
226 226
 
227
-func imageDiskUsageFromLegacyAPI(du *system.DiskUsage) ImagesDiskUsage {
227
+func imageDiskUsageFromLegacyAPI(du *legacyDiskUsage) ImagesDiskUsage {
228 228
 	idu := ImagesDiskUsage{
229 229
 		TotalSize:  du.LayersSize,
230 230
 		TotalCount: int64(len(du.Images)),
... ...
@@ -250,7 +263,7 @@ func imageDiskUsageFromLegacyAPI(du *system.DiskUsage) ImagesDiskUsage {
250 250
 	return idu
251 251
 }
252 252
 
253
-func containerDiskUsageFromLegacyAPI(du *system.DiskUsage) ContainersDiskUsage {
253
+func containerDiskUsageFromLegacyAPI(du *legacyDiskUsage) ContainersDiskUsage {
254 254
 	cdu := ContainersDiskUsage{
255 255
 		TotalCount: int64(len(du.Containers)),
256 256
 		Items:      du.Containers,
... ...
@@ -259,8 +272,8 @@ func containerDiskUsageFromLegacyAPI(du *system.DiskUsage) ContainersDiskUsage {
259 259
 	var used int64
260 260
 	for _, c := range cdu.Items {
261 261
 		cdu.TotalSize += c.SizeRw
262
-		switch strings.ToLower(c.State) {
263
-		case "running", "paused", "restarting":
262
+		switch c.State {
263
+		case container.StateRunning, container.StatePaused, container.StateRestarting:
264 264
 			cdu.ActiveCount++
265 265
 			used += c.SizeRw
266 266
 		}
... ...
@@ -270,7 +283,7 @@ func containerDiskUsageFromLegacyAPI(du *system.DiskUsage) ContainersDiskUsage {
270 270
 	return cdu
271 271
 }
272 272
 
273
-func buildCacheDiskUsageFromLegacyAPI(du *system.DiskUsage) BuildCacheDiskUsage {
273
+func buildCacheDiskUsageFromLegacyAPI(du *legacyDiskUsage) BuildCacheDiskUsage {
274 274
 	bdu := BuildCacheDiskUsage{
275 275
 		TotalCount: int64(len(du.BuildCache)),
276 276
 		Items:      du.BuildCache,
... ...
@@ -294,7 +307,7 @@ func buildCacheDiskUsageFromLegacyAPI(du *system.DiskUsage) BuildCacheDiskUsage
294 294
 	return bdu
295 295
 }
296 296
 
297
-func volumeDiskUsageFromLegacyAPI(du *system.DiskUsage) VolumesDiskUsage {
297
+func volumeDiskUsageFromLegacyAPI(du *legacyDiskUsage) VolumesDiskUsage {
298 298
 	vdu := VolumesDiskUsage{
299 299
 		TotalCount: int64(len(du.Volumes)),
300 300
 		Items:      du.Volumes,
... ...
@@ -139,11 +139,9 @@ func TestLegacyDiskUsage(t *testing.T) {
139 139
 				return nil, err
140 140
 			}
141 141
 
142
-			return mockJSONResponse(http.StatusOK, nil, system.DiskUsage{
143
-				LegacyDiskUsage: system.LegacyDiskUsage{
144
-					LayersSize: 4096,
145
-					Images:     []image.Summary{},
146
-				},
142
+			return mockJSONResponse(http.StatusOK, nil, &legacyDiskUsage{
143
+				LayersSize: 4096,
144
+				Images:     []image.Summary{},
147 145
 			})(req)
148 146
 		}))
149 147
 	assert.NilError(t, err)
150 148
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+package system
1
+
2
+import (
3
+	buildtypes "github.com/moby/moby/api/types/build"
4
+	"github.com/moby/moby/api/types/container"
5
+	"github.com/moby/moby/api/types/image"
6
+	"github.com/moby/moby/api/types/system"
7
+	"github.com/moby/moby/api/types/volume"
8
+)
9
+
10
+// diskUsageCompat is used to provide API responses with backward-compatibility
11
+// for API < v1.52, which used a different format. For API v1.52, we return
12
+// both "old" and "new" responses if the client did not explicitly opt in to
13
+// using the new format (through the use of the "verbose" query-parameter).
14
+type diskUsageCompat struct {
15
+	*legacyDiskUsage
16
+	*system.DiskUsage
17
+}
18
+
19
+// legacyDiskUsage is the response as was used by API < v1.52.
20
+type legacyDiskUsage struct {
21
+	LayersSize int64                    `json:"LayersSize,omitempty"`
22
+	Images     []image.Summary          `json:"Images,omitzero"`
23
+	Containers []container.Summary      `json:"Containers,omitzero"`
24
+	Volumes    []volume.Volume          `json:"Volumes,omitzero"`
25
+	BuildCache []buildtypes.CacheRecord `json:"BuildCache,omitzero"`
26
+}
... ...
@@ -216,32 +216,34 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
216 216
 	}
217 217
 	diskUsage.BuildCache = buildCacheUsage
218 218
 
219
-	var legacy system.LegacyDiskUsage
219
+	var legacy legacyDiskUsage
220 220
 	if legacyFields {
221 221
 		if diskUsage.Images != nil {
222
-			legacy.LayersSize = diskUsage.Images.TotalSize      //nolint: staticcheck,SA1019: kept to maintain backwards compatibility with API < v1.52.
223
-			legacy.Images = nonNilSlice(diskUsage.Images.Items) //nolint: staticcheck,SA1019: kept to maintain backwards compatibility with API < v1.52.
222
+			legacy.LayersSize = diskUsage.Images.TotalSize
223
+			legacy.Images = nonNilSlice(diskUsage.Images.Items)
224 224
 		}
225 225
 		if diskUsage.Containers != nil {
226
-			legacy.Containers = nonNilSlice(diskUsage.Containers.Items) //nolint: staticcheck,SA1019: kept to maintain backwards compatibility with API < v1.52.
226
+			legacy.Containers = nonNilSlice(diskUsage.Containers.Items)
227 227
 		}
228 228
 		if diskUsage.Volumes != nil {
229
-			legacy.Volumes = nonNilSlice(diskUsage.Volumes.Items) //nolint: staticcheck,SA1019: kept to maintain backwards compatibility with API < v1.52.
229
+			legacy.Volumes = nonNilSlice(diskUsage.Volumes.Items)
230 230
 		}
231 231
 		if diskUsage.BuildCache != nil {
232
-			legacy.BuildCache = nonNilSlice(diskUsage.BuildCache.Items) //nolint: staticcheck,SA1019: kept to maintain backwards compatibility with API < v1.52.
232
+			legacy.BuildCache = nonNilSlice(diskUsage.BuildCache.Items)
233 233
 		}
234 234
 	}
235 235
 	if versions.LessThan(version, "1.52") {
236
-		return httputils.WriteJSON(w, http.StatusOK, legacy)
236
+		return httputils.WriteJSON(w, http.StatusOK, &legacy)
237 237
 	}
238 238
 
239
-	return httputils.WriteJSON(w, http.StatusOK, &system.DiskUsage{
240
-		LegacyDiskUsage: legacy,
241
-		ImageUsage:      diskUsage.Images,
242
-		ContainerUsage:  diskUsage.Containers,
243
-		VolumeUsage:     diskUsage.Volumes,
244
-		BuildCacheUsage: diskUsage.BuildCache,
239
+	return httputils.WriteJSON(w, http.StatusOK, &diskUsageCompat{
240
+		legacyDiskUsage: &legacy,
241
+		DiskUsage: &system.DiskUsage{
242
+			ImageUsage:      diskUsage.Images,
243
+			ContainerUsage:  diskUsage.Containers,
244
+			VolumeUsage:     diskUsage.Volumes,
245
+			BuildCacheUsage: diskUsage.BuildCache,
246
+		},
245 247
 	})
246 248
 }
247 249
 
... ...
@@ -24,27 +24,8 @@ const (
24 24
 // DiskUsage contains response of Engine API:
25 25
 // GET "/system/df"
26 26
 type DiskUsage struct {
27
-	LegacyDiskUsage
28
-
29 27
 	ImageUsage      *image.DiskUsage     `json:"ImageUsage,omitempty"`
30 28
 	ContainerUsage  *container.DiskUsage `json:"ContainerUsage,omitempty"`
31 29
 	VolumeUsage     *volume.DiskUsage    `json:"VolumeUsage,omitempty"`
32 30
 	BuildCacheUsage *build.DiskUsage     `json:"BuildCacheUsage,omitempty"`
33 31
 }
34
-
35
-type LegacyDiskUsage struct {
36
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.TotalSize] instead.
37
-	LayersSize int64 `json:"LayersSize,omitempty"`
38
-
39
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.Items] instead.
40
-	Images []image.Summary `json:"Images,omitzero"`
41
-
42
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ContainersDiskUsage.Items] instead.
43
-	Containers []container.Summary `json:"Containers,omitzero"`
44
-
45
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [VolumesDiskUsage.Items] instead.
46
-	Volumes []volume.Volume `json:"Volumes,omitzero"`
47
-
48
-	// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [BuildCacheDiskUsage.Items] instead.
49
-	BuildCache []build.CacheRecord `json:"BuildCache,omitzero"`
50
-}
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"fmt"
7 7
 	"net/url"
8 8
 	"slices"
9
-	"strings"
10 9
 
11 10
 	"github.com/moby/moby/api/types/build"
12 11
 	"github.com/moby/moby/api/types/container"
... ...
@@ -149,16 +148,21 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis
149 149
 		return DiskUsageResult{}, err
150 150
 	}
151 151
 
152
-	var du system.DiskUsage
153
-	if err := json.NewDecoder(resp.Body).Decode(&du); err != nil {
154
-		return DiskUsageResult{}, fmt.Errorf("Error retrieving disk usage: %v", err)
155
-	}
156
-
157
-	// Generate result from a legacy response.
158 152
 	if versions.LessThan(cli.version, "1.52") {
153
+		// Generate result from a legacy response.
154
+		var du legacyDiskUsage
155
+		if err := json.NewDecoder(resp.Body).Decode(&du); err != nil {
156
+			return DiskUsageResult{}, fmt.Errorf("retrieving disk usage: %v", err)
157
+		}
158
+
159 159
 		return diskUsageResultFromLegacyAPI(&du), nil
160 160
 	}
161 161
 
162
+	var du system.DiskUsage
163
+	if err := json.NewDecoder(resp.Body).Decode(&du); err != nil {
164
+		return DiskUsageResult{}, fmt.Errorf("retrieving disk usage: %v", err)
165
+	}
166
+
162 167
 	var r DiskUsageResult
163 168
 	if idu := du.ImageUsage; idu != nil {
164 169
 		r.Images = ImagesDiskUsage{
... ...
@@ -215,7 +219,16 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis
215 215
 	return r, nil
216 216
 }
217 217
 
218
-func diskUsageResultFromLegacyAPI(du *system.DiskUsage) DiskUsageResult {
218
+// legacyDiskUsage is the response as was used by API < v1.52.
219
+type legacyDiskUsage struct {
220
+	LayersSize int64               `json:"LayersSize,omitempty"`
221
+	Images     []image.Summary     `json:"Images,omitzero"`
222
+	Containers []container.Summary `json:"Containers,omitzero"`
223
+	Volumes    []volume.Volume     `json:"Volumes,omitzero"`
224
+	BuildCache []build.CacheRecord `json:"BuildCache,omitzero"`
225
+}
226
+
227
+func diskUsageResultFromLegacyAPI(du *legacyDiskUsage) DiskUsageResult {
219 228
 	return DiskUsageResult{
220 229
 		Images:     imageDiskUsageFromLegacyAPI(du),
221 230
 		Containers: containerDiskUsageFromLegacyAPI(du),
... ...
@@ -224,7 +237,7 @@ func diskUsageResultFromLegacyAPI(du *system.DiskUsage) DiskUsageResult {
224 224
 	}
225 225
 }
226 226
 
227
-func imageDiskUsageFromLegacyAPI(du *system.DiskUsage) ImagesDiskUsage {
227
+func imageDiskUsageFromLegacyAPI(du *legacyDiskUsage) ImagesDiskUsage {
228 228
 	idu := ImagesDiskUsage{
229 229
 		TotalSize:  du.LayersSize,
230 230
 		TotalCount: int64(len(du.Images)),
... ...
@@ -250,7 +263,7 @@ func imageDiskUsageFromLegacyAPI(du *system.DiskUsage) ImagesDiskUsage {
250 250
 	return idu
251 251
 }
252 252
 
253
-func containerDiskUsageFromLegacyAPI(du *system.DiskUsage) ContainersDiskUsage {
253
+func containerDiskUsageFromLegacyAPI(du *legacyDiskUsage) ContainersDiskUsage {
254 254
 	cdu := ContainersDiskUsage{
255 255
 		TotalCount: int64(len(du.Containers)),
256 256
 		Items:      du.Containers,
... ...
@@ -259,8 +272,8 @@ func containerDiskUsageFromLegacyAPI(du *system.DiskUsage) ContainersDiskUsage {
259 259
 	var used int64
260 260
 	for _, c := range cdu.Items {
261 261
 		cdu.TotalSize += c.SizeRw
262
-		switch strings.ToLower(c.State) {
263
-		case "running", "paused", "restarting":
262
+		switch c.State {
263
+		case container.StateRunning, container.StatePaused, container.StateRestarting:
264 264
 			cdu.ActiveCount++
265 265
 			used += c.SizeRw
266 266
 		}
... ...
@@ -270,7 +283,7 @@ func containerDiskUsageFromLegacyAPI(du *system.DiskUsage) ContainersDiskUsage {
270 270
 	return cdu
271 271
 }
272 272
 
273
-func buildCacheDiskUsageFromLegacyAPI(du *system.DiskUsage) BuildCacheDiskUsage {
273
+func buildCacheDiskUsageFromLegacyAPI(du *legacyDiskUsage) BuildCacheDiskUsage {
274 274
 	bdu := BuildCacheDiskUsage{
275 275
 		TotalCount: int64(len(du.BuildCache)),
276 276
 		Items:      du.BuildCache,
... ...
@@ -294,7 +307,7 @@ func buildCacheDiskUsageFromLegacyAPI(du *system.DiskUsage) BuildCacheDiskUsage
294 294
 	return bdu
295 295
 }
296 296
 
297
-func volumeDiskUsageFromLegacyAPI(du *system.DiskUsage) VolumesDiskUsage {
297
+func volumeDiskUsageFromLegacyAPI(du *legacyDiskUsage) VolumesDiskUsage {
298 298
 	vdu := VolumesDiskUsage{
299 299
 		TotalCount: int64(len(du.Volumes)),
300 300
 		Items:      du.Volumes,