system df: fix image-size calculations

Fix two bugs in `system df`:

1.  The total size was calculated incorrectly as it was creating the sum
    of all image sizes but did not consider that a) the same image may
    be listed more than once (i.e., for each repo-tag pair), and that
    b) images share layers.

    The total size is now calculated directly in `libimage` by taking
    multi-layer use into account.

2.  The reclaimable size was calculated incorrectly.  This number
    indicates which data we can actually remove which means the total
    size minus what containers use (i.e., the "unique" size of the image
    in use by containers).

NOTE: The c/storage version is pinned back to the previous commit as it
      is buggy.  c/common already requires the buggy version, so use a
      `replace` to force/pin.

Fixes: #16135
Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2022-10-17 16:53:48 +02:00
parent 2fb7218e63
commit 34235b2726
50 changed files with 284 additions and 210 deletions

View File

@ -65,24 +65,27 @@ func printSummary(cmd *cobra.Command, reports *entities.SystemDfReport) error {
var ( var (
dfSummaries []*dfSummary dfSummaries []*dfSummary
active int active int
size, reclaimable int64 used int64
) )
visitedImages := make(map[string]bool)
for _, i := range reports.Images { for _, i := range reports.Images {
if _, ok := visitedImages[i.ImageID]; ok {
continue
}
visitedImages[i.ImageID] = true
if i.Containers > 0 { if i.Containers > 0 {
active++ active++
} used += i.UniqueSize
size += i.Size
if i.Containers < 1 {
reclaimable += i.Size
} }
} }
imageSummary := dfSummary{ imageSummary := dfSummary{
Type: "Images", Type: "Images",
Total: len(reports.Images), Total: len(reports.Images),
Active: active, Active: active,
RawSize: size, RawSize: reports.ImagesSize, // The "raw" size is the sum of all layer sizes
RawReclaimable: reclaimable, RawReclaimable: reports.ImagesSize - used, // We can reclaim the date of "unused" images (i.e., the ones without containers)
} }
dfSummaries = append(dfSummaries, &imageSummary) dfSummaries = append(dfSummaries, &imageSummary)

8
go.mod
View File

@ -12,12 +12,12 @@ require (
github.com/containernetworking/cni v1.1.2 github.com/containernetworking/cni v1.1.2
github.com/containernetworking/plugins v1.1.1 github.com/containernetworking/plugins v1.1.1
github.com/containers/buildah v1.28.0 github.com/containers/buildah v1.28.0
github.com/containers/common v0.50.2-0.20221014181637-a6a9c521b6a5 github.com/containers/common v0.50.2-0.20221018104440-95c452ec992c
github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67 github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67
github.com/containers/ocicrypt v1.1.6 github.com/containers/ocicrypt v1.1.6
github.com/containers/psgo v1.8.0 github.com/containers/psgo v1.8.0
github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3 github.com/containers/storage v1.43.1-0.20221018232308-33c396d1aacf
github.com/coreos/go-systemd/v22 v22.4.0 github.com/coreos/go-systemd/v22 v22.4.0
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3 github.com/cyphar/filepath-securejoin v0.2.3
@ -79,7 +79,7 @@ require (
github.com/chzyer/readline v1.5.1 // indirect github.com/chzyer/readline v1.5.1 // indirect
github.com/containerd/cgroups v1.0.4 // indirect github.com/containerd/cgroups v1.0.4 // indirect
github.com/containerd/containerd v1.6.8 // indirect github.com/containerd/containerd v1.6.8 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.12.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.12.1 // indirect
github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a // indirect github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
@ -147,3 +147,5 @@ require (
) )
replace github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20220617142545-8b9452f75cbc replace github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20220617142545-8b9452f75cbc
replace github.com/containers/storage => github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3

16
go.sum
View File

@ -129,7 +129,6 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
@ -142,7 +141,6 @@ github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
@ -377,9 +375,9 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
github.com/containerd/stargz-snapshotter/estargz v0.12.0 h1:idtwRTLjk2erqiYhPWy2L844By8NRFYEwYHcXhoIWPM=
github.com/containerd/stargz-snapshotter/estargz v0.12.0/go.mod h1:AIQ59TewBFJ4GOPEQXujcrJ/EKxh5xXZegW1rkR1P/M= github.com/containerd/stargz-snapshotter/estargz v0.12.0/go.mod h1:AIQ59TewBFJ4GOPEQXujcrJ/EKxh5xXZegW1rkR1P/M=
github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0=
github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@ -410,12 +408,11 @@ github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19
github.com/containers/buildah v1.28.0 h1:63Kpf9nAEJGsDEOArb5Q0dn5S3B9wFQc9kST4nU7+Pw= github.com/containers/buildah v1.28.0 h1:63Kpf9nAEJGsDEOArb5Q0dn5S3B9wFQc9kST4nU7+Pw=
github.com/containers/buildah v1.28.0/go.mod h1:pTYSfpf+Ha/KbnMmwhhhEjkSF3NuhpxZfiDNDORLgqY= github.com/containers/buildah v1.28.0/go.mod h1:pTYSfpf+Ha/KbnMmwhhhEjkSF3NuhpxZfiDNDORLgqY=
github.com/containers/common v0.50.1/go.mod h1:XnWlXPyE9Ky+8v8MfYWJZFnejkprAkUeo0DTWmSiwcY= github.com/containers/common v0.50.1/go.mod h1:XnWlXPyE9Ky+8v8MfYWJZFnejkprAkUeo0DTWmSiwcY=
github.com/containers/common v0.50.2-0.20221014181637-a6a9c521b6a5 h1:Sp6lus6zXyg+Fv3ecoPOXm+80xC23YrKtntqYQU1pCA= github.com/containers/common v0.50.2-0.20221018104440-95c452ec992c h1:ZFMv4o5Mx8iq2O0AuE9sH4uiKqYggkdJPsz3KY65aGg=
github.com/containers/common v0.50.2-0.20221014181637-a6a9c521b6a5/go.mod h1:7AM52N4n4UHzAeArB1vmIw7NhDNpDxrFaycubysYgFo= github.com/containers/common v0.50.2-0.20221018104440-95c452ec992c/go.mod h1:71Q12SyFJO8rWgdMjvR6MC73KGpIpQU6PPkBRgoSots=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.23.0/go.mod h1:EXFFGEsL99S6aqLqK2mQJ3yrNh6Q05UCHt4mhF9JNoM= github.com/containers/image/v5 v5.23.0/go.mod h1:EXFFGEsL99S6aqLqK2mQJ3yrNh6Q05UCHt4mhF9JNoM=
github.com/containers/image/v5 v5.23.1-0.20221013202101-87afcefe9766/go.mod h1:2JJxA5K1NFpA3FtrK+Csmdlj++5oveB7CsXhekEJsIU=
github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67 h1:kCKq/UASl4o6mwlqbBP8r+6fMIdQg3RkC2znw6H65A4= github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67 h1:kCKq/UASl4o6mwlqbBP8r+6fMIdQg3RkC2znw6H65A4=
github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67/go.mod h1:V+wF8uIye+czYC4HWHGh4IK9dZBTsQUG1ZYie9gXxCQ= github.com/containers/image/v5 v5.23.1-0.20221015133641-1921a1993c67/go.mod h1:V+wF8uIye+czYC4HWHGh4IK9dZBTsQUG1ZYie9gXxCQ=
github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a h1:spAGlqziZjCJL25C6F1zsQY05tfCKE9F5YwtEWWe6hU= github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a h1:spAGlqziZjCJL25C6F1zsQY05tfCKE9F5YwtEWWe6hU=
@ -430,9 +427,6 @@ github.com/containers/ocicrypt v1.1.6 h1:uoG52u2e91RE4UqmBICZY8dNshgfvkdl3BW6jnx
github.com/containers/ocicrypt v1.1.6/go.mod h1:WgjxPWdTJMqYMjf3M6cuIFFA1/MpyyhIM99YInA+Rvc= github.com/containers/ocicrypt v1.1.6/go.mod h1:WgjxPWdTJMqYMjf3M6cuIFFA1/MpyyhIM99YInA+Rvc=
github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY=
github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc=
github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s=
github.com/containers/storage v1.43.1-0.20221014072257-a144fee6f51c/go.mod h1:K2qol6lCT/LRqZ3TMNRBU22tCTC6/Mb4G23K5SHhrYw=
github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3 h1:3jBfOfHFmaubuvhKSgfV7Krr2ZNpOlGiU9OhQYkoTxY= github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3 h1:3jBfOfHFmaubuvhKSgfV7Krr2ZNpOlGiU9OhQYkoTxY=
github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3/go.mod h1:K2qol6lCT/LRqZ3TMNRBU22tCTC6/Mb4G23K5SHhrYw= github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3/go.mod h1:K2qol6lCT/LRqZ3TMNRBU22tCTC6/Mb4G23K5SHhrYw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@ -1411,7 +1405,6 @@ github.com/opencontainers/runtime-tools v0.9.1-0.20221014010322-58c91d646d86/go.
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
@ -2154,7 +2147,6 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -47,6 +47,7 @@ type SystemDfOptions struct {
// SystemDfReport describes the response for df information // SystemDfReport describes the response for df information
type SystemDfReport struct { type SystemDfReport struct {
ImagesSize int64
Images []*SystemDfImageReport Images []*SystemDfImageReport
Containers []*SystemDfContainerReport Containers []*SystemDfContainerReport
Volumes []*SystemDfVolumeReport Volumes []*SystemDfVolumeReport

View File

@ -253,7 +253,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
dfImages = []*entities.SystemDfImageReport{} dfImages = []*entities.SystemDfImageReport{}
) )
imageStats, err := ic.Libpod.LibimageRuntime().DiskUsage(ctx) imageStats, totalImageSize, err := ic.Libpod.LibimageRuntime().DiskUsage(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -352,7 +352,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
} }
dfVolumes = append(dfVolumes, &report) dfVolumes = append(dfVolumes, &report)
} }
return &entities.SystemDfReport{ return &entities.SystemDfReport{
ImagesSize: totalImageSize,
Images: dfImages, Images: dfImages,
Containers: dfContainers, Containers: dfContainers,
Volumes: dfVolumes, Volumes: dfVolumes,

View File

@ -8,7 +8,7 @@ t POST 'libpod/system/prune?volumes=true&all=true' params='' 200
## podman system df ## podman system df
t GET system/df 200 '{"LayersSize":0,"Images":[],"Containers":[],"Volumes":[],"BuildCache":[],"BuilderSize":0}' t GET system/df 200 '{"LayersSize":0,"Images":[],"Containers":[],"Volumes":[],"BuildCache":[],"BuilderSize":0}'
t GET libpod/system/df 200 '{"Images":[],"Containers":[],"Volumes":[]}' t GET libpod/system/df 200 '{"ImagesSize":0,"Images":[],"Containers":[],"Volumes":[]}'
# Create volume. We expect df to report this volume next invocation of system/df # Create volume. We expect df to report this volume next invocation of system/df
t GET libpod/info 200 t GET libpod/info 200

View File

@ -52,10 +52,39 @@ function teardown() {
is "${lines[10]}" "[0-9a-f]\{64\} *[01] * 0B" \ is "${lines[10]}" "[0-9a-f]\{64\} *[01] * 0B" \
"system df -v, 'Volumes', second line" "system df -v, 'Volumes', second line"
# Clean up # Make sure that the return image "raw" size is correct
run_podman image inspect $IMAGE --format "{{.Size}}"
expectedSize="$output"
run_podman system df --format "{{.RawSize}}"
is "${lines[0]}" "$expectedSize" "raw image size is correct"
# Clean up and check reclaimable image data
run_podman system df --format '{{.Reclaimable}}'
is "${lines[0]}" "0B (0%)" "cannot reclaim image data as it's still used by the containers"
run_podman exec c2 touch /stop run_podman exec c2 touch /stop
run_podman wait c2 run_podman wait c2
# Create a second image by committing a container.
run_podman container commit -q c1
image="$output"
run_podman system df --format '{{.Reclaimable}}'
is "${lines[0]}" ".* (100%)" "100 percent of image data is reclaimable because $IMAGE has unique size of 0"
# Make sure the unique size is now really 0. We cannot use --format for
# that unfortunately but we can exploit the fact that $IMAGE is used by
# two containers.
run_podman system df -v
is "$output" ".*0B\\s\\+2.*"
run_podman rm c1 c2 run_podman rm c1 c2
run_podman system df --format '{{.Reclaimable}}'
is "${lines[0]}" ".* (100%)" "100 percent of image data is reclaimable because all containers are gone"
run_podman rmi $image
run_podman volume rm -a run_podman volume rm -a
} }

View File

@ -28,26 +28,51 @@ type ImageDiskUsage struct {
// DiskUsage calculates the disk usage for each image in the local containers // DiskUsage calculates the disk usage for each image in the local containers
// storage. Note that a single image may yield multiple usage reports, one for // storage. Note that a single image may yield multiple usage reports, one for
// each repository tag. // each repository tag.
func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, error) { func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, int64, error) {
layerTree, err := r.layerTree() layerTree, err := r.layerTree()
if err != nil { if err != nil {
return nil, err return nil, -1, err
} }
images, err := r.ListImages(ctx, nil, nil) images, err := r.ListImages(ctx, nil, nil)
if err != nil { if err != nil {
return nil, err return nil, -1, err
} }
var totalSize int64
visitedImages := make(map[string]bool)
visistedLayers := make(map[string]bool)
var allUsages []ImageDiskUsage var allUsages []ImageDiskUsage
for _, image := range images { for _, image := range images {
usages, err := diskUsageForImage(ctx, image, layerTree) usages, err := diskUsageForImage(ctx, image, layerTree)
if err != nil { if err != nil {
return nil, err return nil, -1, err
} }
allUsages = append(allUsages, usages...) allUsages = append(allUsages, usages...)
if _, ok := visitedImages[image.ID()]; ok {
// Do not count an image twice
continue
} }
return allUsages, err visitedImages[image.ID()] = true
size, err := image.Size()
if err != nil {
return nil, -1, err
}
for _, layer := range layerTree.layersOf(image) {
if _, ok := visistedLayers[layer.ID]; ok {
// Do not count a layer twice, so remove its
// size from the image size.
size -= layer.UncompressedSize
continue
}
visistedLayers[layer.ID] = true
}
totalSize += size
}
return allUsages, totalSize, err
} }
// diskUsageForImage returns the disk-usage baseistics for the specified image. // diskUsageForImage returns the disk-usage baseistics for the specified image.

