UNPKG

@yawetse/pkgcloud

Version:

An infrastructure-as-a-service agnostic cloud library for node.js

148 lines (130 loc) 3.98 kB
/* * service.js: Service model * * (C) 2013 Rackspace, Ken Perkins * (C) 2015 IBM Corp. * MIT LICENSE * */ var _ = require('underscore'); function matchRegion(a, b) { if (!a && !b) { return true; } else if ((!a && b) || (a && !b)) { return false; } return a.toLowerCase() === b.toLowerCase(); } /** * Service class * * @description The service class is a thin wrapper on an entry in the openstack * service catalog * * @param {object} details the data for the new service * @param {object} details.endpoints the array of endpoints * @param {String} details.name the name of the service * @param {String} details.type the type of the new service * @constructor */ var Service = function (details) { var self = this; if (!details || typeof details !== 'object') { throw new Error('details are a required argument'); } self.endpoints = details.endpoints; self.name = details.name; self.type = details.type; }; /** * Service.getEndpointUrl * * @description gets the endpoint URL for a given service, optionally providing * the region. * * @param {object} options the options for the endpoint call * @param {String} [options.region] a region to use, if provided * @param {boolean} [options.useInternal] prefer an internal endpoint, if available * @param {boolean} [options.useAdminUrl] prefer an admin endpoint, if available * * @returns {String} the endpoint uri */ Service.prototype.getEndpointUrl = function (options) { var self = this, url = null; options = options || {}; options.serviceType = options.serviceType || this.type; // if the serviceType is wrong, return null if (options.serviceType.toLowerCase() !== this.type.toLowerCase()) { return ''; } //since we don't know if this is a v2 or v3 catalog, check if the "interface" field is set on an endpoint, if so, we're v3 if (self.endpoints && self.endpoints.length > 0 && self.endpoints[0]['interface'] !== undefined) { self.v3 = true; } if (options.region) { _.each(self.endpoints, function (endpoint) { if (!endpoint.region || !matchRegion(endpoint.region, options.region)) { return; } if (self.v3 === true) { if (endpointMatchDesiredInterface(endpoint)) { url = endpoint.url; } } else { url = getUrl(endpoint); } }); } else { _.each(self.endpoints, function(endpoint) { if (url) { return; } // return the first region-less endpoint if (!endpoint.region) { url = getUrl(endpoint); } }); } /** * getUrl * * @description utility function for getEndpointUrl * @param {object} endpoint the endpoint to use * @param {string} [endpoint.internalURL] the internal URL of the endpoint * @param {string} [endpoint.publicURL] the public URL of the endpoint * * @returns {String} the uri of the endpoint */ function getUrl(endpoint) { var useInternal = typeof options.useInternal === 'boolean' ? options.useInternal : false; return useInternal && endpoint.internalURL ? endpoint.internalURL : ((typeof options.useAdmin === 'boolean' && options.useAdmin && endpoint.adminURL) ? endpoint.adminURL : endpoint.publicURL); } /** * endpointMatchDesiredInterface * * @description determine if the endpoint interface matches the desired interface * @param {object} endpoint * @returns {Boolean} */ function endpointMatchDesiredInterface(endpoint) { var interfaceToUse = 'public'; if (options.useInternal === true) { interfaceToUse = 'internal'; } else if (options.useAdmin === true) { interfaceToUse = 'admin'; } return endpoint['interface'] === interfaceToUse; } if (!url) { throw new Error('Unable to identify endpoint url'); } return url; }; exports.Service = Service;