omni/internal/backend/grpc/grpc.go
Andrey Smirnov dfcbaae7d0
chore: initial commit
Omni is source-available under BUSL.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
Co-Authored-By: Artem Chernyshev <artem.chernyshev@talos-systems.com>
Co-Authored-By: Utku Ozdemir <utku.ozdemir@siderolabs.com>
Co-Authored-By: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
Co-Authored-By: Philipp Sauter <philipp.sauter@siderolabs.com>
Co-Authored-By: Noel Georgi <git@frezbo.dev>
Co-Authored-By: evgeniybryzh <evgeniybryzh@gmail.com>
Co-Authored-By: Tim Jones <tim.jones@siderolabs.com>
Co-Authored-By: Andrew Rynhard <andrew@rynhard.io>
Co-Authored-By: Spencer Smith <spencer.smith@talos-systems.com>
Co-Authored-By: Christian Rolland <christian.rolland@siderolabs.com>
Co-Authored-By: Gerard de Leeuw <gdeleeuw@leeuwit.nl>
Co-Authored-By: Steve Francis <67986293+steverfrancis@users.noreply.github.com>
Co-Authored-By: Volodymyr Mazurets <volodymyrmazureets@gmail.com>
2024-02-29 17:19:57 +04:00

128 lines
3.5 KiB
Go

// Copyright (c) 2024 Sidero Labs, Inc.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
// Package grpc implements gRPC server.
package grpc
import (
"compress/gzip"
"context"
"fmt"
"math"
"net"
"net/http"
"github.com/cosi-project/runtime/pkg/state"
gateway "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/encoding/protojson"
"github.com/siderolabs/omni/client/api/talos/machine"
"github.com/siderolabs/omni/internal/backend/logging"
"github.com/siderolabs/omni/internal/backend/monitoring"
"github.com/siderolabs/omni/internal/memconn"
"github.com/siderolabs/omni/internal/pkg/compress"
"github.com/siderolabs/omni/internal/pkg/config"
"github.com/siderolabs/omni/internal/pkg/siderolink"
)
// ServiceServer is a gRPC service server.
type ServiceServer interface {
register(grpc.ServiceRegistrar)
gateway(context.Context, *gateway.ServeMux, string, []grpc.DialOption) error
}
// MakeServiceServers creates a list of service servers.
func MakeServiceServers(
state state.State,
logHandler *siderolink.LogHandler,
oidcProvider OIDCProvider,
jwtSigningKeyProvider JWTSigningKeyProvider,
logger *zap.Logger,
) ([]ServiceServer, error) {
dest, err := generateDest(config.Config.APIURL)
if err != nil {
return nil, err
}
return []ServiceServer{
&ResourceServer{},
&oidcServer{
provider: oidcProvider,
},
&managementServer{
logHandler: logHandler,
omniconfigDest: dest,
omniState: state,
jwtSigningKeyProvider: jwtSigningKeyProvider,
logger: logger.With(logging.Component("management_server")),
},
&authServer{
state: state,
logger: logger.With(logging.Component("auth_server")),
},
&COSIResourceServer{
State: state,
},
}, nil
}
// New creates new grpc server and registers all routes.
func New(ctx context.Context, mux *http.ServeMux, servers []ServiceServer, transport *memconn.Transport, logger *zap.Logger, options ...grpc.ServerOption) (*grpc.Server, error) {
server := grpc.NewServer(options...)
for _, srv := range servers {
srv.register(server)
}
marshaller := &gateway.JSONPb{
MarshalOptions: protojson.MarshalOptions{
UseProtoNames: true,
UseEnumNumbers: true,
},
}
runtimeMux := gateway.NewServeMux(
gateway.WithMarshalerOption(gateway.MIMEWildcard, marshaller),
)
opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
// we are proxying requests to ourselves, so we don't need to impose a limit
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)),
grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
return transport.Dial()
}),
grpc.WithSharedWriteBuffer(true),
}
for _, srv := range servers {
err := srv.gateway(ctx, runtimeMux, transport.Address, opts)
if err != nil {
return nil, fmt.Errorf("error registering gateway: %w", err)
}
}
if err := machine.RegisterMachineServiceHandlerFromEndpoint(ctx, runtimeMux, transport.Address, opts); err != nil {
return nil, fmt.Errorf("error registering gateway: %w", err)
}
mux.Handle("/api/",
compress.Handler(
monitoring.NewHandler(
logging.NewHandler(
http.StripPrefix("/api", runtimeMux),
logger.With(zap.String("handler", "grpc_gateway")),
),
prometheus.Labels{"handler": "grpc_gateway"},
),
gzip.DefaultCompression,
),
)
return server, nil
}