forked from concourse/baggageclaim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
command.go
152 lines (120 loc) · 4.4 KB
/
command.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
package baggageclaimcmd
import (
"fmt"
"os"
"time"
"code.cloudfoundry.org/clock"
"code.cloudfoundry.org/lager"
"github.com/concourse/baggageclaim/api"
"github.com/concourse/baggageclaim/reaper"
"github.com/concourse/baggageclaim/uidgid"
"github.com/concourse/baggageclaim/volume"
"github.com/tedsuo/ifrit"
"github.com/tedsuo/ifrit/grouper"
"github.com/tedsuo/ifrit/http_server"
"github.com/tedsuo/ifrit/sigmon"
"github.com/xoebus/zest"
)
type BaggageclaimCommand struct {
Logger LagerFlag
BindIP IPFlag `long:"bind-ip" default:"127.0.0.1" description:"IP address on which to listen for API traffic."`
BindPort uint16 `long:"bind-port" default:"7788" description:"Port on which to listen for API traffic."`
VolumesDir DirFlag `long:"volumes" required:"true" description:"Directory in which to place volume data."`
Driver string `long:"driver" default:"detect" choice:"detect" choice:"naive" choice:"btrfs" choice:"overlay" description:"Driver to use for managing volumes."`
BtrfsBin string `long:"btrfs-bin" default:"btrfs" description:"Path to btrfs binary"`
MkfsBin string `long:"mkfs-bin" default:"mkfs.btrfs" description:"Path to mkfs.btrfs binary"`
OverlaysDir string `long:"overlays-dir" description:"Path to directory in which to store overlay data"`
ReapInterval time.Duration `long:"reap-interval" default:"10s" description:"Interval on which to reap expired volumes."`
Metrics struct {
YellerAPIKey string `long:"yeller-api-key" description:"Yeller API key. If specified, all errors logged will be emitted."`
YellerEnvironment string `long:"yeller-environment" description:"Environment to tag on all Yeller events emitted."`
} `group:"Metrics & Diagnostics"`
}
func (cmd *BaggageclaimCommand) Execute(args []string) error {
runner, err := cmd.Runner(args)
if err != nil {
return err
}
return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}
func (cmd *BaggageclaimCommand) Runner(args []string) (ifrit.Runner, error) {
logger, _ := cmd.constructLogger()
listenAddr := fmt.Sprintf("%s:%d", cmd.BindIP.IP(), cmd.BindPort)
var privilegedNamespacer, unprivilegedNamespacer uidgid.Namespacer
if uidgid.Supported() {
privilegedNamespacer = &uidgid.UidNamespacer{
Translator: uidgid.NewTranslator(uidgid.NewPrivilegedMapper()),
Logger: logger.Session("uid-namespacer"),
}
unprivilegedNamespacer = &uidgid.UidNamespacer{
Translator: uidgid.NewTranslator(uidgid.NewUnprivilegedMapper()),
Logger: logger.Session("uid-namespacer"),
}
} else {
privilegedNamespacer = uidgid.NoopNamespacer{}
unprivilegedNamespacer = uidgid.NoopNamespacer{}
}
locker := volume.NewLockManager()
driver, err := cmd.driver(logger)
if err != nil {
logger.Error("failed-to-set-up-driver", err)
return nil, err
}
filesystem, err := volume.NewFilesystem(driver, cmd.VolumesDir.Path())
if err != nil {
logger.Error("failed-to-initialize-filesystem", err)
return nil, err
}
volumeRepo := volume.NewRepository(
logger.Session("repository"),
filesystem,
locker,
privilegedNamespacer,
unprivilegedNamespacer,
)
apiHandler, err := api.NewHandler(
logger.Session("api"),
volume.NewStrategerizer(),
volumeRepo,
)
if err != nil {
logger.Fatal("failed-to-create-handler", err)
}
clock := clock.NewClock()
morbidReality := reaper.NewReaper(clock, volumeRepo)
members := []grouper.Member{
{Name: "api", Runner: http_server.New(listenAddr, apiHandler)},
{Name: "reaper", Runner: reaper.NewRunner(logger, clock, cmd.ReapInterval, morbidReality.Reap)},
}
return onReady(grouper.NewParallel(os.Interrupt, members), func() {
logger.Info("listening", lager.Data{
"addr": listenAddr,
})
}), nil
}
func (cmd *BaggageclaimCommand) constructLogger() (lager.Logger, *lager.ReconfigurableSink) {
logger, reconfigurableSink := cmd.Logger.Logger("baggageclaim")
if cmd.Metrics.YellerAPIKey != "" {
yellerSink := zest.NewYellerSink(cmd.Metrics.YellerAPIKey, cmd.Metrics.YellerEnvironment)
logger.RegisterSink(yellerSink)
}
return logger, reconfigurableSink
}
func onReady(runner ifrit.Runner, cb func()) ifrit.Runner {
return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
process := ifrit.Background(runner)
subExited := process.Wait()
subReady := process.Ready()
for {
select {
case <-subReady:
cb()
subReady = nil
case err := <-subExited:
return err
case sig := <-signals:
process.Signal(sig)
}
}
})
}