containerd / containerd/nri

The error type is missing when stub.Run fails

Open
#83 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
406
Forks
102
Avg merge
1d 10h
Merged PRs (30d)
8

Description

I want to implement NRI reconnect logic in onClose() which is when the NRI plugin loses connection to the NRI server, the NRI plugin attempts to reconnect. However, during the reconnection attempt, we need to detect the possible error types of the connection and handle them differently based on the error type. However, the current error return of the NRI plugin's Start function does not distinguish between error categories. For example, whether the connection was lost due to containerd restarting or NRI being disabled on the containerd side. If NRI is disabled on the containerd side, the NRI plugin does not need to reconnect anymore. If containerd simply restarts, the NRI plugin needs to keep trying to reconnect until the connection is successful. The corresponding code in the nri repository is https://github.com/containerd/nri/blob/main/pkg/stub/stub.go#L315. I paste below.

In the Start function, we can return errors because of several reasons:

* stub already started
* stub.connect() return error
* failed to listen multiplex.PluginServiceConn
* failed to multiplex ttrpc client connection
* failed to register plugin
* ...

Can we give more info for us to detect error types not an error string?

```
// Start event processing, register to NRI and wait for getting configured.
func (stub *stub) Start(ctx context.Context) (retErr error) {
stub.Lock()
defer stub.Unlock()

if stub.started {
return fmt.Errorf("stub already started")
}
stub.started = true

err := stub.connect()
if err != nil {
return err
}

rpcm := multiplex.Multiplex(stub.conn)
defer func() {
if retErr != nil {
rpcm.Close()
stub.rpcm = nil
}
}()

rpcl, err := rpcm.Listen(multiplex.PluginServiceConn)
if err != nil {
return err
}
defer func() {
if retErr != nil {
rpcl.Close()
stub.rpcl = nil
}
}()

rpcs, err := ttrpc.NewServer(stub.serverOpts...)
if err != nil {
return fmt.Errorf("failed to create ttrpc server: %w", err)
}
defer func() {
if retErr != nil {
rpcs.Close()
stub.rpcs = nil
}
}()

api.RegisterPluginService(rpcs, stub)

conn, err := rpcm.Open(multiplex.RuntimeServiceConn)
if err != nil {
return fmt.Errorf("failed to multiplex ttrpc client connection: %w", err)
}

clientOpts := []ttrpc.ClientOpts{
ttrpc.WithOnClose(func() {
stub.connClosed()
}),
}
rpcc := ttrpc.NewClient(conn, append(clientOpts, stub.clientOpts...)...)
defer func() {
if retErr != nil {
rpcc.Close()
stub.rpcc = nil
}
}()

stub.srvErrC = make(chan error, 1)
stub.cfgErrC = make(chan error, 1)
go func() {
stub.srvErrC <- rpcs.Serve(ctx, rpcl)
close(stub.doneC)
}()

stub.rpcm = rpcm
stub.rpcl = rpcl
stub.rpcs = rpcs
stub.rpcc = rpcc

stub.runtime = api.NewRuntimeClient(rpcc)

if err = stub.register(ctx); err != nil {
stub.close()
return err
}

if err = <-stub.cfgErrC; err != nil {
return err
}
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.