Skip to content

Commit

Permalink
Refactor gRPC and Auth situation.
Browse files Browse the repository at this point in the history
As we discussed in googleapis/google-cloud-node#1463',
many of auth parameters will be called in a initialization
of the module itself and then used later.

For this purpose, GAX also serves an object which keeps
the auth data and handle its feature under the same context.

This also offers a new dependency of google-auto-auth library
instead of google-auth-library, and supports nice optional parameters
like keyFile.
  • Loading branch information
jmuk committed Aug 12, 2016
1 parent b90b529 commit 242b47b
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 82 deletions.
4 changes: 1 addition & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ var bundling = require('./lib/bundling');
exports.createApiCall = require('./lib/api_callable').createApiCall;
exports.EventEmitter = eventEmitter.EventEmitter;
exports.BundleEventEmitter = eventEmitter.BundleEventEmitter;
exports.createStub = grpc.createStub;
exports.loadGrpc = grpc.loadGrpc;
exports.constructSettingsGrpc = grpc.constructSettingsGrpc;
exports.grpc = grpc;
exports.createByteLengthFunction = grpc.createByteLengthFunction;
exports.PathTemplate = require('./lib/path_template').PathTemplate;
exports.CallSettings = gax.CallSettings;
Expand Down
167 changes: 91 additions & 76 deletions lib/grpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,119 +32,133 @@
*/
'use strict';

var GoogleAuth = require('google-auth-library');
var AuthFactory = new GoogleAuth();
var autoAuth = require('google-auto-auth');

var createCredPromise = require('./auth').createCredPromise;
var gax = require('./gax');

/**
* @callback CredentialsCallback
* @param {?Error} err - An error if authentication failed.
* @param {?grpc.ChannelCredentials} creds - A gRPC credentials if succeeded.
* A class which keeps the context of gRPC and auth for the gRPC.
*
* @param {Object=} options - The optional parameters. It will be directly
* passed to google-auto-auth library, so parameters like keyFile or
* credentials will be valid.
* @param {Object=} options.auth - An instance of google-auto-auth.
* When specified, this auth instance will be used instead of creating
* a new one.
* @param {Object=} options.grpc - When specified, this will be used
* for the 'grpc' module in this context. By default, it will load the grpc
* module in the standard way.
* @constructor
*/
function GrpcClient(options) {
if (!(this instanceof GrpcClient)) {
return new GrpcClient(options);
}
options = options || {};
this.auth = options.auth || autoAuth(options);
this.grpc = options.grpc || require('grpc');
}
module.exports = GrpcClient;

/**
* To authorize requests through gRPC, we must get the raw google-auth-library
* auth client object.
*
* Creates a gRPC credentials from the authentications.
* @private
*
* @param {CredentialsCallback} callback - The callback function.
* @param {Object=} opts - options values for configuring auth
* @param {(String|String[])} opts.scopes - the scope or scopes to use when
* obtaining the credentials.
* @param {Object} opts - options values for configuring credentials.
* @param {Object=} opts.sslCreds - when specified, this is used instead
* of default credentials.
* @param {Object=} opts.grpc - when specified, this is used as the module
* for grpc.
* of default channel credentials.
* @param {Object} auth - the authentication object.
* @return {Object} The gRPC credential object.
*/
function getCredentials(callback, opts) {
AuthFactory.getApplicationDefault(function(err, auth) {
if (err) {
callback(err);
return;
}

/* Apply any provided scope if there are required */
if (opts.scopes && auth.createScopedRequired &&
auth.createScopedRequired()) {
auth = auth.createScoped(opts.scopes);
}
var grpc = opts.grpc || require('grpc');
var sslCreds = opts.sslCreds || grpc.credentials.createSsl();
var credentials = grpc.credentials.combineChannelCredentials(
GrpcClient.prototype._getCredentials = function _getCredentials(opts, auth) {
var sslCreds = opts.sslCreds || this.grpc.credentials.createSsl();
var credentials = this.grpc.credentials.combineChannelCredentials(
sslCreds,
grpc.credentials.createFromGoogleCredential(auth)
);

callback(null, credentials);
});
}
this.grpc.credentials.createFromGoogleCredential(auth)
);
return credentials;
};

