From a4284d310a8d955cfb71c204918dc54e5c79ace0 Mon Sep 17 00:00:00 2001 From: Andre Rodrigues Date: Thu, 8 Nov 2012 15:18:17 +0000 Subject: [PATCH 1/4] Adding missing storage account operations --- .../models/servicemanagementserialize.js | 75 +++++++++++++++ .../servicemanagementservice.js | 92 ++++++++++++++++++- 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/lib/services/serviceManagement/models/servicemanagementserialize.js b/lib/services/serviceManagement/models/servicemanagementserialize.js index dad6a7d17..175a2d6e0 100644 --- a/lib/services/serviceManagement/models/servicemanagementserialize.js +++ b/lib/services/serviceManagement/models/servicemanagementserialize.js @@ -130,6 +130,81 @@ ServiceManagementSerialize.prototype.buildCreateStorageAccount = function(servic } }; +/** +* Create the message body for UpdateStorageAccount +* +* @param {string} serviceName The name of the service. +* @param {object} serviceOptions The properties for the new service. +* @param {object} client The servicemanagement object. +*/ +ServiceManagementSerialize.prototype.buildUpdateStorageAccount = function(serviceName, serviceOptions, client) { + var encLabel = undefined; + if (serviceOptions.Label) { + encLabel = new Buffer(serviceOptions.Label).toString('base64'); + } + + if (client.serializetype === 'XML') { + var doc = _createXmlRoot('UpdateStorageServiceInput'); + _addDefinedValueXml(doc, 'ServiceName', serviceName); + + if (encLabel) { + _addDefinedValueXml(doc, 'Label', encLabel); + } + + if (serviceOptions.Description) { + _addDefinedValueXml(doc, 'Description', serviceOptions.Description); + } + + if (serviceOptions.GeoReplicationEnabled) { + _addDefinedValueXml(doc, 'GeoReplicationEnabled', serviceOptions.GeoReplicationEnabled); + } + + return doc.toString(); + } else { + var jdoc = { + ServiceName: serviceName + }; + + if (encLabel) { + jdoc.Label = encLabel; + } + + if (serviceOptions.Description) { + jdoc.Description = serviceOptions.Description; + } + + if (serviceOptions.GeoReplicationEnabled) { + jdoc.GeoReplicationEnabled = serviceOptions.GeoReplicationEnabled; + } + + return JSON.stringify(jdoc); + } +}; + +/** +* Create the message body for RegenerateStorageKeys +* +* @param {string} serviceName The name of the service. +* @param {string} keyType The key type. +* @param {object} client The servicemanagement object. +*/ +ServiceManagementSerialize.prototype.buildRegenerateStorageKeys = function(serviceName, keyType, client) { + if (client.serializetype === 'XML') { + var doc = _createXmlRoot('RegenerateKeys'); + doc.ele('KeyType').txt(keyType); + + return doc.toString(); + } else { + var jdoc = { + RegenerateKeys: { + KeyType: keyType + } + }; + + return JSON.stringify(jdoc); + } +}; + /** * Create the message body for CreateOSImage * Use the specified serialization - for now only XML. diff --git a/lib/services/serviceManagement/servicemanagementservice.js b/lib/services/serviceManagement/servicemanagementservice.js index 3243c1130..aae84029e 100644 --- a/lib/services/serviceManagement/servicemanagementservice.js +++ b/lib/services/serviceManagement/servicemanagementservice.js @@ -570,7 +570,7 @@ ServiceManagementService.prototype.deleteHostedService = function(serviceName, c }; /** -* Returns keys of specified storage account. +* Creates a new storage account. * * @param {string} serviceName The name of the storage service. Required. * @param {string} serviceOptions Object with properties for the service. Optional @@ -628,6 +628,44 @@ ServiceManagementService.prototype.createStorageAccount = function(serviceName, }); }; +/** +* Updates a storage account. +* +* @param {string} serviceName The name of the storage service. Required. +* @param {string} serviceOptions Object with properties for the service. Optional +* { +* Description: optional. Defaults to 'Service host' +* Label: optional. Defaults to serviceName +* GeoReplicationEnabled: optional. Indicates if the geo replication is enabled. +* } +* @param {function} callback The callback function called on completion. Required. +*/ +ServiceManagementService.prototype.updateStorageAccount = function(serviceName, serviceOptions, callback) { + if (!callback) { + if (typeof serviceOptions === 'function') { + callback = serviceOptions; + serviceOptions = null; + } + } + + validateStringArgument(serviceName, 'serviceName', 'updateStorageAccount'); + validateObjectArgument(callback, 'callback', 'updateStorageAccount'); + + var path = '/' + this.subscriptionId + '/services/storageservices/' + serviceName; + var webResource = WebResource.put(path); + webResource.withOkCode(HttpConstants.HttpResponseCodes.OK_CODE, true); + + var outbody = this.serialize.buildUpdateStorageAccount(serviceName, serviceOptions, this); + this.performRequest(webResource, outbody, null, function (responseObject, next) { + + var finalCallback = function (returnObject) { + callback(returnObject.error, returnObject.response); + }; + + next(responseObject, finalCallback); + }); +}; + /** * Returns keys of specified storage account. * @@ -679,6 +717,58 @@ ServiceManagementService.prototype.getStorageAccountProperties = function(servic }); }; +/** +* Regenerates a storage account's keys +* +* @param {string} serviceName The name of the hosted service. Required. +* @param {string} keyType The storage key type (primary or secondary). Required. +* @param {function} callback The callback function called on completion. Required. +*/ +ServiceManagementService.prototype.regenerateStorageAccountKeys = function(serviceName, keyType, callback) { + validateStringArgument(serviceName, 'serviceName', 'deleteDeployment'); + validateObjectArgument(callback, 'callback', 'deleteDeployment'); + + var path = '/' + this.subscriptionId + '/services/storageservices/' + serviceName + '/keys?action=regenerate'; + var webResource = WebResource.post(path); + webResource.withOkCode(HttpConstants.HttpResponseCodes.OK_CODE, true); + var outbody = this.serialize.buildRegenerateStorageKeys(serviceName, keyType, this); + + + + this.performRequest(webResource, outbody, null, function (responseObject, next) { + + var finalCallback = function (returnObject) { + callback(returnObject.error, returnObject.response); + }; + + next(responseObject, finalCallback); + }); +}; + +/** +* Deletes a storage account +* +* @param {string} serviceName The name of the hosted service. Required. +* @param {function} callback The callback function called on completion. Required. +*/ +ServiceManagementService.prototype.deleteStorageAccount = function(serviceName, callback) { + validateStringArgument(serviceName, 'serviceName', 'deleteDeployment'); + validateObjectArgument(callback, 'callback', 'deleteDeployment'); + + var path = '/' + this.subscriptionId + '/services/storageservices/' + serviceName; + var webResource = WebResource.del(path); + webResource.withOkCode(HttpConstants.HttpResponseCodes.OK_CODE, true); + + this.performRequest(webResource, null, null, function (responseObject, next) { + + var finalCallback = function (returnObject) { + callback(returnObject.error, returnObject.response); + }; + + next(responseObject, finalCallback); + }); +}; + /** * Gets deployment properties for named deployment * From 942bf2758ff6e8289567102e14f0a9c694b2b29c Mon Sep 17 00:00:00 2001 From: Andre Rodrigues Date: Wed, 14 Nov 2012 15:06:15 +0000 Subject: [PATCH 2/4] #469: Making access conditions case insensitive. --- examples/samples/blobuploaddownloadsample.js | 9 +-- lib/http/webresource.js | 40 +++++++----- test/http/webresource-tests.js | 67 ++++++++++++++++++++ test/testlist.txt | 1 + 4 files changed, 95 insertions(+), 22 deletions(-) create mode 100644 test/http/webresource-tests.js diff --git a/examples/samples/blobuploaddownloadsample.js b/examples/samples/blobuploaddownloadsample.js index d78d18bbb..68a549a1e 100644 --- a/examples/samples/blobuploaddownloadsample.js +++ b/examples/samples/blobuploaddownloadsample.js @@ -53,8 +53,7 @@ function createContainer() { blobService.createContainerIfNotExists(container, function (error) { if (error) { console.log(error); - } - else { + } else { console.log('Created the container ' + container); uploadSample(); } @@ -203,8 +202,7 @@ function testAccess(containerName, blobName, etag) { if (processArguments.length > 5 || processArguments.length < 4) { console.log('Incorrect number of arguments'); -} -else if (processArguments.length == 5) { +} else if (processArguments.length == 5) { // Adding a third argument on the command line, whatever it is, will delete the container before running the sample. blobService.deleteContainer(container, function (error) { if (error) { @@ -213,8 +211,7 @@ else if (processArguments.length == 5) { createContainer(); } }); -} -else { +} else { createContainer(); } diff --git a/lib/http/webresource.js b/lib/http/webresource.js index d77ca9ab2..978515841 100644 --- a/lib/http/webresource.js +++ b/lib/http/webresource.js @@ -287,40 +287,48 @@ WebResource.prototype.addOptionalMetadataHeaders = function (metadata) { WebResource.prototype.addOptionalAccessConditionHeader = function (accessConditionHeaders) { if (accessConditionHeaders) { - if (accessConditionHeaders[HeaderConstants.IF_MATCH]) { - this.addOptionalHeader(HeaderConstants.IF_MATCH, accessConditionHeaders[HeaderConstants.IF_MATCH]); + var ifMatch = azureutil.tryGetValueInsensitive(HeaderConstants.IF_MATCH, accessConditionHeaders); + if (ifMatch) { + this.addOptionalHeader(HeaderConstants.IF_MATCH, ifMatch); } - if (accessConditionHeaders[HeaderConstants.IF_MODIFIED_SINCE]) { - this.addOptionalHeader(HeaderConstants.IF_MODIFIED_SINCE, accessConditionHeaders[HeaderConstants.IF_MODIFIED_SINCE]); + var ifModifiedSince = azureutil.tryGetValueInsensitive(HeaderConstants.IF_MODIFIED_SINCE, accessConditionHeaders); + if (ifModifiedSince) { + this.addOptionalHeader(HeaderConstants.IF_MODIFIED_SINCE, ifModifiedSince); } - if (accessConditionHeaders[HeaderConstants.IF_NONE_MATCH]) { - this.addOptionalHeader(HeaderConstants.IF_NONE_MATCH, accessConditionHeaders[HeaderConstants.IF_NONE_MATCH]); + var ifNoneMatch = azureutil.tryGetValueInsensitive(HeaderConstants.IF_NONE_MATCH, accessConditionHeaders); + if (ifNoneMatch) { + this.addOptionalHeader(HeaderConstants.IF_NONE_MATCH, ifNoneMatch); } - if (accessConditionHeaders[HeaderConstants.IF_UNMODIFIED_SINCE]) { - this.addOptionalHeader(HeaderConstants.IF_UNMODIFIED_SINCE, accessConditionHeaders[HeaderConstants.IF_UNMODIFIED_SINCE]); + var ifUnmodifiedSince = azureutil.tryGetValueInsensitive(HeaderConstants.IF_UNMODIFIED_SINCE, accessConditionHeaders); + if (ifUnmodifiedSince) { + this.addOptionalHeader(HeaderConstants.IF_UNMODIFIED_SINCE, ifUnmodifiedSince); } } }; WebResource.prototype.addOptionalSourceAccessConditionHeader = function (accessConditionHeaders) { if (accessConditionHeaders) { - if (accessConditionHeaders[HeaderConstants.SOURCE_IF_MATCH_HEADER]) { - this.addOptionalHeader(HeaderConstants.SOURCE_IF_MATCH_HEADER, accessConditionHeaders[HeaderConstants.SOURCE_IF_MATCH_HEADER]); + var sourceIfMatch = azureutil.tryGetValueInsensitive(HeaderConstants.SOURCE_IF_MATCH_HEADER, accessConditionHeaders); + if (sourceIfMatch) { + this.addOptionalHeader(HeaderConstants.SOURCE_IF_MATCH_HEADER, sourceIfMatch); } - if (accessConditionHeaders[HeaderConstants.SOURCE_IF_MODIFIED_SINCE_HEADER]) { - this.addOptionalHeader(HeaderConstants.SOURCE_IF_MODIFIED_SINCE_HEADER, accessConditionHeaders[HeaderConstants.SOURCE_IF_MODIFIED_SINCE_HEADER]); + var sourceIfModifiedSince = azureutil.tryGetValueInsensitive(HeaderConstants.SOURCE_IF_MODIFIED_SINCE_HEADER, accessConditionHeaders); + if (sourceIfModifiedSince) { + this.addOptionalHeader(HeaderConstants.SOURCE_IF_MODIFIED_SINCE_HEADER, sourceIfModifiedSince); } - if (accessConditionHeaders[HeaderConstants.SOURCE_IF_NONE_MATCH_HEADER]) { - this.addOptionalHeader(HeaderConstants.SOURCE_IF_NONE_MATCH_HEADER, accessConditionHeaders[HeaderConstants.SOURCE_IF_NONE_MATCH_HEADER]); + var sourceIfNoneMatch = azureutil.tryGetValueInsensitive(HeaderConstants.SOURCE_IF_NONE_MATCH_HEADER, accessConditionHeaders); + if (sourceIfNoneMatch) { + this.addOptionalHeader(HeaderConstants.SOURCE_IF_NONE_MATCH_HEADER, sourceIfNoneMatch); } - if (accessConditionHeaders[HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE_HEADER]) { - this.addOptionalHeader(HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE_HEADER, accessConditionHeaders[HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE_HEADER]); + var sourceIfUnmodifiedSince = azureutil.tryGetValueInsensitive(HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE_HEADER, accessConditionHeaders); + if (sourceIfUnmodifiedSince) { + this.addOptionalHeader(HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE_HEADER, sourceIfUnmodifiedSince); } } }; diff --git a/test/http/webresource-tests.js b/test/http/webresource-tests.js new file mode 100644 index 000000000..ca0589564 --- /dev/null +++ b/test/http/webresource-tests.js @@ -0,0 +1,67 @@ +/** +* 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 should = require('should'); +var testutil = require('../util/util'); +var WebResource = require('../../lib/http/webresource'); +var azure = testutil.libRequire('azure'); +var Constants = azure.Constants; +var HeaderConstants = Constants.HeaderConstants; + +suite('webresource-tests', function () { + test('addOptionalAccessConditionHeader', function () { + var ifMatch = 'ifmatch'; + var ifModifiedSince = 'ifModifiedSince'; + var ifNoneMatch = 'ifNoneMatch'; + var ifUnmodifiedSince = 'ifUnmodifiedSince'; + + var accessConditions = { + 'If-Match': ifMatch, + 'If-Modified-Since': ifModifiedSince, + 'If-None-Match': ifNoneMatch, + 'If-Unmodified-Since': ifUnmodifiedSince + }; + + var webResource = new WebResource(); + webResource.addOptionalAccessConditionHeader(accessConditions); + + webResource.headers[HeaderConstants.IF_MATCH].should.equal(ifMatch); + webResource.headers[HeaderConstants.IF_MODIFIED_SINCE].should.equal(ifModifiedSince); + webResource.headers[HeaderConstants.IF_NONE_MATCH].should.equal(ifNoneMatch); + webResource.headers[HeaderConstants.IF_UNMODIFIED_SINCE].should.equal(ifUnmodifiedSince); + }); + + test('addOptionalSourceAccessConditionHeader', function () { + var sourceIfMatch = 'sourceIfmatch'; + var sourceIfModifiedSince = 'sourceIfModifiedSince'; + var sourceIfNoneMatch = 'sourceIfNoneMatch'; + var sourceIfUnmodifiedSince = 'sourceIfUnmodifiedSince'; + + var accessConditions = { + 'x-ms-source-If-Match': sourceIfMatch, + 'x-ms-source-If-Modified-Since': sourceIfModifiedSince, + 'x-ms-source-If-None-Match': sourceIfNoneMatch, + 'x-ms-source-If-Unmodified-Since': sourceIfUnmodifiedSince + }; + + var webResource = new WebResource(); + webResource.addOptionalSourceAccessConditionHeader(accessConditions); + + webResource.headers[HeaderConstants.SOURCE_IF_MATCH_HEADER].should.equal(sourceIfMatch); + webResource.headers[HeaderConstants.SOURCE_IF_MODIFIED_SINCE_HEADER].should.equal(sourceIfModifiedSince); + webResource.headers[HeaderConstants.SOURCE_IF_NONE_MATCH_HEADER].should.equal(sourceIfNoneMatch); + webResource.headers[HeaderConstants.SOURCE_IF_UNMODIFIED_SINCE_HEADER].should.equal(sourceIfUnmodifiedSince); + }); +}); \ No newline at end of file diff --git a/test/testlist.txt b/test/testlist.txt index f086ddfb9..b3a74b9d7 100644 --- a/test/testlist.txt +++ b/test/testlist.txt @@ -1,6 +1,7 @@ serviceruntime/roleenvironment-tests.js serviceruntime/runtimeversionmanager-tests.js serviceruntime/runtimeversionprotocolclient-tests.js +http/webresource-tests.js services/blob/blobservice-tests.js services/blob/sharedaccesssignature-tests.js services/blob/sharedkey-tests.js From 76ec049a459a6df39873f16bb37fa668d81f26af Mon Sep 17 00:00:00 2001 From: Andre Rodrigues Date: Wed, 14 Nov 2012 16:01:21 +0000 Subject: [PATCH 3/4] #470: Fix issue with ACL policy dates - milliseconds padding. --- .../blob/models/containeraclresult.js | 6 +- lib/util/iso8061date.js | 17 +++-- test/services/blob/blobservice-tests.js | 68 +++++++++++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/lib/services/blob/models/containeraclresult.js b/lib/services/blob/models/containeraclresult.js index 9b7d1a4a2..35b795b5f 100644 --- a/lib/services/blob/models/containeraclresult.js +++ b/lib/services/blob/models/containeraclresult.js @@ -22,6 +22,8 @@ var ISO8061Date = require('../../../util/iso8061date'); // Expose 'ContainerAclResult'. exports = module.exports = ContainerAclResult; +var ACL_MILLISECONDS_PADING = 7; + function ContainerAclResult(signedIdentifiers) { if (signedIdentifiers) { this.signedIdentifiers = signedIdentifiers; @@ -51,7 +53,7 @@ ContainerAclResult.serialize = function (signedIdentifiersJs) { var startIsoString = signedIdentifier.AccessPolicy.Start; if (startIsoString instanceof Date) { // Convert to expected ISO 8061 date format - startIsoString = ISO8061Date.format(startIsoString); + startIsoString = ISO8061Date.format(startIsoString, ACL_MILLISECONDS_PADING); } doc = doc @@ -64,7 +66,7 @@ ContainerAclResult.serialize = function (signedIdentifiersJs) { var expiryIsoString = signedIdentifier.AccessPolicy.Expiry; if (expiryIsoString instanceof Date) { // Convert to expected ISO 8061 date format - expiryIsoString = ISO8061Date.format(expiryIsoString); + expiryIsoString = ISO8061Date.format(expiryIsoString, ACL_MILLISECONDS_PADING); } doc = doc diff --git a/lib/util/iso8061date.js b/lib/util/iso8061date.js index 207199eef..589dfdd88 100644 --- a/lib/util/iso8061date.js +++ b/lib/util/iso8061date.js @@ -16,11 +16,12 @@ /** * Formats a date into an iso 8061 string. * -* @param {date} date The date to format. -* @param {bool} skipMilliseconds Boolean value indicating if the miliseconds part of the date should not be included. +* @param {date} date The date to format. +* @param {bool} skipMilliseconds Boolean value indicating if the miliseconds part of the date should not be included. +* @param {integer} millisecondsPading Number of digits to left pad the miliseconds. * @return {string} The date formated in the ISO 8061 date format. */ -exports.format = function (date, skipMilliseconds) { +exports.format = function (date, skipMilliseconds, millisecondsPading) { var components = [ date.getUTCFullYear(), '-', @@ -37,7 +38,11 @@ exports.format = function (date, skipMilliseconds) { if (!skipMilliseconds) { components.push('.'); - components.push(leftPadThree(date.getUTCMilliseconds())); + if (!millisecondsPading) { + millisecondsPading = 3; + } + + components.push(leftPad(date.getUTCMilliseconds(), millisecondsPading)); } components.push('Z'); @@ -77,9 +82,9 @@ var leftPadTwo = function (n) { return (n < 10 ? '0' : '') + n; }; -var leftPadThree = function (n) { +var leftPad = function (n, millisecondsPading) { var currentN = '' + n; - while (currentN.length < 3) { + while (currentN.length < millisecondsPading) { currentN = '0' + currentN; } diff --git a/test/services/blob/blobservice-tests.js b/test/services/blob/blobservice-tests.js index 54ebb1ab2..681faba5d 100644 --- a/test/services/blob/blobservice-tests.js +++ b/test/services/blob/blobservice-tests.js @@ -420,6 +420,74 @@ suite('blobservice-tests', function () { }); }); + test('SetContainerAclWithPolicies', function (done) { + var containerName = testutil.generateId(containerNamesPrefix, containerNames, blobtestutil.isMocked); + + var readWriteStartDate = new Date(); + var readWriteExpiryDate = new Date(readWriteStartDate); + readWriteExpiryDate.setMinutes(readWriteStartDate.getMinutes() + 10); + + var readWriteSharedAccessPolicy = { + Id: 'readwrite', + AccessPolicy: { + Start: readWriteStartDate, + Expiry: readWriteExpiryDate, + Permissions: 'rw' + } + }; + + var readSharedAccessPolicy = { + Id: 'read', + AccessPolicy: { + Expiry: readWriteStartDate, + Permissions: 'r' + } + }; + + var options = {}; + options.signedIdentifiers = [readWriteSharedAccessPolicy, readSharedAccessPolicy]; + + blobService.createContainer(containerName, function (createError, container1, createContainerResponse) { + assert.equal(createError, null); + assert.notEqual(container1, null); + assert.ok(createContainerResponse.isSuccessful); + + blobService.setContainerAcl(containerName, BlobConstants.BlobContainerPublicAccessType.BLOB, options, function (setAclError, setAclContainer1, setResponse1) { + assert.equal(setAclError, null); + assert.notEqual(setAclContainer1, null); + assert.ok(setResponse1.isSuccessful); + + blobService.getContainerAcl(containerName, function (getAclError, getAclContainer1, getResponse1) { + assert.equal(getAclError, null); + assert.notEqual(getAclContainer1, null); + if (getAclContainer1) { + assert.equal(getAclContainer1.publicAccessLevel, BlobConstants.BlobContainerPublicAccessType.BLOB); + } + + assert.ok(getResponse1.isSuccessful); + + blobService.setContainerAcl(containerName, BlobConstants.BlobContainerPublicAccessType.CONTAINER, function (setAclError2, setAclContainer2, setResponse2) { + assert.equal(setAclError2, null); + assert.notEqual(setAclContainer2, null); + assert.ok(setResponse2.isSuccessful); + + blobService.getContainerAcl(containerName, function (getAclError2, getAclContainer2, getResponse3) { + assert.equal(getAclError2, null); + assert.notEqual(getAclContainer2, null); + if (getAclContainer2) { + assert.equal(getAclContainer2.publicAccessLevel, BlobConstants.BlobContainerPublicAccessType.CONTAINER); + } + + assert.ok(getResponse3.isSuccessful); + + done(); + }); + }); + }); + }); + }); + }); + test('SetContainerAclSignedIdentifiers', function (done) { var containerName = testutil.generateId(containerNamesPrefix, containerNames, blobtestutil.isMocked); From 42e71f5f9f9930f565aad13c74e07acad3017657 Mon Sep 17 00:00:00 2001 From: Andre Rodrigues Date: Wed, 14 Nov 2012 16:58:31 +0000 Subject: [PATCH 4/4] Applying review comments. --- lib/services/serviceManagement/servicemanagementservice.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/services/serviceManagement/servicemanagementservice.js b/lib/services/serviceManagement/servicemanagementservice.js index aae84029e..9fac7e13a 100644 --- a/lib/services/serviceManagement/servicemanagementservice.js +++ b/lib/services/serviceManagement/servicemanagementservice.js @@ -728,6 +728,10 @@ ServiceManagementService.prototype.regenerateStorageAccountKeys = function(servi validateStringArgument(serviceName, 'serviceName', 'deleteDeployment'); validateObjectArgument(callback, 'callback', 'deleteDeployment'); + if (keyType.toLowerCase() !== 'primary' && keyType.toLowerCase() !== 'secondary') { + throw new Error('Invalid storage account type'); + } + var path = '/' + this.subscriptionId + '/services/storageservices/' + serviceName + '/keys?action=regenerate'; var webResource = WebResource.post(path); webResource.withOkCode(HttpConstants.HttpResponseCodes.OK_CODE, true);