github.com/argoproj/argo-cd/v2@v2.10.9/reposerver/apiclient/clientset.go (about)

     1  package apiclient
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"fmt"
     7  	"time"
     8  
     9  	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    10  	grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
    11  	log "github.com/sirupsen/logrus"
    12  	"google.golang.org/grpc"
    13  	"google.golang.org/grpc/credentials"
    14  	"google.golang.org/grpc/credentials/insecure"
    15  
    16  	argogrpc "github.com/argoproj/argo-cd/v2/util/grpc"
    17  	"github.com/argoproj/argo-cd/v2/util/io"
    18  )
    19  
    20  //go:generate go run github.com/vektra/mockery/v2@v2.15.0 --name=RepoServerServiceClient
    21  
    22  const (
    23  	// MaxGRPCMessageSize contains max grpc message size
    24  	MaxGRPCMessageSize = 100 * 1024 * 1024
    25  )
    26  
    27  // TLSConfiguration describes parameters for TLS configuration to be used by a repo server API client
    28  type TLSConfiguration struct {
    29  	// Whether to disable TLS for connections
    30  	DisableTLS bool
    31  	// Whether to enforce strict validation of TLS certificates
    32  	StrictValidation bool
    33  	// List of certificates to validate the peer against (if StrictCerts is true)
    34  	Certificates *x509.CertPool
    35  }
    36  
    37  // Clientset represents repository server api clients
    38  type Clientset interface {
    39  	NewRepoServerClient() (io.Closer, RepoServerServiceClient, error)
    40  }
    41  
    42  type clientSet struct {
    43  	address        string
    44  	timeoutSeconds int
    45  	tlsConfig      TLSConfiguration
    46  }
    47  
    48  func (c *clientSet) NewRepoServerClient() (io.Closer, RepoServerServiceClient, error) {
    49  	conn, err := NewConnection(c.address, c.timeoutSeconds, &c.tlsConfig)
    50  	if err != nil {
    51  		return nil, nil, fmt.Errorf("failed to open a new connection to repo server: %w", err)
    52  	}
    53  	return conn, NewRepoServerServiceClient(conn), nil
    54  }
    55  
    56  func NewConnection(address string, timeoutSeconds int, tlsConfig *TLSConfiguration) (*grpc.ClientConn, error) {
    57  	retryOpts := []grpc_retry.CallOption{
    58  		grpc_retry.WithMax(3),
    59  		grpc_retry.WithBackoff(grpc_retry.BackoffLinear(1000 * time.Millisecond)),
    60  	}
    61  	unaryInterceptors := []grpc.UnaryClientInterceptor{grpc_retry.UnaryClientInterceptor(retryOpts...)}
    62  	if timeoutSeconds > 0 {
    63  		unaryInterceptors = append(unaryInterceptors, argogrpc.WithTimeout(time.Duration(timeoutSeconds)*time.Second))
    64  	}
    65  	opts := []grpc.DialOption{
    66  		grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(retryOpts...)),
    67  		grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unaryInterceptors...)),
    68  		grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(MaxGRPCMessageSize), grpc.MaxCallSendMsgSize(MaxGRPCMessageSize)),
    69  		grpc.WithUnaryInterceptor(argogrpc.OTELUnaryClientInterceptor()),
    70  		grpc.WithStreamInterceptor(argogrpc.OTELStreamClientInterceptor()),
    71  	}
    72  
    73  	tlsC := &tls.Config{}
    74  	if !tlsConfig.DisableTLS {
    75  		if !tlsConfig.StrictValidation {
    76  			tlsC.InsecureSkipVerify = true
    77  		} else {
    78  			tlsC.RootCAs = tlsConfig.Certificates
    79  		}
    80  		opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsC)))
    81  	} else {
    82  		opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
    83  	}
    84  
    85  	conn, err := grpc.Dial(address, opts...)
    86  	if err != nil {
    87  		log.Errorf("Unable to connect to repository service with address %s", address)
    88  		return nil, err
    89  	}
    90  	return conn, nil
    91  }
    92  
    93  // NewRepoServerClientset creates new instance of repo server Clientset
    94  func NewRepoServerClientset(address string, timeoutSeconds int, tlsConfig TLSConfiguration) Clientset {
    95  	return &clientSet{address: address, timeoutSeconds: timeoutSeconds, tlsConfig: tlsConfig}
    96  }