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 }