diff options
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` @@ -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 @@ -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 |