CNPG-I gRPC Server Lifecycle#
Overview#
The gRPC server lifecycle for CNPG-I plugins is centralized in pkg/pluginhelper/http inside the cnpg-i-machinery repository. All three plugin types in plugin-barman-cloud — operator, instance, and restore — delegate their Start(ctx) method to the same http.Server.Start implementation rather than managing the gRPC server themselves.
Core Abstraction: http.Server#
The Server struct holds:
IdentityImpl— the plugin's identity service implementationEnrichers []ServerEnricher— a list of functions that register additional gRPC services onto the server- Transport config:
PluginPath(Unix socket) orServerAddress+TLS cert paths (TCP), which are mutually exclusive
ServerEnricher is a simple function type func(*grpc.Server) error that lets callers register any number of gRPC services without knowing how the server is constructed.
Lifecycle: Server.Start(ctx)#
Start executes the following sequence:
- Identity query — calls
GetPluginMetadatato retrieve the plugin name and version; fails fast if the identity service errors . - Listener creation — calls
createListener, which chooses between a TCP listener (createTCPListener) and a Unix domain socket listener (createUnixDomainSocketListener) based on whetherServerAddressis set . For Unix sockets, it removes any stale socket file first . - gRPC server construction — builds a
grpc.Serverwith chained unary and streaming interceptors: logging injection and failed-request logging (fromgrpc.go), plus panic recovery viago-grpc-middleware. - TLS (optional) — if any cert path is set, configures mTLS via
setupTLSCerts; certificates are loaded fresh per connection viagetConfigForClient. - Service registration — registers
IdentityServerand then calls eachServerEnricherto register plugin-specific services . - Shutdown goroutine — spawns a goroutine that calls
grpcServer.Stop()whenctx.Done()fires . This is the sole shutdown mechanism; there is no graceful drain. - Serve — calls
grpcServer.Serve(listener)on the current goroutine, blocking until the server stops. Thenet.ErrClosederror (produced byStop()) is swallowed; other errors are logged and returned .
How Plugins Use It#
Each plugin type constructs an http.Server directly and calls srv.Start(ctx):
| Plugin | File | Services registered via enrich |
|---|---|---|
| operator | operator/start.go | ReconcilerHooks, OperatorLifecycle |
| instance | instance/start.go | WAL, Backup, Metrics, health check |
| restore | restore/start.go | WAL, RestoreJobHooks, health check |
The pattern is identical across all three: define an enrich closure that registers services, populate http.Server, and return srv.Start(ctx).
Operator plugin — TCP + mTLS#
The operator plugin is the only one that populates TLS cert fields and ServerAddress , enabling mTLS over TCP. The instance and restore plugins leave those fields empty and default to a Unix domain socket under the configured PluginPath.
CreateMainCmd — CLI Entry Point#
For plugins that expose a CLI, CreateMainCmd wraps Server.Start in a Cobra serve command. It wires flags (--plugin-path, --server-cert, --server-key, --client-cert, --server-address) to Viper, injects a logger if the caller didn't supply one, and calls srv.Start(cmd.Context()). The cert flags are mutually required together and mutually exclusive with --plugin-path , enforcing the Unix-vs-TCP transport choice at the CLI level.
Key Files#
| File | Purpose |
|---|---|
pkg/pluginhelper/http/server.go | Server struct, Start, CreateMainCmd, listener creation, TLS setup |
pkg/pluginhelper/http/grpc.go | Logging and failed-request gRPC interceptors |
internal/cnpgi/operator/start.go | Operator plugin wiring |
internal/cnpgi/instance/start.go | Instance plugin wiring |
internal/cnpgi/restore/start.go | Restore plugin wiring |