mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
feat(api): Add npipe support (#2018)
This commit is contained in:
parent
0368c4e937
commit
4129550d44
17 changed files with 133 additions and 43 deletions
|
@ -2,8 +2,8 @@ package endpoints
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/portainer/portainer"
|
||||
"github.com/portainer/portainer/crypto"
|
||||
|
@ -109,7 +109,7 @@ func (payload *endpointCreatePayload) Validate(r *http.Request) error {
|
|||
}
|
||||
payload.AzureAuthenticationKey = azureAuthenticationKey
|
||||
default:
|
||||
url, err := request.RetrieveMultiPartFormValue(r, "URL", false)
|
||||
url, err := request.RetrieveMultiPartFormValue(r, "URL", true)
|
||||
if err != nil {
|
||||
return portainer.Error("Invalid endpoint URL")
|
||||
}
|
||||
|
@ -192,7 +192,12 @@ func (handler *Handler) createAzureEndpoint(payload *endpointCreatePayload) (*po
|
|||
func (handler *Handler) createUnsecuredEndpoint(payload *endpointCreatePayload) (*portainer.Endpoint, *httperror.HandlerError) {
|
||||
endpointType := portainer.DockerEnvironment
|
||||
|
||||
if !strings.HasPrefix(payload.URL, "unix://") {
|
||||
if payload.URL == "" {
|
||||
payload.URL = "unix:///var/run/docker.sock"
|
||||
if runtime.GOOS == "windows" {
|
||||
payload.URL = "npipe:////./pipe/docker_engine"
|
||||
}
|
||||
} else {
|
||||
agentOnDockerEnvironment, err := client.ExecutePingOperation(payload.URL, nil)
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{http.StatusInternalServerError, "Unable to ping Docker environment", err}
|
||||
|
|
|
@ -164,22 +164,32 @@ func createDial(endpoint *portainer.Endpoint) (net.Conn, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var host string
|
||||
if url.Scheme == "tcp" {
|
||||
host = url.Host
|
||||
} else if url.Scheme == "unix" {
|
||||
host := url.Host
|
||||
|
||||
if url.Scheme == "unix" || url.Scheme == "npipe" {
|
||||
host = url.Path
|
||||
}
|
||||
|
||||
var (
|
||||
dial net.Conn
|
||||
dialErr error
|
||||
)
|
||||
|
||||
if endpoint.TLSConfig.TLS {
|
||||
tlsConfig, err := crypto.CreateTLSConfigurationFromDisk(endpoint.TLSConfig.TLSCACertPath, endpoint.TLSConfig.TLSCertPath, endpoint.TLSConfig.TLSKeyPath, endpoint.TLSConfig.TLSSkipVerify)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tls.Dial(url.Scheme, host, tlsConfig)
|
||||
dial, dialErr = tls.Dial(url.Scheme, host, tlsConfig)
|
||||
} else {
|
||||
if url.Scheme == "npipe" {
|
||||
dial, dialErr = createWinDial(host)
|
||||
} else {
|
||||
dial, dialErr = net.Dial(url.Scheme, host)
|
||||
}
|
||||
}
|
||||
|
||||
return net.Dial(url.Scheme, host)
|
||||
return dial, dialErr
|
||||
}
|
||||
|
||||
func createExecStartRequest(execID string) (*http.Request, error) {
|
||||
|
|
11
api/http/handler/websocket/websocket_exec_linux.go
Normal file
11
api/http/handler/websocket/websocket_exec_linux.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
// +build linux
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func createWinDial(host string) (net.Conn, error) {
|
||||
return nil, nil
|
||||
}
|
13
api/http/handler/websocket/websocket_exec_windows.go
Normal file
13
api/http/handler/websocket/websocket_exec_windows.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
// +build windows
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
func createWinDial(host string) (net.Conn, error) {
|
||||
return winio.DialPipe(host, nil)
|
||||
}
|
|
@ -58,21 +58,6 @@ func (factory *proxyFactory) newDockerHTTPProxy(u *url.URL, enableSignature bool
|
|||
return factory.createDockerReverseProxy(u, enableSignature)
|
||||
}
|
||||
|
||||
func (factory *proxyFactory) newDockerSocketProxy(path string) http.Handler {
|
||||
proxy := &socketProxy{}
|
||||
transport := &proxyTransport{
|
||||
enableSignature: false,
|
||||
ResourceControlService: factory.ResourceControlService,
|
||||
TeamMembershipService: factory.TeamMembershipService,
|
||||
SettingsService: factory.SettingsService,
|
||||
RegistryService: factory.RegistryService,
|
||||
DockerHubService: factory.DockerHubService,
|
||||
dockerTransport: newSocketTransport(path),
|
||||
}
|
||||
proxy.Transport = transport
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (factory *proxyFactory) createDockerReverseProxy(u *url.URL, enableSignature bool) *httputil.ReverseProxy {
|
||||
proxy := newSingleHostReverseProxyWithHostHeader(u)
|
||||
transport := &proxyTransport{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package proxy
|
||||
|
||||
// unixSocketHandler represents a handler to proxy HTTP requests via a unix:// socket
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
|
@ -9,11 +8,11 @@ import (
|
|||
httperror "github.com/portainer/portainer/http/error"
|
||||
)
|
||||
|
||||
type socketProxy struct {
|
||||
type localProxy struct {
|
||||
Transport *proxyTransport
|
||||
}
|
||||
|
||||
func (proxy *socketProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
func (proxy *localProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Force URL/domain to http/unixsocket to be able to
|
||||
// use http.Transport RoundTrip to do the requests via the socket
|
||||
r.URL.Scheme = "http"
|
22
api/http/proxy/local_linux.go
Normal file
22
api/http/proxy/local_linux.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
// +build linux
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (factory *proxyFactory) newLocalProxy(path string) http.Handler {
|
||||
proxy := &localProxy{}
|
||||
transport := &proxyTransport{
|
||||
enableSignature: false,
|
||||
ResourceControlService: factory.ResourceControlService,
|
||||
TeamMembershipService: factory.TeamMembershipService,
|
||||
SettingsService: factory.SettingsService,
|
||||
RegistryService: factory.RegistryService,
|
||||
DockerHubService: factory.DockerHubService,
|
||||
dockerTransport: newSocketTransport(path),
|
||||
}
|
||||
proxy.Transport = transport
|
||||
return proxy
|
||||
}
|
33
api/http/proxy/local_windows.go
Normal file
33
api/http/proxy/local_windows.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
// +build windows
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
func (factory *proxyFactory) newLocalProxy(path string) http.Handler {
|
||||
proxy := &localProxy{}
|
||||
transport := &proxyTransport{
|
||||
enableSignature: false,
|
||||
ResourceControlService: factory.ResourceControlService,
|
||||
TeamMembershipService: factory.TeamMembershipService,
|
||||
SettingsService: factory.SettingsService,
|
||||
RegistryService: factory.RegistryService,
|
||||
DockerHubService: factory.DockerHubService,
|
||||
dockerTransport: newNamedPipeTransport(path),
|
||||
}
|
||||
proxy.Transport = transport
|
||||
return proxy
|
||||
}
|
||||
|
||||
func newNamedPipeTransport(namedPipePath string) *http.Transport {
|
||||
return &http.Transport{
|
||||
Dial: func(proto, addr string) (conn net.Conn, err error) {
|
||||
return winio.DialPipe(namedPipePath, nil)
|
||||
},
|
||||
}
|
||||
}
|
|
@ -51,8 +51,7 @@ func (manager *Manager) createDockerProxy(endpointURL *url.URL, tlsConfig *porta
|
|||
}
|
||||
return manager.proxyFactory.newDockerHTTPProxy(endpointURL, false), nil
|
||||
}
|
||||
// Assume unix:// scheme
|
||||
return manager.proxyFactory.newDockerSocketProxy(endpointURL.Path), nil
|
||||
return manager.proxyFactory.newLocalProxy(endpointURL.Path), nil
|
||||
}
|
||||
|
||||
func (manager *Manager) createProxy(endpoint *portainer.Endpoint) (http.Handler, error) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue