Skip to content

Commit 5437f01

Browse files
committed
add delete
1 parent 55eba43 commit 5437f01

11 files changed

Lines changed: 192 additions & 58 deletions

File tree

config/cni.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"github.com/projecteru2/cocoon/utils"
77
)
88

9-
const netnsPath = "/var/run/netns"
9+
const NetnsPath = "/var/run/netns"
1010

1111
// EnsureCNIDirs creates all static directories required by the CNI network provider.
1212
func (c *Config) EnsureCNIDirs() error {
@@ -22,18 +22,10 @@ func (c *Config) cniDBDir() string { return filepath.Join(c.cniDir(), "db") }
2222
func (c *Config) CNIIndexFile() string { return filepath.Join(c.cniDBDir(), "networks.json") }
2323
func (c *Config) CNIIndexLock() string { return filepath.Join(c.cniDBDir(), "networks.lock") }
2424

25-
// CNIConfDir returns the directory for CNI plugin configuration files.
26-
// Default: /etc/cni/net.d (standard CNI convention).
27-
func (c *Config) CNIConfDir() string { return "/etc/cni/net.d" }
28-
29-
// CNIBinDir returns the directory for CNI plugin binaries.
30-
// Default: /opt/cni/bin (standard CNI convention).
31-
func (c *Config) CNIBinDir() string { return "/opt/cni/bin" }
32-
3325
// CNICacheDir returns the directory for CNI result cache.
3426
func (c *Config) CNICacheDir() string { return filepath.Join(c.cniDir(), "cache") }
3527

3628
// CNINetnsPath returns the named netns path for a VM.
3729
func (c *Config) CNINetnsPath(vmID string) string {
38-
return filepath.Join(netnsPath, vmID)
30+
return filepath.Join(NetnsPath, vmID)
3931
}

config/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ type Config struct {
2828
// PoolSize is the goroutine pool size for concurrent operations.
2929
// Defaults to runtime.NumCPU() if zero.
3030
PoolSize int `json:"pool_size" mapstructure:"pool_size"`
31+
// CNIConfDir is the directory for CNI plugin configuration files.
32+
// Default: /etc/cni/net.d.
33+
CNIConfDir string `json:"cni_conf_dir" mapstructure:"cni_conf_dir"`
34+
// CNIBinDir is the directory for CNI plugin binaries.
35+
// Default: /opt/cni/bin.
36+
CNIBinDir string `json:"cni_bin_dir" mapstructure:"cni_bin_dir"`
3137
// DefaultRootPassword is the root password injected into cloudimg VMs
3238
// via cloud-init metadata. Empty means no password is set.
3339
DefaultRootPassword string `json:"default_root_password" mapstructure:"default_root_password"`
@@ -42,6 +48,8 @@ func DefaultConfig() *Config {
4248
RunDir: "/var/run/cocoon",
4349
LogDir: "/var/log/cocoon",
4450
CHBinary: "cloud-hypervisor",
51+
CNIConfDir: "/etc/cni/net.d",
52+
CNIBinDir: "/opt/cni/bin",
4553
StopTimeoutSeconds: 30,
4654
PoolSize: runtime.NumCPU(),
4755
Log: &coretypes.ServerLogConfig{
@@ -67,5 +75,11 @@ func EnsureDirs(conf *Config) (*Config, error) {
6775
if conf.CHBinary == "" {
6876
conf.CHBinary = defaults.CHBinary
6977
}
78+
if conf.CNIConfDir == "" {
79+
conf.CNIConfDir = defaults.CNIConfDir
80+
}
81+
if conf.CNIBinDir == "" {
82+
conf.CNIBinDir = defaults.CNIBinDir
83+
}
7084
return conf, nil
7185
}

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/projecteru2/cocoon
33
go 1.25.6
44

55
require (
6+
github.com/containernetworking/cni v1.3.0
67
github.com/docker/go-units v0.5.0
78
github.com/gofrs/flock v0.13.0
89
github.com/google/go-containerregistry v0.21.0
@@ -51,7 +52,7 @@ require (
5152
github.com/subosito/gotenv v1.6.0 // indirect
5253
github.com/vbatts/tar-split v0.12.2 // indirect
5354
go.yaml.in/yaml/v3 v3.0.4 // indirect
54-
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect
55+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
5556
golang.org/x/sys v0.41.0 // indirect
5657
golang.org/x/text v0.28.0 // indirect
5758
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect

go.sum

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP
88
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
99
github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw=
1010
github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY=
11+
github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
12+
github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
1113
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
1214
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
1315
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -30,6 +32,10 @@ github.com/getsentry/sentry-go v0.42.0 h1:eeFMACuZTbUQf90RE8dE4tXeSe4CZyfvR1MBL7
3032
github.com/getsentry/sentry-go v0.42.0/go.mod h1:eRXCoh3uvmjQLY6qu63BjUZnaBu5L5WhMV1RwYO8W5s=
3133
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
3234
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
35+
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
36+
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
37+
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
38+
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
3339
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
3440
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
3541
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -41,6 +47,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
4147
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
4248
github.com/google/go-containerregistry v0.21.0 h1:ocqxUOczFwAZQBMNE7kuzfqvDe0VWoZxQMOesXreCDI=
4349
github.com/google/go-containerregistry v0.21.0/go.mod h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0=
50+
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
51+
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
4452
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
4553
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
4654
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -62,6 +70,10 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
6270
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
6371
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
6472
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
73+
github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo=
74+
github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
75+
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
76+
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
6577
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
6678
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
6779
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
@@ -111,6 +123,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
111123
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
112124
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
113125
github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
126+
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
127+
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
114128
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
115129
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
116130
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -122,8 +136,8 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
122136
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
123137
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
124138
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
125-
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o=
126-
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
139+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
140+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
127141
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
128142
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
129143
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -156,6 +170,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
156170
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
157171
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
158172
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
173+
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
174+
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
159175
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
160176
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
161177
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

hypervisor/cloudhypervisor/create.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,11 @@ func (ch *CloudHypervisor) prepareOCI(ctx context.Context, vmID string, vmCfg *t
138138
// Format: ip=<client-IP>:<server>:<gw-IP>:<netmask>:<hostname>:<device>:<autoconf>
139139
if len(networkConfigs) > 0 {
140140
cmdline.WriteString(" net.ifnames=0")
141-
for _, n := range networkConfigs {
141+
for i, n := range networkConfigs {
142142
if n.Network != nil {
143-
fmt.Fprintf(&cmdline, " ip=%s::%s:%s::%s:off",
143+
fmt.Fprintf(&cmdline, " ip=%s::%s:%s::eth%d:off",
144144
n.Network.IP, n.Network.Gateway,
145-
net.IP(n.Network.Netmask), n.Network.Device)
145+
net.IP(n.Network.Netmask), i)
146146
}
147147
}
148148
}
@@ -184,14 +184,14 @@ func (ch *CloudHypervisor) prepareCloudimg(ctx context.Context, vmID string, vmC
184184
Hostname: vmCfg.Name,
185185
RootPassword: ch.conf.DefaultRootPassword,
186186
}
187-
for _, n := range networkConfigs {
187+
for i, n := range networkConfigs {
188188
if n.Network != nil {
189189
ones, _ := n.Network.Netmask.Size()
190190
metaCfg.Networks = append(metaCfg.Networks, metadata.NetworkInfo{
191191
IP: n.Network.IP.String(),
192192
Prefix: ones,
193193
Gateway: n.Network.Gateway.String(),
194-
Device: n.Network.Device,
194+
Device: fmt.Sprintf("eth%d", i),
195195
Mac: n.Mac,
196196
})
197197
}

hypervisor/cloudhypervisor/gc.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package cloudhypervisor
33
import (
44
"context"
55
"errors"
6+
"fmt"
7+
"os"
68
"time"
79

10+
"github.com/projecteru2/cocoon/config"
811
"github.com/projecteru2/cocoon/gc"
912
"github.com/projecteru2/cocoon/hypervisor"
1013
"github.com/projecteru2/cocoon/types"
@@ -19,6 +22,7 @@ type chSnapshot struct {
1922
staleCreate []string // IDs in stale "creating" state (crash remnants)
2023
runDirs []string // subdirectory names under CHRunDir
2124
logDirs []string // subdirectory names under CHLogDir
25+
netnsNames []string // entries under /var/run/netns/
2226
}
2327

2428
func (s chSnapshot) UsedBlobIDs() map[string]struct{} { return s.blobIDs }
@@ -57,6 +61,13 @@ func (ch *CloudHypervisor) GCModule() gc.Module[chSnapshot] {
5761
if snap.logDirs, err = utils.ScanSubdirs(ch.conf.CHLogDir()); err != nil {
5862
return snap, err
5963
}
64+
// Scan named netns: entries in /var/run/netns/ that match VM IDs.
65+
// These are bind-mount files (not dirs), so use ScanEntries.
66+
if entries, readErr := os.ReadDir(config.NetnsPath); readErr == nil {
67+
for _, e := range entries {
68+
snap.netnsNames = append(snap.netnsNames, e.Name())
69+
}
70+
}
6071
return snap, nil
6172
},
6273
Resolve: func(snap chSnapshot, _ map[string]any) []string {
@@ -66,7 +77,8 @@ func (ch *CloudHypervisor) GCModule() gc.Module[chSnapshot] {
6677
reserved := map[string]struct{}{"db": {}}
6778
runOrphans := utils.FilterUnreferenced(snap.runDirs, snap.vmIDs, reserved)
6879
logOrphans := utils.FilterUnreferenced(snap.logDirs, snap.vmIDs, reserved)
69-
candidates := append(append(runOrphans, logOrphans...), snap.staleCreate...)
80+
netnsOrphans := utils.FilterUnreferenced(snap.netnsNames, snap.vmIDs)
81+
candidates := append(append(append(runOrphans, logOrphans...), netnsOrphans...), snap.staleCreate...)
7082
seen := make(map[string]struct{}, len(candidates))
7183
var result []string
7284
for _, id := range candidates {
@@ -80,8 +92,14 @@ func (ch *CloudHypervisor) GCModule() gc.Module[chSnapshot] {
8092
},
8193
Collect: func(ctx context.Context, ids []string) error {
8294
var errs []error
83-
// Remove orphan directories (best-effort for dirs that may not exist).
8495
for _, id := range ids {
96+
// Remove orphan netns (bind-mount file). Kernel cleans up
97+
// bridge/tap/veth devices automatically when netns is destroyed.
98+
nsPath := ch.conf.CNINetnsPath(id)
99+
if err := os.Remove(nsPath); err != nil && !os.IsNotExist(err) {
100+
errs = append(errs, fmt.Errorf("remove netns %s: %w", id, err))
101+
}
102+
// Remove orphan run/log directories.
85103
if err := ch.removeVMDirs(ctx, id); err != nil {
86104
errs = append(errs, err)
87105
}

images/index.go

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
const minHexLen = 12
1717

18-
// Entry defines the common behavior of an image index entry.
18+
// Entry defines the common behavior of an image index (*entry).
1919
// Both OCI and cloudimg imageEntry types implement this with value receivers.
2020
type Entry interface {
2121
EntryID() string
@@ -37,15 +37,14 @@ func (idx *Index[E]) Init() {
3737
}
3838
}
3939

40-
// ReferencedDigests collects all blob digest hex strings referenced by any entry.
40+
// ReferencedDigests collects all blob digest hex strings referenced by any (*entry).
4141
func ReferencedDigests[E Entry](images map[string]*E) map[string]struct{} {
4242
refs := make(map[string]struct{})
4343
for _, ep := range images {
4444
if ep == nil {
4545
continue
4646
}
47-
e := *ep
48-
for _, hex := range e.DigestHexes() {
47+
for _, hex := range (*ep).DigestHexes() {
4948
refs[hex] = struct{}{}
5049
}
5150
}
@@ -79,8 +78,7 @@ func LookupRefs[E Entry](images map[string]*E, id string, normalizers ...func(st
7978
if ep == nil {
8079
continue
8180
}
82-
e := *ep
83-
dStr := e.EntryID()
81+
dStr := (*ep).EntryID()
8482
dHex := strings.TrimPrefix(dStr, "sha256:")
8583
if dStr == id || dHex == id {
8684
refs = append(refs, ref)
@@ -119,13 +117,12 @@ func entryToImage[E Entry](entry *E, typ string, sizer func(*E) int64) *types.Im
119117
if entry == nil {
120118
return nil
121119
}
122-
e := *entry
123120
return &types.Image{
124-
ID: e.EntryID(),
125-
Name: e.EntryRef(),
121+
ID: (*entry).EntryID(),
122+
Name: (*entry).EntryRef(),
126123
Type: typ,
127124
Size: sizer(entry),
128-
CreatedAt: e.EntryCreatedAt(),
125+
CreatedAt: (*entry).EntryCreatedAt(),
129126
}
130127
}
131128

@@ -136,13 +133,12 @@ func listImages[E Entry](images map[string]*E, typ string, sizer func(*E) int64)
136133
if ep == nil {
137134
continue
138135
}
139-
e := *ep
140136
result = append(result, &types.Image{
141-
ID: e.EntryID(),
142-
Name: e.EntryRef(),
137+
ID: (*ep).EntryID(),
138+
Name: (*ep).EntryRef(),
143139
Type: typ,
144140
Size: sizer(ep),
145-
CreatedAt: e.EntryCreatedAt(),
141+
CreatedAt: (*ep).EntryCreatedAt(),
146142
})
147143
}
148144
return result

0 commit comments

Comments
 (0)