129 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
package containers
 | 
						|
 | 
						|
import (
 | 
						|
	"os"
 | 
						|
 | 
						|
	"github.com/containers/common/pkg/completion"
 | 
						|
	"github.com/containers/podman/v2/cmd/podman/common"
 | 
						|
	"github.com/containers/podman/v2/cmd/podman/registry"
 | 
						|
	"github.com/containers/podman/v2/cmd/podman/validate"
 | 
						|
	"github.com/containers/podman/v2/pkg/domain/entities"
 | 
						|
	"github.com/containers/podman/v2/pkg/util"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"github.com/spf13/cobra"
 | 
						|
)
 | 
						|
 | 
						|
// 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 [options] CONTAINER [CONTAINER...]",
 | 
						|
		Short: "Fetch the logs of one or more containers",
 | 
						|
		Long:  logsDescription,
 | 
						|
		Args: func(cmd *cobra.Command, args []string) error {
 | 
						|
			switch {
 | 
						|
			case registry.IsRemote() && logsOptions.Latest:
 | 
						|
				return errors.New(cmd.Name() + " does not support 'latest' when run remotely")
 | 
						|
			case registry.IsRemote() && len(args) > 1:
 | 
						|
				return errors.New(cmd.Name() + " does not support multiple containers when run remotely")
 | 
						|
			case logsOptions.Latest && len(args) > 0:
 | 
						|
				return errors.New("--latest and containers cannot be used together")
 | 
						|
			case !logsOptions.Latest && len(args) < 1:
 | 
						|
				return errors.New("specify at least one container name or ID to log")
 | 
						|
			}
 | 
						|
			return nil
 | 
						|
		},
 | 
						|
		RunE:              logs,
 | 
						|
		ValidArgsFunction: common.AutocompleteContainers,
 | 
						|
		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,
 | 
						|
		Args:              logsCommand.Args,
 | 
						|
		RunE:              logsCommand.RunE,
 | 
						|
		ValidArgsFunction: logsCommand.ValidArgsFunction,
 | 
						|
		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() {
 | 
						|
	// if run remotely we only allow one container arg
 | 
						|
	if registry.IsRemote() {
 | 
						|
		logsCommand.Use = "logs [options] CONTAINER"
 | 
						|
		containerLogsCommand.Use = logsCommand.Use
 | 
						|
	}
 | 
						|
 | 
						|
	// logs
 | 
						|
	registry.Commands = append(registry.Commands, registry.CliCommand{
 | 
						|
		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
 | 
						|
		Command: logsCommand,
 | 
						|
	})
 | 
						|
	logsFlags(logsCommand)
 | 
						|
	validate.AddLatestFlag(logsCommand, &logsOptions.Latest)
 | 
						|
 | 
						|
	// container logs
 | 
						|
	registry.Commands = append(registry.Commands, registry.CliCommand{
 | 
						|
		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
 | 
						|
		Command: containerLogsCommand,
 | 
						|
		Parent:  containerCmd,
 | 
						|
	})
 | 
						|
	logsFlags(containerLogsCommand)
 | 
						|
	validate.AddLatestFlag(containerLogsCommand, &logsOptions.Latest)
 | 
						|
}
 | 
						|
 | 
						|
func logsFlags(cmd *cobra.Command) {
 | 
						|
	flags := cmd.Flags()
 | 
						|
 | 
						|
	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")
 | 
						|
 | 
						|
	sinceFlagName := "since"
 | 
						|
	flags.StringVar(&logsOptions.SinceRaw, sinceFlagName, "", "Show logs since TIMESTAMP")
 | 
						|
	_ = cmd.RegisterFlagCompletionFunc(sinceFlagName, completion.AutocompleteNone)
 | 
						|
 | 
						|
	tailFlagName := "tail"
 | 
						|
	flags.Int64Var(&logsOptions.Tail, tailFlagName, -1, "Output the specified number of LINES at the end of the logs.  Defaults to -1, which prints all lines")
 | 
						|
	_ = cmd.RegisterFlagCompletionFunc(tailFlagName, completion.AutocompleteNone)
 | 
						|
 | 
						|
	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(_ *cobra.Command, args []string) error {
 | 
						|
	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.StdoutWriter = os.Stdout
 | 
						|
	logsOptions.StderrWriter = os.Stderr
 | 
						|
	return registry.ContainerEngine().ContainerLogs(registry.GetContext(), args, logsOptions.ContainerLogsOptions)
 | 
						|
}
 |