common/output.go (91 lines of code) (raw):

package common import ( "encoding/json" "reflect" "strings" "time" "github.com/JeffreyRichter/enum/enum" ) var EOutputMessageType = OutputMessageType(0) // OutputMessageType defines the nature of the output, ex: progress report, job summary, or error type OutputMessageType uint8 func (OutputMessageType) Init() OutputMessageType { return OutputMessageType(0) } // simple print, allowed to float up func (OutputMessageType) Info() OutputMessageType { return OutputMessageType(1) } // simple print, allowed to float up func (OutputMessageType) Progress() OutputMessageType { return OutputMessageType(2) } // should be printed on the same line over and over again, not allowed to float up func (OutputMessageType) Dryrun() OutputMessageType { return OutputMessageType(6) } // simple print // EndOfJob used to be called Exit, but now it's not necessarily an exit, because we may have follow-up jobs func (OutputMessageType) EndOfJob() OutputMessageType { return OutputMessageType(3) } // (may) exit after printing // TODO: if/when we review the STE structure, with regard to the old out-of-process design vs the current in-process design, we should // confirm whether we also need a separate exit code to signal process exit. For now, let's assume that anything listening to our stdout // will detect process exit (if needs to) by detecting that we have closed our stdout. func (OutputMessageType) Error() OutputMessageType { return OutputMessageType(4) } // indicate fatal error, exit right after func (OutputMessageType) Prompt() OutputMessageType { return OutputMessageType(5) } // ask the user a question after erasing the progress func (OutputMessageType) Response() OutputMessageType { return OutputMessageType(7) } /* Response to LCMMsg (like PerformanceAdjustment) //Json with determined fields for output-type json, INFO for other o/p types. */ // ListOutputTypes func (OutputMessageType) ListObject() OutputMessageType { return OutputMessageType(8) } func (OutputMessageType) ListSummary() OutputMessageType { return OutputMessageType(9) } func (OutputMessageType) LoginStatusInfo() OutputMessageType { return OutputMessageType(10) } func (o OutputMessageType) String() string { return enum.StringInt(o, reflect.TypeOf(o)) } // defines the output and how it should be handled type outputMessage struct { msgContent string msgType OutputMessageType exitCode ExitCode // only for when the application is meant to exit after printing (i.e. Error or Final) inputChannel chan<- string // support getting a response from the user promptDetails PromptDetails } func (m outputMessage) shouldExitProcess() bool { return m.msgType == EOutputMessageType.Error() || (m.msgType == EOutputMessageType.EndOfJob() && !(m.exitCode == EExitCode.NoExit())) } // used for output types that are not simple strings, such as progress and init // a given format(text,json) is passed in, and the appropriate string is returned type OutputBuilder func(OutputFormat) string type PromptDetails struct { PromptType PromptType ResponseOptions []ResponseOption // used from prompt messages where we expect a response PromptTarget string // used when prompt message is targeting a specific resource, ease partner team integration } var EPromptType = PromptType("") type PromptType string func (PromptType) Reauth() PromptType { return PromptType("Reauth") } func (PromptType) Cancel() PromptType { return PromptType("Cancel") } func (PromptType) Overwrite() PromptType { return PromptType("Overwrite") } func (PromptType) DeleteDestination() PromptType { return PromptType("DeleteDestination") } // -------------------------------------- JSON templates -------------------------------------- // // used to help formatting of JSON outputs func GetJsonStringFromTemplate(template interface{}) string { jsonOutput, err := json.Marshal(template) PanicIfErr(err) return string(jsonOutput) } // defines the general output template when the format is set to json type JsonOutputTemplate struct { TimeStamp time.Time MessageType string MessageContent string // a simple string for INFO and ERROR, a serialized JSON for INIT, PROGRESS, EXIT PromptDetails PromptDetails } func newJsonOutputTemplate(messageType OutputMessageType, messageContent string, promptDetails PromptDetails) *JsonOutputTemplate { return &JsonOutputTemplate{TimeStamp: time.Now(), MessageType: messageType.String(), MessageContent: messageContent, PromptDetails: promptDetails} } type InitMsgJsonTemplate struct { LogFileLocation string JobID string IsCleanupJob bool } func GetStandardInitOutputBuilder(jobID string, logFileLocation string, isCleanupJob bool, cleanupMessage string) OutputBuilder { return func(format OutputFormat) string { if format == EOutputFormat.Json() { return GetJsonStringFromTemplate(InitMsgJsonTemplate{ JobID: jobID, LogFileLocation: logFileLocation, IsCleanupJob: isCleanupJob, }) } var sb strings.Builder if isCleanupJob { cleanupHeader := "(" + cleanupMessage + " with cleanup jobID " + jobID sb.WriteString(strings.Repeat("-", len(cleanupHeader)) + "\n") sb.WriteString(cleanupHeader) } else { sb.WriteString("\nJob " + jobID + " has started\n") if logFileLocation != "" { sb.WriteString("Log file is located at: " + logFileLocation) } sb.WriteString("\n") } return sb.String() } }