Vendor in latest containers/common

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2024-02-27 16:20:50 -05:00
parent 98d1ad5a22
commit 2c9c7273ca
19 changed files with 365 additions and 90 deletions

4
go.mod
View File

@ -11,14 +11,14 @@ require (
github.com/checkpoint-restore/go-criu/v7 v7.0.0
github.com/containernetworking/plugins v1.4.0
github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c
github.com/containers/common v0.57.1-0.20240207210145-1eeaf97594e9
github.com/containers/common v0.57.1-0.20240229151045-1c65e0de241a
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/gvisor-tap-vsock v0.7.3
github.com/containers/image/v5 v5.29.3-0.20240227090231-5bef5e1e1506
github.com/containers/libhvee v0.6.1-0.20240225143609-c1bda9d3838c
github.com/containers/ocicrypt v1.1.9
github.com/containers/psgo v1.9.0
github.com/containers/storage v1.52.1-0.20240227082351-387d7c8480b0
github.com/containers/storage v1.52.1-0.20240229151339-eadc620e74e7
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

8
go.sum
View File

@ -76,8 +76,8 @@ github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7w
github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0=
github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c h1:r+1vFyTAoXptJrsPsnOMI3G0jm4+BCfXAcIyuA33lzo=
github.com/containers/buildah v1.34.1-0.20240201124221-b850c711ff5c/go.mod h1:Hw4qo2URFpWvZ2tjLstoQMpNC6+gR4PtxQefvV/UKaA=
github.com/containers/common v0.57.1-0.20240207210145-1eeaf97594e9 h1:JFkj+j5hSOJdCpLhpx+xp1pEbMfXj2xtorRx223PqYo=
github.com/containers/common v0.57.1-0.20240207210145-1eeaf97594e9/go.mod h1:0NtD59teSfqhgJqcgg73on5AuaGo8XbbVLv+i2bl0oY=
github.com/containers/common v0.57.1-0.20240229151045-1c65e0de241a h1:N/AOv7bQBTD/+inld7Qpc2WzxtpbsPgPDB/gg7JGQKA=
github.com/containers/common v0.57.1-0.20240229151045-1c65e0de241a/go.mod h1:8irlyBcVooYx0F+YmoY7PQPAIgdJvCj17bvL7PqeaxI=
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.3 h1:yORnf15sP+sLFhxLNLgmB5/lOhldn9dRMHx/tmYtSOQ=
@ -94,8 +94,8 @@ github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOj
github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPNFN4jwA9GBys=
github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g=
github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A=
github.com/containers/storage v1.52.1-0.20240227082351-387d7c8480b0 h1:n5UoWBdTeOGN5rlV49ZqS8E4vgo8Z6LxFFgbCDNaU+c=
github.com/containers/storage v1.52.1-0.20240227082351-387d7c8480b0/go.mod h1:mFA6QpUoT9qTa3q2DD1CvSo3Az3syNkw1P9X+4nUYdY=
github.com/containers/storage v1.52.1-0.20240229151339-eadc620e74e7 h1:rL6WUiGo7uyDY8WRfpLidnzSZuPPepcQLuc9p29Y9k8=
github.com/containers/storage v1.52.1-0.20240229151339-eadc620e74e7/go.mod h1:mFA6QpUoT9qTa3q2DD1CvSo3Az3syNkw1P9X+4nUYdY=
github.com/containers/winquit v1.1.0 h1:jArun04BNDQvt2W0Y78kh9TazN2EIEMG5Im6/JY7+pE=
github.com/containers/winquit v1.1.0/go.mod h1:PsPeZlnbkmGGIToMPHF1zhWjBUkd8aHjMOr/vFcPxw8=
github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=

View File

@ -19,6 +19,7 @@ import (
structcopier "github.com/jinzhu/copier"
"github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)
@ -294,7 +295,7 @@ func (m *ManifestList) Inspect() (*define.ManifestListData, error) {
return &inspectList, nil
}
// Options for adding a manifest list.
// Options for adding an image or artifact to a manifest list.
type ManifestListAddOptions struct {
// Add all images to the list if the to-be-added image itself is a
// manifest list.
@ -371,6 +372,104 @@ func (m *ManifestList) Add(ctx context.Context, name string, options *ManifestLi
return newDigest, nil
}
// Options for creating an artifact manifest for one or more files and adding
// the artifact manifest to a manifest list.
type ManifestListAddArtifactOptions struct {
// The artifactType to set in the artifact manifest.
Type *string `json:"artifact_type"`
// The mediaType to set in the config.MediaType field in the artifact manifest.
ConfigType string `json:"artifact_config_type"`
// Content to point to from the config field in the artifact manifest.
Config string `json:"artifact_config"`
// The mediaType to set in the layer descriptors in the artifact manifest.
LayerType string `json:"artifact_layer_type"`
// Whether or not to suppress the org.opencontainers.image.title annotation in layer descriptors.
ExcludeTitles bool `json:"exclude_layer_titles"`
// Annotations to set in the artifact manifest.
Annotations map[string]string `json:"annotations"`
// Subject to set in the artifact manifest.
Subject string `json:"subject"`
}
// Add adds one or more manifests to the manifest list and returns the digest
// of the added instance.
func (m *ManifestList) AddArtifact(ctx context.Context, options *ManifestListAddArtifactOptions, files ...string) (digest.Digest, error) {
if options == nil {
options = &ManifestListAddArtifactOptions{}
}
opts := manifests.AddArtifactOptions{
ManifestArtifactType: options.Type,
Annotations: maps.Clone(options.Annotations),
ExcludeTitles: options.ExcludeTitles,
}
if options.ConfigType != "" {
opts.ConfigDescriptor = &imgspecv1.Descriptor{
MediaType: options.ConfigType,
Digest: imgspecv1.DescriptorEmptyJSON.Digest,
Size: imgspecv1.DescriptorEmptyJSON.Size,
Data: slices.Clone(imgspecv1.DescriptorEmptyJSON.Data),
}
}
if options.Config != "" {
if opts.ConfigDescriptor == nil {
opts.ConfigDescriptor = &imgspecv1.Descriptor{
MediaType: imgspecv1.MediaTypeImageConfig,
}
}
opts.ConfigDescriptor.Digest = digest.FromString(options.Config)
opts.ConfigDescriptor.Size = int64(len(options.Config))
opts.ConfigDescriptor.Data = slices.Clone([]byte(options.Config))
}
if opts.ConfigDescriptor == nil {
empty := imgspecv1.DescriptorEmptyJSON
opts.ConfigDescriptor = &empty
}
if options.LayerType != "" {
opts.LayerMediaType = &options.LayerType
}
if options.Subject != "" {
ref, err := alltransports.ParseImageName(options.Subject)
if err != nil {
withDocker := fmt.Sprintf("%s://%s", docker.Transport.Name(), options.Subject)
ref, err = alltransports.ParseImageName(withDocker)
if err != nil {
image, _, err := m.image.runtime.LookupImage(options.Subject, &LookupImageOptions{ManifestList: true})
if err != nil {
return "", fmt.Errorf("locating subject for artifact manifest: %w", err)
}
ref = image.storageReference
}
}
opts.SubjectReference = ref
}
// Lock the image record where this list lives.
locker, err := manifests.LockerForImage(m.image.runtime.store, m.ID())
if err != nil {
return "", err
}
locker.Lock()
defer locker.Unlock()
systemContext := m.image.runtime.systemContextCopy()
// Make sure to reload the image from the containers storage to fetch
// the latest data (e.g., new or delete digests).
if err := m.reload(); err != nil {
return "", err
}
newDigest, err := m.list.AddArtifact(ctx, systemContext, opts, files...)
if err != nil {
return "", err
}
// Write the changes to disk.
if err := m.saveAndReload(); err != nil {
return "", err
}
return newDigest, nil
}
// Options for annotating a manifest list.
type ManifestListAnnotateOptions struct {
// Add the specified annotations to the added image.
@ -387,10 +486,16 @@ type ManifestListAnnotateOptions struct {
OSVersion string
// Add the specified variant to the added image.
Variant string
// Add the specified annotations to the index itself.
IndexAnnotations map[string]string
// Set the subject to which the index refers.
Subject string
}
// Annotate an image instance specified by `d` in the manifest list.
func (m *ManifestList) AnnotateInstance(d digest.Digest, options *ManifestListAnnotateOptions) error {
ctx := context.Background()
if options == nil {
return nil
}
@ -430,6 +535,54 @@ func (m *ManifestList) AnnotateInstance(d digest.Digest, options *ManifestListAn
return err
}
}
if len(options.IndexAnnotations) > 0 {
if err := m.list.SetAnnotations(nil, options.IndexAnnotations); err != nil {
return err
}
}
if options.Subject != "" {
ref, err := alltransports.ParseImageName(options.Subject)
if err != nil {
withDocker := fmt.Sprintf("%s://%s", docker.Transport.Name(), options.Subject)
ref, err = alltransports.ParseImageName(withDocker)
if err != nil {
image, _, err := m.image.runtime.LookupImage(options.Subject, &LookupImageOptions{ManifestList: true})
if err != nil {
return fmt.Errorf("locating subject for image index: %w", err)
}
ref = image.storageReference
}
}
src, err := ref.NewImageSource(ctx, &m.image.runtime.systemContext)
if err != nil {
return err
}
defer src.Close()
subjectManifestBytes, subjectManifestType, err := src.GetManifest(ctx, nil)
if err != nil {
return err
}
subjectManifestDigest, err := manifest.Digest(subjectManifestBytes)
if err != nil {
return err
}
var subjectArtifactType string
if !manifest.MIMETypeIsMultiImage(subjectManifestType) {
var subjectManifest imgspecv1.Manifest
if json.Unmarshal(subjectManifestBytes, &subjectManifest) == nil {
subjectArtifactType = subjectManifest.ArtifactType
}
}
descriptor := &imgspecv1.Descriptor{
MediaType: subjectManifestType,
ArtifactType: subjectArtifactType,
Digest: subjectManifestDigest,
Size: int64(len(subjectManifestBytes)),
}
if err := m.list.SetSubject(descriptor); err != nil {
return err
}
}
// Write the changes to disk.
return m.saveAndReload()

View File

@ -711,10 +711,18 @@ func (l *list) AddArtifact(ctx context.Context, sys *types.SystemContext, option
if err != nil {
return "", fmt.Errorf("digesting manifest of subject %q: %w", transports.ImageName(options.SubjectReference), err)
}
var subjectArtifactType string
if !manifest.MIMETypeIsMultiImage(subjectManifestType) {
var subjectManifest v1.Manifest
if json.Unmarshal(subjectManifestBytes, &subjectManifest) == nil {
subjectArtifactType = subjectManifest.ArtifactType
}
}
subject = &v1.Descriptor{
MediaType: subjectManifestType,
Digest: subjectManifestDigest,
Size: int64(len(subjectManifestBytes)),
MediaType: subjectManifestType,
ArtifactType: subjectArtifactType,
Digest: subjectManifestDigest,
Size: int64(len(subjectManifestBytes)),
}
}

View File

@ -60,6 +60,23 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
options = &PullOptions{}
}
defaultConfig, err := config.Default()
if err != nil {
return nil, err
}
if options.MaxRetries == nil {
options.MaxRetries = &defaultConfig.Engine.Retry
}
if options.RetryDelay == nil {
if defaultConfig.Engine.RetryDelay != "" {
duration, err := time.ParseDuration(defaultConfig.Engine.RetryDelay)
if err != nil {
return nil, fmt.Errorf("failed to parse containers.conf retry_delay: %w", err)
}
options.RetryDelay = &duration
}
}
var possiblyUnqualifiedName string // used for short-name resolution
ref, err := alltransports.ParseImageName(name)
if err != nil {

View File

@ -4,10 +4,14 @@ package libimage
import (
"context"
"fmt"
"time"
"github.com/containers/common/pkg/config"
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
dockerDaemonTransport "github.com/containers/image/v5/docker/daemon"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports/alltransports"
"github.com/sirupsen/logrus"
)
@ -31,6 +35,23 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options
options = &PushOptions{}
}
defaultConfig, err := config.Default()
if err != nil {
return nil, err
}
if options.MaxRetries == nil {
options.MaxRetries = &defaultConfig.Engine.Retry
}
if options.RetryDelay == nil {
if defaultConfig.Engine.RetryDelay != "" {
duration, err := time.ParseDuration(defaultConfig.Engine.RetryDelay)
if err != nil {
return nil, fmt.Errorf("failed to parse containers.conf retry_delay: %w", err)
}
options.RetryDelay = &duration
}
}
// Look up the local image. Note that we need to ignore the platform
// and push what the user specified (containers/podman/issues/10344).
image, resolvedSource, err := r.LookupImage(source, nil)
@ -65,6 +86,14 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options
destRef = dockerRef
}
// docker-archive and only DockerV2Schema2MediaType support Gzip compression
if options.CompressionFormat != nil &&
(destRef.Transport().Name() == dockerArchiveTransport.Transport.Name() ||
destRef.Transport().Name() == dockerDaemonTransport.Transport.Name() ||
options.ManifestMIMEType == manifest.DockerV2Schema2MediaType) {
options.CompressionFormat = nil
}
if r.eventChannel != nil {
defer r.writeEvent(&Event{ID: image.ID(), Name: destination, Time: time.Now(), Type: EventTypeImagePush})
}

View File

@ -47,6 +47,7 @@ func Setup(opts *SetupOptions) error {
NoTCPNamespacePorts := true
NoUDPNamespacePorts := true
NoMapGW := true
NoDNS := true
path, err := opts.Config.FindHelperBinary(BinaryName, true)
if err != nil {
@ -102,6 +103,8 @@ func Setup(opts *SetupOptions) error {
NoMapGW = false
// not an actual pasta(1) option
cmdArgs = append(cmdArgs[:i], cmdArgs[i+1:]...)
case "-D", "--dns", "--dns-forward":
NoDNS = false
}
}
@ -120,21 +123,36 @@ func Setup(opts *SetupOptions) error {
if NoMapGW {
cmdArgs = append(cmdArgs, "--no-map-gw")
}
if NoDNS {
// disable pasta reading from /etc/resolv.conf which hides the
// "Couldn't get any nameserver address" warning when only
// localhost resolvers are configured.
cmdArgs = append(cmdArgs, "--dns", "none")
}
cmdArgs = append(cmdArgs, "--netns", opts.Netns)
// always pass --quiet to silence the info output from pasta
cmdArgs = append(cmdArgs, "--quiet", "--netns", opts.Netns)
logrus.Debugf("pasta arguments: %s", strings.Join(cmdArgs, " "))
// pasta forks once ready, and quits once we delete the target namespace
_, err = exec.Command(path, cmdArgs...).Output()
out, err := exec.Command(path, cmdArgs...).CombinedOutput()
if err != nil {
exitErr := &exec.ExitError{}
if errors.As(err, &exitErr) {
return fmt.Errorf("pasta failed with exit code %d:\n%s",
exitErr.ExitCode(), exitErr.Stderr)
exitErr.ExitCode(), string(out))
}
return fmt.Errorf("failed to start pasta: %w", err)
}
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))
}
return nil
}

