forked from cloudfoundry/bosh-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
138 lines (114 loc) · 3.2 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"fmt"
"os"
"os/signal"
"runtime/debug"
"syscall"
bosherr "github.com/cloudfoundry/bosh-utils/errors"
boshlog "github.com/cloudfoundry/bosh-utils/logger"
boshlogfile "github.com/cloudfoundry/bosh-utils/logger/file"
boshsys "github.com/cloudfoundry/bosh-utils/system"
boshcmd "github.com/cloudfoundry/bosh-cli/v7/cmd"
bilog "github.com/cloudfoundry/bosh-cli/v7/logger"
boshui "github.com/cloudfoundry/bosh-cli/v7/ui"
boshuifmt "github.com/cloudfoundry/bosh-cli/v7/ui/fmt"
)
func main() {
logger := newLogger()
defer handlePanic()
ui := boshui.NewConfUI(logger)
defer ui.Flush()
cmdFactory := boshcmd.NewFactory(boshcmd.NewBasicDeps(ui, logger))
cmd, err := cmdFactory.New(os.Args[1:])
if err != nil {
fail(err, ui, logger)
}
err = cmd.Execute()
if err != nil {
fail(err, ui, logger)
} else {
success(ui, logger)
}
}
func newLogger() boshlog.Logger {
level := boshlog.LevelNone
logLevelString := os.Getenv("BOSH_LOG_LEVEL")
if logLevelString != "" {
var err error
level, err = boshlog.Levelify(logLevelString)
if err != nil {
err = bosherr.WrapError(err, "Invalid BOSH_LOG_LEVEL value")
logger := boshlog.NewLogger(boshlog.LevelError)
ui := boshui.NewConsoleUI(logger)
fail(err, ui, logger)
}
}
logPath := os.Getenv("BOSH_LOG_PATH")
if logPath != "" {
return newSignalableFileLogger(logPath, level)
}
return newSignalableLogger(boshlog.NewLogger(level))
}
func newSignalableLogger(logger boshlog.Logger) boshlog.Logger {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP)
signalableLogger, _ := bilog.NewSignalableLogger(logger, c)
return signalableLogger
}
func newSignalableFileLogger(logPath string, level boshlog.LogLevel) boshlog.Logger {
// Log file logger errors to the STDERR logger
logger := boshlog.NewLogger(boshlog.LevelError)
fs := boshsys.NewOsFileSystem(logger)
// Log file will be closed by process exit
// Log file readable by all
logfileLogger, _, err := boshlogfile.New(level, logPath, boshlogfile.DefaultLogFileMode, fs)
if err != nil {
logger := boshlog.NewLogger(boshlog.LevelError)
ui := boshui.NewConsoleUI(logger)
fail(err, ui, logger)
}
return newSignalableLogger(logfileLogger)
}
func handlePanic() {
panic := recover()
if panic != nil {
var msg string
var hideTrace bool
switch obj := panic.(type) {
case string:
msg = obj
case fmt.Stringer:
msg = obj.String()
case error:
msg = obj.Error()
case bosherr.UserError:
msg = obj.Err.Error()
hideTrace = true
default:
msg = fmt.Sprintf("%#v", obj)
}
// Always output to regardless of main logger's level
logger := boshlog.NewLogger(boshlog.LevelError)
if hideTrace {
logger.Error("CLI", "Panic: %s", msg)
} else {
logger.ErrorWithDetails("CLI", "Panic: %s", msg, debug.Stack())
}
ui := boshui.NewConsoleUI(logger)
fail(nil, ui, logger)
}
}
func fail(err error, ui boshui.UI, logger boshlog.Logger) {
if err != nil {
logger.Error("CLI", err.Error())
ui.ErrorLinef(boshuifmt.MultilineError(err))
}
ui.ErrorLinef("Exit code 1")
ui.Flush() // todo make sure UI is flushed
os.Exit(1)
}
func success(ui boshui.UI, logger boshlog.Logger) {
logger.Debug("CLI", "Succeeded")
ui.PrintLinef("Succeeded")
}