// set up the GRPC server func setupGRPCServer(signerConfig signer.Config) (*grpc.Server, net.Listener, error) { //RPC server setup kms := &api.KeyManagementServer{ CryptoServices: signerConfig.CryptoServices, } ss := &api.SignerServer{ CryptoServices: signerConfig.CryptoServices, } hs := ghealth.NewServer() lis, err := net.Listen("tcp", signerConfig.GRPCAddr) if err != nil { return nil, nil, fmt.Errorf("grpc server failed to listen on %s: %v", signerConfig.GRPCAddr, err) } creds := credentials.NewTLS(signerConfig.TLSConfig) opts := []grpc.ServerOption{grpc.Creds(creds)} grpcServer := grpc.NewServer(opts...) pb.RegisterKeyManagementServer(grpcServer, kms) pb.RegisterSignerServer(grpcServer, ss) healthpb.RegisterHealthServer(grpcServer, hs) // Set status for both of the grpc service "KeyManagement" and "Signer", these are // the only two we have at present, if we add more grpc service in the future, // we should add a new line for that service here as well. hs.SetServingStatus(notary.HealthCheckKeyManagement, healthpb.HealthCheckResponse_SERVING) hs.SetServingStatus(notary.HealthCheckSigner, healthpb.HealthCheckResponse_SERVING) return grpcServer, lis, nil }
// BuildGrpcServer creates a new, unstarted grpc.Server and returns it. // It also returns a net.Listener to start it on. func BuildGrpcServer(port int, cache *Cache, keyFile, certFile, caCertFile, readonlyKeys, writableKeys string) (*grpc.Server, net.Listener) { lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { log.Fatalf("Failed to listen on port %d: %v", port, err) } s := serverWithAuth(keyFile, certFile, caCertFile) r := &RpcCacheServer{cache: cache} if writableKeys != "" { r.writableKeys = loadKeys(writableKeys) } if readonlyKeys != "" { r.readonlyKeys = loadKeys(readonlyKeys) if len(r.readonlyKeys) > 0 { // This saves duplication when checking later; writable keys are implicitly readable too. for k, v := range r.writableKeys { if _, present := r.readonlyKeys[k]; !present { r.readonlyKeys[k] = v } } } } pb.RegisterRpcCacheServer(s, r) healthserver := health.NewServer() healthserver.SetServingStatus("plz-rpc-cache", healthpb.HealthCheckResponse_SERVING) healthpb.RegisterHealthServer(s, healthserver) return s, lis }
// TestHealthCheckForOverallStatus query for signer's overall health status func TestHealthCheckForOverallStatus(t *testing.T) { hs := health.NewServer() s := getStubbedHealthServer(hs) signerClient, _, cleanup := setUpSignerClient(t, s) defer cleanup() // both of the service are NOT SERVING, expect the health check for overall status to be failed. hs.SetServingStatus(notary.HealthCheckKeyManagement, healthpb.HealthCheckResponse_NOT_SERVING) hs.SetServingStatus(notary.HealthCheckSigner, healthpb.HealthCheckResponse_NOT_SERVING) err := signerClient.CheckHealth(1*time.Second, notary.HealthCheckOverall) require.Error(t, err) require.Contains(t, err.Error(), "NOT_SERVING, want SERVING") // change the status of KeyManagement to SERVING and keep the status of Signer // still be NOT SERVING, expect the health check for overall status to be failed. hs.SetServingStatus(notary.HealthCheckKeyManagement, healthpb.HealthCheckResponse_SERVING) err = signerClient.CheckHealth(1*time.Second, notary.HealthCheckOverall) require.Error(t, err) require.Contains(t, err.Error(), "NOT_SERVING, want SERVING") // change the status of Signer to SERVING, expect the health check for overall status to success. hs.SetServingStatus(notary.HealthCheckSigner, healthpb.HealthCheckResponse_SERVING) err = signerClient.CheckHealth(1*time.Second, notary.HealthCheckOverall) require.NoError(t, err) }
// healthCheckUnhealthy does not succeed if the service is unhealthy func healthCheckUnhealthy(t *testing.T, serviceName string) { hs := health.NewServer() hs.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING) s := getStubbedHealthServer(hs) signerClient, _, cleanup := setUpSignerClient(t, s) defer cleanup() require.Error(t, signerClient.CheckHealth(1*time.Second, serviceName)) }
// TestHealthCheckNonexistentService query for a nonexistent service's health status // which expected to fail. func TestHealthCheckNonexistentService(t *testing.T) { hs := health.NewServer() s := getStubbedHealthServer(hs) signerClient, _, cleanup := setUpSignerClient(t, s) defer cleanup() // check a nonexistent service, expect to be failed. err := signerClient.CheckHealth(1*time.Second, "Hola Rio") require.Error(t, err) require.Contains(t, err.Error(), "Unknown grpc service Hola Rio") }
// healthCheckTimeout does not succeed if the health check to the server times out func healthCheckTimeout(t *testing.T, serviceName string) { hs := health.NewServer() hs.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING) s := getStubbedHealthServer(hs) signerClient, _, cleanup := setUpSignerClient(t, s) defer cleanup() err := signerClient.CheckHealth(0*time.Second, serviceName) require.Error(t, err) require.Contains(t, err.Error(), context.DeadlineExceeded.Error()) }
func startServer(protocol, address string, sv *supervisor.Supervisor) (*grpc.Server, error) { // TODO: We should use TLS. // TODO: Add an option for the SocketGroup. sockets, err := listeners.Init(protocol, address, "", nil) if err != nil { return nil, err } if len(sockets) != 1 { return nil, fmt.Errorf("incorrect number of listeners") } l := sockets[0] s := grpc.NewServer() types.RegisterAPIServer(s, server.NewServer(sv)) healthServer := health.NewServer() grpc_health_v1.RegisterHealthServer(s, healthServer) go func() { logrus.Debugf("containerd: grpc api on %s", address) if err := s.Serve(l); err != nil { logrus.WithField("error", err).Fatal("containerd: serve grpc") } }() return s, nil }
// RegisterHealthServer registers the component's health status to the gRPC server func (c *Component) RegisterHealthServer(srv *grpc.Server) { c.healthServer = health.NewServer() healthpb.RegisterHealthServer(srv, c.healthServer) }