diff --git a/go.mod b/go.mod index a0f73aa2..7467d224 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/containers/common v0.57.0 github.com/containers/image/v5 v5.29.0 - github.com/containers/podman/v4 v4.8.0 + github.com/containers/podman/v4 v4.8.1 github.com/go-kit/log v0.2.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 diff --git a/go.sum b/go.sum index 8d9a70bc..3dd0881d 100644 --- a/go.sum +++ b/go.sum @@ -258,8 +258,8 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOjIdEM= github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPNFN4jwA9GBys= -github.com/containers/podman/v4 v4.8.0 h1:UIabha6E2/wfCCe5/Kqn9/k6MAz/CnjcADBlo6WH02Y= -github.com/containers/podman/v4 v4.8.0/go.mod h1:xtbor/KJs+xeWFS6KZmW7TGsKFNxBtnawYBS9AdFvHM= +github.com/containers/podman/v4 v4.8.1 h1:wUc3TlpHCzolc7+ADdyH/dfzIi1agKUhniBt6esRaMc= +github.com/containers/podman/v4 v4.8.1/go.mod h1:xtbor/KJs+xeWFS6KZmW7TGsKFNxBtnawYBS9AdFvHM= github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s= diff --git a/vendor/github.com/containers/podman/v4/libpod/boltdb_state_internal.go b/vendor/github.com/containers/podman/v4/libpod/boltdb_state_internal.go index 388110f2..75888410 100644 --- a/vendor/github.com/containers/podman/v4/libpod/boltdb_state_internal.go +++ b/vendor/github.com/containers/podman/v4/libpod/boltdb_state_internal.go @@ -4,7 +4,9 @@ package libpod import ( + "errors" "fmt" + "io/fs" "os" "path/filepath" "runtime" @@ -94,6 +96,7 @@ type dbConfigValidation struct { runtimeValue string key []byte defaultValue string + isPath bool } // Check if the configuration of the database is compatible with the @@ -112,42 +115,49 @@ func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error { runtime.GOOS, osKey, runtime.GOOS, + false, }, { "libpod root directory (staticdir)", filepath.Clean(rt.config.Engine.StaticDir), staticDirKey, "", + true, }, { "libpod temporary files directory (tmpdir)", filepath.Clean(rt.config.Engine.TmpDir), tmpDirKey, "", + true, }, { "storage temporary directory (runroot)", filepath.Clean(rt.StorageConfig().RunRoot), runRootKey, storeOpts.RunRoot, + true, }, { "storage graph root directory (graphroot)", filepath.Clean(rt.StorageConfig().GraphRoot), graphRootKey, storeOpts.GraphRoot, + true, }, { "storage graph driver", rt.StorageConfig().GraphDriverName, graphDriverKey, storeOpts.GraphDriverName, + false, }, { "volume path", rt.config.Engine.VolumePath, volPathKey, "", + true, }, } @@ -222,22 +232,45 @@ func readOnlyValidateConfig(bucket *bolt.Bucket, toCheck dbConfigValidation) (bo } dbValue := string(keyBytes) + ourValue := toCheck.runtimeValue + + // Tolerate symlinks when possible - most relevant for OStree systems + // and rootless containers, where we want to put containers in /home, + // which is symlinked to /var/home. + if toCheck.isPath { + if dbValue != "" { + // Ignore ENOENT on both, on a fresh system some paths + // may not exist this early in Libpod init. + dbVal, err := filepath.EvalSymlinks(dbValue) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return false, fmt.Errorf("evaluating symlinks on DB %s path %q: %w", toCheck.name, dbValue, err) + } + dbValue = dbVal + } + if ourValue != "" { + ourVal, err := filepath.EvalSymlinks(ourValue) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return false, fmt.Errorf("evaluating symlinks on configured %s path %q: %w", toCheck.name, ourValue, err) + } + ourValue = ourVal + } + } - if toCheck.runtimeValue != dbValue { + if ourValue != dbValue { // If the runtime value is the empty string and default is not, // check against default. - if toCheck.runtimeValue == "" && toCheck.defaultValue != "" && dbValue == toCheck.defaultValue { + if ourValue == "" && toCheck.defaultValue != "" && dbValue == toCheck.defaultValue { return true, nil } // If the DB value is the empty string, check that the runtime // value is the default. - if dbValue == "" && toCheck.defaultValue != "" && toCheck.runtimeValue == toCheck.defaultValue { + if dbValue == "" && toCheck.defaultValue != "" && ourValue == toCheck.defaultValue { return true, nil } return true, fmt.Errorf("database %s %q does not match our %s %q: %w", - toCheck.name, dbValue, toCheck.name, toCheck.runtimeValue, define.ErrDBBadConfig) + toCheck.name, dbValue, toCheck.name, ourValue, define.ErrDBBadConfig) } return true, nil diff --git a/vendor/github.com/containers/podman/v4/libpod/container.go b/vendor/github.com/containers/podman/v4/libpod/container.go index bc904f0b..9bd80283 100644 --- a/vendor/github.com/containers/podman/v4/libpod/container.go +++ b/vendor/github.com/containers/podman/v4/libpod/container.go @@ -688,15 +688,7 @@ func (c *Container) Hostname() string { // if the container is not running in a private UTS namespace, // return the host's hostname. - privateUTS := false - if c.config.Spec.Linux != nil { - for _, ns := range c.config.Spec.Linux.Namespaces { - if ns.Type == spec.UTSNamespace { - privateUTS = true - break - } - } - } + privateUTS := c.hasPrivateUTS() if !privateUTS { hostname, err := os.Hostname() if err == nil { diff --git a/vendor/github.com/containers/podman/v4/libpod/container_internal_freebsd.go b/vendor/github.com/containers/podman/v4/libpod/container_internal_freebsd.go index 2ecb931f..152de929 100644 --- a/vendor/github.com/containers/podman/v4/libpod/container_internal_freebsd.go +++ b/vendor/github.com/containers/podman/v4/libpod/container_internal_freebsd.go @@ -389,3 +389,10 @@ func (c *Container) getPlatformRunPath() (string, error) { func (c *Container) addMaskedPaths(g *generate.Generator) { // There are currently no FreeBSD-specific masked paths } + +func (c *Container) hasPrivateUTS() bool { + // Currently we always use a private UTS namespace on FreeBSD. This + // should be optional but needs a FreeBSD section in the OCI runtime + // specification. + return true +} diff --git a/vendor/github.com/containers/podman/v4/libpod/container_internal_linux.go b/vendor/github.com/containers/podman/v4/libpod/container_internal_linux.go index 6a8774b2..7f6508d3 100644 --- a/vendor/github.com/containers/podman/v4/libpod/container_internal_linux.go +++ b/vendor/github.com/containers/podman/v4/libpod/container_internal_linux.go @@ -811,3 +811,16 @@ func (c *Container) addMaskedPaths(g *generate.Generator) { g.AddLinuxMaskedPaths("/sys/devices/virtual/powercap") } } + +func (c *Container) hasPrivateUTS() bool { + privateUTS := false + if c.config.Spec.Linux != nil { + for _, ns := range c.config.Spec.Linux.Namespaces { + if ns.Type == spec.UTSNamespace { + privateUTS = true + break + } + } + } + return privateUTS +} diff --git a/vendor/github.com/containers/podman/v4/libpod/sqlite_state.go b/vendor/github.com/containers/podman/v4/libpod/sqlite_state.go index 9c88eb4e..b1d366ae 100644 --- a/vendor/github.com/containers/podman/v4/libpod/sqlite_state.go +++ b/vendor/github.com/containers/podman/v4/libpod/sqlite_state.go @@ -7,6 +7,7 @@ import ( "database/sql" "errors" "fmt" + "io/fs" "os" "path/filepath" goruntime "runtime" @@ -41,13 +42,17 @@ const ( sqliteOptionForeignKeys = "&_foreign_keys=1" // Make sure that transactions happen exclusively. sqliteOptionTXLock = "&_txlock=exclusive" + // Make sure busy timeout is set to high value to keep retying when the db is locked. + // Timeout is in ms, so set it to 100s to have enough time to retry the operations. + sqliteOptionBusyTimeout = "&_busy_timeout=100000" // Assembled sqlite options used when opening the database. sqliteOptions = "db.sql?" + sqliteOptionLocation + sqliteOptionSynchronous + sqliteOptionForeignKeys + - sqliteOptionTXLock + sqliteOptionTXLock + + sqliteOptionBusyTimeout ) // NewSqliteState creates a new SQLite-backed state database. @@ -312,14 +317,14 @@ func (s *SQLiteState) ValidateDBConfig(runtime *Runtime) (defErr error) { );` var ( - os, staticDir, tmpDir, graphRoot, runRoot, graphDriver, volumePath string - runtimeOS = goruntime.GOOS - runtimeStaticDir = filepath.Clean(s.runtime.config.Engine.StaticDir) - runtimeTmpDir = filepath.Clean(s.runtime.config.Engine.TmpDir) - runtimeGraphRoot = filepath.Clean(s.runtime.StorageConfig().GraphRoot) - runtimeRunRoot = filepath.Clean(s.runtime.StorageConfig().RunRoot) - runtimeGraphDriver = s.runtime.StorageConfig().GraphDriverName - runtimeVolumePath = filepath.Clean(s.runtime.config.Engine.VolumePath) + dbOS, staticDir, tmpDir, graphRoot, runRoot, graphDriver, volumePath string + runtimeOS = goruntime.GOOS + runtimeStaticDir = filepath.Clean(s.runtime.config.Engine.StaticDir) + runtimeTmpDir = filepath.Clean(s.runtime.config.Engine.TmpDir) + runtimeGraphRoot = filepath.Clean(s.runtime.StorageConfig().GraphRoot) + runtimeRunRoot = filepath.Clean(s.runtime.StorageConfig().RunRoot) + runtimeGraphDriver = s.runtime.StorageConfig().GraphDriverName + runtimeVolumePath = filepath.Clean(s.runtime.config.Engine.VolumePath) ) // Some fields may be empty, indicating they are set to the default. @@ -356,7 +361,7 @@ func (s *SQLiteState) ValidateDBConfig(runtime *Runtime) (defErr error) { row := tx.QueryRow("SELECT Os, StaticDir, TmpDir, GraphRoot, RunRoot, GraphDriver, VolumeDir FROM DBConfig;") - if err := row.Scan(&os, &staticDir, &tmpDir, &graphRoot, &runRoot, &graphDriver, &volumePath); err != nil { + if err := row.Scan(&dbOS, &staticDir, &tmpDir, &graphRoot, &runRoot, &graphDriver, &volumePath); err != nil { if errors.Is(err, sql.ErrNoRows) { if _, err := tx.Exec(createRow, 1, schemaVersion, runtimeOS, runtimeStaticDir, runtimeTmpDir, runtimeGraphRoot, @@ -374,11 +379,26 @@ func (s *SQLiteState) ValidateDBConfig(runtime *Runtime) (defErr error) { return fmt.Errorf("retrieving DB config: %w", err) } - if err := tx.Commit(); err != nil { - return fmt.Errorf("committing database validation row: %w", err) - } + checkField := func(fieldName, dbVal, ourVal string, isPath bool) error { + if isPath { + // Evaluate symlinks. Ignore ENOENT. No guarantee all + // directories exist this early in Libpod init. + if dbVal != "" { + dbValClean, err := filepath.EvalSymlinks(dbVal) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("cannot evaluate symlinks on DB %s path %q: %w", fieldName, dbVal, err) + } + dbVal = dbValClean + } + if ourVal != "" { + ourValClean, err := filepath.EvalSymlinks(ourVal) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("cannot evaluate symlinks on our %s path %q: %w", fieldName, ourVal, err) + } + ourVal = ourValClean + } + } - checkField := func(fieldName, dbVal, ourVal string) error { if dbVal != ourVal { return fmt.Errorf("database %s %q does not match our %s %q: %w", fieldName, dbVal, fieldName, ourVal, define.ErrDBBadConfig) } @@ -386,28 +406,34 @@ func (s *SQLiteState) ValidateDBConfig(runtime *Runtime) (defErr error) { return nil } - if err := checkField("os", os, runtimeOS); err != nil { + if err := checkField("os", dbOS, runtimeOS, false); err != nil { return err } - if err := checkField("static dir", staticDir, runtimeStaticDir); err != nil { + if err := checkField("static dir", staticDir, runtimeStaticDir, true); err != nil { return err } - if err := checkField("tmp dir", tmpDir, runtimeTmpDir); err != nil { + if err := checkField("tmp dir", tmpDir, runtimeTmpDir, true); err != nil { return err } - if err := checkField("graph root", graphRoot, runtimeGraphRoot); err != nil { + if err := checkField("graph root", graphRoot, runtimeGraphRoot, true); err != nil { return err } - if err := checkField("run root", runRoot, runtimeRunRoot); err != nil { + if err := checkField("run root", runRoot, runtimeRunRoot, true); err != nil { return err } - if err := checkField("graph driver", graphDriver, runtimeGraphDriver); err != nil { + if err := checkField("graph driver", graphDriver, runtimeGraphDriver, false); err != nil { return err } - if err := checkField("volume path", volumePath, runtimeVolumePath); err != nil { + if err := checkField("volume path", volumePath, runtimeVolumePath, true); err != nil { return err } + if err := tx.Commit(); err != nil { + return fmt.Errorf("committing database validation row: %w", err) + } + // Do not return any error after the commit call because the defer will + // try to roll back the transaction which results in an logged error. + return nil } @@ -1698,6 +1724,10 @@ func (s *SQLiteState) RemovePodContainers(pod *Pod) (defErr error) { return err } + if err := tx.Commit(); err != nil { + return fmt.Errorf("committing pod containers %s removal transaction: %w", pod.ID(), err) + } + return nil } diff --git a/vendor/github.com/containers/podman/v4/pkg/bindings/containers/exec.go b/vendor/github.com/containers/podman/v4/pkg/bindings/containers/exec.go index 9a73a656..395ef06d 100644 --- a/vendor/github.com/containers/podman/v4/pkg/bindings/containers/exec.go +++ b/vendor/github.com/containers/podman/v4/pkg/bindings/containers/exec.go @@ -114,10 +114,15 @@ func ExecStart(ctx context.Context, sessionID string, options *ExecStartOptions) // ExecRemove removes a given exec session. func ExecRemove(ctx context.Context, sessionID string, options *ExecRemoveOptions) error { + v := bindings.ServiceVersion(ctx) + // The exec remove endpoint was added in 4.8. + if v.Major < 4 || (v.Major == 4 && v.Minor < 8) { + // Do no call this endpoint as it will not be supported on the server and throw an "NOT FOUND" error. + return bindings.NewAPIVersionError("/exec/{id}/remove", v, "4.8.0") + } if options == nil { options = new(ExecRemoveOptions) } - _ = options conn, err := bindings.GetClient(ctx) if err != nil { return err diff --git a/vendor/github.com/containers/podman/v4/pkg/bindings/errors.go b/vendor/github.com/containers/podman/v4/pkg/bindings/errors.go index 039d2187..a7cbeb30 100644 --- a/vendor/github.com/containers/podman/v4/pkg/bindings/errors.go +++ b/vendor/github.com/containers/podman/v4/pkg/bindings/errors.go @@ -6,6 +6,7 @@ import ( "fmt" "io" + "github.com/blang/semver/v4" "github.com/containers/podman/v4/pkg/errorhandling" ) @@ -61,3 +62,26 @@ func CheckResponseCode(inError error) (int, error) { return -1, errors.New("is not type ErrorModel") } } + +type APIVersionError struct { + endpoint string + serverVersion *semver.Version + requiredVersion string +} + +// NewAPIVersionError create bindings error when the endpoint on the server is not supported +// because the version is to old. +// - endpoint is the name fo the endpoint (e.g. /containers/json) +// - version is the server API version +// - requiredVersion is the server version need to use said endpoint +func NewAPIVersionError(endpoint string, version *semver.Version, requiredVersion string) *APIVersionError { + return &APIVersionError{ + endpoint: endpoint, + serverVersion: version, + requiredVersion: requiredVersion, + } +} + +func (e *APIVersionError) Error() string { + return fmt.Sprintf("API server version is %s, need at least %s to call %s", e.serverVersion.String(), e.requiredVersion, e.endpoint) +} diff --git a/vendor/github.com/containers/podman/v4/pkg/domain/infra/abi/play.go b/vendor/github.com/containers/podman/v4/pkg/domain/infra/abi/play.go index 1d1f3a64..9a1811bd 100644 --- a/vendor/github.com/containers/podman/v4/pkg/domain/infra/abi/play.go +++ b/vendor/github.com/containers/podman/v4/pkg/domain/infra/abi/play.go @@ -714,6 +714,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY podSpec.PodSpecGen.ServiceContainerID = serviceContainer.ID() } + if options.Replace { + if _, err := ic.PodRm(ctx, []string{podName}, entities.PodRmOptions{Force: true, Ignore: true}); err != nil { + return nil, nil, fmt.Errorf("replacing pod %v: %w", podName, err) + } + } // Create the Pod pod, err := generate.MakePod(&podSpec, ic.Libpod) if err != nil { diff --git a/vendor/github.com/containers/podman/v4/pkg/domain/infra/tunnel/containers.go b/vendor/github.com/containers/podman/v4/pkg/domain/infra/tunnel/containers.go index 55dc6a0d..d57d2cd6 100644 --- a/vendor/github.com/containers/podman/v4/pkg/domain/infra/tunnel/containers.go +++ b/vendor/github.com/containers/podman/v4/pkg/domain/infra/tunnel/containers.go @@ -17,6 +17,7 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/api/handlers" + "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/bindings/containers" "github.com/containers/podman/v4/pkg/bindings/images" "github.com/containers/podman/v4/pkg/domain/entities" @@ -588,6 +589,11 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrID string, o } defer func() { if err := containers.ExecRemove(ic.ClientCtx, sessionID, nil); err != nil { + apiErr := new(bindings.APIVersionError) + if errors.As(err, &apiErr) { + // if the API is to old do not throw an error + return + } if retErr == nil { exitCode = -1 retErr = err diff --git a/vendor/github.com/containers/podman/v4/version/rawversion/version.go b/vendor/github.com/containers/podman/v4/version/rawversion/version.go index 67e21783..9e4fd267 100644 --- a/vendor/github.com/containers/podman/v4/version/rawversion/version.go +++ b/vendor/github.com/containers/podman/v4/version/rawversion/version.go @@ -7,4 +7,4 @@ package rawversion // // NOTE: remember to bump the version at the top of the top-level README.md // file when this is bumped. -const RawVersion = "4.8.0" +const RawVersion = "4.8.1" diff --git a/vendor/modules.txt b/vendor/modules.txt index 2ac69819..e162d384 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -288,7 +288,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7 github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/utils github.com/containers/ocicrypt/utils/keyprovider -# github.com/containers/podman/v4 v4.8.0 +# github.com/containers/podman/v4 v4.8.1 ## explicit; go 1.18 github.com/containers/podman/v4/cmd/podman/parse github.com/containers/podman/v4/cmd/podman/registry