mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-10-25 07:17:35 +00:00
Merge current main into v5.2 branch
We want everything from main into the v5.2 branch. We'll consider ourselves officially branched after v5.2.0-rc2 releases. Signed-off-by: Matt Heon <mheon@redhat.com>
This commit is contained in:
commit
579f36a061
49 changed files with 942 additions and 661 deletions
|
|
@ -247,8 +247,5 @@ func run(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
if cmd.Flag("gpus").Changed {
|
||||
logrus.Info("--gpus is a Docker specific option and is a NOOP")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,8 +126,11 @@ func init() {
|
|||
_ = initCmd.RegisterFlagCompletionFunc(USBFlagName, completion.AutocompleteDefault)
|
||||
|
||||
VolumeDriverFlagName := "volume-driver"
|
||||
flags.StringVar(&initOpts.VolumeDriver, VolumeDriverFlagName, "", "Optional volume driver")
|
||||
flags.String(VolumeDriverFlagName, "", "Optional volume driver")
|
||||
_ = initCmd.RegisterFlagCompletionFunc(VolumeDriverFlagName, completion.AutocompleteDefault)
|
||||
if err := flags.MarkDeprecated(VolumeDriverFlagName, "will be ignored"); err != nil {
|
||||
logrus.Error("unable to mark volume-driver flag deprecated")
|
||||
}
|
||||
|
||||
IgnitionPathFlagName := "ignition-path"
|
||||
flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package connection
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
|
|
@ -14,10 +13,16 @@ import (
|
|||
var (
|
||||
// Skip creating engines since this command will obtain connection information to said engines.
|
||||
rmCmd = &cobra.Command{
|
||||
Use: "remove [options] NAME",
|
||||
Aliases: []string{"rm"},
|
||||
Long: `Delete named destination from podman configuration`,
|
||||
Short: "Delete named destination",
|
||||
Use: "remove [options] NAME",
|
||||
Aliases: []string{"rm"},
|
||||
Long: `Delete named destination from podman configuration`,
|
||||
Short: "Delete named destination",
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
if rmOpts.All {
|
||||
return nil
|
||||
}
|
||||
return cobra.ExactArgs(1)(cmd, args)
|
||||
},
|
||||
ValidArgsFunction: common.AutocompleteSystemConnections,
|
||||
RunE: rm,
|
||||
Example: `podman system connection remove devl
|
||||
|
|
@ -60,10 +65,6 @@ func rm(cmd *cobra.Command, args []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if len(args) != 1 {
|
||||
return errors.New("accepts 1 arg(s), received 0")
|
||||
}
|
||||
|
||||
delete(cfg.Connection.Connections, args[0])
|
||||
if cfg.Connection.Default == args[0] {
|
||||
cfg.Connection.Default = ""
|
||||
|
|
|
|||
|
|
@ -158,9 +158,12 @@ func appendSubPaths(dirs []string, path string, isUserFlag bool, filterPtr func(
|
|||
}
|
||||
|
||||
err = filepath.WalkDir(resolvedPath, func(_path string, info os.DirEntry, err error) error {
|
||||
if info == nil || info.IsDir() {
|
||||
if filterPtr == nil || filterPtr(_path, isUserFlag) {
|
||||
dirs = append(dirs, _path)
|
||||
// Ignore drop-in directory subpaths
|
||||
if !strings.HasSuffix(_path, ".d") {
|
||||
if info == nil || info.IsDir() {
|
||||
if filterPtr == nil || filterPtr(_path, isUserFlag) {
|
||||
dirs = append(dirs, _path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
@ -256,16 +259,11 @@ func loadUnitDropins(unit *parser.UnitFile, sourcePaths []string) error {
|
|||
}
|
||||
|
||||
dropinDirs := []string{}
|
||||
unitDropinPaths := unit.GetUnitDropinPaths()
|
||||
|
||||
for _, sourcePath := range sourcePaths {
|
||||
dropinDirs = append(dropinDirs, path.Join(sourcePath, unit.Filename+".d"))
|
||||
}
|
||||
|
||||
// For instantiated templates, also look in the non-instanced template dropin dirs
|
||||
templateBase, templateInstance := unit.GetTemplateParts()
|
||||
if templateBase != "" && templateInstance != "" {
|
||||
for _, sourcePath := range sourcePaths {
|
||||
dropinDirs = append(dropinDirs, path.Join(sourcePath, templateBase+".d"))
|
||||
for _, dropinPath := range unitDropinPaths {
|
||||
dropinDirs = append(dropinDirs, path.Join(sourcePath, dropinPath))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -359,15 +357,14 @@ func enableServiceFile(outputPath string, service *parser.UnitFile) {
|
|||
}
|
||||
|
||||
serviceFilename := service.Filename
|
||||
templateBase, templateInstance := service.GetTemplateParts()
|
||||
templateBase, templateInstance, isTemplate := service.GetTemplateParts()
|
||||
|
||||
// For non-instantiated template service we only support installs if a
|
||||
// DefaultInstance is given. Otherwise we ignore the Install group, but
|
||||
// it is still useful when instantiating the unit via a symlink.
|
||||
if templateBase != "" && templateInstance == "" {
|
||||
if isTemplate && templateInstance == "" {
|
||||
if defaultInstance, ok := service.Lookup(quadlet.InstallGroup, "DefaultInstance"); ok {
|
||||
parts := strings.SplitN(templateBase, "@", 2)
|
||||
serviceFilename = parts[0] + "@" + defaultInstance + parts[1]
|
||||
serviceFilename = templateBase + "@" + defaultInstance + filepath.Ext(serviceFilename)
|
||||
} else {
|
||||
serviceFilename = ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ else
|
|||
endif
|
||||
GVPROXY_VERSION ?= 0.7.3
|
||||
VFKIT_VERSION ?= 0.5.1
|
||||
KRUNKIT_VERSION ?= 0.1.1
|
||||
KRUNKIT_VERSION ?= 0.1.2
|
||||
GVPROXY_RELEASE_URL ?= https://github.com/containers/gvisor-tap-vsock/releases/download/v$(GVPROXY_VERSION)/gvproxy-darwin
|
||||
VFKIT_RELEASE_URL ?= https://github.com/crc-org/vfkit/releases/download/v$(VFKIT_VERSION)/vfkit-unsigned
|
||||
KRUNKIT_RELEASE_URL ?= https://github.com/containers/krunkit/releases/download/v$(KRUNKIT_VERSION)/krunkit-podman-unsigned-$(KRUNKIT_VERSION).tgz
|
||||
|
|
|
|||
|
|
@ -160,10 +160,6 @@ Example: `-v "$HOME/git:$HOME/git:ro,security_model=none"`
|
|||
Default volume mounts are defined in *containers.conf*. Unless changed, the default values
|
||||
is `$HOME:$HOME`.
|
||||
|
||||
#### **--volume-driver**
|
||||
|
||||
Driver to use for mounting volumes from the host, such as `virtfs`.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
Initialize the default Podman machine, pulling the content from the internet.
|
||||
|
|
|
|||
|
|
@ -50,11 +50,15 @@ other sections are passed on untouched, allowing the use of any normal systemd c
|
|||
like dependencies or cgroup limits.
|
||||
|
||||
The source files also support drop-ins in the same [way systemd does](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html).
|
||||
For a given source file (say `foo.container`), the corresponding `.d`directory (in this
|
||||
case `foo.container.d`) will be scanned for files with a `.conf` extension that are merged into
|
||||
the base file in alphabetical order. The format of these drop-in files is the same as the base file.
|
||||
This is useful to alter or add configuration settings for a unit, without having to modify unit
|
||||
files.
|
||||
For a given source file (`foo.container`), the corresponding `.d` directory (`foo.container.d`) will
|
||||
be scanned for files with a `.conf` extension, which are then merged into the base file in alphabetical
|
||||
order. Top-level type drop-ins (`container.d`) will also be included. If the unit contains dashes ("-")
|
||||
in the name (`foo-bar-baz.container`), then the drop-in directories generated by truncating the name after
|
||||
the dash are searched as well (`foo-.container.d` and `foo-bar-.container.d`). Drop-in files with the same name
|
||||
further down the hierarchy override those further up (`foo-bar-baz.container.d/10-override.conf` overrides
|
||||
`foo-bar-.container.d/10-override.conf`, which overrides `foo-.service.d/10-override.conf`, which overrides
|
||||
`container.d/10-override.conf`). The format of these drop-in files is the same as the base file. This is useful
|
||||
to alter or add configuration settings for a unit, without having to modify unit files.
|
||||
|
||||
For rootless containers, when administrators place Quadlet files in the
|
||||
/etc/containers/systemd/users directory, all users' sessions execute the
|
||||
|
|
@ -302,6 +306,7 @@ Valid options for `[Container]` are listed below:
|
|||
| SecurityLabelNested=true | --security-opt label=nested |
|
||||
| SecurityLabelType=spc_t | --security-opt label=type:spc_t |
|
||||
| ShmSize=100m | --shm-size=100m |
|
||||
| StopSignal=SIGINT | --stop-signal=SIGINT |
|
||||
| StopTimeout=20 | --stop-timeout=20 |
|
||||
| SubGIDMap=gtest | --subgidname=gtest |
|
||||
| SubUIDMap=utest | --subuidname=utest |
|
||||
|
|
@ -727,6 +732,12 @@ Size of /dev/shm.
|
|||
|
||||
This is equivalent to the Podman `--shm-size` option and generally has the form `number[unit]`
|
||||
|
||||
### `StopSignal=`
|
||||
|
||||
Signal to stop a container. Default is **SIGTERM**.
|
||||
|
||||
This is equivalent to the Podman `--stop-signal` option
|
||||
|
||||
### `StopTimeout=`
|
||||
|
||||
Seconds to wait before forcibly stopping the container.
|
||||
|
|
|
|||
8
go.mod
8
go.mod
|
|
@ -13,7 +13,7 @@ require (
|
|||
github.com/checkpoint-restore/go-criu/v7 v7.1.0
|
||||
github.com/containernetworking/plugins v1.5.1
|
||||
github.com/containers/buildah v1.36.1-0.20240715114330-4a82e0a3f382
|
||||
github.com/containers/common v0.59.1-0.20240715151621-fdf625dfee0e
|
||||
github.com/containers/common v0.59.1-0.20240717135212-fdbae3a180cb
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.7.4-0.20240515153903-01a1a0cd3f70
|
||||
github.com/containers/image/v5 v5.31.1-0.20240711123249-1dbd8fbbe516
|
||||
|
|
@ -60,14 +60,14 @@ require (
|
|||
github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc
|
||||
github.com/opencontainers/selinux v1.11.0
|
||||
github.com/openshift/imagebuilder v1.2.11
|
||||
github.com/rootless-containers/rootlesskit/v2 v2.1.0
|
||||
github.com/rootless-containers/rootlesskit/v2 v2.2.0
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
||||
github.com/vbauerster/mpb/v8 v8.7.3
|
||||
github.com/vbauerster/mpb/v8 v8.7.4
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
go.etcd.io/bbolt v1.3.10
|
||||
golang.org/x/crypto v0.25.0
|
||||
|
|
@ -200,7 +200,7 @@ require (
|
|||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||
|
|
|
|||
27
go.sum
27
go.sum
|
|
@ -79,8 +79,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.36.1-0.20240715114330-4a82e0a3f382 h1:NUScZGjAC6Cd1KuPcnCac10Q/gz01PULzh7Em/VXZOc=
|
||||
github.com/containers/buildah v1.36.1-0.20240715114330-4a82e0a3f382/go.mod h1:HlwJHYRlP5j8siiPY46I8py00hlGxWPC/vCZZ/01EEU=
|
||||
github.com/containers/common v0.59.1-0.20240715151621-fdf625dfee0e h1:x6PiZObWn9XD9lcvC6ShqDvvoTsRBktY8ycuwhlWWug=
|
||||
github.com/containers/common v0.59.1-0.20240715151621-fdf625dfee0e/go.mod h1:KrQ9y5qa7TBVzp7qs7I1MVi6Uxntu0hM5wjd5bmvMnM=
|
||||
github.com/containers/common v0.59.1-0.20240717135212-fdbae3a180cb h1:9OgHqOACzWRzPFewtx/lOSKnPvWAMMlW3ruvXQL4fP4=
|
||||
github.com/containers/common v0.59.1-0.20240717135212-fdbae3a180cb/go.mod h1:KrQ9y5qa7TBVzp7qs7I1MVi6Uxntu0hM5wjd5bmvMnM=
|
||||
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.4-0.20240515153903-01a1a0cd3f70 h1:aACcXSIgcuPq5QdNZZ8B53BCdhqYvw33/8QmZWJATvg=
|
||||
|
|
@ -294,15 +294,14 @@ github.com/hugelgupf/vmtest v0.0.0-20230810222836-f8c8e381617c h1:4A+BVHylCBQPxl
|
|||
github.com/hugelgupf/vmtest v0.0.0-20230810222836-f8c8e381617c/go.mod h1:d2FMzS0rIF+3Daufcw660EZfTJihdNPeEwBBJgO4Ap0=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20230731140434-0f9eb93a696c h1:P/3mFnHCv1A/ej4m8pF5EB6FUt9qEL2Q9lfrcUNwCYs=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20230731140434-0f9eb93a696c/go.mod h1:7474bZ1YNCvarT6WFKie4kEET6J0KYRDC4XJqqXzQW4=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240710054256-ddd8a41251c9 h1:LZJWucZz7ztCqY6Jsu7N9g124iJ2kt/O62j3+UchZFg=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240710054256-ddd8a41251c9/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs=
|
||||
github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
|
@ -407,9 +406,8 @@ github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqw
|
|||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||
|
|
@ -435,8 +433,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
|||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/rootless-containers/rootlesskit/v2 v2.1.0 h1:dKqduSlzo5TlTv7tTIoTct2cRUNQf+soqcs+6b1ynvE=
|
||||
github.com/rootless-containers/rootlesskit/v2 v2.1.0/go.mod h1:W+5NaXv3l2sD4LiPxRWLOlY+p9H0+Ev71zel/zFRnLo=
|
||||
github.com/rootless-containers/rootlesskit/v2 v2.2.0 h1:qTA3QyfsZSKmvKDL7m5lCl55OmJZXmKf381dSb5Ig9E=
|
||||
github.com/rootless-containers/rootlesskit/v2 v2.2.0/go.mod h1:AyUlpgPnMv085smZXp5mt4D9q4mNjbHOcZwaVobRzyU=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
|
||||
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
|
|
@ -502,16 +500,16 @@ github.com/u-root/gobusybox/src v0.0.0-20230806212452-e9366a5b9fdc h1:udgfN9Qy57
|
|||
github.com/u-root/gobusybox/src v0.0.0-20230806212452-e9366a5b9fdc/go.mod h1:lYt+LVfZBBwDZ3+PHk4k/c/TnKOkjJXiJO73E32Mmpc=
|
||||
github.com/u-root/u-root v0.11.1-0.20230807200058-f87ad7ccb594 h1:1AIJqOtdEufYfGb3eRpdaqWONzBOpAwrg1fehbWg+Mg=
|
||||
github.com/u-root/u-root v0.11.1-0.20230807200058-f87ad7ccb594/go.mod h1:PQzg9XJGp6Y1hRmTUruSO7lR7kKR6FpoSObf5n5bTfE=
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
|
||||
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
|
||||
github.com/vbauerster/mpb/v8 v8.7.3 h1:n/mKPBav4FFWp5fH4U0lPpXfiOmCEgl5Yx/NM3tKJA0=
|
||||
github.com/vbauerster/mpb/v8 v8.7.3/go.mod h1:9nFlNpDGVoTmQ4QvNjSLtwLmAFjwmq0XaAF26toHGNM=
|
||||
github.com/vbauerster/mpb/v8 v8.7.4 h1:p4f16iMfUt3PkAC73SCzAtgtSf8TYDqEbJUT3odPrPo=
|
||||
github.com/vbauerster/mpb/v8 v8.7.4/go.mod h1:r1B5k2Ljj5KJFCekfihbiqyV4VaaRTANYmvWA2btufI=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
|
|
@ -636,7 +634,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ declare -a hidden=(
|
|||
"docker -D" # Hidden
|
||||
"docker -H" # Hidden
|
||||
|
||||
"docker .* --gpus" # Not likely to be implemented
|
||||
"docker .* --isolation" # Only for Windows containers
|
||||
"docker .* --kernel-memory" # CGroupsV1 only, present but hidden
|
||||
"docker .* --link" # Deprecated in docker
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package libpod
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -87,30 +88,17 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define.
|
|||
if len(newCommand) < 1 || newCommand[0] == "" {
|
||||
return define.HealthCheckNotDefined, "", fmt.Errorf("container %s has no defined healthcheck", c.ID())
|
||||
}
|
||||
rPipe, wPipe, err := os.Pipe()
|
||||
if err != nil {
|
||||
return define.HealthCheckInternalError, "", fmt.Errorf("unable to create pipe for healthcheck session: %w", err)
|
||||
}
|
||||
defer wPipe.Close()
|
||||
defer rPipe.Close()
|
||||
|
||||
streams := new(define.AttachStreams)
|
||||
output := &bytes.Buffer{}
|
||||
|
||||
streams.InputStream = bufio.NewReader(os.Stdin)
|
||||
streams.OutputStream = wPipe
|
||||
streams.ErrorStream = wPipe
|
||||
streams.OutputStream = output
|
||||
streams.ErrorStream = output
|
||||
streams.AttachOutput = true
|
||||
streams.AttachError = true
|
||||
streams.AttachInput = true
|
||||
|
||||
stdout := []string{}
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(rPipe)
|
||||
for scanner.Scan() {
|
||||
stdout = append(stdout, scanner.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
logrus.Debugf("executing health check command %s for %s", strings.Join(newCommand, " "), c.ID())
|
||||
timeStart := time.Now()
|
||||
hcResult := define.HealthCheckSuccess
|
||||
|
|
@ -154,7 +142,7 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define.
|
|||
}
|
||||
}
|
||||
|
||||
eventLog := strings.Join(stdout, "\n")
|
||||
eventLog := output.String()
|
||||
if len(eventLog) > MaxHealthCheckLogLength {
|
||||
eventLog = eventLog[:MaxHealthCheckLogLength]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ type PodContainerStats struct {
|
|||
}
|
||||
|
||||
// GetPodStats returns the stats for each of its containers
|
||||
func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerStats) (map[string]*define.ContainerStats, error) {
|
||||
func (p *Pod) GetPodStats() (map[string]*define.ContainerStats, error) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
|
|
@ -472,15 +472,15 @@ func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerSta
|
|||
}
|
||||
newContainerStats := make(map[string]*define.ContainerStats)
|
||||
for _, c := range containers {
|
||||
newStats, err := c.GetContainerStats(previousContainerStats[c.ID()])
|
||||
// If the container wasn't running, don't include it
|
||||
// but also suppress the error
|
||||
if err != nil && !errors.Is(err, define.ErrCtrStateInvalid) {
|
||||
newStats, err := c.GetContainerStats(nil)
|
||||
if err != nil {
|
||||
// If the container wasn't running ignore it
|
||||
if errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
newContainerStats[c.ID()] = newStats
|
||||
}
|
||||
newContainerStats[c.ID()] = newStats
|
||||
}
|
||||
return newContainerStats, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,17 +39,13 @@ 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 retrying 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 +
|
||||
sqliteOptionBusyTimeout
|
||||
sqliteOptionTXLock
|
||||
)
|
||||
|
||||
// NewSqliteState creates a new SQLite-backed state database.
|
||||
|
|
@ -71,7 +67,18 @@ func NewSqliteState(runtime *Runtime) (_ State, defErr error) {
|
|||
return nil, fmt.Errorf("creating root directory: %w", err)
|
||||
}
|
||||
|
||||
conn, err := sql.Open("sqlite3", filepath.Join(basePath, sqliteOptions))
|
||||
// Make sure busy timeout is set to high value to keep retrying when the db is locked.
|
||||
// Timeout is in ms, so set it to 100s to have enough time to retry the operations.
|
||||
// Some users might want to experiment with different timeout values (#23236)
|
||||
// DO NOT DOCUMENT or recommend PODMAN_SQLITE_BUSY_TIMEOUT outside of testing.
|
||||
busyTimeout := "100000"
|
||||
if env, ok := os.LookupEnv("PODMAN_SQLITE_BUSY_TIMEOUT"); ok {
|
||||
logrus.Debugf("PODMAN_SQLITE_BUSY_TIMEOUT is set to %s", env)
|
||||
busyTimeout = env
|
||||
}
|
||||
sqliteOptionBusyTimeout := "&_busy_timeout=" + busyTimeout
|
||||
|
||||
conn, err := sql.Open("sqlite3", filepath.Join(basePath, sqliteOptions+sqliteOptionBusyTimeout))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("initializing sqlite database: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package autoupdate
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
|
|
@ -367,12 +368,15 @@ func (u *updater) assembleTasks(ctx context.Context) []error {
|
|||
|
||||
u.unitToTasks = make(map[string][]*task)
|
||||
|
||||
errors := []error{}
|
||||
errs := []error{}
|
||||
for _, c := range allContainers {
|
||||
ctr := c
|
||||
state, err := ctr.State()
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
// container may have been removed in the meantime ignore it and not print errors
|
||||
if !errors.Is(err, define.ErrNoSuchCtr) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Only update running containers.
|
||||
|
|
@ -389,7 +393,7 @@ func (u *updater) assembleTasks(ctx context.Context) []error {
|
|||
}
|
||||
policy, err := LookupPolicy(value)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
if policy == PolicyDefault {
|
||||
|
|
@ -400,11 +404,11 @@ func (u *updater) assembleTasks(ctx context.Context) []error {
|
|||
// stored as a label at container creation.
|
||||
unit, exists, err := u.systemdUnitForContainer(ctr, labels)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
if !exists {
|
||||
errors = append(errors, fmt.Errorf("auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable))
|
||||
errs = append(errs, fmt.Errorf("auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable))
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -412,13 +416,13 @@ func (u *updater) assembleTasks(ctx context.Context) []error {
|
|||
image, exists := imageMap[id]
|
||||
if !exists {
|
||||
err := fmt.Errorf("internal error: no image found for ID %s", id)
|
||||
errors = append(errors, err)
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
rawImageName := ctr.RawImageName()
|
||||
if rawImageName == "" {
|
||||
errors = append(errors, fmt.Errorf("locally auto-updating container %q: raw-image name is empty", ctr.ID()))
|
||||
errs = append(errs, fmt.Errorf("locally auto-updating container %q: raw-image name is empty", ctr.ID()))
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +447,7 @@ func (u *updater) assembleTasks(ctx context.Context) []error {
|
|||
u.unitToTasks[unit] = append(u.unitToTasks[unit], &t)
|
||||
}
|
||||
|
||||
return errors
|
||||
return errs
|
||||
}
|
||||
|
||||
// systemdUnitForContainer returns the name of the container's systemd unit.
|
||||
|
|
|
|||
|
|
@ -1581,7 +1581,14 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
|
|||
for _, ctr := range containers {
|
||||
stats, err := ctr.GetContainerStats(containerStats[ctr.ID()])
|
||||
if err != nil {
|
||||
if queryAll && (errors.Is(err, define.ErrCtrRemoved) || errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrStateInvalid)) {
|
||||
if queryAll &&
|
||||
// All these errors might happen while we get stats, when we list all
|
||||
// they must be skipped as they cause podman stats to stop and error otherwise.
|
||||
// ErrCtrStopped can happen when the container process exited before we could
|
||||
// update the container state
|
||||
// https://github.com/containers/podman/issues/23334
|
||||
(errors.Is(err, define.ErrCtrRemoved) || errors.Is(err, define.ErrNoSuchCtr) ||
|
||||
errors.Is(err, define.ErrCtrStateInvalid) || errors.Is(err, define.ErrCtrStopped)) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/containers/common/pkg/cgroups"
|
||||
"github.com/containers/podman/v5/libpod"
|
||||
"github.com/containers/podman/v5/libpod/define"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/containers/podman/v5/pkg/rootless"
|
||||
"github.com/docker/go-units"
|
||||
|
|
@ -37,8 +38,12 @@ func (ic *ContainerEngine) PodStats(ctx context.Context, namesOrIds []string, op
|
|||
func (ic *ContainerEngine) podsToStatsReport(pods []*libpod.Pod) ([]*entities.PodStatsReport, error) {
|
||||
reports := []*entities.PodStatsReport{}
|
||||
for i := range pods { // Access by index to prevent potential loop-variable leaks.
|
||||
podStats, err := pods[i].GetPodStats(nil)
|
||||
podStats, err := pods[i].GetPodStats()
|
||||
if err != nil {
|
||||
// pod was removed, skip it
|
||||
if errors.Is(err, define.ErrNoSuchPod) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
podID := pods[i].ID()[:12]
|
||||
|
|
|
|||
|
|
@ -198,23 +198,24 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
|
|||
iid, _ := c.Image()
|
||||
state, err := c.State()
|
||||
if err != nil {
|
||||
if errors.Is(err, define.ErrNoSuchCtr) {
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get state of container %s: %w", c.ID(), err)
|
||||
}
|
||||
conSize, err := c.RootFsSize()
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrContainerUnknown) {
|
||||
logrus.Error(fmt.Errorf("failed to get root file system size of container %s: %w", c.ID(), err))
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to get root file system size of container %s: %w", c.ID(), err)
|
||||
if errors.Is(err, storage.ErrContainerUnknown) || errors.Is(err, define.ErrNoSuchCtr) {
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get root file system size of container %s: %w", c.ID(), err)
|
||||
}
|
||||
rwsize, err := c.RWSize()
|
||||
if err != nil {
|
||||
if errors.Is(err, storage.ErrContainerUnknown) {
|
||||
logrus.Error(fmt.Errorf("failed to get read/write size of container %s: %w", c.ID(), err))
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to get read/write size of container %s: %w", c.ID(), err)
|
||||
if errors.Is(err, storage.ErrContainerUnknown) || errors.Is(err, define.ErrNoSuchCtr) {
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get read/write size of container %s: %w", c.ID(), err)
|
||||
}
|
||||
report := entities.SystemDfContainerReport{
|
||||
ContainerID: c.ID(),
|
||||
|
|
@ -241,6 +242,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
|
|||
var reclaimableSize int64
|
||||
mountPoint, err := v.MountPoint()
|
||||
if err != nil {
|
||||
if errors.Is(err, define.ErrNoSuchVolume) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if mountPoint == "" {
|
||||
|
|
@ -255,6 +259,9 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
|
|||
}
|
||||
inUse, err := v.VolumeInUse()
|
||||
if err != nil {
|
||||
if errors.Is(err, define.ErrNoSuchVolume) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if len(inUse) == 0 {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,11 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
|
|||
filters := make(map[string][]string, len(opts.Filter))
|
||||
for _, filter := range opts.Filter {
|
||||
f := strings.SplitN(filter, "=", 2)
|
||||
filters[f[0]] = append(filters[f[0]], f[1])
|
||||
if len(f) > 1 {
|
||||
filters[f[0]] = append(filters[f[0]], f[1])
|
||||
} else {
|
||||
filters[f[0]] = append(filters[f[0]], "")
|
||||
}
|
||||
}
|
||||
options := new(images.ListOptions).WithAll(opts.All).WithFilters(filters)
|
||||
psImages, err := images.List(ir.ClientCtx, options)
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ func newFarmWithBuilders(_ context.Context, name string, cons []config.Connectio
|
|||
defer fmt.Printf("Builder %q ready\n", con.Name)
|
||||
builderMutex.Lock()
|
||||
defer builderMutex.Unlock()
|
||||
farm.builders[name] = engine
|
||||
farm.builders[con.Name] = engine
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,18 +66,27 @@ func runDecompression(d decompressor, decompressedFilePath string) (retErr error
|
|||
}
|
||||
defer d.close()
|
||||
|
||||
initMsg := progressBarPrefix + ": " + filepath.Base(decompressedFilePath)
|
||||
finalMsg := initMsg + ": done"
|
||||
filesize := d.compressedFileSize()
|
||||
// bar.ProxyReader() returns nil when the bar is finished.
|
||||
// When the size is set to 0 the bar will finfish immediately, but this happens
|
||||
// in a different goroutine so it is race and only happens sometimes.
|
||||
// In general if the input is an empty file then we do not have to display a
|
||||
// progress bar at all as there is nothing to copy/extract really
|
||||
// https://github.com/containers/podman/issues/23281
|
||||
if filesize > 0 {
|
||||
initMsg := progressBarPrefix + ": " + filepath.Base(decompressedFilePath)
|
||||
finalMsg := initMsg + ": done"
|
||||
|
||||
p, bar := utils.ProgressBar(initMsg, d.compressedFileSize(), finalMsg)
|
||||
// Wait for bars to complete and then shut down the bars container
|
||||
defer p.Wait()
|
||||
p, bar := utils.ProgressBar(initMsg, filesize, finalMsg)
|
||||
// Wait for bars to complete and then shut down the bars container
|
||||
defer p.Wait()
|
||||
|
||||
compressedFileReaderProxy := bar.ProxyReader(compressedFileReader)
|
||||
// Interrupts the bar goroutine. It's important that
|
||||
// bar.Abort(false) is called before p.Wait(), otherwise
|
||||
// can hang.
|
||||
defer bar.Abort(false)
|
||||
compressedFileReader = bar.ProxyReader(compressedFileReader)
|
||||
// Interrupts the bar goroutine. It's important that
|
||||
// bar.Abort(false) is called before p.Wait(), otherwise
|
||||
// can hang.
|
||||
defer bar.Abort(false)
|
||||
}
|
||||
|
||||
var decompressedFileWriter *os.File
|
||||
|
||||
|
|
@ -94,7 +103,7 @@ func runDecompression(d decompressor, decompressedFilePath string) (retErr error
|
|||
}
|
||||
}()
|
||||
|
||||
if err = d.decompress(decompressedFileWriter, compressedFileReaderProxy); err != nil {
|
||||
if err = d.decompress(decompressedFileWriter, compressedFileReader); err != nil {
|
||||
logrus.Errorf("Error extracting compressed file: %q", err)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ type InitOptions struct {
|
|||
IgnitionPath string
|
||||
Image string
|
||||
Volumes []string
|
||||
VolumeDriver string
|
||||
IsDefault bool
|
||||
Memory uint64
|
||||
Name string
|
||||
|
|
|
|||
|
|
@ -117,6 +117,33 @@ var _ = Describe("run basic podman commands", func() {
|
|||
Expect(findmnt.outputToString()).To(ContainSubstring("virtiofs"))
|
||||
})
|
||||
|
||||
It("Volume should be disabled by command line", func() {
|
||||
skipIfWSL("Requires standard volume handling")
|
||||
skipIfVmtype(define.AppleHvVirt, "Skipped on Apple platform")
|
||||
skipIfVmtype(define.LibKrun, "Skipped on Apple platform")
|
||||
|
||||
name := randomString()
|
||||
i := new(initMachine).withImage(mb.imagePath).withNow()
|
||||
|
||||
// Empty arg forces no volumes
|
||||
i.withVolume("")
|
||||
session, err := mb.setName(name).setCmd(i).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(session).To(Exit(0))
|
||||
|
||||
ssh9p := new(sshMachine).withSSHCommand([]string{"findmnt", "-no", "FSTYPE", "-t", "9p"})
|
||||
findmnt9p, err := mb.setName(name).setCmd(ssh9p).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(findmnt9p).To(Exit(0))
|
||||
Expect(findmnt9p.outputToString()).To(BeEmpty())
|
||||
|
||||
sshVirtiofs := new(sshMachine).withSSHCommand([]string{"findmnt", "-no", "FSTYPE", "-t", "virtiofs"})
|
||||
findmntVirtiofs, err := mb.setName(name).setCmd(sshVirtiofs).run()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(findmntVirtiofs).To(Exit(0))
|
||||
Expect(findmntVirtiofs.outputToString()).To(BeEmpty())
|
||||
})
|
||||
|
||||
It("Podman ops with port forwarding and gvproxy", func() {
|
||||
name := randomString()
|
||||
i := new(initMachine)
|
||||
|
|
|
|||
|
|
@ -168,9 +168,13 @@ func (q *QEMUStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func()
|
|||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
spawner, err := newVirtiofsdSpawner(runtime)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
var spawner *virtiofsdSpawner
|
||||
if len(mc.Mounts) > 0 {
|
||||
spawner, err = newVirtiofsdSpawner(runtime)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, hostmnt := range mc.Mounts {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import (
|
|||
func CmdLineVolumesToMounts(volumes []string, volumeType vmconfigs.VolumeMountType) []*vmconfigs.Mount {
|
||||
mounts := []*vmconfigs.Mount{}
|
||||
for i, volume := range volumes {
|
||||
if volume == "" {
|
||||
continue
|
||||
}
|
||||
var mount vmconfigs.Mount
|
||||
tag, source, target, readOnly, _ := vmconfigs.SplitVolume(i, volume)
|
||||
switch volumeType {
|
||||
|
|
|
|||
27
pkg/ps/ps.go
27
pkg/ps/ps.go
|
|
@ -76,7 +76,8 @@ func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOp
|
|||
for _, con := range cons {
|
||||
listCon, err := ListContainerBatch(runtime, con, options)
|
||||
switch {
|
||||
case errors.Is(err, define.ErrNoSuchCtr):
|
||||
// ignore both no ctr and no such pod errors as it means the ctr is gone now
|
||||
case errors.Is(err, define.ErrNoSuchCtr), errors.Is(err, define.ErrNoSuchPod):
|
||||
continue
|
||||
case err != nil:
|
||||
return nil, err
|
||||
|
|
@ -148,6 +149,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
|
|||
networks []string
|
||||
healthStatus string
|
||||
restartCount uint
|
||||
podName string
|
||||
)
|
||||
|
||||
batchErr := ctr.Batch(func(c *libpod.Container) error {
|
||||
|
|
@ -201,10 +203,6 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
|
|||
return err
|
||||
}
|
||||
|
||||
if !opts.Size && !opts.Namespace {
|
||||
return nil
|
||||
}
|
||||
|
||||
if opts.Namespace {
|
||||
ctrPID := strconv.Itoa(pid)
|
||||
cgroup, _ = getNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
|
||||
|
|
@ -231,6 +229,14 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
|
|||
size.RootFsSize = rootFsSize
|
||||
size.RwSize = rwSize
|
||||
}
|
||||
|
||||
if opts.Pod && len(conConfig.Pod) > 0 {
|
||||
podName, err = rt.GetPodName(conConfig.Pod)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find container %s pod (id %s) in state: %w", conConfig.ID, conConfig.Pod, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if batchErr != nil {
|
||||
|
|
@ -256,6 +262,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
|
|||
Networks: networks,
|
||||
Pid: pid,
|
||||
Pod: conConfig.Pod,
|
||||
PodName: podName,
|
||||
Ports: portMappings,
|
||||
Restarts: restartCount,
|
||||
Size: size,
|
||||
|
|
@ -263,16 +270,6 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
|
|||
State: conState.String(),
|
||||
Status: healthStatus,
|
||||
}
|
||||
if opts.Pod && len(conConfig.Pod) > 0 {
|
||||
podName, err := rt.GetPodName(conConfig.Pod)
|
||||
if err != nil {
|
||||
if errors.Is(err, define.ErrNoSuchCtr) {
|
||||
return entities.ListContainer{}, fmt.Errorf("could not find container %s pod (id %s) in state: %w", conConfig.ID, conConfig.Pod, define.ErrNoSuchPod)
|
||||
}
|
||||
return entities.ListContainer{}, err
|
||||
}
|
||||
ps.PodName = podName
|
||||
}
|
||||
|
||||
if opts.Namespace {
|
||||
ps.Namespaces = entities.ListContainerNamespaces{
|
||||
|
|
|
|||
|
|
@ -939,14 +939,63 @@ func (f *UnitFile) PrependUnitLine(groupName string, key string, value string) {
|
|||
group.prependLine(newUnitLine(key, value, false))
|
||||
}
|
||||
|
||||
func (f *UnitFile) GetTemplateParts() (string, string) {
|
||||
func (f *UnitFile) GetTemplateParts() (string, string, bool) {
|
||||
ext := filepath.Ext(f.Filename)
|
||||
basename := strings.TrimSuffix(f.Filename, ext)
|
||||
parts := strings.SplitN(basename, "@", 2)
|
||||
if len(parts) < 2 {
|
||||
return "", ""
|
||||
return parts[0], "", false
|
||||
}
|
||||
return parts[0] + "@" + ext, parts[1]
|
||||
return parts[0], parts[1], true
|
||||
}
|
||||
|
||||
func (f *UnitFile) GetUnitDropinPaths() []string {
|
||||
unitName, instanceName, isTemplate := f.GetTemplateParts()
|
||||
|
||||
ext := filepath.Ext(f.Filename)
|
||||
dropinExt := ext + ".d"
|
||||
|
||||
dropinPaths := []string{}
|
||||
|
||||
// Add top-level drop-in location (pod.d, container.d, etc)
|
||||
topLevelDropIn := strings.TrimPrefix(dropinExt, ".")
|
||||
dropinPaths = append(dropinPaths, topLevelDropIn)
|
||||
|
||||
truncatedParts := strings.Split(unitName, "-")
|
||||
// If the unit contains any '-', then there are truncated paths to search.
|
||||
if len(truncatedParts) > 1 {
|
||||
// We don't need the last item because that would be the full path
|
||||
truncatedParts = truncatedParts[:len(truncatedParts)-1]
|
||||
// Truncated instance names are not included in the drop-in search path
|
||||
// i.e. template-unit@base-instance.service does not search template-unit@base-.service
|
||||
// So we only search truncations of the template name, i.e. template-@.service, and unit name, i.e. template-.service
|
||||
// or only the unit name if it is not a template.
|
||||
for i := range truncatedParts {
|
||||
truncatedUnitPath := strings.Join(truncatedParts[:i+1], "-") + "-"
|
||||
dropinPaths = append(dropinPaths, truncatedUnitPath+dropinExt)
|
||||
// If the unit is a template, add the truncated template name as well.
|
||||
if isTemplate {
|
||||
truncatedTemplatePath := truncatedUnitPath + "@"
|
||||
dropinPaths = append(dropinPaths, truncatedTemplatePath+dropinExt)
|
||||
}
|
||||
}
|
||||
}
|
||||
// For instanced templates, add the base template unit search path
|
||||
if instanceName != "" {
|
||||
dropinPaths = append(dropinPaths, unitName+"@"+dropinExt)
|
||||
}
|
||||
// Add the drop-in directory for the full filename
|
||||
dropinPaths = append(dropinPaths, f.Filename+".d")
|
||||
// Finally, reverse the list so that when drop-ins are parsed,
|
||||
// the most specific are applied instead of the most broad.
|
||||
// dropinPaths should be a list where the items are in order of specific -> broad
|
||||
// i.e., the most specific search path is dropinPaths[0], and broadest search path is dropinPaths[len(dropinPaths)-1]
|
||||
// Uses https://go.dev/wiki/SliceTricks#reversing
|
||||
for i := len(dropinPaths)/2 - 1; i >= 0; i-- {
|
||||
opp := len(dropinPaths) - 1 - i
|
||||
dropinPaths[i], dropinPaths[opp] = dropinPaths[opp], dropinPaths[i]
|
||||
}
|
||||
return dropinPaths
|
||||
}
|
||||
|
||||
func PathEscape(path string) string {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -226,6 +227,43 @@ Also=systemd-networkd-wait-online.service
|
|||
|
||||
var samples = []string{memcachedService, systemdloginService, systemdnetworkdService}
|
||||
|
||||
const sampleDropinService string = "sample-unit.service"
|
||||
|
||||
var sampleDropinServicePaths = []string{
|
||||
"sample-unit.service.d",
|
||||
"sample-.service.d",
|
||||
"service.d",
|
||||
}
|
||||
|
||||
const sampleDropinTemplate string = "sample-template-unit@.service"
|
||||
|
||||
var sampleDropinTemplatePaths = []string{
|
||||
"sample-template-unit@.service.d",
|
||||
"sample-template-@.service.d",
|
||||
"sample-template-.service.d",
|
||||
"sample-@.service.d",
|
||||
"sample-.service.d",
|
||||
"service.d",
|
||||
}
|
||||
|
||||
const sampleDropinTemplateInstance string = "sample-template-unit@base-instance.service"
|
||||
|
||||
var sampleDropinTemplateInstancePaths = []string{
|
||||
"sample-template-unit@base-instance.service.d",
|
||||
"sample-template-unit@.service.d",
|
||||
"sample-template-@.service.d",
|
||||
"sample-template-.service.d",
|
||||
"sample-@.service.d",
|
||||
"sample-.service.d",
|
||||
"service.d",
|
||||
}
|
||||
|
||||
var sampleDropinPaths = map[string][]string{
|
||||
sampleDropinService: sampleDropinServicePaths,
|
||||
sampleDropinTemplate: sampleDropinTemplatePaths,
|
||||
sampleDropinTemplateInstance: sampleDropinTemplateInstancePaths,
|
||||
}
|
||||
|
||||
func TestRanges_Roundtrip(t *testing.T) {
|
||||
for i := range samples {
|
||||
sample := samples[i]
|
||||
|
|
@ -243,3 +281,14 @@ func TestRanges_Roundtrip(t *testing.T) {
|
|||
assert.Equal(t, sample, asStr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnitDropinPaths_Search(t *testing.T) {
|
||||
for filename, expectedPaths := range sampleDropinPaths {
|
||||
f := UnitFile{
|
||||
Filename: filename,
|
||||
}
|
||||
generatedPaths := f.GetUnitDropinPaths()
|
||||
|
||||
assert.True(t, reflect.DeepEqual(expectedPaths, generatedPaths))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ const (
|
|||
KeySecurityLabelType = "SecurityLabelType"
|
||||
KeySetWorkingDirectory = "SetWorkingDirectory"
|
||||
KeyShmSize = "ShmSize"
|
||||
KeyStopSignal = "StopSignal"
|
||||
KeyStopTimeout = "StopTimeout"
|
||||
KeySubGIDMap = "SubGIDMap"
|
||||
KeySubnet = "Subnet"
|
||||
|
|
@ -242,6 +243,7 @@ var (
|
|||
KeySecurityLabelNested: true,
|
||||
KeySecurityLabelType: true,
|
||||
KeyShmSize: true,
|
||||
KeyStopSignal: true,
|
||||
KeyStopTimeout: true,
|
||||
KeySubGIDMap: true,
|
||||
KeySubUIDMap: true,
|
||||
|
|
@ -843,6 +845,10 @@ func ConvertContainer(container *parser.UnitFile, names map[string]string, isUse
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if stopSignal, ok := container.Lookup(ContainerGroup, KeyStopSignal); ok && len(stopSignal) > 0 {
|
||||
podman.add("--stop-signal", stopSignal)
|
||||
}
|
||||
|
||||
if stopTimeout, ok := container.Lookup(ContainerGroup, KeyStopTimeout); ok && len(stopTimeout) > 0 {
|
||||
podman.add("--stop-timeout", stopTimeout)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
requests-mock~=1.12.1
|
||||
requests~=2.32.3
|
||||
setuptools~=70.3.0
|
||||
setuptools~=71.0.0
|
||||
python-dateutil~=2.9.0
|
||||
PyYAML~=6.0.0
|
||||
openapi-schema-validator~=0.6.2
|
||||
|
|
|
|||
|
|
@ -41,25 +41,22 @@ var _ = Describe("Podman healthcheck run", func() {
|
|||
})
|
||||
|
||||
It("podman run healthcheck and logs should contain healthcheck output", func() {
|
||||
session := podmanTest.Podman([]string{"run", "--name", "test-logs", "-dt", "--health-interval", "1s", "--health-cmd", "echo working", "busybox", "sleep", "3600"})
|
||||
session := podmanTest.Podman([]string{"run", "--name", "test-logs", "-dt", "--health-interval", "1s",
|
||||
// echo -n is important for https://github.com/containers/podman/issues/23332
|
||||
"--health-cmd", "echo -n working", ALPINE, "sleep", "3600"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
|
||||
// Buy a little time to get container running
|
||||
for i := 0; i < 5; i++ {
|
||||
hc := podmanTest.Podman([]string{"healthcheck", "run", "test-logs"})
|
||||
hc.WaitWithDefaultTimeout()
|
||||
exitCode := hc.ExitCode()
|
||||
if exitCode == 0 || i == 4 {
|
||||
break
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Healthcheck.Log}}", "test-logs"})
|
||||
hc := podmanTest.Podman([]string{"healthcheck", "run", "test-logs"})
|
||||
hc.WaitWithDefaultTimeout()
|
||||
Expect(hc).Should(ExitCleanly())
|
||||
Expect(hc.OutputToString()).To(ContainSubstring("working"))
|
||||
|
||||
// using json formatter here to make sure the newline is not part of the output string an just added by podman inspect
|
||||
hc = podmanTest.Podman([]string{"container", "inspect", "--format", "{{json (index .State.Healthcheck.Log 0).Output}}", "test-logs"})
|
||||
hc.WaitWithDefaultTimeout()
|
||||
Expect(hc).Should(ExitCleanly())
|
||||
// exact output match for https://github.com/containers/podman/issues/23332
|
||||
Expect(string(hc.Out.Contents())).To(Equal("\"working\"\n"))
|
||||
})
|
||||
|
||||
It("podman healthcheck from image's config (not container config)", func() {
|
||||
|
|
|
|||
5
test/e2e/quadlet/stopsignal.container
Normal file
5
test/e2e/quadlet/stopsignal.container
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
## assert-podman-args "--stop-signal" "SIGKILL"
|
||||
|
||||
[Container]
|
||||
Image=localhost/imagename
|
||||
StopSignal=SIGKILL
|
||||
|
|
@ -854,6 +854,7 @@ BOGUS=foo
|
|||
Entry("selinux.container", "selinux.container", 0, ""),
|
||||
Entry("shmsize.container", "shmsize.container", 0, ""),
|
||||
Entry("shortname.container", "shortname.container", 0, "Warning: shortname.container specifies the image \"shortname\" which not a fully qualified image name. This is not ideal for performance and security reasons. See the podman-pull manpage discussion of short-name-aliases.conf for details."),
|
||||
Entry("stopsigal.container", "stopsignal.container", 0, ""),
|
||||
Entry("stoptimeout.container", "stoptimeout.container", 0, ""),
|
||||
Entry("subidmapping.container", "subidmapping.container", 0, ""),
|
||||
Entry("subidmapping-with-remap.container", "subidmapping-with-remap.container", 1, "converting \"subidmapping-with-remap.container\": deprecated Remap keys are set along with explicit mapping keys"),
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ package integration
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
|
|
@ -543,56 +545,58 @@ EXPOSE 2004-2005/tcp`, ALPINE)
|
|||
}
|
||||
})
|
||||
|
||||
It("podman run network bind to 127.0.0.1", func() {
|
||||
slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
|
||||
Expect(slirp4netnsHelp).Should(ExitCleanly())
|
||||
networkConfiguration := "slirp4netns:outbound_addr=127.0.0.1,allow_host_loopback=true"
|
||||
port := strconv.Itoa(GetPort())
|
||||
|
||||
if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
|
||||
ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", port})
|
||||
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", port})
|
||||
session.WaitWithDefaultTimeout()
|
||||
ncListener.WaitWithDefaultTimeout()
|
||||
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(ncListener).Should(Exit(0))
|
||||
Expect(ncListener.ErrorToString()).To(ContainSubstring("Connection from 127.0.0.1"))
|
||||
} else {
|
||||
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", port})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).To(ExitWithError(125, "outbound_addr not supported"))
|
||||
for _, local := range []bool{true, false} {
|
||||
local := local
|
||||
testName := "HostIP"
|
||||
if local {
|
||||
testName = "127.0.0.1"
|
||||
}
|
||||
})
|
||||
It(fmt.Sprintf("podman run network slirp4netns bind to %s", testName), func() {
|
||||
ip := "127.0.0.1"
|
||||
if !local {
|
||||
// Determine our likeliest outgoing IP address
|
||||
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
It("podman run network bind to HostIP", func() {
|
||||
// Determine our likeliest outgoing IP address
|
||||
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer conn.Close()
|
||||
ip = conn.LocalAddr().(*net.UDPAddr).IP.String()
|
||||
}
|
||||
port := strconv.Itoa(GetPort())
|
||||
|
||||
defer conn.Close()
|
||||
ip := conn.LocalAddr().(*net.UDPAddr).IP
|
||||
port := strconv.Itoa(GetPort())
|
||||
networkConfiguration := fmt.Sprintf("slirp4netns:outbound_addr=%s,allow_host_loopback=true", ip)
|
||||
|
||||
slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
|
||||
Expect(slirp4netnsHelp).Should(ExitCleanly())
|
||||
networkConfiguration := fmt.Sprintf("slirp4netns:outbound_addr=%s,allow_host_loopback=true", ip.String())
|
||||
listener, err := net.Listen("tcp", ":"+port)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer listener.Close()
|
||||
|
||||
if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
|
||||
ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", port})
|
||||
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, ALPINE, "nc", "-w", "2", "10.0.2.2", port})
|
||||
session.Wait(30)
|
||||
ncListener.Wait(30)
|
||||
msg := RandomString(10)
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
// now use a new goroutine to start accepting connection in the background and make the checks there
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
defer wg.Done()
|
||||
conn, err := listener.Accept()
|
||||
Expect(err).ToNot(HaveOccurred(), "accept new connection")
|
||||
defer conn.Close()
|
||||
addr := conn.RemoteAddr()
|
||||
// addr will be in the form ip:port, we don't care about the port as it is random
|
||||
Expect(addr.String()).To(HavePrefix(ip+":"), "remote address")
|
||||
gotBytes, err := io.ReadAll(conn)
|
||||
Expect(err).ToNot(HaveOccurred(), "read from connection")
|
||||
Expect(string(gotBytes)).To(Equal(msg), "received correct message from container")
|
||||
}()
|
||||
|
||||
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, ALPINE, "sh", "-c", "echo -n " + msg + " | nc -w 30 10.0.2.2 " + port})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(ncListener).Should(Exit(0))
|
||||
Expect(ncListener.ErrorToString()).To(ContainSubstring("Connection from " + ip.String()))
|
||||
} else {
|
||||
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, ALPINE, "nc", "-w", "2", "10.0.2.2", port})
|
||||
session.Wait(30)
|
||||
Expect(session).To(ExitWithError(125, "outbound_addr not supported"))
|
||||
}
|
||||
})
|
||||
|
||||
// explicitly close the socket here before we wait to unlock Accept() calls in case of hangs
|
||||
listener.Close()
|
||||
// wait for the checks in the goroutine to be done
|
||||
wg.Wait()
|
||||
})
|
||||
}
|
||||
|
||||
It("podman run network expose ports in image metadata", func() {
|
||||
session := podmanTest.Podman([]string{"create", "--name", "test", "-t", "-P", NGINX_IMAGE})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
docker~=6.1.0
|
||||
requests-mock~=1.12.1
|
||||
requests~=2.32.3
|
||||
setuptools~=70.3.0
|
||||
setuptools~=71.0.0
|
||||
python-dateutil~=2.9.0
|
||||
PyYAML~=6.0.0
|
||||
openapi-schema-validator~=0.6.2
|
||||
|
|
|
|||
|
|
@ -62,31 +62,33 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
|
|||
# podman history is persistent: it permanently alters our base image.
|
||||
# Create a dummy image here so we leave our setup as we found it.
|
||||
# Multiple --name options confirm command-line override (last one wins)
|
||||
run_podman run --name ignore-me --name my-container $IMAGE true
|
||||
run_podman commit my-container my-test-image
|
||||
cname=c_$(safename)
|
||||
iname=i_$(safename)
|
||||
run_podman run --name ignore-me --name $cname $IMAGE true
|
||||
run_podman commit $cname $iname
|
||||
|
||||
run_podman images my-test-image --format '{{ .History }}'
|
||||
is "$output" "localhost/my-test-image:latest" "image history with initial name"
|
||||
run_podman images $iname --format '{{ .History }}'
|
||||
is "$output" "localhost/$iname:latest" "image history with initial name"
|
||||
|
||||
# Generate two randomish tags; 'tr' because they must be all lower-case
|
||||
rand_name1="test-image-history-$(random_string 10 | tr A-Z a-z)"
|
||||
rand_name2="test-image-history-$(random_string 10 | tr A-Z a-z)"
|
||||
# Generate two randomish tags
|
||||
rand_name1="test-image-history-1-$(safename)"
|
||||
rand_name2="test-image-history-2-$(safename)"
|
||||
|
||||
# Tag once, rmi, and make sure the tag name appears in history
|
||||
run_podman tag my-test-image $rand_name1
|
||||
run_podman tag $iname $rand_name1
|
||||
run_podman rmi $rand_name1
|
||||
run_podman images my-test-image --format '{{ .History }}'
|
||||
is "$output" "localhost/my-test-image:latest, localhost/${rand_name1}:latest" "image history after one tag"
|
||||
run_podman images $iname --format '{{ .History }}'
|
||||
is "$output" "localhost/$iname:latest, localhost/${rand_name1}:latest" "image history after one tag"
|
||||
|
||||
# Repeat with second tag. Now both tags should be in history
|
||||
run_podman tag my-test-image $rand_name2
|
||||
run_podman tag $iname $rand_name2
|
||||
run_podman rmi $rand_name2
|
||||
run_podman images my-test-image --format '{{ .History }}'
|
||||
is "$output" "localhost/my-test-image:latest, localhost/${rand_name2}:latest, localhost/${rand_name1}:latest" \
|
||||
run_podman images $iname --format '{{ .History }}'
|
||||
is "$output" "localhost/$iname:latest, localhost/${rand_name2}:latest, localhost/${rand_name1}:latest" \
|
||||
"image history after two tags"
|
||||
|
||||
run_podman rmi my-test-image
|
||||
run_podman rm my-container
|
||||
run_podman rmi $iname
|
||||
run_podman rm $cname
|
||||
}
|
||||
|
||||
@test "podman images - filter" {
|
||||
|
|
@ -102,26 +104,31 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
|
|||
|
||||
# Create a dummy container, then commit that as an image. We will
|
||||
# now be able to use before/after/since queries
|
||||
run_podman run --name mytinycontainer $IMAGE true
|
||||
run_podman commit -q mytinycontainer mynewimage
|
||||
cname=c_$(safename)
|
||||
iname=i_$(safename)
|
||||
run_podman run --name $cname $IMAGE true
|
||||
run_podman commit -q $cname $iname
|
||||
new_iid=$output
|
||||
|
||||
# (refactor common options for legibility)
|
||||
opts='--noheading --no-trunc --format={{.ID}}--{{.Repository}}:{{.Tag}}'
|
||||
|
||||
run_podman images ${opts} --filter=after=$iid
|
||||
is "$output" "sha256:$new_iid--localhost/mynewimage:latest" "filter: after"
|
||||
is "$output" "sha256:$new_iid--localhost/$iname:latest" "filter: after"
|
||||
|
||||
# Same thing, with 'since' instead of 'after'
|
||||
run_podman images ${opts} --filter=since=$iid
|
||||
is "$output" "sha256:$new_iid--localhost/mynewimage:latest" "filter: since"
|
||||
is "$output" "sha256:$new_iid--localhost/$iname:latest" "filter: since"
|
||||
|
||||
run_podman images ${opts} --filter=before=mynewimage
|
||||
run_podman images ${opts} --filter=before=$iname
|
||||
is "$output" "sha256:$iid--$IMAGE" "filter: before"
|
||||
|
||||
run_podman 125 image list -f json
|
||||
is "$output" 'Error: invalid image filter "json": must be in the format "filter=value or filter!=value"' "Invalid filter"
|
||||
|
||||
# Clean up
|
||||
run_podman rmi mynewimage
|
||||
run_podman rm mytinycontainer
|
||||
run_podman rmi $iname
|
||||
run_podman rm $cname
|
||||
}
|
||||
|
||||
# Regression test for https://github.com/containers/podman/issues/7651
|
||||
|
|
@ -238,7 +245,7 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
|
|||
}
|
||||
|
||||
@test "podman images - rmi -af removes all containers and pods" {
|
||||
pname=$(random_string)
|
||||
pname=p_$(safename)
|
||||
run_podman create --pod new:$pname $IMAGE
|
||||
|
||||
run_podman inspect --format '{{.ID}}' $IMAGE
|
||||
|
|
@ -274,7 +281,7 @@ Deleted: $pauseID" "infra images gets removed as well"
|
|||
}
|
||||
|
||||
@test "podman images - rmi -f can remove infra images" {
|
||||
pname=$(random_string)
|
||||
pname=p_$(safename)
|
||||
run_podman create --pod new:$pname $IMAGE
|
||||
|
||||
pauseImage=$(pause_image)
|
||||
|
|
@ -299,8 +306,7 @@ Deleted: $pauseID"
|
|||
}
|
||||
|
||||
@test "podman rmi --ignore" {
|
||||
random_image_name=$(random_string)
|
||||
random_image_name=${random_image_name,,} # name must be lowercase
|
||||
random_image_name=i_$(safename)
|
||||
run_podman 1 rmi $random_image_name
|
||||
is "$output" "Error: $random_image_name: image not known.*"
|
||||
run_podman rmi --ignore $random_image_name
|
||||
|
|
@ -313,8 +319,7 @@ Deleted: $pauseID"
|
|||
run_podman image rm --force bogus
|
||||
is "$output" "" "Should print no output"
|
||||
|
||||
random_image_name=$(random_string)
|
||||
random_image_name=${random_image_name,,} # name must be lowercase
|
||||
random_image_name=i_$(safename)
|
||||
run_podman image tag $IMAGE $random_image_name
|
||||
run_podman image rm --force bogus $random_image_name
|
||||
assert "$output" = "Untagged: localhost/$random_image_name:latest" "removed image"
|
||||
|
|
@ -324,24 +329,26 @@ Deleted: $pauseID"
|
|||
}
|
||||
|
||||
@test "podman images - commit docker with comment" {
|
||||
run_podman run --name my-container -d $IMAGE top
|
||||
run_podman 125 commit -m comment my-container my-test-image
|
||||
cname=c_$(safename)
|
||||
iname=i_$(safename)
|
||||
run_podman run --name $cname -d $IMAGE top
|
||||
run_podman 125 commit -m comment $cname $iname
|
||||
assert "$output" == "Error: messages are only compatible with the docker image format (-f docker)" "podman should fail unless docker format"
|
||||
|
||||
# Without -q: verbose output, but only on podman-local, not remote
|
||||
run_podman commit my-container --format docker -m comment my-test-image1
|
||||
run_podman commit $cname --format docker -m comment ${iname}_2
|
||||
if ! is_remote; then
|
||||
assert "$output" =~ "Getting image.*Writing manif" \
|
||||
"Without -q, verbose output"
|
||||
fi
|
||||
|
||||
# With -q, both local and remote: only an image ID
|
||||
run_podman commit -q my-container --format docker -m comment my-test-image2
|
||||
run_podman commit -q $cname --format docker -m comment ${iname}_3
|
||||
assert "$output" =~ "^[0-9a-f]{64}\$" \
|
||||
"With -q, output is a commit ID, no warnings or other output"
|
||||
|
||||
run_podman rmi my-test-image1 my-test-image2
|
||||
run_podman rm my-container --force -t 0
|
||||
run_podman rmi ${iname}_2 ${iname}_3
|
||||
run_podman rm $cname --force -t 0
|
||||
}
|
||||
|
||||
@test "podman pull image with additional store" {
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ echo $rand | 0 | $rand
|
|||
}
|
||||
|
||||
@test "podman run --name" {
|
||||
randomname=$(random_string 30)
|
||||
randomname=c_$(safename)
|
||||
|
||||
run_podman run -d --name $randomname $IMAGE sleep inf
|
||||
cid=$output
|
||||
|
|
@ -192,7 +192,8 @@ echo $rand | 0 | $rand
|
|||
run_podman 1 image exists $NONLOCAL_IMAGE
|
||||
|
||||
# Run a container, without --rm; this should block subsequent --rmi
|
||||
run_podman run --name /keepme $NONLOCAL_IMAGE /bin/true
|
||||
cname=c_$(safename)
|
||||
run_podman run --name /$cname $NONLOCAL_IMAGE /bin/true
|
||||
run_podman image exists $NONLOCAL_IMAGE
|
||||
|
||||
# Now try running with --rmi : it should succeed, but not remove the image
|
||||
|
|
@ -202,7 +203,7 @@ echo $rand | 0 | $rand
|
|||
run_podman image exists $NONLOCAL_IMAGE
|
||||
|
||||
# Remove the stray container, and run one more time with --rmi.
|
||||
run_podman rm /keepme
|
||||
run_podman rm /$cname
|
||||
run_podman run --rmi $NONLOCAL_IMAGE /bin/true
|
||||
run_podman 1 image exists $NONLOCAL_IMAGE
|
||||
|
||||
|
|
@ -220,7 +221,7 @@ echo $rand | 0 | $rand
|
|||
# on write.
|
||||
echo "$(random_string 120)" > $cidfile
|
||||
|
||||
cname=$(random_string)
|
||||
cname=c_$(safename)
|
||||
run_podman run --name $cname \
|
||||
--conmon-pidfile=$pidfile \
|
||||
--cidfile=$cidfile \
|
||||
|
|
@ -255,23 +256,25 @@ echo $rand | 0 | $rand
|
|||
skip_if_remote "podman-remote does not support docker-archive"
|
||||
|
||||
# Create an image that, when run, outputs a random magic string
|
||||
cname=c_$(safename)
|
||||
expect=$(random_string 20)
|
||||
run_podman run --name myc --entrypoint="[\"/bin/echo\",\"$expect\"]" $IMAGE
|
||||
run_podman run --name $cname --entrypoint="[\"/bin/echo\",\"$expect\"]" $IMAGE
|
||||
is "$output" "$expect" "podman run --entrypoint echo-randomstring"
|
||||
|
||||
# Save it as a tar archive
|
||||
run_podman commit myc myi
|
||||
iname=i_$(safename)
|
||||
run_podman commit $cname $iname
|
||||
archive=$PODMAN_TMPDIR/archive.tar
|
||||
run_podman save --quiet myi -o $archive
|
||||
run_podman save --quiet $iname -o $archive
|
||||
is "$output" "" "podman save"
|
||||
|
||||
# Clean up image and container from container storage...
|
||||
run_podman rmi myi
|
||||
run_podman rm myc
|
||||
run_podman rmi $iname
|
||||
run_podman rm $cname
|
||||
|
||||
# ... then confirm we can run from archive. This re-imports the image
|
||||
# and runs it, producing our random string as the last line.
|
||||
run_podman run docker-archive:$archive
|
||||
run_podman run --name ${cname}_2 docker-archive:$archive
|
||||
is "${lines[0]}" "Getting image source signatures" "podman run docker-archive, first line of output"
|
||||
is "$output" ".*Copying blob" "podman run docker-archive"
|
||||
is "$output" ".*Copying config" "podman run docker-archive"
|
||||
|
|
@ -279,8 +282,8 @@ echo $rand | 0 | $rand
|
|||
is "${lines[-1]}" "$expect" "podman run docker-archive: expected random string output"
|
||||
|
||||
# Clean up container as well as re-imported image
|
||||
run_podman rm -a
|
||||
run_podman rmi myi
|
||||
run_podman rm ${cname}_2
|
||||
run_podman rmi $iname
|
||||
|
||||
# Repeat the above, with podman-create and podman-start.
|
||||
run_podman create docker-archive:$archive
|
||||
|
|
@ -291,7 +294,7 @@ echo $rand | 0 | $rand
|
|||
|
||||
# Clean up.
|
||||
run_podman rm $cid
|
||||
run_podman rmi myi
|
||||
run_podman rmi $iname
|
||||
}
|
||||
|
||||
# #6735 : complex interactions with multiple user namespaces
|
||||
|
|
@ -407,15 +410,16 @@ json-file | f
|
|||
|
||||
while read driver do_check; do
|
||||
msg=$(random_string 15)
|
||||
run_podman run --name myctr --log-driver $driver $IMAGE echo $msg
|
||||
cname=c_$(safename)
|
||||
run_podman run --name $cname --log-driver $driver $IMAGE echo $msg
|
||||
is "$output" "$msg" "basic output sanity check (driver=$driver)"
|
||||
|
||||
# Simply confirm that podman preserved our argument as-is
|
||||
run_podman inspect --format '{{.HostConfig.LogConfig.Type}}' myctr
|
||||
run_podman inspect --format '{{.HostConfig.LogConfig.Type}}' $cname
|
||||
is "$output" "$driver" "podman inspect: driver"
|
||||
|
||||
# If LogPath is non-null, check that it exists and has a valid log
|
||||
run_podman inspect --format '{{.HostConfig.LogConfig.Path}}' myctr
|
||||
run_podman inspect --format '{{.HostConfig.LogConfig.Path}}' $cname
|
||||
if [[ $do_check != '-' ]]; then
|
||||
is "$output" "/.*" "LogPath (driver=$driver)"
|
||||
if ! test -e "$output"; then
|
||||
|
|
@ -433,17 +437,17 @@ json-file | f
|
|||
# Cannot perform check
|
||||
:
|
||||
else
|
||||
run_podman logs myctr
|
||||
run_podman logs $cname
|
||||
is "$output" "$msg" "podman logs, with driver '$driver'"
|
||||
fi
|
||||
else
|
||||
run_podman 125 logs myctr
|
||||
run_podman 125 logs $cname
|
||||
if ! is_remote; then
|
||||
is "$output" ".*this container is using the 'none' log driver, cannot read logs.*" \
|
||||
"podman logs, with driver 'none', should fail with error"
|
||||
fi
|
||||
fi
|
||||
run_podman rm myctr
|
||||
run_podman rm $cname
|
||||
done < <(parse_table "$tests")
|
||||
|
||||
# Invalid log-driver argument
|
||||
|
|
@ -462,13 +466,14 @@ json-file | f
|
|||
pidfile="${PODMAN_TMPDIR}/$(random_string 20)"
|
||||
|
||||
# Multiple --log-driver options to confirm that last one wins
|
||||
run_podman run --name myctr --log-driver=none --log-driver journald \
|
||||
cname=c_$(safename)
|
||||
run_podman run --name $cname --log-driver=none --log-driver journald \
|
||||
--conmon-pidfile $pidfile $IMAGE echo $msg
|
||||
|
||||
journalctl --output cat _PID=$(cat $pidfile)
|
||||
is "$output" "$msg" "check that journalctl output equals the container output"
|
||||
|
||||
run_podman rm myctr
|
||||
run_podman rm $cname
|
||||
}
|
||||
|
||||
@test "podman run --tz" {
|
||||
|
|
@ -530,18 +535,20 @@ json-file | f
|
|||
rm -f $new_runtime
|
||||
}
|
||||
|
||||
@test "podman --noout run should print output" {
|
||||
run_podman --noout run -d --name test $IMAGE echo hi
|
||||
@test "podman --noout run should not print output" {
|
||||
cname=c_$(safename)
|
||||
run_podman --noout run -d --name $cname $IMAGE echo hi
|
||||
is "$output" "" "output should be empty"
|
||||
run_podman wait test
|
||||
run_podman --noout rm test
|
||||
run_podman wait $cname
|
||||
run_podman --noout rm $cname
|
||||
is "$output" "" "output should be empty"
|
||||
}
|
||||
|
||||
@test "podman --noout create should print output" {
|
||||
run_podman --noout create --name test $IMAGE echo hi
|
||||
@test "podman --noout create should not print output" {
|
||||
cname=c_$(safename)
|
||||
run_podman --noout create --name $cname $IMAGE echo hi
|
||||
is "$output" "" "output should be empty"
|
||||
run_podman --noout rm test
|
||||
run_podman --noout rm $cname
|
||||
is "$output" "" "output should be empty"
|
||||
}
|
||||
|
||||
|
|
@ -549,15 +556,16 @@ json-file | f
|
|||
outfile=${PODMAN_TMPDIR}/out-results
|
||||
|
||||
# first we'll need to run something, write its output to a file, and then read its contents.
|
||||
run_podman --out $outfile run -d --name test $IMAGE echo hola
|
||||
cname=c_$(safename)
|
||||
run_podman --out $outfile run -d --name $cname $IMAGE echo hola
|
||||
is "$output" "" "output should be redirected"
|
||||
run_podman wait test
|
||||
run_podman wait $cname
|
||||
|
||||
# compare the container id against the one in the file
|
||||
run_podman container inspect --format '{{.Id}}' test
|
||||
run_podman container inspect --format '{{.Id}}' $cname
|
||||
is "$output" "$(<$outfile)" "container id should match"
|
||||
|
||||
run_podman --out /dev/null rm test
|
||||
run_podman --out /dev/null rm $cname
|
||||
is "$output" "" "output should be empty"
|
||||
}
|
||||
|
||||
|
|
@ -565,22 +573,22 @@ json-file | f
|
|||
outfile=${PODMAN_TMPDIR}/out-results
|
||||
|
||||
# first we'll need to run something, write its output to a file, and then read its contents.
|
||||
run_podman --out $outfile create --name test $IMAGE echo hola
|
||||
cname=c_$(safename)
|
||||
run_podman --out $outfile create --name $cname $IMAGE echo hola
|
||||
is "$output" "" "output should be redirected"
|
||||
|
||||
# compare the container id against the one in the file
|
||||
run_podman container inspect --format '{{.Id}}' test
|
||||
run_podman container inspect --format '{{.Id}}' $cname
|
||||
is "$output" "$(<$outfile)" "container id should match"
|
||||
|
||||
run_podman --out /dev/null rm test
|
||||
run_podman --out /dev/null rm $cname
|
||||
is "$output" "" "output should be empty"
|
||||
}
|
||||
|
||||
# Regression test for issue #8082
|
||||
@test "podman run : look up correct image name" {
|
||||
# Create a 2nd tag for the local image. Force to lower case, and apply it.
|
||||
local newtag="localhost/$(random_string 10)/$(random_string 8)"
|
||||
newtag=${newtag,,}
|
||||
# Create a 2nd tag for the local image.
|
||||
local newtag="localhost/r_$(safename)/i_$(safename)"
|
||||
run_podman tag $IMAGE $newtag
|
||||
|
||||
# Create a container with the 2nd tag and make sure that it's being
|
||||
|
|
@ -596,7 +604,7 @@ json-file | f
|
|||
newtag2="${newtag}:$(random_string 6|tr A-Z a-z)"
|
||||
run_podman tag $IMAGE $newtag2
|
||||
|
||||
cname="$(random_string 14|tr A-Z a-z)"
|
||||
cname="c_$(safename)"
|
||||
run_podman create --name $cname $newtag2
|
||||
run_podman inspect --format "{{.ImageName}}" $cname
|
||||
is "$output" "$newtag2" \
|
||||
|
|
@ -621,7 +629,7 @@ json-file | f
|
|||
}
|
||||
|
||||
@test "podman inspect includes image data" {
|
||||
randomname=$(random_string 30)
|
||||
randomname=c_$(safename)
|
||||
|
||||
run_podman inspect $IMAGE --format "{{.ID}}"
|
||||
expected="$IMAGE $output"
|
||||
|
|
@ -650,7 +658,7 @@ json-file | f
|
|||
run_podman inspect --format '{{.ID}}' $IMAGE
|
||||
local iid="$output"
|
||||
|
||||
random_cname=c$(random_string 15 | tr A-Z a-z)
|
||||
random_cname=c_$(safename)
|
||||
local rootless=0
|
||||
if is_rootless; then
|
||||
rootless=1
|
||||
|
|
@ -708,8 +716,8 @@ json-file | f
|
|||
run_podman image mount $IMAGE
|
||||
romount="$output"
|
||||
|
||||
randomname=$(random_string 30)
|
||||
# FIXME FIXME FIXME: Remove :O once (if) #14504 is fixed!
|
||||
randomname=c_$(safename)
|
||||
# :O (overlay) required with rootfs; see #14504
|
||||
run_podman run --name=$randomname --rootfs $romount:O echo "Hello world"
|
||||
is "$output" "Hello world"
|
||||
|
||||
|
|
@ -730,7 +738,7 @@ json-file | f
|
|||
char_count=700000
|
||||
|
||||
# Container name; primarily needed when running podman-remote
|
||||
cname=mybigdatacontainer
|
||||
cname=c_$(safename)
|
||||
|
||||
# This is one of those cases where BATS is not the best test framework.
|
||||
# We can't do any output redirection, because 'run' overrides it so
|
||||
|
|
@ -744,14 +752,15 @@ json-file | f
|
|||
is "${lines[1]}" "$char_count+0 records out" "dd: number of records out"
|
||||
|
||||
# We don't have many tests for '-l'. This is as good a place as any
|
||||
if ! is_remote; then
|
||||
cname=-l
|
||||
local dash_l=-l
|
||||
if is_remote; then
|
||||
dash_l=$cname
|
||||
fi
|
||||
|
||||
# Now find that log file, and count the NULs in it.
|
||||
# The log file is of the form '<timestamp> <P|F> <data>', where P|F
|
||||
# is Partial/Full; I think that's called "kubernetes log format"?
|
||||
run_podman inspect $cname --format '{{.HostConfig.LogConfig.Path}}'
|
||||
run_podman inspect $dash_l --format '{{.HostConfig.LogConfig.Path}}'
|
||||
logfile="$output"
|
||||
|
||||
count_zero=$(tr -cd '\0' <$logfile | wc -c)
|
||||
|
|
@ -768,14 +777,14 @@ json-file | f
|
|||
}
|
||||
|
||||
@test "podman run --timeout - basic test" {
|
||||
cid=timeouttest
|
||||
cname=c_$(safename)
|
||||
t0=$SECONDS
|
||||
run_podman 255 run --name $cid --timeout 2 $IMAGE sleep 60
|
||||
run_podman 255 run --name $cname --timeout 2 $IMAGE sleep 60
|
||||
t1=$SECONDS
|
||||
# Confirm that container is stopped. Podman-remote unfortunately
|
||||
# cannot tell the difference between "stopped" and "exited", and
|
||||
# spits them out interchangeably, so we need to recognize either.
|
||||
run_podman inspect --format '{{.State.Status}} {{.State.ExitCode}}' $cid
|
||||
run_podman inspect --format '{{.State.Status}} {{.State.ExitCode}}' $cname
|
||||
is "$output" "\\(stopped\|exited\\) \-1" \
|
||||
"Status and exit code of stopped container"
|
||||
|
||||
|
|
@ -785,7 +794,7 @@ json-file | f
|
|||
assert "$delta_t" -gt 1 "podman stop: ran too quickly!"
|
||||
assert "$delta_t" -le 6 "podman stop: took too long"
|
||||
|
||||
run_podman rm $cid
|
||||
run_podman rm $cname
|
||||
}
|
||||
|
||||
@test "podman run no /etc/mtab " {
|
||||
|
|
@ -1029,21 +1038,26 @@ EOF
|
|||
@test "podman run failed --rm " {
|
||||
port=$(random_free_port)
|
||||
|
||||
# Container names must sort alphanumerically
|
||||
c_ok=c1_$(safename)
|
||||
c_fail_no_rm=c2_$(safename)
|
||||
c_fail_with_rm=c3_$(safename)
|
||||
|
||||
# Run two containers with the same port bindings. The second must fail
|
||||
run_podman run -p $port:80 --rm -d --name c_ok $IMAGE top
|
||||
run_podman 126 run -p $port:80 -d --name c_fail_no_rm $IMAGE top
|
||||
run_podman 126 run -p $port:80 --rm -d --name c_fail_with_rm $IMAGE top
|
||||
run_podman run -p $port:80 --rm -d --name $c_ok $IMAGE top
|
||||
run_podman 126 run -p $port:80 -d --name $c_fail_no_rm $IMAGE top
|
||||
run_podman 126 run -p $port:80 --rm -d --name $c_fail_with_rm $IMAGE top
|
||||
# Prior to #15060, the third container would still show up in ps -a
|
||||
run_podman ps -a --sort names --format '{{.Image}}--{{.Names}}'
|
||||
is "$output" "$IMAGE--c_fail_no_rm
|
||||
$IMAGE--c_ok" \
|
||||
is "$output" "$IMAGE--${c_ok}
|
||||
$IMAGE--${c_fail_no_rm}" \
|
||||
"podman ps -a shows running & failed containers, but not failed-with-rm"
|
||||
|
||||
run_podman container rm -f -t 0 c_ok c_fail_no_rm
|
||||
run_podman container rm -f -t 0 $c_ok $c_fail_no_rm
|
||||
}
|
||||
|
||||
@test "podman run --attach stdin prints container ID" {
|
||||
ctr_name="container-$(random_string 5)"
|
||||
ctr_name="container-$(safename)"
|
||||
run_podman run --name $ctr_name --attach stdin $IMAGE echo hello
|
||||
run_output=$output
|
||||
run_podman inspect --format "{{.Id}}" $ctr_name
|
||||
|
|
@ -1191,7 +1205,7 @@ EOF
|
|||
}
|
||||
|
||||
@test "podman run bad --name" {
|
||||
randomname=$(random_string 30)
|
||||
randomname=c_$(safename)
|
||||
run_podman 125 create --name "$randomname/bad" $IMAGE
|
||||
run_podman create --name "/$randomname" $IMAGE
|
||||
run_podman ps -a --filter name="^/$randomname$" --format '{{ .Names }}'
|
||||
|
|
@ -1253,7 +1267,7 @@ EOF
|
|||
run_podman run --uidmap=0:1000:200 --rm --rootfs "$romount:idmap=uids=@2000-1-1;gids=@2000-1-1" stat -c %u:%g /testfile
|
||||
is "$output" "1:1"
|
||||
|
||||
myvolume=my-volume-$(random_string)
|
||||
myvolume=my-volume-$(safename)
|
||||
run_podman volume create $myvolume
|
||||
mkdir $romount/volume
|
||||
run_podman run --rm --uidmap=0:1000:10000 -v volume:/volume:idmap --rootfs $romount stat -c %u:%g /volume
|
||||
|
|
@ -1265,7 +1279,7 @@ EOF
|
|||
|
||||
@test "podman run --restart=always -- wait" {
|
||||
# regression test for #18572 to make sure Podman waits less than 20 seconds
|
||||
ctr=$(random_string)
|
||||
ctr=c_$(safename)
|
||||
run_podman run -d --restart=always --name=$ctr $IMAGE false
|
||||
PODMAN_TIMEOUT=20 run_podman wait $ctr
|
||||
is "$output" "1" "container should exit 1"
|
||||
|
|
@ -1284,7 +1298,7 @@ cat >$containersconf <<EOF
|
|||
[engine]
|
||||
static_dir="$static_dir"
|
||||
EOF
|
||||
ctr=$(random_string)
|
||||
ctr=c_$(safename)
|
||||
CONTAINERS_CONF_OVERRIDE=$containersconf PODMAN_TIMEOUT=20 run_podman run --name=$ctr $IMAGE true
|
||||
CONTAINERS_CONF_OVERRIDE=$containersconf PODMAN_TIMEOUT=20 run_podman inspect --format "{{.ID}}" $ctr
|
||||
cid="$output"
|
||||
|
|
@ -1370,7 +1384,7 @@ search | $IMAGE |
|
|||
}
|
||||
|
||||
@test "podman create container with conflicting name" {
|
||||
local cname="$(random_string 10 | tr A-Z a-z)"
|
||||
local cname=c_$(safename)
|
||||
local output_msg_ext="^Error: .*: the container name \"$cname\" is already in use by .* You have to remove that container to be able to reuse that name: that name is already in use by an external entity, or use --replace to instruct Podman to do so."
|
||||
local output_msg="^Error: .*: the container name \"$cname\" is already in use by .* You have to remove that container to be able to reuse that name: that name is already in use, or use --replace to instruct Podman to do so."
|
||||
if is_remote; then
|
||||
|
|
@ -1433,12 +1447,13 @@ search | $IMAGE |
|
|||
}
|
||||
|
||||
@test "podman run - rm pod if container creation failed with -pod new:" {
|
||||
run_podman run -d --name foobar $IMAGE hostname
|
||||
cname=c_$(safename)
|
||||
run_podman run -d --name $cname $IMAGE hostname
|
||||
cid=$output
|
||||
|
||||
podname=pod$(random_string)
|
||||
run_podman 125 run --rm --pod "new:$podname" --name foobar $IMAGE hostname
|
||||
is "$output" ".*creating container storage: the container name \"foobar\" is already in use by"
|
||||
podname=pod_$(safename)
|
||||
run_podman 125 run --rm --pod "new:$podname" --name $cname $IMAGE hostname
|
||||
is "$output" ".*creating container storage: the container name \"$cname\" is already in use by"
|
||||
|
||||
# pod should've been cleaned up
|
||||
# if container creation failed
|
||||
|
|
@ -1467,27 +1482,28 @@ search | $IMAGE |
|
|||
@test "podman run - stopping loop" {
|
||||
skip_if_remote "this doesn't work with with the REST service"
|
||||
|
||||
run_podman run -d --name testctr --stop-timeout 240 $IMAGE sh -c 'echo READY; sleep 999'
|
||||
cname=c_$(safename)
|
||||
run_podman run -d --name $cname --stop-timeout 240 $IMAGE sh -c 'echo READY; sleep 999'
|
||||
cid="$output"
|
||||
wait_for_ready testctr
|
||||
wait_for_ready $cname
|
||||
|
||||
run_podman inspect --format '{{ .State.ConmonPid }}' testctr
|
||||
run_podman inspect --format '{{ .State.ConmonPid }}' $cname
|
||||
conmon_pid=$output
|
||||
|
||||
${PODMAN} stop testctr &
|
||||
${PODMAN} stop $cname &
|
||||
stop_pid=$!
|
||||
|
||||
timeout=20
|
||||
while :;do
|
||||
sleep 0.5
|
||||
run_podman container inspect --format '{{.State.Status}}' testctr
|
||||
run_podman container inspect --format '{{.State.Status}}' $cname
|
||||
if [[ "$output" = "stopping" ]]; then
|
||||
break
|
||||
fi
|
||||
timeout=$((timeout - 1))
|
||||
if [[ $timeout == 0 ]]; then
|
||||
run_podman ps -a
|
||||
die "Timed out waiting for testctr to acknowledge signal"
|
||||
die "Timed out waiting for container to acknowledge signal"
|
||||
fi
|
||||
done
|
||||
|
||||
|
|
@ -1496,14 +1512,14 @@ search | $IMAGE |
|
|||
|
||||
# Unclear why `-t0` is required here, works locally without.
|
||||
# But it shouldn't hurt and does make the test pass...
|
||||
PODMAN_TIMEOUT=5 run_podman 125 stop -t0 testctr
|
||||
PODMAN_TIMEOUT=5 run_podman 125 stop -t0 $cname
|
||||
is "$output" "Error: container .* conmon exited prematurely, exit code could not be retrieved: internal libpod error" "correct error on missing conmon"
|
||||
|
||||
# This should be safe because stop is guaranteed to call cleanup?
|
||||
run_podman inspect --format "{{ .State.Status }}" testctr
|
||||
run_podman inspect --format "{{ .State.Status }}" $cname
|
||||
is "$output" "exited" "container has successfully transitioned to exited state after stop"
|
||||
|
||||
run_podman rm -f -t0 testctr
|
||||
run_podman rm -f -t0 $cname
|
||||
}
|
||||
|
||||
# vim: filetype=sh
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ function _check_health {
|
|||
Status | \"healthy\"
|
||||
FailingStreak | 0
|
||||
Log[-1].ExitCode | 0
|
||||
Log[-1].Output | \"Life is Good on stdout\\\nLife is Good on stderr\"
|
||||
Log[-1].Output | \"Life is Good on stdout\\\nLife is Good on stderr\\\n\"
|
||||
" "$current_time" "healthy"
|
||||
|
||||
current_time=$(date --iso-8601=seconds)
|
||||
|
|
@ -71,7 +71,7 @@ Log[-1].Output | \"Life is Good on stdout\\\nLife is Good on stderr\"
|
|||
Status | \"healthy\"
|
||||
FailingStreak | [123]
|
||||
Log[-1].ExitCode | 1
|
||||
Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\"
|
||||
Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\\\n\"
|
||||
" "$current_time" "healthy"
|
||||
|
||||
# Check that we now we do have valid podman units with this
|
||||
|
|
@ -85,7 +85,7 @@ Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\"
|
|||
Status | \"unhealthy\"
|
||||
FailingStreak | [3456]
|
||||
Log[-1].ExitCode | 1
|
||||
Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\"
|
||||
Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\\\n\"
|
||||
" "$current_time" "unhealthy"
|
||||
|
||||
# now the on-failure should kick in and kill the container
|
||||
|
|
|
|||
|
|
@ -64,14 +64,18 @@ function run_quadlet() {
|
|||
assert $status -eq 0 "Failed to convert quadlet file: $sourcefile"
|
||||
is "$output" "" "quadlet should report no errors"
|
||||
|
||||
run cat $UNIT_DIR/$service
|
||||
assert $status -eq 0 "Could not cat $UNIT_DIR/$service"
|
||||
echo "$output"
|
||||
local content="$output"
|
||||
|
||||
# Ensure this is teared down
|
||||
UNIT_FILES+=("$UNIT_DIR/$service")
|
||||
|
||||
QUADLET_SERVICE_NAME="$service"
|
||||
QUADLET_SERVICE_CONTENT="$content"
|
||||
QUADLET_SYSLOG_ID="$(basename $service .service)"
|
||||
QUADLET_CONTAINER_NAME="systemd-$QUADLET_SYSLOG_ID"
|
||||
|
||||
cat $UNIT_DIR/$QUADLET_SERVICE_NAME
|
||||
}
|
||||
|
||||
function service_setup() {
|
||||
|
|
@ -1599,4 +1603,58 @@ EOF
|
|||
run_podman rmi $untagged_image:latest $built_image $(pause_image)
|
||||
run_podman network rm podman-default-kube-network
|
||||
}
|
||||
|
||||
@test "quadlet - drop-in files" {
|
||||
local quadlet_tmpdir="${PODMAN_TMPDIR}/dropins"
|
||||
|
||||
local quadlet_file="truncated-$(random_string).container"
|
||||
|
||||
local -A dropin_dirs=(
|
||||
[toplevel]=container.d
|
||||
[truncated]=truncated-.container.d
|
||||
[quadlet]="${quadlet_file}.d"
|
||||
)
|
||||
|
||||
# Table of drop-in .conf files. Format is:
|
||||
#
|
||||
# apply | dir | filename | [Section] | Content=...
|
||||
local dropin_files="
|
||||
y | toplevel | 10 | [Unit] | Description=Test File for Dropin Configuration
|
||||
n | toplevel | 99 | [Install] | WantedBy=default.target
|
||||
y | truncated | 50 | [Container] | ContainerName=truncated-dropins
|
||||
n | truncated | 99 | [Service] | Restart=always
|
||||
n | truncated | 99 | [Install] | WantedBy=multiuser.target
|
||||
y | quadlet | 99 | [Service] | RestartSec=60s
|
||||
"
|
||||
|
||||
# Pass 1: Create all drop-in directories and files
|
||||
while read apply dir file section content; do
|
||||
local d="${quadlet_tmpdir}/${dropin_dirs[${dir}]}"
|
||||
mkdir -p "${d}"
|
||||
|
||||
local f="${d}/${file}.conf"
|
||||
echo "${section}" >>"${f}"
|
||||
echo "${content}" >>"${f}"
|
||||
done < <(parse_table "${dropin_files}")
|
||||
|
||||
# Create the base quadlet file
|
||||
quadlet_base="${PODMAN_TMPDIR}/${quadlet_file}"
|
||||
cat > "${quadlet_base}" <<EOF
|
||||
[Container]
|
||||
Image="${IMAGE}"
|
||||
EOF
|
||||
|
||||
# Generate the quadlet file from the base file and any drop-in .conf files.
|
||||
run_quadlet "${quadlet_base}" "${quadlet_tmpdir}"
|
||||
|
||||
# Pass 2: test whether the expected .conf files are applied
|
||||
# and the overridden .conf files are not.
|
||||
while read apply dir file section content; do
|
||||
if [[ "${apply}" = "y" ]]; then
|
||||
assert "${QUADLET_SERVICE_CONTENT}" =~ "${content}" "Set in ${dir}/${file}.conf"
|
||||
else
|
||||
assert "${QUADLET_SERVICE_CONTENT}" !~ "${content}" "Set in ${dir}/${file}.conf but should have been overridden"
|
||||
fi
|
||||
done < <(parse_table "${dropin_files}")
|
||||
}
|
||||
# vim: filetype=sh
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ function check_subcommand() {
|
|||
# ...or machine. But podman machine is ultra-finicky, it fails as root
|
||||
# or if qemu is missing. Instead of checking for all the possible ways
|
||||
# to skip it, just try running init. If it works, we can test it.
|
||||
run_podman '?' machine init --image-path=/dev/null mymachine
|
||||
run_podman '?' machine init --image=/dev/null mymachine
|
||||
if [[ $status -eq 0 ]]; then
|
||||
can_run_podman_machine=true
|
||||
extra_args_table+="
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1153,6 +1153,28 @@ function random_string() {
|
|||
head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length
|
||||
}
|
||||
|
||||
##############
|
||||
# safename # Returns a pseudorandom string suitable for container/image/etc names
|
||||
##############
|
||||
#
|
||||
# Name will include the bats test number and a pseudorandom element,
|
||||
# eg "t123-xyz123". safename() will return the same string across
|
||||
# multiple invocations within a given test; this makes it easier for
|
||||
# a maintainer to see common name patterns.
|
||||
#
|
||||
# String is lower-case so it can be used as an image name
|
||||
#
|
||||
function safename() {
|
||||
# FIXME: I don't think these can ever fail. Remove checks once I'm sure.
|
||||
test -n "$BATS_SUITE_TMPDIR"
|
||||
test -n "$BATS_SUITE_TEST_NUMBER"
|
||||
safenamepath=$BATS_SUITE_TMPDIR/.safename.$BATS_SUITE_TEST_NUMBER
|
||||
if [[ ! -e $safenamepath ]]; then
|
||||
echo -n "t${BATS_SUITE_TEST_NUMBER}-$(random_string 8 | tr A-Z a-z)" >$safenamepath
|
||||
fi
|
||||
cat $safenamepath
|
||||
}
|
||||
|
||||
#########################
|
||||
# find_exec_pid_files # Returns nothing or exec_pid hash files
|
||||
#########################
|
||||
|
|
|
|||
6
vendor/github.com/containers/common/libimage/filters.go
generated
vendored
6
vendor/github.com/containers/common/libimage/filters.go
generated
vendored
|
|
@ -88,6 +88,8 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
|||
return tree, nil
|
||||
}
|
||||
|
||||
filterInvalidValue := `invalid image filter %q: must be in the format "filter=value or filter!=value"`
|
||||
|
||||
var wantedReferenceMatches, unwantedReferenceMatches []string
|
||||
filters := map[string][]filterFunc{}
|
||||
duplicate := map[string]string{}
|
||||
|
|
@ -101,7 +103,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
|||
} else {
|
||||
split = strings.SplitN(f, "=", 2)
|
||||
if len(split) != 2 {
|
||||
return nil, fmt.Errorf("invalid image filter %q: must be in the format %q", f, "filter=value or filter!=value")
|
||||
return nil, fmt.Errorf(filterInvalidValue, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +197,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
|||
filter = filterBefore(until)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported image filter %q", key)
|
||||
return nil, fmt.Errorf(filterInvalidValue, key)
|
||||
}
|
||||
if negate {
|
||||
filter = negateFilter(filter)
|
||||
|
|
|
|||
3
vendor/github.com/u-root/uio/ulog/log.go
generated
vendored
3
vendor/github.com/u-root/uio/ulog/log.go
generated
vendored
|
|
@ -16,7 +16,6 @@ import "log"
|
|||
// It puts your information somewhere for safekeeping.
|
||||
type Logger interface {
|
||||
Printf(format string, v ...interface{})
|
||||
Print(v ...interface{})
|
||||
}
|
||||
|
||||
// Log is a Logger that prints to the log package's default logger.
|
||||
|
|
@ -24,8 +23,8 @@ var Log Logger = log.Default()
|
|||
|
||||
type emptyLogger struct{}
|
||||
|
||||
// Printf implements Logger.Printf.
|
||||
func (emptyLogger) Printf(format string, v ...interface{}) {}
|
||||
func (emptyLogger) Print(v ...interface{}) {}
|
||||
|
||||
// Null is a logger that prints nothing.
|
||||
var Null Logger = emptyLogger{}
|
||||
|
|
|
|||
13
vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go
generated
vendored
13
vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go
generated
vendored
|
|
@ -233,7 +233,7 @@ func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) error {
|
|||
var tip component
|
||||
var refilling, filling, padding []byte
|
||||
var fillCount int
|
||||
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, uint(width)))
|
||||
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, int64(width)))
|
||||
|
||||
if curWidth != 0 {
|
||||
if !stat.Completed || s.tipOnComplete {
|
||||
|
|
@ -241,20 +241,19 @@ func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) error {
|
|||
s.tip.count++
|
||||
fillCount += tip.width
|
||||
}
|
||||
if stat.Refill != 0 {
|
||||
refWidth := int(internal.PercentageRound(stat.Total, stat.Refill, uint(width)))
|
||||
switch refWidth := 0; {
|
||||
case stat.Refill != 0:
|
||||
refWidth = int(internal.PercentageRound(stat.Total, stat.Refill, int64(width)))
|
||||
curWidth -= refWidth
|
||||
refWidth += curWidth
|
||||
fallthrough
|
||||
default:
|
||||
for w := s.components[iFiller].width; curWidth-fillCount >= w; fillCount += w {
|
||||
filling = append(filling, s.components[iFiller].bytes...)
|
||||
}
|
||||
for w := s.components[iRefiller].width; refWidth-fillCount >= w; fillCount += w {
|
||||
refilling = append(refilling, s.components[iRefiller].bytes...)
|
||||
}
|
||||
} else {
|
||||
for w := s.components[iFiller].width; curWidth-fillCount >= w; fillCount += w {
|
||||
filling = append(filling, s.components[iFiller].bytes...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
16
vendor/github.com/vbauerster/mpb/v8/decor/eta.go
generated
vendored
16
vendor/github.com/vbauerster/mpb/v8/decor/eta.go
generated
vendored
|
|
@ -81,15 +81,15 @@ func (d *movingAverageETA) Decor(s Statistics) (string, int) {
|
|||
func (d *movingAverageETA) EwmaUpdate(n int64, dur time.Duration) {
|
||||
if n <= 0 {
|
||||
d.zDur += dur
|
||||
} else {
|
||||
durPerItem := float64(d.zDur+dur) / float64(n)
|
||||
if math.IsInf(durPerItem, 0) || math.IsNaN(durPerItem) {
|
||||
d.zDur += dur
|
||||
return
|
||||
}
|
||||
d.zDur = 0
|
||||
d.average.Add(durPerItem)
|
||||
return
|
||||
}
|
||||
durPerItem := float64(d.zDur+dur) / float64(n)
|
||||
if math.IsInf(durPerItem, 0) || math.IsNaN(durPerItem) {
|
||||
d.zDur += dur
|
||||
return
|
||||
}
|
||||
d.zDur = 0
|
||||
d.average.Add(durPerItem)
|
||||
}
|
||||
|
||||
// AverageETA decorator. It's wrapper of NewAverageETA.
|
||||
|
|
|
|||
2
vendor/github.com/vbauerster/mpb/v8/decor/percentage.go
generated
vendored
2
vendor/github.com/vbauerster/mpb/v8/decor/percentage.go
generated
vendored
|
|
@ -61,7 +61,7 @@ func NewPercentage(format string, wcc ...WC) Decorator {
|
|||
format = "% d"
|
||||
}
|
||||
f := func(s Statistics) string {
|
||||
p := internal.Percentage(s.Total, s.Current, 100)
|
||||
p := internal.PercentageRound(s.Total, s.Current, 100)
|
||||
return fmt.Sprintf(format, percentageType(p))
|
||||
}
|
||||
return Any(f, wcc...)
|
||||
|
|
|
|||
16
vendor/github.com/vbauerster/mpb/v8/decor/speed.go
generated
vendored
16
vendor/github.com/vbauerster/mpb/v8/decor/speed.go
generated
vendored
|
|
@ -96,15 +96,15 @@ func (d *movingAverageSpeed) Decor(_ Statistics) (string, int) {
|
|||
func (d *movingAverageSpeed) EwmaUpdate(n int64, dur time.Duration) {
|
||||
if n <= 0 {
|
||||
d.zDur += dur
|
||||
} else {
|
||||
durPerByte := float64(d.zDur+dur) / float64(n)
|
||||
if math.IsInf(durPerByte, 0) || math.IsNaN(durPerByte) {
|
||||
d.zDur += dur
|
||||
return
|
||||
}
|
||||
d.zDur = 0
|
||||
d.average.Add(durPerByte)
|
||||
return
|
||||
}
|
||||
durPerByte := float64(d.zDur+dur) / float64(n)
|
||||
if math.IsInf(durPerByte, 0) || math.IsNaN(durPerByte) {
|
||||
d.zDur += dur
|
||||
return
|
||||
}
|
||||
d.zDur = 0
|
||||
d.average.Add(durPerByte)
|
||||
}
|
||||
|
||||
// AverageSpeed decorator with dynamic unit measure adjustment. It's
|
||||
|
|
|
|||
13
vendor/github.com/vbauerster/mpb/v8/internal/percentage.go
generated
vendored
13
vendor/github.com/vbauerster/mpb/v8/internal/percentage.go
generated
vendored
|
|
@ -3,17 +3,20 @@ package internal
|
|||
import "math"
|
||||
|
||||
// Percentage is a helper function, to calculate percentage.
|
||||
func Percentage(total, current int64, width uint) float64 {
|
||||
if total <= 0 {
|
||||
func Percentage(total, current, width uint) float64 {
|
||||
if total == 0 {
|
||||
return 0
|
||||
}
|
||||
if current >= total {
|
||||
return float64(width)
|
||||
}
|
||||
return float64(int64(width)*current) / float64(total)
|
||||
return float64(width*current) / float64(total)
|
||||
}
|
||||
|
||||
// PercentageRound same as Percentage but with math.Round.
|
||||
func PercentageRound(total, current int64, width uint) float64 {
|
||||
return math.Round(Percentage(total, current, width))
|
||||
func PercentageRound(total, current, width int64) float64 {
|
||||
if total < 0 || current < 0 || width < 0 {
|
||||
return 0
|
||||
}
|
||||
return math.Round(Percentage(uint(total), uint(current), uint(width)))
|
||||
}
|
||||
|
|
|
|||
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
|
|
@ -169,7 +169,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.59.1-0.20240715151621-fdf625dfee0e
|
||||
# github.com/containers/common v0.59.1-0.20240717135212-fdbae3a180cb
|
||||
## explicit; go 1.21.0
|
||||
github.com/containers/common/internal
|
||||
github.com/containers/common/internal/attributedstring
|
||||
|
|
@ -949,8 +949,8 @@ github.com/proglottis/gpgme
|
|||
# github.com/rivo/uniseg v0.4.7
|
||||
## explicit; go 1.18
|
||||
github.com/rivo/uniseg
|
||||
# github.com/rootless-containers/rootlesskit/v2 v2.1.0
|
||||
## explicit; go 1.19
|
||||
# github.com/rootless-containers/rootlesskit/v2 v2.2.0
|
||||
## explicit; go 1.21.0
|
||||
github.com/rootless-containers/rootlesskit/v2/pkg/api
|
||||
github.com/rootless-containers/rootlesskit/v2/pkg/lowlevelmsgutil
|
||||
github.com/rootless-containers/rootlesskit/v2/pkg/port
|
||||
|
|
@ -1062,8 +1062,8 @@ github.com/twitchyliquid64/golang-asm/objabi
|
|||
github.com/twitchyliquid64/golang-asm/src
|
||||
github.com/twitchyliquid64/golang-asm/sys
|
||||
github.com/twitchyliquid64/golang-asm/unsafeheader
|
||||
# github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63
|
||||
## explicit; go 1.16
|
||||
# github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701
|
||||
## explicit; go 1.21
|
||||
github.com/u-root/uio/ulog
|
||||
# github.com/ugorji/go/codec v1.2.12
|
||||
## explicit; go 1.11
|
||||
|
|
@ -1079,7 +1079,7 @@ github.com/ulikunitz/xz/lzma
|
|||
github.com/vbatts/tar-split/archive/tar
|
||||
github.com/vbatts/tar-split/tar/asm
|
||||
github.com/vbatts/tar-split/tar/storage
|
||||
# github.com/vbauerster/mpb/v8 v8.7.3
|
||||
# github.com/vbauerster/mpb/v8 v8.7.4
|
||||
## explicit; go 1.17
|
||||
github.com/vbauerster/mpb/v8
|
||||
github.com/vbauerster/mpb/v8/cwriter
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue