@@ -11,6 +11,31 @@ import (
1111 "github.com/reeflective/team/server/commands"
1212)
1313
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+
1439// main shows how to use a teamserver and teamclient with gRPC backends (transport & RPC).
1540func main () {
1641 // 1) Teamserver & listeners
@@ -77,6 +102,7 @@ func main() {
77102 }
78103}
79104
105+ // mainSmallGRPC is the equivalent of main, without comments.
80106func mainSmallGRPC () {
81107 // Server
82108 gTeamserver := grpc .NewListener ()
@@ -103,41 +129,139 @@ func mainSmallGRPC() {
103129 }
104130}
105131
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 ))
108142 if err != nil {
109143 log .Fatal (err )
110144 }
111145
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+ }
116156
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+ }
119162
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 )
122171 if err != nil {
123172 log .Fatal (err )
124173 }
125174}
126175
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.
127230func 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.
128247 var clientOpts []client.Options
129248 clientOpts = append (clientOpts ,
130249 client .WithInMemory (),
131250 )
132251
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 ... )
138254
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 )
140258
141- func mainCustom () {}
259+ // Generate completions for the tree.
260+ carapace .Gen (serverCmds )
142261
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