@@ -11,6 +11,31 @@ import (
11
11
"github.com/reeflective/team/server/commands"
12
12
)
13
13
14
+ // mainSmallest is the smallest example of a teamserver usage.
15
+ // The latter can only serve itself in-memory, since there are no
16
+ // remote teamserver listener stacks registered with it. Still, the
17
+ // teamserver functionality is complete and works identically regardless.
18
+ func mainSmallest () {
19
+ teamserver , err := server .New ("smallserver" )
20
+ if err != nil {
21
+ log .Fatal (err )
22
+ }
23
+
24
+ // Generate a tree of server-side commands: this tree also has client-only
25
+ // commands as a subcommand "client" of the "teamserver" command root here.
26
+ serverCmds := commands .Generate (teamserver , teamserver .Self ())
27
+ serverCmds .Use = "smallserver"
28
+
29
+ // Generate completions for the tree.
30
+ carapace .Gen (serverCmds )
31
+
32
+ // Run our teamserver binary.
33
+ err = serverCmds .Execute ()
34
+ if err != nil {
35
+ log .Fatal (err )
36
+ }
37
+ }
38
+
14
39
// main shows how to use a teamserver and teamclient with gRPC backends (transport & RPC).
15
40
func main () {
16
41
// 1) Teamserver & listeners
@@ -77,6 +102,7 @@ func main() {
77
102
}
78
103
}
79
104
105
+ // mainSmallGRPC is the equivalent of main, without comments.
80
106
func mainSmallGRPC () {
81
107
// Server
82
108
gTeamserver := grpc .NewListener ()
@@ -103,41 +129,139 @@ func mainSmallGRPC() {
103
129
}
104
130
}
105
131
106
- func mainSmallest () {
107
- teamserver , err := server .New ("smallserver" )
132
+ // mainNoCommands illustrates the fact (without much proof and code) that the teamclient
133
+ // and teamserver toolsets are not restrained to CLI usage nor have any obligation to use
134
+ // and expose themselves via a CLI.
135
+ // On the other hand, some programs may wish to offer it in specific circumstances, or even
136
+ // make use of it on the teamclient-side but not on the teamserver. Many setups are possible.
137
+ func mainNoCommands () {
138
+ // Server
139
+ gTeamserver := grpc .NewListener ()
140
+
141
+ teamserver , err := server .New ("teamserver" , server .WithListener (gTeamserver ))
108
142
if err != nil {
109
143
log .Fatal (err )
110
144
}
111
145
112
- // Generate a tree of server-side commands: this tree also has client-only
113
- // commands as a subcommand "client" of the "teamserver" command root here.
114
- serverCmds := commands .Generate (teamserver , teamserver .Self ())
115
- serverCmds .Use = "smallserver"
146
+ // Note that we don't create a self-client for the teamserver: we don't need to have
147
+ // any teamclient interaction with the teamserver, and we just want to start/stop it
148
+ // from our code.
149
+ //
150
+ // Instead, let's first start a listener job on some address: this call is non blocking,
151
+ // and should we want to keep control of the listener job, we can use the returned ID.
152
+ listenerID , err := teamserver .ServeAddr ("grpc/mTLS" , "localhost" , 31350 )
153
+ if err != nil {
154
+ log .Fatal (err )
155
+ }
116
156
117
- // Generate completions for the tree.
118
- carapace .Gen (serverCmds )
157
+ // We can kill the listener from code like this.
158
+ err = teamserver .ListenerClose (listenerID )
159
+ if err != nil {
160
+ log .Fatal (err )
161
+ }
119
162
120
- // Run our teamserver binary.
121
- err = serverCmds .Execute ()
163
+ // Finally, simply ask the server to start the daemon (blocking), which also starts
164
+ // all listeners that might be saved as persistent jobs. To be noted, you will typically
165
+ // favor the above ServeAddr() function in your code rather than the daemon one below,
166
+ // since -while being entirely possible- the latter will likely be favored by CLI users.
167
+ //
168
+ // Note that we don't pass the name of the listener stack we want to use: the daemon
169
+ // function always uses the first listener backend that has been registered to the server.
170
+ err = teamserver .ServeDaemon ("localhost" , 31350 )
122
171
if err != nil {
123
172
log .Fatal (err )
124
173
}
125
174
}
126
175
176
+ // mainIntegrated demonstrates a use case where the library user might already have an existing,
177
+ // established and/or working program. This program will naturally already dispose of core things
178
+ // like loggers, database configurations or backends, specific directories for output, etc.
179
+ //
180
+ // This example therefore shows how to use some other options to tightly integrate the teamserver
181
+ // toolset to such programs, while maintaining a strictly identical behavior and function set.
182
+ //
183
+ // Note that we use nil pointers everywhere in those functions, so this function is very much
184
+ // unsafe to run as is. It should be noted again, however, that the library tries to fail safe
185
+ // and as early as possible, as illustrated by the various errors returned in examples above.
186
+ func mainIntegrated () {
187
+ // Use the classic gRPC example backend.
188
+ gTeamserver := grpc .NewListener ()
189
+
190
+ var serverOpts []server.Options
191
+ serverOpts = append (serverOpts ,
192
+ // Filesystem
193
+ server .WithHomeDirectory ("~/.config" ), // If we use an appdirectory different from ~/.app/directory .
194
+ server .WithTeamDirectory ("" ), // We might want the teamserver-specific output not to use a specific subdir in it.
195
+
196
+ // Logging.
197
+ server .WithLogger (nil ), // We might have a fully set-up logger, with multiple output destinations.
198
+ server .WithLogFile ("path/to/log.file" ), // Or we are fine with default teamserver logger, but a specific file.
199
+
200
+ // Network (listeners and settings).
201
+ server .WithDefaultPort (31340 ), // Default port of daemon/listeners.
202
+ server .WithListener (gTeamserver ), // Please see above examples, and the documentation. Any number of them can be registered.
203
+ server .WithListener (nil ), // Another listener/RPC backend stack used/needed by your application.
204
+
205
+ // Database (stores users certificates)
206
+ server .WithDatabase (nil ), // Either pass the teamserver a running DB to store/fetch users certificates data.
207
+ server .WithDatabaseConfig (nil ), // Or a specific configuration to use for connecting to one.
208
+ )
209
+
210
+ // Pass those options at creation time: some of them cannot be passed later,
211
+ // while others can (eg, listener backends can be added and listener configs
212
+ // chosen at any time).
213
+ teamserver , err := server .New ("teamserver" , serverOpts ... )
214
+ if err != nil {
215
+ log .Fatal (err )
216
+ }
217
+
218
+ // Again, note that we don't pass the name of the listener stack we want to use: the daemon
219
+ // function always uses the first listener backend that has been registered to the server.
220
+ err = teamserver .ServeDaemon ("localhost" , 31350 )
221
+ if err != nil {
222
+ log .Fatal (err )
223
+ }
224
+ }
225
+
226
+ // mainInMemory adapts the mainSmallest example with options to instruct the teamserver
227
+ // to never touch the host filesystem: all filesystem calls are redirected to an in-memory
228
+ // filesystem (which therefore holds all log files and contents in memory), and an in-memory
229
+ // SQLite database instance.
127
230
func mainInMemory () {
231
+ var serverOpts []server.Options
232
+ serverOpts = append (serverOpts ,
233
+ server .WithInMemory (),
234
+ server .WithDefaultPort (31340 ), // Default port of daemon/listeners.
235
+ )
236
+
237
+ // Pass those options at creation time: some of them cannot be passed later,
238
+ // while others can (eg, listener backends can be added and listener configs
239
+ // chosen at any time).
240
+ teamserver , err := server .New ("teamserver" , serverOpts ... )
241
+ if err != nil {
242
+ log .Fatal (err )
243
+ }
244
+
245
+ // Pass specific options for the teamserver
246
+ // self-client, to provide identical behavior.
128
247
var clientOpts []client.Options
129
248
clientOpts = append (clientOpts ,
130
249
client .WithInMemory (),
131
250
)
132
251
133
- var serverOpts []client.Options
134
- serverOpts = append (serverOpts ,
135
- client .WithInMemory (),
136
- )
137
- }
252
+ // Ask the teamserver to create its own teamclient (without any RPC client backend).
253
+ teamclient := teamserver .Self (clientOpts ... )
138
254
139
- func mainIntegrated () {}
255
+ // Generate a tree of server-side commands: this tree also has client-only
256
+ // commands as a subcommand "client" of the "teamserver" command root here.
257
+ serverCmds := commands .Generate (teamserver , teamclient )
140
258
141
- func mainCustom () {}
259
+ // Generate completions for the tree.
260
+ carapace .Gen (serverCmds )
142
261
143
- func mainNoCommands () {}
262
+ // Run our teamserver binary.
263
+ err = serverCmds .Execute ()
264
+ if err != nil {
265
+ log .Fatal (err )
266
+ }
267
+ }
0 commit comments