diff --git a/lib/azure.js b/lib/azure.js index 6271618db9..8d32ca0fcf 100644 --- a/lib/azure.js +++ b/lib/azure.js @@ -201,6 +201,31 @@ exports.createSqlManagementService = function (subscriptionId, authentication, h return new SqlManagementService(subscriptionId, authentication, hostOptions); }; +var HDInsightService = require('./services/serviceManagement/hdinsightservice'); +exports.HDInsightService = HDInsightService; + +/** +* Creates a new HDInsightService object. +* +* @param {string} subscriptionId The subscription ID for the account. +* @param {string} authentication The authentication object for the client. +* { +* keyfile: 'path to .pem', +* certfile: 'path to .pem', +* keyvalue: privatekey value, +* certvalue: public cert value +* } +* @param {string} hostOptions The host options to override defaults. +* { +* host: 'management.core.windows.net', +* apiversion: '2012-03-01', +* serializetype: 'XML' +* } +*/ +exports.createHDInsightService = function (subscriptionId, authentication, hostOptions) { + return new HDInsightService(subscriptionId, authentication, hostOptions); +}; + /** * ServiceBusManagementService client exports. */ @@ -269,4 +294,4 @@ exports.date = require('./util/date'); */ exports.isEmulated = function (host) { return exports.ServiceClient.isEmulated(host); -}; \ No newline at end of file +}; diff --git a/lib/services/serviceManagement/hdinsightnamespaceutils.js b/lib/services/serviceManagement/hdinsightnamespaceutils.js new file mode 100644 index 0000000000..e0b63b4a13 --- /dev/null +++ b/lib/services/serviceManagement/hdinsightnamespaceutils.js @@ -0,0 +1,59 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// External dependencies +var crypto = require('crypto'); + +function HDInsightNamespace() { + +} + +function _LongUnsignedRor(value, count) { + for(var i = 0; i= i ; j--) { + loopValue += data[j] * multiplier; + multiplier = multiplier * 256; + } + + // Converts them into base32 + var bytes = Math.min(data.length - i, 5); + for (var bitOffset = (bytes+1)*8 - 5; bitOffset > 3; bitOffset -= 5) { + var index = _LongUnsignedRor(loopValue,bitOffset) % 32; + result += base32StandardAlphabet[index]; + } + } + return result; +} + +HDInsightNamespace.prototype.GetNameSpace = function (subscriptionId, prefix, location) { + location = location.replace(' ', '-'); + var hash = crypto.createHash('sha256').update(new Buffer(subscriptionId, 'utf-8')).digest('hex'); + return prefix + _Base32NoPaddingEncode(new Buffer(hash, 'hex')) + '-' + location; +}; + +module.exports = HDInsightNamespace; diff --git a/lib/services/serviceManagement/hdinsightservice.js b/lib/services/serviceManagement/hdinsightservice.js new file mode 100644 index 0000000000..20e4e328a6 --- /dev/null +++ b/lib/services/serviceManagement/hdinsightservice.js @@ -0,0 +1,304 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Module dependencies. +var util = require('util'); +var azureUtil = require('../../util/util.js'); +var js2xml = require('../../util/js2xml'); +var _ = require('underscore'); +var uuid = require('node-uuid'); +var Validate = require('../../util/validate.js'); + +var ServiceManagementClient = require('../core/servicemanagementclient'); + +// var js2xml = require('../../util/js2xml'); +// var Constants = require('../../util/constants'); + +/** +* +* Creates a new HDInsightService object +* +* @constructor +* @param {string} subscriptionId Subscription ID for the account or the connection string +* @param {object} authentication The authentication object for the client. +* { +* keyfile: 'path to .pem', +* certfile: 'path to .pem', +* keyvalue: privatekey value, +* certvalue: public cert value +* } +* @param {object} hostOptions The host options to override defaults. +* { +* host: 'management.core.windows.net', +* apiversion: '2012-03-01', +* serializetype: 'XML' +* } +*/ +function HDInsightService(subscriptionId, authentication, hostOptions) { + if (typeof subscriptionId != 'string' || subscriptionId.length === 0) { + throw new Error('A subscriptionId or a connection string is required'); + } + + if (!hostOptions) { + hostOptions = { }; + } + + hostOptions.serializetype = 'XML'; + HDInsightService['super_'].call(this, authentication, hostOptions); + + this.subscriptionId = subscriptionId; +} + +util.inherits(HDInsightService, ServiceManagementClient); + +var WebResource = require('../../http/webresource'); + +/** +* +* Converts a cluster creation object into a playload that is actually sent to the server to create the cluster. +* +* @param {object} clusterCreationObject The object used to supply all parameters needed to create a cluster. +* { +* // the following are required fields +* name: 'the name of the cluster (dns name) all lower case', +* location: 'the Azure data center where the cluster is to be created', +* defaultStorageAccountName: 'The name of the default Azure storage account', +* defaultStorageAccountKey: 'The secret key for the default Azure storage account', +* defaultStorageContainer: 'The container for the default Azure storage account', +* user: 'The username to use for the cluster', +* password: 'The password to use for the cluster', +* nodes: number // The number of nodes to use +* // the following are optional fields +* additionalStorageAccounts : [ { +* name: 'the name of the storage acount' +* key: 'the secret key for the storage acount' +* }, { // additional accounts following the same pattern } +* ] +* // the following are optional but if one is specified the other is required +* oozieMetastore : { +* server : 'the name of the sql server to use', +* database : 'the sql databse to use' +* user : 'the user name to use when logging into the database' +* password : 'the password to use when logging into the database' +* } +* hiveMetastore : { +* server : 'the name of the sql server to use', +* database : 'the sql databse to use' +* user : 'the user name to use when logging into the database' +* password : 'the password to use when logging into the database' +* } +* } +*/ +HDInsightService.prototype.convertCreationObject = function (clusterCreationObject) { + var payload = { + Resource : { + '$' : { 'xmlns' : 'http://schemas.microsoft.com/windowsazure' }, + IntrinsicSettings : { + ClusterContainer : { + '$' : { xmlns : 'http://schemas.datacontract.org/2004/07/Microsoft.ClusterServices.DataAccess.Context' }, + AzureStorageLocation : clusterCreationObject.location, + Deployment : { + ASVAccounts : { + ASVAccount : [{ + AccountName : clusterCreationObject.defaultStorageAccountName, + BlobContainerName : clusterCreationObject.defaultStorageContainer, + SecretKey : clusterCreationObject.defaultStorageAccountKey + }] + }, + ClusterPassword : clusterCreationObject.password, + ClusterUsername : clusterCreationObject.user, + NodeSizes : { + ClusterNodeSize : [ + { + Count : 1, + RoleType : 'HeadNode', + VMSize : 'ExtraLarge' + }, + { + Count : clusterCreationObject.nodes, + RoleType : 'DataNode', + VMSize : 'Large' + } + ] + }, + SqlMetaStores : { }, + Version : 'default' + }, + DeploymentAction : 'Create', + DnsName : clusterCreationObject.name, + IncarnationID : uuid.v4(), + SubscriptionId : this.subscriptionId + } + } + } + }; + if (clusterCreationObject.additionalStorageAccounts) { + for (var i = 0; i < clusterCreationObject.additionalStorageAccounts.length; i++) { + var account = { + AccountName : clusterCreationObject.additionalStorageAccounts[i].name, + BlobContainerName : 'deployment1', + SecretKey : clusterCreationObject.additionalStorageAccounts[i].key + }; + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount.push(account); + } + } + if (clusterCreationObject.oozieMetastore) { + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.SqlMetaStores.SqlAzureMetaStore = []; + var oozieMetastore = { + '$' : { xmlns: 'http://schemas.datacontract.org/2004/07/Microsoft.ClusterServices.DataAccess' }, + AzureServerName : clusterCreationObject.oozieMetastore.server, + DatabaseName : clusterCreationObject.oozieMetastore.database, + Password : clusterCreationObject.oozieMetastore.password, + Type : 'OozieMetastore', + Username : clusterCreationObject.oozieMetastore.user + }; + var hiveMetastore = { + '$' : { xmlns: 'http://schemas.datacontract.org/2004/07/Microsoft.ClusterServices.DataAccess' }, + AzureServerName : clusterCreationObject.hiveMetastore.server, + DatabaseName : clusterCreationObject.hiveMetastore.database, + Password : clusterCreationObject.hiveMetastore.password, + Type : 'OozieMetastore', + Username : clusterCreationObject.hiveMetastore.user + }; + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.SqlMetaStores.SqlAzureMetaStore.push(oozieMetastore); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.SqlMetaStores.SqlAzureMetaStore.push(hiveMetastore); + } + return payload; +}; + +HDInsightService.prototype.deleteCluster = function (callback) { + callback('ERROR', null); +}; + +/** +* +* Creates a new HDInsight Cluster +* +* @param {object} clusterCreationObject // The details of the cluster to create +* { +* // the following are required fields +* name: 'the name of the cluster (dns name) all lower case', +* location: 'the Azure data center where the cluster is to be created', +* defaultStorageAccountName: 'The name of the default Azure storage account', +* defaultStorageAccountKey: 'The secret key for the default Azure storage account', +* defaultStorageContainer: 'The container for the default Azure storage account', +* user: 'The username to use for the cluster', +* password: 'The password to use for the cluster', +* nodes: number // The number of nodes to use +* // the following are optional fields +* additionalStorageAccounts : [ { +* name: 'the name of the storage acount' +* key: 'the secret key for the storage acount' +* }, { // additional accounts following the same pattern } +* ] +* // the following are optional but if one is specified the other is required +* oozieMetastore : { +* server : 'the name of the sql server to use', +* database : 'the sql databse to use' +* user : 'the user name to use when logging into the database' +* password : 'the password to use when logging into the database' +* } +* hiveMetastore : { +* server : 'the name of the sql server to use', +* database : 'the sql databse to use' +* user : 'the user name to use when logging into the database' +* password : 'the password to use when logging into the database' +* } +* } +* @param {function} callback +* +* +* +*/ +HDInsightService.prototype.createCluster = function (clusterCreationObject, callback) { + // Convert the simply form "clusterCreationObject" into the complex form "payload" needed by the server REST call. + Validate.isValidHDInsightCreationObject(clusterCreationObject); + var payload = this.convertCreationObject(clusterCreationObject); + var regionCloudServiceName = azureUtil.getNameSpace(this.subscriptionId, 'hdinsight' , 'East US'); + var path = '/' + this.subscriptionId + '/cloudservices/' + regionCloudServiceName + '/resources/hdinsight/containers/' + payload.Resource.IntrinsicSettings.ClusterContainer.DnsName; + var webResource = WebResource.put(path); + webResource.withHeader('x-ms-version', '2011-08-18'); + webResource.withHeader('accept', 'application/xml'); + this.performRequest(webResource, js2xml.serialize(payload), null, function (responseObject, next) { + var finalCallback = function (returnObject) { + callback(returnObject.error, returnObject.response); + }; + + next(responseObject, finalCallback); + }); +}; + +/** +* +* Lists all HDInsight clusters current existing on the subscription. +* @param {function} callback +* +*/ +HDInsightService.prototype.listClusters = function (callback) { + var path = '/' + this.subscriptionId + '/cloudservices'; + var webResource = WebResource.get(path); + webResource.withHeader('x-ms-version', '2011-08-18'); + webResource.withHeader('accept', 'application/xml'); + + this.performRequest(webResource, null, null, function (responseObject , next) { + var cloudServices = []; + if (!responseObject.error) { + if (responseObject.response && responseObject.response.body && + responseObject.response.body.CloudServices && responseObject.response.body.CloudServices.CloudService) { + + if (!_.isArray(responseObject.response.body.CloudServices.CloudService)) { + responseObject.response.body.CloudServices.CloudService = [ responseObject.response.body.CloudServices.CloudService ]; + } + + var cloudService = responseObject.response.body.CloudServices.CloudService; + + for (var i = 0; i < cloudService.length; i++) { + if (cloudService[i].Name && + cloudService[i].Name.indexOf('hdinsight') === 0) { + var resources = []; + + if (cloudService[i].Resources && cloudService[i].Resources.Resource) { + if (!_.isArray(cloudService[i].Resources.Resource)) { + cloudService[i].Resources.Resource = [ cloudService[i].Resources.Resource ]; + } + + var resource = cloudService[i].Resources.Resource; + for (var j = 0; j < resource.length; j++) { + if (resource[j].ResourceProviderNamespace == 'hdinsight') { + resources.push(resource[j]); + } + } + cloudService[i].Resources.Resource = resources; + } + + cloudServices.push (cloudService[i]); + } + + responseObject.response.body.CloudServices.CloudService = cloudServices; + } + + } + } + + var finalCallback = function (returnObject) { + callback(returnObject.error, returnObject.response); + }; + + next(responseObject, finalCallback); + + }); +}; + +module.exports = HDInsightService; \ No newline at end of file diff --git a/lib/util/util.js b/lib/util/util.js index f58bf40320..4dfb92c847 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -15,6 +15,7 @@ var fs = require('fs'); var path = require('path'); +var assert = require('assert'); var crypto = require('crypto'); var _ = require('underscore'); @@ -265,6 +266,65 @@ exports.tryGetValueInsensitive = function (key, haystack, defaultValue) { return defaultValue; }; +function _LongUnsignedRor(value, count) { + for(var i = 0; i= i ; j--) { + loopValue += data[j] * multiplier; + multiplier = multiplier * 256; + } + + // Converts them into base32 + var bytes = Math.min(data.length - i, 5); + for (var bitOffset = (bytes+1)*8 - 5; bitOffset > 3; bitOffset -= 5) { + var index = _LongUnsignedRor(loopValue,bitOffset) % 32; + result += base32StandardAlphabet[index]; + } + } + return result; +} + +/** +* Returns the namespace for a subscriptoinId, prefix and location +* +* @subscriptionId {string} The Azure subscription id. +* @prefix {string} The prifix for the service. +* @location {string} The location of the service. +* @return {Bool} True if the value is an integer number; false otherwise. +*/ +exports.getNameSpace = function (subscriptionId, prefix, location) { + location = location.replace(' ', '-'); + var hash = crypto.createHash('sha256').update(new Buffer(subscriptionId, 'utf-8')).digest('hex'); + return prefix + _Base32NoPaddingEncode(new Buffer(hash, 'hex')) + '-' + location; +}; + +/** +* Determines if a value (string or number) is an integer number. +* +* @param {object} The value to assess. +* @return {Bool} True if the value is an integer number; false otherwise. +*/ +exports.isInt = function (value){ + if((parseFloat(value) == parseInt(value, 10)) && !isNaN(value)) { + return true; + } + else { + return false; + } +}; + /** * Returns the value in a chained object. * @@ -345,4 +405,56 @@ exports.analyzeStream = function (stream, calculateMD5, callback) { }); }; +function pollRequest(channel, reqid, callback) { +  channel.getOperationStatus(reqid, function(error, response) { +    if (error) { +      callback(error, { isSuccessful: false }); +    } else { +      assert.ok(response.isSuccessful); +      var body = response.body; +      if (body.Status === 'InProgress') { +        setTimeout(function() { +          pollRequest(channel, reqid, callback); +        }, exports.POLL_REQUEST_INTERVAL); +      } else if (body.Status === 'Failed') { +        callback(body.Error, { isSuccessful: false,  statusCode: body.HttpStatusCode}); +      } else { +        callback(null, { isSuccessful: true,  statusCode: body.HttpStatusCode}); +      } +    } +  }); +} + +exports.doServiceManagementOperation = function(channel, operation) { +  var callback = arguments[arguments.length - 1]; + +  /*jshint camelcase:false*/ +  function callback_(error, response) { +    if (error) { +      callback(error, response); +    } else { +      if (response.statusCode === 200) { +        callback(null, response); +      } else { +        // poll +        pollRequest(channel, response.headers['x-ms-request-id'], function(error, response) { +          if (error) { +            callback(error, response); +          } else { +            callback(null, response); +          } +        }); +      } +    } +  } + +  var args = Array.prototype.slice.call(arguments).slice(2, arguments.length - 1); +  args.push(callback_); +  if (!channel[operation]) { +    throw new Error('Incorrect service management operarion requested : ' + operation); +  } + +  channel[operation].apply(channel, args); +}; + exports.pathExistsSync = fs.existsSync ? fs.existsSync : path.existsSync; \ No newline at end of file diff --git a/lib/util/validate.js b/lib/util/validate.js index 57037f666f..c7caabf33b 100644 --- a/lib/util/validate.js +++ b/lib/util/validate.js @@ -36,6 +36,120 @@ exports.isValidUri = function (uri) { } }; +/** +* +* Validates that a clusterCreationObject is properly formed. +* +* @param {object} clusterCreationObject The object used to supply all parameters needed to create a cluster. +* { +* // the following are required fields +* name: 'the name of the cluster (dns name) all lower case', +* location: 'the Azure data center where the cluster is to be created', +* defaultStorageAccountName: 'The name of the default Azure storage account', +* defaultStorageAccountKey: 'The secret key for the default Azure storage account', +* defaultStorageContainer: 'The container for the default Azure storage account', +* user: 'The username to use for the cluster', +* password: 'The password to use for the cluster', +* nodes: number // The number of nodes to use +* // the following are optional fields +* additionalStorageAccounts : [ { +* name: 'the name of the storage acount' +* key: 'the secret key for the storage acount' +* }, { // additional accounts following the same pattern } +* ] +* // the following are optional but if one is specified the other is required +* oozieMetastore : { +* server : 'the name of the sql server to use', +* database : 'the sql databse to use' +* user : 'the user name to use when logging into the database' +* password : 'the password to use when logging into the database' +* } +* hiveMetastore : { +* server : 'the name of the sql server to use', +* database : 'the sql databse to use' +* user : 'the user name to use when logging into the database' +* password : 'the password to use when logging into the database' +* } +* } +*/ +exports.isValidHDInsightCreationObject = function (clusterCreationObject) { + if (typeof(clusterCreationObject.name) != 'string') { + throw new Error('The [name] field is required when creating a cluster and must be a string'); + } + if (typeof(clusterCreationObject.location) != 'string') { + throw new Error('The [location] field is required when creating a cluster and must be a string'); + } + if (typeof(clusterCreationObject.defaultStorageAccountName) != 'string') { + throw new Error('The [defaultStorageAccountName] field is required when creating a cluster and must be a string'); + } + if (typeof(clusterCreationObject.defaultStorageAccountKey) != 'string') { + throw new Error('The [defaultStorageAccountKey] field is required when creating a cluster and must be a string'); + } + if (typeof(clusterCreationObject.defaultStorageContainer) != 'string') { + throw new Error('The [defaultStorageContainer] field is required when creating a cluster and must be a string'); + } + if (!this.containerNameIsValid(clusterCreationObject.defaultStorageContainer, function() {})) { + throw new Error('The [defaultStorageContainer] field is required when creating a cluster and must be a valid storage container name'); + } + if (typeof(clusterCreationObject.user) != 'string') { + throw new Error('The [user] field is required when creating a cluster and must be a string'); + } + if (typeof(clusterCreationObject.password) != 'string') { + throw new Error('The [password] field is required when creating a cluster and must be a string'); + } + if (typeof(clusterCreationObject.nodes) != 'number' || !azureutil.isInt(clusterCreationObject.nodes)) { + throw new Error('The [nodes] field is required when creating a cluster and must be an integer'); + } + if (clusterCreationObject.additionalStorageAccounts) { + if (!_.isArray(clusterCreationObject.additionalStorageAccounts)) { + throw new Error('The [additionalStorageAccounts] field is optional when creating a cluster but must be an array when specified'); + } + for (var i = 0; i < clusterCreationObject.additionalStorageAccounts.length; i++) { + var account = clusterCreationObject.additionalStorageAccounts[i]; + if (typeof(account.name) != 'string') { + throw new Error('The [additionalStorageAccounts] field is optional but if supplied each element must have a [name] field and it must be a string. Element ' + i + ' does not have a [name] field or it is not a string'); + } + if (typeof(account.key) != 'string') { + throw new Error('The [additionalStorageAccounts] field is optional but if supplied each element must have a [key] field and it must be a string. Element ' + i + ' does not have a [key] field or it is not a string'); + } + } + } + if (clusterCreationObject.oozieMetastore) { + if (!clusterCreationObject.hiveMetastore) { + throw new Error('If the [oozieMetastore] field is supplied, than the [hiveMetastore] field must also be supplied'); + } + if (typeof(clusterCreationObject.oozieMetastore.server) != 'string') { + throw new Error('If the [oozieMetastore] field is supplied it must contain a [server] field which must be a string'); + } + if (typeof(clusterCreationObject.oozieMetastore.database) != 'string') { + throw new Error('If the [oozieMetastore] field is supplied it must contain a [database] field which must be a string'); + } + if (typeof(clusterCreationObject.oozieMetastore.user) != 'string') { + throw new Error('If the [oozieMetastore] field is supplied it must contain a [user] field which must be a string'); + } + if (typeof(clusterCreationObject.oozieMetastore.password) != 'string') { + throw new Error('If the [oozieMetastore] field is supplied it must contain a [password] field which must be a string'); + } + } + if (clusterCreationObject.hiveMetastore) { + if (!clusterCreationObject.oozieMetastore) { + throw new Error('If the [hiveMetastore] field is supplied, than the [oozieMetastore] field must also be supplied'); + } + if (typeof(clusterCreationObject.hiveMetastore.server) != 'string') { + throw new Error('If the [hiveMetastore] field is supplied it must contain a [server] field which must be a string'); + } + if (typeof(clusterCreationObject.hiveMetastore.database) != 'string') { + throw new Error('If the [hiveMetastore] field is supplied it must contain a [database] field which must be a string'); + } + if (typeof(clusterCreationObject.hiveMetastore.user) != 'string') { + throw new Error('If the [hiveMetastore] field is supplied it must contain a [user] field which must be a string'); + } + if (typeof(clusterCreationObject.hiveMetastore.password) != 'string') { + throw new Error('If the [hiveMetastore] field is supplied it must contain a [password] field which must be a string'); + } + } +}; + /** * Creates a anonymous function that check if a given key is base 64 encoded. * diff --git a/package.json b/package.json index b80154c3bb..0789ab3a34 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "tunnel": ">= 0.0.1", "request": ">= 2.9.203", "validator": ">= 0.4.12", - "wns": ">= 0.5.3" + "wns": ">= 0.5.3", + "encdec": ">= 0.1.3" }, "devDependencies": { "mocha": "*", diff --git a/test/services/HDInsight/PerformRequestStubUtil.js b/test/services/HDInsight/PerformRequestStubUtil.js new file mode 100644 index 0000000000..091b5da28b --- /dev/null +++ b/test/services/HDInsight/PerformRequestStubUtil.js @@ -0,0 +1,94 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var mockData = null; + +var sinon = require('sinon'); +var _performRequestOriginal; +var _performRequestStub; +var _originalClass; +var _lastWebResource; + +function PerformRequestStubUtil(originalClass) { + _originalClass = originalClass; + _performRequestOriginal = originalClass.prototype._performRequest; + originalClass.prototype._performRequestOriginal = originalClass.prototype._performRequest; + _performRequestStub = sinon.stub(originalClass.prototype, '_performRequest', function(webResource, body, options, callback) { + _lastWebResource = webResource; + var response; + var result; + if (!mockData) { + this._performRequestOriginal(webResource, body, options, callback); + } + else if (mockData.errorCode) { + response = { + isSuccessful: false, + statusCode: mockData.statusCode, + body: { Error: { '$': {}, Code: mockData.errorCode, Message: mockData.message } } + }; + + var err = []; + err['Error'] = mockData.message; + err.code = mockData.errorCode; + result = { error: err, response: response }; + callback(result, function(responseObject, finalCallback) { + finalCallback(responseObject); + }); + } + else if (mockData.body) { + response = { + isSuccessful: true, + statusCode: 200, + body: mockData.body + }; + result = { error: null, response: response }; + callback(result, function(responseObject, finalCallback) { + finalCallback(responseObject); + }); + } + }); + originalClass.prototype._performRequest = _performRequestStub; + // hdInsight._performRequest = function(webResource, body, options, callback) { + // if (!isMocked) { + // _performRequestOriginal(webResource, body, options, callback); + // } +} + +module.exports = PerformRequestStubUtil; + +PerformRequestStubUtil.prototype.GetLastWebResource = function() { + return _lastWebResource; +}; + +PerformRequestStubUtil.prototype.StubAuthenticationFailed = function(url) { + var msg = 'The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.'; + this.StubProcessRequestWithError(url, 403, 'AuthenticationFailed', msg); +}; + +PerformRequestStubUtil.prototype.StubProcessRequestWithError = function(url, statusCode, errorCode, message) { + mockData = { statusCode: statusCode, errorCode: errorCode, message: message }; +}; + +PerformRequestStubUtil.prototype.NoStubProcessRequest = function() { + mockData = null; +}; + +PerformRequestStubUtil.prototype.StubProcessRequestWithSuccess = function(url, body) { + mockData = { body: body }; +}; + +PerformRequestStubUtil.prototype.Revert = function() { + _originalClass.prototype._performRequest = _performRequestOriginal; +}; \ No newline at end of file diff --git a/test/services/HDInsight/creds.xml b/test/services/HDInsight/creds.xml new file mode 100644 index 0000000000..80e5e85271 --- /dev/null +++ b/test/services/HDInsight/creds.xml @@ -0,0 +1,63 @@ + + + + default + {subscription Id} + path to valid .cer file + path to invalid .cer file + known-cluster + https://known-cluster.azurehdinsight.net:563 + userName + PASSWORD + hadoop + + https://umapi.rdfetest.dnsdemo4.com:8443 + hadoopservicesnightly + {subscription Id} + + + default-storage-account.blob.core.windows.net + SECRET KEY + deployment1 + + + + additional-storage-account.blob.core.windows.net + SECREATE KEY + deployment1 + + + + + HiveDB1 + some-server.database.windows.net + somedbname-hive + dbusername + dbpassword + + + HiveDB2 + some-server.database.windows.net + somedbname-hive + dbusername + dbpassword + + + + + OozieDB1 + some-server2.database.windows.net + somedbname-oozie + dbusername + dbpassword + + + OozieDB2 + some-server2.database.windows.net + somedbname-oozie + dbusername + dbpassword + + + + \ No newline at end of file diff --git a/test/services/HDInsight/hdinsight-createCluster-unit-tests.js b/test/services/HDInsight/hdinsight-createCluster-unit-tests.js new file mode 100644 index 0000000000..e1e36d9c5d --- /dev/null +++ b/test/services/HDInsight/hdinsight-createCluster-unit-tests.js @@ -0,0 +1,1194 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var mocha = require('mocha'); +var should = require('should'); +var _ = require('underscore'); +var HDInsightTestUtils = require('./hdinsight-test-utils.js'); +var HDInsightNamespace = require('../../../lib/services/serviceManagement/hdinsightnamespaceutils.js'); + +// Test includes +var testutil = require('../../util/util'); + +var PerformRequestStubUtil = require('./PerformRequestStubUtil.js'); + +var azure = testutil.libRequire('azure'); +var performRequestStubUtil; + +describe('HDInsight createCluster (under unit test)', function() { + var subscriptionId = process.env['AZURE_SUBSCRIPTION_ID']; + var auth = { keyvalue: testutil.getCertificateKey(), certvalue: testutil.getCertificate() }; + var HDInsight = require('../../../lib/services/serviceManagement/hdinsightservice.js'); + var hdInsight = azure.createHDInsightService(subscriptionId, auth); + var hdinsightTestUtils = new HDInsightTestUtils(); + + beforeEach(function (done) { + performRequestStubUtil.NoStubProcessRequest(); + done(); + }); + + afterEach(function (done) { + performRequestStubUtil.NoStubProcessRequest(); + done(); + }); + + after(function (done) { + performRequestStubUtil.Revert(); + done(); + }); + + // NOTE: To Do, we should actually create new acounts for our tests + // So that we can work on any existing subscription. + before (function (done) { + performRequestStubUtil = new PerformRequestStubUtil(HDInsight); + done(); + }); + + it('should pass the error to the callback function', function(done) { + performRequestStubUtil.StubAuthenticationFailed('http://test.com'); + var clusterCreationObject = hdinsightTestUtils.getDefaultWithAsvAndMetastores(); + hdInsight.createCluster(clusterCreationObject, function (err, response) { + should.exist(err); + response.statusCode.should.be.eql(403); + done(); + }); + }); + + it('should provide the right headers for the request', function(done) { + performRequestStubUtil.StubProcessRequestWithSuccess('http://test.com', {}); + var clusterCreationObject = hdinsightTestUtils.getDefaultWithAsvAndMetastores(); + hdInsight.createCluster(clusterCreationObject, function (err) { + var webResource = performRequestStubUtil.GetLastWebResource(); + should.exist(webResource); + var namespaceUtil = new HDInsightNamespace(); + var regionCloudServiceName = namespaceUtil.GetNameSpace(subscriptionId, 'hdinsight' , 'East US'); + webResource.path.should.be.eql('/' + subscriptionId + '/cloudservices/' + regionCloudServiceName + '/resources/hdinsight/containers/' + clusterCreationObject.name); + webResource.httpVerb.should.be.eql('PUT'); + _.size(webResource.headers).should.be.eql(2); + webResource.headers['x-ms-version'].should.be.eql('2011-08-18'); + webResource.headers['accept'].should.be.eql('application/xml'); + done(err); + }); + }); + + it('should validate the name field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = {}; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [name] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the name field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [name] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the location field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [location] field is required when creating a cluster and must be a string'); + } + }) + + it('should validate the location field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [location] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageAccountName field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageAccountName] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageAccountName field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageAccountName] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageAccountKey field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageAccountKey] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageAccountKey field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageAccountKey] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageContainer field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageContainer] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageContainer field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageContainer] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the defaultStorageContainer field is not invalid', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'INVLAID' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [defaultStorageContainer] field is required when creating a cluster and must be a valid storage container name'); + } + }); + + it('should validate the user field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [user] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the user field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [user] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the password field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [password] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the password field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 4 + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [password] field is required when creating a cluster and must be a string'); + } + }); + + it('should validate the nodes field of the clusterCreationObject is not undefined', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [nodes] field is required when creating a cluster and must be an integer'); + } + }); + + it('should validate the nodes field of the clusterCreationObject is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 'not a number' + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [nodes] field is required when creating a cluster and must be an integer'); + } + }); + + it('should validate the additionalStorageAccounts field of the clusterCreationObject is an array', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [additionalStorageAccounts] field is optional when creating a cluster but must be an array when specified'); + } + }); + + it('should validate the additionalStorageAccounts elements contain a name field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ }] + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [additionalStorageAccounts] field is optional but if supplied each element must have a [name] field and it must be a string. Element 0 does not have a [name] field or it is not a string'); + } + }); + + it('should validate the additionalStorageAccounts elements contain a name field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 4 + }] + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [additionalStorageAccounts] field is optional but if supplied each element must have a [name] field and it must be a string. Element 0 does not have a [name] field or it is not a string'); + } + }); + + it('should validate the additionalStorageAccounts elements contain a key field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name' + }] + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [additionalStorageAccounts] field is optional but if supplied each element must have a [key] field and it must be a string. Element 0 does not have a [key] field or it is not a string'); + } + }); + + it('should validate the additionalStorageAccounts elements contain a key field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 4 + }] + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('The [additionalStorageAccounts] field is optional but if supplied each element must have a [key] field and it must be a string. Element 0 does not have a [key] field or it is not a string'); + } + }); + + it('should validate that if an oozie metastore is provided then a hive metastore is also provided', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied, than the [hiveMetastore] field must also be supplied'); + } + }); + + it('should validate that if a hive metastore is provided then an oozie metastore is also provided', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied, than the [oozieMetastore] field must also be supplied'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a server field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : {}, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [server] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a server field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 4 + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [server] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a database field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server' + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [database] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a database field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 4 + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [database] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a user field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database' + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [user] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a user field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 4 + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [user] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a password field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user' + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [password] field which must be a string'); + } + }); + + it('should validate that if an oozie metastore is provided then it contains a password field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 4 + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [oozieMetastore] field is supplied it must contain a [password] field which must be a string'); + } + }); + + + it('should validate that if an hive metastore is provided then it contains a server field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : {} + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [server] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a server field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 4 + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [server] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a database field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 'server' + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [database] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a database field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 'server', + database : 4 + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [database] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a user field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 'server', + database : 'database' + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [user] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a user field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 'server', + database : 'database', + user : 4 + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [user] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a password field', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 'server', + database : 'database', + user : 'user' + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [password] field which must be a string'); + } + }); + + it('should validate that if an hive metastore is provided then it contains a password field and it is a string', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'test', + defaultStorageAccountKey : 'KEY', + defaultStorageContainer : 'deploy1', + user : 'user', + password : 'password', + nodes : 4, + additionalStorageAccounts : [{ + name : 'name', + key : 'KEY' + }], + oozieMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 'password' + }, + hiveMetastore : { + server : 'server', + database : 'database', + user : 'user', + password : 4 + } + }; + try + { + hdInsight.createCluster(clusterCreationObject, function(err, response) {}); + throw new Error('this line should never be reached'); + } + catch (error) + { + error.message.should.be.eql('If the [hiveMetastore] field is supplied it must contain a [password] field which must be a string'); + } + }); + + it('should convert the the clusterCreationObject with no additionalStorageAccounts and no metastores to the proper payload object', function() { + performRequestStubUtil.StubAuthenticationFailed('http://test'); + var clusterCreationObject = { + name : 'test', + location : 'East US', + defaultStorageAccountName : 'defaultAccount', + defaultStorageAccountKey : 'defaultKEY', + defaultStorageContainer : 'defaultContainer', + user : 'user', + password : 'password', + nodes : 4 + }; + var payload = hdInsight.convertCreationObject(clusterCreationObject); + should.exist(payload.Resource); + should.exist(payload.Resource.$); + should.exist(payload.Resource.$.xmlns); + payload.Resource.$.xmlns.should.be.eql('http://schemas.microsoft.com/windowsazure'); + should.exist(payload.Resource.IntrinsicSettings); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.$); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.$.xmlns); + payload.Resource.IntrinsicSettings.ClusterContainer.$.xmlns.should.be.eql('http://schemas.datacontract.org/2004/07/Microsoft.ClusterServices.DataAccess.Context'); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount.should.be.an.instanceOf(Array); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount.length.should.be.eql(1); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount[0]); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount[0].AccountName.should.be.eql('defaultAccount'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount[0].BlobContainerName.should.be.eql('defaultContainer'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ASVAccounts.ASVAccount[0].SecretKey.should.be.eql('defaultKEY'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ClusterPassword.should.be.eql('password'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.ClusterUsername.should.be.eql('user'); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes); + should.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize.should.be.an.instanceOf(Array); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize.length.should.be.eql(2); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize[0].Count.should.be.eql(1); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize[0].RoleType.should.be.eql('HeadNode'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize[0].VMSize.should.be.eql('ExtraLarge'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize[1].Count.should.be.eql(4); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize[1].RoleType.should.be.eql('DataNode'); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.NodeSizes.ClusterNodeSize[1].VMSize.should.be.eql('Large'); + should.not.exist(payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.SqlMetaStores.SqlAzureMetaStore); + payload.Resource.IntrinsicSettings.ClusterContainer.Deployment.Version.should.be.eql('default'); + payload.Resource.IntrinsicSettings.ClusterContainer.DeploymentAction.should.be.eql('Create'); + payload.Resource.IntrinsicSettings.ClusterContainer.DnsName.should.be.eql('test'); + // TODO: validate that the IncarnationID is a properly formated guid. + // payload.Resource.IntrinsicSettings.ClusterContainer.IncarnationID. should.be.a.guid(); + payload.Resource.IntrinsicSettings.ClusterContainer.SubscriptionId.should.be.eql(subscriptionId); + }); +}); diff --git a/test/services/HDInsight/hdinsight-listClusters-unit-tests.js b/test/services/HDInsight/hdinsight-listClusters-unit-tests.js new file mode 100644 index 0000000000..daf916c867 --- /dev/null +++ b/test/services/HDInsight/hdinsight-listClusters-unit-tests.js @@ -0,0 +1,160 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var mocha = require('mocha'); +var should = require('should'); +var _ = require('underscore'); + +// Test includes +var testutil = require('../../util/util'); + +var PerformRequestStubUtil = require('./PerformRequestStubUtil.js'); + +var azure = testutil.libRequire('azure'); +var performRequestStubUtil; + +describe('HDInsight listClusters (under unit test)', function() { + var subscriptionId = process.env['AZURE_SUBSCRIPTION_ID']; + var auth = { keyvalue: testutil.getCertificateKey(), certvalue: testutil.getCertificate() }; + var HDInsight = require('../../../lib/services/serviceManagement/hdinsightservice.js'); + var hdInsight = azure.createHDInsightService(subscriptionId, auth); + var creds; + + beforeEach(function (done) { + performRequestStubUtil.NoStubProcessRequest(); + done(); + }); + + afterEach(function (done) { + performRequestStubUtil.NoStubProcessRequest(); + done(); + }); + + after(function (done) { + performRequestStubUtil.Revert(); + done(); + }); + + // NOTE: To Do, we should actually create new acounts for our tests + // So that we can work on any existing subscription. + before (function (done) { + performRequestStubUtil = new PerformRequestStubUtil(HDInsight); + done(); + }); + + var goodResult = { + CloudServices: { + CloudService: [ + { Name: 'not-hdinsight' } , + { + Name: 'hdinsightHRIEVKWCABCRT3AK64SGDGFJDR7EM64QV4T5UXU23MU6ZPCWG5NQ-East-US-2', + GeoRegion: 'East US 2', + Resources: { + Resource: [ + { + ResourceProviderNamespace: 'hdinsight', + Type: 'containers', + Name: 'tsthdx00hdxcibld02', + State: 'Started', + SubState: 'Running' + }, + { + ResourceProviderNamespace: 'not-hdinsight' + } + ] + } + } + ] + } + }; + + var singleResult = { + CloudServices: { + CloudService: { + Name: 'hdinsightHRIEVKWCABCRT3AK64SGDGFJDR7EM64QV4T5UXU23MU6ZPCWG5NQ-East-US-2', + GeoRegion: 'East US 2', + Resources: { + Resource: { + ResourceProviderNamespace: 'hdinsight', + Type: 'containers', + Name: 'tsthdx00hdxcibld02', + State: 'Started', + SubState: 'Running' + } + } + } + } + }; + + it('should pass the error to the callback function', function(done) { + performRequestStubUtil.StubAuthenticationFailed('http://test.com'); + hdInsight.listClusters(function (err, response) { + should.exist(err); + response.statusCode.should.be.eql(403); + done(); + }); + }); + + it('should turn single cloudservice items and resource items into arrays', function(done) { + performRequestStubUtil.StubProcessRequestWithSuccess('http://test.com', singleResult); + hdInsight.listClusters(function (err, response) { + should.not.exist(err); + should.exist(response.body.CloudServices.CloudService); + _.isArray(response.body.CloudServices.CloudService).should.be.eql(true); + response.body.CloudServices.CloudService.length.should.be.eql(1); + should.exist(response.body.CloudServices.CloudService[0].Resources.Resource); + _.isArray(response.body.CloudServices.CloudService).should.be.eql(true); + response.body.CloudServices.CloudService.length.should.be.eql(1); + done(err); + }); + }); + + it('should provide the right headers for the request', function(done) { + performRequestStubUtil.StubProcessRequestWithSuccess('http://test.com', goodResult); + hdInsight.listClusters(function (err) { + var webResource = performRequestStubUtil.GetLastWebResource(); + should.exist(webResource); + webResource.path.should.be.eql('/' + subscriptionId + '/cloudservices'); + webResource.httpVerb.should.be.eql('GET'); + _.size(webResource.headers).should.be.eql(2); + webResource.headers['x-ms-version'].should.be.eql('2011-08-18'); + webResource.headers['accept'].should.be.eql('application/xml'); + done(err); + }); + }); + + it('should remove CloudServices not related to HDInsight', function (done) { + performRequestStubUtil.StubProcessRequestWithSuccess('http://test.com', goodResult); + hdInsight.listClusters(function (err, response) { + should.not.exist(err); + should.exist(response.body.CloudServices.CloudService); + response.body.CloudServices.CloudService.length.should.eql(1); + response.body.CloudServices.CloudService[0].Name.should.eql('hdinsightHRIEVKWCABCRT3AK64SGDGFJDR7EM64QV4T5UXU23MU6ZPCWG5NQ-East-US-2'); + done(err); + }); + }); + + it('should remove resources not representing a cluster', function (done) { + performRequestStubUtil.StubProcessRequestWithSuccess('http://test.com', goodResult); + hdInsight.listClusters(function (err, response) { + should.not.exist(err); + should.exist(response.body.CloudServices.CloudService); + response.body.CloudServices.CloudService[0].Resources.Resource.length.should.eql(1); + response.body.CloudServices.CloudService[0].Resources.Resource[0].Name.should.eql('tsthdx00hdxcibld02'); + done(err); + }); + }); + +}); diff --git a/test/services/HDInsight/hdinsight-test-utils.js b/test/services/HDInsight/hdinsight-test-utils.js new file mode 100644 index 0000000000..a0c7dec624 --- /dev/null +++ b/test/services/HDInsight/hdinsight-test-utils.js @@ -0,0 +1,154 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var fs = require('fs'); +var xml2js = require('xml2js'); +var _ = require('underscore'); +var should = require('should'); +var creds; + +function HDInsightTestUtils(callback) { + this.getTestCredentialData(function (result) { + creds = result; + should.exist(result); + if (callback) { + callback(); + } + }); +} + +module.exports = HDInsightTestUtils; + +HDInsightTestUtils.prototype.getDefaultCreds = function() { + return creds['default']; +}; + +HDInsightTestUtils.prototype.getDefaultWithAsvAndMetastores = function() { + return this.getCreationWithAsvAndMetastore('default'); +}; + +HDInsightTestUtils.prototype.getCreationWithAsvAndMetastore = function (name) { + var cred = creds[name]; + var clusterCreationObject = { + name : 'tistocks-jstest2', + location : 'East US', + defaultStorageAccountName : cred.defaultStorageAccount.name, + defaultStorageAccountKey : cred.defaultStorageAccount.key, + defaultStorageContainer : cred.defaultStorageAccount.container, + user : cred.user, + password : cred.password, + nodes : 4, + additionalStorageAccounts : [{ + name : cred.additionalStorageAccounts[0].name, + key : cred.additionalStorageAccounts[0].key + }], + oozieMetastore : { + server : cred.oozieStores[0].server, + database : cred.oozieStores[0].database, + user : cred.oozieStores[0].user, + password : cred.oozieStores[0].password + }, + hiveMetastore : { + server : cred.hiveStores[0].server, + database : cred.hiveStores[0].database, + user : cred.hiveStores[0].user, + password : cred.hiveStores[0].password + } + }; + return clusterCreationObject; +}; + +HDInsightTestUtils.prototype.getTestCredentialData = function(callback) { + var file = process.env['AZURE_HDINSIGHT_CREDENTIALFILE']; + if (!file) { + file = __dirname + '/creds.xml'; + } + var parser = new xml2js.Parser(); + fs.readFile(file, 'utf-8', function(err, data) { + parser.parseString(data, function(err, result) { + var creds = result.ArrayOfAzureTestCredentials.AzureTestCredentials; + if (!_.isArray(creds)) { + creds = [ + creds + ]; + } + var retval = { }; + for (var i = 0; i < creds.length; i++) { + var cred = { + credsName : creds[i].CredentialsName[0], + subscriptionId : creds[i].SubscriptionId[0], + dnsName : creds[i].DnsName[0], + cluster : creds[i].Cluster[0], + user : creds[i].AzureUserName[0], + password : creds[i].AzurePassword[0], + hadoopUserName : creds[i].HadoopUserName[0], + defaultStorageAccount : { + name : creds[i].DefaultStorageAccount[0].Name[0], + key : creds[i].DefaultStorageAccount[0].Key[0], + container : creds[i].DefaultStorageAccount[0].Container[0] + } + }; + if (_.isArray(creds[i].AdditionalStorageAccounts)) { + creds[i].AdditionalStorageAccounts = creds[i].AdditionalStorageAccounts[0]; + } + var accounts = creds[i].AdditionalStorageAccounts.StorageAccountCredentials; + if (!_.isArray(accounts)) { + accounts = [ accounts ]; + } + cred.additionalStorageAccounts = []; + for (var j = 0; j < accounts.length; j++) { + var account = { + name : accounts[j].Name[0], + key : accounts[j].Key[0], + container : accounts[j].Container[0] + }; + cred.additionalStorageAccounts.push(account); + } + var oozies = creds[i].OozieStores[0].MetastoreCredentials; + if (!_.isArray(oozies)) { + oozies = [ oozies ]; + } + cred.oozieStores = []; + for (j = 0; j < oozies.length; j++) { + var oozie = { + description : oozies[j].Description[0], + server : oozies[j].SqlServer[0], + database : oozies[j].Database[0], + user : oozies[j].UserName[0], + password : oozies[j].Password[0] + }; + cred.oozieStores.push(oozie); + } + var hives = creds[i].HiveStores[0].MetastoreCredentials; + if (!_.isArray(hives)) { + hives = [ hives ]; + } + cred.hiveStores = []; + for (j = 0; j < hives.length; j++) { + var hive = { + description : hives[j].Description[0], + server : hives[j].SqlServer[0], + database : hives[j].Database[0], + user : hives[j].UserName[0], + password : hives[j].Password[0] + }; + cred.hiveStores.push(hive); + } + retval[cred.credsName] = cred; + } + callback(retval); + }); + }); +}; diff --git a/test/services/HDInsight/hdinsight-tests.js b/test/services/HDInsight/hdinsight-tests.js new file mode 100644 index 0000000000..1983bd730d --- /dev/null +++ b/test/services/HDInsight/hdinsight-tests.js @@ -0,0 +1,66 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var assert = require('assert'); +var mocha = require('mocha'); +var should = require('should'); +var HDInsightTestUtils = require('./hdinsight-test-utils.js'); + +// Test includes +var testutil = require('../../util/util'); + +var azure = testutil.libRequire('azure'); + +describe('HDInsight Test', function() { + var auth = { keyvalue: testutil.getCertificateKey(), certvalue: testutil.getCertificate() }; + var hdInsight; + var hdInsightTestUtils; + + beforeEach(function (done) { + done(); + }); + + afterEach(function (done) { + done(); + }); + + after(function (done) { + done(); + }); + + before (function (done) { + hdInsightTestUtils = new HDInsightTestUtils(function () { + hdInsight = azure.createHDInsightService(hdInsightTestUtils.getDefaultCreds().subscriptionId, auth); + done(); + }); + }); + + it('should be able to create a cluster', function (done) { + var clusterCreationObject = hdInsightTestUtils.getDefaultWithAsvAndMetastores(); + hdInsight.createCluster(clusterCreationObject, function (err, response) { + done(err); + }); + }); + + it('should be able to list clusters', function (done) { + hdInsight.listClusters(function (err, response) { + should.not.exist(err); + should.exist(response.body.CloudServices); + should.exist(response.body.CloudServices.CloudService); + response.body.CloudServices.CloudService.length.should.be.above(0); + done(err); + }); + }); +}); diff --git a/test/services/HDInsight/hdinsight-unit-tests.js b/test/services/HDInsight/hdinsight-unit-tests.js new file mode 100644 index 0000000000..7519e221c6 --- /dev/null +++ b/test/services/HDInsight/hdinsight-unit-tests.js @@ -0,0 +1,115 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var assert = require('assert'); +var mocha = require('mocha'); +var should = require('should'); +var sinon = require('sinon'); +var HDInsightTestUtils = require('./hdinsight-test-utils.js') + +// Test includes +var testutil = require('../../util/util'); + +var azure = testutil.libRequire('azure'); +var hdInsightUtil; + +describe('HDInsight listClusters', function() { + + var subscriptionId = process.env['AZURE_SUBSCRIPTION_ID']; + var auth = { keyvalue: testutil.getCertificateKey(), certvalue: testutil.getCertificate() }; + var hdInsight = azure.createHDInsightService(subscriptionId, auth); + var hdinsightTestUtils = new HDInsightTestUtils(); + + beforeEach(function (done) { + done(); + }); + + afterEach(function (done) { + done(); + }); + + after(function (done) { + done(); + }); + + // NOTE: To Do, we should actually create new acounts for our tests + // So that we can work on any existing subscription. + before (function (done) { + done(); + }); + + it('should be able to access the credentail information', function() { + // hdinsightTestUtils.getTestCredentialData(function (result) { + // should.exist(result); + // }); + }); + + // it('should run tests', function (done) { + // var result; + // // hdInsightUtil.StubProcessRequestWithError(403, 'Unauthorized', 'You are not authorized'); + // result = { + // CloudServices: { + // CloudService: [ + // { Name: 'not-hdinsight' } , + // { + // Name: 'hdinsightHRIEVKWCABCRT3AK64SGDGFJDR7EM64QV4T5UXU23MU6ZPCWG5NQ-East-US-2', + // GeoRegion: 'East US 2', + // Resources: { + // Resource: [ + // { + // ResourceProviderNamespace: 'hdinsight', + // Type: 'containers', + // Name: 'tsthdx00hdxcibld02', + // State: 'Started', + // SubState: 'Running' + // }, + // { + // ResourceProviderNamespace: 'not-hdinsight' + // } + // ] + // } + // } + // ] + // } + // }; + + // hdInsightUtil.StubProcessRequestWithSuccess(result); + // hdInsight.listClusters(function (err, response) { + // console.log(err); + // console.log(response); + // should.not.exist(err); + // should.exist(response.body.CloudServices.CloudService); + // response.body.CloudServices.CloudService.length.should.eql(1); + // response.body.CloudServices.CloudService[0].Resources.Resource.length.should.eql(1); + // response.body.CloudServices.CloudService[0].Resources.Resource[0].Name.should.eql('tsthdx00hdxcibld02'); + // done(err); + // }); + // }); + + // it('should list storage accounts', function (done) { + // var result; + + // hdInsight.listClusters(function (err, response) { + // console.log(err); + // console.log(response); + // should.not.exist(err); + // // response.bar.should.eql('foo'); + // response.should.eql(''); + // // response.length.should.eql(2); + // done(err); + // }); + // }); + +}); diff --git a/test/services/HDInsight/namespace-tests.js b/test/services/HDInsight/namespace-tests.js new file mode 100644 index 0000000000..525156a13b --- /dev/null +++ b/test/services/HDInsight/namespace-tests.js @@ -0,0 +1,52 @@ +/** +* Copyright (c) Microsoft. All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Test functions +var azureUtil = require('../../../lib/util/util.js'); + +// Test includes +var assert = require('assert'); + +describe('HDInsight Namespace Test', function() { + + it('GetNameSpace should properly create namespaces', function (done) { + var subscriptionId = '0bf0b5da-dc38-4795-8595-3170ffefec48'; + var expected = 'hdinsightC2D4FSA77HSYSQLRU4V73NKI3YH2OYHQXACMRGPECIHSH7FXTUAQ-East-US'; + var result = azureUtil.getNameSpace(subscriptionId, 'hdinsight', 'East US'); + assert.equal(expected, result); + + subscriptionId = 'c72f7fde-36ec-4cdf-93bf-43f90fe5373a'; + expected = 'hdinsightGTUVH76U5MNNGTJEFMKSGQMQO7AFBW52LMZPQ22R6UUXVWBDRBVA-East-US'; + result = azureUtil.getNameSpace(subscriptionId, 'hdinsight', 'East US'); + assert.equal(expected, result); + + subscriptionId = '04066490-336b-4732-adfa-90ba5422cc84'; + expected = 'hdinsightXVS5S5SBDTTR7OJ4IOKGRTFM2M3P33KWPGP5SPYDJZYUMY73KOIQ-East-US'; + result = azureUtil.getNameSpace(subscriptionId, 'hdinsight', 'East US'); + assert.equal(expected, result); + + subscriptionId = '3cfbb7fc-1347-4eff-bf07-2e1f43084b00'; + expected = 'hdinsightVXFY2XGLQTT5PCJCDRKJXWE2W2PQZOJK3NLO4QSNHEKS32E6RM5A-East-US'; + result = azureUtil.getNameSpace(subscriptionId, 'hdinsight', 'East US'); + assert.equal(expected, result); + + subscriptionId = 'ee3733c1-5ebd-4a20-95ce-17dba36a071a'; + expected = 'hdinsightLDBRGOYTMVIJZ2ZAJZZTFFJD7N3MNFCJGONZO53VLK2V5GIEU2SQ-East-US'; + result = azureUtil.getNameSpace(subscriptionId, 'hdinsight', 'East US'); + assert.equal(expected, result); + + done(); + }); +}); diff --git a/test/testlist.txt b/test/testlist.txt index 2b27beeb9b..a5ae1c9584 100644 --- a/test/testlist.txt +++ b/test/testlist.txt @@ -1,47 +1,52 @@ -serviceruntime/roleenvironment-tests.js -serviceruntime/runtimeversionmanager-tests.js -serviceruntime/runtimeversionprotocolclient-tests.js -services/blob/internal/sharedaccesssignature-tests.js -services/blob/internal/sharedkey-tests.js -services/blob/internal/sharedkeylite-tests.js -services/blob/blobservice-tests.js -services/blob/blobservice-gb-tests.js -services/blob/filters-tests.js -services/core/connectionstringparser-tests.js -services/core/serviceclient-tests.js -services/core/exponentialretrypolicyfilter-tests.js -services/core/linearretrypolicyfilter-tests.js -services/core/servicesettings-tests.js -services/core/servicebussettings-tests.js -services/core/servicemanagementsettings-tests.js -services/core/storageservicesettings-tests.js -services/queue/queueservice-tests.js -services/serviceBus/internal/wraptokenmanager-tests.js -services/serviceBus/apnsservice-tests.js -services/serviceBus/apnsservice-registrations-tests.js -services/serviceBus/servicebusservice-tests.js -services/serviceBus/notificationhubs-tests.js -services/serviceBus/wnsservice-tests.js -services/serviceBus/wnsservice-registrations-tests.js -services/serviceBus/wrapservice-tests.js -services/serviceManagement/affinitygroup-tests.js -services/serviceManagement/servicebusmanagementservice-tests.js -services/serviceManagement/servicemanagementservice-tests.js -services/serviceManagement/sqlmanagementservice-tests.js -services/table/internal/sharedkeytable-tests.js -services/table/internal/sharedkeylitetable-tests.js -services/table/batchserviceclient-tests.js -services/table/tabledatatype-tests.js -services/table/tablequery-tests.js -services/table/tableservice-batch-tests.js -services/table/tableservice-tablequery-tests.js -services/table/tableservice-gb-tests.js -services/table/tableservice-tests.js -services/sqlAzure/sqlservice-tests.js -util/date-tests.js -util/edmtype-tests.js -util/iso8061date-tests.js -util/odatahandler-tests.js -util/util-tests.js -util/validate-tests.js -azure-tests.js \ No newline at end of file +# serviceruntime/roleenvironment-tests.js +# serviceruntime/runtimeversionmanager-tests.js +# serviceruntime/runtimeversionprotocolclient-tests.js +# services/blob/internal/sharedaccesssignature-tests.js +# services/blob/internal/sharedkey-tests.js +# services/blob/internal/sharedkeylite-tests.js +# services/blob/blobservice-tests.js +# services/blob/blobservice-gb-tests.js +# services/blob/filters-tests.js +# services/core/connectionstringparser-tests.js +# services/core/serviceclient-tests.js +# services/core/exponentialretrypolicyfilter-tests.js +# services/core/linearretrypolicyfilter-tests.js +# services/core/servicesettings-tests.js +# services/core/servicebussettings-tests.js +# services/core/servicemanagementsettings-tests.js +# services/core/storageservicesettings-tests.js +# services/queue/queueservice-tests.js +# services/serviceBus/internal/wraptokenmanager-tests.js +# services/serviceBus/apnsservice-tests.js +# services/serviceBus/apnsservice-registrations-tests.js +# services/serviceBus/servicebusservice-tests.js +# services/serviceBus/notificationhubs-tests.js +# services/serviceBus/wnsservice-tests.js +# services/serviceBus/wnsservice-registrations-tests.js +# services/serviceBus/wrapservice-tests.js +# services/serviceManagement/affinitygroup-tests.js +# services/serviceManagement/servicebusmanagementservice-tests.js +# services/serviceManagement/servicemanagementservice-tests.js +# services/serviceManagement/sqlmanagementservice-tests.js +# services/table/internal/sharedkeytable-tests.js +# services/table/internal/sharedkeylitetable-tests.js +# services/table/batchserviceclient-tests.js +# services/table/tabledatatype-tests.js +# services/table/tablequery-tests.js +# services/table/tableservice-batch-tests.js +# services/table/tableservice-tablequery-tests.js +# services/table/tableservice-tests.js +# services/table/tableservice-gb-tests.js +# services/sqlAzure/sqlservice-tests.js +# util/date-tests.js +# util/edmtype-tests.js +# util/iso8061date-tests.js +# util/odatahandler-tests.js +# util/util-tests.js +# util/validate-tests.js +# azure-tests.js +# services/HDInsight/hdinsight-tests.js +# services/HDInsight/hdinsight-unit-tests.js +services/HDInsight/hdinsight-listClusters-unit-tests.js +services/HDInsight/hdinsight-createCluster-unit-tests.js +services/HDInsight/namespace-tests.js