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 }