summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/create.go2
-rw-r--r--cmd/podman/common/create_opts.go2
-rw-r--r--cmd/podman/machine/init.go6
-rw-r--r--cmd/podman/machine/inspect.go34
-rw-r--r--cmd/podman/machine/list.go3
-rw-r--r--cmd/podman/machine/machine.go110
-rw-r--r--cmd/podman/machine/platform.go2
-rw-r--r--cmd/podman/machine/platform_windows.go2
-rw-r--r--cmd/podman/machine/rm.go12
-rw-r--r--cmd/podman/machine/set.go2
-rw-r--r--cmd/podman/machine/ssh.go2
-rw-r--r--cmd/podman/machine/start.go6
-rw-r--r--cmd/podman/machine/stop.go4
-rw-r--r--cmd/podman/main.go9
-rw-r--r--cmd/podman/play/kube.go2
-rw-r--r--cmd/podman/system/connection.go15
-rw-r--r--cmd/podman/system/reset.go10
-rw-r--r--cmd/podman/system/reset_machine.go13
-rw-r--r--cmd/podman/system/reset_machine_unsupported.go8
-rw-r--r--cmd/podman/system/service_abi.go37
-rw-r--r--cmd/podman/validate/noop.go9
-rw-r--r--docs/source/markdown/podman-system-reset.1.md3
-rw-r--r--docs/tutorials/rootless_tutorial.md10
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--hack/podman-registry-go/registry.go23
-rw-r--r--libpod/container.go14
-rw-r--r--libpod/events/config.go6
-rw-r--r--libpod/events/events.go22
-rw-r--r--libpod/events/events_linux.go2
-rw-r--r--libpod/events/memory.go49
-rw-r--r--libpod/oci_attach_linux.go3
-rw-r--r--libpod/runtime.go14
-rw-r--r--pkg/api/handlers/libpod/play.go10
-rw-r--r--pkg/api/server/server.go21
-rw-r--r--pkg/domain/infra/abi/containers.go6
-rw-r--r--pkg/domain/infra/abi/system.go44
-rw-r--r--pkg/domain/utils/utils_test.go76
-rw-r--r--pkg/env/env_test.go162
-rw-r--r--pkg/machine/config.go29
-rw-r--r--pkg/machine/e2e/inspect_test.go12
-rw-r--r--pkg/machine/e2e/machine_test.go11
-rw-r--r--pkg/machine/qemu/machine.go79
-rw-r--r--pkg/machine/wsl/machine.go76
-rw-r--r--pkg/specgen/generate/container.go2
-rw-r--r--pkg/specgen/generate/container_create.go16
-rw-r--r--pkg/util/utils.go23
-rw-r--r--test/e2e/benchmarks_test.go71
-rw-r--r--test/e2e/common_test.go34
-rw-r--r--test/e2e/container_clone_test.go26
-rw-r--r--test/e2e/info_test.go28
-rw-r--r--test/e2e/play_kube_test.go8
-rw-r--r--test/e2e/system_connection_test.go2
-rw-r--r--test/e2e/system_reset_test.go7
-rw-r--r--test/e2e/system_service_test.go18
-rw-r--r--test/system/272-system-connection.bats7
-rw-r--r--test/system/700-play.bats17
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go2
-rw-r--r--vendor/modules.txt2
60 files changed, 1009 insertions, 223 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index 1c1a7c3e3..d28becc8a 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -299,7 +299,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
logDriverFlagName := "log-driver"
createFlags.StringVar(
&cf.LogDriver,
- logDriverFlagName, logDriver(),
+ logDriverFlagName, LogDriver(),
"Logging driver for the container",
)
_ = cmd.RegisterFlagCompletionFunc(logDriverFlagName, AutocompleteLogDriver)
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index 16f193b03..c40d1ea51 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -530,7 +530,7 @@ func volumes() []string {
return nil
}
-func logDriver() string {
+func LogDriver() string {
if !registry.IsRemote() {
return containerConfig.Containers.LogDriver
}
diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go
index 4991c6aa3..6c31f3531 100644
--- a/cmd/podman/machine/init.go
+++ b/cmd/podman/machine/init.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/registry"
+ "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -117,7 +118,7 @@ func initMachine(cmd *cobra.Command, args []string) error {
vm machine.VM
)
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
initOpts.Name = defaultMachineName
if len(args) > 0 {
if len(args[0]) > maxMachineNameSize {
@@ -145,11 +146,14 @@ func initMachine(cmd *cobra.Command, args []string) error {
// Finished = *, err != nil - Exit with an error message
return err
}
+ newMachineEvent(events.Init, events.Event{Name: initOpts.Name})
fmt.Println("Machine init complete")
+
if now {
err = vm.Start(initOpts.Name, machine.StartOptions{})
if err == nil {
fmt.Printf("Machine %q started successfully\n", initOpts.Name)
+ newMachineEvent(events.Start, events.Event{Name: initOpts.Name})
}
} else {
extra := ""
diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go
index 21e5074b7..4600a2b6d 100644
--- a/cmd/podman/machine/inspect.go
+++ b/cmd/podman/machine/inspect.go
@@ -4,13 +4,12 @@
package machine
import (
- "encoding/json"
"os"
+ "github.com/containers/common/pkg/report"
"github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/utils"
- "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/machine"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -52,7 +51,7 @@ func inspect(cmd *cobra.Command, args []string) error {
args = append(args, defaultMachineName)
}
vms := make([]machine.InspectInfo, 0, len(args))
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
for _, vmName := range args {
vm, err := provider.LoadVMByName(vmName)
if err != nil {
@@ -66,12 +65,29 @@ func inspect(cmd *cobra.Command, args []string) error {
}
vms = append(vms, *ii)
}
- if len(inspectFlag.format) > 0 {
- // need jhonce to work his template magic
- return define.ErrNotImplemented
- }
- if err := printJSON(vms); err != nil {
- logrus.Error(err)
+ switch {
+ case cmd.Flag("format").Changed:
+ row := report.NormalizeFormat(inspectFlag.format)
+ row = report.EnforceRange(row)
+
+ tmpl, err := report.NewTemplate("Machine inspect").Parse(row)
+ if err != nil {
+ return err
+ }
+
+ w, err := report.NewWriterDefault(os.Stdout)
+ if err != nil {
+ return err
+ }
+
+ if err := tmpl.Execute(w, vms); err != nil {
+ logrus.Error(err)
+ }
+ w.Flush()
+ default:
+ if err := printJSON(vms); err != nil {
+ logrus.Error(err)
+ }
}
return errs.PrintErrors()
}
diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
index c987bf71a..ef26b7886 100644
--- a/cmd/podman/machine/list.go
+++ b/cmd/podman/machine/list.go
@@ -4,7 +4,6 @@
package machine
import (
- "encoding/json"
"os"
"sort"
"strconv"
@@ -85,7 +84,7 @@ func list(cmd *cobra.Command, args []string) error {
listFlag.format = "{{.Name}}\n"
}
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
listResponse, err = provider.List(opts)
if err != nil {
return errors.Wrap(err, "error listing vms")
diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go
index d3775f022..553f1ef7a 100644
--- a/cmd/podman/machine/machine.go
+++ b/cmd/podman/machine/machine.go
@@ -4,25 +4,38 @@
package machine
import (
+ "errors"
+ "net"
+ "os"
+ "path/filepath"
+ "regexp"
"strings"
+ "sync"
+ "time"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/validate"
+ "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
+ "github.com/containers/podman/v4/pkg/util"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var (
- noOp = func(cmd *cobra.Command, args []string) error {
- return nil
- }
+ // Pull in configured json library
+ json = registry.JSONLibrary()
+
+ openEventSock sync.Once // Singleton support for opening sockets as needed
+ sockets []net.Conn // Opened sockets, if any
+
// Command: podman _machine_
machineCmd = &cobra.Command{
Use: "machine",
Short: "Manage a virtual machine",
Long: "Manage a virtual machine. Virtual machines are used to run Podman.",
- PersistentPreRunE: noOp,
- PersistentPostRunE: noOp,
+ PersistentPreRunE: validate.NoOp,
+ PersistentPostRunE: closeMachineEvents,
RunE: validate.SubCommandExists,
}
)
@@ -51,7 +64,7 @@ func autocompleteMachine(cmd *cobra.Command, args []string, toComplete string) (
func getMachines(toComplete string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
machines, err := provider.List(machine.ListOptions{})
if err != nil {
cobra.CompErrorln(err.Error())
@@ -64,3 +77,88 @@ func getMachines(toComplete string) ([]string, cobra.ShellCompDirective) {
}
return suggestions, cobra.ShellCompDirectiveNoFileComp
}
+
+func initMachineEvents() {
+ sockPaths, err := resolveEventSock()
+ if err != nil {
+ logrus.Warnf("Failed to resolve machine event sockets, machine events will not be published: %v", err)
+ }
+
+ for _, path := range sockPaths {
+ conn, err := (&net.Dialer{}).DialContext(registry.Context(), "unix", path)
+ if err != nil {
+ logrus.Warnf("Failed to open event socket %q: %v", path, err)
+ continue
+ }
+ logrus.Debugf("Machine event socket %q found", path)
+ sockets = append(sockets, conn)
+ }
+}
+
+func resolveEventSock() ([]string, error) {
+ // Used mostly for testing
+ if sock, found := os.LookupEnv("PODMAN_MACHINE_EVENTS_SOCK"); found {
+ return []string{sock}, nil
+ }
+
+ xdg, err := util.GetRuntimeDir()
+ if err != nil {
+ logrus.Warnf("Failed to get runtime dir, machine events will not be published: %s", err)
+ return nil, nil
+ }
+
+ re := regexp.MustCompile(`machine_events.*\.sock`)
+ sockPaths := make([]string, 0)
+ fn := func(path string, info os.DirEntry, err error) error {
+ switch {
+ case err != nil:
+ return err
+ case info.IsDir():
+ return nil
+ case info.Type() != os.ModeSocket:
+ return nil
+ case !re.MatchString(info.Name()):
+ return nil
+ }
+
+ logrus.Debugf("Machine events will be published on: %q", path)
+ sockPaths = append(sockPaths, path)
+ return nil
+ }
+
+ if err := filepath.WalkDir(filepath.Join(xdg, "podman"), fn); err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ return nil, nil
+ }
+ return nil, err
+ }
+ return sockPaths, nil
+}
+
+func newMachineEvent(status events.Status, event events.Event) {
+ openEventSock.Do(initMachineEvents)
+
+ event.Status = status
+ event.Time = time.Now()
+ event.Type = events.Machine
+
+ payload, err := json.Marshal(event)
+ if err != nil {
+ logrus.Errorf("Unable to format machine event: %q", err)
+ return
+ }
+
+ for _, sock := range sockets {
+ if _, err := sock.Write(payload); err != nil {
+ logrus.Errorf("Unable to write machine event: %q", err)
+ }
+ }
+}
+
+func closeMachineEvents(cmd *cobra.Command, _ []string) error {
+ logrus.Debugf("Called machine %s.PersistentPostRunE(%s)", cmd.Name(), strings.Join(os.Args, " "))
+ for _, sock := range sockets {
+ _ = sock.Close()
+ }
+ return nil
+}
diff --git a/cmd/podman/machine/platform.go b/cmd/podman/machine/platform.go
index 77fec083e..5ba649a48 100644
--- a/cmd/podman/machine/platform.go
+++ b/cmd/podman/machine/platform.go
@@ -8,6 +8,6 @@ import (
"github.com/containers/podman/v4/pkg/machine/qemu"
)
-func getSystemDefaultProvider() machine.Provider {
+func GetSystemDefaultProvider() machine.Provider {
return qemu.GetQemuProvider()
}
diff --git a/cmd/podman/machine/platform_windows.go b/cmd/podman/machine/platform_windows.go
index 03978eda1..cdbc52459 100644
--- a/cmd/podman/machine/platform_windows.go
+++ b/cmd/podman/machine/platform_windows.go
@@ -5,6 +5,6 @@ import (
"github.com/containers/podman/v4/pkg/machine/wsl"
)
-func getSystemDefaultProvider() machine.Provider {
+func GetSystemDefaultProvider() machine.Provider {
return wsl.GetWSLProvider()
}
diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go
index 617a70a76..a6e66265c 100644
--- a/cmd/podman/machine/rm.go
+++ b/cmd/podman/machine/rm.go
@@ -10,6 +10,7 @@ import (
"strings"
"github.com/containers/podman/v4/cmd/podman/registry"
+ "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
"github.com/spf13/cobra"
)
@@ -50,7 +51,7 @@ func init() {
flags.BoolVar(&destroyOptions.SaveImage, imageFlagName, false, "Do not delete the image file")
}
-func rm(cmd *cobra.Command, args []string) error {
+func rm(_ *cobra.Command, args []string) error {
var (
err error
vm machine.VM
@@ -60,7 +61,7 @@ func rm(cmd *cobra.Command, args []string) error {
vmName = args[0]
}
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
vm, err = provider.LoadVMByName(vmName)
if err != nil {
return err
@@ -83,5 +84,10 @@ func rm(cmd *cobra.Command, args []string) error {
return nil
}
}
- return remove()
+ err = remove()
+ if err != nil {
+ return err
+ }
+ newMachineEvent(events.Remove, events.Event{Name: vmName})
+ return nil
}
diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go
index a994c981b..5777882da 100644
--- a/cmd/podman/machine/set.go
+++ b/cmd/podman/machine/set.go
@@ -83,7 +83,7 @@ func setMachine(cmd *cobra.Command, args []string) error {
if len(args) > 0 && len(args[0]) > 0 {
vmName = args[0]
}
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
vm, err = provider.LoadVMByName(vmName)
if err != nil {
return err
diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go
index e1175d632..4a86da67a 100644
--- a/cmd/podman/machine/ssh.go
+++ b/cmd/podman/machine/ssh.go
@@ -51,7 +51,7 @@ func ssh(cmd *cobra.Command, args []string) error {
// Set the VM to default
vmName := defaultMachineName
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
// If len is greater than 0, it means we may have been
// provided the VM name. If so, we check. The VM name,
diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go
index 56acb09cb..c9b99e63b 100644
--- a/cmd/podman/machine/start.go
+++ b/cmd/podman/machine/start.go
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/containers/podman/v4/cmd/podman/registry"
+ "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -31,7 +32,7 @@ func init() {
})
}
-func start(cmd *cobra.Command, args []string) error {
+func start(_ *cobra.Command, args []string) error {
var (
err error
vm machine.VM
@@ -41,7 +42,7 @@ func start(cmd *cobra.Command, args []string) error {
vmName = args[0]
}
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
vm, err = provider.LoadVMByName(vmName)
if err != nil {
return err
@@ -62,5 +63,6 @@ func start(cmd *cobra.Command, args []string) error {
return err
}
fmt.Printf("Machine %q started successfully\n", vmName)
+ newMachineEvent(events.Start, events.Event{Name: vmName})
return nil
}
diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go
index e6bf3cf2b..993662792 100644
--- a/cmd/podman/machine/stop.go
+++ b/cmd/podman/machine/stop.go
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/containers/podman/v4/cmd/podman/registry"
+ "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
"github.com/spf13/cobra"
)
@@ -40,7 +41,7 @@ func stop(cmd *cobra.Command, args []string) error {
if len(args) > 0 && len(args[0]) > 0 {
vmName = args[0]
}
- provider := getSystemDefaultProvider()
+ provider := GetSystemDefaultProvider()
vm, err = provider.LoadVMByName(vmName)
if err != nil {
return err
@@ -49,5 +50,6 @@ func stop(cmd *cobra.Command, args []string) error {
return err
}
fmt.Printf("Machine %q stopped successfully\n", vmName)
+ newMachineEvent(events.Stop, events.Event{Name: vmName})
return nil
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 8f580601e..929c8a757 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -18,6 +18,7 @@ import (
_ "github.com/containers/podman/v4/cmd/podman/secrets"
_ "github.com/containers/podman/v4/cmd/podman/system"
_ "github.com/containers/podman/v4/cmd/podman/system/connection"
+ "github.com/containers/podman/v4/cmd/podman/validate"
_ "github.com/containers/podman/v4/cmd/podman/volumes"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/rootless"
@@ -64,8 +65,8 @@ func parseCommands() *cobra.Command {
c.Command.Hidden = true
// overwrite persistent pre/post function to skip setup
- c.Command.PersistentPostRunE = noop
- c.Command.PersistentPreRunE = noop
+ c.Command.PersistentPostRunE = validate.NoOp
+ c.Command.PersistentPreRunE = validate.NoOp
addCommand(c)
continue
}
@@ -120,7 +121,3 @@ func addCommand(c registry.CliCommand) {
c.Command.SetUsageTemplate(usageTemplate)
c.Command.DisableFlagsInUseLine = true
}
-
-func noop(cmd *cobra.Command, args []string) error {
- return nil
-}
diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go
index 40d14a609..3be7396ce 100644
--- a/cmd/podman/play/kube.go
+++ b/cmd/podman/play/kube.go
@@ -87,7 +87,7 @@ func init() {
_ = kubeCmd.RegisterFlagCompletionFunc(staticIPFlagName, completion.AutocompleteNone)
logDriverFlagName := "log-driver"
- flags.StringVar(&kubeOptions.LogDriver, logDriverFlagName, "", "Logging driver for the container")
+ flags.StringVar(&kubeOptions.LogDriver, logDriverFlagName, common.LogDriver(), "Logging driver for the container")
_ = kubeCmd.RegisterFlagCompletionFunc(logDriverFlagName, common.AutocompleteLogDriver)
logOptFlagName := "log-opt"
diff --git a/cmd/podman/system/connection.go b/cmd/podman/system/connection.go
index 5164de78c..5dbe50fc9 100644
--- a/cmd/podman/system/connection.go
+++ b/cmd/podman/system/connection.go
@@ -7,18 +7,15 @@ import (
)
var (
- // Skip creating engines since this command will obtain connection information to said engines
- noOp = func(cmd *cobra.Command, args []string) error {
- return nil
- }
-
+ // ConnectionCmd skips creating engines (PersistentPreRunE/PersistentPostRunE are No-Op's) since
+ // sub-commands will obtain connection information to said engines
ConnectionCmd = &cobra.Command{
Use: "connection",
- Short: "Manage remote ssh destinations",
- Long: `Manage ssh destination information in podman configuration`,
- PersistentPreRunE: noOp,
+ Short: "Manage remote API service destinations",
+ Long: `Manage remote API service destination information in podman configuration`,
+ PersistentPreRunE: validate.NoOp,
RunE: validate.SubCommandExists,
- PersistentPostRunE: noOp,
+ PersistentPostRunE: validate.NoOp,
TraverseChildren: false,
}
)
diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go
index 8f2e73375..176573bf6 100644
--- a/cmd/podman/system/reset.go
+++ b/cmd/podman/system/reset.go
@@ -61,7 +61,9 @@ func reset(cmd *cobra.Command, args []string) {
- all pods
- all images
- all networks
- - all build cache`)
+ - all build cache
+ - all machines`)
+
if len(listCtn) > 0 {
fmt.Println(`WARNING! The following external containers will be purged:`)
// print first 12 characters of ID and first configured name alias
@@ -103,5 +105,11 @@ func reset(cmd *cobra.Command, args []string) {
//nolint:gocritic
os.Exit(define.ExecErrorCodeGeneric)
}
+
+ // Shutdown podman-machine and delete all machine files
+ if err := resetMachine(); err != nil {
+ logrus.Error(err)
+ }
+
os.Exit(0)
}
diff --git a/cmd/podman/system/reset_machine.go b/cmd/podman/system/reset_machine.go
new file mode 100644
index 000000000..a07b4fb83
--- /dev/null
+++ b/cmd/podman/system/reset_machine.go
@@ -0,0 +1,13 @@
+//go:build (amd64 && !remote) || (arm64 && !remote)
+// +build amd64,!remote arm64,!remote
+
+package system
+
+import (
+ cmdMach "github.com/containers/podman/v4/cmd/podman/machine"
+)
+
+func resetMachine() error {
+ provider := cmdMach.GetSystemDefaultProvider()
+ return provider.RemoveAndCleanMachines()
+}
diff --git a/cmd/podman/system/reset_machine_unsupported.go b/cmd/podman/system/reset_machine_unsupported.go
new file mode 100644
index 000000000..e063cd089
--- /dev/null
+++ b/cmd/podman/system/reset_machine_unsupported.go
@@ -0,0 +1,8 @@
+//go:build !amd64 && !arm64
+// +build !amd64,!arm64
+
+package system
+
+func resetMachine() error {
+ return nil
+}
diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go
index f8abea3aa..9dc9de1c8 100644
--- a/cmd/podman/system/service_abi.go
+++ b/cmd/podman/system/service_abi.go
@@ -4,17 +4,18 @@
package system
import (
- "context"
+ "fmt"
"net"
"net/url"
"os"
"path/filepath"
+ "github.com/containers/podman/v4/cmd/podman/registry"
api "github.com/containers/podman/v4/pkg/api/server"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/infra"
"github.com/containers/podman/v4/pkg/servicereaper"
- "github.com/containers/podman/v4/pkg/util"
+ "github.com/coreos/go-systemd/v22/activation"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
@@ -27,7 +28,26 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities
err error
)
- if opts.URI != "" {
+ libpodRuntime, err := infra.GetRuntime(registry.Context(), flags, cfg)
+ if err != nil {
+ return err
+ }
+
+ if opts.URI == "" {
+ if _, found := os.LookupEnv("LISTEN_PID"); !found {
+ return errors.New("no service URI provided and socket activation protocol is not active")
+ }
+
+ listeners, err := activation.Listeners()
+ if err != nil {
+ return fmt.Errorf("cannot retrieve file descriptors from systemd: %w", err)
+ }
+ if len(listeners) != 1 {
+ return fmt.Errorf("wrong number of file descriptors for socket activation protocol (%d != 1)", len(listeners))
+ }
+ listener = listeners[0]
+ libpodRuntime.SetRemoteURI(listeners[0].Addr().String())
+ } else {
uri, err := url.Parse(opts.URI)
if err != nil {
return errors.Errorf("%s is an invalid socket destination", opts.URI)
@@ -39,7 +59,6 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities
if err != nil {
return err
}
- util.SetSocketPath(path)
if os.Getenv("LISTEN_FDS") != "" {
// If it is activated by systemd, use the first LISTEN_FD (3)
// instead of opening the socket file.
@@ -67,6 +86,7 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities
default:
logrus.Debugf("Attempting API Service endpoint scheme %q", uri.Scheme)
}
+ libpodRuntime.SetRemoteURI(uri.String())
}
// Close stdin, so shortnames will not prompt
@@ -78,15 +98,10 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities
if err := unix.Dup2(int(devNullfile.Fd()), int(os.Stdin.Fd())); err != nil {
return err
}
- rt, err := infra.GetRuntime(context.Background(), flags, cfg)
- if err != nil {
- return err
- }
servicereaper.Start()
-
- infra.StartWatcher(rt)
- server, err := api.NewServerWithSettings(rt, listener, opts)
+ infra.StartWatcher(libpodRuntime)
+ server, err := api.NewServerWithSettings(libpodRuntime, listener, opts)
if err != nil {
return err
}
diff --git a/cmd/podman/validate/noop.go b/cmd/podman/validate/noop.go
new file mode 100644
index 000000000..2243ef5c4
--- /dev/null
+++ b/cmd/podman/validate/noop.go
@@ -0,0 +1,9 @@
+package validate
+
+import (
+ "github.com/spf13/cobra"
+)
+
+func NoOp(_ *cobra.Command, _ []string) error {
+ return nil
+}
diff --git a/docs/source/markdown/podman-system-reset.1.md b/docs/source/markdown/podman-system-reset.1.md
index c463481e6..11ce11d07 100644
--- a/docs/source/markdown/podman-system-reset.1.md
+++ b/docs/source/markdown/podman-system-reset.1.md
@@ -7,7 +7,7 @@ podman\-system\-reset - Reset storage back to initial state
**podman system reset** [*options*]
## DESCRIPTION
-**podman system reset** removes all pods, containers, images, networks and volumes.
+**podman system reset** removes all pods, containers, images, networks and volumes, and machines.
This command must be run **before** changing any of the following fields in the
`containers.conf` or `storage.conf` files: `driver`, `static_dir`, `tmp_dir`
@@ -36,6 +36,7 @@ WARNING! This will remove:
- all images
- all networks
- all build cache
+ - all machines
Are you sure you want to continue? [y/N] y
```
diff --git a/docs/tutorials/rootless_tutorial.md b/docs/tutorials/rootless_tutorial.md
index 5d20f2cc0..981916806 100644
--- a/docs/tutorials/rootless_tutorial.md
+++ b/docs/tutorials/rootless_tutorial.md
@@ -19,11 +19,11 @@ or for all commands by changing the value for the "Default OCI runtime" in the `
### Installing Podman
-For installing Podman, please see the [installation instructions](https://github.com/containers/podman/blob/main/install.md).
+For installing Podman, please see the [installation instructions](https://podman.io/getting-started/installation).
### Building Podman
-For building Podman, please see the [installation instructions](https://github.com/containers/podman/blob/main/install.md#building-from-scratch).
+For building Podman, please see the [build instructions](https://podman.io/getting-started/installation#building-from-scratch).
### Install `slirp4netns`
@@ -81,10 +81,10 @@ If you update either `/etc/subuid` or `/etc/subgid`, you need to stop all the ru
Rather than updating the files directly, the `usermod` program can be used to assign UIDs and GIDs to a user.
```
-usermod --add-subuids 200000-201000 --add-subgids 200000-201000 johndoe
+usermod --add-subuids 100000-165535 --add-subgids 100000-165535 johndoe
grep johndoe /etc/subuid /etc/subgid
-/etc/subuid:johndoe:200000:1001
-/etc/subgid:johndoe:200000:1001
+/etc/subuid:johndoe:100000:65536
+/etc/subgid:johndoe:100000:65536
```
### Enable unprivileged `ping`
diff --git a/go.mod b/go.mod
index 6f5941603..c80f59460 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/containers/image/v5 v5.21.1
github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f
github.com/containers/psgo v1.7.2
- github.com/containers/storage v1.40.0
+ github.com/containers/storage v1.40.2
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3
diff --git a/go.sum b/go.sum
index 5219dd50a..f2737d093 100644
--- a/go.sum
+++ b/go.sum
@@ -386,8 +386,9 @@ github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZP
github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa/go.mod h1:LkkL34WRi4dI4jt9Cp+ImdZi/P5i36glSHimT5CP5zM=
github.com/containers/storage v1.39.0/go.mod h1:UAD0cKLouN4BOQRgZut/nMjrh/EnTCjSNPgp4ZuGWMs=
github.com/containers/storage v1.39.1-0.20220422100603-8996869ae40b/go.mod h1:hFiHLMgNU0r3MiUpE97hEBaEKCN8fEIuEEBXoFC9eN0=
-github.com/containers/storage v1.40.0 h1:erKY3ZVgp2F8+9jldwkJKJezrToNYs1YH/gqbPuwHes=
github.com/containers/storage v1.40.0/go.mod h1:zUyPC3CFIGR1OhY1CKkffxgw9+LuH76PGvVcFj38dgs=
+github.com/containers/storage v1.40.2 h1:GUlHaGnrs1JOEwv6YEvkQdgYXOXZdU1Angy4wgWNgF8=
+github.com/containers/storage v1.40.2/go.mod h1:zUyPC3CFIGR1OhY1CKkffxgw9+LuH76PGvVcFj38dgs=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
diff --git a/hack/podman-registry-go/registry.go b/hack/podman-registry-go/registry.go
index 095f6fb18..af8f3117c 100644
--- a/hack/podman-registry-go/registry.go
+++ b/hack/podman-registry-go/registry.go
@@ -31,10 +31,31 @@ type Registry struct {
running bool
}
+// Options allows for customizing a registry.
+type Options struct {
+ // Image - custom registry image.
+ Image string
+}
+
// Start a new registry and return it along with it's image, user, password, and port.
func Start() (*Registry, error) {
+ return StartWithOptions(nil)
+}
+
+// StartWithOptions a new registry and return it along with it's image, user, password, and port.
+func StartWithOptions(options *Options) (*Registry, error) {
+ if options == nil {
+ options = &Options{}
+ }
+
+ var args []string
+ if options.Image != "" {
+ args = append(args, "-i", options.Image)
+ }
+ args = append(args, "start")
+
// Start a registry.
- out, err := utils.ExecCmd(binary, "start")
+ out, err := utils.ExecCmd(binary, args...)
if err != nil {
return nil, errors.Wrapf(err, "error running %q: %s", binary, out)
}
diff --git a/libpod/container.go b/libpod/container.go
index 3e7ab7b0a..457b290b7 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -288,6 +288,15 @@ func (c *Container) Config() *ContainerConfig {
return nil
}
+ if c != nil {
+ networks, err := c.networks()
+ if err != nil {
+ return nil
+ }
+
+ returnConfig.Networks = networks
+ }
+
return returnConfig
}
@@ -1260,7 +1269,10 @@ func (c *Container) NetworkMode() string {
// Unlocked accessor for networks
func (c *Container) networks() (map[string]types.PerNetworkOptions, error) {
- return c.runtime.state.GetNetworks(c)
+ if c != nil && c.runtime != nil && c.runtime.state != nil { // can fail if c.networks is called from the tests
+ return c.runtime.state.GetNetworks(c)
+ }
+ return nil, nil
}
// getInterfaceByName returns a formatted interface name for a given
diff --git a/libpod/events/config.go b/libpod/events/config.go
index 35680a275..00cdca007 100644
--- a/libpod/events/config.go
+++ b/libpod/events/config.go
@@ -17,6 +17,8 @@ const (
Journald EventerType = iota
// Null is a no-op events logger. It does not read or write events.
Null EventerType = iota
+ // Memory indicates the event logger will hold events in memory
+ Memory EventerType = iota
)
// Event describes the attributes of a libpod event
@@ -55,7 +57,7 @@ type Details struct {
// EventerOptions describe options that need to be passed to create
// an eventer
type EventerOptions struct {
- // EventerType describes whether to use journald or a file
+ // EventerType describes whether to use journald, file or memory
EventerType string
// LogFilePath is the path to where the log file should reside if using
// the file logger
@@ -110,6 +112,8 @@ const (
System Type = "system"
// Volume - event is related to volumes
Volume Type = "volume"
+ // Machine - event is related to machine VM's
+ Machine Type = "machine"
// Attach ...
Attach Status = "attach"
diff --git a/libpod/events/events.go b/libpod/events/events.go
index 1745095fb..04417fd8d 100644
--- a/libpod/events/events.go
+++ b/libpod/events/events.go
@@ -20,6 +20,8 @@ func (et EventerType) String() string {
return "file"
case Journald:
return "journald"
+ case Memory:
+ return "memory"
case Null:
return "none"
default:
@@ -34,6 +36,8 @@ func IsValidEventer(eventer string) bool {
return true
case Journald.String():
return true
+ case Memory.String():
+ return true
case Null.String():
return true
default:
@@ -41,7 +45,7 @@ func IsValidEventer(eventer string) bool {
}
}
-// NewEvent creates a event struct and populates with
+// NewEvent creates an event struct and populates with
// the given status and time.
func NewEvent(status Status) Event {
return Event{
@@ -63,7 +67,7 @@ func (e *Event) ToJSONString() (string, error) {
return string(b), err
}
-// ToHumanReadable returns human readable event as a formatted string
+// ToHumanReadable returns human-readable event as a formatted string
func (e *Event) ToHumanReadable(truncate bool) string {
var humanFormat string
id := e.ID
@@ -90,7 +94,7 @@ func (e *Event) ToHumanReadable(truncate bool) string {
} else {
humanFormat = fmt.Sprintf("%s %s %s", e.Time, e.Type, e.Status)
}
- case Volume:
+ case Volume, Machine:
humanFormat = fmt.Sprintf("%s %s %s %s", e.Time, e.Type, e.Status, e.Name)
}
return humanFormat
@@ -99,19 +103,19 @@ func (e *Event) ToHumanReadable(truncate bool) string {
// NewEventFromString takes stringified json and converts
// it to an event
func newEventFromJSONString(event string) (*Event, error) {
- e := Event{}
- if err := json.Unmarshal([]byte(event), &e); err != nil {
+ e := new(Event)
+ if err := json.Unmarshal([]byte(event), e); err != nil {
return nil, err
}
- return &e, nil
+ return e, nil
}
-// ToString converts a Type to a string
+// String converts a Type to a string
func (t Type) String() string {
return string(t)
}
-// ToString converts a status to a string
+// String converts a status to a string
func (s Status) String() string {
return string(s)
}
@@ -123,6 +127,8 @@ func StringToType(name string) (Type, error) {
return Container, nil
case Image.String():
return Image, nil
+ case Machine.String():
+ return Machine, nil
case Network.String():
return Network, nil
case Pod.String():
diff --git a/libpod/events/events_linux.go b/libpod/events/events_linux.go
index 482d7d6dd..4320f2190 100644
--- a/libpod/events/events_linux.go
+++ b/libpod/events/events_linux.go
@@ -21,6 +21,8 @@ func NewEventer(options EventerOptions) (Eventer, error) {
return EventLogFile{options}, nil
case strings.ToUpper(Null.String()):
return NewNullEventer(), nil
+ case strings.ToUpper(Memory.String()):
+ return NewMemoryEventer(), nil
default:
return nil, errors.Errorf("unknown event logger type: %s", strings.ToUpper(options.EventerType))
}
diff --git a/libpod/events/memory.go b/libpod/events/memory.go
new file mode 100644
index 000000000..b3e03d86b
--- /dev/null
+++ b/libpod/events/memory.go
@@ -0,0 +1,49 @@
+package events
+
+import (
+ "context"
+)
+
+// EventMemory is the structure for event writing to a channel. It contains the eventer
+// options and the event itself. Methods for reading and writing are also defined from it.
+type EventMemory struct {
+ options EventerOptions
+ elements chan *Event
+}
+
+// Write event to memory queue
+func (e EventMemory) Write(event Event) (err error) {
+ e.elements <- &event
+ return
+}
+
+// Read event(s) from memory queue
+func (e EventMemory) Read(ctx context.Context, options ReadOptions) (err error) {
+ select {
+ case <-ctx.Done():
+ return
+ default:
+ }
+
+ select {
+ case event := <-e.elements:
+ options.EventChannel <- event
+ default:
+ }
+ return nil
+}
+
+// String returns eventer type
+func (e EventMemory) String() string {
+ return e.options.EventerType
+}
+
+// NewMemoryEventer returns configured MemoryEventer
+func NewMemoryEventer() Eventer {
+ return EventMemory{
+ options: EventerOptions{
+ EventerType: Memory.String(),
+ },
+ elements: make(chan *Event, 100),
+ }
+}
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index c6af294d5..06f8f8719 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -9,6 +9,7 @@ import (
"net"
"os"
"path/filepath"
+ "syscall"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/libpod/define"
@@ -259,7 +260,7 @@ func redirectResponseToOutputStreams(outputStream, errorStream io.Writer, writeO
}
}
}
- if er == io.EOF {
+ if errors.Is(er, io.EOF) || errors.Is(er, syscall.ECONNRESET) {
break
}
if er != nil {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index d5daa2f8a..f4cd9cf00 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -1158,7 +1158,7 @@ func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) {
return plugin.GetVolumePlugin(name, pluginPath)
}
-// GetSecretsStoreageDir returns the directory that the secrets manager should take
+// GetSecretsStorageDir returns the directory that the secrets manager should take
func (r *Runtime) GetSecretsStorageDir() string {
return filepath.Join(r.store.GraphRoot(), "secrets")
}
@@ -1206,7 +1206,17 @@ func (r *Runtime) Network() nettypes.ContainerNetwork {
return r.network
}
-// Network returns the network interface which is used by the runtime
+// GetDefaultNetworkName returns the network interface which is used by the runtime
func (r *Runtime) GetDefaultNetworkName() string {
return r.config.Network.DefaultNetwork
}
+
+// RemoteURI returns the API server URI
+func (r *Runtime) RemoteURI() string {
+ return r.config.Engine.RemoteURI
+}
+
+// SetRemoteURI records the API server URI
+func (r *Runtime) SetRemoteURI(uri string) {
+ r.config.Engine.RemoteURI = uri
+}
diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go
index ca9ada761..b71afc28c 100644
--- a/pkg/api/handlers/libpod/play.go
+++ b/pkg/api/handlers/libpod/play.go
@@ -70,6 +70,16 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
password = authConf.Password
}
+ logDriver := query.LogDriver
+ if logDriver == "" {
+ config, err := runtime.GetConfig()
+ if err != nil {
+ utils.Error(w, http.StatusInternalServerError, err)
+ return
+ }
+ query.LogDriver = config.Containers.LogDriver
+ }
+
containerEngine := abi.ContainerEngine{Libpod: runtime}
options := entities.PlayKubeOptions{
Annotations: query.Annotations,
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index a906a01f1..7f5537fb4 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -20,7 +20,6 @@ import (
"github.com/containers/podman/v4/pkg/api/server/idle"
"github.com/containers/podman/v4/pkg/api/types"
"github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/coreos/go-systemd/v22/activation"
"github.com/coreos/go-systemd/v22/daemon"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
@@ -65,25 +64,7 @@ func NewServerWithSettings(runtime *libpod.Runtime, listener net.Listener, opts
}
func newServer(runtime *libpod.Runtime, listener net.Listener, opts entities.ServiceOptions) (*APIServer, error) {
- // If listener not provided try socket activation protocol
- if listener == nil {
- if _, found := os.LookupEnv("LISTEN_PID"); !found {
- return nil, fmt.Errorf("no service listener provided and socket activation protocol is not active")
- }
-
- listeners, err := activation.Listeners()
- if err != nil {
- return nil, fmt.Errorf("cannot retrieve file descriptors from systemd: %w", err)
- }
- if len(listeners) != 1 {
- return nil, fmt.Errorf("wrong number of file descriptors for socket activation protocol (%d != 1)", len(listeners))
- }
- listener = listeners[0]
- // note that activation.Listeners() return nil when it cannot listen on the fd (i.e. udp connection)
- if listener == nil {
- return nil, fmt.Errorf("unexpected fd received from systemd: cannot listen on it")
- }
- }
+ logrus.Infof("API service listening on %q. URI: %q", listener.Addr(), runtime.RemoteURI())
if opts.CorsHeaders == "" {
logrus.Debug("CORS Headers were not set")
} else {
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 89b09bb1d..5ca678d6f 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -1548,6 +1548,12 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti
return nil, err
}
+ if len(spec.Networks) > 0 && pod.SharesNet() {
+ logrus.Warning("resetting network config, cannot specify a network other than the pod's when sharing the net namespace")
+ spec.Networks = nil
+ spec.NetworkOptions = nil
+ }
+
allNamespaces := []struct {
isShared bool
value *specgen.Namespace
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 8e96e4154..17df0e3f8 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -6,6 +6,7 @@ import (
"net/url"
"os"
"os/exec"
+ "path/filepath"
"github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/config"
@@ -27,27 +28,40 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
if err != nil {
return nil, err
}
+ info.Host.RemoteSocket = &define.RemoteSocket{Path: ic.Libpod.RemoteURI()}
- socketPath, err := util.SocketPath()
+ // `podman system connection add` invokes podman via ssh to fill in connection string. Here
+ // we are reporting the default systemd activation socket path as we cannot know if a future
+ // service may be run with another URI.
+ if ic.Libpod.RemoteURI() == "" {
+ xdg := "/run"
+ if path, err := util.GetRuntimeDir(); err != nil {
+ // Info is as good as we can guess...
+ return info, err
+ } else if path != "" {
+ xdg = path
+ }
+
+ uri := url.URL{
+ Scheme: "unix",
+ Path: filepath.Join(xdg, "podman", "podman.sock"),
+ }
+ ic.Libpod.SetRemoteURI(uri.String())
+ info.Host.RemoteSocket.Path = uri.Path
+ }
+
+ uri, err := url.Parse(ic.Libpod.RemoteURI())
if err != nil {
return nil, err
}
- rs := define.RemoteSocket{
- Path: socketPath,
- Exists: false,
- }
- // Check if the socket exists
- if fi, err := os.Stat(socketPath); err == nil {
- if fi.Mode()&os.ModeSocket != 0 {
- rs.Exists = true
- }
+ if uri.Scheme == "unix" {
+ _, err := os.Stat(uri.Path)
+ info.Host.RemoteSocket.Exists = err == nil
+ } else {
+ info.Host.RemoteSocket.Exists = true
}
- // TODO
- // it was suggested future versions of this could perform
- // a ping on the socket for greater confidence the socket is
- // actually active.
- info.Host.RemoteSocket = &rs
+
return info, err
}
diff --git a/pkg/domain/utils/utils_test.go b/pkg/domain/utils/utils_test.go
new file mode 100644
index 000000000..952a4b5be
--- /dev/null
+++ b/pkg/domain/utils/utils_test.go
@@ -0,0 +1,76 @@
+package utils
+
+import (
+ "net/url"
+ "sort"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestToLibpodFilters(t *testing.T) {
+ good := url.Values{}
+ good.Set("apple", "red")
+ good.Set("banana", "yellow")
+ good.Set("pear", "")
+ goodResult := []string{"apple=red", "banana=yellow", "pear="}
+ sort.Strings(goodResult)
+
+ empty := url.Values{}
+ type args struct {
+ f url.Values
+ }
+ tests := []struct {
+ name string
+ args args
+ wantFilters []string
+ }{
+ {
+ name: "GoodURLValue",
+ args: args{
+ f: good,
+ },
+ wantFilters: goodResult,
+ },
+ {
+ name: "Empty",
+ args: args{
+ f: empty,
+ },
+ wantFilters: nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.ElementsMatchf(t, ToLibpodFilters(tt.args.f), tt.wantFilters, "ToLibpodFilters() = %v, want %v", ToLibpodFilters(tt.args.f), tt.wantFilters)
+ })
+ }
+}
+
+func TestToURLValues(t *testing.T) {
+ good := url.Values{}
+ good.Set("apple", "red")
+ good.Set("banana", "yellow")
+ good.Set("pear", "")
+ goodResult := []string{"apple=red", "banana=yellow", "pear="}
+
+ type args struct {
+ f []string
+ }
+ tests := []struct {
+ name string
+ args args
+ wantFilters url.Values
+ }{
+ {
+ name: "Good",
+ args: args{goodResult},
+ wantFilters: good,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.EqualValuesf(t, ToURLValues(tt.args.f), tt.wantFilters, "ToURLValues() = %v, want %v", ToURLValues(tt.args.f), tt.wantFilters)
+ })
+ }
+}
diff --git a/pkg/env/env_test.go b/pkg/env/env_test.go
new file mode 100644
index 000000000..c77061ecf
--- /dev/null
+++ b/pkg/env/env_test.go
@@ -0,0 +1,162 @@
+package env
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSlice(t *testing.T) {
+ goodMap := make(map[string]string, 0)
+ goodMap["apple"] = "red"
+ goodMap["banana"] = "yellow"
+ goodMap["pear"] = ""
+ goodResult := []string{"apple=red", "banana=yellow", "pear"}
+ type args struct {
+ m map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want []string
+ }{
+ {
+ name: "Good",
+ args: args{
+ m: goodMap,
+ },
+ want: goodResult,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert.ElementsMatchf(t, Slice(tt.args.m), tt.want, "Slice() = %v, want %v", Slice(tt.args.m), tt.want)
+ })
+ }
+}
+
+func TestJoin(t *testing.T) {
+ firstMap := make(map[string]string, 0)
+ firstMap["apple"] = "red"
+ secondMap := make(map[string]string, 0)
+ secondMap["banana"] = "yellow"
+ goodResult := make(map[string]string, 0)
+ goodResult["apple"] = "red"
+ goodResult["banana"] = "yellow"
+ overrideResult := make(map[string]string, 0)
+ overrideResult["apple"] = "green"
+ overrideResult["banana"] = "yellow"
+ overrideMap := make(map[string]string, 0)
+ overrideMap["banana"] = "yellow"
+ overrideMap["apple"] = "green"
+ type args struct {
+ base map[string]string
+ override map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want map[string]string
+ }{
+ {
+ name: "GoodJoin",
+ args: args{
+ base: firstMap,
+ override: secondMap,
+ },
+ want: goodResult,
+ },
+ {
+ name: "GoodOverride",
+ args: args{
+ base: firstMap,
+ override: overrideMap,
+ },
+ want: overrideResult,
+ },
+ {
+ name: "EmptyOverride",
+ args: args{
+ base: firstMap,
+ override: nil,
+ },
+ want: firstMap,
+ },
+ {
+ name: "EmptyBase",
+ args: args{
+ base: nil,
+ override: firstMap,
+ },
+ want: firstMap,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := Join(tt.args.base, tt.args.override)
+ assert.EqualValuesf(t, got, tt.want, "Join() = %v, want %v", got, tt.want)
+ })
+ }
+}
+
+func Test_parseEnv(t *testing.T) {
+ good := make(map[string]string)
+
+ type args struct {
+ env map[string]string
+ line string
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "Good",
+ args: args{
+ env: good,
+ line: "apple=red",
+ },
+ wantErr: false,
+ },
+ {
+ name: "GoodNoValue",
+ args: args{
+ env: good,
+ line: "apple=",
+ },
+ wantErr: false,
+ },
+ {
+ name: "GoodNoKeyNoValue",
+ args: args{
+ env: good,
+ line: "=",
+ },
+ wantErr: true,
+ },
+ {
+ name: "BadNoKey",
+ args: args{
+ env: good,
+ line: "=foobar",
+ },
+ wantErr: true,
+ },
+ {
+ name: "BadOnlyDelim",
+ args: args{
+ env: good,
+ line: "=",
+ },
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if err := parseEnv(tt.args.env, tt.args.line); (err != nil) != tt.wantErr {
+ t.Errorf("parseEnv() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index 9a0ce757a..d34776714 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -52,6 +52,7 @@ type Provider interface {
List(opts ListOptions) ([]*ListResponse, error)
IsValidVMName(name string) (bool, error)
CheckExclusiveActiveVM() (bool, string, error)
+ RemoveAndCleanMachines() error
}
type RemoteConnectionType string
@@ -170,11 +171,11 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url
// GetDataDir returns the filepath where vm images should
// live for podman-machine.
func GetDataDir(vmType string) (string, error) {
- data, err := homedir.GetDataHome()
+ dataDirPrefix, err := DataDirPrefix()
if err != nil {
return "", err
}
- dataDir := filepath.Join(data, "containers", "podman", "machine", vmType)
+ dataDir := filepath.Join(dataDirPrefix, vmType)
if _, err := os.Stat(dataDir); !os.IsNotExist(err) {
return dataDir, nil
}
@@ -182,14 +183,24 @@ func GetDataDir(vmType string) (string, error) {
return dataDir, mkdirErr
}
+// DataDirPrefix returns the path prefix for all machine data files
+func DataDirPrefix() (string, error) {
+ data, err := homedir.GetDataHome()
+ if err != nil {
+ return "", err
+ }
+ dataDir := filepath.Join(data, "containers", "podman", "machine")
+ return dataDir, nil
+}
+
// GetConfigDir returns the filepath to where configuration
// files for podman-machine should live
func GetConfDir(vmType string) (string, error) {
- conf, err := homedir.GetConfigHome()
+ confDirPrefix, err := ConfDirPrefix()
if err != nil {
return "", err
}
- confDir := filepath.Join(conf, "containers", "podman", "machine", vmType)
+ confDir := filepath.Join(confDirPrefix, vmType)
if _, err := os.Stat(confDir); !os.IsNotExist(err) {
return confDir, nil
}
@@ -197,6 +208,16 @@ func GetConfDir(vmType string) (string, error) {
return confDir, mkdirErr
}
+// ConfDirPrefix returns the path prefix for all machine config files
+func ConfDirPrefix() (string, error) {
+ conf, err := homedir.GetConfigHome()
+ if err != nil {
+ return "", err
+ }
+ confDir := filepath.Join(conf, "containers", "podman", "machine")
+ return confDir, nil
+}
+
// ResourceConfig describes physical attributes of the machine
type ResourceConfig struct {
// CPUs to be assigned to the VM
diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go
index e282dd21d..b34285dd8 100644
--- a/pkg/machine/e2e/inspect_test.go
+++ b/pkg/machine/e2e/inspect_test.go
@@ -43,9 +43,11 @@ var _ = Describe("podman machine stop", func() {
Expect(foo2).To(Exit(0))
inspect := new(inspectMachine)
+ inspect = inspect.withFormat("{{.Name}}")
inspectSession, err := mb.setName("foo1").setCmd(inspect).run()
Expect(err).To(BeNil())
Expect(inspectSession).To(Exit(0))
+ Expect(inspectSession.Bytes()).To(ContainSubstring("foo1"))
type fakeInfos struct {
Status string
@@ -56,13 +58,13 @@ var _ = Describe("podman machine stop", func() {
Expect(err).ToNot(HaveOccurred())
Expect(len(infos)).To(Equal(2))
- //rm := new(rmMachine)
- //// Must manually clean up due to multiple names
- //for _, name := range []string{"foo1", "foo2"} {
+ // rm := new(rmMachine)
+ // // Must manually clean up due to multiple names
+ // for _, name := range []string{"foo1", "foo2"} {
// mb.setName(name).setCmd(rm.withForce()).run()
// mb.names = []string{}
- //}
- //mb.names = []string{}
+ // }
+ // mb.names = []string{}
})
})
diff --git a/pkg/machine/e2e/machine_test.go b/pkg/machine/e2e/machine_test.go
index 2b3b60b2b..657014b05 100644
--- a/pkg/machine/e2e/machine_test.go
+++ b/pkg/machine/e2e/machine_test.go
@@ -23,14 +23,20 @@ func TestMain(m *testing.M) {
const (
defaultStream string = "podman-testing"
- tmpDir string = "/var/tmp"
)
var (
+ tmpDir = "/var/tmp"
fqImageName string
suiteImageName string
)
+func init() {
+ if value, ok := os.LookupEnv("TMPDIR"); ok {
+ tmpDir = value
+ }
+}
+
// TestLibpod ginkgo master function
func TestMachine(t *testing.T) {
RegisterFailHandler(Fail)
@@ -70,7 +76,8 @@ var _ = SynchronizedAfterSuite(func() {},
})
func setup() (string, *machineTestBuilder) {
- homeDir, err := ioutil.TempDir("/var/tmp", "podman_test")
+ // Set TMPDIR if this needs a new directory
+ homeDir, err := ioutil.TempDir("", "podman_test")
if err != nil {
Fail(fmt.Sprintf("failed to create home directory: %q", err))
}
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 91e15c2af..6e36b0886 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -525,10 +525,11 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
time.Sleep(wait)
wait++
}
- defer qemuSocketConn.Close()
if err != nil {
return err
}
+ defer qemuSocketConn.Close()
+
fd, err := qemuSocketConn.(*net.UnixConn).File()
if err != nil {
return err
@@ -1543,3 +1544,79 @@ func (v *MachineVM) editCmdLine(flag string, value string) {
v.CmdLine = append(v.CmdLine, []string{flag, value}...)
}
}
+
+// RemoveAndCleanMachines removes all machine and cleans up any other files associatied with podman machine
+func (p *Provider) RemoveAndCleanMachines() error {
+ var (
+ vm machine.VM
+ listResponse []*machine.ListResponse
+ opts machine.ListOptions
+ destroyOptions machine.RemoveOptions
+ )
+ destroyOptions.Force = true
+ var prevErr error
+
+ listResponse, err := p.List(opts)
+ if err != nil {
+ return err
+ }
+
+ for _, mach := range listResponse {
+ vm, err = p.LoadVMByName(mach.Name)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ _, remove, err := vm.Remove(mach.Name, destroyOptions)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ } else {
+ if err := remove(); err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ }
+ }
+
+ // Clean leftover files in data dir
+ dataDir, err := machine.DataDirPrefix()
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ } else {
+ err := os.RemoveAll(dataDir)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ }
+
+ // Clean leftover files in conf dir
+ confDir, err := machine.ConfDirPrefix()
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ } else {
+ err := os.RemoveAll(confDir)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ }
+ return prevErr
+}
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index bc2ac7864..57fb36fc9 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -1442,3 +1442,79 @@ func (v *MachineVM) getResources() (resources machine.ResourceConfig) {
resources.DiskSize = getDiskSize(v)
return
}
+
+// RemoveAndCleanMachines removes all machine and cleans up any other files associatied with podman machine
+func (p *Provider) RemoveAndCleanMachines() error {
+ var (
+ vm machine.VM
+ listResponse []*machine.ListResponse
+ opts machine.ListOptions
+ destroyOptions machine.RemoveOptions
+ )
+ destroyOptions.Force = true
+ var prevErr error
+
+ listResponse, err := p.List(opts)
+ if err != nil {
+ return err
+ }
+
+ for _, mach := range listResponse {
+ vm, err = p.LoadVMByName(mach.Name)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ _, remove, err := vm.Remove(mach.Name, destroyOptions)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ } else {
+ if err := remove(); err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ }
+ }
+
+ // Clean leftover files in data dir
+ dataDir, err := machine.DataDirPrefix()
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ } else {
+ err := os.RemoveAll(dataDir)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ }
+
+ // Clean leftover files in conf dir
+ confDir, err := machine.ConfDirPrefix()
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ } else {
+ err := os.RemoveAll(confDir)
+ if err != nil {
+ if prevErr != nil {
+ logrus.Error(prevErr)
+ }
+ prevErr = err
+ }
+ }
+ return prevErr
+}
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 831c1d7b9..63caaa77c 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -501,6 +501,8 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID s
_, mounts := c.SortUserVolumes(c.Spec())
specg.Mounts = mounts
specg.HostDeviceList = conf.DeviceHostSrc
+ specg.Networks = conf.Networks
+
mapSecurityConfig(conf, specg)
if c.IsInfra() { // if we are creating this spec for a pod's infra ctr, map the compatible options
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 8b9ed8ffe..19a2b702c 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -175,13 +175,15 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
return nil, nil, nil, errors.New("the given container could not be retrieved")
}
conf := c.Config()
- out, err := json.Marshal(conf.Spec.Linux)
- if err != nil {
- return nil, nil, nil, err
- }
- err = json.Unmarshal(out, runtimeSpec.Linux)
- if err != nil {
- return nil, nil, nil, err
+ if conf != nil && conf.Spec != nil && conf.Spec.Linux != nil {
+ out, err := json.Marshal(conf.Spec.Linux)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ err = json.Unmarshal(out, runtimeSpec.Linux)
+ if err != nil {
+ return nil, nil, nil, err
+ }
}
if s.ResourceLimits != nil {
switch {
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 9842a0f73..a0bf8b50d 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -731,29 +731,6 @@ func IDtoolsToRuntimeSpec(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxI
return convertedIDMap
}
-var socketPath string
-
-func SetSocketPath(path string) {
- socketPath = path
-}
-
-func SocketPath() (string, error) {
- if socketPath != "" {
- return socketPath, nil
- }
- xdg, err := GetRuntimeDir()
- if err != nil {
- return "", err
- }
- if len(xdg) == 0 {
- // If no xdg is returned, assume root socket
- xdg = "/run"
- }
-
- // Glue the socket path together
- return filepath.Join(xdg, "podman", "podman.sock"), nil
-}
-
func LookupUser(name string) (*user.User, error) {
// Assume UID look up first, if it fails lookup by username
if u, err := user.LookupId(name); err == nil {
diff --git a/test/e2e/benchmarks_test.go b/test/e2e/benchmarks_test.go
index 746dec0a6..ef4d51893 100644
--- a/test/e2e/benchmarks_test.go
+++ b/test/e2e/benchmarks_test.go
@@ -36,11 +36,14 @@ type benchmark struct {
options newBenchmarkOptions
}
+var benchmarkRegistry *podmanRegistry.Registry
+
// Allows for customizing the benchnmark in an easy to extend way.
type newBenchmarkOptions struct {
// Sets the benchmark's init function.
init func()
- // Run a local registry for this benchmark.
+ // Run a local registry for this benchmark. Use `getPortUserPass()` in
+ // the benchmark to get the port, user and password.
needsRegistry bool
}
@@ -53,6 +56,15 @@ func newBenchmark(name string, main func(), options *newBenchmarkOptions) {
allBenchmarks = append(allBenchmarks, bm)
}
+// getPortUserPass returns the port, user and password of the currently running
+// registry.
+func getPortUserPass() (string, string, string) {
+ if benchmarkRegistry == nil {
+ return "", "", ""
+ }
+ return benchmarkRegistry.Port, benchmarkRegistry.User, benchmarkRegistry.Password
+}
+
var _ = Describe("Podman Benchmark Suite", func() {
var (
timedir string
@@ -75,6 +87,15 @@ var _ = Describe("Podman Benchmark Suite", func() {
cleanup := func() {
podmanTest.Cleanup()
os.RemoveAll(timedir)
+
+ // Stop the local registry.
+ if benchmarkRegistry != nil {
+ if err := benchmarkRegistry.Stop(); err != nil {
+ logrus.Errorf("Error stopping registry: %v", err)
+ os.Exit(1)
+ }
+ benchmarkRegistry = nil
+ }
}
totalMemoryInKb := func() (total uint64) {
@@ -109,22 +130,23 @@ var _ = Describe("Podman Benchmark Suite", func() {
// All benchmarks are executed here to have *one* table listing all data.
Measure("Podman Benchmark Suite", func(b Benchmarker) {
+
+ registryOptions := &podmanRegistry.Options{
+ Image: "docker-archive:" + imageTarPath(registry),
+ }
+
for i := range allBenchmarks {
setup()
bm := allBenchmarks[i]
// Start a local registry if requested.
- var registry *podmanRegistry.Registry
if bm.options.needsRegistry {
- reg, err := podmanRegistry.Start()
+ reg, err := podmanRegistry.StartWithOptions(registryOptions)
if err != nil {
logrus.Errorf("Error starting registry: %v", err)
os.Exit(1)
}
- registry = reg
- os.Setenv(podmanRegistry.UserKey, reg.User)
- os.Setenv(podmanRegistry.PassKey, reg.Password)
- os.Setenv(podmanRegistry.PortKey, reg.Port)
+ benchmarkRegistry = reg
}
if bm.options.init != nil {
@@ -139,17 +161,6 @@ var _ = Describe("Podman Benchmark Suite", func() {
mem := totalMemoryInKb()
b.RecordValueWithPrecision("[MEM] "+bm.name, float64(mem), "KB", 1)
- // Stop the local registry.
- if bm.options.needsRegistry {
- os.Unsetenv(podmanRegistry.UserKey)
- os.Unsetenv(podmanRegistry.PassKey)
- os.Unsetenv(podmanRegistry.PortKey)
- if err := registry.Stop(); err != nil {
- logrus.Errorf("Error stopping registry: %v", err)
- os.Exit(1)
- }
- }
-
cleanup()
}
}, numBenchmarkSamples)
@@ -166,11 +177,27 @@ var _ = Describe("Podman Benchmark Suite", func() {
Expect(session).Should(Exit(0))
}, nil)
+ newBenchmark("podman push", func() {
+ port, user, pass := getPortUserPass()
+ session := podmanTest.Podman([]string{"push", "--tls-verify=false", "--creds", user + ":" + pass, UBI_INIT, "localhost:" + port + "/repo/image:tag"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ }, &newBenchmarkOptions{needsRegistry: true})
+
newBenchmark("podman pull", func() {
- session := podmanTest.Podman([]string{"pull", "quay.io/libpod/cirros"})
+ port, user, pass := getPortUserPass()
+ session := podmanTest.Podman([]string{"pull", "--tls-verify=false", "--creds", user + ":" + pass, "localhost:" + port + "/repo/image:tag"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- }, nil)
+ }, &newBenchmarkOptions{
+ needsRegistry: true,
+ init: func() {
+ port, user, pass := getPortUserPass()
+ session := podmanTest.Podman([]string{"push", "--tls-verify=false", "--creds", user + ":" + pass, UBI_INIT, "localhost:" + port + "/repo/image:tag"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ },
+ })
newBenchmark("podman load [docker]", func() {
session := podmanTest.Podman([]string{"load", "-i", "./testdata/docker-two-images.tar.xz"})
@@ -197,9 +224,7 @@ var _ = Describe("Podman Benchmark Suite", func() {
}, nil)
newBenchmark("podman login + logout", func() {
- user := os.Getenv(podmanRegistry.UserKey)
- pass := os.Getenv(podmanRegistry.PassKey)
- port := os.Getenv(podmanRegistry.PortKey)
+ port, user, pass := getPortUserPass()
session := podmanTest.Podman([]string{"login", "-u", user, "-p", pass, "--tls-verify=false", "localhost:" + port})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index a61ef8640..28991af7f 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -6,6 +6,7 @@ import (
"io/ioutil"
"math/rand"
"net"
+ "net/url"
"os"
"os/exec"
"path/filepath"
@@ -1063,3 +1064,36 @@ func digShort(container, lookupName string, matchNames []string, p *PodmanTestIn
}
Fail("dns is not responding")
}
+
+// WaitForFile to be created in defaultWaitTimeout seconds, returns false if file not created
+func WaitForFile(path string) (err error) {
+ until := time.Now().Add(time.Duration(defaultWaitTimeout) * time.Second)
+ for i := 1; time.Now().Before(until); i++ {
+ _, err = os.Stat(path)
+ switch {
+ case err == nil:
+ return nil
+ case errors.Is(err, os.ErrNotExist):
+ time.Sleep(time.Duration(i) * time.Second)
+ default:
+ return err
+ }
+ }
+ return err
+}
+
+// WaitForService blocks, waiting for some service listening on given host:port
+func WaitForService(address url.URL) {
+ // Wait for podman to be ready
+ var conn net.Conn
+ var err error
+ for i := 1; i <= 5; i++ {
+ conn, err = net.Dial("tcp", address.Host)
+ if err != nil {
+ // Podman not available yet...
+ time.Sleep(time.Duration(i) * time.Second)
+ }
+ }
+ Expect(err).ShouldNot(HaveOccurred())
+ conn.Close()
+}
diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go
index da9b511e0..94ccd6ffe 100644
--- a/test/e2e/container_clone_test.go
+++ b/test/e2e/container_clone_test.go
@@ -266,4 +266,30 @@ var _ = Describe("Podman container clone", func() {
Expect(clone).ToNot(Exit(0))
})
+
+ It("podman container clone network passing", func() {
+ networkCreate := podmanTest.Podman([]string{"network", "create", "testing123"})
+ networkCreate.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork("testing123")
+ Expect(networkCreate).To(Exit(0))
+ run := podmanTest.Podman([]string{"run", "--network", "bridge", "-dt", ALPINE})
+ run.WaitWithDefaultTimeout()
+ Expect(run).To(Exit(0))
+
+ connect := podmanTest.Podman([]string{"network", "connect", "testing123", run.OutputToString()})
+ connect.WaitWithDefaultTimeout()
+ Expect(connect).To(Exit(0))
+
+ clone := podmanTest.Podman([]string{"container", "clone", run.OutputToString()})
+ clone.WaitWithDefaultTimeout()
+ Expect(clone).To(Exit(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", clone.OutputToString()})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).To(Exit(0))
+ Expect(inspect.InspectContainerToJSON()[0].NetworkSettings.Networks).To(HaveLen(2))
+ _, ok := inspect.InspectContainerToJSON()[0].NetworkSettings.Networks["testing123"]
+ Expect(ok).To(BeTrue())
+
+ })
})
diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go
index f989a9d29..2c2c82cb6 100644
--- a/test/e2e/info_test.go
+++ b/test/e2e/info_test.go
@@ -119,33 +119,31 @@ var _ = Describe("Podman Info", func() {
Expect(string(out)).To(Equal(expect))
})
- It("podman info check RemoteSocket", func() {
+ It("check RemoteSocket ", func() {
session := podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Path}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(MatchRegexp("/run/.*podman.*sock"))
- if IsRemote() {
- session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"})
- session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("true"))
+ session = podmanTest.Podman([]string{"info", "--format", "{{.Host.ServiceIsRemote}}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ if podmanTest.RemoteTest {
+ Expect(session.OutputToString()).To(Equal("true"))
+ } else {
+ Expect(session.OutputToString()).To(Equal("false"))
}
- })
- It("verify ServiceIsRemote", func() {
- session := podmanTest.Podman([]string{"info", "--format", "{{.Host.ServiceIsRemote}}"})
+ session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"})
session.WaitWithDefaultTimeout()
- Expect(session).To(Exit(0))
-
- if podmanTest.RemoteTest {
+ Expect(session).Should(Exit(0))
+ if IsRemote() {
Expect(session.OutputToString()).To(ContainSubstring("true"))
- } else {
- Expect(session.OutputToString()).To(ContainSubstring("false"))
}
+
})
- It("Podman info must contain cgroupControllers with ReleventControllers", func() {
+ It("Podman info must contain cgroupControllers with RelevantControllers", func() {
SkipIfRootless("Hard to tell which controllers are going to be enabled for rootless")
SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users")
session := podmanTest.Podman([]string{"info", "--format", "{{.Host.CgroupControllers}}"})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 0e91db04c..45414ec04 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -3180,8 +3180,10 @@ invalid kube kind
Expect(ls).Should(Exit(0))
Expect(ls.OutputToStringArray()).To(HaveLen(1))
- containerLen := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{len .Containers}}'"})
-
+ containerLen := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "{{len .Containers}}"})
+ containerLen.WaitWithDefaultTimeout()
+ Expect(containerLen).Should(Exit(0))
+ Expect(containerLen.OutputToString()).To(Equal("2"))
ctr01Name := "ctr01"
ctr02Name := "ctr02"
@@ -3199,7 +3201,7 @@ invalid kube kind
replace.WaitWithDefaultTimeout()
Expect(replace).Should(Exit(0))
- newContainerLen := podmanTest.Podman([]string{"pod", "inspect", newPod.Name, "--format", "'{{len .Containers}}'"})
+ newContainerLen := podmanTest.Podman([]string{"pod", "inspect", newPod.Name, "--format", "{{len .Containers}}"})
newContainerLen.WaitWithDefaultTimeout()
Expect(newContainerLen).Should(Exit(0))
Expect(newContainerLen.OutputToString()).NotTo(Equal(containerLen.OutputToString()))
diff --git a/test/e2e/system_connection_test.go b/test/e2e/system_connection_test.go
index 95920136e..2228c23b2 100644
--- a/test/e2e/system_connection_test.go
+++ b/test/e2e/system_connection_test.go
@@ -247,7 +247,7 @@ var _ = Describe("podman system connection", func() {
// podman-remote commands will be executed by ginkgo directly.
SkipIfContainerized("sshd is not available when running in a container")
SkipIfRemote("connection heuristic requires both podman and podman-remote binaries")
- SkipIfNotRootless("FIXME: setup ssh keys when root")
+ SkipIfNotRootless(fmt.Sprintf("FIXME: setup ssh keys when root. uid(%d) euid(%d)", os.Getuid(), os.Geteuid()))
SkipIfSystemdNotRunning("cannot test connection heuristic if systemd is not running")
SkipIfNotActive("sshd", "cannot test connection heuristic if sshd is not running")
})
diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go
index ec94bb819..28f2e25ca 100644
--- a/test/e2e/system_reset_test.go
+++ b/test/e2e/system_reset_test.go
@@ -89,5 +89,12 @@ var _ = Describe("podman system reset", func() {
Expect(session).Should(Exit(0))
// default network should exists
Expect(session.OutputToStringArray()).To(HaveLen(1))
+
+ // TODO: machine tests currently don't run outside of the machine test pkg
+ // no machines are created here to cleanup
+ session = podmanTest.Podman([]string{"machine", "list", "-q"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToStringArray()).To(BeEmpty())
})
})
diff --git a/test/e2e/system_service_test.go b/test/e2e/system_service_test.go
index 2bc7756d6..398290426 100644
--- a/test/e2e/system_service_test.go
+++ b/test/e2e/system_service_test.go
@@ -20,7 +20,7 @@ var _ = Describe("podman system service", func() {
// The timeout used to for the service to respond. As shown in #12167,
// this may take some time on machines under high load.
- var timeout = 20
+ var timeout = 30
BeforeEach(func() {
tempdir, err := CreateTempDirInTempDir()
@@ -122,22 +122,6 @@ var _ = Describe("podman system service", func() {
})
})
-// WaitForService blocks, waiting for some service listening on given host:port
-func WaitForService(address url.URL) {
- // Wait for podman to be ready
- var conn net.Conn
- var err error
- for i := 1; i <= 5; i++ {
- conn, err = net.Dial("tcp", address.Host)
- if err != nil {
- // Podman not available yet...
- time.Sleep(time.Duration(i) * time.Second)
- }
- }
- Expect(err).ShouldNot(HaveOccurred())
- conn.Close()
-}
-
// randomPort leans on the go net library to find an available port...
func randomPort() string {
port, err := utils.GetRandomPort()
diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats
index 7b70f60f4..e9e9a01ea 100644
--- a/test/system/272-system-connection.bats
+++ b/test/system/272-system-connection.bats
@@ -99,10 +99,9 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true" \
_SERVICE_PID=$!
wait_for_port localhost $_SERVICE_PORT
- # FIXME: #12023, RemoteSocket is always /run/something
-# run_podman info --format '{{.Host.RemoteSocket.Path}}'
-# is "$output" "tcp:localhost:$_SERVICE_PORT" \
-# "podman info works, and talks to the correct server"
+ _run_podman_remote info --format '{{.Host.RemoteSocket.Path}}'
+ is "$output" "tcp:localhost:$_SERVICE_PORT" \
+ "podman info works, and talks to the correct server"
_run_podman_remote info --format '{{.Store.GraphRoot}}'
is "$output" "${PODMAN_TMPDIR}/root" \
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index b0624cbf2..7988b26a4 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -278,3 +278,20 @@ status: {}
run_podman 125 play kube - < $PODMAN_TMPDIR/test.yaml
assert "$output" =~ "invalid annotation \"test\"=\"$RANDOMSTRING\"" "Expected to fail with annotation length greater than 63"
}
+
+@test "podman play kube - default log driver" {
+ TESTDIR=$PODMAN_TMPDIR/testdir
+ mkdir -p $TESTDIR
+ echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
+ # Get the default log driver
+ run_podman info --format "{{.Host.LogDriver}}"
+ default_driver=$output
+
+ # Make sure that the default log driver is used
+ run_podman play kube $PODMAN_TMPDIR/test.yaml
+ run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
+ is "$output" "$default_driver" "play kube uses default log driver"
+
+ run_podman stop -a -t 0
+ run_podman pod rm -t 0 -f test_pod
+}
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 32b7211cb..148dabb45 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.40.0
+1.40.2
diff --git a/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go b/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go
index 34fdc5790..2af33a6fc 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go
@@ -133,7 +133,7 @@ func createUsernsProcess(uidMaps []idtools.IDMap, gidMaps []idtools.IDMap) (int,
_ = unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(unix.SIGKILL), 0, 0, 0)
// just wait for the SIGKILL
for {
- syscall.Syscall6(uintptr(unix.SYS_PAUSE), 0, 0, 0, 0, 0, 0)
+ syscall.Pause()
}
}
cleanupFunc := func() {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index c2c17a6b9..6cb4088d6 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -235,7 +235,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.40.0
+# github.com/containers/storage v1.40.2
## explicit
github.com/containers/storage
github.com/containers/storage/drivers