client

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: GPL-3.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoTeamclient indicates that the client cannot remotely query a server
	// to get its version or user information, because there is no client RPC
	// to do it. Make sure that your team/client.Client has been given one.
	ErrNoTeamclient = errors.New("this teamclient has no client implementation")

	// ErrConfig is an error related to the teamclient connection configuration.
	ErrConfig = errors.New("client config error")

	// ErrNoConfig indicates that no configuration, default or on file system, was found.
	ErrNoConfig = errors.New("no client configuration was selected or parsed")

	// ErrConfigNoUser says that the configuration has no user,
	// which is not possible even if the client is an in-memory one.
	ErrConfigNoUser = errors.New("client config with empty user")

	// ErrClient indicates an error raised by the client when igniting or connecting.
	// Most errors are raised by the underlying transport stack, which can be user-specific,
	// so users of this library should unwrap ErrClient errors to check against their owns.
	ErrClient = errors.New("teamclient dialer")
)

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the core driver of an application teamclient. It provides the core tools needed by any application/program to be the client of an local/remote/in-memory teamserver.

This client object is by default not connected to any teamserver, and has therefore no way of fulfilling its core duties, on purpose. The client also DOES NOT include any teamserver-side code.

This teamclient core job is to:

  • Fetch, configure and use teamserver endpoint configurations.
  • Drive the process of connecting to & disconnecting from a server.
  • Query a teamserver for its version and users information.

Additionally, this client offers:

  • Pre-configured loggers for all client-side related events.
  • Various options to configure its backends and behaviors.
  • A builtin, abstracted and app-specific filesystem (in memory or on disk).

Various combinations of teamclient/teamserver usage are possible. Please see the Go module example/ directory for a list of them.

func New

func New(app string, options ...Options) (*Client, error)

New is the required constructor of a new application teamclient. Parameters:

  • The name of the application using the teamclient.
  • Variadic options (...Options) which are applied at creation time.

The team.Client backend that answers Users()/VersionServer() is resolved from the options:

  • From the dialer passed with WithDialer(), when that dialer also implements team.Client (the common case for RPC transports).
  • From a backend passed explicitly with WithTeamClient() (used, for instance, by teamserver.Self() so a server can be an in-memory client of itself).

The teamclient will only perform a few init things before being returned:

  • Setup its filesystem, either on-disk (default behavior) or in-memory.
  • Initialize loggers and the files they use, if any.

This may return an error if the teamclient is unable to work with the provided options (or lack thereof), which may happen if the teamclient cannot use and write to its directories and log files. No client is returned if the error is not nil.

func (*Client) Config

func (tc *Client) Config() *Config

Config returns the currently used teamclient server configuration. This configuration might be empty (not nil), if no specific server configuration was loaded by the client yet.

func (*Client) ConfigsDir

func (tc *Client) ConfigsDir() string

ConfigsDir returns the path to the remote teamserver configs directory for this application (~/.app/teamclient/configs), creating the directory if needed, or logging a fatal event if failing to create it.

This uses the on-disk filesystem even if the teamclient is in memory mode.

func (*Client) Connect

func (tc *Client) Connect(options ...Options) (err error)

Connect uses the default client configurations to connect to the teamserver.

This call might be blocking and expect user input: if multiple server configurations are found in the application directory, the application will prompt the user to choose one of them. If the teamclient was created WithConfig() option, or if passed in this call, user input is guaranteed NOT to be needed.

It only connects the teamclient if it has an available dialer. If none is available, this function returns no error, as it is possible that this client has a teamclient implementation ready.

func (*Client) Disconnect

func (tc *Client) Disconnect() error

Disconnect disconnects the client from the server, closing the connection and the client log file. Any errors are logged to this file and returned. If the teamclient has been passed the WithNoDisconnect() option, it won't disconnect.

func (*Client) Filesystem

func (tc *Client) Filesystem() *assets.FS

Filesystem returns an abstract filesystem used by the teamclient. This filesystem can be either of two things:

  • By default, the on-disk filesystem, without any specific bounds.
  • If the teamclient was created with the InMemory() option, a full in-memory filesystem (with root `.app/`).

Use cases for this filesystem might include:

  • The wish to have a fully abstracted filesystem to work for testing
  • Ensuring that the filesystem code in your application remains the same regardless of the underlying, actual filesystem.

The type returned is currently an internal type because it wraps some os.Filesystem methods for working more transparently: this may change in the future if the Go stdlib offers write support to its new io/fs.FS.

func (*Client) GetConfigs

func (tc *Client) GetConfigs() map[string]*Config

GetConfigs returns a list of available configs in the application teamclient remote server configs directory (~/.app/teamclient/configs/).

This uses the on-disk filesystem even if the teamclient is in memory mode.

func (*Client) HomeDir

func (tc *Client) HomeDir() string

