1// Copyright 2017 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Package internal supports the options and transport packages. 16package internal 17 18import ( 19 "errors" 20 "net/http" 21 22 "golang.org/x/oauth2" 23 "golang.org/x/oauth2/google" 24 "google.golang.org/grpc" 25) 26 27// DialSettings holds information needed to establish a connection with a 28// Google API service. 29type DialSettings struct { 30 Endpoint string 31 Scopes []string 32 TokenSource oauth2.TokenSource 33 Credentials *google.Credentials 34 CredentialsFile string // if set, Token Source is ignored. 35 CredentialsJSON []byte 36 UserAgent string 37 APIKey string 38 Audiences []string 39 HTTPClient *http.Client 40 GRPCDialOpts []grpc.DialOption 41 GRPCConn *grpc.ClientConn 42 NoAuth bool 43 44 // Google API system parameters. For more information please read: 45 // https://cloud.google.com/apis/docs/system-parameters 46 QuotaProject string 47 RequestReason string 48} 49 50// Validate reports an error if ds is invalid. 51func (ds *DialSettings) Validate() error { 52 hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil 53 if ds.NoAuth && hasCreds { 54 return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials") 55 } 56 // Credentials should not appear with other options. 57 // We currently allow TokenSource and CredentialsFile to coexist. 58 // TODO(jba): make TokenSource & CredentialsFile an error (breaking change). 59 nCreds := 0 60 if ds.Credentials != nil { 61 nCreds++ 62 } 63 if ds.CredentialsJSON != nil { 64 nCreds++ 65 } 66 if ds.CredentialsFile != "" { 67 nCreds++ 68 } 69 if ds.APIKey != "" { 70 nCreds++ 71 } 72 if ds.TokenSource != nil { 73 nCreds++ 74 } 75 if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 { 76 return errors.New("WithScopes is incompatible with WithAudience") 77 } 78 // Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility. 79 if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") { 80 return errors.New("multiple credential options provided") 81 } 82 if ds.HTTPClient != nil && ds.GRPCConn != nil { 83 return errors.New("WithHTTPClient is incompatible with WithGRPCConn") 84 } 85 if ds.HTTPClient != nil && ds.GRPCDialOpts != nil { 86 return errors.New("WithHTTPClient is incompatible with gRPC dial options") 87 } 88 if ds.HTTPClient != nil && ds.QuotaProject != "" { 89 return errors.New("WithHTTPClient is incompatible with QuotaProject") 90 } 91 if ds.HTTPClient != nil && ds.RequestReason != "" { 92 return errors.New("WithHTTPClient is incompatible with RequestReason") 93 } 94 95 return nil 96} 97