Merge pull request #23409 from arixmkii/unix-api-socket

Implement publishing API UNIX socket on Windows platforms
This commit is contained in:
openshift-merge-bot[bot] 2024-10-11 10:23:14 +00:00 committed by GitHub
commit f311979ec0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 145 additions and 17 deletions

View File

@ -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())
})
})

View File

@ -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()

View File

@ -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 {

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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}
}

View File

@ -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)