HomeDir returns the root application directory (~/.app/ by default). This directory can be set with the environment variable <APP>_ROOT_DIR. This directory is not to be confused with the ~/.app/teamclient directory returned by the client.TeamDir(), which is specific to the app teamclient.

func (*Client) LogsDir

func (tc *Client) LogsDir() string

LogsDir returns the directory of the teamclient logs (~/.app/logs), creating the directory if needed, or logging a fatal event if failing to create it.

func (*Client) Name

func (tc *Client) Name() string

Name returns the name of the client application.

func (*Client) NamedLogger

func (tc *Client) NamedLogger(pkg, stream string) *slog.Logger

NamedLogger returns a new logger tagged with a package/domain and a more precise flow/stream. The events are logged according to the teamclient logging backend setup.

func (*Client) NewTLSConfigFrom

func (tc *Client) NewTLSConfigFrom(caCert string, cert string, key string) (*tls.Config, error)

NewTLSConfigFrom generates a working client TLS configuration prepared for Mutual TLS. It requires the three credential materials presents in any user remote teamserver config.

func (*Client) ReadConfig

func (tc *Client) ReadConfig(confFilePath string) (*Config, error)

ReadConfig loads a client config into a struct. Errors are returned as is: users can check directly for JSON/encoding/filesystem errors.

This uses the on-disk filesystem even if the teamclient is in memory mode.

func (*Client) SaveConfig

func (tc *Client) SaveConfig(config *Config) error

SaveConfig saves a client config to disk.

This uses the on-disk filesystem even if the teamclient is in memory mode.

func (*Client) SelectConfig

func (tc *Client) SelectConfig() *Config

SelectConfig either returns the only configuration found in the app client remote configs directory, or prompts the user to select one. This call might thus be blocking, and expect user input.

This uses the on-disk filesystem even if the teamclient is in memory mode.

func (*Client) SetLogFormat added in v0.3.0

func (tc *Client) SetLogFormat(format log.Format)

SetLogFormat rebuilds the teamclient console stream in the given format (log.FormatConsole/Text/JSON). The file logger stays plain text. Intended for use at startup (eg. from the teamclient `--log-format` flag).

func (*Client) SetLogLevel

func (tc *Client) SetLogLevel(level int)

SetLogLevel sets the logging level of all teamclient loggers.

func (*Client) SetLogWriter

func (tc *Client) SetLogWriter(stdout, stderr io.Writer)

SetLogWriter sets the streams to which the console logger (not the file logger) should write. This is used by the teamclient cobra command tree to synchronize its stdout/stderr with the teamclient backend.

func (*Client) TeamDir

func (tc *Client) TeamDir() string

TeamDir returns the teamclient directory of the app (named ~/.<app>/teamclient/), creating the directory if needed, or logging an error event if failing to create it. This directory is used to store teamclient logs and remote server configs.

func (*Client) Users

func (tc *Client) Users() (users []team.User, err error)

Users returns a list of all users registered to the application server. If the teamclient has no backend, it returns an ErrNoTeamclient error. If the backend returns an error, the latter is returned as is.

func (*Client) VersionClient

func (tc *Client) VersionClient() (ver team.Version, err error)

VersionClient returns the version information of the client, and thus does not require the teamclient to be connected to a teamserver.

This is always computed locally from the client binary's own build information: a client reporting its own version never needs to reach a peer, so this call never traverses the transport backend.

func (*Client) VersionServer

func (tc *Client) VersionServer() (ver team.Version, err error)

VersionServer returns the version information of the server to which the client is connected. If the teamclient has no backend, it returns an ErrNoTeamclient error. If the backend returns an error, the latter is returned as is.

type Config

type Config struct {
	User          string `json:"user"` // This value is actually ignored for the most part (cert CN is used instead)
	Host          string `json:"host"`
	Port          int    `json:"port"`
	Token         string `json:"token"`
	CACertificate string `json:"ca_certificate"`
	PrivateKey    string `json:"private_key"`
	Certificate   string `json:"certificate"`
}

Config is a JSON client connection configuration. It contains the addresses of a team server, the name of the user allowed to connect to it, and cryptographic material to secure and authenticate the client-server connection (using Mutual TLS).

type Dialer

type Dialer interface {
	// Init is used by any dialer to query the teamclient driving it about:
	//   - The remote teamserver address and transport credentials
	//   - The user registered in this remote teamserver configuration.
	//   - To make use of client-side loggers, filesystem and other utilities.
	Init(c *Client) error

	// Dial should connect to the endpoint available in any
	// of the client remote teamserver configurations.
	Dial() error

	// Close should close the connection or any related component.
	Close() error
}

Dialer represents a type using a teamclient core (and its configured teamserver remote) to setup, initiate and use a connection to this remote teamserver.

A dialer will very often also implement the team.Client interface (Users and VersionServer), since the connection it dials is what answers those queries. In that case the teamclient core uses the dialer as its backend automatically, so there is no need to register it twice: WithDialer() alone is enough. Only pass a separate backend with WithTeamClient() if it is a distinct object.

