Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -37,14 +37,14 @@ type LegacyDiskUsage struct {
|
| 37 | 37 |
LayersSize int64 `json:"LayersSize,omitempty"` |
| 38 | 38 |
|
| 39 | 39 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.Items] instead. |
| 40 |
- Images []*image.Summary `json:"Images,omitempty"` |
|
| 40 |
+ Images []image.Summary `json:"Images,omitzero"` |
|
| 41 | 41 |
|
| 42 | 42 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ContainersDiskUsage.Items] instead. |
| 43 |
- Containers []*container.Summary `json:"Containers,omitempty"` |
|
| 43 |
+ Containers []container.Summary `json:"Containers,omitzero"` |
|
| 44 | 44 |
|
| 45 | 45 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [VolumesDiskUsage.Items] instead. |
| 46 |
- Volumes []*volume.Volume `json:"Volumes,omitempty"` |
|
| 46 |
+ Volumes []volume.Volume `json:"Volumes,omitzero"` |
|
| 47 | 47 |
|
| 48 | 48 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [BuildCacheDiskUsage.Items] instead. |
| 49 |
- BuildCache []*build.CacheRecord `json:"BuildCache,omitempty"` |
|
| 49 |
+ BuildCache []build.CacheRecord `json:"BuildCache,omitzero"` |
|
| 50 | 50 |
} |
| ... | ... |
@@ -171,13 +171,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 | 173 |
if options.Verbose {
|
| 174 |
- r.Images.Items = slices.Collect(func(yield func(image.Summary) bool) {
|
|
| 175 |
- for _, i := range du.Images {
|
|
| 176 |
- if !yield(*i) {
|
|
| 177 |
- return |
|
| 178 |
- } |
|
| 179 |
- } |
|
| 180 |
- }) |
|
| 174 |
+ r.Images.Items = du.Images |
|
| 181 | 175 |
} |
| 182 | 176 |
} |
| 183 | 177 |
|
| ... | ... |
@@ -194,13 +188,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 194 | 194 |
} |
| 195 | 195 |
} else if du.Containers != nil && options.Verbose {
|
| 196 | 196 |
// Fallback for legacy response. |
| 197 |
- r.Containers.Items = slices.Collect(func(yield func(container.Summary) bool) {
|
|
| 198 |
- for _, c := range du.Containers {
|
|
| 199 |
- if !yield(*c) {
|
|
| 200 |
- return |
|
| 201 |
- } |
|
| 202 |
- } |
|
| 203 |
- }) |
|
| 197 |
+ r.Containers.Items = du.Containers |
|
| 204 | 198 |
} |
| 205 | 199 |
|
| 206 | 200 |
if du.BuildCacheUsage != nil {
|
| ... | ... |
@@ -216,13 +204,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 216 | 216 |
} |
| 217 | 217 |
} else if du.BuildCache != nil && options.Verbose {
|
| 218 | 218 |
// Fallback for legacy response. |
| 219 |
- r.BuildCache.Items = slices.Collect(func(yield func(build.CacheRecord) bool) {
|
|
| 220 |
- for _, b := range du.BuildCache {
|
|
| 221 |
- if !yield(*b) {
|
|
| 222 |
- return |
|
| 223 |
- } |
|
| 224 |
- } |
|
| 225 |
- }) |
|
| 219 |
+ r.BuildCache.Items = du.BuildCache |
|
| 226 | 220 |
} |
| 227 | 221 |
|
| 228 | 222 |
if du.VolumeUsage != nil {
|
| ... | ... |
@@ -238,13 +220,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 238 | 238 |
} |
| 239 | 239 |
} else if du.Volumes != nil && options.Verbose {
|
| 240 | 240 |
// Fallback for legacy response. |
| 241 |
- r.Volumes.Items = slices.Collect(func(yield func(volume.Volume) bool) {
|
|
| 242 |
- for _, v := range du.Volumes {
|
|
| 243 |
- if !yield(*v) {
|
|
| 244 |
- return |
|
| 245 |
- } |
|
| 246 |
- } |
|
| 247 |
- }) |
|
| 241 |
+ r.Volumes.Items = du.Volumes |
|
| 248 | 242 |
} |
| 249 | 243 |
|
| 250 | 244 |
return r, nil |
| ... | ... |
@@ -140,7 +140,7 @@ func TestLegacyDiskUsage(t *testing.T) {
|
| 140 | 140 |
return mockJSONResponse(http.StatusOK, nil, system.DiskUsage{
|
| 141 | 141 |
LegacyDiskUsage: system.LegacyDiskUsage{
|
| 142 | 142 |
LayersSize: 4096, |
| 143 |
- Images: []*image.Summary{},
|
|
| 143 |
+ Images: []image.Summary{},
|
|
| 144 | 144 |
}, |
| 145 | 145 |
})(req) |
| 146 | 146 |
})) |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/moby/moby/v2/daemon/internal/filters" |
| 9 | 9 |
"github.com/moby/moby/v2/daemon/server/backend" |
| 10 | 10 |
"github.com/moby/moby/v2/daemon/server/imagebackend" |
| 11 |
+ "github.com/moby/moby/v2/internal/sliceutil" |
|
| 11 | 12 |
"github.com/pkg/errors" |
| 12 | 13 |
"golang.org/x/sync/errgroup" |
| 13 | 14 |
) |
| ... | ... |
@@ -51,7 +52,7 @@ func (daemon *Daemon) containerDiskUsage(ctx context.Context, verbose bool) (*ba |
| 51 | 51 |
du.ActiveCount = activeCount |
| 52 | 52 |
|
| 53 | 53 |
if verbose {
|
| 54 |
- du.Items = containers |
|
| 54 |
+ du.Items = sliceutil.Deref(containers) |
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
return du, nil |
| ... | ... |
@@ -96,7 +97,7 @@ func (daemon *Daemon) imageDiskUsage(ctx context.Context, verbose bool) (*backen |
| 96 | 96 |
du.ActiveCount = activeCount |
| 97 | 97 |
|
| 98 | 98 |
if verbose {
|
| 99 |
- du.Items = images |
|
| 99 |
+ du.Items = sliceutil.Deref(images) |
|
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 | 102 |
return du, nil |
| ... | ... |
@@ -130,7 +131,7 @@ func (daemon *Daemon) localVolumesSize(ctx context.Context, verbose bool) (*back |
| 130 | 130 |
du.ActiveCount = activeCount |
| 131 | 131 |
|
| 132 | 132 |
if verbose {
|
| 133 |
- du.Items = volumes |
|
| 133 |
+ du.Items = sliceutil.Deref(volumes) |
|
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 | 136 |
return du, nil |
| ... | ... |
@@ -150,15 +150,15 @@ func (b *Builder) Cancel(ctx context.Context, id string) error {
|
| 150 | 150 |
} |
| 151 | 151 |
|
| 152 | 152 |
// DiskUsage returns a report about space used by build cache |
| 153 |
-func (b *Builder) DiskUsage(ctx context.Context) ([]*build.CacheRecord, error) {
|
|
| 153 |
+func (b *Builder) DiskUsage(ctx context.Context) ([]build.CacheRecord, error) {
|
|
| 154 | 154 |
duResp, err := b.controller.DiskUsage(ctx, &controlapi.DiskUsageRequest{})
|
| 155 | 155 |
if err != nil {
|
| 156 | 156 |
return nil, err |
| 157 | 157 |
} |
| 158 | 158 |
|
| 159 |
- var items []*build.CacheRecord |
|
| 159 |
+ var items []build.CacheRecord |
|
| 160 | 160 |
for _, r := range duResp.Record {
|
| 161 |
- items = append(items, &build.CacheRecord{
|
|
| 161 |
+ items = append(items, build.CacheRecord{
|
|
| 162 | 162 |
ID: r.ID, |
| 163 | 163 |
Parents: r.Parents, |
| 164 | 164 |
Type: r.RecordType, |
| ... | ... |
@@ -37,7 +37,7 @@ type BuildCacheDiskUsage struct {
|
| 37 | 37 |
TotalCount int64 |
| 38 | 38 |
TotalSize int64 |
| 39 | 39 |
Reclaimable int64 |
| 40 |
- Items []*build.CacheRecord |
|
| 40 |
+ Items []build.CacheRecord |
|
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 | 43 |
// ContainerDiskUsage contains disk usage for containers. |
| ... | ... |
@@ -46,7 +46,7 @@ type ContainerDiskUsage struct {
|
| 46 | 46 |
TotalCount int64 |
| 47 | 47 |
TotalSize int64 |
| 48 | 48 |
Reclaimable int64 |
| 49 |
- Items []*container.Summary |
|
| 49 |
+ Items []container.Summary |
|
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 | 52 |
// ImageDiskUsage contains disk usage for images. |
| ... | ... |
@@ -55,7 +55,7 @@ type ImageDiskUsage struct {
|
| 55 | 55 |
TotalCount int64 |
| 56 | 56 |
TotalSize int64 |
| 57 | 57 |
Reclaimable int64 |
| 58 |
- Items []*image.Summary |
|
| 58 |
+ Items []image.Summary |
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
// VolumeDiskUsage contains disk usage for volumes. |
| ... | ... |
@@ -64,5 +64,5 @@ type VolumeDiskUsage struct {
|
| 64 | 64 |
TotalCount int64 |
| 65 | 65 |
TotalSize int64 |
| 66 | 66 |
Reclaimable int64 |
| 67 |
- Items []*volume.Volume |
|
| 67 |
+ Items []volume.Volume |
|
| 68 | 68 |
} |
| ... | ... |
@@ -32,7 +32,7 @@ type ClusterBackend interface {
|
| 32 | 32 |
|
| 33 | 33 |
// BuildBackend provides build specific system information. |
| 34 | 34 |
type BuildBackend interface {
|
| 35 |
- DiskUsage(context.Context) ([]*build.CacheRecord, error) |
|
| 35 |
+ DiskUsage(context.Context) ([]build.CacheRecord, error) |
|
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 | 38 |
// StatusProvider provides methods to get the swarm status of the current node. |
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"net/http" |
| 8 |
- "slices" |
|
| 9 | 8 |
"strconv" |
| 10 | 9 |
"time" |
| 11 | 10 |
|
| ... | ... |
@@ -197,7 +196,7 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, |
| 197 | 197 |
}) |
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 |
- var buildCache []*buildtypes.CacheRecord |
|
| 200 |
+ var buildCache []buildtypes.CacheRecord |
|
| 201 | 201 |
if getBuildCache {
|
| 202 | 202 |
eg.Go(func() error {
|
| 203 | 203 |
var err error |
| ... | ... |
@@ -205,11 +204,6 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, |
| 205 | 205 |
if err != nil {
|
| 206 | 206 |
return errors.Wrap(err, "error getting build cache usage") |
| 207 | 207 |
} |
| 208 |
- if buildCache == nil {
|
|
| 209 |
- // Ensure empty `BuildCache` field is represented as empty JSON array(`[]`) |
|
| 210 |
- // instead of `null` to be consistent with `Images`, `Containers` etc. |
|
| 211 |
- buildCache = []*buildtypes.CacheRecord{}
|
|
| 212 |
- } |
|
| 213 | 208 |
return nil |
| 214 | 209 |
}) |
| 215 | 210 |
} |
| ... | ... |
@@ -228,16 +222,10 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, |
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 | 230 |
if legacyFields {
|
| 231 |
- v.LayersSize = systemDiskUsage.Images.TotalSize //nolint: staticcheck,SA1019: v.LayersSize is deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.TotalSize] instead. |
|
| 232 |
- v.Images = systemDiskUsage.Images.Items //nolint: staticcheck,SA1019: v.Images is deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.Items] instead. |
|
| 231 |
+ v.LayersSize = systemDiskUsage.Images.TotalSize //nolint: staticcheck,SA1019: v.LayersSize is deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.TotalSize] instead. |
|
| 232 |
+ v.Images = nonNilSlice(systemDiskUsage.Images.Items) //nolint: staticcheck,SA1019: v.Images is deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.Items] instead. |
|
| 233 | 233 |
} else if verbose {
|
| 234 |
- v.ImageUsage.Items = slices.Collect(func(yield func(image.Summary) bool) {
|
|
| 235 |
- for _, i := range systemDiskUsage.Images.Items {
|
|
| 236 |
- if !yield(*i) {
|
|
| 237 |
- return |
|
| 238 |
- } |
|
| 239 |
- } |
|
| 240 |
- }) |
|
| 234 |
+ v.ImageUsage.Items = systemDiskUsage.Images.Items |
|
| 241 | 235 |
} |
| 242 | 236 |
} |
| 243 | 237 |
if systemDiskUsage != nil && systemDiskUsage.Containers != nil {
|
| ... | ... |
@@ -249,15 +237,9 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, |
| 249 | 249 |
} |
| 250 | 250 |
|
| 251 | 251 |
if legacyFields {
|
| 252 |
- v.Containers = systemDiskUsage.Containers.Items //nolint: staticcheck,SA1019: v.Containers is deprecated: kept to maintain backwards compatibility with API < v1.52, use [ContainersDiskUsage.Items] instead. |
|
| 252 |
+ v.Containers = nonNilSlice(systemDiskUsage.Containers.Items) //nolint: staticcheck,SA1019: v.Containers is deprecated: kept to maintain backwards compatibility with API < v1.52, use [ContainersDiskUsage.Items] instead. |
|
| 253 | 253 |
} else if verbose {
|
| 254 |
- v.ContainerUsage.Items = slices.Collect(func(yield func(container.Summary) bool) {
|
|
| 255 |
- for _, c := range systemDiskUsage.Containers.Items {
|
|
| 256 |
- if !yield(*c) {
|
|
| 257 |
- return |
|
| 258 |
- } |
|
| 259 |
- } |
|
| 260 |
- }) |
|
| 254 |
+ v.ContainerUsage.Items = systemDiskUsage.Containers.Items |
|
| 261 | 255 |
} |
| 262 | 256 |
} |
| 263 | 257 |
if systemDiskUsage != nil && systemDiskUsage.Volumes != nil {
|
| ... | ... |
@@ -269,15 +251,9 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, |
| 269 | 269 |
} |
| 270 | 270 |
|
| 271 | 271 |
if legacyFields {
|
| 272 |
- v.Volumes = systemDiskUsage.Volumes.Items //nolint: staticcheck,SA1019: v.Volumes is deprecated: kept to maintain backwards compatibility with API < v1.52, use [VolumesDiskUsage.Items] instead. |
|
| 272 |
+ v.Volumes = nonNilSlice(systemDiskUsage.Volumes.Items) //nolint: staticcheck,SA1019: v.Volumes is deprecated: kept to maintain backwards compatibility with API < v1.52, use [VolumesDiskUsage.Items] instead. |
|
| 273 | 273 |
} else if verbose {
|
| 274 |
- v.VolumeUsage.Items = slices.Collect(func(yield func(volume.Volume) bool) {
|
|
| 275 |
- for _, v := range systemDiskUsage.Volumes.Items {
|
|
| 276 |
- if !yield(*v) {
|
|
| 277 |
- return |
|
| 278 |
- } |
|
| 279 |
- } |
|
| 280 |
- }) |
|
| 274 |
+ v.VolumeUsage.Items = systemDiskUsage.Volumes.Items |
|
| 281 | 275 |
} |
| 282 | 276 |
} |
| 283 | 277 |
if getBuildCache {
|
| ... | ... |
@@ -306,20 +282,23 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, |
| 306 | 306 |
v.BuildCacheUsage.Reclaimable = reclaimable |
| 307 | 307 |
|
| 308 | 308 |
if legacyFields {
|
| 309 |
- v.BuildCache = buildCache //nolint: staticcheck,SA1019: v.BuildCache is deprecated: kept to maintain backwards compatibility with API < v1.52, use [BuildCacheDiskUsage.Items] instead. |
|
| 309 |
+ v.BuildCache = nonNilSlice(buildCache) //nolint: staticcheck,SA1019: v.BuildCache is deprecated: kept to maintain backwards compatibility with API < v1.52, use [BuildCacheDiskUsage.Items] instead. |
|
| 310 | 310 |
} else if verbose {
|
| 311 |
- v.BuildCacheUsage.Items = slices.Collect(func(yield func(buildtypes.CacheRecord) bool) {
|
|
| 312 |
- for _, b := range buildCache {
|
|
| 313 |
- if !yield(*b) {
|
|
| 314 |
- return |
|
| 315 |
- } |
|
| 316 |
- } |
|
| 317 |
- }) |
|
| 311 |
+ v.BuildCacheUsage.Items = buildCache |
|
| 318 | 312 |
} |
| 319 | 313 |
} |
| 320 | 314 |
return httputils.WriteJSON(w, http.StatusOK, v) |
| 321 | 315 |
} |
| 322 | 316 |
|
| 317 |
+// nonNilSlice is used for the legacy fields, which are either omitted |
|
| 318 |
+// entirely, or (if set), must return an empty slice in the response. |
|
| 319 |
+func nonNilSlice[T any](s []T) []T {
|
|
| 320 |
+ if s == nil {
|
|
| 321 |
+ return []T{}
|
|
| 322 |
+ } |
|
| 323 |
+ return s |
|
| 324 |
+} |
|
| 325 |
+ |
|
| 323 | 326 |
type invalidRequestError struct {
|
| 324 | 327 |
Err error |
| 325 | 328 |
} |
| ... | ... |
@@ -37,14 +37,14 @@ type LegacyDiskUsage struct {
|
| 37 | 37 |
LayersSize int64 `json:"LayersSize,omitempty"` |
| 38 | 38 |
|
| 39 | 39 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ImagesDiskUsage.Items] instead. |
| 40 |
- Images []*image.Summary `json:"Images,omitempty"` |
|
| 40 |
+ Images []image.Summary `json:"Images,omitzero"` |
|
| 41 | 41 |
|
| 42 | 42 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [ContainersDiskUsage.Items] instead. |
| 43 |
- Containers []*container.Summary `json:"Containers,omitempty"` |
|
| 43 |
+ Containers []container.Summary `json:"Containers,omitzero"` |
|
| 44 | 44 |
|
| 45 | 45 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [VolumesDiskUsage.Items] instead. |
| 46 |
- Volumes []*volume.Volume `json:"Volumes,omitempty"` |
|
| 46 |
+ Volumes []volume.Volume `json:"Volumes,omitzero"` |
|
| 47 | 47 |
|
| 48 | 48 |
// Deprecated: kept to maintain backwards compatibility with API < v1.52, use [BuildCacheDiskUsage.Items] instead. |
| 49 |
- BuildCache []*build.CacheRecord `json:"BuildCache,omitempty"` |
|
| 49 |
+ BuildCache []build.CacheRecord `json:"BuildCache,omitzero"` |
|
| 50 | 50 |
} |
| ... | ... |
@@ -171,13 +171,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 | 173 |
if options.Verbose {
|
| 174 |
- r.Images.Items = slices.Collect(func(yield func(image.Summary) bool) {
|
|
| 175 |
- for _, i := range du.Images {
|
|
| 176 |
- if !yield(*i) {
|
|
| 177 |
- return |
|
| 178 |
- } |
|
| 179 |
- } |
|
| 180 |
- }) |
|
| 174 |
+ r.Images.Items = du.Images |
|
| 181 | 175 |
} |
| 182 | 176 |
} |
| 183 | 177 |
|
| ... | ... |
@@ -194,13 +188,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 194 | 194 |
} |
| 195 | 195 |
} else if du.Containers != nil && options.Verbose {
|
| 196 | 196 |
// Fallback for legacy response. |
| 197 |
- r.Containers.Items = slices.Collect(func(yield func(container.Summary) bool) {
|
|
| 198 |
- for _, c := range du.Containers {
|
|
| 199 |
- if !yield(*c) {
|
|
| 200 |
- return |
|
| 201 |
- } |
|
| 202 |
- } |
|
| 203 |
- }) |
|
| 197 |
+ r.Containers.Items = du.Containers |
|
| 204 | 198 |
} |
| 205 | 199 |
|
| 206 | 200 |
if du.BuildCacheUsage != nil {
|
| ... | ... |
@@ -216,13 +204,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 216 | 216 |
} |
| 217 | 217 |
} else if du.BuildCache != nil && options.Verbose {
|
| 218 | 218 |
// Fallback for legacy response. |
| 219 |
- r.BuildCache.Items = slices.Collect(func(yield func(build.CacheRecord) bool) {
|
|
| 220 |
- for _, b := range du.BuildCache {
|
|
| 221 |
- if !yield(*b) {
|
|
| 222 |
- return |
|
| 223 |
- } |
|
| 224 |
- } |
|
| 225 |
- }) |
|
| 219 |
+ r.BuildCache.Items = du.BuildCache |
|
| 226 | 220 |
} |
| 227 | 221 |
|
| 228 | 222 |
if du.VolumeUsage != nil {
|
| ... | ... |
@@ -238,13 +220,7 @@ func (cli *Client) DiskUsage(ctx context.Context, options DiskUsageOptions) (Dis |
| 238 | 238 |
} |
| 239 | 239 |
} else if du.Volumes != nil && options.Verbose {
|
| 240 | 240 |
// Fallback for legacy response. |
| 241 |
- r.Volumes.Items = slices.Collect(func(yield func(volume.Volume) bool) {
|
|
| 242 |
- for _, v := range du.Volumes {
|
|
| 243 |
- if !yield(*v) {
|
|
| 244 |
- return |
|
| 245 |
- } |
|
| 246 |
- } |
|
| 247 |
- }) |
|
| 241 |
+ r.Volumes.Items = du.Volumes |
|
| 248 | 242 |
} |
| 249 | 243 |
|
| 250 | 244 |
return r, nil |