-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
180 lines (158 loc) · 4.48 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package main
import (
"math/rand"
"os"
"path/filepath"
"strings"
"time"
"code.cloudfoundry.org/lager"
"github.com/SUSE/groot-btrfs/commands"
"github.com/SUSE/groot-btrfs/commands/config"
"github.com/SUSE/groot-btrfs/store"
"github.com/cloudfoundry/dropsonde"
"github.com/containers/storage/pkg/reexec"
"github.com/urfave/cli"
)
var version string
const (
defaultDraxBin = "drax"
defaultNewuidmapBin = "newuidmap"
defaultNewgidmapBin = "newgidmap"
)
func init() {
rand.Seed(time.Now().UnixNano())
if reexec.Init() {
os.Exit(0)
}
}
func main() {
grootfs := cli.NewApp()
grootfs.Name = "grootfs"
grootfs.Version = version
grootfs.Usage = "I am Groot!"
grootfs.Flags = []cli.Flag{
cli.StringFlag{
Name: "config",
Usage: "Path to config file",
},
cli.StringFlag{
Name: "store",
Usage: "Path to the store directory",
Value: store.DefaultStorePath,
},
cli.StringFlag{
Name: "log-level",
Usage: "Set logging level <debug|info|error|fatal>",
Value: "fatal",
},
cli.StringFlag{
Name: "log-file",
Usage: "File to write logs to. Using this option sets the log level to `info` if --log-level is not specified.",
},
cli.StringFlag{
Name: "drax-bin",
Usage: "Path to drax bin. (If not provided will use $PATH)",
Value: defaultDraxBin,
},
cli.StringFlag{
Name: "btrfs-progs-path",
Usage: "Path to btrfs progs. (If not provided will use $PATH)",
Value: "",
},
cli.StringFlag{
Name: "newuidmap-bin",
Usage: "Path to newuidmap bin. (If not provided will use $PATH)",
Value: defaultNewuidmapBin,
},
cli.StringFlag{
Name: "newgidmap-bin",
Usage: "Path to newgidmap bin. (If not provided will use $PATH)",
Value: defaultNewgidmapBin,
},
cli.StringFlag{
Name: "metron-endpoint",
Usage: "Metron endpoint used to send metrics",
Value: "",
},
}
grootfs.Commands = []cli.Command{
commands.InitStoreCommand,
commands.DeleteStoreCommand,
commands.GenerateVolumeSizeMetadata,
commands.CreateCommand,
commands.DeleteCommand,
commands.StatsCommand,
commands.CleanCommand,
commands.ListCommand,
}
grootfs.Before = func(ctx *cli.Context) error {
cfgBuilder, err := config.NewBuilder(ctx.GlobalString("config"))
if err != nil {
return cli.NewExitError(err.Error(), 1)
}
ctx.App.Metadata["configBuilder"] = cfgBuilder
cfg, err := cfgBuilder.WithStorePath(ctx.GlobalString("store"), ctx.IsSet("store")).
WithDraxBin(ctx.GlobalString("drax-bin"), ctx.IsSet("drax-bin")).
WithMetronEndpoint(ctx.GlobalString("metron-endpoint")).
WithLogLevel(ctx.GlobalString("log-level"), ctx.IsSet("log-level")).
WithLogFile(ctx.GlobalString("log-file")).
WithBtrfsProgsPath(ctx.GlobalString("btrfs-progs-path"), ctx.IsSet("btrfs-progs-path")).
WithNewuidmapBin(ctx.GlobalString("newuidmap-bin"), ctx.IsSet("newuidmap-bin")).
WithNewgidmapBin(ctx.GlobalString("newgidmap-bin"), ctx.IsSet("newgidmap-bin")).
Build()
if err != nil {
return cli.NewExitError(err.Error(), 1)
}
lagerLogLevel := translateLogLevel(cfg.LogLevel)
logger, err := configureLogger(lagerLogLevel, cfg.LogFile)
if err != nil {
return cli.NewExitError(err.Error(), 1)
}
ctx.App.Metadata["logger"] = logger
// Sadness. We need to do that becuase we use stderr for logs so user
// errors need to end up in stdout.
cli.ErrWriter = os.Stdout
if err := os.Setenv("TMPDIR", filepath.Join(cfg.StorePath, store.TempDirName)); err != nil {
logger.Error("setting TMPDIR env var", err)
return cli.NewExitError(err.Error(), 1)
}
dropsondeOrigin := grootfs.Name
if cfg.MetronEndpoint != "" {
if err := dropsonde.Initialize(cfg.MetronEndpoint, dropsondeOrigin); err != nil {
logger.Error("failed-to-initialize-metrics-emitter", err)
}
}
return nil
}
if err := grootfs.Run(os.Args); err != nil {
os.Exit(1)
}
}
func translateLogLevel(logLevel string) lager.LogLevel {
switch strings.ToUpper(logLevel) {
case "DEBUG":
return lager.DEBUG
case "INFO":
return lager.INFO
case "ERROR":
return lager.ERROR
default:
return lager.FATAL
}
}
func configureLogger(logLevel lager.LogLevel, logFile string) (lager.Logger, error) {
logWriter := os.Stderr
if logFile != "" {
var err error
logWriter, err = os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
return nil, err
}
if logLevel == lager.FATAL {
logLevel = lager.INFO
}
}
logger := lager.NewLogger("grootfs")
logger.RegisterSink(lager.NewWriterSink(logWriter, logLevel))
return logger, nil
}