mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-08-29 03:37:54 +00:00
Use `Default()` instead of re-loading containers.conf. Also rework how the containers.conf objects are handled for parsing the CLI. Previously, we were conflating "loading the defaults" with "storing values from the CLI" with "libpod may further change fields" which ultimately led to various bugs and test failues. To address the issue, separate the defaults from the values from the CLI and properly name the fields to make the semantics less ambiguous. [NO NEW TESTS NEEDED] as it's not a functional change. Fixes: containers/common/issues/1200 Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
149 lines
4.1 KiB
Go
149 lines
4.1 KiB
Go
//go:build linux && !remote
|
|
// +build linux,!remote
|
|
|
|
package system
|
|
|
|
import (
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/containers/common/pkg/completion"
|
|
"github.com/containers/podman/v4/cmd/podman/common"
|
|
"github.com/containers/podman/v4/cmd/podman/registry"
|
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
|
"github.com/containers/podman/v4/pkg/rootless"
|
|
"github.com/containers/podman/v4/pkg/systemd"
|
|
"github.com/containers/podman/v4/pkg/util"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/pflag"
|
|
)
|
|
|
|
var (
|
|
srvDescription = `Run an API service
|
|
|
|
Enable a listening service for API access to Podman commands.
|
|
`
|
|
|
|
srvCmd = &cobra.Command{
|
|
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
|
|
Use: "service [options] [URI]",
|
|
Args: cobra.MaximumNArgs(1),
|
|
Short: "Run API service",
|
|
Long: srvDescription,
|
|
RunE: service,
|
|
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
|
Example: `podman system service --time=0 unix:///tmp/podman.sock
|
|
podman system service --time=0 tcp://localhost:8888`,
|
|
}
|
|
|
|
srvArgs = struct {
|
|
CorsHeaders string
|
|
PProfAddr string
|
|
Timeout uint
|
|
}{}
|
|
)
|
|
|
|
func init() {
|
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
|
Command: srvCmd,
|
|
Parent: systemCmd,
|
|
})
|
|
|
|
flags := srvCmd.Flags()
|
|
cfg := registry.PodmanConfig()
|
|
|
|
timeFlagName := "time"
|
|
flags.UintVarP(&srvArgs.Timeout, timeFlagName, "t", cfg.ContainersConfDefaultsRO.Engine.ServiceTimeout,
|
|
"Time until the service session expires in seconds. Use 0 to disable the timeout")
|
|
_ = srvCmd.RegisterFlagCompletionFunc(timeFlagName, completion.AutocompleteNone)
|
|
flags.SetNormalizeFunc(aliasTimeoutFlag)
|
|
|
|
flags.StringVarP(&srvArgs.CorsHeaders, "cors", "", "", "Set CORS Headers")
|
|
_ = srvCmd.RegisterFlagCompletionFunc("cors", completion.AutocompleteNone)
|
|
|
|
flags.StringVarP(&srvArgs.PProfAddr, "pprof-address", "", "",
|
|
"Binding network address for pprof profile endpoints, default: do not expose endpoints")
|
|
_ = flags.MarkHidden("pprof-address")
|
|
}
|
|
|
|
func aliasTimeoutFlag(_ *pflag.FlagSet, name string) pflag.NormalizedName {
|
|
if name == "timeout" {
|
|
name = "time"
|
|
}
|
|
return pflag.NormalizedName(name)
|
|
}
|
|
|
|
func service(cmd *cobra.Command, args []string) error {
|
|
apiURI, err := resolveAPIURI(args)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Clean up any old existing unix domain socket
|
|
if len(apiURI) > 0 {
|
|
uri, err := url.Parse(apiURI)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// socket activation uses a unix:// socket in the shipped unit files but apiURI is coded as "" at this layer.
|
|
if uri.Scheme == "unix" && !registry.IsRemote() {
|
|
if err := syscall.Unlink(uri.Path); err != nil && !os.IsNotExist(err) {
|
|
return err
|
|
}
|
|
mask := syscall.Umask(0177)
|
|
defer syscall.Umask(mask)
|
|
}
|
|
}
|
|
|
|
return restService(cmd.Flags(), registry.PodmanConfig(), entities.ServiceOptions{
|
|
CorsHeaders: srvArgs.CorsHeaders,
|
|
PProfAddr: srvArgs.PProfAddr,
|
|
Timeout: time.Duration(srvArgs.Timeout) * time.Second,
|
|
URI: apiURI,
|
|
})
|
|
}
|
|
|
|
func resolveAPIURI(uri []string) (string, error) {
|
|
// When determining _*THE*_ listening endpoint --
|
|
// 1) User input wins always
|
|
// 2) systemd socket activation
|
|
// 3) rootless honors XDG_RUNTIME_DIR
|
|
// 4) lastly adapter.DefaultAPIAddress
|
|
|
|
if len(uri) == 0 {
|
|
if v, found := os.LookupEnv("PODMAN_SOCKET"); found {
|
|
logrus.Debugf("PODMAN_SOCKET=%q used to determine API endpoint", v)
|
|
uri = []string{v}
|
|
}
|
|
}
|
|
|
|
switch {
|
|
case len(uri) > 0 && uri[0] != "":
|
|
return uri[0], nil
|
|
case systemd.SocketActivated():
|
|
logrus.Info("Using systemd socket activation to determine API endpoint")
|
|
return "", nil
|
|
case rootless.IsRootless():
|
|
xdg, err := util.GetRuntimeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
socketName := "podman.sock"
|
|
socketPath := filepath.Join(xdg, "podman", socketName)
|
|
if err := os.MkdirAll(filepath.Dir(socketPath), 0700); err != nil {
|
|
return "", err
|
|
}
|
|
return "unix:" + socketPath, nil
|
|
default:
|
|
if err := os.MkdirAll(filepath.Dir(registry.DefaultRootAPIPath), 0700); err != nil {
|
|
return "", err
|
|
}
|
|
return registry.DefaultRootAPIAddress, nil
|
|
}
|
|
}
|