mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-24 03:06:48 +01:00
124 lines
4.1 KiB
Go
124 lines
4.1 KiB
Go
|
// Copyright 2023 Google LLC
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package grpctransport
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"net"
|
||
|
"os"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"cloud.google.com/go/auth"
|
||
|
"cloud.google.com/go/compute/metadata"
|
||
|
"google.golang.org/grpc"
|
||
|
grpcgoogle "google.golang.org/grpc/credentials/google"
|
||
|
)
|
||
|
|
||
|
func isDirectPathEnabled(endpoint string, opts *Options) bool {
|
||
|
if opts.InternalOptions != nil && !opts.InternalOptions.EnableDirectPath {
|
||
|
return false
|
||
|
}
|
||
|
if !checkDirectPathEndPoint(endpoint) {
|
||
|
return false
|
||
|
}
|
||
|
if b, _ := strconv.ParseBool(os.Getenv(disableDirectPathEnvVar)); b {
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func checkDirectPathEndPoint(endpoint string) bool {
|
||
|
// Only [dns:///]host[:port] is supported, not other schemes (e.g., "tcp://" or "unix://").
|
||
|
// Also don't try direct path if the user has chosen an alternate name resolver
|
||
|
// (i.e., via ":///" prefix).
|
||
|
if strings.Contains(endpoint, "://") && !strings.HasPrefix(endpoint, "dns:///") {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if endpoint == "" {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func isTokenProviderDirectPathCompatible(tp auth.TokenProvider, _ *Options) bool {
|
||
|
if tp == nil {
|
||
|
return false
|
||
|
}
|
||
|
tok, err := tp.Token(context.Background())
|
||
|
if err != nil {
|
||
|
return false
|
||
|
}
|
||
|
if tok == nil {
|
||
|
return false
|
||
|
}
|
||
|
if source, _ := tok.Metadata["auth.google.tokenSource"].(string); source != "compute-metadata" {
|
||
|
return false
|
||
|
}
|
||
|
if acct, _ := tok.Metadata["auth.google.serviceAccount"].(string); acct != "default" {
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func isDirectPathXdsUsed(o *Options) bool {
|
||
|
// Method 1: Enable DirectPath xDS by env;
|
||
|
if b, _ := strconv.ParseBool(os.Getenv(enableDirectPathXdsEnvVar)); b {
|
||
|
return true
|
||
|
}
|
||
|
// Method 2: Enable DirectPath xDS by option;
|
||
|
if o.InternalOptions != nil && o.InternalOptions.EnableDirectPathXds {
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// configureDirectPath returns some dial options and an endpoint to use if the
|
||
|
// configuration allows the use of direct path. If it does not the provided
|
||
|
// grpcOpts and endpoint are returned.
|
||
|
func configureDirectPath(grpcOpts []grpc.DialOption, opts *Options, endpoint string, creds *auth.Credentials) ([]grpc.DialOption, string) {
|
||
|
if isDirectPathEnabled(endpoint, opts) && metadata.OnGCE() && isTokenProviderDirectPathCompatible(creds, opts) {
|
||
|
// Overwrite all of the previously specific DialOptions, DirectPath uses its own set of credentials and certificates.
|
||
|
grpcOpts = []grpc.DialOption{
|
||
|
grpc.WithCredentialsBundle(grpcgoogle.NewDefaultCredentialsWithOptions(grpcgoogle.DefaultCredentialsOptions{PerRPCCreds: &grpcCredentialsProvider{creds: creds}}))}
|
||
|
if timeoutDialerOption != nil {
|
||
|
grpcOpts = append(grpcOpts, timeoutDialerOption)
|
||
|
}
|
||
|
// Check if google-c2p resolver is enabled for DirectPath
|
||
|
if isDirectPathXdsUsed(opts) {
|
||
|
// google-c2p resolver target must not have a port number
|
||
|
if addr, _, err := net.SplitHostPort(endpoint); err == nil {
|
||
|
endpoint = "google-c2p:///" + addr
|
||
|
} else {
|
||
|
endpoint = "google-c2p:///" + endpoint
|
||
|
}
|
||
|
} else {
|
||
|
if !strings.HasPrefix(endpoint, "dns:///") {
|
||
|
endpoint = "dns:///" + endpoint
|
||
|
}
|
||
|
grpcOpts = append(grpcOpts,
|
||
|
// For now all DirectPath go clients will be using the following lb config, but in future
|
||
|
// when different services need different configs, then we should change this to a
|
||
|
// per-service config.
|
||
|
grpc.WithDisableServiceConfig(),
|
||
|
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"grpclb":{"childPolicy":[{"pick_first":{}}]}}]}`))
|
||
|
}
|
||
|
// TODO: add support for system parameters (quota project, request reason) via chained interceptor.
|
||
|
}
|
||
|
return grpcOpts, endpoint
|
||
|
}
|