github.com/hernad/nomad@v1.6.112/command/operator_raft_logs.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package command 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "os" 10 "strings" 11 12 "github.com/hernad/nomad/helper/raftutil" 13 "github.com/posener/complete" 14 ) 15 16 type OperatorRaftLogsCommand struct { 17 Meta 18 } 19 20 func (c *OperatorRaftLogsCommand) Help() string { 21 helpText := ` 22 Usage: nomad operator raft logs <path to nomad data dir> 23 24 Display the log entries persisted in the Nomad data directory in JSON 25 format. 26 27 This command requires file system permissions to access the data directory on 28 disk. The Nomad server locks access to the data directory, so this command 29 cannot be run on a data directory that is being used by a running Nomad server. 30 31 This is a low-level debugging tool and not subject to Nomad's usual backward 32 compatibility guarantees. 33 34 Raft Logs Options: 35 36 -pretty 37 By default this command outputs newline delimited JSON. If the -pretty flag 38 is passed, each entry will be pretty-printed. 39 ` 40 return strings.TrimSpace(helpText) 41 } 42 43 func (c *OperatorRaftLogsCommand) AutocompleteFlags() complete.Flags { 44 return complete.Flags{} 45 } 46 47 func (c *OperatorRaftLogsCommand) AutocompleteArgs() complete.Predictor { 48 return complete.PredictNothing 49 } 50 51 func (c *OperatorRaftLogsCommand) Synopsis() string { 52 return "Display raft log content" 53 } 54 55 func (c *OperatorRaftLogsCommand) Name() string { return "operator raft logs" } 56 57 func (c *OperatorRaftLogsCommand) Run(args []string) int { 58 59 var pretty bool 60 flagSet := c.Meta.FlagSet(c.Name(), FlagSetClient) 61 flagSet.Usage = func() { c.Ui.Output(c.Help()) } 62 flagSet.BoolVar(&pretty, "pretty", false, "") 63 64 if err := flagSet.Parse(args); err != nil { 65 return 1 66 } 67 68 args = flagSet.Args() 69 if l := len(args); l != 1 { 70 c.Ui.Error("This command takes one argument: <path>") 71 c.Ui.Error(commandErrorText(c)) 72 return 1 73 } 74 75 raftPath, err := raftutil.FindRaftFile(args[0]) 76 if err != nil { 77 c.Ui.Error(err.Error()) 78 return 1 79 } 80 81 enc := json.NewEncoder(os.Stdout) 82 if pretty { 83 enc.SetIndent("", " ") 84 } 85 86 logChan, warningsChan, err := raftutil.LogEntries(raftPath) 87 if err != nil { 88 c.Ui.Error(err.Error()) 89 return 1 90 } 91 92 // so that the warnings don't end up mixed into the JSON stream, 93 // collect them and print them once we're done 94 warnings := []error{} 95 96 DONE: 97 for { 98 select { 99 case log := <-logChan: 100 if log == nil { 101 break DONE // no more logs, but break to print warnings 102 } 103 if err := enc.Encode(log); err != nil { 104 c.Ui.Error(fmt.Sprintf("failed to encode output: %v", err)) 105 return 1 106 } 107 case warning := <-warningsChan: 108 warnings = append(warnings, warning) 109 } 110 } 111 112 for _, warning := range warnings { 113 c.Ui.Error(warning.Error()) 114 } 115 116 return 0 117 }