1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
//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.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
}
}
|