View File

@ -73,6 +73,7 @@ func (r *Runtime) filterImages(ctx context.Context, images []*Image, options *Li
// compileImageFilters creates `filterFunc`s for the specified filters. The // compileImageFilters creates `filterFunc`s for the specified filters. The
// required format is `key=value` with the following supported keys: // required format is `key=value` with the following supported keys:
//
// after, since, before, containers, dangling, id, label, readonly, reference, intermediate // after, since, before, containers, dangling, id, label, readonly, reference, intermediate
func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) (map[string][]filterFunc, error) { func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) (map[string][]filterFunc, error) {
logrus.Tracef("Parsing image filters %s", options.Filters) logrus.Tracef("Parsing image filters %s", options.Filters)

View File

@ -775,6 +775,7 @@ func (i *Image) Unmount(force bool) error {
// Size computes the size of the image layers and associated data. // Size computes the size of the image layers and associated data.
func (i *Image) Size() (int64, error) { func (i *Image) Size() (int64, error) {
// TODO: cache the result to optimize performance of subsequent calls
return i.runtime.store.ImageSize(i.ID()) return i.runtime.store.ImageSize(i.ID())
} }

View File

@ -126,6 +126,17 @@ func (r *Runtime) layerTree() (*layerTree, error) {
return &tree, nil return &tree, nil
} }
// layersOf returns all storage layers of the specified image.
func (t *layerTree) layersOf(image *Image) []*storage.Layer {
var layers []*storage.Layer
node := t.node(image.TopLayer())
for node != nil {
layers = append(layers, node.layer)
node = node.parent
}
return layers
}
// children returns the child images of parent. Child images are images with // children returns the child images of parent. Child images are images with
// either the same top layer as parent or parent being the true parent layer. // either the same top layer as parent or parent being the true parent layer.
// Furthermore, the history of the parent and child images must match with the // Furthermore, the history of the parent and child images must match with the

View File

@ -69,9 +69,9 @@ func toPlatformString(os, arch, variant string) string {
// Checks whether the image matches the specified platform. // Checks whether the image matches the specified platform.
// Returns // Returns
// * 1) a matching error that can be used for logging (or returning) what does not match // - 1) a matching error that can be used for logging (or returning) what does not match
// * 2) a bool indicating whether architecture, os or variant were set (some callers need that to decide whether they need to throw an error) // - 2) a bool indicating whether architecture, os or variant were set (some callers need that to decide whether they need to throw an error)
// * 3) a fatal error that occurred prior to check for matches (e.g., storage errors etc.) // - 3) a fatal error that occurred prior to check for matches (e.g., storage errors etc.)
func (i *Image) matchesPlatform(ctx context.Context, os, arch, variant string) (error, bool, error) { func (i *Image) matchesPlatform(ctx context.Context, os, arch, variant string) (error, bool, error) {
if err := i.isCorrupted(""); err != nil { if err := i.isCorrupted(""); err != nil {
return err, false, nil return err, false, nil

View File

@ -7,7 +7,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
@ -329,7 +328,7 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ
cniPathName := "" cniPathName := ""
if writeToDisk { if writeToDisk {
cniPathName = filepath.Join(n.cniConfigDir, network.Name+".conflist") cniPathName = filepath.Join(n.cniConfigDir, network.Name+".conflist")
err = ioutil.WriteFile(cniPathName, b, 0o644) err = os.WriteFile(cniPathName, b, 0o644)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }

View File

@ -7,7 +7,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -174,7 +173,7 @@ func (n *netavarkNetwork) loadNetworks() error {
n.networks = nil n.networks = nil
n.modTime = modTime n.modTime = modTime
files, err := ioutil.ReadDir(n.networkConfigDir) files, err := os.ReadDir(n.networkConfigDir)
if err != nil && !errors.Is(err, os.ErrNotExist) { if err != nil && !errors.Is(err, os.ErrNotExist) {
return err return err
} }

View File

@ -6,7 +6,6 @@ package network
import ( import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@ -42,6 +41,7 @@ const (
// 3. check containers, images and CNI networks and if there are some we have an existing install and should continue to use CNI // 3. check containers, images and CNI networks and if there are some we have an existing install and should continue to use CNI
// //
// revive does not like the name because the package is already called network // revive does not like the name because the package is already called network
//
//nolint:revive //nolint:revive
func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (types.NetworkBackend, types.ContainerNetwork, error) { func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (types.NetworkBackend, types.ContainerNetwork, error) {
backend := types.NetworkBackend(conf.Network.NetworkBackend) backend := types.NetworkBackend(conf.Network.NetworkBackend)
@ -100,7 +100,7 @@ func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (type
func defaultNetworkBackend(store storage.Store, conf *config.Config) (backend types.NetworkBackend, err error) { func defaultNetworkBackend(store storage.Store, conf *config.Config) (backend types.NetworkBackend, err error) {
// read defaultNetworkBackend file // read defaultNetworkBackend file
file := filepath.Join(store.GraphRoot(), defaultNetworkBackendFileName) file := filepath.Join(store.GraphRoot(), defaultNetworkBackendFileName)
b, err := ioutil.ReadFile(file) b, err := os.ReadFile(file)
if err == nil { if err == nil {
val := string(b) val := string(b)
if val == string(types.Netavark) { if val == string(types.Netavark) {

View File

@ -45,7 +45,6 @@ var (
// cleaned config has no defined nameservers left, adds default DNS entries // cleaned config has no defined nameservers left, adds default DNS entries
// 2. Given the caller provides the enable/disable state of IPv6, the filter // 2. Given the caller provides the enable/disable state of IPv6, the filter
// code will remove all IPv6 nameservers if it is not enabled for containers // code will remove all IPv6 nameservers if it is not enabled for containers
//
func filterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) []byte { func filterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) []byte {
// If we're using the host netns, we have nothing to do besides hash the file. // If we're using the host netns, we have nothing to do besides hash the file.
if !netnsEnabled { if !netnsEnabled {

View File

@ -226,6 +226,9 @@ type NetworkOptions struct {
// Networks contains all networks with the PerNetworkOptions. // Networks contains all networks with the PerNetworkOptions.
// The map should contain at least one element. // The map should contain at least one element.
Networks map[string]PerNetworkOptions `json:"networks"` Networks map[string]PerNetworkOptions `json:"networks"`
// List of custom DNS server for podman's DNS resolver.
// Priority order will be kept as defined by user in the configuration.
DNSServers []string `json:"dns_servers,omitempty"`
} }
// PortMapping is one or more ports that will be mapped into the container. // PortMapping is one or more ports that will be mapped into the container.

View File

@ -8,7 +8,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"math" "math"
"os" "os"
"path/filepath" "path/filepath"
@ -143,7 +142,7 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool)
basePath := cgroupRoot + userSlice basePath := cgroupRoot + userSlice
controllersFile = fmt.Sprintf("%s/cgroup.controllers", basePath) controllersFile = fmt.Sprintf("%s/cgroup.controllers", basePath)
} }
controllersFileBytes, err := ioutil.ReadFile(controllersFile) controllersFileBytes, err := os.ReadFile(controllersFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err) return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err)
} }
@ -294,7 +293,7 @@ func (c *CgroupControl) initialize() (err error) {
} }
func readFileAsUint64(path string) (uint64, error) { func readFileAsUint64(path string) (uint64, error) {
data, err := ioutil.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -310,7 +309,7 @@ func readFileAsUint64(path string) (uint64, error) {
} }
func readFileByKeyAsUint64(path, key string) (uint64, error) { func readFileByKeyAsUint64(path, key string) (uint64, error) {
content, err := ioutil.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -533,7 +532,7 @@ func (c *CgroupControl) AddPid(pid int) error {
if c.cgroup2 { if c.cgroup2 {
p := filepath.Join(cgroupRoot, c.path, "cgroup.procs") p := filepath.Join(cgroupRoot, c.path, "cgroup.procs")
if err := ioutil.WriteFile(p, pidString, 0o644); err != nil { if err := os.WriteFile(p, pidString, 0o644); err != nil {
return fmt.Errorf("write %s: %w", p, err) return fmt.Errorf("write %s: %w", p, err)
} }
return nil return nil
@ -556,7 +555,7 @@ func (c *CgroupControl) AddPid(pid int) error {
continue continue
} }
p := filepath.Join(c.getCgroupv1Path(n), "tasks") p := filepath.Join(c.getCgroupv1Path(n), "tasks")
if err := ioutil.WriteFile(p, pidString, 0o644); err != nil { if err := os.WriteFile(p, pidString, 0o644); err != nil {
return fmt.Errorf("write %s: %w", p, err) return fmt.Errorf("write %s: %w", p, err)
} }
} }

View File

@ -8,7 +8,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"math" "math"
"os" "os"
"path/filepath" "path/filepath"
@ -96,7 +95,7 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool)
basePath := cgroupRoot + userSlice basePath := cgroupRoot + userSlice
controllersFile = fmt.Sprintf("%s/cgroup.controllers", basePath) controllersFile = fmt.Sprintf("%s/cgroup.controllers", basePath)
} }
controllersFileBytes, err := ioutil.ReadFile(controllersFile) controllersFileBytes, err := os.ReadFile(controllersFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err) return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err)
} }
@ -247,7 +246,7 @@ func (c *CgroupControl) initialize() (err error) {
} }
func readFileAsUint64(path string) (uint64, error) { func readFileAsUint64(path string) (uint64, error) {
data, err := ioutil.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -263,7 +262,7 @@ func readFileAsUint64(path string) (uint64, error) {
} }
func readFileByKeyAsUint64(path, key string) (uint64, error) { func readFileByKeyAsUint64(path, key string) (uint64, error) {
content, err := ioutil.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -516,7 +515,7 @@ func (c *CgroupControl) AddPid(pid int) error {
continue continue
} }
p := filepath.Join(c.getCgroupv1Path(n), "tasks") p := filepath.Join(c.getCgroupv1Path(n), "tasks")
if err := ioutil.WriteFile(p, pidString, 0o644); err != nil { if err := os.WriteFile(p, pidString, 0o644); err != nil {
return fmt.Errorf("write %s: %w", p, err) return fmt.Errorf("write %s: %w", p, err)
} }
} }

View File

@ -7,7 +7,6 @@ import (
"bufio" "bufio"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -99,12 +98,12 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) {
func rmDirRecursively(path string) error { func rmDirRecursively(path string) error {
killProcesses := func(signal syscall.Signal) { killProcesses := func(signal syscall.Signal) {
if signal == unix.SIGKILL { if signal == unix.SIGKILL {
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0o600); err == nil { if err := os.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0o600); err == nil {
return return
} }
} }
// kill all the processes that are still part of the cgroup // kill all the processes that are still part of the cgroup
if procs, err := ioutil.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil { if procs, err := os.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil {
for _, pidS := range strings.Split(string(procs), "\n") { for _, pidS := range strings.Split(string(procs), "\n") {
if pid, err := strconv.Atoi(pidS); err == nil { if pid, err := strconv.Atoi(pidS); err == nil {
_ = unix.Kill(pid, signal) _ = unix.Kill(pid, signal)
@ -116,7 +115,7 @@ func rmDirRecursively(path string) error {
if err := os.Remove(path); err == nil || errors.Is(err, os.ErrNotExist) { if err := os.Remove(path); err == nil || errors.Is(err, os.ErrNotExist) {
return nil return nil
} }
entries, err := ioutil.ReadDir(path) entries, err := os.ReadDir(path)
if err != nil { if err != nil {
return err return err
} }

View File

@ -5,7 +5,7 @@ package cgroups
import ( import (
"fmt" "fmt"
"io/ioutil" "os"
"path/filepath" "path/filepath"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
@ -31,7 +31,7 @@ func (c *pidHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error {
} }
p := filepath.Join(PIDRoot, "pids.max") p := filepath.Join(PIDRoot, "pids.max")
return ioutil.WriteFile(p, []byte(fmt.Sprintf("%d\n", res.Pids.Limit)), 0o644) return os.WriteFile(p, []byte(fmt.Sprintf("%d\n", res.Pids.Limit)), 0o644)
} }
// Create the cgroup // Create the cgroup

View File

@ -53,18 +53,20 @@ func systemdCreate(path string, c *systemdDbus.Conn) error {
} }
/* /*
systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that
has the following license: has the following license:
Copyright The containerd Authors. Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0 https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, Unless required by applicable law or agreed to in writing, software
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
limitations under the License. See the License for the specific language governing permissions and
limitations under the License.
*/ */
func systemdDestroyConn(path string, c *systemdDbus.Conn) error { func systemdDestroyConn(path string, c *systemdDbus.Conn) error {
name := filepath.Base(path) name := filepath.Base(path)

View File

@ -108,22 +108,22 @@ func systemdCreate(resources *configs.Resources, path string, c *systemdDbus.Con
} }
/* /*
systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that
has the following license: has the following license:
Copyright The containerd Authors. Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0 https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
func systemdDestroyConn(path string, c *systemdDbus.Conn) error { func systemdDestroyConn(path string, c *systemdDbus.Conn) error {
name := filepath.Base(path) name := filepath.Base(path)

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -24,7 +23,7 @@ func readAcct(ctr *CgroupControl, name string) (uint64, error) {
func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) { func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) {
p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name)
data, err := ioutil.ReadFile(p) data, err := os.ReadFile(p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -54,7 +53,7 @@ func GetSystemCPUUsage() (uint64, error) {
return readFileAsUint64(p) return readFileAsUint64(p)
} }
files, err := ioutil.ReadDir(cgroupRoot) files, err := os.ReadDir(cgroupRoot)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -90,7 +89,7 @@ func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) {
if cgroupv2 { if cgroupv2 {
parentPath = fmt.Sprintf("%s.effective", parentPath) parentPath = fmt.Sprintf("%s.effective", parentPath)
} }
data, err := ioutil.ReadFile(parentPath) data, err := os.ReadFile(parentPath)
if err != nil { if err != nil {
// if the file doesn't exist, it is likely that the cpuset controller // if the file doesn't exist, it is likely that the cpuset controller
// is not enabled in the kernel. // is not enabled in the kernel.
@ -106,7 +105,7 @@ func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := ioutil.WriteFile(path, data, 0o644); err != nil { if err := os.WriteFile(path, data, 0o644); err != nil {
return nil, fmt.Errorf("write %s: %w", path, err) return nil, fmt.Errorf("write %s: %w", path, err)
} }
return data, nil return data, nil
@ -126,7 +125,7 @@ func createCgroupv2Path(path string) (deferredError error) {
if !strings.HasPrefix(path, cgroupRoot+"/") { if !strings.HasPrefix(path, cgroupRoot+"/") {
return fmt.Errorf("invalid cgroup path %s", path) return fmt.Errorf("invalid cgroup path %s", path)
} }
content, err := ioutil.ReadFile(cgroupRoot + "/cgroup.controllers") content, err := os.ReadFile(cgroupRoot + "/cgroup.controllers")
if err != nil { if err != nil {
return err return err
} }
@ -154,7 +153,7 @@ func createCgroupv2Path(path string) (deferredError error) {
// We enable the controllers for all the path components except the last one. It is not allowed to add // We enable the controllers for all the path components except the last one. It is not allowed to add
// PIDs if there are already enabled controllers. // PIDs if there are already enabled controllers.
if i < len(elements[3:])-1 { if i < len(elements[3:])-1 {
if err := ioutil.WriteFile(filepath.Join(current, "cgroup.subtree_control"), res, 0o755); err != nil { if err := os.WriteFile(filepath.Join(current, "cgroup.subtree_control"), res, 0o755); err != nil {
return err return err
} }
} }

View File

@ -579,6 +579,7 @@ type SecretConfig struct {
// ConfigMapConfig represents the "configmap" TOML config table // ConfigMapConfig represents the "configmap" TOML config table
// //
// revive does not like the name because the package is already called config // revive does not like the name because the package is already called config
//
//nolint:revive //nolint:revive
type ConfigMapConfig struct { type ConfigMapConfig struct {
// Driver specifies the configmap driver to use. // Driver specifies the configmap driver to use.
@ -1037,6 +1038,7 @@ func (c *Config) Capabilities(user string, addCapabilities, dropCapabilities []s
// Device parses device mapping string to a src, dest & permissions string // Device parses device mapping string to a src, dest & permissions string
// Valid values for device looklike: // Valid values for device looklike:
//
// '/dev/sdc" // '/dev/sdc"
// '/dev/sdc:/dev/xvdc" // '/dev/sdc:/dev/xvdc"
// '/dev/sdc:/dev/xvdc:rwm" // '/dev/sdc:/dev/xvdc:rwm"

View File

@ -685,4 +685,3 @@ func useUserConfigLocations() bool {
// GetRootlessUID == -1 on Windows, so exclude negative range // GetRootlessUID == -1 on Windows, so exclude negative range
return unshare.GetRootlessUID() > 0 return unshare.GetRootlessUID() > 0
} }

View File

@ -2,7 +2,6 @@ package config
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -37,7 +36,7 @@ func getDefaultProcessLimits() []string {
rlim := unix.Rlimit{Cur: oldMaxSize, Max: oldMaxSize} rlim := unix.Rlimit{Cur: oldMaxSize, Max: oldMaxSize}
oldrlim := rlim oldrlim := rlim
// Attempt to set file limit and process limit to pid_max in OS // Attempt to set file limit and process limit to pid_max in OS
dat, err := ioutil.ReadFile("/proc/sys/kernel/pid_max") dat, err := os.ReadFile("/proc/sys/kernel/pid_max")
if err == nil { if err == nil {
val := strings.TrimSuffix(string(dat), "\n") val := strings.TrimSuffix(string(dat), "\n")
max, err := strconv.ParseUint(val, 10, 64) max, err := strconv.ParseUint(val, 10, 64)

View File

@ -4,7 +4,7 @@
package config package config
import ( import (
"io/ioutil" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
@ -53,7 +53,7 @@ func defaultLogDriver() string {
func useSystemd() bool { func useSystemd() bool {
systemdOnce.Do(func() { systemdOnce.Do(func() {
dat, err := ioutil.ReadFile("/proc/1/comm") dat, err := os.ReadFile("/proc/1/comm")
if err == nil { if err == nil {
val := strings.TrimSuffix(string(dat), "\n") val := strings.TrimSuffix(string(dat), "\n")
usesSystemd = (val == "systemd") usesSystemd = (val == "systemd")
@ -68,13 +68,13 @@ func useJournald() bool {
return return
} }
for _, root := range []string{"/run/log/journal", "/var/log/journal"} { for _, root := range []string{"/run/log/journal", "/var/log/journal"} {
dirs, err := ioutil.ReadDir(root) dirs, err := os.ReadDir(root)
if err != nil { if err != nil {
continue continue
} }
for _, d := range dirs { for _, d := range dirs {
if d.IsDir() { if d.IsDir() {
if _, err := ioutil.ReadDir(filepath.Join(root, d.Name())); err == nil { if _, err := os.ReadDir(filepath.Join(root, d.Name())); err == nil {
usesJournald = true usesJournald = true
return return
} }

View File

@ -3,14 +3,14 @@ package download
import ( import (
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"os"
) )
// FromURL downloads the specified source to a file in tmpdir (OS defaults if // FromURL downloads the specified source to a file in tmpdir (OS defaults if
// empty). // empty).
func FromURL(tmpdir, source string) (string, error) { func FromURL(tmpdir, source string) (string, error) {
tmp, err := ioutil.TempFile(tmpdir, "") tmp, err := os.CreateTemp(tmpdir, "")
if err != nil { if err != nil {
return "", fmt.Errorf("creating temporary download file: %w", err) return "", fmt.Errorf("creating temporary download file: %w", err)
} }

View File

@ -38,6 +38,7 @@ func ComputeUntilTimestamp(filterValues []string) (time.Time, error) {
// background. // background.
// //
// revive does not like the name because the package is already called filters // revive does not like the name because the package is already called filters
//
//nolint:revive //nolint:revive
func FiltersFromRequest(r *http.Request) ([]string, error) { func FiltersFromRequest(r *http.Request) ([]string, error) {
var ( var (

View File

@ -5,7 +5,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -31,7 +30,7 @@ func Read(path string, extensionStages []string) (*current.Hook, error) {
if !strings.HasSuffix(path, ".json") { if !strings.HasSuffix(path, ".json") {
return nil, ErrNoJSONSuffix return nil, ErrNoJSONSuffix
} }
content, err := ioutil.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -64,7 +63,7 @@ func read(content []byte) (hook *current.Hook, err error) {
// clobbering any previous entries with the same filenames. // clobbering any previous entries with the same filenames.
func ReadDir(path string, extensionStages []string, hooks map[string]*current.Hook) error { func ReadDir(path string, extensionStages []string, hooks map[string]*current.Hook) error {
logrus.Debugf("reading hooks from %s", path) logrus.Debugf("reading hooks from %s", path)
files, err := ioutil.ReadDir(path) files, err := os.ReadDir(path)
if err != nil { if err != nil {
return err return err
} }

View File

@ -10,6 +10,7 @@ import (
) )
// TODO: change name to MachineMarker since package is already called machine // TODO: change name to MachineMarker since package is already called machine
//
//nolint:revive //nolint:revive
type MachineMarker struct { type MachineMarker struct {
Enabled bool Enabled bool
@ -57,6 +58,7 @@ func IsPodmanMachine() bool {
} }
// TODO: change name to HostType since package is already called machine // TODO: change name to HostType since package is already called machine
//
//nolint:revive //nolint:revive
func MachineHostType() string { func MachineHostType() string {
return GetMachineMarker().Type return GetMachineMarker().Type

View File

@ -103,6 +103,7 @@ func ValidateVolumeOpts(options []string) ([]string, error) {
// Device parses device mapping string to a src, dest & permissions string // Device parses device mapping string to a src, dest & permissions string
// Valid values for device looklike: // Valid values for device looklike:
//
// '/dev/sdc" // '/dev/sdc"
// '/dev/sdc:/dev/xvdc" // '/dev/sdc:/dev/xvdc"
// '/dev/sdc:/dev/xvdc:rwm" // '/dev/sdc:/dev/xvdc:rwm"

View File

@ -33,13 +33,13 @@ import (
// //
// Splitting rules // Splitting rules
// //
// 1) If string is not valid UTF-8, return it without splitting as // 1. If string is not valid UTF-8, return it without splitting as
// single item array. // single item array.
// 2) Assign all unicode characters into one of 4 sets: lower case // 2. Assign all unicode characters into one of 4 sets: lower case
// letters, upper case letters, numbers, and all other characters. // letters, upper case letters, numbers, and all other characters.
// 3) Iterate through characters of string, introducing splits // 3. Iterate through characters of string, introducing splits
// between adjacent characters that belong to different sets. // between adjacent characters that belong to different sets.
// 4) Iterate through array of split strings, and if a given string // 4. Iterate through array of split strings, and if a given string
// is upper case: // is upper case:
// if subsequent string is lower case: // if subsequent string is lower case:
// move last character of upper case string to beginning of // move last character of upper case string to beginning of

View File

@ -4,6 +4,7 @@ Package report provides helper structs/methods/funcs for formatting output
To format output for an array of structs: To format output for an array of structs:
ExamplePodman: ExamplePodman:
headers := report.Headers(struct { headers := report.Headers(struct {
ID string ID string
}{}, nil) }{}, nil)
@ -24,6 +25,7 @@ ExamplePodman:
// fa85da03b40141899f3af3de6d27852b // fa85da03b40141899f3af3de6d27852b
ExampleUser: ExampleUser:
headers := report.Headers(struct { headers := report.Headers(struct {
CID string CID string
}{}, map[string]string{"CID":"ID"}) }{}, map[string]string{"CID":"ID"})
@ -67,7 +69,6 @@ The following template functions are added to the template when parsed:
report.Funcs() may be used to add additional template functions. report.Funcs() may be used to add additional template functions.
Adding an existing function will replace that function for the life of that template. Adding an existing function will replace that function for the life of that template.
Note: Your code should not ignore errors Note: Your code should not ignore errors
*/ */
package report package report

View File

@ -88,6 +88,7 @@ func truncateWithLength(source string, length int) string {
// Array of map is returned to support range templates // Array of map is returned to support range templates
// Note: unexported fields can be supported by adding field to overrides // Note: unexported fields can be supported by adding field to overrides
// Note: It is left to the developer to write out said headers // Note: It is left to the developer to write out said headers
//
// Podman commands use the general rules of: // Podman commands use the general rules of:
// 1) unchanged --format includes headers // 1) unchanged --format includes headers
// 2) --format '{{.ID}" # no headers // 2) --format '{{.ID}" # no headers

View File

@ -5,6 +5,7 @@ import "regexp"
var jsonRegex = regexp.MustCompile(`^\s*(json|{{\s*json\s*(\.)?\s*}})\s*$`) var jsonRegex = regexp.MustCompile(`^\s*(json|{{\s*json\s*(\.)?\s*}})\s*$`)
// JSONFormat test CLI --format string to be a JSON request // JSONFormat test CLI --format string to be a JSON request
//
// if report.IsJSON(cmd.Flag("format").Value.String()) { // if report.IsJSON(cmd.Flag("format").Value.String()) {
// ... process JSON and output // ... process JSON and output
// } // }

View File

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -96,7 +96,7 @@ func (d *Driver) Store(id string, data []byte) error {
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(d.secretsDataFilePath, marshalled, 0o600) err = os.WriteFile(d.secretsDataFilePath, marshalled, 0o600)
if err != nil { if err != nil {
return err return err
} }
@ -120,7 +120,7 @@ func (d *Driver) Delete(id string) error {
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(d.secretsDataFilePath, marshalled, 0o600) err = os.WriteFile(d.secretsDataFilePath, marshalled, 0o600)
if err != nil { if err != nil {
return err return err
} }
@ -145,7 +145,7 @@ func (d *Driver) getAllData() (map[string][]byte, error) {
} }
defer file.Close() defer file.Close()
byteValue, err := ioutil.ReadAll(file) byteValue, err := io.ReadAll(file)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -60,7 +59,7 @@ func defaultDriverConfig() *driverConfig {
continue continue
} }
cfg.Root = path cfg.Root = path
bs, err := ioutil.ReadFile(filepath.Join(path, ".gpg-id")) bs, err := os.ReadFile(filepath.Join(path, ".gpg-id"))
if err != nil { if err != nil {
continue continue
} }
@ -76,7 +75,7 @@ func (cfg *driverConfig) findGpgID() {
path := cfg.Root path := cfg.Root
for len(path) > 1 { for len(path) > 1 {
if _, err := os.Stat(filepath.Join(path, ".gpg-id")); err == nil { if _, err := os.Stat(filepath.Join(path, ".gpg-id")); err == nil {
bs, err := ioutil.ReadFile(filepath.Join(path, ".gpg-id")) bs, err := os.ReadFile(filepath.Join(path, ".gpg-id"))
if err != nil { if err != nil {
continue continue
} }
@ -106,7 +105,7 @@ func NewDriver(opts map[string]string) (*Driver, error) {
// List returns all secret IDs // List returns all secret IDs
func (d *Driver) List() (secrets []string, err error) { func (d *Driver) List() (secrets []string, err error) {
files, err := ioutil.ReadDir(d.Root) files, err := os.ReadDir(d.Root)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read secret directory: %w", err) return nil, fmt.Errorf("failed to read secret directory: %w", err)
} }
@ -168,7 +167,7 @@ func (d *Driver) gpg(ctx context.Context, in io.Reader, out io.Writer, args ...s
cmd.Env = os.Environ() cmd.Env = os.Environ()
cmd.Stdin = in cmd.Stdin = in
cmd.Stdout = out cmd.Stdout = out
cmd.Stderr = ioutil.Discard cmd.Stderr = io.Discard
return cmd.Run() return cmd.Run()
} }

View File

@ -56,6 +56,7 @@ var secretNameRegexp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.-]*$`)
// SecretsManager holds information on handling secrets // SecretsManager holds information on handling secrets
// //
// revive does not like the name because the package is already called secrets // revive does not like the name because the package is already called secrets
//
//nolint:revive //nolint:revive
type SecretsManager struct { type SecretsManager struct {
// secretsPath is the path to the db file where secrets are stored // secretsPath is the path to the db file where secrets are stored
@ -90,6 +91,7 @@ type Secret struct {
// Currently only the unencrypted filedriver is implemented. // Currently only the unencrypted filedriver is implemented.
// //
// revive does not like the name because the package is already called secrets // revive does not like the name because the package is already called secrets
//
//nolint:revive //nolint:revive
type SecretsDriver interface { type SecretsDriver interface {
// List lists all secret ids in the secrets data store // List lists all secret ids in the secrets data store

View File

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io"
"os" "os"
"strings" "strings"
"time" "time"
@ -51,7 +51,7 @@ func (s *SecretsManager) loadDB() error {
return err return err
} }
byteValue, err := ioutil.ReadAll(file) byteValue, err := io.ReadAll(file)
if err != nil { if err != nil {
return err return err
} }
@ -176,7 +176,7 @@ func (s *SecretsManager) store(entry *Secret) error {
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(s.secretsDBPath, marshalled, 0o600) err = os.WriteFile(s.secretsDBPath, marshalled, 0o600)
if err != nil { if err != nil {
return err return err
} }
@ -202,7 +202,7 @@ func (s *SecretsManager) delete(nameOrID string) error {
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(s.secretsDBPath, marshalled, 0o600) err = os.WriteFile(s.secretsDBPath, marshalled, 0o600)
if err != nil { if err != nil {
return err return err
} }

View File

@ -3,7 +3,6 @@ package ssh
import ( import (
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net" "net"
"net/url" "net/url"
"os" "os"
@ -106,7 +105,7 @@ func ReadPassword(prompt string) (pw []byte, err error) {
} }
func PublicKey(path string, passphrase []byte) (ssh.Signer, error) { func PublicKey(path string, passphrase []byte) (ssh.Signer, error) {
key, err := ioutil.ReadFile(path) key, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,7 +4,6 @@ import (
"bufio" "bufio"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -42,7 +41,7 @@ func (s subscriptionData) saveTo(dir string) error {
if err := os.MkdirAll(filepath.Dir(path), s.dirMode); err != nil { if err := os.MkdirAll(filepath.Dir(path), s.dirMode); err != nil {
return err return err
} }
return ioutil.WriteFile(path, s.data, s.mode) return os.WriteFile(path, s.data, s.mode)
} }
func readAll(root, prefix string, parentMode os.FileMode) ([]subscriptionData, error) { func readAll(root, prefix string, parentMode os.FileMode) ([]subscriptionData, error) {
@ -50,7 +49,7 @@ func readAll(root, prefix string, parentMode os.FileMode) ([]subscriptionData, e
data := []subscriptionData{} data := []subscriptionData{}
files, err := ioutil.ReadDir(path) files, err := os.ReadDir(path)
if err != nil { if err != nil {
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
return data, nil return data, nil
@ -90,7 +89,7 @@ func readFileOrDir(root, name string, parentMode os.FileMode) ([]subscriptionDat
} }
return dirData, nil return dirData, nil
} }
bytes, err := ioutil.ReadFile(path) bytes, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -153,7 +152,9 @@ func getMountsMap(path string) (string, string, error) { //nolint
// containerRunDir: Private data for storing subscriptions on the host mounted in container. // containerRunDir: Private data for storing subscriptions on the host mounted in container.
// mountFile: Additional mount points required for the container. // mountFile: Additional mount points required for the container.
// mountPoint: Container image mountpoint, or the directory from the hosts perspective that // mountPoint: Container image mountpoint, or the directory from the hosts perspective that
//
// corresponds to `/` in the container. // corresponds to `/` in the container.
//
// uid: to assign to content created for subscriptions // uid: to assign to content created for subscriptions
// gid: to assign to content created for subscriptions // gid: to assign to content created for subscriptions
// rootless: indicates whether container is running in rootless mode // rootless: indicates whether container is running in rootless mode
@ -268,7 +269,7 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string
if err := os.MkdirAll(filepath.Dir(ctrDirOrFileOnHost), s.dirMode); err != nil { if err := os.MkdirAll(filepath.Dir(ctrDirOrFileOnHost), s.dirMode); err != nil {
return nil, err return nil, err
} }
if err := ioutil.WriteFile(ctrDirOrFileOnHost, s.data, s.mode); err != nil { if err := os.WriteFile(ctrDirOrFileOnHost, s.data, s.mode); err != nil {
return nil, fmt.Errorf("saving data to container filesystem: %w", err) return nil, fmt.Errorf("saving data to container filesystem: %w", err)
} }
} }

View File

@ -3,7 +3,6 @@ package sysinfo
import ( import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path" "path"
"strings" "strings"
@ -210,12 +209,12 @@ func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetI
return cgroupCpusetInfo{} return cgroupCpusetInfo{}
} }
cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus")) cpus, err := os.ReadFile(path.Join(mountPoint, "cpuset.cpus"))
if err != nil { if err != nil {
return cgroupCpusetInfo{} return cgroupCpusetInfo{}
} }
mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems")) mems, err := os.ReadFile(path.Join(mountPoint, "cpuset.mems"))
if err != nil { if err != nil {
return cgroupCpusetInfo{} return cgroupCpusetInfo{}
} }
@ -255,7 +254,7 @@ func cgroupEnabled(mountPoint, name string) bool {
} }
func readProcBool(file string) bool { func readProcBool(file string) bool {
val, err := ioutil.ReadFile(file) val, err := os.ReadFile(file)
if err != nil { if err != nil {
return false return false
} }

View File

@ -103,8 +103,10 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
// if the incoming nanosecond portion is longer or shorter than 9 digits it is // if the incoming nanosecond portion is longer or shorter than 9 digits it is
// converted to nanoseconds. The expectation is that the seconds and // converted to nanoseconds. The expectation is that the seconds and
// seconds will be used to create a time variable. For example: // seconds will be used to create a time variable. For example:
//
// seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0) // seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0)
// if err == nil since := time.Unix(seconds, nanoseconds) // if err == nil since := time.Unix(seconds, nanoseconds)
//
// returns seconds as def(aultSeconds) if value == "" // returns seconds as def(aultSeconds) if value == ""
func ParseTimestamps(value string, def int64) (secs, nanoSecs int64, err error) { func ParseTimestamps(value string, def int64) (secs, nanoSecs int64, err error) {
if value == "" { if value == "" {

7
vendor/modules.txt vendored
View File

@ -75,7 +75,7 @@ github.com/containerd/containerd/log
github.com/containerd/containerd/pkg/userns github.com/containerd/containerd/pkg/userns
github.com/containerd/containerd/platforms github.com/containerd/containerd/platforms
github.com/containerd/containerd/sys github.com/containerd/containerd/sys
# github.com/containerd/stargz-snapshotter/estargz v0.12.0 # github.com/containerd/stargz-snapshotter/estargz v0.12.1
## explicit; go 1.16 ## explicit; go 1.16
github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz
github.com/containerd/stargz-snapshotter/estargz/errorutil github.com/containerd/stargz-snapshotter/estargz/errorutil
@ -117,7 +117,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/util
github.com/containers/buildah/util github.com/containers/buildah/util
# github.com/containers/common v0.50.2-0.20221014181637-a6a9c521b6a5 # github.com/containers/common v0.50.2-0.20221018104440-95c452ec992c
## explicit; go 1.17 ## explicit; go 1.17
github.com/containers/common/libimage github.com/containers/common/libimage
github.com/containers/common/libimage/define github.com/containers/common/libimage/define
@ -263,7 +263,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process github.com/containers/psgo/internal/process
# github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3 # github.com/containers/storage v1.43.1-0.20221018232308-33c396d1aacf => github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3
## explicit; go 1.16 ## explicit; go 1.16
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers
@ -971,3 +971,4 @@ gopkg.in/yaml.v3
## explicit; go 1.12 ## explicit; go 1.12
sigs.k8s.io/yaml sigs.k8s.io/yaml
# github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20220617142545-8b9452f75cbc # github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20220617142545-8b9452f75cbc
# github.com/containers/storage => github.com/containers/storage v1.43.1-0.20221014174544-ebf857fda6f3