github.com/Azure/draft-classic@v0.16.0/cmd/draft/logs.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/Azure/draft/pkg/draft/draftpath"
    10  	"github.com/Azure/draft/pkg/local"
    11  	"github.com/hpcloud/tail"
    12  	"github.com/spf13/cobra"
    13  )
    14  
    15  const logsDesc = `This command outputs logs from the draft server to help debug builds.`
    16  
    17  var (
    18  	runningEnvironment string
    19  )
    20  
    21  type logsCmd struct {
    22  	out     io.Writer
    23  	appName string
    24  	buildID string
    25  	line    uint
    26  	tail    bool
    27  	args    []string
    28  	home    draftpath.Home
    29  }
    30  
    31  func newLogsCmd(out io.Writer) *cobra.Command {
    32  	lc := &logsCmd{
    33  		out:  out,
    34  		args: []string{"build-id"},
    35  	}
    36  
    37  	cmd := &cobra.Command{
    38  		Use:     "logs <build-id>",
    39  		Short:   logsDesc,
    40  		Long:    logsDesc,
    41  		PreRunE: lc.complete,
    42  		RunE: func(cmd *cobra.Command, args []string) error {
    43  			deployedApp, err := local.DeployedApplication(draftToml, runningEnvironment)
    44  			if err != nil {
    45  				return err
    46  			}
    47  			lc.appName = deployedApp.Name
    48  			b, err := getLatestBuildID(lc.appName)
    49  			if err != nil {
    50  				return fmt.Errorf("cannot get latest build: %v", err)
    51  			}
    52  			lc.buildID = b
    53  
    54  			if len(args) > 0 {
    55  				lc.buildID = args[0]
    56  			}
    57  			return lc.run(cmd, args)
    58  		},
    59  	}
    60  
    61  	f := cmd.Flags()
    62  	f.BoolVar(&lc.tail, "tail", false, "tail the logs file as it's being written")
    63  	f.UintVar(&lc.line, "line", 20, "line location to tail from (offset from end of file)")
    64  	f.StringVarP(&runningEnvironment, environmentFlagName, environmentFlagShorthand, defaultDraftEnvironment(), environmentFlagUsage)
    65  	return cmd
    66  }
    67  
    68  func (l *logsCmd) complete(_ *cobra.Command, args []string) error {
    69  	l.home = draftpath.Home(homePath())
    70  	return nil
    71  }
    72  
    73  func (l *logsCmd) run(_ *cobra.Command, _ []string) error {
    74  	if l.tail {
    75  		return l.tailLogs(int64(l.line))
    76  	}
    77  	return l.dumpLogs()
    78  }
    79  
    80  func (l *logsCmd) dumpLogs() error {
    81  	f, err := os.Open(filepath.Join(l.home.Logs(), l.appName, l.buildID))
    82  	if err != nil {
    83  		return fmt.Errorf("could not read logs for %s: %v", l.buildID, err)
    84  	}
    85  	defer f.Close()
    86  	io.Copy(l.out, f)
    87  	return nil
    88  }
    89  
    90  func (l *logsCmd) tailLogs(offset int64) error {
    91  	t, err := tail.TailFile(filepath.Join(l.home.Logs(), l.appName, l.buildID), tail.Config{
    92  		Location: &tail.SeekInfo{Offset: -offset, Whence: os.SEEK_END},
    93  		Logger:   tail.DiscardingLogger,
    94  		Follow:   true,
    95  		ReOpen:   true,
    96  	})
    97  	if err != nil {
    98  		return err
    99  	}
   100  	for line := range t.Lines {
   101  		fmt.Fprintln(l.out, line.Text)
   102  	}
   103  	return t.Wait()
   104  }