Init is a transport-agnostic preparation phase, Dial the transport-specific binding phase; keeping them separate lets implementations compose by embedding a base dialer and overriding only Dial().

type Options

type Options func(opts *opts)

Options are client options. You can set or modify the behavior of a teamclient at various steps with these options, which are a variadic parameter of several client.Client methods. Note that some options can only be used once, while others can be used multiple times. Examples of the former are log files, while the latter includes dialers/hooks. Each option will specify this in its description.

func WithConfig

func WithConfig(config *Config) Options

WithConfig sets the client to use a given remote teamserver configuration which to connect to, instead of using default on-disk user/application configurations. This function will be very useful to library users who wish to implement specific remote teamserver selection & connection strategies, depending on the domains and use cases of these tools.

func WithConsoleOptions added in v0.3.0

func WithConsoleOptions(style func(*log.ConsoleOptions)) Options

WithConsoleOptions restyles the built-in console logger (level markers/colors, package/time/message colors, column widths, timestamp) while KEEPING the default console+file loggers and their runtime level control. The callback receives the console options pre-filled with the library defaults; tweak only what you want. Use this instead of WithLogger when you want the team look with small changes rather than a completely custom backend.

This option can only be used once, and should be passed client.New().

func WithDialer

func WithDialer(dialer Dialer) Options

WithDialer sets a custom dialer to connect to the teamserver. See the Dialer type documentation for implementation/usage details.

If the dialer also implements the team.Client interface (Users and VersionServer, the common case for RPC transports), it is automatically used as the teamclient backend as well, so you do not need to register it twice. Use WithTeamClient() only to provide a backend that is a distinct object.

This option can be used multiple times, either when using team/client.New() or when using the teamclient.Connect() method.

func WithHomeDirectory

func WithHomeDirectory(path string) Options

WithHomeDirectory sets the default path (~/.app/) of the application directory. This path can still be overridden at the user-level with the env var APP_ROOT_DIR.

This option can only be used once, and must be passed client.New().

func WithInMemory

func WithInMemory() Options

WithInMemory deactivates all interactions of the client with the on-disk filesystem. This will in effect use in-memory files for all file-based logging and database data. This might be useful for testing, or if you happen to embed a teamclient in a program without the intent of using it now, etc.

This option can only be used once, and should be passed client.New().

func WithLogFile

func WithLogFile(filePath string) Options

WithLogFile sets the path to the file where teamclient logging should be done. If not specified, the client log file is ~/.app/teamclient/logs/app.teamclient.log.

This option can only be used once, and should be passed client.New().

func WithLogFormat added in v0.3.0

func WithLogFormat(format log.Format) Options

WithLogFormat selects how the teamclient console/stdout stream is rendered: log.FormatConsole (default, aligned+colored), log.FormatText (logfmt) or log.FormatJSON (structured). The file logger always stays plain text. This is the programmatic equivalent of the teamclient `--log-format` CLI flag.

This option can only be used once, and should be passed client.New().

func WithLogger

func WithLogger(handler slog.Handler) Options

WithLogger sets the teamclient to use a specific slog.Handler as its sole logging backend, in place of the default console+file loggers. Since the handler fully controls formatting and routing, the teamclient's runtime level/output controls (SetLogLevel/SetLogWriter) do not apply to it.

This option can only be used once, and should be passed client.New().

func WithNoDisconnect

func WithNoDisconnect() Options

WithNoDisconnect is meant to be used when the teamclient commands are used in a closed-loop (readline-style) application, where the connection is used more than once in the lifetime of the Go program. If this is the case, this option will ensure that any cobra client command runners produced by this library will not disconnect after each execution.

This option can only be used once, and should be passed client.New().

func WithNoLogs

func WithNoLogs(noLogs bool) Options

WithNoLogs deactivates all logging normally done by the teamclient if noLogs is set to true, or keeps/reestablishes them if false.

This option can only be used once, and should be passed client.New().

func WithTeamClient added in v0.3.0

func WithTeamClient(client team.Client) Options

WithTeamClient sets the team.Client backend answering the teamclient core Users() and VersionServer() calls. This is only needed when the backend is a distinct object from the dialer (a dialer that also implements team.Client is picked up automatically by WithDialer). It is used, for example, by teamserver.Self() so that a teamserver can be an in-memory client of itself.

This option can be used multiple times, either when using team/client.New() or when using the teamclient.Connect() method.

func WithTeamDirectory

func WithTeamDirectory(name string) Options

WithTeamDirectory sets the name (not a path) of the teamclient-specific subdirectory. For example, passing "my_team_dir" will make the teamclient use ~/.app/my_team_dir/ instead of ~/.app/teamclient/. If this function is called with an empty string, the teamclient will not use any subdirectory for its own outputs, thus using ~/.app as its teamclient directory.

This option can only be used once, and should be passed client.New().

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL