mirror of
https://github.com/containers/podman.git
synced 2025-10-19 12:12:36 +08:00
V2 Fix support for tcp://[::]<port> connections
* Fix support for socket activation, on remote and service $ systemd-socket-activate -l 8083 --fdname=podman bin/podman system service --log-level=debug --time=30 $ bin/podman-remote --remote=tcp://[::]:8083 image ls Or, use the podman.{socket,service} unit files $ bin/podman-remote --remote=unix:///run/podman/podman.sock image ls Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
@ -57,7 +57,7 @@ func service(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logrus.Infof("using API endpoint: \"%s\"", apiURI)
|
logrus.Infof("using API endpoint: '%s'", apiURI)
|
||||||
|
|
||||||
opts := entities.ServiceOptions{
|
opts := entities.ServiceOptions{
|
||||||
URI: apiURI,
|
URI: apiURI,
|
||||||
@ -75,7 +75,6 @@ func service(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resolveApiURI(_url []string) (string, error) {
|
func resolveApiURI(_url []string) (string, error) {
|
||||||
|
|
||||||
// When determining _*THE*_ listening endpoint --
|
// When determining _*THE*_ listening endpoint --
|
||||||
// 1) User input wins always
|
// 1) User input wins always
|
||||||
// 2) systemd socket activation
|
// 2) systemd socket activation
|
||||||
@ -83,14 +82,15 @@ func resolveApiURI(_url []string) (string, error) {
|
|||||||
// 4) if varlink -- adapter.DefaultVarlinkAddress
|
// 4) if varlink -- adapter.DefaultVarlinkAddress
|
||||||
// 5) lastly adapter.DefaultAPIAddress
|
// 5) lastly adapter.DefaultAPIAddress
|
||||||
|
|
||||||
if _url == nil {
|
if len(_url) == 0 {
|
||||||
if v, found := os.LookupEnv("PODMAN_SOCKET"); found {
|
if v, found := os.LookupEnv("PODMAN_SOCKET"); found {
|
||||||
|
logrus.Debugf("PODMAN_SOCKET='%s' used to determine API endpoint", v)
|
||||||
_url = []string{v}
|
_url = []string{v}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case len(_url) > 0:
|
case len(_url) > 0 && _url[0] != "":
|
||||||
return _url[0], nil
|
return _url[0], nil
|
||||||
case systemd.SocketActivated():
|
case systemd.SocketActivated():
|
||||||
logrus.Info("using systemd socket activation to determine API endpoint")
|
logrus.Info("using systemd socket activation to determine API endpoint")
|
||||||
|
@ -51,7 +51,7 @@ func NewServerWithSettings(runtime *libpod.Runtime, duration time.Duration, list
|
|||||||
func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (*APIServer, error) {
|
func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (*APIServer, error) {
|
||||||
// If listener not provided try socket activation protocol
|
// If listener not provided try socket activation protocol
|
||||||
if listener == nil {
|
if listener == nil {
|
||||||
if _, found := os.LookupEnv("LISTEN_FDS"); !found {
|
if _, found := os.LookupEnv("LISTEN_PID"); !found {
|
||||||
return nil, errors.Errorf("Cannot create API Server, no listener provided and socket activation protocol is not active.")
|
return nil, errors.Errorf("Cannot create API Server, no listener provided and socket activation protocol is not active.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
methods = []string{"<N/A>"}
|
methods = []string{"<N/A>"}
|
||||||
}
|
}
|
||||||
logrus.Debugf("Methods: %s Path: %s", strings.Join(methods, ", "), path)
|
logrus.Debugf("Methods: %6s Path: %s", strings.Join(methods, ", "), path)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -179,6 +179,7 @@ func (s *APIServer) Shutdown() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gracefully shutdown server, duration of wait same as idle window
|
// Gracefully shutdown server, duration of wait same as idle window
|
||||||
|
// TODO: Should we really wait the idle window for shutdown?
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), s.idleTracker.Duration)
|
ctx, cancel := context.WithTimeout(context.Background(), s.idleTracker.Duration)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -126,7 +126,7 @@ func tcpClient(_url *url.URL) (*http.Client, error) {
|
|||||||
return &http.Client{
|
return &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||||
return net.Dial("tcp", _url.Path)
|
return net.Dial("tcp", _url.Host)
|
||||||
},
|
},
|
||||||
DisableCompression: true,
|
DisableCompression: true,
|
||||||
},
|
},
|
||||||
|
@ -35,7 +35,7 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
|
|||||||
|
|
||||||
func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceOptions) error {
|
func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceOptions) error {
|
||||||
var (
|
var (
|
||||||
listener net.Listener
|
listener *net.Listener
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,13 +45,14 @@ func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceO
|
|||||||
return errors.Errorf("%s is an invalid socket destination", opts.URI)
|
return errors.Errorf("%s is an invalid socket destination", opts.URI)
|
||||||
}
|
}
|
||||||
address := strings.Join(fields[1:], ":")
|
address := strings.Join(fields[1:], ":")
|
||||||
listener, err = net.Listen(fields[0], address)
|
l, err := net.Listen(fields[0], address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "unable to create socket %s", opts.URI)
|
return errors.Wrapf(err, "unable to create socket %s", opts.URI)
|
||||||
}
|
}
|
||||||
|
listener = &l
|
||||||
}
|
}
|
||||||
|
|
||||||
server, err := api.NewServerWithSettings(ic.Libpod, opts.Timeout, &listener)
|
server, err := api.NewServerWithSettings(ic.Libpod, opts.Timeout, listener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -62,7 +63,9 @@ func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceO
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
err = server.Serve()
|
err = server.Serve()
|
||||||
_ = listener.Close()
|
if listener != nil {
|
||||||
|
_ = (*listener).Close()
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,38 +3,33 @@ package systemd
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SocketActivated determine if podman is running under the socket activation protocol
|
// SocketActivated determine if podman is running under the socket activation protocol
|
||||||
|
// Criteria is based on the expectations of "github.com/coreos/go-systemd/v22/activation"
|
||||||
func SocketActivated() bool {
|
func SocketActivated() bool {
|
||||||
pid, pid_found := os.LookupEnv("LISTEN_PID")
|
pid, found := os.LookupEnv("LISTEN_PID")
|
||||||
fds, fds_found := os.LookupEnv("LISTEN_FDS")
|
if !found {
|
||||||
fdnames, fdnames_found := os.LookupEnv("LISTEN_FDNAMES")
|
|
||||||
|
|
||||||
if !(pid_found && fds_found && fdnames_found) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := strconv.Atoi(pid)
|
p, err := strconv.Atoi(pid)
|
||||||
if err != nil || p != os.Getpid() {
|
if err != nil || p != os.Getpid() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fds, found := os.LookupEnv("LISTEN_FDS")
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
nfds, err := strconv.Atoi(fds)
|
nfds, err := strconv.Atoi(fds)
|
||||||
if err != nil || nfds < 1 {
|
if err != nil || nfds == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// First available file descriptor is always 3.
|
// "github.com/coreos/go-systemd/v22/activation" will use and validate this variable's
|
||||||
if nfds > 1 {
|
// value. We're just providing a fast fail
|
||||||
names := strings.Split(fdnames, ":")
|
if _, found = os.LookupEnv("LISTEN_FDNAMES"); !found {
|
||||||
for _, n := range names {
|
return false
|
||||||
if strings.Contains(n, "podman") {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user