mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-09 14:41:31 +02:00
Users can now add a port suffix to the endpoints used by talosctl. Either in the CLI flag or the ~/.talos/config. The default port is still 50000. Signed-off-by: Philipp Sauter <philipp.sauter@siderolabs.com>
117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package resolver
|
|
|
|
import (
|
|
"math/rand"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"google.golang.org/grpc/resolver"
|
|
|
|
"github.com/talos-systems/talos/pkg/machinery/generic/slices"
|
|
)
|
|
|
|
// RoundRobinResolverScheme is a scheme to use in grpc.Dial for the round-robin gRPC resolver.
|
|
// This resolver requires that all endpoints have a port appended.
|
|
// To ensure this, use EnsureEndpointsHavePorts before constructing a connection string.
|
|
const RoundRobinResolverScheme = "talosroundrobin"
|
|
|
|
func init() {
|
|
resolver.Register(&roundRobinResolverBuilder{
|
|
scheme: RoundRobinResolverScheme,
|
|
})
|
|
}
|
|
|
|
type roundRobinResolverBuilder struct {
|
|
scheme string
|
|
}
|
|
|
|
// Build implements resolver.Builder.
|
|
func (b *roundRobinResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
|
r := &roundRobinResolver{
|
|
target: target,
|
|
cc: cc,
|
|
}
|
|
|
|
if err := r.start(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return r, nil
|
|
}
|
|
|
|
// Build implements resolver.Builder.
|
|
func (b *roundRobinResolverBuilder) Scheme() string {
|
|
return b.scheme
|
|
}
|
|
|
|
type roundRobinResolver struct {
|
|
target resolver.Target
|
|
cc resolver.ClientConn
|
|
}
|
|
|
|
// EnsureEndpointsHavePorts returns the list of endpoints with default port appended to those addresses that don't have a port.
|
|
func EnsureEndpointsHavePorts(endpoints []string, defaultPort int) []string {
|
|
return slices.Map(endpoints, func(endpoint string) string {
|
|
_, _, err := net.SplitHostPort(endpoint)
|
|
if err != nil {
|
|
return net.JoinHostPort(endpoint, strconv.Itoa(defaultPort))
|
|
}
|
|
|
|
return endpoint
|
|
})
|
|
}
|
|
|
|
func (r *roundRobinResolver) start() error {
|
|
var addrs []resolver.Address //nolint:prealloc
|
|
|
|
//nolint:staticcheck
|
|
endpoints := strings.Split(r.target.Endpoint, ",")
|
|
|
|
for _, addr := range endpoints {
|
|
serverName := addr
|
|
|
|
host, _, err := net.SplitHostPort(serverName)
|
|
if err == nil {
|
|
serverName = host
|
|
}
|
|
|
|
addrs = append(addrs, resolver.Address{
|
|
ServerName: serverName,
|
|
Addr: addr,
|
|
})
|
|
}
|
|
|
|
// shuffle the list in case client does just one request
|
|
rand.Shuffle(len(addrs), func(i, j int) {
|
|
addrs[i], addrs[j] = addrs[j], addrs[i]
|
|
})
|
|
|
|
serviceConfigJSON := `{
|
|
"loadBalancingConfig": [{
|
|
"round_robin": {}
|
|
}]
|
|
}`
|
|
|
|
parsedServiceConfig := r.cc.ParseServiceConfig(serviceConfigJSON)
|
|
|
|
if parsedServiceConfig.Err != nil {
|
|
return parsedServiceConfig.Err
|
|
}
|
|
|
|
return r.cc.UpdateState(resolver.State{
|
|
Addresses: addrs,
|
|
ServiceConfig: parsedServiceConfig,
|
|
})
|
|
}
|
|
|
|
// ResolveNow implements resolver.Resolver.
|
|
func (r *roundRobinResolver) ResolveNow(o resolver.ResolveNowOptions) {}
|
|
|
|
// ResolveNow implements resolver.Resolver.
|
|
func (r *roundRobinResolver) Close() {}
|