github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/varlink.go (about)

     1  // +build varlink,!remoteclient
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"time"
    10  
    11  	"github.com/containers/libpod/cmd/podman/cliconfig"
    12  	"github.com/containers/libpod/cmd/podman/libpodruntime"
    13  	"github.com/containers/libpod/pkg/adapter"
    14  	"github.com/containers/libpod/pkg/rootless"
    15  	"github.com/containers/libpod/pkg/util"
    16  	iopodman "github.com/containers/libpod/pkg/varlink"
    17  	"github.com/containers/libpod/pkg/varlinkapi"
    18  	"github.com/containers/libpod/version"
    19  	"github.com/pkg/errors"
    20  	"github.com/sirupsen/logrus"
    21  	"github.com/spf13/cobra"
    22  	"github.com/varlink/go/varlink"
    23  )
    24  
    25  var (
    26  	varlinkCommand     cliconfig.VarlinkValues
    27  	varlinkDescription = `Run varlink interface.  Podman varlink listens on the specified unix domain socket for incoming connects.
    28  
    29    Tools speaking varlink protocol can remotely manage pods, containers and images.
    30  `
    31  	_varlinkCommand = &cobra.Command{
    32  		Use:   "varlink [flags] [URI]",
    33  		Short: "Run varlink interface",
    34  		Long:  varlinkDescription,
    35  		RunE: func(cmd *cobra.Command, args []string) error {
    36  			varlinkCommand.InputArgs = args
    37  			varlinkCommand.GlobalFlags = MainGlobalOpts
    38  			return varlinkCmd(&varlinkCommand)
    39  		},
    40  		Example: `podman varlink unix:/run/podman/io.podman
    41    podman varlink --timeout 5000 unix:/run/podman/io.podman`,
    42  	}
    43  )
    44  
    45  func init() {
    46  	varlinkCommand.Command = _varlinkCommand
    47  	varlinkCommand.SetHelpTemplate(HelpTemplate())
    48  	varlinkCommand.SetUsageTemplate(UsageTemplate())
    49  	flags := varlinkCommand.Flags()
    50  	flags.Int64VarP(&varlinkCommand.Timeout, "timeout", "t", 1000, "Time until the varlink session expires in milliseconds.  Use 0 to disable the timeout")
    51  }
    52  
    53  func varlinkCmd(c *cliconfig.VarlinkValues) error {
    54  	varlinkURI := adapter.DefaultVarlinkAddress
    55  	if rootless.IsRootless() {
    56  		xdg, err := util.GetRuntimeDir()
    57  		if err != nil {
    58  			return err
    59  		}
    60  		socketDir := filepath.Join(xdg, "podman/io.podman")
    61  		if _, err := os.Stat(filepath.Dir(socketDir)); os.IsNotExist(err) {
    62  			if err := os.Mkdir(filepath.Dir(socketDir), 0755); err != nil {
    63  				return err
    64  			}
    65  		}
    66  		varlinkURI = fmt.Sprintf("unix:%s", socketDir)
    67  	}
    68  	args := c.InputArgs
    69  
    70  	if len(args) > 1 {
    71  		return errors.Errorf("too many arguments. You may optionally provide 1")
    72  	}
    73  
    74  	if len(args) > 0 {
    75  		varlinkURI = args[0]
    76  	}
    77  
    78  	logrus.Debugf("Using varlink socket: %s", varlinkURI)
    79  	timeout := time.Duration(c.Timeout) * time.Millisecond
    80  
    81  	// Create a single runtime for varlink
    82  	runtime, err := libpodruntime.GetRuntimeDisableFDs(getContext(), &c.PodmanCommand)
    83  	if err != nil {
    84  		return errors.Wrapf(err, "error creating libpod runtime")
    85  	}
    86  	defer runtime.DeferredShutdown(false)
    87  
    88  	var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(c.PodmanCommand.Command, runtime)}
    89  	// Register varlink service. The metadata can be retrieved with:
    90  	// $ varlink info [varlink address URI]
    91  	service, err := varlink.NewService(
    92  		"Atomic",
    93  		"podman",
    94  		version.Version,
    95  		"https://github.com/containers/libpod",
    96  	)
    97  	if err != nil {
    98  		return errors.Wrapf(err, "unable to create new varlink service")
    99  	}
   100  
   101  	for _, i := range varlinkInterfaces {
   102  		if err := service.RegisterInterface(i); err != nil {
   103  			return errors.Errorf("unable to register varlink interface %v", i)
   104  		}
   105  	}
   106  
   107  	// Run the varlink server at the given address
   108  	if err = service.Listen(varlinkURI, timeout); err != nil {
   109  		switch err.(type) {
   110  		case varlink.ServiceTimeoutError:
   111  			logrus.Infof("varlink service expired (use --timeout to increase session time beyond %d ms, 0 means never timeout)", c.Int64("timeout"))
   112  			return nil
   113  		default:
   114  			return errors.Wrapf(err, "unable to start varlink service")
   115  		}
   116  	}
   117  
   118  	return nil
   119  }