summaryrefslogtreecommitdiff
path: root/cmd/podmanV2
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podmanV2')
-rw-r--r--cmd/podmanV2/Makefile12
-rw-r--r--cmd/podmanV2/containers/cleanup.go75
-rw-r--r--cmd/podmanV2/containers/logs.go108
-rw-r--r--cmd/podmanV2/containers/ps.go146
-rw-r--r--cmd/podmanV2/containers/run.go38
-rw-r--r--cmd/podmanV2/containers/wait.go5
-rw-r--r--cmd/podmanV2/images/list.go14
-rw-r--r--cmd/podmanV2/registry/registry.go6
-rw-r--r--cmd/podmanV2/system/service.go124
-rw-r--r--cmd/podmanV2/system/system.go8
-rw-r--r--cmd/podmanV2/system/varlink.go56
11 files changed, 430 insertions, 162 deletions
diff --git a/cmd/podmanV2/Makefile b/cmd/podmanV2/Makefile
index b847a9385..01d551212 100644
--- a/cmd/podmanV2/Makefile
+++ b/cmd/podmanV2/Makefile
@@ -1,2 +1,10 @@
-all:
- CGO_ENABLED=1 GO111MODULE=off go build -tags 'ABISupport systemd seccomp'
+all: podman podman-remote
+
+podman:
+ CGO_ENABLED=1 GO111MODULE=off go build -tags 'ABISupport systemd varlink seccomp'
+
+podman-remote:
+ CGO_ENABLED=1 GO111MODULE=off go build -tags '!ABISupport systemd seccomp' -o podmanV2-remote
+
+clean:
+ rm podmanV2 podmanV2-remote
diff --git a/cmd/podmanV2/containers/cleanup.go b/cmd/podmanV2/containers/cleanup.go
new file mode 100644
index 000000000..3f45db160
--- /dev/null
+++ b/cmd/podmanV2/containers/cleanup.go
@@ -0,0 +1,75 @@
+package containers
+
+import (
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ cleanupDescription = `
+ podman container cleanup
+
+ Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits.
+`
+ cleanupCommand = &cobra.Command{
+ Use: "cleanup [flags] CONTAINER [CONTAINER...]",
+ Short: "Cleanup network and mountpoints of one or more containers",
+ Long: cleanupDescription,
+ RunE: cleanup,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman container cleanup --latest
+ podman container cleanup ctrID1 ctrID2 ctrID3
+ podman container cleanup --all`,
+ }
+)
+
+var (
+ cleanupOptions entities.ContainerCleanupOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Parent: containerCmd,
+ Command: cleanupCommand,
+ })
+ flags := cleanupCommand.Flags()
+ flags.BoolVarP(&cleanupOptions.All, "all", "a", false, "Cleans up all containers")
+ flags.BoolVarP(&cleanupOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVar(&cleanupOptions.Remove, "rm", false, "After cleanup, remove the container entirely")
+ flags.BoolVar(&cleanupOptions.RemoveImage, "rmi", false, "After cleanup, remove the image entirely")
+
+}
+
+func cleanup(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ )
+ responses, err := registry.ContainerEngine().ContainerCleanup(registry.GetContext(), args, cleanupOptions)
+ if err != nil {
+ return err
+ }
+ for _, r := range responses {
+ if r.CleanErr == nil && r.RmErr == nil && r.RmiErr == nil {
+ fmt.Println(r.Id)
+ continue
+ }
+ if r.RmErr != nil {
+ errs = append(errs, r.RmErr)
+ }
+ if r.RmiErr != nil {
+ errs = append(errs, r.RmiErr)
+ }
+ if r.CleanErr != nil {
+ errs = append(errs, r.CleanErr)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podmanV2/containers/logs.go b/cmd/podmanV2/containers/logs.go
new file mode 100644
index 000000000..d1a179495
--- /dev/null
+++ b/cmd/podmanV2/containers/logs.go
@@ -0,0 +1,108 @@
+package containers
+
+import (
+ "os"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+// logsOptionsWrapper wraps entities.LogsOptions and prevents leaking
+// CLI-only fields into the API types.
+type logsOptionsWrapper struct {
+ entities.ContainerLogsOptions
+
+ SinceRaw string
+}
+
+var (
+ logsOptions logsOptionsWrapper
+ logsDescription = `Retrieves logs for one or more containers.
+
+ This does not guarantee execution order when combined with podman run (i.e., your run may not have generated any logs at the time you execute podman logs).
+`
+ logsCommand = &cobra.Command{
+ Use: "logs [flags] CONTAINER [CONTAINER...]",
+ Short: "Fetch the logs of one or more container",
+ Long: logsDescription,
+ RunE: logs,
+ PreRunE: preRunE,
+ Example: `podman logs ctrID
+ podman logs --names ctrID1 ctrID2
+ podman logs --tail 2 mywebserver
+ podman logs --follow=true --since 10m ctrID
+ podman logs mywebserver mydbserver`,
+ }
+
+ containerLogsCommand = &cobra.Command{
+ Use: logsCommand.Use,
+ Short: logsCommand.Short,
+ Long: logsCommand.Long,
+ PreRunE: logsCommand.PreRunE,
+ RunE: logsCommand.RunE,
+ Example: `podman container logs ctrID
+ podman container logs --names ctrID1 ctrID2
+ podman container logs --tail 2 mywebserver
+ podman container logs --follow=true --since 10m ctrID
+ podman container logs mywebserver mydbserver`,
+ }
+)
+
+func init() {
+ // logs
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: logsCommand,
+ })
+
+ logsCommand.SetHelpTemplate(registry.HelpTemplate())
+ logsCommand.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := logsCommand.Flags()
+ logsFlags(flags)
+
+ // container logs
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: containerLogsCommand,
+ Parent: containerCmd,
+ })
+
+ containerLogsFlags := containerLogsCommand.Flags()
+ logsFlags(containerLogsFlags)
+}
+
+func logsFlags(flags *pflag.FlagSet) {
+ flags.BoolVar(&logsOptions.Details, "details", false, "Show extra details provided to the logs")
+ flags.BoolVarP(&logsOptions.Follow, "follow", "f", false, "Follow log output. The default is false")
+ flags.BoolVarP(&logsOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.StringVar(&logsOptions.SinceRaw, "since", "", "Show logs since TIMESTAMP")
+ flags.Int64Var(&logsOptions.Tail, "tail", -1, "Output the specified number of LINES at the end of the logs. Defaults to -1, which prints all lines")
+ flags.BoolVarP(&logsOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log")
+ flags.BoolVarP(&logsOptions.Names, "names", "n", false, "Output the container name in the log")
+ flags.SetInterspersed(false)
+ _ = flags.MarkHidden("details")
+}
+
+func logs(cmd *cobra.Command, args []string) error {
+ if len(args) > 0 && logsOptions.Latest {
+ return errors.New("no containers can be specified when using 'latest'")
+ }
+ if !logsOptions.Latest && len(args) < 1 {
+ return errors.New("specify at least one container name or ID to log")
+ }
+ if logsOptions.SinceRaw != "" {
+ // parse time, error out if something is wrong
+ since, err := util.ParseInputTime(logsOptions.SinceRaw)
+ if err != nil {
+ return errors.Wrapf(err, "error parsing --since %q", logsOptions.SinceRaw)
+ }
+ logsOptions.Since = since
+ }
+ logsOptions.Writer = os.Stdout
+ return registry.ContainerEngine().ContainerLogs(registry.GetContext(), args, logsOptions.ContainerLogsOptions)
+}
diff --git a/cmd/podmanV2/containers/ps.go b/cmd/podmanV2/containers/ps.go
index 2397eb8c0..8c1d44842 100644
--- a/cmd/podmanV2/containers/ps.go
+++ b/cmd/podmanV2/containers/ps.go
@@ -4,8 +4,6 @@ import (
"encoding/json"
"fmt"
"os"
- "sort"
- "strconv"
"strings"
"text/tabwriter"
"text/template"
@@ -13,12 +11,8 @@ import (
tm "github.com/buger/goterm"
"github.com/containers/buildah/pkg/formats"
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/cmd/podmanV2/report"
"github.com/containers/libpod/pkg/domain/entities"
- "github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -44,9 +38,6 @@ var (
filters []string
noTrunc bool
defaultHeaders string = "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES"
-
-// CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
-
)
func init() {
@@ -143,7 +134,6 @@ func getResponses() ([]entities.ListContainer, error) {
}
func ps(cmd *cobra.Command, args []string) error {
- // []string to map[string][]string
for _, f := range filters {
split := strings.SplitN(f, "=", 2)
if len(split) == 1 {
@@ -178,8 +168,7 @@ func ps(cmd *cobra.Command, args []string) error {
if !listOpts.Quiet && !cmd.Flag("format").Changed {
format = headers + format
}
- funcs := report.AppendFuncMap(psFuncMap)
- tmpl, err := template.New("listPods").Funcs(funcs).Parse(format)
+ tmpl, err := template.New("listContainers").Parse(format)
if err != nil {
return err
}
@@ -217,7 +206,7 @@ func createPsOut() (string, string) {
var row string
if listOpts.Namespace {
headers := "CONTAINER ID\tNAMES\tPID\tCGROUPNS\tIPC\tMNT\tNET\tPIDN\tUSERNS\tUTS\n"
- row := "{{.ID}}\t{{names .Names}}\t{{.Pid}}\t{{.Namespaces.Cgroup}}\t{{.Namespaces.IPC}}\t{{.Namespaces.MNT}}\t{{.Namespaces.NET}}\t{{.Namespaces.PIDNS}}\t{{.Namespaces.User}}\t{{.Namespaces.UTS}}\n"
+ row := "{{.ID}}\t{{.Names}}\t{{.Pid}}\t{{.Namespaces.Cgroup}}\t{{.Namespaces.IPC}}\t{{.Namespaces.MNT}}\t{{.Namespaces.NET}}\t{{.Namespaces.PIDNS}}\t{{.Namespaces.User}}\t{{.Namespaces.UTS}}\n"
return headers, row
}
headers := defaultHeaders
@@ -226,7 +215,7 @@ func createPsOut() (string, string) {
} else {
row += "{{slice .ID 0 12}}"
}
- row += "\t{{.Image}}\t{{cmd .Command}}\t{{humanDuration .Created}}\t{{state .}}\t{{ports .Ports}}\t{{names .Names}}"
+ row += "\t{{.Image}}\t{{.Command}}\t{{.CreatedHuman}}\t{{.State}}\t{{.Ports}}\t{{.Names}}"
if listOpts.Pod {
headers += "\tPOD ID\tPODNAME"
@@ -240,7 +229,7 @@ func createPsOut() (string, string) {
if listOpts.Size {
headers += "\tSIZE"
- row += "\t{{consize .Size}}"
+ row += "\t{{.Size}}"
}
if !strings.HasSuffix(headers, "\n") {
headers += "\n"
@@ -250,130 +239,3 @@ func createPsOut() (string, string) {
}
return headers, row
}
-
-var psFuncMap = template.FuncMap{
- "cmd": func(conCommand []string) string {
- return strings.Join(conCommand, " ")
- },
- "state": func(con entities.ListContainer) string {
- var state string
- switch con.State {
- case "running":
- t := units.HumanDuration(time.Since(time.Unix(con.StartedAt, 0)))
- state = "Up " + t + " ago"
- case "configured":
- state = "Created"
- case "exited":
- t := units.HumanDuration(time.Since(time.Unix(con.ExitedAt, 0)))
- state = fmt.Sprintf("Exited (%d) %s ago", con.ExitCode, t)
- default:
- state = con.State
- }
- return state
- },
- "ports": func(ports []ocicni.PortMapping) string {
- if len(ports) == 0 {
- return ""
- }
- return portsToString(ports)
- },
- "names": func(names []string) string {
- return names[0]
- },
- "consize": func(csize shared.ContainerSize) string {
- virt := units.HumanSizeWithPrecision(float64(csize.RootFsSize), 3)
- s := units.HumanSizeWithPrecision(float64(csize.RwSize), 3)
- return fmt.Sprintf("%s (virtual %s)", s, virt)
- },
-}
-
-// portsToString converts the ports used to a string of the from "port1, port2"
-// and also groups a continuous list of ports into a readable format.
-func portsToString(ports []ocicni.PortMapping) string {
- type portGroup struct {
- first int32
- last int32
- }
- var portDisplay []string
- if len(ports) == 0 {
- return ""
- }
- //Sort the ports, so grouping continuous ports become easy.
- sort.Slice(ports, func(i, j int) bool {
- return comparePorts(ports[i], ports[j])
- })
-
- // portGroupMap is used for grouping continuous ports.
- portGroupMap := make(map[string]*portGroup)
- var groupKeyList []string
-
- for _, v := range ports {
-
- hostIP := v.HostIP
- if hostIP == "" {
- hostIP = "0.0.0.0"
- }
- // If hostPort and containerPort are not same, consider as individual port.
- if v.ContainerPort != v.HostPort {
- portDisplay = append(portDisplay, fmt.Sprintf("%s:%d->%d/%s", hostIP, v.HostPort, v.ContainerPort, v.Protocol))
- continue
- }
-
- portMapKey := fmt.Sprintf("%s/%s", hostIP, v.Protocol)
-
- portgroup, ok := portGroupMap[portMapKey]
- if !ok {
- portGroupMap[portMapKey] = &portGroup{first: v.ContainerPort, last: v.ContainerPort}
- // This list is required to traverse portGroupMap.
- groupKeyList = append(groupKeyList, portMapKey)
- continue
- }
-
- if portgroup.last == (v.ContainerPort - 1) {
- portgroup.last = v.ContainerPort
- continue
- }
- }
- // For each portMapKey, format group list and appned to output string.
- for _, portKey := range groupKeyList {
- group := portGroupMap[portKey]
- portDisplay = append(portDisplay, formatGroup(portKey, group.first, group.last))
- }
- return strings.Join(portDisplay, ", ")
-}
-
-func comparePorts(i, j ocicni.PortMapping) bool {
- if i.ContainerPort != j.ContainerPort {
- return i.ContainerPort < j.ContainerPort
- }
-
- if i.HostIP != j.HostIP {
- return i.HostIP < j.HostIP
- }
-
- if i.HostPort != j.HostPort {
- return i.HostPort < j.HostPort
- }
-
- return i.Protocol < j.Protocol
-}
-
-// formatGroup returns the group as <IP:startPort:lastPort->startPort:lastPort/Proto>
-// e.g 0.0.0.0:1000-1006->1000-1006/tcp.
-func formatGroup(key string, start, last int32) string {
- parts := strings.Split(key, "/")
- groupType := parts[0]
- var ip string
- if len(parts) > 1 {
- ip = parts[0]
- groupType = parts[1]
- }
- group := strconv.Itoa(int(start))
- if start != last {
- group = fmt.Sprintf("%s-%d", group, last)
- }
- if ip != "" {
- group = fmt.Sprintf("%s:%s->%s", ip, group, group)
- }
- return fmt.Sprintf("%s/%s", group, groupType)
-}
diff --git a/cmd/podmanV2/containers/run.go b/cmd/podmanV2/containers/run.go
index 5c0069afc..0bf0f90f8 100644
--- a/cmd/podmanV2/containers/run.go
+++ b/cmd/podmanV2/containers/run.go
@@ -5,15 +5,14 @@ import (
"os"
"strings"
- "github.com/sirupsen/logrus"
-
- "github.com/containers/libpod/pkg/domain/entities"
-
+ "github.com/containers/common/pkg/config"
"github.com/containers/libpod/cmd/podmanV2/common"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -75,6 +74,30 @@ func run(cmd *cobra.Command, args []string) error {
return err
}
+ ie, err := registry.NewImageEngine(cmd, args)
+ if err != nil {
+ return err
+ }
+ br, err := ie.Exists(registry.GetContext(), args[0])
+ if err != nil {
+ return err
+ }
+ pullPolicy, err := config.ValidatePullPolicy(cliVals.Pull)
+ if err != nil {
+ return err
+ }
+ if !br.Value || pullPolicy == config.PullImageAlways {
+ if pullPolicy == config.PullImageNever {
+ return errors.New("unable to find a name and tag match for busybox in repotags: no such image")
+ }
+ _, pullErr := ie.Pull(registry.GetContext(), args[0], entities.ImagePullOptions{
+ Authfile: cliVals.Authfile,
+ Quiet: cliVals.Quiet,
+ })
+ if pullErr != nil {
+ return pullErr
+ }
+ }
// If -i is not set, clear stdin
if !cliVals.Interactive {
runOpts.InputStream = nil
@@ -109,15 +132,18 @@ func run(cmd *cobra.Command, args []string) error {
}
runOpts.Spec = s
report, err := registry.ContainerEngine().ContainerRun(registry.GetContext(), runOpts)
+ // report.ExitCode is set by ContainerRun even it it returns an error
+ if report != nil {
+ registry.SetExitCode(report.ExitCode)
+ }
if err != nil {
return err
}
if cliVals.Detach {
fmt.Println(report.Id)
}
- registry.SetExitCode(report.ExitCode)
if runRmi {
- _, err := registry.ImageEngine().Delete(registry.GetContext(), []string{report.Id}, entities.ImageDeleteOptions{})
+ _, err := registry.ImageEngine().Delete(registry.GetContext(), []string{args[0]}, entities.ImageDeleteOptions{})
if err != nil {
logrus.Errorf("%s", errors.Wrapf(err, "failed removing image"))
}
diff --git a/cmd/podmanV2/containers/wait.go b/cmd/podmanV2/containers/wait.go
index bf3c86200..29a0e5546 100644
--- a/cmd/podmanV2/containers/wait.go
+++ b/cmd/podmanV2/containers/wait.go
@@ -5,7 +5,6 @@ import (
"fmt"
"time"
- "github.com/containers/libpod/cmd/podmanV2/parse"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/cmd/podmanV2/utils"
"github.com/containers/libpod/libpod/define"
@@ -23,9 +22,7 @@ var (
Long: waitDescription,
RunE: wait,
PersistentPreRunE: preRunE,
- Args: func(cmd *cobra.Command, args []string) error {
- return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
- },
+ Args: registry.IdOrLatestArgs,
Example: `podman wait --latest
podman wait --interval 5000 ctrID
podman wait ctrID1 ctrID2`,
diff --git a/cmd/podmanV2/images/list.go b/cmd/podmanV2/images/list.go
index 2d6cb3596..6b02e239e 100644
--- a/cmd/podmanV2/images/list.go
+++ b/cmd/podmanV2/images/list.go
@@ -130,6 +130,9 @@ func writeJSON(imageS []*entities.ImageSummary) error {
}
func writeTemplate(imageS []*entities.ImageSummary, err error) error {
+ var (
+ hdr, row string
+ )
type image struct {
entities.ImageSummary
Repository string `json:"repository,omitempty"`
@@ -148,10 +151,15 @@ func writeTemplate(imageS []*entities.ImageSummary, err error) error {
listFlag.readOnly = true
}
}
-
- hdr, row := imageListFormat(listFlag)
+ if len(listFlag.format) < 1 {
+ hdr, row = imageListFormat(listFlag)
+ } else {
+ row = listFlag.format
+ if !strings.HasSuffix(row, "\n") {
+ row += "\n"
+ }
+ }
format := hdr + "{{range . }}" + row + "{{end}}"
-
tmpl := template.Must(template.New("list").Funcs(report.PodmanTemplateFuncs()).Parse(format))
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
defer w.Flush()
diff --git a/cmd/podmanV2/registry/registry.go b/cmd/podmanV2/registry/registry.go
index 8ff44041f..07c2b33ff 100644
--- a/cmd/podmanV2/registry/registry.go
+++ b/cmd/podmanV2/registry/registry.go
@@ -9,7 +9,11 @@ import (
"github.com/spf13/cobra"
)
-type CobraFuncs func(cmd *cobra.Command, args []string) error
+// DefaultAPIAddress is the default address of the REST socket
+const DefaultAPIAddress = "unix:/run/podman/podman.sock"
+
+// DefaultVarlinkAddress is the default address of the varlink socket
+const DefaultVarlinkAddress = "unix:/run/podman/io.podman"
type CliCommand struct {
Mode []entities.EngineMode
diff --git a/cmd/podmanV2/system/service.go b/cmd/podmanV2/system/service.go
new file mode 100644
index 000000000..5573f7039
--- /dev/null
+++ b/cmd/podmanV2/system/service.go
@@ -0,0 +1,124 @@
+package system
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/systemd"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+)
+
+var (
+ srvDescription = `Run an API service
+
+Enable a listening service for API access to Podman commands.
+`
+
+ srvCmd = &cobra.Command{
+ Use: "service [flags] [URI]",
+ Args: cobra.MaximumNArgs(1),
+ Short: "Run API service",
+ Long: srvDescription,
+ RunE: service,
+ Example: `podman system service --time=0 unix:///tmp/podman.sock
+ podman system service --varlink --time=0 unix:///tmp/podman.sock`,
+ }
+
+ srvArgs = struct {
+ Timeout int64
+ Varlink bool
+ }{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: srvCmd,
+ Parent: systemCmd,
+ })
+
+ flags := srvCmd.Flags()
+ flags.Int64VarP(&srvArgs.Timeout, "time", "t", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
+ flags.Int64Var(&srvArgs.Timeout, "timeout", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
+ flags.BoolVar(&srvArgs.Varlink, "varlink", false, "Use legacy varlink service instead of REST")
+
+ _ = flags.MarkDeprecated("varlink", "valink API is deprecated.")
+}
+
+func service(cmd *cobra.Command, args []string) error {
+ apiURI, err := resolveApiURI(args)
+ if err != nil {
+ return err
+ }
+ logrus.Infof("using API endpoint: \"%s\"", apiURI)
+
+ opts := entities.ServiceOptions{
+ URI: apiURI,
+ Timeout: time.Duration(srvArgs.Timeout) * time.Second,
+ Command: cmd,
+ }
+
+ if srvArgs.Varlink {
+ return registry.ContainerEngine().VarlinkService(registry.GetContext(), opts)
+ }
+
+ logrus.Warn("This function is EXPERIMENTAL")
+ fmt.Fprintf(os.Stderr, "This function is EXPERIMENTAL.\n")
+ return registry.ContainerEngine().RestService(registry.GetContext(), opts)
+}
+
+func resolveApiURI(_url []string) (string, error) {
+
+ // When determining _*THE*_ listening endpoint --
+ // 1) User input wins always
+ // 2) systemd socket activation
+ // 3) rootless honors XDG_RUNTIME_DIR
+ // 4) if varlink -- adapter.DefaultVarlinkAddress
+ // 5) lastly adapter.DefaultAPIAddress
+
+ if _url == nil {
+ if v, found := os.LookupEnv("PODMAN_SOCKET"); found {
+ _url = []string{v}
+ }
+ }
+
+ switch {
+ case len(_url) > 0:
+ return _url[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"
+ if srvArgs.Varlink {
+ socketName = "io.podman"
+ }
+ socketDir := filepath.Join(xdg, "podman", socketName)
+ if _, err := os.Stat(filepath.Dir(socketDir)); err != nil {
+ if os.IsNotExist(err) {
+ if err := os.Mkdir(filepath.Dir(socketDir), 0755); err != nil {
+ return "", err
+ }
+ } else {
+ return "", err
+ }
+ }
+ return "unix:" + socketDir, nil
+ case srvArgs.Varlink:
+ return registry.DefaultVarlinkAddress, nil
+ default:
+ return registry.DefaultAPIAddress, nil
+ }
+}
diff --git a/cmd/podmanV2/system/system.go b/cmd/podmanV2/system/system.go
index 4e805c7bd..b44632187 100644
--- a/cmd/podmanV2/system/system.go
+++ b/cmd/podmanV2/system/system.go
@@ -8,7 +8,7 @@ import (
var (
// Command: podman _system_
- cmd = &cobra.Command{
+ systemCmd = &cobra.Command{
Use: "system",
Short: "Manage podman",
Long: "Manage podman",
@@ -21,10 +21,10 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
- Command: cmd,
+ Command: systemCmd,
})
- cmd.SetHelpTemplate(registry.HelpTemplate())
- cmd.SetUsageTemplate(registry.UsageTemplate())
+ systemCmd.SetHelpTemplate(registry.HelpTemplate())
+ systemCmd.SetUsageTemplate(registry.UsageTemplate())
}
func preRunE(cmd *cobra.Command, args []string) error {
diff --git a/cmd/podmanV2/system/varlink.go b/cmd/podmanV2/system/varlink.go
new file mode 100644
index 000000000..da9af6fe4
--- /dev/null
+++ b/cmd/podmanV2/system/varlink.go
@@ -0,0 +1,56 @@
+package system
+
+import (
+ "time"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ varlinkDescription = `Run varlink interface. Podman varlink listens on the specified unix domain socket for incoming connects.
+
+ Tools speaking varlink protocol can remotely manage pods, containers and images.
+`
+ varlinkCmd = &cobra.Command{
+ Use: "varlink [flags] [URI]",
+ Args: cobra.MinimumNArgs(1),
+ Short: "Run varlink interface",
+ Long: varlinkDescription,
+ PreRunE: preRunE,
+ RunE: varlinkE,
+ Example: `podman varlink unix:/run/podman/io.podman
+ podman varlink --timeout 5000 unix:/run/podman/io.podman`,
+ }
+ varlinkArgs = struct {
+ Timeout int64
+ }{}
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: varlinkCmd,
+ })
+ varlinkCmd.SetHelpTemplate(registry.HelpTemplate())
+ varlinkCmd.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := varlinkCmd.Flags()
+ flags.Int64VarP(&varlinkArgs.Timeout, "time", "t", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
+ flags.Int64Var(&varlinkArgs.Timeout, "timeout", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
+
+}
+
+func varlinkE(cmd *cobra.Command, args []string) error {
+ uri := registry.DefaultVarlinkAddress
+ if len(args) > 0 {
+ uri = args[0]
+ }
+ opts := entities.ServiceOptions{
+ URI: uri,
+ Timeout: time.Duration(varlinkArgs.Timeout) * time.Second,
+ Command: cmd,
+ }
+ return registry.ContainerEngine().VarlinkService(registry.GetContext(), opts)
+}