mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
36230daa86
rancher/kine ➡️ k3s-io/kine Part of https://github.com/rancher/k3s/issues/2189 Signed-off-by: Jacob Blain Christen <jacob@rancher.com>
163 lines
3.7 KiB
Go
163 lines
3.7 KiB
Go
package endpoint
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/k3s-io/kine/pkg/drivers/dqlite"
|
|
"github.com/k3s-io/kine/pkg/drivers/generic"
|
|
"github.com/k3s-io/kine/pkg/drivers/mysql"
|
|
"github.com/k3s-io/kine/pkg/drivers/pgsql"
|
|
"github.com/k3s-io/kine/pkg/drivers/sqlite"
|
|
"github.com/k3s-io/kine/pkg/server"
|
|
"github.com/k3s-io/kine/pkg/tls"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
const (
|
|
KineSocket = "unix://kine.sock"
|
|
SQLiteBackend = "sqlite"
|
|
DQLiteBackend = "dqlite"
|
|
ETCDBackend = "etcd3"
|
|
MySQLBackend = "mysql"
|
|
PostgresBackend = "postgres"
|
|
)
|
|
|
|
type Config struct {
|
|
GRPCServer *grpc.Server
|
|
Listener string
|
|
Endpoint string
|
|
ConnectionPoolConfig generic.ConnectionPoolConfig
|
|
|
|
tls.Config
|
|
}
|
|
|
|
type ETCDConfig struct {
|
|
Endpoints []string
|
|
TLSConfig tls.Config
|
|
LeaderElect bool
|
|
}
|
|
|
|
func Listen(ctx context.Context, config Config) (ETCDConfig, error) {
|
|
driver, dsn := ParseStorageEndpoint(config.Endpoint)
|
|
if driver == ETCDBackend {
|
|
return ETCDConfig{
|
|
Endpoints: strings.Split(config.Endpoint, ","),
|
|
TLSConfig: config.Config,
|
|
LeaderElect: true,
|
|
}, nil
|
|
}
|
|
|
|
leaderelect, backend, err := getKineStorageBackend(ctx, driver, dsn, config)
|
|
if err != nil {
|
|
return ETCDConfig{}, errors.Wrap(err, "building kine")
|
|
}
|
|
|
|
if err := backend.Start(ctx); err != nil {
|
|
return ETCDConfig{}, errors.Wrap(err, "starting kine backend")
|
|
}
|
|
|
|
listen := config.Listener
|
|
if listen == "" {
|
|
listen = KineSocket
|
|
}
|
|
|
|
b := server.New(backend)
|
|
grpcServer := grpcServer(config)
|
|
b.Register(grpcServer)
|
|
|
|
listener, err := createListener(listen)
|
|
if err != nil {
|
|
return ETCDConfig{}, err
|
|
}
|
|
|
|
go func() {
|
|
if err := grpcServer.Serve(listener); err != nil {
|
|
logrus.Errorf("Kine server shutdown: %v", err)
|
|
}
|
|
<-ctx.Done()
|
|
grpcServer.Stop()
|
|
listener.Close()
|
|
}()
|
|
|
|
return ETCDConfig{
|
|
LeaderElect: leaderelect,
|
|
Endpoints: []string{listen},
|
|
TLSConfig: tls.Config{},
|
|
}, nil
|
|
}
|
|
|
|
func createListener(listen string) (ret net.Listener, rerr error) {
|
|
network, address := networkAndAddress(listen)
|
|
|
|
if network == "unix" {
|
|
if err := os.Remove(address); err != nil && !os.IsNotExist(err) {
|
|
logrus.Warnf("failed to remove socket %s: %v", address, err)
|
|
}
|
|
defer func() {
|
|
if err := os.Chmod(address, 0600); err != nil {
|
|
rerr = err
|
|
}
|
|
}()
|
|
}
|
|
|
|
logrus.Infof("Kine listening on %s://%s", network, address)
|
|
return net.Listen(network, address)
|
|
}
|
|
|
|
func grpcServer(config Config) *grpc.Server {
|
|
if config.GRPCServer != nil {
|
|
return config.GRPCServer
|
|
}
|
|
return grpc.NewServer()
|
|
}
|
|
|
|
func getKineStorageBackend(ctx context.Context, driver, dsn string, cfg Config) (bool, server.Backend, error) {
|
|
var (
|
|
backend server.Backend
|
|
leaderElect = true
|
|
err error
|
|
)
|
|
switch driver {
|
|
case SQLiteBackend:
|
|
leaderElect = false
|
|
backend, err = sqlite.New(ctx, dsn, cfg.ConnectionPoolConfig)
|
|
case DQLiteBackend:
|
|
backend, err = dqlite.New(ctx, dsn, cfg.ConnectionPoolConfig)
|
|
case PostgresBackend:
|
|
backend, err = pgsql.New(ctx, dsn, cfg.Config, cfg.ConnectionPoolConfig)
|
|
case MySQLBackend:
|
|
backend, err = mysql.New(ctx, dsn, cfg.Config, cfg.ConnectionPoolConfig)
|
|
default:
|
|
return false, nil, fmt.Errorf("storage backend is not defined")
|
|
}
|
|
|
|
return leaderElect, backend, err
|
|
}
|
|
|
|
func ParseStorageEndpoint(storageEndpoint string) (string, string) {
|
|
network, address := networkAndAddress(storageEndpoint)
|
|
switch network {
|
|
case "":
|
|
return SQLiteBackend, ""
|
|
case "http":
|
|
fallthrough
|
|
case "https":
|
|
return ETCDBackend, address
|
|
}
|
|
return network, address
|
|
}
|
|
|
|
func networkAndAddress(str string) (string, string) {
|
|
parts := strings.SplitN(str, "://", 2)
|
|
if len(parts) > 1 {
|
|
return parts[0], parts[1]
|
|
}
|
|
return "", parts[0]
|
|
}
|