diff --git a/go.mod b/go.mod index 8e395272b3..5228133b10 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/checkpoint-restore/go-criu/v7 v7.2.0 github.com/containernetworking/plugins v1.5.1 github.com/containers/buildah v1.37.1-0.20241018144937-2551c8f3d110 - github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7 + github.com/containers/common v0.60.3 github.com/containers/conmon v2.0.20+incompatible github.com/containers/gvisor-tap-vsock v0.7.5 github.com/containers/image/v5 v5.32.3-0.20241016192323-a66152c1cdf6 @@ -24,7 +24,7 @@ require ( github.com/containers/winquit v1.1.0 github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 github.com/coreos/stream-metadata-go v0.4.4 - github.com/crc-org/crc/v2 v2.38.0 + github.com/crc-org/crc/v2 v2.42.0 github.com/crc-org/vfkit v0.5.1 github.com/cyphar/filepath-securejoin v0.3.4 github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e @@ -97,6 +97,7 @@ require ( github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect + github.com/containerd/containerd v1.7.21 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect diff --git a/go.sum b/go.sum index 9a2d90b59e..de0e4eaf30 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= +github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= +github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -79,8 +81,8 @@ github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+ github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containers/buildah v1.37.1-0.20241018144937-2551c8f3d110 h1:YcrjUM1CwDTEnaPHgpVmjid/R3zAVXRRHcgknQsajlI= github.com/containers/buildah v1.37.1-0.20241018144937-2551c8f3d110/go.mod h1:SVyERMThmMXGTdle/9MdRuX2Ae7eVY9qDVartYXIx7E= -github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7 h1:EFzq3sjwy0vBr9RoZPzTbtoGZR4hoZsmgxuIs5Uc5FA= -github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7/go.mod h1:T8vpUWd7AspK7CMELf/c+NCZB6bKrRkLriRCspdFGyQ= +github.com/containers/common v0.60.3 h1:pToT7gtFx/KWyMtWw98g4pIbW54i9KfGH2QrdN2s1io= +github.com/containers/common v0.60.3/go.mod h1:I0upBi1qJX3QmzGbUOBN1LVP6RvkKhd3qQpZbQT+Q54= 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/gvisor-tap-vsock v0.7.5 h1:bTy4u3DOmmUPwurL6me2rsgfypAFDhyeJleUcQmBR/E= @@ -110,8 +112,8 @@ github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09/go.mod h1 github.com/coreos/stream-metadata-go v0.4.4 h1:PM/6iNhofKGydsatiY1zdnMMHBT34skb5P7nfEFR4GU= github.com/coreos/stream-metadata-go v0.4.4/go.mod h1:fMObQqQm8Ku91G04btKzEH3AsdP1mrAb986z9aaK0tE= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crc-org/crc/v2 v2.38.0 h1:8QcoH4hYksfKUQOLXHZw4jIY1aNS162WraZR4mzQzC8= -github.com/crc-org/crc/v2 v2.38.0/go.mod h1:HPY6grOaExM4Bhmd3T4RSkP0eizWsb8wSgoSwNsV5+k= +github.com/crc-org/crc/v2 v2.42.0 h1:9GpIttMaBq6ezN/m4sBMW92OU9wu/g4rv1JAp782yyE= +github.com/crc-org/crc/v2 v2.42.0/go.mod h1:Hp+y5Oa4S/qAesCotV/AXHEYHya0fyrrKYvEX6EmQZ4= github.com/crc-org/vfkit v0.5.1 h1:r1zNf1g1bLbgu5BgIQodirvYaIGWJQ91eS/PIgNO6lo= github.com/crc-org/vfkit v0.5.1/go.mod h1:Hqi20zQcqXMk6JqvByvOidHYv+KzPx3G+cjkdGSWv60= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= diff --git a/vendor/github.com/containerd/containerd/LICENSE b/vendor/github.com/containerd/containerd/LICENSE new file mode 100644 index 0000000000..584149b6ee --- /dev/null +++ b/vendor/github.com/containerd/containerd/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright The containerd Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + 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 + distributed under the License is distributed on an "AS IS" BASIS, + 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. diff --git a/vendor/github.com/containerd/containerd/NOTICE b/vendor/github.com/containerd/containerd/NOTICE new file mode 100644 index 0000000000..8915f02773 --- /dev/null +++ b/vendor/github.com/containerd/containerd/NOTICE @@ -0,0 +1,16 @@ +Docker +Copyright 2012-2015 Docker, Inc. + +This product includes software developed at Docker, Inc. (https://www.docker.com). + +The following is courtesy of our legal counsel: + + +Use and transfer of Docker may be subject to certain restrictions by the +United States and other governments. +It is your responsibility to ensure that your use and/or transfer does not +violate applicable laws. + +For more information, please see https://www.bis.doc.gov + +See also https://www.apache.org/dev/crypto.html and/or seek legal counsel. diff --git a/vendor/github.com/containerd/containerd/platforms/platforms_deprecated.go b/vendor/github.com/containerd/containerd/platforms/platforms_deprecated.go new file mode 100644 index 0000000000..b057304cff --- /dev/null +++ b/vendor/github.com/containerd/containerd/platforms/platforms_deprecated.go @@ -0,0 +1,176 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://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, + 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. +*/ + +package platforms + +import ( + "github.com/containerd/platforms" + specs "github.com/opencontainers/image-spec/specs-go/v1" +) + +// Platform is a type alias for convenience, so there is no need to import image-spec package everywhere. +// +// Deprecated: use [specs.Platform]. +type Platform = specs.Platform + +// DefaultSpec returns the current platform's default platform specification. +// +// Deprecated: use [platforms.DefaultSpec]. +func DefaultSpec() specs.Platform { + return platforms.DefaultSpec() +} + +// Default returns the default matcher for the platform. +// +// Deprecated: use [platforms.Default]. +func Default() platforms.MatchComparer { + return platforms.Default() +} + +// DefaultString returns the default string specifier for the platform. +// +// Deprecated: use [platforms.DefaultString]. +func DefaultString() string { + return platforms.Format(platforms.DefaultSpec()) // For 1.7 continue using the old format without os-version included. +} + +// DefaultStrict returns strict form of Default. +// +// Deprecated: use [platforms.DefaultStrict]. +func DefaultStrict() MatchComparer { + return platforms.DefaultStrict() +} + +// MatchComparer is able to match and compare platforms to +// filter and sort platforms. +// +// Deprecated: use [platforms.MatchComparer]. +type MatchComparer = platforms.MatchComparer + +// Matcher matches platforms specifications, provided by an image or runtime. +// +// Deprecated: use [platforms.Matcher]. +type Matcher = platforms.Matcher + +// NewMatcher returns a simple matcher based on the provided platform +// specification. The returned matcher only looks for equality based on os, +// architecture and variant. +// +// One may implement their own matcher if this doesn't provide the required +// functionality. +// +// Applications should opt to use `Match` over directly parsing specifiers. +// +// Deprecated: use [platforms.NewMatcher]. +func NewMatcher(platform specs.Platform) platforms.Matcher { + return platforms.NewMatcher(platform) +} + +// Parse parses the platform specifier syntax into a platform declaration. +// +// Platform specifiers are in the format `||/[/]`. +// The minimum required information for a platform specifier is the operating +// system or architecture. If there is only a single string (no slashes), the +// value will be matched against the known set of operating systems, then fall +// back to the known set of architectures. The missing component will be +// inferred based on the local environment. +// +// Deprecated: use [platforms.Parse]. +func Parse(specifier string) (specs.Platform, error) { + return platforms.Parse(specifier) +} + +// MustParse is like Parses but panics if the specifier cannot be parsed. +// Simplifies initialization of global variables. +// +// Deprecated: use [platforms.MustParse]. +func MustParse(specifier string) specs.Platform { + return platforms.MustParse(specifier) +} + +// Format returns a string specifier from the provided platform specification. +// +// Deprecated: use [platforms.Format]. +func Format(platform specs.Platform) string { + return platforms.Format(platform) +} + +// Normalize validates and translate the platform to the canonical value. +// +// For example, if "Aarch64" is encountered, we change it to "arm64" or if +// "x86_64" is encountered, it becomes "amd64". +// +// Deprecated: use [platforms.Normalize]. +func Normalize(platform specs.Platform) specs.Platform { + return platforms.Normalize(platform) +} + +// Only returns a match comparer for a single platform +// using default resolution logic for the platform. +// +// For arm/v8, will also match arm/v7, arm/v6 and arm/v5 +// For arm/v7, will also match arm/v6 and arm/v5 +// For arm/v6, will also match arm/v5 +// For amd64, will also match 386 +// +// Deprecated: use [platforms.Only]. +func Only(platform specs.Platform) platforms.MatchComparer { + return platforms.Only(platform) +} + +// OnlyStrict returns a match comparer for a single platform. +// +// Unlike Only, OnlyStrict does not match sub platforms. +// So, "arm/vN" will not match "arm/vM" where M < N, +// and "amd64" will not also match "386". +// +// OnlyStrict matches non-canonical forms. +// So, "arm64" matches "arm/64/v8". +// +// Deprecated: use [platforms.OnlyStrict]. +func OnlyStrict(platform specs.Platform) platforms.MatchComparer { + return platforms.OnlyStrict(platform) +} + +// Ordered returns a platform MatchComparer which matches any of the platforms +// but orders them in order they are provided. +// +// Deprecated: use [platforms.Ordered]. +func Ordered(platform ...specs.Platform) platforms.MatchComparer { + return platforms.Ordered(platform...) +} + +// Any returns a platform MatchComparer which matches any of the platforms +// with no preference for ordering. +// +// Deprecated: use [platforms.Any]. +func Any(platform ...specs.Platform) platforms.MatchComparer { + return platforms.Any(platform...) +} + +// All is a platform MatchComparer which matches all platforms +// with preference for ordering. +// +// Deprecated: use [platforms.All]. +var All = platforms.All + +// GetWindowsOsVersion returns the version of Windows of the local system, +// it returns an empty string on other platforms. +// +// Deprecated: this function is deprecated, and removed in github.com/containerd/platforms +func GetWindowsOsVersion() string { + return getWindowsOsVersion() +} diff --git a/vendor/github.com/containerd/containerd/platforms/platforms_deprecated_other.go b/vendor/github.com/containerd/containerd/platforms/platforms_deprecated_other.go new file mode 100644 index 0000000000..0d17529ecd --- /dev/null +++ b/vendor/github.com/containerd/containerd/platforms/platforms_deprecated_other.go @@ -0,0 +1,23 @@ +//go:build !windows + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://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, + 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. +*/ + +package platforms + +func getWindowsOsVersion() string { + return "" +} diff --git a/vendor/github.com/containerd/containerd/platforms/platforms_deprecated_windows.go b/vendor/github.com/containerd/containerd/platforms/platforms_deprecated_windows.go new file mode 100644 index 0000000000..dc0fdbf12b --- /dev/null +++ b/vendor/github.com/containerd/containerd/platforms/platforms_deprecated_windows.go @@ -0,0 +1,49 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://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, + 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. +*/ + +package platforms + +import ( + "fmt" + "strconv" + "strings" + + "github.com/Microsoft/hcsshim/osversion" + "golang.org/x/sys/windows" +) + +func getWindowsOsVersion() string { + major, minor, build := windows.RtlGetNtVersionNumbers() + return fmt.Sprintf("%d.%d.%d", major, minor, build) +} + +// Deprecated: this function is deprecated, and removed in github.com/containerd/platforms +func GetOsVersion(osVersionPrefix string) osversion.OSVersion { + parts := strings.Split(osVersionPrefix, ".") + if len(parts) < 3 { + return osversion.OSVersion{} + } + + majorVersion, _ := strconv.Atoi(parts[0]) + minorVersion, _ := strconv.Atoi(parts[1]) + buildNumber, _ := strconv.Atoi(parts[2]) + + return osversion.OSVersion{ + MajorVersion: uint8(majorVersion), + MinorVersion: uint8(minorVersion), + Build: uint16(buildNumber), + } +} diff --git a/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go index b2cd6cedb3..1f4f925fe5 100644 --- a/vendor/github.com/containers/common/libimage/copier.go +++ b/vendor/github.com/containers/common/libimage/copier.go @@ -60,13 +60,6 @@ type CopyOptions struct { CertDirPath string // Force layer compression when copying to a `dir` transport destination. DirForceCompress bool - - // ImageListSelection is one of CopySystemImage, CopyAllImages, or - // CopySpecificImages, to control whether, when the source reference is a list, - // copy.Image() copies only an image which matches the current runtime - // environment, or all images which match the supplied reference, or only - // specific images from the source reference. - ImageListSelection copy.ImageListSelection // Allow contacting registries over HTTP, or HTTPS with failed TLS // verification. Note that this does not affect other TLS connections. InsecureSkipTLSVerify types.OptionalBool @@ -160,8 +153,8 @@ type CopyOptions struct { extendTimeoutSocket string } -// Copier is a helper to conveniently copy images. -type Copier struct { +// copier is an internal helper to conveniently copy images. +type copier struct { extendTimeoutSocket string imageCopyOptions copy.Options retryOptions retry.Options @@ -172,13 +165,6 @@ type Copier struct { destinationLookup LookupReferenceFunc } -// newCopier creates a Copier based on a runtime's system context. -// Note that fields in options *may* overwrite the counterparts of -// the specified system context. Please make sure to call `(*Copier).Close()`. -func (r *Runtime) newCopier(options *CopyOptions) (*Copier, error) { - return NewCopier(options, r.SystemContext()) -} - // storageAllowedPolicyScopes overrides the policy for local storage // to ensure that we can read images from it. var storageAllowedPolicyScopes = signature.PolicyTransportScopes{ @@ -220,13 +206,12 @@ func getDockerAuthConfig(name, passwd, creds, idToken string) (*types.DockerAuth } } -// NewCopier creates a Copier based on a provided system context. -// Note that fields in options *may* overwrite the counterparts of -// the specified system context. Please make sure to call `(*Copier).Close()`. -func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) { - c := Copier{extendTimeoutSocket: options.extendTimeoutSocket} - sysContextCopy := *sc - c.systemContext = &sysContextCopy +// newCopier creates a copier. Note that fields in options *may* overwrite the +// counterparts of the specified system context. Please make sure to call +// `(*copier).close()`. +func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { + c := copier{extendTimeoutSocket: options.extendTimeoutSocket} + c.systemContext = r.systemContextCopy() if options.SourceLookupReferenceFunc != nil { c.sourceLookup = options.SourceLookupReferenceFunc @@ -315,7 +300,6 @@ func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) { c.imageCopyOptions.ProgressInterval = time.Second } - c.imageCopyOptions.ImageListSelection = options.ImageListSelection c.imageCopyOptions.ForceCompressionFormat = options.ForceCompressionFormat c.imageCopyOptions.ForceManifestMIMEType = options.ManifestMIMEType c.imageCopyOptions.SourceCtx = c.systemContext @@ -341,14 +325,14 @@ func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) { return &c, nil } -// Close open resources. -func (c *Copier) Close() error { +// close open resources. +func (c *copier) close() error { return c.policyContext.Destroy() } -// Copy the source to the destination. Returns the bytes of the copied +// copy the source to the destination. Returns the bytes of the copied // manifest which may be used for digest computation. -func (c *Copier) Copy(ctx context.Context, source, destination types.ImageReference) ([]byte, error) { +func (c *copier) copy(ctx context.Context, source, destination types.ImageReference) ([]byte, error) { logrus.Debugf("Copying source image %s to destination image %s", source.StringWithinTransport(), destination.StringWithinTransport()) // Avoid running out of time when running inside a systemd unit by diff --git a/vendor/github.com/containers/common/libimage/disk_usage.go b/vendor/github.com/containers/common/libimage/disk_usage.go index 7b7b56ad7d..6264b25ec9 100644 --- a/vendor/github.com/containers/common/libimage/disk_usage.go +++ b/vendor/github.com/containers/common/libimage/disk_usage.go @@ -31,12 +31,12 @@ type ImageDiskUsage struct { // storage. Note that a single image may yield multiple usage reports, one for // each repository tag. func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, int64, error) { - images, layers, err := r.getImagesAndLayers() + images, err := r.ListImages(ctx, nil, nil) if err != nil { return nil, -1, err } - layerTree, err := r.newLayerTreeFromData(images, layers) + layerTree, err := r.layerTree(ctx, images) if err != nil { return nil, -1, err } diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go index aa11d54f53..2465d370d2 100644 --- a/vendor/github.com/containers/common/libimage/filters.go +++ b/vendor/github.com/containers/common/libimage/filters.go @@ -19,22 +19,19 @@ import ( // filterFunc is a prototype for a positive image filter. Returning `true` // indicates that the image matches the criteria. -type filterFunc func(*Image, *layerTree) (bool, error) - -type compiledFilters map[string][]filterFunc +type filterFunc func(*Image) (bool, error) // Apply the specified filters. All filters of each key must apply. -// tree must be provided if compileImageFilters indicated it is necessary. -func (i *Image) applyFilters(ctx context.Context, filters compiledFilters, tree *layerTree) (bool, error) { +func (i *Image) applyFilters(ctx context.Context, filters map[string][]filterFunc) (bool, error) { for key := range filters { for _, filter := range filters[key] { - matches, err := filter(i, tree) + matches, err := filter(i) if err != nil { // Some images may have been corrupted in the // meantime, so do an extra check and make the // error non-fatal (see containers/podman/issues/12582). if errCorrupted := i.isCorrupted(ctx, ""); errCorrupted != nil { - logrus.Error(errCorrupted.Error()) + logrus.Errorf(errCorrupted.Error()) return false, nil } return false, err @@ -50,11 +47,18 @@ func (i *Image) applyFilters(ctx context.Context, filters compiledFilters, tree // filterImages returns a slice of images which are passing all specified // filters. -// tree must be provided if compileImageFilters indicated it is necessary. -func (r *Runtime) filterImages(ctx context.Context, images []*Image, filters compiledFilters, tree *layerTree) ([]*Image, error) { +func (r *Runtime) filterImages(ctx context.Context, images []*Image, options *ListImagesOptions) ([]*Image, error) { + if len(options.Filters) == 0 || len(images) == 0 { + return images, nil + } + + filters, err := r.compileImageFilters(ctx, options) + if err != nil { + return nil, err + } result := []*Image{} for i := range images { - match, err := images[i].applyFilters(ctx, filters, tree) + match, err := images[i].applyFilters(ctx, filters) if err != nil { return nil, err } @@ -69,19 +73,25 @@ func (r *Runtime) filterImages(ctx context.Context, images []*Image, filters com // required format is `key=value` with the following supported keys: // // after, since, before, containers, dangling, id, label, readonly, reference, intermediate -// -// compileImageFilters returns: compiled filters, if LayerTree is needed, error -func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) (compiledFilters, bool, error) { +func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) (map[string][]filterFunc, error) { logrus.Tracef("Parsing image filters %s", options.Filters) - if len(options.Filters) == 0 { - return nil, false, nil + + var tree *layerTree + getTree := func() (*layerTree, error) { + if tree == nil { + t, err := r.layerTree(ctx, nil) + if err != nil { + return nil, err + } + tree = t + } + return tree, nil } filterInvalidValue := `invalid image filter %q: must be in the format "filter=value or filter!=value"` var wantedReferenceMatches, unwantedReferenceMatches []string - filters := compiledFilters{} - needsLayerTree := false + filters := map[string][]filterFunc{} duplicate := map[string]string{} for _, f := range options.Filters { var key, value string @@ -93,7 +103,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp } else { split = strings.SplitN(f, "=", 2) if len(split) != 2 { - return nil, false, fmt.Errorf(filterInvalidValue, f) + return nil, fmt.Errorf(filterInvalidValue, f) } } @@ -103,7 +113,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp case "after", "since": img, err := r.time(key, value) if err != nil { - return nil, false, err + return nil, err } key = "since" filter = filterAfter(img.Created()) @@ -111,23 +121,27 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp case "before": img, err := r.time(key, value) if err != nil { - return nil, false, err + return nil, err } filter = filterBefore(img.Created()) case "containers": if err := r.containers(duplicate, key, value, options.IsExternalContainerFunc); err != nil { - return nil, false, err + return nil, err } filter = filterContainers(value, options.IsExternalContainerFunc) case "dangling": dangling, err := r.bool(duplicate, key, value) if err != nil { - return nil, false, err + return nil, err + } + t, err := getTree() + if err != nil { + return nil, err } - needsLayerTree = true - filter = filterDangling(ctx, dangling) + + filter = filterDangling(ctx, dangling, t) case "id": filter = filterID(value) @@ -135,31 +149,35 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp case "digest": f, err := filterDigest(value) if err != nil { - return nil, false, err + return nil, err } filter = f case "intermediate": intermediate, err := r.bool(duplicate, key, value) if err != nil { - return nil, false, err + return nil, err + } + t, err := getTree() + if err != nil { + return nil, err } - needsLayerTree = true - filter = filterIntermediate(ctx, intermediate) + + filter = filterIntermediate(ctx, intermediate, t) case "label": filter = filterLabel(ctx, value) case "readonly": readOnly, err := r.bool(duplicate, key, value) if err != nil { - return nil, false, err + return nil, err } filter = filterReadOnly(readOnly) case "manifest": manifest, err := r.bool(duplicate, key, value) if err != nil { - return nil, false, err + return nil, err } filter = filterManifest(ctx, manifest) @@ -174,12 +192,12 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp case "until": until, err := r.until(value) if err != nil { - return nil, false, err + return nil, err } filter = filterBefore(until) default: - return nil, false, fmt.Errorf(filterInvalidValue, key) + return nil, fmt.Errorf(filterInvalidValue, key) } if negate { filter = negateFilter(filter) @@ -192,12 +210,12 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp filter := filterReferences(r, wantedReferenceMatches, unwantedReferenceMatches) filters["reference"] = append(filters["reference"], filter) - return filters, needsLayerTree, nil + return filters, nil } func negateFilter(f filterFunc) filterFunc { - return func(img *Image, tree *layerTree) (bool, error) { - b, err := f(img, tree) + return func(img *Image) (bool, error) { + b, err := f(img) return !b, err } } @@ -254,7 +272,7 @@ func (r *Runtime) bool(duplicate map[string]string, key, value string) (bool, er // filterManifest filters whether or not the image is a manifest list func filterManifest(ctx context.Context, value bool) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { isManifestList, err := img.IsManifestList(ctx) if err != nil { return false, err @@ -266,7 +284,7 @@ func filterManifest(ctx context.Context, value bool) filterFunc { // filterReferences creates a reference filter for matching the specified wantedReferenceMatches value (OR logic) // and for matching the unwantedReferenceMatches values (AND logic) func filterReferences(r *Runtime, wantedReferenceMatches, unwantedReferenceMatches []string) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { // Empty reference filters, return true if len(wantedReferenceMatches) == 0 && len(unwantedReferenceMatches) == 0 { return true, nil @@ -358,7 +376,7 @@ func imageMatchesReferenceFilter(r *Runtime, img *Image, value string) (bool, er // filterLabel creates a label for matching the specified value. func filterLabel(ctx context.Context, value string) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { labels, err := img.Labels(ctx) if err != nil { return false, err @@ -369,28 +387,28 @@ func filterLabel(ctx context.Context, value string) filterFunc { // filterAfter creates an after filter for matching the specified value. func filterAfter(value time.Time) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { return img.Created().After(value), nil } } // filterBefore creates a before filter for matching the specified value. func filterBefore(value time.Time) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { return img.Created().Before(value), nil } } // filterReadOnly creates a readonly filter for matching the specified value. func filterReadOnly(value bool) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { return img.IsReadOnly() == value, nil } } // filterContainers creates a container filter for matching the specified value. func filterContainers(value string, fn IsExternalContainerFunc) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { ctrs, err := img.Containers() if err != nil { return false, err @@ -415,8 +433,8 @@ func filterContainers(value string, fn IsExternalContainerFunc) filterFunc { } // filterDangling creates a dangling filter for matching the specified value. -func filterDangling(ctx context.Context, value bool) filterFunc { - return func(img *Image, tree *layerTree) (bool, error) { +func filterDangling(ctx context.Context, value bool, tree *layerTree) filterFunc { + return func(img *Image) (bool, error) { isDangling, err := img.isDangling(ctx, tree) if err != nil { return false, err @@ -427,7 +445,7 @@ func filterDangling(ctx context.Context, value bool) filterFunc { // filterID creates an image-ID filter for matching the specified value. func filterID(value string) filterFunc { - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { return strings.HasPrefix(img.ID(), value), nil } } @@ -437,7 +455,7 @@ func filterDigest(value string) (filterFunc, error) { if !strings.HasPrefix(value, "sha256:") { return nil, fmt.Errorf("invalid value %q for digest filter", value) } - return func(img *Image, _ *layerTree) (bool, error) { + return func(img *Image) (bool, error) { return img.containsDigestPrefix(value), nil }, nil } @@ -445,8 +463,8 @@ func filterDigest(value string) (filterFunc, error) { // filterIntermediate creates an intermediate filter for images. An image is // considered to be an intermediate image if it is dangling (i.e., no tags) and // has no children (i.e., no other image depends on it). -func filterIntermediate(ctx context.Context, value bool) filterFunc { - return func(img *Image, tree *layerTree) (bool, error) { +func filterIntermediate(ctx context.Context, value bool, tree *layerTree) filterFunc { + return func(img *Image) (bool, error) { isIntermediate, err := img.isIntermediate(ctx, tree) if err != nil { return false, err diff --git a/vendor/github.com/containers/common/libimage/history.go b/vendor/github.com/containers/common/libimage/history.go index 845f4088e2..56f84e37aa 100644 --- a/vendor/github.com/containers/common/libimage/history.go +++ b/vendor/github.com/containers/common/libimage/history.go @@ -25,7 +25,7 @@ func (i *Image) History(ctx context.Context) ([]ImageHistory, error) { return nil, err } - layerTree, err := i.runtime.newFreshLayerTree() + layerTree, err := i.runtime.layerTree(ctx, nil) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index a971b6c67e..9cc77cdb25 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/containerd/platforms" + "github.com/containerd/containerd/platforms" "github.com/containers/common/libimage/platform" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/manifest" @@ -257,7 +257,7 @@ func (i *Image) TopLayer() string { // Parent returns the parent image or nil if there is none func (i *Image) Parent(ctx context.Context) (*Image, error) { - tree, err := i.runtime.newFreshLayerTree() + tree, err := i.runtime.layerTree(ctx, nil) if err != nil { return nil, err } @@ -291,7 +291,7 @@ func (i *Image) Children(ctx context.Context) ([]*Image, error) { // created for this invocation only. func (i *Image) getChildren(ctx context.Context, all bool, tree *layerTree) ([]*Image, error) { if tree == nil { - t, err := i.runtime.newFreshLayerTree() + t, err := i.runtime.layerTree(ctx, nil) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/common/libimage/image_tree.go b/vendor/github.com/containers/common/libimage/image_tree.go index 9628a319f1..8b9d1f4c47 100644 --- a/vendor/github.com/containers/common/libimage/image_tree.go +++ b/vendor/github.com/containers/common/libimage/image_tree.go @@ -3,6 +3,7 @@ package libimage import ( + "context" "fmt" "strings" @@ -37,7 +38,7 @@ func (i *Image) Tree(traverseChildren bool) (string, error) { fmt.Fprintf(sb, "No Image Layers") } - layerTree, err := i.runtime.newFreshLayerTree() + layerTree, err := i.runtime.layerTree(context.Background(), nil) if err != nil { return "", err } diff --git a/vendor/github.com/containers/common/libimage/import.go b/vendor/github.com/containers/common/libimage/import.go index a03f288533..552c48eae0 100644 --- a/vendor/github.com/containers/common/libimage/import.go +++ b/vendor/github.com/containers/common/libimage/import.go @@ -108,9 +108,9 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption if err != nil { return "", err } - defer c.Close() + defer c.close() - if _, err := c.Copy(ctx, srcRef, destRef); err != nil { + if _, err := c.copy(ctx, srcRef, destRef); err != nil { return "", err } diff --git a/vendor/github.com/containers/common/libimage/layer_tree.go b/vendor/github.com/containers/common/libimage/layer_tree.go index aeb1d45bb3..9af120e252 100644 --- a/vendor/github.com/containers/common/libimage/layer_tree.go +++ b/vendor/github.com/containers/common/libimage/layer_tree.go @@ -89,18 +89,21 @@ func (l *layerNode) repoTags() ([]string, error) { return orderedTags, nil } -// newFreshLayerTree extracts a layerTree from consistent layers and images in the local storage. -func (r *Runtime) newFreshLayerTree() (*layerTree, error) { - images, layers, err := r.getImagesAndLayers() +// layerTree extracts a layerTree from the layers in the local storage and +// relates them to the specified images. +func (r *Runtime) layerTree(ctx context.Context, images []*Image) (*layerTree, error) { + layers, err := r.store.Layers() if err != nil { return nil, err } - return r.newLayerTreeFromData(images, layers) -} -// newLayerTreeFromData extracts a layerTree from the given the layers and images. -// The caller is responsible for (layers, images) being consistent. -func (r *Runtime) newLayerTreeFromData(images []*Image, layers []storage.Layer) (*layerTree, error) { + if images == nil { + images, err = r.ListImages(ctx, nil, nil) + if err != nil { + return nil, err + } + } + tree := layerTree{ nodes: make(map[string]*layerNode), ociCache: make(map[string]*ociv1.Image), diff --git a/vendor/github.com/containers/common/libimage/manifest_list.go b/vendor/github.com/containers/common/libimage/manifest_list.go index a23315da3c..1a6004c01a 100644 --- a/vendor/github.com/containers/common/libimage/manifest_list.go +++ b/vendor/github.com/containers/common/libimage/manifest_list.go @@ -7,28 +7,20 @@ import ( "errors" "fmt" "maps" - "os" - "path/filepath" "slices" "time" "github.com/containers/common/libimage/define" "github.com/containers/common/libimage/manifests" - manifesterrors "github.com/containers/common/pkg/manifests" - "github.com/containers/common/pkg/supplemented" imageCopy "github.com/containers/image/v5/copy" "github.com/containers/image/v5/docker" "github.com/containers/image/v5/manifest" - "github.com/containers/image/v5/oci/layout" - "github.com/containers/image/v5/signature" "github.com/containers/image/v5/transports/alltransports" "github.com/containers/image/v5/types" "github.com/containers/storage" structcopier "github.com/jinzhu/copier" "github.com/opencontainers/go-digest" - imgspec "github.com/opencontainers/image-spec/specs-go" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) // NOTE: the abstractions and APIs here are a first step to further merge @@ -109,157 +101,8 @@ func (r *Runtime) lookupManifestList(name string) (*Image, manifests.List, error return image, list, nil } -// ConvertToManifestList converts the image into a manifest list if it is not -// already also a list. An error is returned if the conversion fails. -func (i *Image) ConvertToManifestList(ctx context.Context) (*ManifestList, error) { - // If we don't need to do anything, don't do anything. - if list, err := i.ToManifestList(); err == nil || !errors.Is(err, ErrNotAManifestList) { - return list, err - } - - // Determine which type we prefer for the new manifest list or image index. - _, imageManifestType, err := i.Manifest(ctx) - if err != nil { - return nil, fmt.Errorf("reading the image's manifest: %w", err) - } - var preferredListType string - switch imageManifestType { - case manifest.DockerV2Schema2MediaType, - manifest.DockerV2Schema1SignedMediaType, - manifest.DockerV2Schema1MediaType, - manifest.DockerV2ListMediaType: - preferredListType = manifest.DockerV2ListMediaType - case imgspecv1.MediaTypeImageManifest, imgspecv1.MediaTypeImageIndex: - preferredListType = imgspecv1.MediaTypeImageIndex - default: - preferredListType = "" - } - - // Create a list and add the image's manifest to it. Use OCI format - // for now. If we need to convert it to Docker format, we'll do that - // while copying it. - list := manifests.Create() - if _, err := list.Add(ctx, &i.runtime.systemContext, i.storageReference, false); err != nil { - return nil, fmt.Errorf("generating new image index: %w", err) - } - listBytes, err := list.Serialize(imgspecv1.MediaTypeImageIndex) - if err != nil { - return nil, fmt.Errorf("serializing image index: %w", err) - } - listDigest, err := manifest.Digest(listBytes) - if err != nil { - return nil, fmt.Errorf("digesting image index: %w", err) - } - - // Build an OCI layout containing the image index as the only item. - tmp, err := os.MkdirTemp("", "") - if err != nil { - return nil, fmt.Errorf("serializing initial list: %w", err) - } - defer os.RemoveAll(tmp) - - // Drop our image index in there. - if err := os.Mkdir(filepath.Join(tmp, imgspecv1.ImageBlobsDir), 0o755); err != nil { - return nil, fmt.Errorf("creating directory for blobs: %w", err) - } - if err := os.Mkdir(filepath.Join(tmp, imgspecv1.ImageBlobsDir, listDigest.Algorithm().String()), 0o755); err != nil { - return nil, fmt.Errorf("creating directory for %s blobs: %w", listDigest.Algorithm().String(), err) - } - listFile := filepath.Join(tmp, imgspecv1.ImageBlobsDir, listDigest.Algorithm().String(), listDigest.Encoded()) - if err := os.WriteFile(listFile, listBytes, 0o644); err != nil { - return nil, fmt.Errorf("writing image index for OCI layout: %w", err) - } - - // Build the index for the layout. - index := imgspecv1.Index{ - Versioned: imgspec.Versioned{ - SchemaVersion: 2, - }, - MediaType: imgspecv1.MediaTypeImageIndex, - Manifests: []imgspecv1.Descriptor{{ - MediaType: imgspecv1.MediaTypeImageIndex, - Digest: listDigest, - Size: int64(len(listBytes)), - }}, - } - indexBytes, err := json.Marshal(&index) - if err != nil { - return nil, fmt.Errorf("encoding image index for OCI layout: %w", err) - } - - // Write the index for the layout. - indexFile := filepath.Join(tmp, imgspecv1.ImageIndexFile) - if err := os.WriteFile(indexFile, indexBytes, 0o644); err != nil { - return nil, fmt.Errorf("writing top-level index for OCI layout: %w", err) - } - - // Write the "why yes, this is an OCI layout" file. - layoutFile := filepath.Join(tmp, imgspecv1.ImageLayoutFile) - layoutBytes, err := json.Marshal(imgspecv1.ImageLayout{Version: imgspecv1.ImageLayoutVersion}) - if err != nil { - return nil, fmt.Errorf("encoding image layout structure for OCI layout: %w", err) - } - if err := os.WriteFile(layoutFile, layoutBytes, 0o644); err != nil { - return nil, fmt.Errorf("writing oci-layout file: %w", err) - } - - // Build an OCI layout reference to use as a source. - tmpRef, err := layout.NewReference(tmp, "") - if err != nil { - return nil, fmt.Errorf("creating reference to directory: %w", err) - } - bundle := supplemented.Reference(tmpRef, []types.ImageReference{i.storageReference}, imageCopy.CopySystemImage, nil) - - // Build a policy that ensures we don't prevent ourselves from reading - // this reference. - signaturePolicy, err := signature.DefaultPolicy(&i.runtime.systemContext) - if err != nil { - return nil, fmt.Errorf("obtaining default signature policy: %w", err) - } - acceptAnything := signature.PolicyTransportScopes{ - "": []signature.PolicyRequirement{signature.NewPRInsecureAcceptAnything()}, - } - signaturePolicy.Transports[i.storageReference.Transport().Name()] = acceptAnything - signaturePolicy.Transports[tmpRef.Transport().Name()] = acceptAnything - policyContext, err := signature.NewPolicyContext(signaturePolicy) - if err != nil { - return nil, fmt.Errorf("creating new signature policy context: %w", err) - } - defer func() { - if err2 := policyContext.Destroy(); err2 != nil { - logrus.Errorf("Destroying signature policy context: %v", err2) - } - }() - - // Copy from the OCI layout into the same image record, so that it gets - // both its own manifest and the image index. - copyOptions := imageCopy.Options{ - ForceManifestMIMEType: imageManifestType, - } - if _, err := imageCopy.Image(ctx, policyContext, i.storageReference, bundle, ©Options); err != nil { - return nil, fmt.Errorf("writing updates to image: %w", err) - } - - // Now explicitly write the list's manifest to the image as its "main" - // manifest. - if _, err := list.SaveToImage(i.runtime.store, i.ID(), i.storageImage.Names, preferredListType); err != nil { - return nil, fmt.Errorf("saving image index: %w", err) - } - - // Reload the record. - if err = i.reload(); err != nil { - return nil, fmt.Errorf("reloading image record: %w", err) - } - mList, err := i.runtime.LookupManifestList(i.storageImage.ID) - if err != nil { - return nil, fmt.Errorf("looking up new manifest list: %w", err) - } - - return mList, nil -} - // ToManifestList converts the image into a manifest list. An error is thrown -// if the image is not a manifest list. +// if the image is no manifest list. func (i *Image) ToManifestList() (*ManifestList, error) { list, err := i.getManifestList() if err != nil { @@ -296,7 +139,7 @@ func (m *ManifestList) LookupInstance(ctx context.Context, architecture, os, var return nil, err } - allImages, err := m.image.runtime.ListImages(ctx, nil) + allImages, err := m.image.runtime.ListImages(ctx, nil, nil) if err != nil { return nil, err } @@ -351,9 +194,6 @@ func (m *ManifestList) reload() error { // getManifestList is a helper to obtain a manifest list func (i *Image) getManifestList() (manifests.List, error) { _, list, err := manifests.LoadFromImage(i.runtime.store, i.ID()) - if errors.Is(err, manifesterrors.ErrManifestTypeNotSupported) { - err = fmt.Errorf("%s: %w", err.Error(), ErrNotAManifestList) - } return list, err } @@ -796,7 +636,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma if err != nil { return "", err } - defer copier.Close() + defer copier.close() pushOptions := manifests.PushOptions{ AddCompression: options.AddCompression, diff --git a/vendor/github.com/containers/common/libimage/manifests/manifests.go b/vendor/github.com/containers/common/libimage/manifests/manifests.go index 50c32569ac..a1625bb1bf 100644 --- a/vendor/github.com/containers/common/libimage/manifests/manifests.go +++ b/vendor/github.com/containers/common/libimage/manifests/manifests.go @@ -342,7 +342,8 @@ func (l *list) Reference(store storage.Store, multiple cp.ImageListSelection, in } } // write the index that refers to this one artifact image - indexFile := filepath.Join(tmp, v1.ImageIndexFile) + tag := "latest" + indexFile := filepath.Join(tmp, "index.json") index := v1.Index{ Versioned: imgspec.Versioned{ SchemaVersion: 2, @@ -352,6 +353,9 @@ func (l *list) Reference(store storage.Store, multiple cp.ImageListSelection, in MediaType: v1.MediaTypeImageManifest, Digest: artifactManifestDigest, Size: int64(len(contents)), + Annotations: map[string]string{ + v1.AnnotationRefName: tag, + }, }}, } indexBytes, err := json.Marshal(&index) @@ -362,16 +366,12 @@ func (l *list) Reference(store storage.Store, multiple cp.ImageListSelection, in return nil, fmt.Errorf("writing image index for OCI layout: %w", err) } // write the layout file - layoutFile := filepath.Join(tmp, v1.ImageLayoutFile) - layoutBytes, err := json.Marshal(v1.ImageLayout{Version: v1.ImageLayoutVersion}) - if err != nil { - return nil, fmt.Errorf("encoding image layout for OCI layout: %w", err) - } - if err := os.WriteFile(layoutFile, layoutBytes, 0o644); err != nil { + layoutFile := filepath.Join(tmp, "oci-layout") + if err := os.WriteFile(layoutFile, []byte(`{"imageLayoutVersion": "1.0.0"}`), 0o644); err != nil { return nil, fmt.Errorf("writing oci-layout file: %w", err) } // build the reference to this artifact image's oci layout - ref, err := ocilayout.NewReference(tmp, "") + ref, err := ocilayout.NewReference(tmp, tag) if err != nil { return nil, fmt.Errorf("creating ImageReference for artifact with files %q: %w", symlinkedFiles, err) } @@ -676,14 +676,14 @@ func (l *list) Add(ctx context.Context, sys *types.SystemContext, ref types.Imag // This should provide for all of the ways to construct a manifest outlined in // https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidelines-for-artifact-usage -// - no blobs → set ManifestArtifactType -// - blobs, no configuration → set ManifestArtifactType and possibly LayerMediaType, and provide file names -// - blobs and configuration → set ManifestArtifactType, possibly LayerMediaType, and ConfigDescriptor, and provide file names +// * no blobs → set ManifestArtifactType +// * blobs, no configuration → set ManifestArtifactType and possibly LayerMediaType, and provide file names +// * blobs and configuration → set ManifestArtifactType, possibly LayerMediaType, and ConfigDescriptor, and provide file names // // The older style of describing artifacts: -// - leave ManifestArtifactType blank -// - specify a zero-length application/vnd.oci.image.config.v1+json config blob -// - set LayerMediaType to a custom type +// * leave ManifestArtifactType blank +// * specify a zero-length application/vnd.oci.image.config.v1+json config blob +// * set LayerMediaType to a custom type // // When reading data produced elsewhere, note that newer tooling will produce // manifests with ArtifactType set. If the manifest's ArtifactType is not set, diff --git a/vendor/github.com/containers/common/libimage/platform/platform.go b/vendor/github.com/containers/common/libimage/platform/platform.go index 54c3b8deb4..2272cee757 100644 --- a/vendor/github.com/containers/common/libimage/platform/platform.go +++ b/vendor/github.com/containers/common/libimage/platform/platform.go @@ -4,7 +4,7 @@ import ( "fmt" "runtime" - "github.com/containerd/platforms" + "github.com/containerd/containerd/platforms" v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" ) diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go index c4ad5df0c7..3db1b2992b 100644 --- a/vendor/github.com/containers/common/libimage/pull.go +++ b/vendor/github.com/containers/common/libimage/pull.go @@ -235,7 +235,7 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, if err != nil { return nil, err } - defer c.Close() + defer c.close() // Figure out a name for the storage destination. var storageName, imageName string @@ -321,7 +321,7 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, return nil, fmt.Errorf("parsing %q: %w", storageName, err) } - _, err = c.Copy(ctx, ref, destRef) + _, err = c.copy(ctx, ref, destRef) return []string{imageName}, err } @@ -391,7 +391,7 @@ func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, read if err != nil { return nil, err } - defer c.Close() + defer c.close() // Get a slice of storage references we can copy. references, destNames, err := r.storageReferencesReferencesFromArchiveReader(ctx, readerRef, reader) @@ -401,7 +401,7 @@ func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, read // Now copy all of the images. Use readerRef for performance. for _, destRef := range references { - if _, err := c.Copy(ctx, readerRef, destRef); err != nil { + if _, err := c.copy(ctx, readerRef, destRef); err != nil { return nil, err } } @@ -640,7 +640,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str if err != nil { return nil, err } - defer c.Close() + defer c.close() var pullErrors []error for _, candidate := range resolved.PullCandidates { @@ -678,7 +678,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str } } var manifestBytes []byte - if manifestBytes, err = c.Copy(ctx, srcRef, destRef); err != nil { + if manifestBytes, err = c.copy(ctx, srcRef, destRef); err != nil { logrus.Debugf("Error pulling candidate %s: %v", candidateString, err) pullErrors = append(pullErrors, err) continue diff --git a/vendor/github.com/containers/common/libimage/push.go b/vendor/github.com/containers/common/libimage/push.go index 5db6cfbcfe..f89b8fc070 100644 --- a/vendor/github.com/containers/common/libimage/push.go +++ b/vendor/github.com/containers/common/libimage/push.go @@ -114,7 +114,7 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options return nil, err } - defer c.Close() + defer c.close() - return c.Copy(ctx, srcRef, destRef) + return c.copy(ctx, srcRef, destRef) } diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index f7c9b2bf97..1baf41d5d2 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -161,23 +161,6 @@ func (r *Runtime) storageToImage(storageImage *storage.Image, ref types.ImageRef } } -// getImagesAndLayers obtains consistent slices of Image and storage.Layer -func (r *Runtime) getImagesAndLayers() ([]*Image, []storage.Layer, error) { - snapshot, err := r.store.MultiList( - storage.MultiListOptions{ - Images: true, - Layers: true, - }) - if err != nil { - return nil, nil, err - } - images := []*Image{} - for i := range snapshot.Images { - images = append(images, r.storageToImage(&snapshot.Images[i], nil)) - } - return images, snapshot.Layers, nil -} - // Exists returns true if the specified image exists in the local containers // storage. Note that it may return false if an image corrupted. func (r *Runtime) Exists(name string) (bool, error) { @@ -496,7 +479,7 @@ func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, possiblyUnqualifi return nil, "", fmt.Errorf("%s: %w (could not cast to tagged)", originalName, storage.ErrImageUnknown) } - allImages, err := r.ListImages(context.Background(), nil) + allImages, err := r.ListImages(context.Background(), nil, nil) if err != nil { return nil, "", err } @@ -584,46 +567,39 @@ type ListImagesOptions struct { SetListData bool } -// ListImagesByNames lists the images in the local container storage by specified names -// The name lookups use the LookupImage semantics. -func (r *Runtime) ListImagesByNames(names []string) ([]*Image, error) { - images := []*Image{} - for _, name := range names { - image, _, err := r.LookupImage(name, nil) - if err != nil { - return nil, err - } - images = append(images, image) - } - return images, nil -} - -// ListImages lists the images in the local container storage and filter the images by ListImagesOptions -func (r *Runtime) ListImages(ctx context.Context, options *ListImagesOptions) ([]*Image, error) { +// ListImages lists images in the local container storage. If names are +// specified, only images with the specified names are looked up and filtered. +func (r *Runtime) ListImages(ctx context.Context, names []string, options *ListImagesOptions) ([]*Image, error) { if options == nil { options = &ListImagesOptions{} } - filters, needsLayerTree, err := r.compileImageFilters(ctx, options) - if err != nil { - return nil, err - } - - if options.SetListData { - needsLayerTree = true + var images []*Image + if len(names) > 0 { + for _, name := range names { + image, _, err := r.LookupImage(name, nil) + if err != nil { + return nil, err + } + images = append(images, image) + } + } else { + storageImages, err := r.store.Images() + if err != nil { + return nil, err + } + for i := range storageImages { + images = append(images, r.storageToImage(&storageImages[i], nil)) + } } - snapshot, err := r.store.MultiList( - storage.MultiListOptions{ - Images: true, - Layers: needsLayerTree, - }) + filtered, err := r.filterImages(ctx, images, options) if err != nil { return nil, err } - images := []*Image{} - for i := range snapshot.Images { - images = append(images, r.storageToImage(&snapshot.Images[i], nil)) + + if !options.SetListData { + return filtered, nil } // If explicitly requested by the user, pre-compute and cache the @@ -632,23 +608,11 @@ func (r *Runtime) ListImages(ctx context.Context, options *ListImagesOptions) ([ // as the layer tree will computed once for all instead of once for // each individual image (see containers/podman/issues/17828). - var tree *layerTree - if needsLayerTree { - tree, err = r.newLayerTreeFromData(images, snapshot.Layers) - if err != nil { - return nil, err - } - } - - filtered, err := r.filterImages(ctx, images, filters, tree) + tree, err := r.layerTree(ctx, images) if err != nil { return nil, err } - if !options.SetListData { - return filtered, nil - } - for i := range filtered { isDangling, err := filtered[i].isDangling(ctx, tree) if err != nil { @@ -789,7 +753,7 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem IsExternalContainerFunc: options.IsExternalContainerFunc, Filters: options.Filters, } - filteredImages, err := r.ListImages(ctx, options) + filteredImages, err := r.ListImages(ctx, nil, options) if err != nil { appendError(err) return nil, rmErrors diff --git a/vendor/github.com/containers/common/libimage/save.go b/vendor/github.com/containers/common/libimage/save.go index 46529d10f3..62cad3288d 100644 --- a/vendor/github.com/containers/common/libimage/save.go +++ b/vendor/github.com/containers/common/libimage/save.go @@ -123,9 +123,9 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string if err != nil { return err } - defer c.Close() + defer c.close() - _, err = c.Copy(ctx, srcRef, destRef) + _, err = c.copy(ctx, srcRef, destRef) return err } @@ -208,7 +208,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st if err != nil { return err } - defer c.Close() + defer c.close() destRef, err := writer.NewReference(nil) if err != nil { @@ -220,7 +220,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st return err } - if _, err := c.Copy(ctx, srcRef, destRef); err != nil { + if _, err := c.copy(ctx, srcRef, destRef); err != nil { return err } } diff --git a/vendor/github.com/containers/common/libimage/search.go b/vendor/github.com/containers/common/libimage/search.go index 6ab016b3b5..b26ad80d26 100644 --- a/vendor/github.com/containers/common/libimage/search.go +++ b/vendor/github.com/containers/common/libimage/search.go @@ -215,7 +215,7 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri } paramsArr := []SearchResult{} - for i := range limit { + for i := 0; i < limit; i++ { // Check whether query matches filters if !(filterMatchesAutomatedFilter(&options.Filter, results[i]) && filterMatchesOfficialFilter(&options.Filter, results[i]) && filterMatchesStarFilter(&options.Filter, results[i])) { continue @@ -275,7 +275,7 @@ func searchRepositoryTags(ctx context.Context, sys *types.SystemContext, registr } } paramsArr := []SearchResult{} - for i := range limit { + for i := 0; i < limit; i++ { params := SearchResult{ Name: imageRef.DockerReference().Name(), Tag: tags[i], diff --git a/vendor/github.com/containers/common/libnetwork/cni/run.go b/vendor/github.com/containers/common/libnetwork/cni/run.go index 68a42945c0..337a27b8ef 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/run.go +++ b/vendor/github.com/containers/common/libnetwork/cni/run.go @@ -62,6 +62,7 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma } for name, netOpts := range options.Networks { + netOpts := netOpts network := n.networks[name] rt := getRuntimeConfig(namespacePath, options.ContainerName, options.ContainerID, name, ports, &netOpts) @@ -236,6 +237,7 @@ func (n *cniNetwork) teardown(namespacePath string, options types.TeardownOption var multiErr *multierror.Error teardown := func() error { for name, netOpts := range options.Networks { + netOpts := netOpts rt := getRuntimeConfig(namespacePath, options.ContainerName, options.ContainerID, name, ports, &netOpts) cniConfList, newRt, err := getCachedNetworkConfig(n.cniConf, name, rt) diff --git a/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go b/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go index 8a7cc534e6..7ca62137b2 100644 --- a/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go +++ b/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go @@ -229,10 +229,9 @@ func checkIfEntryExists(current HostEntry, entries HostEntries) bool { return false } -// parseExtraHosts converts a slice of "name1;name2;name3:ip" string to entries. -// Each entry can contain one or more hostnames separated by semicolons and an IP address separated by a colon. -// Because podman and buildah both store the extra hosts in this format, -// we convert it here instead of having to do this on the caller side. +// parseExtraHosts converts a slice of "name:ip" string to entries. +// Because podman and buildah both store the extra hosts in this format +// we convert it here instead of having to this on the caller side. func parseExtraHosts(extraHosts []string, hostContainersInternalIP string) (HostEntries, error) { entries := make(HostEntries, 0, len(extraHosts)) for _, entry := range extraHosts { @@ -253,8 +252,7 @@ func parseExtraHosts(extraHosts []string, hostContainersInternalIP string) (Host } ip = hostContainersInternalIP } - names := strings.Split(values[0], ";") - e := HostEntry{IP: ip, Names: names} + e := HostEntry{IP: ip, Names: []string{values[0]}} entries = append(entries, e) } return entries, nil diff --git a/vendor/github.com/containers/common/libnetwork/etchosts/ip.go b/vendor/github.com/containers/common/libnetwork/etchosts/ip.go index 588fbff352..909fcf67d2 100644 --- a/vendor/github.com/containers/common/libnetwork/etchosts/ip.go +++ b/vendor/github.com/containers/common/libnetwork/etchosts/ip.go @@ -10,27 +10,17 @@ import ( "github.com/containers/storage/pkg/unshare" ) -// HostContainersInternalOptions contains the options for GetHostContainersInternalIP() -type HostContainersInternalOptions struct { - // Conf is the containers.Conf, must not be nil - Conf *config.Config - // NetStatus is the network status for the container, - // if this is set networkInterface must not be nil - NetStatus map[string]types.StatusBlock - // NetworkInterface of the current runtime - NetworkInterface types.ContainerNetwork - // Exclude are then ips that should not be returned, this is - // useful to prevent returning the same ip as in the container. - Exclude []net.IP - // PreferIP is a ip that should be used if set but it has a - // lower priority than the containers.conf config option. - // This is used for the pasta --map-guest-addr ip. - PreferIP string +// GetHostContainersInternalIP returns the host.containers.internal ip +// if netStatus is not nil then networkInterface also must be non nil otherwise this function panics +func GetHostContainersInternalIP(conf *config.Config, netStatus map[string]types.StatusBlock, networkInterface types.ContainerNetwork) string { + return GetHostContainersInternalIPExcluding(conf, netStatus, networkInterface, nil) } -// GetHostContainersInternalIP returns the host.containers.internal ip -func GetHostContainersInternalIP(opts HostContainersInternalOptions) string { - switch opts.Conf.Containers.HostContainersInternalIP { +// GetHostContainersInternalIPExcluding returns the host.containers.internal ip +// Exclude are ips that should not be returned, this is useful to prevent returning the same ip as in the container. +// if netStatus is not nil then networkInterface also must be non nil otherwise this function panics +func GetHostContainersInternalIPExcluding(conf *config.Config, netStatus map[string]types.StatusBlock, networkInterface types.ContainerNetwork, exclude []net.IP) string { + switch conf.Containers.HostContainersInternalIP { case "": // if empty (default) we will automatically choose one below // if machine using gvproxy we let the gvproxy dns server handle the dns name so do not add it @@ -40,22 +30,16 @@ func GetHostContainersInternalIP(opts HostContainersInternalOptions) string { case "none": return "" default: - return opts.Conf.Containers.HostContainersInternalIP - } - - // caller has a specific ip it prefers - if opts.PreferIP != "" { - return opts.PreferIP + return conf.Containers.HostContainersInternalIP } - ip := "" // Only use the bridge ip when root, as rootless the interfaces are created // inside the special netns and not the host so we cannot use them. if unshare.IsRootless() { - return util.GetLocalIPExcluding(opts.Exclude) + return util.GetLocalIPExcluding(exclude) } - for net, status := range opts.NetStatus { - network, err := opts.NetworkInterface.NetworkInspect(net) + for net, status := range netStatus { + network, err := networkInterface.NetworkInspect(net) // only add the host entry for bridge networks // ip/macvlan gateway is normally not on the host if err != nil || network.Driver != types.BridgeNetworkDriver { @@ -76,19 +60,7 @@ func GetHostContainersInternalIP(opts HostContainersInternalOptions) string { if ip != "" { return ip } - return util.GetLocalIPExcluding(opts.Exclude) -} - -// GetHostContainersInternalIPExcluding returns the host.containers.internal ip -// Exclude are ips that should not be returned, this is useful to prevent returning the same ip as in the container. -// if netStatus is not nil then networkInterface also must be non nil otherwise this function panics -func GetHostContainersInternalIPExcluding(conf *config.Config, netStatus map[string]types.StatusBlock, networkInterface types.ContainerNetwork, exclude []net.IP) string { - return GetHostContainersInternalIP(HostContainersInternalOptions{ - Conf: conf, - NetStatus: netStatus, - NetworkInterface: networkInterface, - Exclude: exclude, - }) + return util.GetLocalIPExcluding(exclude) } // GetNetworkHostEntries returns HostEntries for all ips in the network status diff --git a/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go b/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go index 84bc4f621a..f8b9b76dfd 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go +++ b/vendor/github.com/containers/common/libnetwork/internal/rootlessnetns/netns_linux.go @@ -1,7 +1,6 @@ package rootlessnetns import ( - "encoding/json" "errors" "fmt" "io/fs" @@ -35,9 +34,6 @@ const ( // refCountFile file name for the ref count file refCountFile = "ref-count" - // infoCacheFile file name for the cache file used to store the rootless netns info - infoCacheFile = "info.json" - // rootlessNetNsConnPidFile is the name of the rootless netns slirp4netns/pasta pid file rootlessNetNsConnPidFile = "rootless-netns-conn.pid" @@ -58,9 +54,11 @@ type Netns struct { // config contains containers.conf options. config *config.Config - // info contain information about ip addresses used in the netns. - // A caller can get this info via Info(). - info *types.RootlessNetnsInfo + // ipAddresses used in the netns, this is needed to store + // the netns ips that are used by pasta. This is then handed + // back to the caller via IPAddresses() which then can make + // sure to not use them for host.containers.internal. + ipAddresses []net.IP } type rootlessNetnsError struct { @@ -117,9 +115,6 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) { // quick check if pasta/slirp4netns are still running err := unix.Kill(pid, 0) if err == nil { - if err := n.deserializeInfo(); err != nil { - return nil, false, wrapError("deserialize info", err) - } // All good, return the netns. return nsRef, false, nil } @@ -232,15 +227,6 @@ func (n *Netns) setupPasta(nsPath string) error { return wrapError("create resolv.conf", err) } - n.info = &types.RootlessNetnsInfo{ - IPAddresses: res.IPAddresses, - DnsForwardIps: res.DNSForwardIPs, - MapGuestIps: res.MapGuestAddrIPs, - } - if err := n.serializeInfo(); err != nil { - return wrapError("serialize info", err) - } - return nil } @@ -275,12 +261,6 @@ func (n *Netns) setupSlirp4netns(nsPath string) error { if err != nil { return wrapError("determine default slirp4netns DNS address", err) } - nameservers := []string{resolveIP.String()} - - netnsIP, err := slirp4netns.GetIP(res.Subnet) - if err != nil { - return wrapError("determine default slirp4netns ip address", err) - } if err := resolvconf.New(&resolvconf.Params{ Path: n.getPath(resolvConfName), @@ -290,19 +270,10 @@ func (n *Netns) setupSlirp4netns(nsPath string) error { }, IPv6Enabled: res.IPv6, KeepHostServers: true, - Nameservers: nameservers, + Nameservers: []string{resolveIP.String()}, }); err != nil { return wrapError("create resolv.conf", err) } - - n.info = &types.RootlessNetnsInfo{ - IPAddresses: []net.IP{*netnsIP}, - DnsForwardIps: nameservers, - } - if err := n.serializeInfo(); err != nil { - return wrapError("serialize info", err) - } - return nil } @@ -570,6 +541,20 @@ func (n *Netns) runInner(toRun func() error, cleanup bool) (err error) { if err := toRun(); err != nil { return err } + + // get the current active addresses in the netns, and store them + addrs, err := net.InterfaceAddrs() + if err != nil { + return err + } + ips := make([]net.IP, 0, len(addrs)) + for _, addr := range addrs { + // make sure to skip localhost and other special addresses + if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { + ips = append(ips, ipnet.IP) + } + } + n.ipAddresses = ips return nil }) } @@ -645,7 +630,9 @@ func (n *Netns) Run(lock *lockfile.LockFile, toRun func() error) error { // IPAddresses returns the currently used ip addresses in the netns // These should then not be assigned for the host.containers.internal entry. func (n *Netns) Info() *types.RootlessNetnsInfo { - return n.info + return &types.RootlessNetnsInfo{ + IPAddresses: n.ipAddresses, + } } func refCount(dir string, inc int) (int, error) { @@ -684,26 +671,3 @@ func readPidFile(path string) (int, error) { } return strconv.Atoi(strings.TrimSpace(string(b))) } - -func (n *Netns) serializeInfo() error { - f, err := os.Create(filepath.Join(n.dir, infoCacheFile)) - if err != nil { - return err - } - return json.NewEncoder(f).Encode(n.info) -} - -func (n *Netns) deserializeInfo() error { - f, err := os.Open(filepath.Join(n.dir, infoCacheFile)) - if err != nil { - if errors.Is(err, fs.ErrNotExist) { - return nil - } - return err - } - defer f.Close() - if n.info == nil { - n.info = new(types.RootlessNetnsInfo) - } - return json.NewDecoder(f).Decode(n.info) -} diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/util.go b/vendor/github.com/containers/common/libnetwork/internal/util/util.go index 260e74d06e..96c21e76f6 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/util/util.go +++ b/vendor/github.com/containers/common/libnetwork/internal/util/util.go @@ -112,7 +112,7 @@ func GetFreeIPv4NetworkSubnet(usedNetworks []*net.IPNet, subnetPools []config.Su // GetFreeIPv6NetworkSubnet returns a unused ipv6 subnet func GetFreeIPv6NetworkSubnet(usedNetworks []*net.IPNet) (*types.Subnet, error) { // FIXME: Is 10000 fine as limit? We should prevent an endless loop. - for range 10000 { + for i := 0; i < 10000; i++ { // RFC4193: Choose the ipv6 subnet random and NOT sequentially. network, err := getRandomIPv6Subnet() if err != nil { diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/validate.go b/vendor/github.com/containers/common/libnetwork/internal/util/validate.go index ddc778a5fe..55995440e4 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/util/validate.go +++ b/vendor/github.com/containers/common/libnetwork/internal/util/validate.go @@ -129,6 +129,7 @@ func ValidateSetupOptions(n NetUtil, namespacePath string, options types.SetupOp return errors.New("must specify at least one network") } for name, netOpts := range options.Networks { + netOpts := netOpts network, err := n.Network(name) if err != nil { return err diff --git a/vendor/github.com/containers/common/libnetwork/netavark/config.go b/vendor/github.com/containers/common/libnetwork/netavark/config.go index 8b43a787e4..842c7e3122 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/config.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/config.go @@ -126,7 +126,7 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo // generate random network ID var i int - for i = range 1000 { + for i = 0; i < 1000; i++ { id := stringid.GenerateNonCryptoID() if _, err := n.getNetwork(id); err != nil { newNetwork.ID = id diff --git a/vendor/github.com/containers/common/libnetwork/network/interface_cni.go b/vendor/github.com/containers/common/libnetwork/network/interface_cni.go index 3de3a3045e..0a8bc44724 100644 --- a/vendor/github.com/containers/common/libnetwork/network/interface_cni.go +++ b/vendor/github.com/containers/common/libnetwork/network/interface_cni.go @@ -1,4 +1,6 @@ //go:build (linux || freebsd) && cni +// +build linux freebsd +// +build cni package network diff --git a/vendor/github.com/containers/common/libnetwork/network/interface_cni_unsupported.go b/vendor/github.com/containers/common/libnetwork/network/interface_cni_unsupported.go index d0645dc506..2f4bb83718 100644 --- a/vendor/github.com/containers/common/libnetwork/network/interface_cni_unsupported.go +++ b/vendor/github.com/containers/common/libnetwork/network/interface_cni_unsupported.go @@ -1,4 +1,6 @@ //go:build (linux || freebsd) && !cni +// +build linux freebsd +// +build !cni package network diff --git a/vendor/github.com/containers/common/libnetwork/pasta/pasta_linux.go b/vendor/github.com/containers/common/libnetwork/pasta/pasta_linux.go index 10b667eb6c..fd68f87f27 100644 --- a/vendor/github.com/containers/common/libnetwork/pasta/pasta_linux.go +++ b/vendor/github.com/containers/common/libnetwork/pasta/pasta_linux.go @@ -26,16 +26,11 @@ import ( ) const ( - dnsForwardOpt = "--dns-forward" - mapGuestAddrOpt = "--map-guest-addr" + dnsForwardOpt = "--dns-forward" // dnsForwardIpv4 static ip used as nameserver address inside the netns, // given this is a "link local" ip it should be very unlikely that it causes conflicts - dnsForwardIpv4 = "169.254.1.1" - - // mapGuestAddrIpv4 static ip used as forwarder address inside the netns to reach the host, - // given this is a "link local" ip it should be very unlikely that it causes conflicts - mapGuestAddrIpv4 = "169.254.1.2" + dnsForwardIpv4 = "169.254.0.1" ) type SetupOptions struct { @@ -50,61 +45,45 @@ type SetupOptions struct { ExtraOptions []string } -// Setup2 alias for Setup() -func Setup2(opts *SetupOptions) (*SetupResult, error) { - return Setup(opts) +func Setup(opts *SetupOptions) error { + _, err := Setup2(opts) + return err } -// Setup start the pasta process for the given netns. +// Setup2 start the pasta process for the given netns. // The pasta binary is looked up in the HelperBinariesDir and $PATH. // Note that there is no need for any special cleanup logic, the pasta // process will automatically exit when the netns path is deleted. -func Setup(opts *SetupOptions) (*SetupResult, error) { +func Setup2(opts *SetupOptions) (*SetupResult, error) { path, err := opts.Config.FindHelperBinary(BinaryName, true) if err != nil { return nil, fmt.Errorf("could not find pasta, the network namespace can't be configured: %w", err) } - cmdArgs, dnsForwardIPs, mapGuestAddrIPs, err := createPastaArgs(opts) + cmdArgs, dnsForwardIPs, err := createPastaArgs(opts) if err != nil { return nil, err } logrus.Debugf("pasta arguments: %s", strings.Join(cmdArgs, " ")) - for { - // pasta forks once ready, and quits once we delete the target namespace - out, err := exec.Command(path, cmdArgs...).CombinedOutput() - if err != nil { - exitErr := &exec.ExitError{} - if errors.As(err, &exitErr) { - // special backwards compat check, --map-guest-addr was added in pasta version 20240814 so we - // cannot hard require it yet. Once we are confident that the update is most distros we can remove it. - if exitErr.ExitCode() == 1 && - strings.Contains(string(out), "unrecognized option '"+mapGuestAddrOpt) && - len(mapGuestAddrIPs) == 1 && mapGuestAddrIPs[0] == mapGuestAddrIpv4 { - // we did add the default --map-guest-addr option, if users set something different we want - // to get to the error below. We have to unset mapGuestAddrIPs here to avoid a infinite loop. - mapGuestAddrIPs = nil - // Trim off last two args which are --map-guest-addr 169.254.1.2. - cmdArgs = cmdArgs[:len(cmdArgs)-2] - continue - } - return nil, fmt.Errorf("pasta failed with exit code %d:\n%s", - exitErr.ExitCode(), string(out)) - } - return nil, fmt.Errorf("failed to start pasta: %w", err) + // pasta forks once ready, and quits once we delete the target namespace + out, err := exec.Command(path, cmdArgs...).CombinedOutput() + if err != nil { + exitErr := &exec.ExitError{} + if errors.As(err, &exitErr) { + return nil, fmt.Errorf("pasta failed with exit code %d:\n%s", + exitErr.ExitCode(), string(out)) } + return nil, fmt.Errorf("failed to start pasta: %w", err) + } - if len(out) > 0 { - // TODO: This should be warning but as of August 2024 pasta still prints - // things with --quiet that we do not care about. In podman CI I still see - // "Couldn't get any nameserver address" so until this is fixed we cannot - // enable it. For now info is fine and we can bump it up later, it is only a - // nice to have. - logrus.Infof("pasta logged warnings: %q", strings.TrimSpace(string(out))) - } - break + if len(out) > 0 { + // TODO: This should be warning but right now pasta still prints + // things with --quiet that we do not care about. + // For now info is fine and we can bump it up later, it is only a + // nice to have. + logrus.Infof("pasta logged warnings: %q", string(out)) } var ipv4, ipv6 bool @@ -133,27 +112,19 @@ func Setup(opts *SetupOptions) (*SetupResult, error) { } result.IPv6 = ipv6 - result.DNSForwardIPs = filterIpFamily(dnsForwardIPs, ipv4, ipv6) - result.MapGuestAddrIPs = filterIpFamily(mapGuestAddrIPs, ipv4, ipv6) - - return result, nil -} - -func filterIpFamily(ips []string, ipv4, ipv6 bool) []string { - var result []string - for _, ip := range ips { + for _, ip := range dnsForwardIPs { ipp := net.ParseIP(ip) - // add the ip only if the address family matches + // add the namesever ip only if the address family matches if ipv4 && util.IsIPv4(ipp) || ipv6 && util.IsIPv6(ipp) { - result = append(result, ip) + result.DNSForwardIPs = append(result.DNSForwardIPs, ip) } } - return result + + return result, nil } -// createPastaArgs creates the pasta arguments, it returns the args to be passed to pasta(1) -// and as second arg the dns forward ips used. As third arg the map guest addr ips used. -func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) { +// createPastaArgs creates the pasta arguments, it returns the args to be passed to pasta(1) and as second arg the dns forward ips used. +func createPastaArgs(opts *SetupOptions) ([]string, []string, error) { noTCPInitPorts := true noUDPInitPorts := true noTCPNamespacePorts := true @@ -178,7 +149,6 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) { }) var dnsForwardIPs []string - var mapGuestAddrIPs []string for i, opt := range cmdArgs { switch opt { case "-t", "--tcp-ports": @@ -196,10 +166,6 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) { if len(cmdArgs) > i+1 { dnsForwardIPs = append(dnsForwardIPs, cmdArgs[i+1]) } - case mapGuestAddrOpt: - if len(cmdArgs) > i+1 { - mapGuestAddrIPs = append(mapGuestAddrIPs, cmdArgs[i+1]) - } } } @@ -220,7 +186,7 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) { noUDPInitPorts = false cmdArgs = append(cmdArgs, "-u") default: - return nil, nil, nil, fmt.Errorf("can't forward protocol: %s", protocol) + return nil, nil, fmt.Errorf("can't forward protocol: %s", protocol) } arg := fmt.Sprintf("%s%d-%d:%d-%d", addr, @@ -260,13 +226,5 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) { cmdArgs = append(cmdArgs, "--netns", opts.Netns) - // do this as last arg so we can easily trim them off in the error case when we have an older version - if len(mapGuestAddrIPs) == 0 { - // the user did not request custom --map-guest-addr so add our own so that we can use this - // for our own host.containers.internal host entry. - cmdArgs = append(cmdArgs, mapGuestAddrOpt, mapGuestAddrIpv4) - mapGuestAddrIPs = append(mapGuestAddrIPs, mapGuestAddrIpv4) - } - - return cmdArgs, dnsForwardIPs, mapGuestAddrIPs, nil + return cmdArgs, dnsForwardIPs, nil } diff --git a/vendor/github.com/containers/common/libnetwork/pasta/types.go b/vendor/github.com/containers/common/libnetwork/pasta/types.go index f570afc3e5..b601e51695 100644 --- a/vendor/github.com/containers/common/libnetwork/pasta/types.go +++ b/vendor/github.com/containers/common/libnetwork/pasta/types.go @@ -10,9 +10,6 @@ type SetupResult struct { // DNSForwardIP is the ip used in --dns-forward, it should be added as first // entry to resolv.conf in the container. DNSForwardIPs []string - // MapGuestIps are the ips used for the --map-guest-addr option which - // we can use for the host.containers.internal entry. - MapGuestAddrIPs []string // IPv6 says whenever pasta run with ipv6 support IPv6 bool } diff --git a/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go b/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go index 9721750abf..6f713431c8 100644 --- a/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go +++ b/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go @@ -645,7 +645,7 @@ func setupRootlessPortMappingViaSlirp(ports []types.PortMapping, cmd *exec.Cmd, if hostIP == "" { hostIP = "0.0.0.0" } - for i := range port.Range { + for i := uint16(0); i < port.Range; i++ { if err := openSlirp4netnsPort(apiSocket, protocol, hostIP, port.HostPort+i, port.ContainerPort+i); err != nil { return err } diff --git a/vendor/github.com/containers/common/libnetwork/types/network.go b/vendor/github.com/containers/common/libnetwork/types/network.go index 77c76bf787..9741103f5b 100644 --- a/vendor/github.com/containers/common/libnetwork/types/network.go +++ b/vendor/github.com/containers/common/libnetwork/types/network.go @@ -342,10 +342,6 @@ type TeardownOptions struct { type RootlessNetnsInfo struct { // IPAddresses used in the netns, must not be used for host.containers.internal IPAddresses []net.IP - // DnsForwardIps ips used in resolv.conf - DnsForwardIps []string - // MapGuestIps should be used for the host.containers.internal entry when set - MapGuestIps []string } // FilterFunc can be passed to NetworkList to filter the networks. diff --git a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go index 371fbba9a1..43fd2c1b58 100644 --- a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go +++ b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go @@ -9,13 +9,20 @@ import ( "errors" "fmt" "slices" + "sort" "strings" "sync" - "github.com/moby/sys/capability" + "github.com/syndtr/gocapability/capability" ) var ( + // Used internally and populated during init(). + capabilityList []string + + // Used internally and populated during init(). + capsList []capability.Cap + // ErrUnknownCapability is thrown when an unknown capability is processed. ErrUnknownCapability = errors.New("unknown capability") @@ -28,67 +35,67 @@ var ( // Useful on the CLI for `--cap-add=all` etc. const All = "ALL" -func capName(c capability.Cap) string { +func getCapName(c capability.Cap) string { return "CAP_" + strings.ToUpper(c.String()) } -// capStrList returns all capabilities supported by the currently running kernel, -// or an error if the list can not be obtained. -var capStrList = sync.OnceValues(func() ([]string, error) { - list, err := capability.ListSupported() - if err != nil { - return nil, err +func init() { + last := capability.CAP_LAST_CAP + // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap + if last == capability.Cap(63) { + last = capability.CAP_BLOCK_SUSPEND } - caps := make([]string, len(list)) - for i, c := range list { - caps[i] = capName(c) + for _, cap := range capability.List() { + if cap > last { + continue + } + capsList = append(capsList, cap) + capabilityList = append(capabilityList, getCapName(cap)) + sort.Strings(capabilityList) } - slices.Sort(caps) - return caps, nil -}) - -// BoundingSet returns the capabilities in the current bounding set. -func BoundingSet() ([]string, error) { - return boundingSet() } -var boundingSet = sync.OnceValues(func() ([]string, error) { - currentCaps, err := capability.NewPid2(0) - if err != nil { - return nil, err - } - err = currentCaps.Load() - if err != nil { - return nil, err - } - list, err := capability.ListSupported() - if err != nil { - return nil, err - } - var r []string - for _, c := range list { - if !currentCaps.Get(capability.BOUNDING, c) { - continue +var ( + boundingSetOnce sync.Once + boundingSetRet []string + boundingSetErr error +) + +// BoundingSet returns the capabilities in the current bounding set +func BoundingSet() ([]string, error) { + boundingSetOnce.Do(func() { + currentCaps, err := capability.NewPid2(0) + if err != nil { + boundingSetErr = err + return } - r = append(r, capName(c)) - } - slices.Sort(r) - return r, nil -}) + err = currentCaps.Load() + if err != nil { + boundingSetErr = err + return + } + var r []string + for _, c := range capsList { + if !currentCaps.Get(capability.BOUNDING, c) { + continue + } + r = append(r, getCapName(c)) + } + boundingSetRet = r + sort.Strings(boundingSetRet) + boundingSetErr = err + }) + return boundingSetRet, boundingSetErr +} -// AllCapabilities returns all capabilities supported by the running kernel. +// AllCapabilities returns all known capabilities. func AllCapabilities() []string { - list, _ := capStrList() - return list + return capabilityList } // NormalizeCapabilities normalizes caps by adding a "CAP_" prefix (if not yet // present). func NormalizeCapabilities(caps []string) ([]string, error) { - all, err := capStrList() - if err != nil { - return nil, err - } normalized := make([]string, 0, len(caps)) for _, c := range caps { c = strings.ToUpper(c) @@ -99,23 +106,19 @@ func NormalizeCapabilities(caps []string) ([]string, error) { if !strings.HasPrefix(c, "CAP_") { c = "CAP_" + c } - if !slices.Contains(all, c) { + if !slices.Contains(capabilityList, c) { return nil, fmt.Errorf("%q: %w", c, ErrUnknownCapability) } normalized = append(normalized, c) } - slices.Sort(normalized) + sort.Strings(normalized) return normalized, nil } // ValidateCapabilities validates if caps only contains valid capabilities. func ValidateCapabilities(caps []string) error { - all, err := capStrList() - if err != nil { - return err - } for _, c := range caps { - if !slices.Contains(all, c) { + if !slices.Contains(capabilityList, c) { return fmt.Errorf("%q: %w", c, ErrUnknownCapability) } } @@ -152,7 +155,7 @@ func MergeCapabilities(base, adds, drops []string) ([]string, error) { return nil, errors.New("adding all caps and removing all caps not allowed") } // "Drop" all capabilities; return what's in capAdd instead - slices.Sort(capAdd) + sort.Strings(capAdd) return capAdd, nil } @@ -192,6 +195,6 @@ func MergeCapabilities(base, adds, drops []string) ([]string, error) { } caps = append(caps, cap) } - slices.Sort(caps) + sort.Strings(caps) return caps, nil } diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go index d2c610fb15..717685789b 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go @@ -95,8 +95,7 @@ func init() { func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]controller, error) { if cgroup2 { controllers := []controller{} - controllersFile := filepath.Join(cgroupRoot, "cgroup.controllers") - + controllersFile := cgroupRoot + "/cgroup.controllers" // rootless cgroupv2: check available controllers for current user, systemd or servicescope will inherit if unshare.IsRootless() { userSlice, err := getCgroupPathForCurrentProcess() @@ -105,7 +104,7 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) } // userSlice already contains '/' so not adding here basePath := cgroupRoot + userSlice - controllersFile = filepath.Join(basePath, "cgroup.controllers") + controllersFile = basePath + "/cgroup.controllers" } controllersFileBytes, err := os.ReadFile(controllersFile) if err != nil { @@ -598,7 +597,7 @@ func createCgroupv2Path(path string) (deferredError error) { if !strings.HasPrefix(path, cgroupRoot+"/") { return fmt.Errorf("invalid cgroup path %s", path) } - content, err := os.ReadFile(filepath.Join(cgroupRoot, "cgroup.controllers")) + content, err := os.ReadFile(cgroupRoot + "/cgroup.controllers") if err != nil { return err } @@ -626,43 +625,8 @@ 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 // PIDs if there are already enabled controllers. if i < len(elements[3:])-1 { - subtreeControl := filepath.Join(current, "cgroup.subtree_control") - if err := os.WriteFile(subtreeControl, res, 0o755); err != nil { - // The kernel returns ENOENT either if the file itself is missing, or a controller - if errors.Is(err, os.ErrNotExist) { - if err2 := fileutils.Exists(subtreeControl); err2 != nil { - // If the file itself is missing, return the original error. - return err - } - repeatAttempts := 1000 - for repeatAttempts > 0 { - // store the controllers that failed to be enabled, so we can retry them - newCtrs := [][]byte{} - for _, ctr := range ctrs { - // Try to enable each controller individually, at least we can give a better error message if any fails. - if err := os.WriteFile(subtreeControl, []byte(fmt.Sprintf("+%s\n", ctr)), 0o755); err != nil { - // The kernel can return EBUSY when a process was moved to a sub-cgroup - // and the controllers are enabled in its parent cgroup. Retry a few times when - // it happens. - if errors.Is(err, unix.EBUSY) { - newCtrs = append(newCtrs, ctr) - } else { - return fmt.Errorf("enabling controller %s: %w", ctr, err) - } - } - } - if len(newCtrs) == 0 { - err = nil - break - } - ctrs = newCtrs - repeatAttempts-- - time.Sleep(time.Millisecond) - } - if err != nil { - return err - } - } + if err := os.WriteFile(filepath.Join(current, "cgroup.subtree_control"), res, 0o755); err != nil { + return err } } } @@ -822,12 +786,6 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) { continue } - // If we are on a cgroup v2 system and there are cgroup v1 controllers - // mounted, ignore them when the current process is at the root cgroup. - if cgroup2 && parts[1] != "" && parts[2] == "/" { - continue - } - var cgroupPath string if cgroup2 { diff --git a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go index b1529410f9..ead630e755 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go @@ -23,7 +23,7 @@ func systemdCreate(resources *configs.Resources, path string, c *systemdDbus.Con slice = strings.TrimSuffix(slice, "/") var lastError error - for i := range 2 { + for i := 0; i < 2; i++ { properties := []systemdDbus.Property{ systemdDbus.PropDescription("cgroup " + name), systemdDbus.PropWants(slice), diff --git a/vendor/github.com/containers/common/pkg/config/config_bsd.go b/vendor/github.com/containers/common/pkg/config/config_bsd.go index 9f3513a676..e378a07224 100644 --- a/vendor/github.com/containers/common/pkg/config/config_bsd.go +++ b/vendor/github.com/containers/common/pkg/config/config_bsd.go @@ -1,4 +1,4 @@ -//go:build freebsd || netbsd || openbsd +//go:build (freebsd || netbsd || openbsd) package config diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 236b51204a..c00efecbb3 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -27,19 +27,16 @@ # #apparmor_profile = "container-default" -# Base file to create the `/etc/hosts` file inside the container. This must either -# be an absolute path to a file on the host system, or one of the following -# special flags: -# "" Use the host's `/etc/hosts` file (the default) -# `none` Do not use a base file (i.e. start with an empty file) -# `image` Use the container image's `/etc/hosts` file as base file +# The hosts entries from the base hosts file are added to the containers hosts +# file. This must be either an absolute path or as special values "image" which +# uses the hosts file from the container image or "none" which means +# no base hosts file is used. The default is "" which will use /etc/hosts. # #base_hosts_file = "" # List of cgroup_conf entries specifying a list of cgroup files to write to and # their values. For example `memory.high=1073741824` sets the # memory.high limit to 1GB. -# # cgroup_conf = [] # Default way to to create a cgroup namespace for the container @@ -129,25 +126,13 @@ default_sysctls = [ # #env_host = false -# Set the IP address the container should expect to connect to the host. The IP -# address is used by Podman to automatically add the `host.containers.internal` -# and `host.docker.internal` hostnames to the container's `/etc/hosts` file. It -# is also used for the *host-gateway* flag of Podman's `--add-host` CLI option. -# If no IP address is configured (the default), Podman will try to determine it -# automatically, but might fail to do so depending on the container's network -# setup. Adding these internal hostnames to `/etc/hosts` is silently skipped then. -# Set this config to `none` to never add the internal hostnames to `/etc/hosts`. -# -# Note: If Podman is running in a virtual machine using `podman machine` (this -# includes Mac and Windows hosts), Podman will silently skip adding the internal -# hostnames to `/etc/hosts`, unless an IP address was configured manually. The -# internal hostnames are resolved by the gvproxy DNS resolver instead. This config -# has no effect on gvproxy. However, since `/etc/hosts` bypasses the DNS resolver, -# a manually configured IP address still takes precedence. -# -# Note: This config doesn't affect the actual network setup, it just tells Podman -# the IP address it should expect. Configuring an IP address here doesn't ensure -# that the container can actually reach the host using this IP address. +# Set the ip for the host.containers.internal entry in the containers /etc/hosts +# file. This can be set to "none" to disable adding this entry. By default it +# will automatically choose the host ip. +# +# NOTE: When using podman machine this entry will never be added to the containers +# hosts file instead the gvproxy dns resolver will resolve this hostname. Therefore +# it is not possible to disable the entry in this case. # #host_containers_internal_ip = "" @@ -236,10 +221,8 @@ default_sysctls = [ # #netns = "private" -# Do not modify the `/etc/hosts` file in the container. Podman assumes control -# over the container's `/etc/hosts` file by default; refer to the `--add-host` -# CLI option for details. To disable this, either set this config to `true`, or -# use the functionally identical `--no-hosts` CLI option. +# Create /etc/hosts for the container. By default, container engine manage +# /etc/hosts, automatically adding the container's own IP address. # #no_hosts = false @@ -433,8 +416,6 @@ default_sysctls = [ #List of compression algorithms. If set makes sure that requested compression variant #for each platform is added to the manifest list keeping original instance intact in #the same manifest list on every `manifest push`. Supported values are (`gzip`, `zstd` and `zstd:chunked`). -#`zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning -#in that case. # #add_compression = ["gzip", "zstd", "zstd:chunked"] @@ -457,8 +438,6 @@ default_sysctls = [ # This field is ignored when pushing images to the docker-daemon and # docker-archive formats. It is also ignored when the manifest format is set # to v2s2. -# `zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning -# in that case. # #compression_format = "gzip" @@ -886,15 +865,7 @@ default_sysctls = [ # Virtualization provider used to run Podman machine. # If it is empty or commented out, the default provider will be used. -# Linux: -# qemu - Open source machine emulator and virtualizer. (Default) -# Windows: there are currently two options: -# wsl - Windows Subsystem for Linux (Default) -# hyperv - Windows Server Virtualization -# Mac: there are currently two options: -# applehv - Default Apple Hypervisor (Default) -# libkrun - Launch virtual machines using the libkrun platform, optimized -# for sharing GPU with the machine. +# #provider = "" # Rosetta supports running x86_64 Linux binaries on a Podman machine on Apple silicon. diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd b/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd index 894153ed33..21753f4f25 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd +++ b/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd @@ -326,8 +326,6 @@ default_sysctls = [ # The compression format to use when pushing an image. # Valid options are: `gzip`, `zstd` and `zstd:chunked`. -# `zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning -# in that case. # #compression_format = "gzip" diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 02ff1284c7..311b090b9c 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -120,12 +120,12 @@ var ( additionalHelperBinariesDir string defaultUnixComposeProviders = []string{ + "docker-compose", "$HOME/.docker/cli-plugins/docker-compose", "/usr/local/lib/docker/cli-plugins/docker-compose", "/usr/local/libexec/docker/cli-plugins/docker-compose", "/usr/lib/docker/cli-plugins/docker-compose", "/usr/libexec/docker/cli-plugins/docker-compose", - "docker-compose", "podman-compose", } @@ -231,6 +231,7 @@ func defaultConfig() (*Config, error) { DNSServers: attributedstring.Slice{}, DefaultCapabilities: attributedstring.NewSlice(DefaultCapabilities), DefaultSysctls: attributedstring.Slice{}, + DefaultUlimits: attributedstring.NewSlice(getDefaultProcessLimits()), Devices: attributedstring.Slice{}, EnableKeyring: true, EnableLabeling: selinuxEnabled(), diff --git a/vendor/github.com/containers/common/pkg/config/default_bsd.go b/vendor/github.com/containers/common/pkg/config/default_bsd.go index 2e87dc8b0f..c619e1783f 100644 --- a/vendor/github.com/containers/common/pkg/config/default_bsd.go +++ b/vendor/github.com/containers/common/pkg/config/default_bsd.go @@ -1,4 +1,4 @@ -//go:build freebsd || netbsd || openbsd +//go:build (freebsd || netbsd || openbsd) package config diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go index 928ae9fa27..9e2ae4796b 100644 --- a/vendor/github.com/containers/common/pkg/config/default_linux.go +++ b/vendor/github.com/containers/common/pkg/config/default_linux.go @@ -1,13 +1,47 @@ package config import ( + "fmt" "os" + "strconv" + "strings" + + "golang.org/x/sys/unix" +) + +const ( + oldMaxSize = uint64(1048576) ) func getDefaultCgroupsMode() string { return "enabled" } +// getDefaultProcessLimits returns the nproc for the current process in ulimits format +// Note that nfile sometimes cannot be set to unlimited, and the limit is hardcoded +// to (oldMaxSize) 1048576 (2^20), see: http://stackoverflow.com/a/1213069/1811501 +// In rootless containers this will fail, and the process will just use its current limits +func getDefaultProcessLimits() []string { + rlim := unix.Rlimit{Cur: oldMaxSize, Max: oldMaxSize} + oldrlim := rlim + // Attempt to set file limit and process limit to pid_max in OS + dat, err := os.ReadFile("/proc/sys/kernel/pid_max") + if err == nil { + val := strings.TrimSuffix(string(dat), "\n") + max, err := strconv.ParseUint(val, 10, 64) + if err == nil { + rlim = unix.Rlimit{Cur: max, Max: max} + } + } + defaultLimits := []string{} + if err := unix.Setrlimit(unix.RLIMIT_NPROC, &rlim); err == nil { + defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", rlim.Cur, rlim.Max)) + } else if err := unix.Setrlimit(unix.RLIMIT_NPROC, &oldrlim); err == nil { + defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", oldrlim.Cur, oldrlim.Max)) + } + return defaultLimits +} + // getDefaultTmpDir for linux func getDefaultTmpDir() string { // first check the TMPDIR env var diff --git a/vendor/github.com/containers/common/pkg/config/default_windows.go b/vendor/github.com/containers/common/pkg/config/default_windows.go index 610aa122bf..70627cbda8 100644 --- a/vendor/github.com/containers/common/pkg/config/default_windows.go +++ b/vendor/github.com/containers/common/pkg/config/default_windows.go @@ -42,17 +42,11 @@ func getLibpodTmpDir() string { } // getDefaultMachineVolumes returns default mounted volumes (possibly with env vars, which will be expanded) -// It is executed only if the machine provider is Hyper-V and it mimics WSL -// behavior where the host %USERPROFILE% drive (e.g. C:\) is automatically -// mounted in the guest under /mnt/ (e.g. /mnt/c/) func getDefaultMachineVolumes() []string { hd := homedir.Get() vol := filepath.VolumeName(hd) hostMnt := filepath.ToSlash(strings.TrimPrefix(hd, vol)) - return []string{ - fmt.Sprintf("%s:%s", hd, hostMnt), - fmt.Sprintf("%s:%s", vol+"\\", "/mnt/"+strings.ToLower(vol[0:1])), - } + return []string{fmt.Sprintf("%s:%s", hd, hostMnt)} } func getDefaultComposeProviders() []string { diff --git a/vendor/github.com/containers/common/pkg/hooks/exec/runtimeconfigfilter.go b/vendor/github.com/containers/common/pkg/hooks/exec/runtimeconfigfilter.go index 3027112609..ac17ac64da 100644 --- a/vendor/github.com/containers/common/pkg/hooks/exec/runtimeconfigfilter.go +++ b/vendor/github.com/containers/common/pkg/hooks/exec/runtimeconfigfilter.go @@ -56,6 +56,7 @@ func RuntimeConfigFilterWithOptions(ctx context.Context, options RuntimeConfigFi return nil, err } for i, hook := range options.Hooks { + hook := hook var stdout bytes.Buffer hookErr, err = RunWithOptions(ctx, RunOptions{Hook: &hook, Dir: options.Dir, State: data, Stdout: &stdout, PostKillTimeout: options.PostKillTimeout}) if err != nil { diff --git a/vendor/github.com/containers/common/pkg/netns/netns_linux.go b/vendor/github.com/containers/common/pkg/netns/netns_linux.go index 5461b05f75..3a3372889a 100644 --- a/vendor/github.com/containers/common/pkg/netns/netns_linux.go +++ b/vendor/github.com/containers/common/pkg/netns/netns_linux.go @@ -75,7 +75,7 @@ func NewNS() (ns.NetNS, error) { return nil, err } - for range 10000 { + for i := 0; i < 10000; i++ { nsName, err := getRandomNetnsName() if err != nil { return nil, err @@ -108,7 +108,7 @@ func NewNSFrom(fromNetns string) (string, error) { return "", err } - for range 10000 { + for i := 0; i < 10000; i++ { nsName, err := getRandomNetnsName() if err != nil { return "", err diff --git a/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go b/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go index adafb1c26c..830482ff0c 100644 --- a/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go +++ b/vendor/github.com/containers/common/pkg/report/camelcase/camelcase.go @@ -73,7 +73,7 @@ func Split(src string) (entries []string) { } // handle upper case -> lower case sequences, e.g. // "PDFL", "oader" -> "PDF", "Loader" - for i := range len(runes) - 1 { + for i := 0; i < len(runes)-1; i++ { if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) { runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...) runes[i] = runes[i][:len(runes[i])-1] diff --git a/vendor/github.com/containers/common/pkg/report/template.go b/vendor/github.com/containers/common/pkg/report/template.go index 607bb7ff2b..0f7d5e5bfe 100644 --- a/vendor/github.com/containers/common/pkg/report/template.go +++ b/vendor/github.com/containers/common/pkg/report/template.go @@ -101,7 +101,7 @@ func Headers(object any, overrides map[string]string) []map[string]string { // Column header will be field name upper-cased. headers := make(map[string]string, value.NumField()) - for i := range value.Type().NumField() { + for i := 0; i < value.Type().NumField(); i++ { field := value.Type().Field(i) // Recurse to find field names from promoted structs if field.Type.Kind() == reflect.Struct && field.Anonymous { diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go index a6538ffb90..ded66365bb 100644 --- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go +++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go @@ -11,7 +11,6 @@ import ( "github.com/containers/common/pkg/umask" "github.com/containers/storage/pkg/fileutils" "github.com/containers/storage/pkg/idtools" - securejoin "github.com/cyphar/filepath-securejoin" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/sirupsen/logrus" @@ -347,10 +346,7 @@ func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint, srcBackendDir := "/usr/share/crypto-policies/back-ends/FIPS" destDir := "/etc/crypto-policies/back-ends" - srcOnHost, err := securejoin.SecureJoin(mountPoint, srcBackendDir) - if err != nil { - return fmt.Errorf("resolve %s in the container: %w", srcBackendDir, err) - } + srcOnHost := filepath.Join(mountPoint, srcBackendDir) if err := fileutils.Exists(srcOnHost); err != nil { if errors.Is(err, os.ErrNotExist) { return nil diff --git a/vendor/github.com/containers/common/pkg/systemd/systemd_linux.go b/vendor/github.com/containers/common/pkg/systemd/systemd_linux.go index ea61ecaa18..c1d8ed72e9 100644 --- a/vendor/github.com/containers/common/pkg/systemd/systemd_linux.go +++ b/vendor/github.com/containers/common/pkg/systemd/systemd_linux.go @@ -74,7 +74,7 @@ func MoveRootlessNetnsSlirpProcessToUserSlice(pid int) error { func MovePauseProcessToScope(pausePidPath string) { var err error - for range 10 { + for i := 0; i < 10; i++ { randBytes := make([]byte, 4) _, err = rand.Read(randBytes) if err != nil { diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index c73ec15cd4..3703dc8d93 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.61.0-dev" +const Version = "0.60.3" diff --git a/vendor/modules.txt b/vendor/modules.txt index eb7665b61c..078a0e619d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -107,6 +107,9 @@ github.com/chzyer/readline # github.com/containerd/cgroups/v3 v3.0.3 ## explicit; go 1.18 github.com/containerd/cgroups/v3/cgroup1/stats +# github.com/containerd/containerd v1.7.21 +## explicit; go 1.21 +github.com/containerd/containerd/platforms # github.com/containerd/errdefs v0.1.0 ## explicit; go 1.20 github.com/containerd/errdefs @@ -169,8 +172,8 @@ github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/volumes github.com/containers/buildah/util -# github.com/containers/common v0.60.1-0.20241018183244-7e6f2b4d6de7 -## explicit; go 1.22.0 +# github.com/containers/common v0.60.3 +## explicit; go 1.21.0 github.com/containers/common/internal github.com/containers/common/internal/attributedstring github.com/containers/common/libimage @@ -424,8 +427,8 @@ github.com/coreos/stream-metadata-go/fedoracoreos github.com/coreos/stream-metadata-go/fedoracoreos/internals github.com/coreos/stream-metadata-go/stream github.com/coreos/stream-metadata-go/stream/rhcos -# github.com/crc-org/crc/v2 v2.38.0 -## explicit; go 1.21 +# github.com/crc-org/crc/v2 v2.42.0 +## explicit; go 1.22.0 github.com/crc-org/crc/v2/pkg/crc/logging github.com/crc-org/crc/v2/pkg/os # github.com/crc-org/vfkit v0.5.1