-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.go
More file actions
146 lines (125 loc) · 3.31 KB
/
server.go
File metadata and controls
146 lines (125 loc) · 3.31 KB
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
package west
import (
"context"
"errors"
"fmt"
"github.com/rs/zerolog"
"github.com/sprisa/west/config"
l "github.com/sprisa/x/log"
"github.com/sirupsen/logrus"
"github.com/slackhq/nebula"
nebulaCfg "github.com/slackhq/nebula/config"
"github.com/slackhq/nebula/overlay"
"github.com/slackhq/nebula/util"
"gopkg.in/yaml.v3"
)
// A version string that can be set with
//
// -ldflags "-X main.Build=SOMEVERSION"
//
// at compile-time.
var Build string = "west v0.0.1"
type Control = nebula.Control
type NebulaConfigCtrl = nebulaCfg.C
type OnStartFunc = func(*Control)
// TODO: Add add an `onReady` and wait for Nebula to be fully up.
// e.g. after "handshake message received"
type ServerOpts struct {
// Custom Logging
Log *logrus.Logger
// Nebula config
Config *config.Config
// Hook called after Nebula server starts
OnStart OnStartFunc
// Hook called before Nebula shuts down.
// Will block until function returns.
OnShutdown func()
DeviceFactory overlay.DeviceFactory
}
type Server struct {
Ctrl *Control
opts *ServerOpts
}
func NewServer(opts *ServerOpts) (*Server, error) {
log := opts.Log
if log == nil {
log = logrus.StandardLogger()
}
nebulaConfig := opts.Config
if nebulaConfig == nil {
return nil, errors.New("expected west config")
}
c, err := CreateNebulaConfigCtrl(nebulaConfig, log)
if err != nil {
return nil, err
}
return NewServerWithConfigCtrl(opts, c)
}
func NewServerWithConfigCtrl(opts *ServerOpts, c *NebulaConfigCtrl) (*Server, error) {
if opts.Log == nil {
opts.Log = logrus.StandardLogger()
}
nebulaConfig := opts.Config
if nebulaConfig == nil {
return nil, errors.New("expected west config")
}
port := nebulaConfig.Listen.Port
ctrl, err := nebula.Main(c, false, Build, opts.Log, opts.DeviceFactory, nil)
if err != nil {
switch v := err.(type) {
case *util.ContextualError:
v.Log(opts.Log)
return nil, v.Unwrap()
default:
// TODO: Move this port error decoration up into harbor
return nil, fmt.Errorf("nebula error on port %d: %w", port, err)
}
}
return &Server{Ctrl: ctrl, opts: opts}, nil
}
func CreateNebulaConfigCtrl(cfg *config.Config, log *logrus.Logger) (*NebulaConfigCtrl, error) {
nebulaYaml, err := configToYaml(cfg)
if err != nil {
return nil, err
}
nebulaYamlStr := string(nebulaYaml)
if l.Log.GetLevel() == zerolog.DebugLevel {
println("CONFIG")
println(nebulaYamlStr)
}
c := nebulaCfg.NewC(log)
// Can use ReloadConfigString to handle static-host-map changes
// c.ReloadConfigString()
// TODO: Could just turn the struct into a record map
// or commit the types upstream.
err = c.LoadString(nebulaYamlStr)
if err != nil {
return nil, fmt.Errorf("failed to load nebula config: %w", err)
}
return c, nil
}
func (s *Server) Listen(ctx context.Context) error {
log := s.opts.Log
port := s.opts.Config.Listen.Port
// Start Nebula Server
s.Ctrl.Start()
// Wait for OnStart hook
if s.opts.OnStart != nil {
s.opts.OnStart(s.Ctrl)
}
// Wait for server to be stopped (context cancelled)
<-ctx.Done()
// Wait for OnShutdown hook
if s.opts.OnShutdown != nil {
s.opts.OnShutdown()
}
log.Infof("Shutting down nebula server on port %d \n", port)
s.Ctrl.Stop()
return nil
}
func (s *Server) IFaceName() string {
return s.Ctrl.Device().Name()
}
func configToYaml(cfg *config.Config) ([]byte, error) {
return yaml.Marshal(cfg)
}