diff --git a/pkg/machine/e2e/api_test.go b/pkg/machine/e2e/api_test.go new file mode 100644 index 0000000000..6e081d7975 --- /dev/null +++ b/pkg/machine/e2e/api_test.go @@ -0,0 +1,96 @@ +package e2e_test + +import ( + "context" + "os/exec" + "path/filepath" + "runtime" + + "github.com/containers/podman/v5/pkg/machine" + "github.com/docker/docker/client" + jsoniter "github.com/json-iterator/go" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +const ( + NamedPipeProto = "npipe://" +) + +var _ = Describe("run podman API test calls", func() { + + It("client connect to machine socket", func() { + if runtime.GOOS == "windows" { + Skip("Go docker client doesn't support unix socket on Windows") + } + name := randomString() + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run() + Expect(err).ToNot(HaveOccurred()) + Expect(session).To(Exit(0)) + + inspectJSON := new(inspectMachine) + inspectSession, err := mb.setName(name).setCmd(inspectJSON).run() + Expect(err).ToNot(HaveOccurred()) + Expect(inspectSession).To(Exit(0)) + + var inspectInfo []machine.InspectInfo + err = jsoniter.Unmarshal(inspectSession.Bytes(), &inspectInfo) + Expect(err).ToNot(HaveOccurred()) + sockPath := inspectInfo[0].ConnectionInfo.PodmanSocket.GetPath() + + cli, err := client.NewClientWithOpts(client.WithHost("unix://" + sockPath)) + Expect(err).ToNot(HaveOccurred()) + _, err = cli.Ping(context.Background()) + Expect(err).ToNot(HaveOccurred()) + }) + + It("client connect to machine named pipe", func() { + if runtime.GOOS != "windows" { + Skip("test is only supported on Windows") + } + name := randomString() + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run() + Expect(err).ToNot(HaveOccurred()) + Expect(session).To(Exit(0)) + + inspectJSON := new(inspectMachine) + inspectSession, err := mb.setName(name).setCmd(inspectJSON).run() + Expect(err).ToNot(HaveOccurred()) + Expect(inspectSession).To(Exit(0)) + + var inspectInfo []machine.InspectInfo + err = jsoniter.Unmarshal(inspectSession.Bytes(), &inspectInfo) + Expect(err).ToNot(HaveOccurred()) + pipePath := inspectInfo[0].ConnectionInfo.PodmanPipe.GetPath() + + cli, err := client.NewClientWithOpts(client.WithHost(NamedPipeProto + filepath.ToSlash(pipePath))) + Expect(err).ToNot(HaveOccurred()) + _, err = cli.Ping(context.Background()) + Expect(err).ToNot(HaveOccurred()) + }) + + It("curl connect to machine socket", func() { + name := randomString() + i := new(initMachine) + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run() + Expect(err).ToNot(HaveOccurred()) + Expect(session).To(Exit(0)) + + inspectJSON := new(inspectMachine) + inspectSession, err := mb.setName(name).setCmd(inspectJSON).run() + Expect(err).ToNot(HaveOccurred()) + Expect(inspectSession).To(Exit(0)) + + var inspectInfo []machine.InspectInfo + err = jsoniter.Unmarshal(inspectSession.Bytes(), &inspectInfo) + Expect(err).ToNot(HaveOccurred()) + sockPath := inspectInfo[0].ConnectionInfo.PodmanSocket.GetPath() + + cmd := exec.Command("curl", "--unix-socket", sockPath, "http://d/v5.0.0/libpod/info") + err = cmd.Run() + Expect(err).ToNot(HaveOccurred()) + }) +}) diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go index 1c6224d793..c23fd0ae01 100644 --- a/pkg/machine/e2e/inspect_test.go +++ b/pkg/machine/e2e/inspect_test.go @@ -80,9 +80,6 @@ var _ = Describe("podman inspect stop", func() { }) It("inspect shows a unique socket name per machine", func() { - skipIfVmtype(define.WSLVirt, "test is only relevant for Unix based providers") - skipIfVmtype(define.HyperVVirt, "test is only relevant for Unix based machines") - var socks []string for c := 0; c < 2; c++ { name := randomString() diff --git a/pkg/machine/machine_windows.go b/pkg/machine/machine_windows.go index d6c23e64f8..174980fc29 100644 --- a/pkg/machine/machine_windows.go +++ b/pkg/machine/machine_windows.go @@ -18,6 +18,7 @@ import ( winio "github.com/Microsoft/go-winio" "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/env" + "github.com/containers/podman/v5/pkg/machine/sockets" "github.com/containers/storage/pkg/fileutils" "github.com/sirupsen/logrus" ) @@ -45,6 +46,7 @@ type WinProxyOpts struct { RemoteUsername string Rootful bool VMType define.VMType + Socket *define.VMFile } func GetProcessState(pid int) (active bool, exitCode int) { @@ -160,6 +162,12 @@ func launchWinProxy(opts WinProxyOpts) (bool, string, error) { waitPipe = GlobalNamedPipe } + hostURL, err := sockets.ToUnixURL(opts.Socket) + if err != nil { + return false, "", err + } + args = append(args, hostURL.String(), dest, opts.IdentityPath) + cmd := exec.Command(command, args...) logrus.Debugf("winssh command: %s %v", command, args) if err := cmd.Start(); err != nil { diff --git a/pkg/machine/shim/networking_windows.go b/pkg/machine/shim/networking_windows.go index 5428a8db4d..f108919cf5 100644 --- a/pkg/machine/shim/networking_windows.go +++ b/pkg/machine/shim/networking_windows.go @@ -6,6 +6,7 @@ import ( "github.com/containers/podman/v5/pkg/machine" "github.com/containers/podman/v5/pkg/machine/define" "github.com/containers/podman/v5/pkg/machine/env" + sc "github.com/containers/podman/v5/pkg/machine/sockets" "github.com/containers/podman/v5/pkg/machine/vmconfigs" ) @@ -22,5 +23,16 @@ func setupMachineSockets(mc *vmconfigs.MachineConfig, dirs *define.MachineDirs) state = machine.DockerGlobal } - return sockets, sockets[len(sockets)-1], state, nil + hostSocket, err := mc.APISocket() + if err != nil { + return nil, "", 0, err + } + + hostURL, err := sc.ToUnixURL(hostSocket) + if err != nil { + return nil, "", 0, err + } + sockets = append(sockets, hostURL.String()) + + return sockets, sockets[len(sockets)-2], state, nil } diff --git a/pkg/machine/vmconfigs/machine.go b/pkg/machine/vmconfigs/machine.go index f47fce845f..8627a0b19e 100644 --- a/pkg/machine/vmconfigs/machine.go +++ b/pkg/machine/vmconfigs/machine.go @@ -15,7 +15,6 @@ import ( "github.com/containers/podman/v5/pkg/errorhandling" "github.com/containers/podman/v5/pkg/machine/connection" "github.com/containers/podman/v5/pkg/machine/define" - "github.com/containers/podman/v5/pkg/machine/env" "github.com/containers/podman/v5/pkg/machine/lock" "github.com/containers/podman/v5/pkg/machine/ports" "github.com/containers/storage/pkg/fileutils" @@ -331,19 +330,8 @@ func (mc *MachineConfig) IsFirstBoot() (bool, error) { } func (mc *MachineConfig) ConnectionInfo(vmtype define.VMType) (*define.VMFile, *define.VMFile, error) { - var ( - socket *define.VMFile - pipe *define.VMFile - ) - - if vmtype == define.HyperVVirt || vmtype == define.WSLVirt { - pipeName := env.WithPodmanPrefix(mc.Name) - pipe = &define.VMFile{Path: `\\.\pipe\` + pipeName} - return nil, pipe, nil - } - socket, err := mc.APISocket() - return socket, nil, err + return socket, getPipe(mc.Name), err } // LoadMachineByName returns a machine config based on the vm name and provider diff --git a/pkg/machine/vmconfigs/machine_unix.go b/pkg/machine/vmconfigs/machine_unix.go new file mode 100644 index 0000000000..1961aeb712 --- /dev/null +++ b/pkg/machine/vmconfigs/machine_unix.go @@ -0,0 +1,11 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd + +package vmconfigs + +import ( + "github.com/containers/podman/v5/pkg/machine/define" +) + +func getPipe(name string) *define.VMFile { + return nil +} diff --git a/pkg/machine/vmconfigs/machine_windows.go b/pkg/machine/vmconfigs/machine_windows.go new file mode 100644 index 0000000000..1092b840ee --- /dev/null +++ b/pkg/machine/vmconfigs/machine_windows.go @@ -0,0 +1,11 @@ +package vmconfigs + +import ( + "github.com/containers/podman/v5/pkg/machine/define" + "github.com/containers/podman/v5/pkg/machine/env" +) + +func getPipe(name string) *define.VMFile { + pipeName := env.WithPodmanPrefix(name) + return &define.VMFile{Path: `\\.\pipe\` + pipeName} +} diff --git a/pkg/machine/wsl/stubber.go b/pkg/machine/wsl/stubber.go index 352202095a..073b0b04bf 100644 --- a/pkg/machine/wsl/stubber.go +++ b/pkg/machine/wsl/stubber.go @@ -186,6 +186,10 @@ func (w WSLStubber) RequireExclusiveActive() bool { } func (w WSLStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo bool) error { + socket, err := mc.APISocket() + if err != nil { + return err + } winProxyOpts := machine.WinProxyOpts{ Name: mc.Name, IdentityPath: mc.SSH.IdentityPath, @@ -193,6 +197,7 @@ func (w WSLStubber) PostStartNetworking(mc *vmconfigs.MachineConfig, noInfo bool RemoteUsername: mc.SSH.RemoteUsername, Rootful: mc.HostUser.Rootful, VMType: w.VMType(), + Socket: socket, } machine.LaunchWinProxy(winProxyOpts, noInfo)