mirror of
https://github.com/cloudnativelabs/kube-router.git
synced 2025-09-27 02:51:04 +02:00
107 lines
2.7 KiB
Go
107 lines
2.7 KiB
Go
package cri
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"google.golang.org/grpc"
|
|
"k8s.io/klog/v2"
|
|
|
|
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
|
)
|
|
|
|
const (
|
|
DefaultConnectionTimeout = 15 * time.Second
|
|
maxMsgSize = 1024 * 1024 * 16 // 16 MB
|
|
)
|
|
|
|
// remoteRuntimeService is a gRPC implementation of RuntimeService.
|
|
type remoteRuntimeService struct {
|
|
timeout time.Duration
|
|
runtimeClient runtimeapi.RuntimeServiceClient
|
|
conn *grpc.ClientConn
|
|
}
|
|
|
|
type containerInfo struct {
|
|
Pid int `json:"pid"`
|
|
}
|
|
|
|
// NewRemoteRuntimeService creates a new RuntimeService.
|
|
func NewRemoteRuntimeService(endpoint string, connectionTimeout time.Duration) (RuntimeService, error) {
|
|
proto, addr, err := EndpointParser(endpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
klog.V(4).Infof("[RuntimeService] got endpoint %s (proto=%s, path=%s)", endpoint, proto, addr)
|
|
|
|
if proto != "unix" {
|
|
return nil, errors.New("[RuntimeService] only unix socket is currently supported")
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), connectionTimeout)
|
|
defer cancel()
|
|
|
|
conn, err := grpc.DialContext(ctx, addr, grpc.WithInsecure(), grpc.WithContextDialer(dialer),
|
|
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize)))
|
|
if err != nil {
|
|
klog.Errorf("Connect remote runtime %s failed: %v", addr, err)
|
|
return nil, err
|
|
}
|
|
|
|
return &remoteRuntimeService{
|
|
timeout: connectionTimeout,
|
|
runtimeClient: runtimeapi.NewRuntimeServiceClient(conn),
|
|
conn: conn,
|
|
}, nil
|
|
}
|
|
|
|
// ContainerInfo returns verbose info of provided container.
|
|
func (r *remoteRuntimeService) ContainerInfo(id string) (*containerInfo, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
|
|
defer cancel()
|
|
|
|
// Verbose should be set, otherwise we'll get an empty slice. see
|
|
resp, err := r.runtimeClient.ContainerStatus(ctx, &runtimeapi.ContainerStatusRequest{
|
|
ContainerId: id,
|
|
Verbose: true,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
info := containerInfo{}
|
|
|
|
if err := json.Unmarshal([]byte(resp.Info["info"]), &info); err != nil {
|
|
return nil, err
|
|
}
|
|
return &info, nil
|
|
}
|
|
|
|
// Close tears down the *grpc.ClientConn and all underlying connections.
|
|
func (r *remoteRuntimeService) Close() error {
|
|
if err := r.conn.Close(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func dialer(ctx context.Context, addr string) (net.Conn, error) {
|
|
return (&net.Dialer{}).DialContext(ctx, "unix", addr)
|
|
}
|
|
|
|
// EndpointParser returns protocol and path of provided endpoint
|
|
func EndpointParser(endpoint string) (proto string, path string, err error) {
|
|
|
|
result := strings.Split(endpoint, "://")
|
|
|
|
if len(result) < 2 {
|
|
return "", "", errors.New("bad endpoint format. should be 'protocol://path'")
|
|
}
|
|
return result[0], result[1], nil
|
|
}
|