View File

@ -370,11 +370,6 @@ type EngineConfig struct {
// LockType is the type of locking to use.
LockType string `toml:"lock_type,omitempty"`
// MachineEnabled indicates if Podman is running in a podman-machine VM
//
// This method is soft deprecated, use machine.IsPodmanMachine instead
MachineEnabled bool `toml:"machine_enabled,omitempty"`
// MultiImageArchive - if true, the container engine allows for storing
// archives (e.g., of the docker-archive transport) with multiple
// images. By default, Podman creates single-image archives.
@ -421,6 +416,14 @@ type EngineConfig struct {
// Indicates whether the application should be running in Remote mode
Remote bool `toml:"remote,omitempty"`
// Number of times to retry pulling/pushing images in case of failure
Retry uint `toml:"retry,omitempty"`
// Delay between retries in case pulling/pushing image fails
// If set, container engines will retry at the set interval,
// otherwise they delay 2 seconds and then exponentially back off.
RetryDelay string `toml:"retry_delay,omitempty"`
// RemoteURI is deprecated, see ActiveService
// RemoteURI containers connection information used to connect to remote system.
RemoteURI string `toml:"remote_uri,omitempty"`
@ -660,6 +663,8 @@ type MachineConfig struct {
Volumes attributedstring.Slice `toml:"volumes,omitempty"`
// Provider is the virtualization provider used to run podman-machine VM
Provider string `toml:"provider,omitempty"`
// Rosetta is the flag to enable Rosetta in the podman-machine VM on Apple Silicon
Rosetta bool `toml:"rosetta,omitempty"`
}
// FarmConfig represents the "farm" TOML config tables

View File

@ -435,6 +435,9 @@ default_sysctls = [
# The compression format to use when pushing an image.
# Valid options are: `gzip`, `zstd` and `zstd:chunked`.
# 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.
#
#compression_format = "gzip"
@ -636,7 +639,8 @@ default_sysctls = [
#
#no_pivot_root = false
# Number of locks available for containers and pods.
# Number of locks available for containers, pods, and volumes. Each container,
# pod, and volume consumes 1 lock for as long as it exists.
# If this is changed, a lock renumber must be performed (e.g. with the
# 'podman system renumber' command).
#
@ -655,6 +659,16 @@ default_sysctls = [
#
#remote = false
# Number of times to retry pulling/pushing images in case of failure
#
#retry = 3
# Delay between retries in case pulling/pushing image fails.
# If set, container engines will retry at the set interval,
# otherwise they delay 2 seconds and then exponentially back off.
#
#retry_delay = "2s"
# Default OCI runtime
#
#runtime = "crun"
@ -809,16 +823,15 @@ default_sysctls = [
#
#disk_size=10
# Default image URI when creating a new VM using `podman machine init`.
# Options: On Linux/Mac, `testing`, `stable`, `next`. On Windows, the major
# version of the OS (e.g `36`) for Fedora 36. For all platforms you can
# alternatively specify a custom download URL to an image. Container engines
# translate URIs $OS and $ARCH to the native OS and ARCH. URI
# "https://example.com/$OS/$ARCH/foobar.ami" becomes
# Default Image used when creating a new VM using `podman machine init`.
# Can be specified as registry with a bootable OCI artifact, download URL, or a local path.
# Registry target must be in the form of `docker://registry/repo/image:version`.
# Container engines translate URIs $OS and $ARCH to the native OS and ARCH.
# URI "https://example.com/$OS/$ARCH/foobar.ami" would become
# "https://example.com/linux/amd64/foobar.ami" on a Linux AMD machine.
# The default value is `testing`.
# If unspecified, the default Podman machine image will be used.
#
#image = "testing"
#image = ""
# Memory in MB a machine is created with.
#
@ -843,6 +856,11 @@ default_sysctls = [
#
#provider = ""
# Rosetta supports running x86_64 Linux binaries on a Podman machine on Apple silicon.
# The default value is `true`. Supported on AppleHV(arm64) machines only.
#
#rosetta=true
# The [machine] table MUST be the last entry in this file.
# (Unless another table is added)
# TOML does not provide a way to end a table other than a further table being

View File

@ -286,10 +286,14 @@ func defaultMachineConfig() MachineConfig {
return MachineConfig{
CPUs: uint64(cpus),
DiskSize: 100,
Image: getDefaultMachineImage(),
Memory: 2048,
User: getDefaultMachineUser(),
Volumes: attributedstring.NewSlice(getDefaultMachineVolumes()),
// TODO: Set machine image default here
// Currently the default is set in Podman as we need time to stabilize
// VM images and locations between different providers.
Image: "",
Memory: 2048,
User: getDefaultMachineUser(),
Volumes: attributedstring.NewSlice(getDefaultMachineVolumes()),
Rosetta: true,
}
}
@ -354,6 +358,7 @@ func defaultEngineConfig() (*EngineConfig, error) {
c.PodmanshTimeout = uint(30)
c.ExitCommandDelay = uint(5 * 60)
c.Remote = isRemote()
c.Retry = 3
c.OCIRuntimes = map[string][]string{
"crun": {
"/usr/bin/crun",
@ -479,7 +484,6 @@ func defaultEngineConfig() (*EngineConfig, error) {
// TODO - ideally we should expose a `type LockType string` along with
// constants.
c.LockType = getDefaultLockType()
c.MachineEnabled = false
c.ChownCopiedFiles = true
c.PodExitPolicy = defaultPodExitPolicy
@ -648,11 +652,6 @@ func (c *Config) LogDriver() string {
return c.Containers.LogDriver
}
// MachineEnabled returns if podman is running inside a VM or not.
func (c *Config) MachineEnabled() bool {
return c.Engine.MachineEnabled
}
// MachineVolumes returns volumes to mount into the VM.
func (c *Config) MachineVolumes() ([]string, error) {
return machineVolumes(c.Machine.Volumes.Get())
@ -682,12 +681,6 @@ func getDefaultSSHConfig() string {
return filepath.Join(dirname, ".ssh", "config")
}
// getDefaultImage returns the default machine image stream
// On Windows this refers to the Fedora major release number
func getDefaultMachineImage() string {
return "testing"
}
// getDefaultMachineUser returns the user to use for rootless podman
// This is only for the apple, hyperv, and qemu implementations.
// WSL's user will be hardcoded in podman to "user"

View File

@ -1,6 +1,13 @@
package config
import "os"
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/containers/storage/pkg/homedir"
)
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
@ -36,7 +43,10 @@ func getLibpodTmpDir() string {
// getDefaultMachineVolumes returns default mounted volumes (possibly with env vars, which will be expanded)
func getDefaultMachineVolumes() []string {
return []string{}
hd := homedir.Get()
vol := filepath.VolumeName(hd)
hostMnt := filepath.ToSlash(strings.TrimPrefix(hd, vol))
return []string{fmt.Sprintf("%s:%s", hd, hostMnt)}
}
func getDefaultComposeProviders() []string {

View File

@ -122,10 +122,8 @@ func (m *Manager) Hooks(config *rspec.Spec, annotations map[string]string, hasBi
switch stage {
case "createContainer":
config.Hooks.CreateContainer = append(config.Hooks.CreateContainer, namedHook.hook.Hook)
case "createRuntime":
case "createRuntime", "prestart":
config.Hooks.CreateRuntime = append(config.Hooks.CreateRuntime, namedHook.hook.Hook)
case "prestart":
config.Hooks.Prestart = append(config.Hooks.Prestart, namedHook.hook.Hook)
case "poststart":
config.Hooks.Poststart = append(config.Hooks.Poststart, namedHook.hook.Hook)
case "poststop":

View File

@ -4,9 +4,6 @@ import (
"os"
"strings"
"sync"
"github.com/containers/common/pkg/config"
"github.com/sirupsen/logrus"
)
type Marker struct {
@ -29,9 +26,7 @@ var (
func loadMachineMarker(file string) {
var kind string
// Support deprecated config value for compatibility
enabled := isLegacyConfigSet()
enabled := false
if content, err := os.ReadFile(file); err == nil {
enabled = true
@ -41,17 +36,6 @@ func loadMachineMarker(file string) {
marker = &Marker{enabled, kind}
}
func isLegacyConfigSet() bool {
config, err := config.Default()
if err != nil {
logrus.Warnf("could not obtain container configuration")
return false
}
//nolint:staticcheck //lint:ignore SA1019 deprecated call
return config.Engine.MachineEnabled
}
func IsPodmanMachine() bool {
return GetMachineMarker().Enabled
}

View File

@ -177,16 +177,26 @@ func newNSPath(nsPath string) (ns.NetNS, error) {
// UnmountNS unmounts the given netns path
func UnmountNS(nsPath string) error {
var rErr error
// Only unmount if it's been bind-mounted (don't touch namespaces in /proc...)
if !strings.HasPrefix(nsPath, "/proc/") {
if err := unix.Unmount(nsPath, unix.MNT_DETACH); err != nil {
return fmt.Errorf("failed to unmount NS: at %s: %v", nsPath, err)
// Do not return here, always try to remove below.
// This is important in case podman now is in a new userns compared to
// when the netns was created. The umount will fail EINVAL but removing
// the file will work and the kernel will destroy the bind mount in the
// other ns because of this. We also need it so pasta doesn't leak.
rErr = fmt.Errorf("failed to unmount NS: at %s: %w", nsPath, err)
}
if err := os.Remove(nsPath); err != nil {
return fmt.Errorf("failed to remove ns path %s: %v", nsPath, err)
err := fmt.Errorf("failed to remove ns path: %w", err)
if rErr != nil {
err = fmt.Errorf("%v, %w", err, rErr)
}
rErr = err
}
}
return nil
return rErr
}

View File

@ -1696,7 +1696,13 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
}
if err := idtools.MkdirAllAs(diffDir, perms, rootUID, rootGID); err != nil {
return "", err
if !inAdditionalStore {
return "", err
}
// if it is in an additional store, do not fail if the directory already exists
if _, err2 := os.Stat(diffDir); err2 != nil {
return "", err
}
}
mergedDir := path.Join(workDirBase, "merged")
@ -1867,7 +1873,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
// Put unmounts the mount path created for the give id.
func (d *Driver) Put(id string) error {
dir := d.dir(id)
dir, _, inAdditionalStore := d.dir2(id)
if _, err := os.Stat(dir); err != nil {
return err
}
@ -1928,11 +1934,27 @@ func (d *Driver) Put(id string) error {
}
}
if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) {
logrus.Debugf("Failed to remove mountpoint %s overlay: %s - %v", id, mountpoint, err)
return fmt.Errorf("removing mount point %q: %w", mountpoint, err)
}
if !inAdditionalStore {
uid, gid := int(0), int(0)
fi, err := os.Stat(mountpoint)
if err != nil {
return err
}
if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
uid, gid = int(stat.Uid), int(stat.Gid)
}
tmpMountpoint := path.Join(dir, "merged.1")
if err := idtools.MkdirAs(tmpMountpoint, 0o700, uid, gid); err != nil && !errors.Is(err, os.ErrExist) {
return err
}
// rename(2) can be used on an empty directory, as it is the mountpoint after umount, and it retains
// its atomic semantic. In this way the "merged" directory is never removed.
if err := unix.Rename(tmpMountpoint, mountpoint); err != nil {
logrus.Debugf("Failed to replace mountpoint %s overlay: %s - %v", id, mountpoint, err)
return fmt.Errorf("replacing mount point %q: %w", mountpoint, err)
}
}
return nil
}

View File

@ -416,7 +416,7 @@ func ReadUserXattrToTarHeader(path string, hdr *tar.Header) error {
return err
}
for _, key := range xattrs {
if strings.HasPrefix(key, "user.") {
if strings.HasPrefix(key, "user.") && !strings.HasPrefix(key, "user.overlay.") {
value, err := system.Lgetxattr(path, key)
if err != nil {
if errors.Is(err, system.E2BIG) {

View File

@ -25,7 +25,7 @@ import (
const (
cacheKey = "chunked-manifest-cache"
cacheVersion = 1
cacheVersion = 2
digestSha256Empty = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
)
@ -207,9 +207,9 @@ func calculateHardLinkFingerprint(f *internal.FileMetadata) (string, error) {
return string(digester.Digest()), nil
}
// generateFileLocation generates a file location in the form $OFFSET@$PATH
func generateFileLocation(path string, offset uint64) []byte {
return []byte(fmt.Sprintf("%d@%s", offset, path))
// generateFileLocation generates a file location in the form $OFFSET:$LEN:$PATH
func generateFileLocation(path string, offset, len uint64) []byte {
return []byte(fmt.Sprintf("%d:%d:%s", offset, len, path))
}
// generateTag generates a tag in the form $DIGEST$OFFSET@LEN.
@ -245,7 +245,7 @@ func writeCache(manifest []byte, format graphdriver.DifferOutputFormat, id strin
var tags []string
for _, k := range toc {
if k.Digest != "" {
location := generateFileLocation(k.Name, 0)
location := generateFileLocation(k.Name, 0, uint64(k.Size))
off := uint64(vdata.Len())
l := uint64(len(location))
@ -276,7 +276,7 @@ func writeCache(manifest []byte, format graphdriver.DifferOutputFormat, id strin
digestLen = len(k.Digest)
}
if k.ChunkDigest != "" {
location := generateFileLocation(k.Name, uint64(k.ChunkOffset))
location := generateFileLocation(k.Name, uint64(k.ChunkOffset), uint64(k.ChunkSize))
off := uint64(vdata.Len())
l := uint64(len(location))
d := generateTag(k.ChunkDigest, off, l)
@ -490,7 +490,9 @@ func findTag(digest string, metadata *metadata) (string, uint64, uint64) {
if digest == d {
startOff := i*metadata.tagLen + metadata.digestLen
parts := strings.Split(string(metadata.tags[startOff:(i+1)*metadata.tagLen]), "@")
off, _ := strconv.ParseInt(parts[0], 10, 64)
len, _ := strconv.ParseInt(parts[1], 10, 64)
return digest, uint64(off), uint64(len)
}
@ -507,12 +509,16 @@ func (c *layersCache) findDigestInternal(digest string) (string, string, int64,
defer c.mutex.RUnlock()
for _, layer := range c.layers {
digest, off, len := findTag(digest, layer.metadata)
digest, off, tagLen := findTag(digest, layer.metadata)
if digest != "" {
position := string(layer.metadata.vdata[off : off+len])
parts := strings.SplitN(position, "@", 2)
position := string(layer.metadata.vdata[off : off+tagLen])
parts := strings.SplitN(position, ":", 3)
if len(parts) != 3 {
continue
}
offFile, _ := strconv.ParseInt(parts[0], 10, 64)
return layer.target, parts[1], offFile, nil
// parts[1] is the chunk length, currently unused.
return layer.target, parts[2], offFile, nil
}
}

View File

@ -1819,13 +1819,17 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff
mode := os.FileMode(r.Mode)
r.Name = filepath.Clean(r.Name)
r.Linkname = filepath.Clean(r.Linkname)
t, err := typeToTarType(r.Type)
if err != nil {
return output, err
}
r.Name = filepath.Clean(r.Name)
// do not modify the value of symlinks
if r.Linkname != "" && t != tar.TypeSymlink {
r.Linkname = filepath.Clean(r.Linkname)
}
if whiteoutConverter != nil {
hdr := archivetar.Header{
Typeflag: t,

4
vendor/modules.txt vendored
View File

@ -171,7 +171,7 @@ 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.57.1-0.20240207210145-1eeaf97594e9
# github.com/containers/common v0.57.1-0.20240229151045-1c65e0de241a
## explicit; go 1.20
github.com/containers/common/internal
github.com/containers/common/internal/attributedstring
@ -353,7 +353,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
# github.com/containers/storage v1.52.1-0.20240227082351-387d7c8480b0
# github.com/containers/storage v1.52.1-0.20240229151339-eadc620e74e7
## explicit; go 1.20
github.com/containers/storage
github.com/containers/storage/drivers