From e0847f5457edfdeb17dad259f1cd06b1d4cec93e Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Thu, 2 Apr 2020 15:58:23 -0700 Subject: V2 podman system service * Added support for system service * Enabled linting on the varlinkapi source, needed to support V2 service command * Added support for PODMAN_SOCKET Skip linting deprecated code Rather than introduce bugs by correcting deprecated code, linting the code is being skipped. Code that is being ported into V2 is being checked. Signed-off-by: Jhon Honce --- cmd/podman/commands_remoteclient.go | 6 +- cmd/podman/main.go | 4 +- cmd/podman/service.go | 6 +- cmd/podman/service_dummy.go | 1 + cmd/podman/varlink.go | 2 +- cmd/podman/varlink_dummy.go | 1 + cmd/podmanV2/Makefile | 12 +++- cmd/podmanV2/registry/registry.go | 6 +- cmd/podmanV2/system/service.go | 124 ++++++++++++++++++++++++++++++++++++ cmd/podmanV2/system/system.go | 8 +-- cmd/podmanV2/system/varlink.go | 56 ++++++++++++++++ 11 files changed, 210 insertions(+), 16 deletions(-) create mode 100644 cmd/podmanV2/system/service.go create mode 100644 cmd/podmanV2/system/varlink.go (limited to 'cmd') diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go index ef523ffb1..11baeb4ae 100644 --- a/cmd/podman/commands_remoteclient.go +++ b/cmd/podman/commands_remoteclient.go @@ -14,7 +14,7 @@ func getMainCommands() []*cobra.Command { } // commands that only the remoteclient implements -func getAppCommands() []*cobra.Command { +func getAppCommands() []*cobra.Command { // nolint:varcheck,deadcode,unused return []*cobra.Command{} } @@ -29,7 +29,7 @@ func getContainerSubCommands() []*cobra.Command { } // commands that only the remoteclient implements -func getGenerateSubCommands() []*cobra.Command { +func getGenerateSubCommands() []*cobra.Command { // nolint:varcheck,deadcode,unused return []*cobra.Command{} } @@ -126,7 +126,7 @@ func getDefaultPidsDescription() string { return "Tune container pids limit (set 0 for unlimited, -1 for server defaults)" } -func getDefaultShareNetwork() string { +func getDefaultShareNetwork() string { // nolint:varcheck,deadcode,unused return "" } diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 5134448da..4435b036e 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -24,8 +24,8 @@ import ( var ( exitCode = define.ExecErrorCodeGeneric Ctx context.Context - span opentracing.Span - closer io.Closer + span opentracing.Span // nolint:varcheck,deadcode,unused + closer io.Closer // nolint:varcheck,deadcode,unused ) // Commands that the remote and local client have diff --git a/cmd/podman/service.go b/cmd/podman/service.go index bcb37eac5..41ec499a1 100644 --- a/cmd/podman/service.go +++ b/cmd/podman/service.go @@ -91,7 +91,7 @@ func resolveApiURI(c *cliconfig.ServiceValues) (string, error) { if len(c.InputArgs) > 0 { apiURI = c.InputArgs[0] - } else if ok := systemd.SocketActivated(); ok { + } else if ok := systemd.SocketActivated(); ok { // nolint: gocritic apiURI = "" } else if rootless.IsRootless() { xdg, err := util.GetRuntimeDir() @@ -161,7 +161,7 @@ func runREST(r *libpod.Runtime, uri string, timeout time.Duration) error { } func runVarlink(r *libpod.Runtime, uri string, timeout time.Duration, c *cliconfig.ServiceValues) error { - var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(&c.PodmanCommand, r)} + var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(c.PodmanCommand.Command, r)} service, err := varlink.NewService( "Atomic", "podman", @@ -182,7 +182,7 @@ func runVarlink(r *libpod.Runtime, uri string, timeout time.Duration, c *cliconf if err = service.Listen(uri, timeout); err != nil { switch err.(type) { case varlink.ServiceTimeoutError: - logrus.Infof("varlink service expired (use --timeout to increase session time beyond %d ms, 0 means never timeout)", timeout.String()) + logrus.Infof("varlink service expired (use --timeout to increase session time beyond %s ms, 0 means never timeout)", timeout.String()) return nil default: return errors.Wrapf(err, "unable to start varlink service") diff --git a/cmd/podman/service_dummy.go b/cmd/podman/service_dummy.go index a774c34de..a726f21c1 100644 --- a/cmd/podman/service_dummy.go +++ b/cmd/podman/service_dummy.go @@ -5,6 +5,7 @@ package main import "github.com/spf13/cobra" var ( + // nolint:varcheck,deadcode,unused _serviceCommand = &cobra.Command{ Use: "", } diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go index 20334ec96..be882d497 100644 --- a/cmd/podman/varlink.go +++ b/cmd/podman/varlink.go @@ -85,7 +85,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error { } defer runtime.DeferredShutdown(false) - var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(&c.PodmanCommand, runtime)} + var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(c.PodmanCommand.Command, runtime)} // Register varlink service. The metadata can be retrieved with: // $ varlink info [varlink address URI] service, err := varlink.NewService( diff --git a/cmd/podman/varlink_dummy.go b/cmd/podman/varlink_dummy.go index 430511d72..0c7981f1a 100644 --- a/cmd/podman/varlink_dummy.go +++ b/cmd/podman/varlink_dummy.go @@ -5,6 +5,7 @@ package main import "github.com/spf13/cobra" var ( + // nolint:varcheck,deadcode,unused _varlinkCommand = &cobra.Command{ Use: "", } 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/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) +} -- cgit v1.2.3-54-g00ecf