Documentation ¶
Overview ¶
package casket implements the Casket server manager.
To use this package:
- Set the AppName and AppVersion variables.
- Call LoadCasketfile() to get the Casketfile. Pass in the name of the server type (like "http"). Make sure the server type's package is imported (import _ "github.com/tmpim/casket/caskethttp").
- Call casket.Start() to start Casket. You get back an Instance, on which you can call Restart() to restart it or Stop() to stop it.
You should call Wait() on your instance to wait for all servers to quit before your process exits.
Index ¶
- Constants
- Variables
- func AssetsPath() string
- func DescribePlugins() string
- func EmitEvent(event EventName, info interface{})
- func IsInternal(addr string) bool
- func IsLoopback(addr string) bool
- func IsUpgrade() bool
- func ListPlugins() map[string][]string
- func RegisterCasketfileLoader(name string, loader Loader)
- func RegisterEventHook(name string, hook EventHook)
- func RegisterParsingCallback(serverType, afterDir string, callback ParsingCallback)
- func RegisterPlugin(name string, plugin Plugin)
- func RegisterServerType(typeName string, srv ServerType)
- func SetDefaultCasketfileLoader(name string, loader Loader)
- func SplitCommandAndArgs(command string) (cmd string, args []string, err error)
- func Started() bool
- func Stop() error
- func TrapSignals()
- func Upgrade() error
- func ValidDirectives(serverType string) []string
- func ValidateAndExecuteDirectives(cdyfile Input, inst *Instance, justValidate bool) error
- type AfterStartup
- type CasketfileInput
- type Context
- type Controller
- func (c *Controller) Context() Context
- func (c *Controller) Get(key interface{}) interface{}
- func (c *Controller) OnFinalShutdown(fn func() error)
- func (c *Controller) OnFirstStartup(fn func() error)
- func (c *Controller) OnRestart(fn func() error)
- func (c *Controller) OnRestartFailed(fn func() error)
- func (c *Controller) OnShutdown(fn func() error)
- func (c *Controller) OnStartup(fn func() error)
- func (c *Controller) ServerType() string
- func (c *Controller) Set(key, val interface{})
- type CtxKey
- type EventHook
- type EventName
- type GracefulServer
- type Input
- type Instance
- func (i *Instance) Casketfile() Input
- func (i *Instance) Restart(newCasketfile Input) (*Instance, error)
- func (i *Instance) SaveServer(s Server, ln net.Listener)
- func (i *Instance) Servers() []ServerListener
- func (i *Instance) ShutdownCallbacks() []error
- func (i *Instance) Stop() error
- func (i *Instance) Wait()
- type Listener
- type Loader
- type LoaderFunc
- type PacketConn
- type ParsingCallback
- type Plugin
- type Server
- type ServerListener
- type ServerType
- type SetupFunc
- type Stopper
- type TCPServer
- type UDPServer
Examples ¶
Constants ¶
const ( StartupEvent EventName = "startup" ShutdownEvent = "shutdown" CertRenewEvent = "certrenew" InstanceStartupEvent = "instancestartup" InstanceRestartEvent = "instancerestart" )
Define names for the various events
Variables ¶
var ( // AppName is the name of the application. AppName string // AppVersion is the version of the application. AppVersion string // Quiet mode will not show any informative output on initialization. Quiet bool // PidFile is the path to the pidfile to create. PidFile string // GracefulTimeout is the maximum duration of a graceful shutdown. GracefulTimeout time.Duration )
Configurable application parameters
var ( // DefaultConfigFile is the name of the configuration file that is loaded // by default if no other file is specified. DefaultConfigFile = "Casketfile" )
var OnProcessExit []func()
OnProcessExit is a list of functions to run when the process exits -- they are ONLY for cleanup and should not block, return errors, or do anything fancy. They will be run with every signal, even if "shutdown callbacks" are not executed. This variable must only be modified in the main goroutine from init() functions.
Functions ¶
func AssetsPath ¶
func AssetsPath() string
AssetsPath returns the path to the folder where the application may store data. If CASKETPATH env variable is set, that value is used. Otherwise, the path is the result of evaluating "$HOME/.casket".
func DescribePlugins ¶
func DescribePlugins() string
DescribePlugins returns a string describing the registered plugins.
func EmitEvent ¶ added in v0.10.0
func EmitEvent(event EventName, info interface{})
EmitEvent executes the different hooks passing the EventType as an argument. This is a blocking function. Hook developers should use 'go' keyword if they don't want to block Casket.
func IsInternal ¶ added in v0.10.0
IsInternal returns true if the IP of addr belongs to a private network IP range. addr must only be an IP or an IP:port combination. Loopback addresses are considered false.
func IsLoopback ¶
IsLoopback returns true if the hostname of addr looks explicitly like a common local hostname. addr must only be a host or a host:port combination.
func IsUpgrade ¶
func IsUpgrade() bool
IsUpgrade returns true if this process is part of an upgrade where a parent casket process spawned this one to upgrade the binary.
func ListPlugins ¶ added in v0.11.0
ListPlugins makes a list of the registered plugins, keyed by plugin type.
func RegisterCasketfileLoader ¶ added in v1.1.0
RegisterCasketfileLoader registers loader named name.
func RegisterEventHook ¶ added in v0.10.0
RegisterEventHook plugs in hook. All the hooks should register themselves and they must have a name.
func RegisterParsingCallback ¶
func RegisterParsingCallback(serverType, afterDir string, callback ParsingCallback)
RegisterParsingCallback registers callback to be called after executing the directive afterDir for server type serverType.
func RegisterPlugin ¶
RegisterPlugin plugs in plugin. All plugins should register themselves, even if they do not perform an action associated with a directive. It is important for the process to know which plugins are available.
The plugin MUST have a name: lower case and one word. If this plugin has an action, it must be the name of the directive that invokes it. A name is always required and must be unique for the server type.
func RegisterServerType ¶
func RegisterServerType(typeName string, srv ServerType)
RegisterServerType registers a server type srv by its name, typeName.
func SetDefaultCasketfileLoader ¶ added in v1.1.0
SetDefaultCasketfileLoader registers loader by name as the default Casketfile loader if no others produce a Casketfile. If another Casketfile loader has already been set as the default, this replaces it.
Do not call RegisterCasketfileLoader on the same loader; that would be redundant.
func SplitCommandAndArgs ¶
SplitCommandAndArgs takes a command string and parses it shell-style into the command and its separate arguments.
Example ¶
var commandLine string var command string var args []string // just for the test - change GOOS and reset it at the end of the test runtimeGoos = "windows" defer func() { runtimeGoos = runtime.GOOS }() commandLine = `mkdir /P "C:\Program Files"` command, args, _ = SplitCommandAndArgs(commandLine) fmt.Printf("Windows: %s: %s [%s]\n", commandLine, command, strings.Join(args, ",")) // set GOOS to linux runtimeGoos = "linux" commandLine = `mkdir -p /path/with\ space` command, args, _ = SplitCommandAndArgs(commandLine) fmt.Printf("Linux: %s: %s [%s]\n", commandLine, command, strings.Join(args, ","))
Output: Windows: mkdir /P "C:\Program Files": mkdir [/P,C:\Program Files] Linux: mkdir -p /path/with\ space: mkdir [-p,/path/with space]
func Started ¶ added in v0.9.1
func Started() bool
Started returns true if at least one instance has been started by this package. It never gets reset to false once it is set to true.
func Stop ¶
func Stop() error
Stop stops ALL servers. It blocks until they are all stopped. It does NOT execute shutdown callbacks, and it deletes all instances after stopping is completed. Do not re-use any references to old instances after calling Stop.
func TrapSignals ¶
func TrapSignals()
TrapSignals create signal handlers for all applicable signals for this system. If your Go program uses signals, this is a rather invasive function; best to implement them yourself in that case. Signals are not required for the casket package to function properly, but this is a convenient way to allow the user to control this part of your program.
func Upgrade ¶
func Upgrade() error
Upgrade re-launches the process, preserving the listeners for a graceful upgrade. It does NOT load new configuration; it only starts the process anew with the current config. This makes it possible to perform zero-downtime binary upgrades.
TODO: For more information when debugging, see: https://forum.golangbridge.org/t/bind-address-already-in-use-even-after-listener-closed/1510?u=matt https://github.com/mholt/shared-conn
func ValidDirectives ¶
ValidDirectives returns the list of all directives that are recognized for the server type serverType. However, not all directives may be installed. This makes it possible to give more helpful error messages, like "did you mean ..." or "maybe you need to plug in ...".
func ValidateAndExecuteDirectives ¶ added in v0.9.5
ValidateAndExecuteDirectives will load the server blocks from cdyfile by parsing it, then execute the directives configured by it and store the resulting server blocks into inst. If justValidate is true, parse callbacks will not be executed between directives, since the purpose is only to check the input for valid syntax.
Types ¶
type AfterStartup ¶
type AfterStartup interface {
OnStartupComplete()
}
AfterStartup is an interface that can be implemented by a server type that wants to run some code after all servers for the same Instance have started.
type CasketfileInput ¶ added in v1.1.0
CasketfileInput represents a Casketfile as input and is simply a convenient way to implement the Input interface.
func (CasketfileInput) Body ¶ added in v1.1.0
func (c CasketfileInput) Body() []byte
Body returns c.Contents.
func (CasketfileInput) Path ¶ added in v1.1.0
func (c CasketfileInput) Path() string
Path returns c.Filepath.
func (CasketfileInput) ServerType ¶ added in v1.1.0
func (c CasketfileInput) ServerType() string
ServerType returns c.ServerType.
type Context ¶
type Context interface { // Called after the Casketfile is parsed into server // blocks but before the directives are executed, // this method gives you an opportunity to inspect // the server blocks and prepare for the execution // of directives. Return the server blocks (which // you may modify, if desired) and an error, if any. // The first argument is the name or path to the // configuration file (Casketfile). // // This function can be a no-op and simply return its // input if there is nothing to do here. InspectServerBlocks(string, []casketfile.ServerBlock) ([]casketfile.ServerBlock, error) // This is what Casket calls to make server instances. // By this time, all directives have been executed and, // presumably, the context has enough state to produce // server instances for Casket to start. MakeServers() ([]Server, error) }
Context is a type which carries a server type through the load and setup phase; it maintains the state between loading the Casketfile, then executing its directives, then making the servers for Casket to manage. Typically, such state involves configuration structs, etc.
type Controller ¶
type Controller struct { casketfile.Dispenser // Key is the key from the top of the server block, usually // an address, hostname, or identifier of some sort. Key string // OncePerServerBlock is a function that executes f // exactly once per server block, no matter how many // hosts are associated with it. If it is the first // time, the function f is executed immediately // (not deferred) and may return an error which is // returned by OncePerServerBlock. OncePerServerBlock func(f func() error) error // ServerBlockIndex is the 0-based index of the // server block as it appeared in the input. ServerBlockIndex int // ServerBlockKeyIndex is the 0-based index of this // key as it appeared in the input at the head of the // server block. ServerBlockKeyIndex int // ServerBlockKeys is a list of keys that are // associated with this server block. All these // keys, consequently, share the same tokens. ServerBlockKeys []string // ServerBlockStorage is used by a directive's // setup function to persist state between all // the keys on a server block. ServerBlockStorage interface{} // contains filtered or unexported fields }
Controller is given to the setup function of directives which gives them access to be able to read tokens with which to configure themselves. It also stores state for the setup functions, can get the current context, and can be used to identify a particular server block using the Key field.
func NewTestController ¶
func NewTestController(serverType, input string) *Controller
NewTestController creates a new Controller for the server type and input specified. The filename is "Testfile". If the server type is not empty and is plugged in, a context will be created so that the results of setup functions can be checked for correctness.
Used only for testing, but exported so plugins can use this for convenience.
func (*Controller) Context ¶
func (c *Controller) Context() Context
Context gets the context associated with the instance associated with c.
func (*Controller) Get ¶ added in v0.10.11
func (c *Controller) Get(key interface{}) interface{}
Get safely gets a value from the Instance's storage.
func (*Controller) OnFinalShutdown ¶
func (c *Controller) OnFinalShutdown(fn func() error)
OnFinalShutdown adds fn to the list of callback functions to execute when the server is about to be shut down NOT as part of a restart.
func (*Controller) OnFirstStartup ¶
func (c *Controller) OnFirstStartup(fn func() error)
OnFirstStartup adds fn to the list of callback functions to execute when the server is about to be started NOT as part of a restart.
func (*Controller) OnRestart ¶
func (c *Controller) OnRestart(fn func() error)
OnRestart adds fn to the list of callback functions to execute when the server is about to be restarted.
func (*Controller) OnRestartFailed ¶ added in v0.11.1
func (c *Controller) OnRestartFailed(fn func() error)
OnRestartFailed adds fn to the list of callback functions to execute if the server failed to restart.
func (*Controller) OnShutdown ¶
func (c *Controller) OnShutdown(fn func() error)
OnShutdown adds fn to the list of callback functions to execute when the server is about to be shut down (including restarts).
func (*Controller) OnStartup ¶
func (c *Controller) OnStartup(fn func() error)
OnStartup adds fn to the list of callback functions to execute when the server is about to be started (including restarts).
func (*Controller) ServerType ¶
func (c *Controller) ServerType() string
ServerType gets the name of the server type that is being set up.
func (*Controller) Set ¶ added in v0.10.11
func (c *Controller) Set(key, val interface{})
Set safely sets a value on the Instance's storage.
type CtxKey ¶ added in v0.10.0
type CtxKey string
CtxKey is a value type for use with context.WithValue.
type EventHook ¶ added in v0.10.0
EventHook is a type which holds information about a startup hook plugin.
type EventName ¶ added in v0.10.0
type EventName string
EventName represents the name of an event used with event hooks.
type GracefulServer ¶
type GracefulServer interface { Server Stopper // Address returns the address the server should // listen on; it is used to pair the server to // its listener during a graceful/zero-downtime // restart. Thus when implementing this method, // you must not access a listener to get the // address; you must store the address the // server is to serve on some other way. Address() string // WrapListener wraps a listener with the // listener middlewares configured for this // server, if any. WrapListener(net.Listener) net.Listener }
GracefulServer is a Server and Stopper, the stopping of which is graceful (whatever that means for the kind of server being implemented). It must be able to return the address it is configured to listen on so that its listener can be paired with it upon graceful restarts. The net.Listener that a GracefulServer creates must implement the Listener interface for restarts to be graceful (assuming the listener is for TCP).
type Input ¶
type Input interface { // Gets the Casketfile contents Body() []byte // Gets the path to the origin file Path() string // The type of server this input is intended for ServerType() string }
Input represents a Casketfile; its contents and file path (which should include the file name at the end of the path). If path does not apply (e.g. piped input) you may use any understandable value. The path is mainly used for logging, error messages, and debugging.
func CasketfileFromPipe ¶ added in v1.1.0
CasketfileFromPipe loads the Casketfile input from f if f is not interactive input. f is assumed to be a pipe or stream, such as os.Stdin. If f is not a pipe, no error is returned but the Input value will be nil. An error is only returned if there was an error reading the pipe, even if the length of what was read is 0.
func DefaultInput ¶
DefaultInput returns the default Casketfile input to use when it is otherwise empty or missing. It uses the default host and port (depends on host, e.g. localhost is 2015, otherwise 443) and root.
func LoadCasketfile ¶ added in v1.1.0
LoadCasketfile loads a Casketfile by calling the plugged in Casketfile loader methods. An error is returned if more than one loader returns a non-nil Casketfile input. If no loaders load a Casketfile, the default loader is used. If no default loader is registered or it returns nil, the server type's default Casketfile is loaded. If the server type does not specify any default Casketfile value, then an empty Casketfile is returned. Consequently, this function never returns a nil value as long as there are no errors.
type Instance ¶
type Instance struct { // these callbacks execute when certain events occur OnFirstStartup []func() error // starting, not as part of a restart OnStartup []func() error // starting, even as part of a restart OnRestart []func() error // before restart commences OnRestartFailed []func() error // if restart failed OnShutdown []func() error // stopping, even as part of a restart OnFinalShutdown []func() error // stopping, not as part of a restart // storing values on an instance is preferable to // global state because these will get garbage- // collected after in-process reloads when the // old instances are destroyed; use StorageMu // to access this value safely Storage map[interface{}]interface{} StorageMu sync.RWMutex // contains filtered or unexported fields }
Instance contains the state of servers created as a result of calling Start and can be used to access or control those servers. It is literally an instance of a server type. Instance values should NOT be copied. Use *Instance for safety.
func Instances ¶ added in v0.10.11
func Instances() []*Instance
Instances returns the list of instances.
func Start ¶
Start starts Casket with the given Casketfile.
This function blocks until all the servers are listening.
func (*Instance) Casketfile ¶ added in v1.1.0
Casketfile returns the Casketfile used to create i.
func (*Instance) Restart ¶
Restart replaces the servers in i with new servers created from executing the newCasketfile. Upon success, it returns the new instance to replace i. Upon failure, i will not be replaced.
func (*Instance) SaveServer ¶
SaveServer adds s and its associated listener ln to the internally-kept list of servers that is running. For saved servers, graceful restarts will be provided.
func (*Instance) Servers ¶ added in v0.9.2
func (i *Instance) Servers() []ServerListener
Servers returns the ServerListeners in i.
func (*Instance) ShutdownCallbacks ¶
ShutdownCallbacks executes all the shutdown callbacks of i, including ones that are scheduled only for the final shutdown of i. An error returned from one does not stop execution of the rest. All the non-nil errors will be returned.
type Listener ¶
Listener is a net.Listener with an underlying file descriptor. A server's listener should implement this interface if it is to support zero-downtime reloads.
type Loader ¶
Loader is a type that can load a Casketfile. It is passed the name of the server type. It returns an error only if something went wrong, not simply if there is no Casketfile for this loader to load.
A Loader should only load the Casketfile if a certain condition or requirement is met, as returning a non-nil Input value along with another Loader will result in an error. In other words, loading the Casketfile must be deliberate & deterministic, not haphazard.
The exception is the default Casketfile loader, which will be called only if no other Casketfile loaders return a non-nil Input. The default loader may always return an Input value.
type LoaderFunc ¶
LoaderFunc is a convenience type similar to http.HandlerFunc that allows you to use a plain function as a Load() method.
type PacketConn ¶
type PacketConn interface { net.PacketConn File() (*os.File, error) }
PacketConn is a net.PacketConn with an underlying file descriptor. A server's packetconn should implement this interface if it is to support zero-downtime reloads (in sofar this holds true for datagram connections).
type ParsingCallback ¶
ParsingCallback is a function that is called after a directive's setup functions have been executed for all the server blocks.
type Plugin ¶
type Plugin struct { // ServerType is the type of server this plugin is for. // Can be empty if not applicable, or if the plugin // can associate with any server type. ServerType string // Action is the plugin's setup function, if associated // with a directive in the Casketfile. Action SetupFunc }
Plugin is a type which holds information about a plugin.
type Server ¶
Server is a type that can listen and serve. It supports both TCP and UDP, although the UDPServer interface can be used for more than just UDP.
If the server uses TCP, it should implement TCPServer completely. If it uses UDP or some other protocol, it should implement UDPServer completely. If it uses both, both interfaces should be fully implemented. Any unimplemented methods should be made as no-ops that simply return nil values.
type ServerListener ¶ added in v0.9.2
type ServerListener struct {
// contains filtered or unexported fields
}
ServerListener pairs a server to its listener and/or packetconn.
func (ServerListener) Addr ¶ added in v0.9.2
func (s ServerListener) Addr() net.Addr
Addr returns the listener's network address. It returns nil when it is not set.
func (ServerListener) LocalAddr ¶ added in v0.9.2
func (s ServerListener) LocalAddr() net.Addr
LocalAddr returns the local network address of the packetconn. It returns nil when it is not set.
type ServerType ¶
type ServerType struct { // Function that returns the list of directives, in // execution order, that are valid for this server // type. Directives should be one word if possible // and lower-cased. Directives func() []string // DefaultInput returns a default config input if none // is otherwise loaded. This is optional, but highly // recommended, otherwise a blank Casketfile will be // used. DefaultInput func() Input // The function that produces a new server type context. // This will be called when a new Casketfile is being // loaded, parsed, and executed independently of any // startup phases before this one. It's a way to keep // each set of server instances separate and to reduce // the amount of global state you need. NewContext func(inst *Instance) Context }
ServerType contains information about a server type.
type SetupFunc ¶
type SetupFunc func(c *Controller) error
SetupFunc is used to set up a plugin, or in other words, execute a directive. It will be called once per key for each server block it appears in.
func DirectiveAction ¶
DirectiveAction gets the action for directive dir of server type serverType.
type Stopper ¶
type Stopper interface { // Stop stops the server. It blocks until the // server is completely stopped. Stop() error }
Stopper is a type that can stop serving. The stop does not necessarily have to be graceful.
type TCPServer ¶
type TCPServer interface { // Listen starts listening by creating a new listener // and returning it. It does not start accepting // connections. For UDP-only servers, this method // can be a no-op that returns (nil, nil). Listen() (net.Listener, error) // Serve starts serving using the provided listener. // Serve must start the server loop nearly immediately, // or at least not return any errors before the server // loop begins. Serve blocks indefinitely, or in other // words, until the server is stopped. For UDP-only // servers, this method can be a no-op that returns nil. Serve(net.Listener) error }
TCPServer is a type that can listen and serve connections. A TCPServer must associate with exactly zero or one net.Listeners.
type UDPServer ¶
type UDPServer interface { // ListenPacket starts listening by creating a new packetconn // and returning it. It does not start accepting connections. // TCP-only servers may leave this method blank and return // (nil, nil). ListenPacket() (net.PacketConn, error) // ServePacket starts serving using the provided packetconn. // ServePacket must start the server loop nearly immediately, // or at least not return any errors before the server // loop begins. ServePacket blocks indefinitely, or in other // words, until the server is stopped. For TCP-only servers, // this method can be a no-op that returns nil. ServePacket(net.PacketConn) error }
UDPServer is a type that can listen and serve packets. A UDPServer must associate with exactly zero or one net.PacketConns.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
basicauth
Package basicauth implements HTTP Basic Authentication for Casket.
|
Package basicauth implements HTTP Basic Authentication for Casket. |
browse
Package browse provides middleware for listing files in a directory when directory path is requested instead of a specific file.
|
Package browse provides middleware for listing files in a directory when directory path is requested instead of a specific file. |
errors
Package errors implements an HTTP error handling middleware.
|
Package errors implements an HTTP error handling middleware. |
extensions
Package extensions contains middleware for clean URLs.
|
Package extensions contains middleware for clean URLs. |
fastcgi
Package fastcgi has middleware that acts as a FastCGI client.
|
Package fastcgi has middleware that acts as a FastCGI client. |
gzip
Package gzip provides a middleware layer that performs gzip compression on the response.
|
Package gzip provides a middleware layer that performs gzip compression on the response. |
header
Package header provides middleware that appends headers to requests based on a set of configuration rules that define which routes receive which headers.
|
Package header provides middleware that appends headers to requests based on a set of configuration rules that define which routes receive which headers. |
httpserver
Package httpserver implements an HTTP server on top of Casket.
|
Package httpserver implements an HTTP server on top of Casket. |
internalsrv
Package internalsrv provides a simple middleware that (a) prevents access to internal locations and (b) allows to return files from internal location by setting a special header, e.g.
|
Package internalsrv provides a simple middleware that (a) prevents access to internal locations and (b) allows to return files from internal location by setting a special header, e.g. |
log
Package log implements request (access) logging middleware.
|
Package log implements request (access) logging middleware. |
markdown
Package markdown is middleware to render markdown files as HTML on-the-fly.
|
Package markdown is middleware to render markdown files as HTML on-the-fly. |
proxy
Package proxy is middleware that proxies HTTP requests.
|
Package proxy is middleware that proxies HTTP requests. |
redirect
Package redirect is middleware for redirecting certain requests to other locations.
|
Package redirect is middleware for redirecting certain requests to other locations. |
rewrite
Package rewrite is middleware for rewriting requests internally to a different path.
|
Package rewrite is middleware for rewriting requests internally to a different path. |
staticfiles
Package staticfiles provides middleware for serving static files from disk.
|
Package staticfiles provides middleware for serving static files from disk. |
status
Package status is middleware for returning status code for requests
|
Package status is middleware for returning status code for requests |
templates
Package templates implements template execution for files to be dynamically rendered for the client.
|
Package templates implements template execution for files to be dynamically rendered for the client. |
websocket
Package websocket implements a WebSocket server by executing a command and piping its input and output through the WebSocket connection.
|
Package websocket implements a WebSocket server by executing a command and piping its input and output through the WebSocket connection. |
package caskettls facilitates the management of TLS assets and integrates Let's Encrypt functionality into Casket with first-class support for creating and renewing certificates automatically.
|
package caskettls facilitates the management of TLS assets and integrates Let's Encrypt functionality into Casket with first-class support for creating and renewing certificates automatically. |
Package telemetry implements the client for server-side telemetry of the network.
|
Package telemetry implements the client for server-side telemetry of the network. |