/**
* Load grpc proto services with the specific arguments.
* @param {Object=} optGrpc - The grpc module when specified. If not, it will
* load the default grpc module.
* @param {Array=} optArguments - The argument list to be passed to grpc.load().
* @return {Object} The grpc loaded result (the toplevel namespace object).
* @param {Array=} args - The argument list to be passed to grpc.load().
* @return {Object} The gRPC loaded result (the toplevel namespace object).
*/
exports.loadGrpc = function loadGrpc(optGrpc, optArguments) {
if (optArguments === undefined && Array.isArray(optGrpc)) {
optArguments = optGrpc;
optGrpc = null;
GrpcClient.prototype.load = function(args) {
if (!args) {
args = [];
} else if (!Array.isArray(args)) {
args = [args];
}
var grpc = optGrpc || require('grpc');
return grpc.load.apply(grpc, optArguments || []);
return this.grpc.load.apply(this.grpc, args);
};

exports.constructSettingsGrpc = function constructSettingsGrpc(
/**
* A wrapper of {@link constructSettings} function with under the gRPC context.
*
* Most of parameters are common among constructSettings, please take a look.
* @param {string} serviceName - The fullly-qualified name of the service.
* @param {Object} clientConfig - A dictionary of the client config.
* @param {Object} configOverrides - A dictionary of overriding configs.
* @param {number} timeout - The timeout parameter.
* @param {Object} pageDescriptors - A dictionary of method names to page
* descriptor instances.
* @param {Object} bundleDescriptors - A dictionary of method names to bundle
* descriptor instances.
* @param {Object} headers - A dictionary of additional HTTP header name to
* its value.
* @return {Object} A mapping of method names to CallSettings.
*/
GrpcClient.prototype.constructSettings = function constructSettings(
serviceName,
clientConfig,
configOverrides,
timeout,
pageDescriptors,
bundleDescriptors,
headers,
optGrpc) {
var grpc = optGrpc || require('grpc');
var metadata = new grpc.Metadata();
headers) {
var metadata = new this.grpc.Metadata();
for (var key in headers) {
metadata.set(key, headers[key]);
}
return gax.constructSettings(
serviceName,
clientConfig,
configOverrides,
grpc.status,
this.grpc.status,
timeout,
pageDescriptors,
bundleDescriptors,
{metadata: metadata});
};

/**
* Creates a promise which resolves to an rpc stub.
*
* @param {String} servicePath - The domain name of the API remote host.
* @param {Number} port - The port on which to connect to the remote host.
* @param {function()} CreateStub - The constructor used to create a grpc stub
* instance.
* @param {Object} options - optional settings. This options will be passed
* to `getCredentials`.
* @param {GetCredentialsFunc=} options.getCredentials - the callback used
* to obtain the credentials. If not specified, use the default
* implementation.
* @return {Promise} A promise which resolves to an rpc stub.
* Creates a gRPC stub with current gRPC and auth.
* @param {string} servicePath - The name of the server of the service.
* @param {number} port - The port of the service.
* @param {function} CreateStub - The constructor function of the stub.
* @param {Object=} options - The optional arguments to customize
* gRpc connection.
* @param {grpc.ClientCredentials} options.sslCreds - The credentials to be used
* to set up gRPC connection.
* @return {Promise} A promse which resolves to a gRPC stub instance.
*/
exports.createStub = function createStub(
GrpcClient.prototype.createStub = function(
servicePath, port, CreateStub, options) {
options = options || {};
var creds = createCredPromise(options.getCredentials || getCredentials,
options);
return creds.then(function buildStub(credentials) {
return new CreateStub(servicePath + ':' + port, credentials);
});
var serviceAddress = servicePath + ':' + port;
return new Promise(function(resolve, reject) {
this.auth.getAuthClient(function(err, auth) {
if (err) {
reject(err);
} else {
resolve(auth);
}
});
}.bind(this)).then(this._getCredentials.bind(this, options))
.then(function buildStub(credentials) {
return new CreateStub(serviceAddress, credentials);
});
};

/**
Expand All @@ -157,8 +171,9 @@ exports.createStub = function createStub(
* @return {function(Object):number} - a function to compute the byte length
* for an object.
*/
exports.createByteLengthFunction = function createByteLengthFunction(message) {
return function getByteLength(obj) {
return message.encode(obj).buffer.length;
};
};
GrpcClient.createByteLengthFunction =
function createByteLengthFunction(message) {
return function getByteLength(obj) {
return message.encode(obj).buffer.length;
};
};
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "google-gax",
"version": "0.5.2",
"version": "0.6.0",
"description": "Google API Extensions",
"main": "index.js",
"dependencies": {
"chai": "*",
"eventemitter2": "1.0.2",
"google-auth-library": "0.9.8",
"eventemitter2": "~1.0.2",
"google-auto-auth": "~0.2.4",
"grpc": "~0.15.0",
"lodash": "~4.11.1",
"through2": "~2.0.1"
Expand Down

0 comments on commit 242b47b

Please sign in to comment.