Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report correct RemoteURI #12895

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions cmd/podman/system/service_abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
Expand All @@ -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.
Expand Down Expand Up @@ -70,6 +89,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
Expand All @@ -81,15 +101,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
}
Expand Down
14 changes: 12 additions & 2 deletions libpod/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,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")
}
Expand Down Expand Up @@ -1188,7 +1188,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
}
18 changes: 1 addition & 17 deletions pkg/api/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -65,28 +64,13 @@ 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]
}
logrus.Infof("API service listening on %q. URI: %q", (*listener).Addr(), runtime.RemoteURI())
if opts.CorsHeaders == "" {
logrus.Debug("CORS Headers were not set")
} else {
logrus.Debugf("CORS Headers were set to %q", opts.CorsHeaders)
}

logrus.Infof("API service listening on %q", (*listener).Addr())
router := mux.NewRouter().UseEncodedPath()
tracker := idle.NewTracker(opts.Timeout)

Expand Down
43 changes: 28 additions & 15 deletions pkg/domain/infra/abi/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,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()}

// `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
}

socketPath, err := util.SocketPath()
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
}

Expand Down
23 changes: 0 additions & 23 deletions pkg/util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,29 +701,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 {
Expand Down
23 changes: 18 additions & 5 deletions test/e2e/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,30 @@ var _ = Describe("Podman Info", func() {
Expect(string(out)).To(Equal(expect))
})

It("podman info check RemoteSocket", func() {
It("check RemoteSocket w/ no server", func() {
SkipIfRemote("Verify RemoteSocket when no API server running")
session := podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Path}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(MatchRegexp("/run/.*podman.*sock"))

session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Equal("false"))
})

It("check RemoteSocket w/ remote server", func() {
if IsRemote() {
session := podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Path}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Equal(podmanTest.RemoteSocket))

session = podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Exists}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("true"))
Expect(session.OutputToString()).To(Equal("true"))
}
})

Expand All @@ -139,13 +152,13 @@ var _ = Describe("Podman Info", func() {
Expect(session).To(Exit(0))

if podmanTest.RemoteTest {
Expect(session.OutputToString()).To(ContainSubstring("true"))
Expect(session.OutputToString()).To(Equal("true"))
} else {
Expect(session.OutputToString()).To(ContainSubstring("false"))
Expect(session.OutputToString()).To(Equal("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}}"})
Expand Down
3 changes: 3 additions & 0 deletions test/e2e/play_kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3149,6 +3149,9 @@ invalid kube kind
Expect(ls.OutputToStringArray()).To(HaveLen(1))

containerLen := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{len .Containers}}'"})
containerLen.WaitWithDefaultTimeout()
Expect(ls).Should(Exit(0))
Expect(ls.OutputToStringArray()).Should(BeNumerically(">", 1))
Copy link
Member

@edsantiago edsantiago Mar 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing len() no wait this looks like copy-paste; it needs more significant cleanup (s/ls/containerLen/, OutputToString() instead of Array).


ctr01Name := "ctr01"
ctr02Name := "ctr02"
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/system_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
})
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/system_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
7 changes: 3 additions & 4 deletions test/system/272-system-connection.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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 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" \
Expand Down