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

@ -63,26 +63,29 @@ func df(cmd *cobra.Command, args []string) error {
func printSummary(cmd *cobra.Command, reports *entities.SystemDfReport) error { 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
}
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, err 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,7 +73,8 @@ 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"
@ -37,11 +36,12 @@ const (
// NetworkBackend returns the network backend name and interface // NetworkBackend returns the network backend name and interface
// It returns either the CNI or netavark backend depending on what is set in the config. // It returns either the CNI or netavark backend depending on what is set in the config.
// If the the backend is set to "" we will automatically assign the backend on the following conditions: // If the the backend is set to "" we will automatically assign the backend on the following conditions:
// 1. read ${graphroot}/defaultNetworkBackend // 1. read ${graphroot}/defaultNetworkBackend
// 2. find netavark binary (if not installed use CNI) // 2. find netavark binary (if not installed 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 // 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

@ -40,12 +40,11 @@ var (
) )
// filterResolvDNS cleans up the config in resolvConf. It has two main jobs: // filterResolvDNS cleans up the config in resolvConf. It has two main jobs:
// 1. If a netns is enabled, it looks for localhost (127.*|::1) entries in the provided // 1. If a netns is enabled, it looks for localhost (127.*|::1) entries in the provided
// resolv.conf, removing local nameserver entries, and, if the resulting // resolv.conf, removing local nameserver entries, and, if the resulting
// 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
Unless required by applicable law or agreed to in writing, software https://www.apache.org/licenses/LICENSE-2.0
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Unless required by applicable law or agreed to in writing, software
See the License for the specific language governing permissions and distributed under the License is distributed on an "AS IS" BASIS,
limitations under the License. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
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,10 +1038,11 @@ 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/xvdc" // '/dev/sdc"
// '/dev/sdc:/dev/xvdc:rwm" // '/dev/sdc:/dev/xvdc"
// '/dev/sdc:rm" // '/dev/sdc:/dev/xvdc:rwm"
// '/dev/sdc:rm"
func Device(device string) (src, dst, permissions string, err error) { func Device(device string) (src, dst, permissions string, err error) {
permissions = "rwm" permissions = "rwm"
split := strings.Split(device, ":") split := strings.Split(device, ":")

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

@ -7,7 +7,7 @@ func getDefaultCgroupsMode() string {
// In theory, FreeBSD should be able to use shm locks but in practice, // In theory, FreeBSD should be able to use shm locks but in practice,
// this causes cryptic error messages from the kernel that look like: // this causes cryptic error messages from the kernel that look like:
// //
// comm podman pid 90813: handling rb error 22 // comm podman pid 90813: handling rb error 22
// //
// These seem to be related to fork/exec code paths. Fall back to // These seem to be related to fork/exec code paths. Fall back to
// file-based locks. // file-based locks.

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

@ -90,8 +90,8 @@ func (m *Manager) namedHooks() (hooks []*namedHook) {
// extensionStageHooks. This takes precedence over their inclusion in // extensionStageHooks. This takes precedence over their inclusion in
// the OCI configuration. For example: // the OCI configuration. For example:
// //
// manager, err := New(ctx, []string{DefaultDir}, []string{"poststop"}) // manager, err := New(ctx, []string{DefaultDir}, []string{"poststop"})
// extensionStageHooks, err := manager.Hooks(config, annotations, hasBindMounts) // extensionStageHooks, err := manager.Hooks(config, annotations, hasBindMounts)
// //
// will have any matching post-stop hooks in extensionStageHooks and // will have any matching post-stop hooks in extensionStageHooks and
// will not insert them into config.Hooks.Poststop. // will not insert them into config.Hooks.Poststop.

View File

@ -15,16 +15,16 @@ import (
// first is written after the watchers are established and the second // first is written after the watchers are established and the second
// when this function exits. The expected usage is: // when this function exits. The expected usage is:
// //
// ctx, cancel := context.WithCancel(context.Background()) // ctx, cancel := context.WithCancel(context.Background())
// sync := make(chan error, 2) // sync := make(chan error, 2)
// go m.Monitor(ctx, sync) // go m.Monitor(ctx, sync)
// err := <-sync // block until writers are established // err := <-sync // block until writers are established
// if err != nil { // if err != nil {
// return err // failed to establish watchers // return err // failed to establish watchers
// } // }
// // do stuff // // do stuff
// cancel() // cancel()
// err = <-sync // block until monitor finishes // err = <-sync // block until monitor finishes
func (m *Manager) Monitor(ctx context.Context, sync chan<- error) { func (m *Manager) Monitor(ctx context.Context, sync chan<- error) {
watcher, err := fsnotify.NewWatcher() watcher, err := fsnotify.NewWatcher()
if err != nil { if err != nil {

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,10 +103,11 @@ 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/xvdc" // '/dev/sdc"
// '/dev/sdc:/dev/xvdc:rwm" // '/dev/sdc:/dev/xvdc"
// '/dev/sdc:rm" // '/dev/sdc:/dev/xvdc:rwm"
// '/dev/sdc:rm"
func Device(device string) (src, dest, permissions string, err error) { func Device(device string) (src, dest, permissions string, err error) {
permissions = "rwm" permissions = "rwm"
arr := strings.Split(device, ":") arr := strings.Split(device, ":")

View File

@ -13,37 +13,37 @@ import (
// //
// Examples // Examples
// //
// "" => [""] // "" => [""]
// "lowercase" => ["lowercase"] // "lowercase" => ["lowercase"]
// "Class" => ["Class"] // "Class" => ["Class"]
// "MyClass" => ["My", "Class"] // "MyClass" => ["My", "Class"]
// "MyC" => ["My", "C"] // "MyC" => ["My", "C"]
// "HTML" => ["HTML"] // "HTML" => ["HTML"]
// "PDFLoader" => ["PDF", "Loader"] // "PDFLoader" => ["PDF", "Loader"]
// "AString" => ["A", "String"] // "AString" => ["A", "String"]
// "SimpleXMLParser" => ["Simple", "XML", "Parser"] // "SimpleXMLParser" => ["Simple", "XML", "Parser"]
// "vimRPCPlugin" => ["vim", "RPC", "Plugin"] // "vimRPCPlugin" => ["vim", "RPC", "Plugin"]
// "GL11Version" => ["GL", "11", "Version"] // "GL11Version" => ["GL", "11", "Version"]
// "99Bottles" => ["99", "Bottles"] // "99Bottles" => ["99", "Bottles"]
// "May5" => ["May", "5"] // "May5" => ["May", "5"]
// "BFG9000" => ["BFG", "9000"] // "BFG9000" => ["BFG", "9000"]
// "BöseÜberraschung" => ["Böse", "Überraschung"] // "BöseÜberraschung" => ["Böse", "Überraschung"]
// "Two spaces" => ["Two", " ", "spaces"] // "Two spaces" => ["Two", " ", "spaces"]
// "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"] // "BadUTF8\xe2\xe2\xa1" => ["BadUTF8\xe2\xe2\xa1"]
// //
// 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
// lower case string // lower case string
func Split(src string) (entries []string) { func Split(src string) (entries []string) {
// don't split invalid utf8 // don't split invalid utf8
if !utf8.ValidString(src) { if !utf8.ValidString(src) {

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"})
@ -55,19 +57,18 @@ Helpers:
Template Functions: Template Functions:
The following template functions are added to the template when parsed: The following template functions are added to the template when parsed:
- join strings.Join, {{join .Field separator}} - join strings.Join, {{join .Field separator}}
- json encode field as JSON {{ json .Field }} - json encode field as JSON {{ json .Field }}
- lower strings.ToLower {{ .Field | lower }} - lower strings.ToLower {{ .Field | lower }}
- pad add spaces as prefix and suffix {{ pad . 2 2 }} - pad add spaces as prefix and suffix {{ pad . 2 2 }}
- split strings.Split {{ .Field | split }} - split strings.Split {{ .Field | split }}
- title strings.Title {{ .Field | title }} - title strings.Title {{ .Field | title }}
- truncate limit field length {{ truncate . 10 }} - truncate limit field length {{ truncate . 10 }}
- upper strings.ToUpper {{ .Field | upper }} - upper strings.ToUpper {{ .Field | upper }}
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

@ -51,11 +51,11 @@ type Formatter struct {
// Parse parses golang template returning a formatter // Parse parses golang template returning a formatter
// //
// - OriginPodman implies text is a template from podman code. Output will // - OriginPodman implies text is a template from podman code. Output will
// be filtered through a tabwriter. // be filtered through a tabwriter.
// //
// - OriginUser implies text is a template from a user. If template includes // - OriginUser implies text is a template from a user. If template includes
// keyword "table" output will be filtered through a tabwriter. // keyword "table" output will be filtered through a tabwriter.
func (f *Formatter) Parse(origin Origin, text string) (*Formatter, error) { func (f *Formatter) Parse(origin Origin, text string) (*Formatter, error) {
f.Origin = origin f.Origin = origin

View File

@ -88,10 +88,11 @@ 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: //
// 1) unchanged --format includes headers // Podman commands use the general rules of:
// 2) --format '{{.ID}" # no headers // 1) unchanged --format includes headers
// 3) --format 'table {{.ID}}' # includes headers // 2) --format '{{.ID}" # no headers
// 3) --format 'table {{.ID}}' # includes headers
func Headers(object interface{}, overrides map[string]string) []map[string]string { func Headers(object interface{}, overrides map[string]string) []map[string]string {
value := reflect.ValueOf(object) value := reflect.ValueOf(object)
if value.Kind() == reflect.Ptr { if value.Kind() == reflect.Ptr {

View File

@ -5,9 +5,10 @@ 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()) { //
// ... process JSON and output // if report.IsJSON(cmd.Flag("format").Value.String()) {
// } // ... process JSON and output
// }
func IsJSON(s string) bool { func IsJSON(s string) bool {
return jsonRegex.MatchString(s) return jsonRegex.MatchString(s)
} }

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)
} }
} }
@ -305,10 +306,10 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string
// (i.e: be FIPs compliant). // (i.e: be FIPs compliant).
// It should only be called if /etc/system-fips exists on host. // It should only be called if /etc/system-fips exists on host.
// It primarily does two things: // It primarily does two things:
// - creates /run/secrets/system-fips in the container root filesystem, and adds it to the `mounts` slice. // - creates /run/secrets/system-fips in the container root filesystem, and adds it to the `mounts` slice.
// - If `/etc/crypto-policies/back-ends` already exists inside of the container, it creates // - If `/etc/crypto-policies/back-ends` already exists inside of the container, it creates
// `/usr/share/crypto-policies/back-ends/FIPS` inside the container as well. // `/usr/share/crypto-policies/back-ends/FIPS` inside the container as well.
// It is done from within the container to ensure to avoid policy incompatibility between the container and host. // It is done from within the container to ensure to avoid policy incompatibility between the container and host.
func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint, mountLabel string, uid, gid int) error { func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint, mountLabel string, uid, gid int) error {
subscriptionsDir := "/run/secrets" subscriptionsDir := "/run/secrets"
ctrDirOnHost := filepath.Join(containerRunDir, subscriptionsDir) ctrDirOnHost := filepath.Join(containerRunDir, subscriptionsDir)

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) //
// if err == nil since := time.Unix(seconds, nanoseconds) // seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0)
// 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