forked from cozy/cozy-stack
/
main.go
136 lines (115 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
package stack
import (
"context"
"fmt"
"os"
"time"
"github.com/cozy/cozy-stack/model/job"
"github.com/cozy/cozy-stack/model/session"
"github.com/cozy/cozy-stack/pkg/assets/dynamic"
build "github.com/cozy/cozy-stack/pkg/config"
"github.com/cozy/cozy-stack/pkg/config/config"
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/utils"
"github.com/google/gops/agent"
"github.com/sirupsen/logrus"
)
// Options can be used to give options when starting the stack.
type Options int
const (
// NoGops option can be used to disable gops support
NoGops Options = iota + 1
// NoDynAssets option can be used to initialize the dynamic assets
NoDynAssets
)
func hasOptions(needle Options, haystack []Options) bool {
for _, opt := range haystack {
if opt == needle {
return true
}
}
return false
}
type gopAgent struct{}
func (g gopAgent) Shutdown(ctx context.Context) error {
fmt.Print(" shutting down gops...")
agent.Close()
fmt.Println("ok.")
return nil
}
// Start is used to initialize all the
func Start(opts ...Options) (processes utils.Shutdowner, err error) {
if build.IsDevRelease() {
fmt.Print(` !! DEVELOPMENT RELEASE !!
You are running a development release which may deactivate some very important
security features. Please do not use this binary as your production server.
`)
}
var shutdowners []utils.Shutdowner
if !hasOptions(NoGops, opts) {
err = agent.Listen(agent.Options{})
if err != nil {
fmt.Fprintf(os.Stderr, "Error on gops agent: %s\n", err)
}
shutdowners = append(shutdowners, gopAgent{})
}
if err = config.MakeVault(config.GetConfig()); err != nil {
return
}
// Check that we can properly reach CouchDB.
u := config.CouchURL()
u.User = config.GetConfig().CouchDB.Auth
attempts := 8
attemptsSpacing := 1 * time.Second
for i := 0; i < attempts; i++ {
_, err = couchdb.CheckStatus()
if err == nil {
break
}
err = fmt.Errorf("Could not reach Couchdb 2 database: %s", err.Error())
if i < attempts-1 {
logrus.Warnf("%s, retrying in %v", err, attemptsSpacing)
time.Sleep(attemptsSpacing)
}
}
if err != nil {
return
}
if err = couchdb.InitGlobalDB(); err != nil {
return
}
// Init the main global connection to the swift server
if err = config.InitDefaultSwiftConnection(); err != nil {
return
}
workersList, err := job.GetWorkersList()
if err != nil {
return
}
var broker job.Broker
var schder job.Scheduler
jobsConfig := config.GetConfig().Jobs
if cli := jobsConfig.Client(); cli != nil {
broker = job.NewRedisBroker(cli)
schder = job.NewRedisScheduler(cli)
} else {
broker = job.NewMemBroker()
schder = job.NewMemScheduler()
}
if err = job.SystemStart(broker, schder, workersList); err != nil {
return
}
shutdowners = append(shutdowners, job.System())
// Initialize the dynamic assets FS. Can be OsFs, MemFs or Swift
if !hasOptions(NoDynAssets, opts) {
err = dynamic.InitDynamicAssetFS()
if err != nil {
return nil, err
}
}
sessionSweeper := session.SweepLoginRegistrations()
shutdowners = append(shutdowners, sessionSweeper)
// Global shutdowner that composes all the running processes of the stack
processes = utils.NewGroupShutdown(shutdowners...)
return
}