github.com/bazelbuild/remote-apis-sdks@v0.0.0-20240425170053-8a36686a6350/go/pkg/flags/flags.go (about)

     1  // Package flags provides a convenient way to initialize the remote client from flags.
     2  package flags
     3  
     4  import (
     5  	"context"
     6  	"flag"
     7  	"time"
     8  
     9  	"github.com/bazelbuild/remote-apis-sdks/go/pkg/balancer"
    10  	"github.com/bazelbuild/remote-apis-sdks/go/pkg/client"
    11  	"github.com/bazelbuild/remote-apis-sdks/go/pkg/moreflag"
    12  	"google.golang.org/grpc"
    13  	"google.golang.org/grpc/keepalive"
    14  
    15  	log "github.com/golang/glog"
    16  )
    17  
    18  var (
    19  	// The flags credential_file, use_application_default_credentials, and use_gce_credentials
    20  	// determine the client identity that is used to authenticate with remote execution.
    21  	// One of the following must be true for client authentication to work, and they are used in
    22  	// this order of preference:
    23  	// - the use_application_default_credentials flag must be set to true, or
    24  	// - the use_gce_credentials must be set to true, or
    25  	// - the credential_file flag must be set to point to a valid credential file
    26  
    27  	// CredFile is the name of a file that contains service account credentials to use when calling
    28  	// remote execution. Used only if --use_application_default_credentials and --use_gce_credentials
    29  	// are false.
    30  	CredFile = flag.String("credential_file", "", "The name of a file that contains service account credentials to use when calling remote execution. Used only if --use_application_default_credentials and --use_gce_credentials are false.")
    31  	// UseApplicationDefaultCreds is whether to use application default credentials to connect to
    32  	// remote execution. See
    33  	// https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login
    34  	UseApplicationDefaultCreds = flag.Bool("use_application_default_credentials", false, "If true, use application default credentials to connect to remote execution. See https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login")
    35  	// UseGCECredentials is whether to use the default GCE credentials to authenticate with remote
    36  	// execution. --use_application_default_credentials must be false.
    37  	UseGCECredentials = flag.Bool("use_gce_credentials", false, "If true (and --use_application_default_credentials is false), use the default GCE credentials to authenticate with remote execution.")
    38  	// UseRPCCredentials can be set to false to disable all per-RPC credentials.
    39  	UseRPCCredentials = flag.Bool("use_rpc_credentials", true, "If false, no per-RPC credentials will be used (disables --credential_file, --use_application_default_credentials, and --use_gce_credentials.")
    40  	// UseExternalAuthToken specifies whether to use an externally provided auth token, given via PerRPCCreds dial option, should be used.
    41  	UseExternalAuthToken = flag.Bool("use_external_auth_token", false, "If true, se an externally provided auth token, given via PerRPCCreds when the SDK is initialized.")
    42  	// Service represents the host (and, if applicable, port) of the remote execution service.
    43  	Service = flag.String("service", "", "The remote execution service to dial when calling via gRPC, including port, such as 'localhost:8790' or 'remotebuildexecution.googleapis.com:443'")
    44  	// ServiceNoSecurity can be set to connect to the gRPC service without TLS and without authentication (enables --service_no_auth).
    45  	ServiceNoSecurity = flag.Bool("service_no_security", false, "If true, do not use TLS or authentication when connecting to the gRPC service.")
    46  	// ServiceNoAuth can be set to disable authentication while still using TLS.
    47  	ServiceNoAuth = flag.Bool("service_no_auth", false, "If true, do not authenticate with the service (implied by --service_no_security).")
    48  	// CASService represents the host (and, if applicable, port) of the CAS service, if different from the remote execution service.
    49  	CASService = flag.String("cas_service", "", "The CAS service to dial when calling via gRPC, including port, such as 'localhost:8790' or 'remotebuildexecution.googleapis.com:443'")
    50  	// Instance gives the instance of remote execution to test (in
    51  	// projects/[PROJECT_ID]/instances/[INSTANCE_NAME] format for Google RBE).
    52  	Instance = flag.String("instance", "", "The instance ID to target when calling remote execution via gRPC (e.g., projects/$PROJECT/instances/default_instance for Google RBE).")
    53  	// CASConcurrency specifies the maximum number of concurrent upload & download RPCs that can be in flight.
    54  	CASConcurrency = flag.Int("cas_concurrency", client.DefaultCASConcurrency, "Num concurrent upload / download RPCs that the SDK is allowed to do.")
    55  	// MaxConcurrentRequests denotes the maximum number of concurrent RPCs on a single gRPC connection.
    56  	MaxConcurrentRequests = flag.Uint("max_concurrent_requests_per_conn", client.DefaultMaxConcurrentRequests, "Maximum number of concurrent RPCs on a single gRPC connection.")
    57  	// MaxConcurrentStreams denotes the maximum number of concurrent stream RPCs on a single gRPC connection.
    58  	MaxConcurrentStreams = flag.Uint("max_concurrent_streams_per_conn", client.DefaultMaxConcurrentStreams, "Maximum number of concurrent stream RPCs on a single gRPC connection.")
    59  	// TLSServerName overrides the server name sent in the TLS session.
    60  	TLSServerName = flag.String("tls_server_name", "", "Override the TLS server name")
    61  	// TLSCACert loads CA certificates from a file
    62  	TLSCACert = flag.String("tls_ca_cert", "", "Load TLS CA certificates from this file")
    63  	// TLSClientAuthCert sets the public key in PEM format for using mTLS auth to connect to the RBE service.
    64  	TLSClientAuthCert = flag.String("tls_client_auth_cert", "", "Certificate to use when using mTLS to connect to the RBE service.")
    65  	// TLSClientAuthKey sets the private key for using mTLS auth to connect to the RBE service.
    66  	TLSClientAuthKey = flag.String("tls_client_auth_key", "", "Key to use when using mTLS to connect to the RBE service.")
    67  	// StartupCapabilities specifies whether to self-configure based on remote server capabilities on startup.
    68  	StartupCapabilities = flag.Bool("startup_capabilities", true, "Whether to self-configure based on remote server capabilities on startup.")
    69  	// RPCTimeouts stores the per-RPC timeout values.
    70  	RPCTimeouts map[string]string
    71  	// KeepAliveTime specifies gRPCs keepalive time parameter.
    72  	KeepAliveTime = flag.Duration("grpc_keepalive_time", 0*time.Second, "After a duration of this time if the client doesn't see any activity it pings the server to see if the transport is still alive. If zero or not set, the mechanism is off.")
    73  	// KeepAliveTimeout specifies gRPCs keepalive timeout parameter.
    74  	KeepAliveTimeout = flag.Duration("grpc_keepalive_timeout", 20*time.Second, "After having pinged for keepalive check, the client waits for a duration of Timeout and if no activity is seen even after that the connection is closed. Default is 20s.")
    75  	// KeepAlivePermitWithoutStream specifies gRPCs keepalive permitWithoutStream parameter.
    76  	KeepAlivePermitWithoutStream = flag.Bool("grpc_keepalive_permit_without_stream", false, "If true, client sends keepalive pings even with no active RPCs; otherwise, doesn't send pings even if time and timeout are set. Default is false.")
    77  )
    78  
    79  func init() {
    80  	// MinConnections denotes the minimum number of gRPC sub-connections the gRPC balancer should create during SDK initialization.
    81  	flag.IntVar(&balancer.MinConnections, "min_grpc_connections", balancer.DefaultMinConnections, "Minimum number of gRPC sub-connections the gRPC balancer should create during SDK initialization.")
    82  	// RPCTimeouts stores the per-RPC timeout values. The flag allows users to override the defaults
    83  	// set in client.DefaultRPCTimeouts. This is in order to not force the users to familiarize
    84  	// themselves with every RPC, otherwise it is easy to accidentally enforce a timeout on
    85  	// WaitExecution, for example.
    86  	flag.Var((*moreflag.StringMapValue)(&RPCTimeouts), "rpc_timeouts", "Comma-separated key value pairs in the form rpc_name=timeout. The key for default RPC is named default. 0 indicates no timeout. Example: GetActionResult=500ms,Execute=0,default=10s.")
    87  }
    88  
    89  // NewClientFromFlags connects to a remote execution service and returns a client suitable for higher-level
    90  // functionality. It uses the flags from above to configure the connection to remote execution.
    91  func NewClientFromFlags(ctx context.Context, opts ...client.Opt) (*client.Client, error) {
    92  	opts = append(opts, []client.Opt{client.CASConcurrency(*CASConcurrency), client.StartupCapabilities(*StartupCapabilities)}...)
    93  	if len(RPCTimeouts) > 0 {
    94  		timeouts := make(map[string]time.Duration)
    95  		for rpc, d := range client.DefaultRPCTimeouts {
    96  			timeouts[rpc] = d
    97  		}
    98  		// Override the defaults with flags, but do not replace.
    99  		for rpc, s := range RPCTimeouts {
   100  			d, err := time.ParseDuration(s)
   101  			if err != nil {
   102  				return nil, err
   103  			}
   104  			timeouts[rpc] = d
   105  		}
   106  		opts = append(opts, client.RPCTimeouts(timeouts))
   107  	}
   108  	var perRPCCreds *client.PerRPCCreds
   109  	tOpts := []client.Opt{}
   110  	for _, opt := range opts {
   111  		switch opt.(type) {
   112  		case *client.PerRPCCreds:
   113  			perRPCCreds = (opt).(*(client.PerRPCCreds))
   114  		default:
   115  			tOpts = append(tOpts, opt)
   116  		}
   117  	}
   118  	opts = tOpts
   119  
   120  	dialOpts := make([]grpc.DialOption, 0)
   121  	if *KeepAliveTime > 0*time.Second {
   122  		params := keepalive.ClientParameters{
   123  			Time:                *KeepAliveTime,
   124  			Timeout:             *KeepAliveTimeout,
   125  			PermitWithoutStream: *KeepAlivePermitWithoutStream,
   126  		}
   127  		log.V(1).Infof("KeepAlive params = %v", params)
   128  		dialOpts = append(dialOpts, grpc.WithKeepaliveParams(params))
   129  	}
   130  	return client.NewClient(ctx, *Instance, client.DialParams{
   131  		Service:               *Service,
   132  		NoSecurity:            *ServiceNoSecurity,
   133  		NoAuth:                *ServiceNoAuth,
   134  		CASService:            *CASService,
   135  		CredFile:              *CredFile,
   136  		DialOpts:              dialOpts,
   137  		UseApplicationDefault: *UseApplicationDefaultCreds,
   138  		UseComputeEngine:      *UseGCECredentials,
   139  		UseExternalAuthToken:  *UseExternalAuthToken,
   140  		ExternalPerRPCCreds:   perRPCCreds,
   141  		TransportCredsOnly:    !*UseRPCCredentials,
   142  		TLSServerName:         *TLSServerName,
   143  		TLSCACertFile:         *TLSCACert,
   144  		TLSClientAuthCert:     *TLSClientAuthCert,
   145  		TLSClientAuthKey:      *TLSClientAuthKey,
   146  		MaxConcurrentRequests: uint32(*MaxConcurrentRequests),
   147  		MaxConcurrentStreams:  uint32(*MaxConcurrentStreams),
   148  	}, opts...)
   149  }