Comparing version 0.8.1 to 0.8.2
@@ -0,1 +1,5 @@ | ||
## v0.8.2 | ||
* Added support for File/Container metadata for Rackspace Storage | ||
* Adding support for Rackspace CDN enabled Containers | ||
## v0.8.1 | ||
@@ -2,0 +6,0 @@ * Added support for limit/marker options for Rackspace getContainers, getFiles |
@@ -74,3 +74,3 @@ # Using Azure with `pkgcloud` | ||
console.log("waiting for server RUNNING state..."); | ||
server.setWait({ status: 'RUNNING' }, 10000, function (err, server) { | ||
server.setWait({ status: server.STATUS.running }, 10000, function (err, server) { | ||
if (err) { | ||
@@ -77,0 +77,0 @@ console.log(err); |
@@ -31,2 +31,5 @@ ## Using the Rackspace Storage provider | ||
bytes: 12345, // size of the container in bytes | ||
metadata: { // key value pairs for the container | ||
// ... | ||
} | ||
} | ||
@@ -57,2 +60,4 @@ ``` | ||
* [`client.destroyContainer(container, function(err, result) { })`](#clientdestroycontainercontainer-functionerr-result--) | ||
* [`client.updateContainerMetadata(container, function(err, container) { })`](#clientupdatecontainermetadatacontainer-functionerr-container--) | ||
* [`client.removeContainerMetadata(container, metadataToRemove, function(err, container) { })`](#clientremovecontainermetadatacontainer-metadatatoremove-functionerr-container--) | ||
@@ -85,4 +90,16 @@ ### Container API Details | ||
Creates a new [`container`](#container-model) with the name from argument `container`. | ||
Creates a new [`container`](#container-model) with the name from argument `container`. You can optionally provide `metadata` on the request: | ||
```javascript | ||
client.createContainer({ | ||
name: 'my-container', | ||
metadata: { | ||
brand: 'bmw', | ||
model: '335i' | ||
year: 2009 | ||
}}, function(err, container) { | ||
// ... | ||
}) | ||
``` | ||
#### client.destroyContainer(container, function(err, result) { }) | ||
@@ -92,2 +109,23 @@ | ||
#### client.updateContainerMetadata(container, function(err, container) { }) | ||
Updates the metadata on the provided [`container`](#container-model) . Currently, the `updateContainer` method only adds new metadata fields. If you need to remove specific metadata properties, you should call `client.removeContainerMetadata(...)`. | ||
```javascript | ||
container.metadata.color = 'red'; | ||
client.updateContainerMetadata(container, function(err, container) { | ||
// ... | ||
}) | ||
``` | ||
#### client.removeContainerMetadata(container, metadataToRemove, function(err, container) { }) | ||
Removes the keys in the `metadataToRemove` object from the stored [`container`](#container-model) metadata. | ||
```Javascript | ||
client.removeContainerMetadata(container, { year: false }, function(err, c) { | ||
// ... | ||
}); | ||
``` | ||
### File APIs | ||
@@ -100,2 +138,3 @@ | ||
* [`client.removeFile(container, file, function(err, result) { })`](#clientremovefilecontainer-file-functionerr-result--) | ||
* [`client.updateFileMetadata(container, file, function(err, file) { })`](#clientupdatefilemetadatacontainer-file-functionerr-file--) | ||
@@ -133,2 +172,10 @@ ### File API Details | ||
local: '/path/to/local/file' // a path to any local file | ||
// Other optional values | ||
metadata: { // provide any number of property/values for metadata | ||
campaign: '2012 magazine' | ||
}, | ||
headers: { // optionally provide raw headers to send to cloud files | ||
'content-type': 'application/json' | ||
} | ||
}; | ||
@@ -238,1 +285,17 @@ ``` | ||
Removes the provided [`file`](#file-model) from the provided [`container`](#container-model). | ||
#### client.updateFileMetadata(container, file, function(err, file) { }) | ||
Updates the [`file`](#file-model) metadata in the the provided [`container`](#container-model). | ||
File metadata is completely replaced with each callt o updateFileMetadata. This is different than container metadata. To delete a property, just remove it from the metadata attribute on the `File` and call `updateFileMetadata`. | ||
```javascript | ||
file.metadata = { | ||
campaign = '2011 website' | ||
}; | ||
client.updateFileMetadata(file.container, file, function(err, file) { | ||
// ... | ||
}); | ||
``` | ||
@@ -59,3 +59,3 @@ var pkgcloud = require('../../lib/pkgcloud'), | ||
console.log("waiting for server RUNNING state..."); | ||
server.setWait({ status: 'RUNNING' }, 10000, function (err, server) { | ||
server.setWait({ status: server.STATUS.running }, 10000, function (err, server) { | ||
if (err) { | ||
@@ -62,0 +62,0 @@ console.log(err); |
@@ -58,3 +58,3 @@ var pkgcloud = require('pkgcloud'), | ||
// Wait for status: ACTIVE on our server, and then callback | ||
server.setWait({ status: 'ACTIVE' }, 5000, function (err) { | ||
server.setWait({ status: server.STATUS.running }, 5000, function (err) { | ||
if (err) { | ||
@@ -61,0 +61,0 @@ console.dir(err); |
@@ -27,2 +27,6 @@ /* | ||
// support either key/accessKey syntax | ||
this.config.key = this.config.key || options.accessKey; | ||
this.config.keyId = this.config.keyId || options.accessKeyId; | ||
if (!this.before) { | ||
@@ -29,0 +33,0 @@ this.before = []; |
@@ -24,16 +24,16 @@ /* | ||
case 'PENDING': | ||
this.status = 'PROVISIONING'; | ||
this.status = this.STATUS.provisioning; | ||
break; | ||
case 'RUNNING': | ||
this.status = 'RUNNING'; | ||
this.status = this.STATUS.running; | ||
break; | ||
case 'STOPPING': | ||
case 'STOPPED': | ||
this.status = 'STOPPED'; | ||
this.status = this.STATUS.stopped; | ||
break; | ||
case 'TERMINATED': | ||
this.status = 'TERMINATED'; | ||
this.status = this.STATUS.terminated; | ||
break; | ||
default: | ||
this.status = 'UNKNOWN'; | ||
this.status = this.STATUS.unknown; | ||
break; | ||
@@ -40,0 +40,0 @@ } |
@@ -60,4 +60,4 @@ /* | ||
// | ||
// ### function createContainer (container, callback) | ||
// #### @container {string|Container} Container to create in AWS S3. | ||
// ### function createContainer (options, callback) | ||
// #### @options {string|Container} Container to create in AWS S3. | ||
// #### @callback {function} Continuation to respond to when complete. | ||
@@ -67,4 +67,4 @@ // Creates the specified `container` in AWS S3 account associated | ||
// | ||
exports.createContainer = function (container, callback) { | ||
var containerName = container instanceof base.Container ? container.name : container, | ||
exports.createContainer = function (options, callback) { | ||
var containerName = options instanceof base.Container ? options.name : options, | ||
self = this; | ||
@@ -78,3 +78,3 @@ | ||
? callback(err) | ||
: callback(null, new (storage.Container)(self, container)); | ||
: callback(null, new (storage.Container)(self, options)); | ||
}); | ||
@@ -81,0 +81,0 @@ }; |
@@ -50,7 +50,7 @@ /* | ||
case 'BUSY': | ||
this.status = 'PROVISIONING'; | ||
this.status = this.STATUS.provisioning; | ||
break; | ||
case 'READYROLE': | ||
case 'READY': | ||
this.status = 'RUNNING'; | ||
this.status = this.STATUS.running; | ||
break; | ||
@@ -62,11 +62,6 @@ case 'STOPPING': | ||
case 'STOPPEDVM': | ||
this.status = 'STOPPED'; | ||
this.status = this.STATUS.stopped; | ||
break; | ||
case 'STOPPINGROLE': | ||
case 'STOPPINGVM': | ||
case 'STOPPEDVM': | ||
this.status = 'STOPPED'; | ||
break; | ||
case 'DELETINGVM': | ||
this.status = 'TERMINATED'; | ||
this.status = this.STATUS.terminated; | ||
break; | ||
@@ -76,3 +71,3 @@ case 'ROLESTATEUNKNOWN': | ||
default: | ||
this.status = 'UNKNOWN'; | ||
this.status = this.STATUS.unknown; | ||
break; | ||
@@ -87,6 +82,6 @@ } | ||
case 'RUNNINGTRANSITIONING': | ||
this.status = 'PROVISIONING'; | ||
this.status = this.STATUS.provisioning; | ||
break; | ||
case 'RUNNING': | ||
this.status = 'RUNNING'; | ||
this.status = this.STATUS.running; | ||
break; | ||
@@ -96,13 +91,13 @@ case 'SUSPENDING': | ||
case 'SUSPENDEDTRANSITIONING': | ||
this.status = 'STOPPED'; | ||
this.status = this.STATUS.stopped; | ||
break; | ||
case 'DELETING': | ||
this.status = 'TERMINATED'; | ||
this.status = this.STATUS.terminated; | ||
break; | ||
default: | ||
this.status = 'UNKNOWN'; | ||
this.status = this.STATUS.unknown; | ||
break; | ||
} | ||
} else { | ||
this.status = 'UNKNOWN'; | ||
this.status = this.STATUS.unknown; | ||
} | ||
@@ -109,0 +104,0 @@ |
@@ -66,4 +66,4 @@ /* | ||
// | ||
// ### function createContainer (container, callback) | ||
// #### @container {string|Container} Container to create in Rackspace Cloudfiles. | ||
// ### function createContainer (options, callback) | ||
// #### @options {string|Container} Container to create in Rackspace Cloudfiles. | ||
// #### @callback {function} Continuation to respond to when complete. | ||
@@ -79,4 +79,4 @@ // Creates the specified `container` in the Rackspace Cloudfiles associated | ||
// | ||
exports.createContainer = function (container, callback) { | ||
var containerName = container instanceof base.Container ? container.name : container, | ||
exports.createContainer = function (options, callback) { | ||
var containerName = options instanceof base.Container ? options.name : options, | ||
self = this; | ||
@@ -93,3 +93,3 @@ | ||
? callback(err) | ||
: callback(null, new (storage.Container)(self, container)); | ||
: callback(null, new (storage.Container)(self, options)); | ||
}); | ||
@@ -96,0 +96,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
/** | ||
/** | ||
* Copyright (c) Microsoft. All rights reserved. | ||
@@ -3,0 +3,0 @@ * |
@@ -786,3 +786,3 @@ /* | ||
var interval = options.pollInterval || 30 * 1000, | ||
maxRetries = options.pollMax || 10, | ||
maxRetries = options.pollMax || 10, | ||
attempts = 0, | ||
@@ -789,0 +789,0 @@ self = this; |
@@ -9,3 +9,4 @@ /* | ||
var utile = require('utile'), | ||
model = require('../base/model'); | ||
model = require('../base/model'), | ||
computeStatus = require('../../common/status').compute; | ||
@@ -42,1 +43,3 @@ var Server = exports.Server = function (client, details) { | ||
}; | ||
Server.prototype.STATUS = computeStatus; |
@@ -10,3 +10,4 @@ /* | ||
compute = require('../../core/compute'), | ||
base = require('../../core/compute/server'); | ||
base = require('../../core/compute/server'), | ||
computeStatus = require('../../common/status').compute; | ||
@@ -26,13 +27,13 @@ var Server = exports.Server = function Server(client, details) { | ||
case 'PROVISIONING': | ||
this.status = "PROVISIONING"; | ||
this.status = this.STATUS.provisioning; | ||
break; | ||
case 'RUNNING': | ||
this.status = "RUNNING"; | ||
this.status = this.STATUS.running; | ||
break; | ||
case 'STOPPING': | ||
case 'STOPPED': | ||
this.status = "STOPPED"; | ||
this.status = this.STATUS.stopped; | ||
break; | ||
default: | ||
this.status = "UNKNOWN"; | ||
this.status = this.STATUS.unknown; | ||
break; | ||
@@ -39,0 +40,0 @@ } |
@@ -28,13 +28,14 @@ /* | ||
case 'REBUILD': | ||
this.status = "PROVISIONING"; | ||
this.status = this.STATUS.provisioning; | ||
break; | ||
case 'ACTIVE': | ||
this.status = "RUNNING"; | ||
this.status = this.STATUS.running; | ||
break; | ||
case 'SUSPENDED': | ||
this.status = "STOPPED"; | ||
case 'SHUTOFF': | ||
this.status = this.STATUS.stopped; | ||
break; | ||
case 'REBOOT': | ||
case 'HARD_REBOOT': | ||
this.status = "REBOOT"; | ||
this.status = this.STATUS.reboot; | ||
break; | ||
@@ -49,9 +50,10 @@ case 'QUEUE_RESIZE': | ||
case 'PASSWORD': | ||
this.status = "UPDATING"; | ||
this.status = this.STATUS.updating; | ||
break; | ||
case 'RESCUE': | ||
this.status = 'ERROR'; | ||
case 'ERROR': | ||
this.status = this.STATUS.error; | ||
break; | ||
default: | ||
this.status = "UNKNOWN"; | ||
this.status = this.STATUS.unknown; | ||
break; | ||
@@ -64,3 +66,3 @@ } | ||
// | ||
this.progress = details.progress || this.progress; | ||
this.progress = details.progress; | ||
this.imageId = details.imageId || this.imageId; | ||
@@ -67,0 +69,0 @@ this.adminPass = details.adminPass || this.adminPass; |
@@ -9,3 +9,4 @@ /* | ||
var utile = require('utile'), | ||
model = require('../../core/base/model'); | ||
model = require('../../core/base/model'), | ||
computeStatus = require('../../common/status').compute; | ||
@@ -22,2 +23,4 @@ var Instance = exports.Instance = function Instance(client, details) { | ||
Instance.prototype.STATUS = computeStatus; | ||
Instance.prototype._setProperties = function (details) { | ||
@@ -37,7 +40,7 @@ this.id = details.id; | ||
case 'RESIZE': | ||
this.status = "PROVISIONING"; | ||
this.status = this.STATUS.provisioning; | ||
break; | ||
case 'RUNNING': | ||
case 'ACTIVE': // Change for keep consistency | ||
this.status = "RUNNING"; | ||
this.status = this.STATUS.running; | ||
break; | ||
@@ -47,9 +50,9 @@ case 'STOPPING': | ||
case 'SHUTDOWN': | ||
this.status = "STOPPED"; | ||
this.status = this.STATUS.stopped; | ||
break; | ||
case 'FAILED': | ||
this.status = 'FAILED'; | ||
this.status = this.STATUS.error; | ||
break; | ||
default: | ||
this.status = "UNKNOWN"; | ||
this.status = this.STATUS.unknown; | ||
break; | ||
@@ -56,0 +59,0 @@ } |
@@ -8,5 +8,4 @@ /* | ||
exports.cdn = require('./cdn'); | ||
exports.compute = require('./compute'); | ||
exports.storage = require('./storage'); | ||
exports.database = require('./database'); |
@@ -12,2 +12,3 @@ /* | ||
pkgcloud = require('../../../../../lib/pkgcloud'), | ||
_ = require('underscore'), | ||
storage = pkgcloud.providers.rackspace.storage; | ||
@@ -17,2 +18,3 @@ | ||
// ### function getContainers (callback) | ||
// #### @options {object} Options for the getContainers call | ||
// #### @callback {function} Continuation to respond to when complete. | ||
@@ -45,16 +47,31 @@ // Gets all Rackspace Cloudfiles containers for this instance. | ||
this.request(getContainerOpts, function (err, body) { | ||
return err | ||
? callback(err) | ||
: callback(null, body.map(function (container) { | ||
// | ||
// The cdn properties are normaly set in response headers | ||
// when requesting single cdn containers | ||
// | ||
container.cdnEnabled = container.cdn_enabled == 'true'; | ||
container.logRetention = container.log_retention == 'true'; | ||
container.cdnUri = container.cdn_uri; | ||
container.cdnSslUri = container.cdn_ssl_uri; | ||
if (err) { | ||
return callback(err); | ||
} | ||
else if (!body || !(body instanceof Array)) { | ||
return new Error('Malformed API Response') | ||
} | ||
if (!options.loadCDNAttributes) { | ||
return callback(null, body.map(function (container) { | ||
return new storage.Container(self, container); | ||
})); | ||
} | ||
else { | ||
var containers = []; | ||
async.forEachLimit(body, 10, function(c, next) { | ||
var container = new storage.Container(self, c); | ||
containers.push(container); | ||
container.refreshCdnDetails(function(err) { | ||
if (err) { | ||
return next(err); | ||
} | ||
next(); | ||
}) | ||
}, function(err) { | ||
callback(err, containers); | ||
}); | ||
} | ||
}); | ||
@@ -81,15 +98,18 @@ }; | ||
} | ||
container = { | ||
name: containerName, | ||
count: parseInt(res.headers['x-container-object-count'], 10), | ||
bytes: parseInt(res.headers['x-container-bytes-used'], 10) | ||
}; | ||
container.cdnUri = res.headers['x-cdn-uri']; | ||
container.cdnSslUri = res.headers['x-cdn-ssl-uri']; | ||
container.cdnEnabled = res.headers['x-cdn-enabled'] == 'true'; | ||
container.ttl = parseInt(res.headers['x-ttl'], 10); | ||
container.logRetention = res.headers['x-log-retention'] == 'true'; | ||
self._getCdnContainerDetails(containerName, function(err, details) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, new (storage.Container)(self, container)); | ||
container = _.extend({}, details, { | ||
name: containerName, | ||
count: parseInt(res.headers['x-container-object-count'], 10), | ||
bytes: parseInt(res.headers['x-container-bytes-used'], 10) | ||
}); | ||
container.metadata = self.deserializeMetadata(self.CONTAINER_META_PREFIX, res.headers); | ||
callback(null, new (storage.Container)(self, container)); | ||
}); | ||
}); | ||
@@ -99,4 +119,4 @@ }; | ||
// | ||
// ### function createContainer (container, callback) | ||
// #### @container {string|Container} Container to create in Rackspace Cloudfiles. | ||
// ### function createContainer (options, callback) | ||
// #### @options {string|Container} Container to create in Rackspace Cloudfiles. | ||
// #### @callback {function} Continuation to respond to when complete. | ||
@@ -106,13 +126,19 @@ // Creates the specified `container` in the Rackspace Cloudfiles associated | ||
// | ||
exports.createContainer = function (container, callback) { | ||
var containerName = container instanceof base.Container ? container.name : container, | ||
exports.createContainer = function (options, callback) { | ||
var containerName = typeof options === 'object' ? options.name : options, | ||
self = this; | ||
this.request({ | ||
var createContainerOpts = { | ||
method: 'PUT', | ||
container: containerName | ||
}, function (err, body, res) { | ||
}; | ||
if (options.metadata) { | ||
createContainerOpts.headers = self.serializeMetadata(self.CONTAINER_META_PREFIX, options.metadata); | ||
} | ||
this.request(createContainerOpts, function (err) { | ||
return err | ||
? callback(err) | ||
: callback(null, new (storage.Container)(self, {name: containerName})); | ||
: callback(null, new (storage.Container)(self, { name: containerName, metadata: options.metadata })); | ||
}); | ||
@@ -122,2 +148,64 @@ }; | ||
// | ||
// ### function updateContainerMetadata (container, callback) | ||
// #### @container {Container} Container to update in Rackspace Cloudfiles. | ||
// #### @callback {function} Continuation to respond to when complete. | ||
// Updates the metadata in the specified `container` in the Rackspace Cloudfiles associated | ||
// with this instance. | ||
// | ||
exports.updateContainerMetadata = function (container, callback) { | ||
this._updateContainerMetadata(container, | ||
this.serializeMetadata(this.CONTAINER_META_PREFIX, container.metadata), | ||
callback); | ||
}; | ||
// | ||
// ### function removeContainerMetadata (container, callback) | ||
// #### @container {Container} Container to remove metadata from in Rackspace Cloudfiles. | ||
// #### @metadataToRemove {object} object with keys representing metadata to remove | ||
// #### @callback {function} Continuation to respond to when complete. | ||
// Removes the provided `metadata` in the specified `container` in the Rackspace Cloudfiles associated | ||
// with this instance. | ||
// | ||
exports.removeContainerMetadata = function (container, metadataToRemove, callback) { | ||
this._updateContainerMetadata(container, | ||
this.serializeMetadata(this.CONTAINER_REMOVE_META_PREFIX, metadataToRemove), | ||
callback); | ||
}; | ||
// | ||
// ### function _updateContainerMetadata (container, headers, callback) | ||
// #### @container {Container} Container to update with provided header metadata in Rackspace Cloudfiles. | ||
// #### @metadata {object} Raw headers to pass as part of the update call. | ||
// #### @callback {function} Continuation to respond to when complete. | ||
// Updates the specified `container` with the provided metadata `headers`in the Rackspace Cloudfiles associated | ||
// with this instance. | ||
// | ||
exports._updateContainerMetadata = function(container, metadata, callback) { | ||
var self = this; | ||
if (!(container instanceof base.Container)) { | ||
throw new Error('Must update an existing container instance'); | ||
} | ||
var updateContainerOpts = { | ||
method: 'POST', | ||
container: container.name, | ||
headers: metadata | ||
}; | ||
this.request(updateContainerOpts, function (err) { | ||
// omit our newly deleted header fields, if any | ||
if (!err) { | ||
container.metadata = _.omit(container.metadata, | ||
_.keys(self.deserializeMetadata(self.CONTAINER_REMOVE_META_PREFIX, metadata))); | ||
} | ||
return err | ||
? callback(err) | ||
: callback(null, container); | ||
}); | ||
}; | ||
// | ||
// ### function destroyContainer (container, callback) | ||
@@ -124,0 +212,0 @@ // #### @container {string} Name of the container to destroy |
@@ -15,2 +15,3 @@ /* | ||
pkgcloud = require('../../../../../lib/pkgcloud'), | ||
_ = require('underscore'), | ||
storage = pkgcloud.providers.rackspace.storage; | ||
@@ -47,4 +48,6 @@ | ||
var container = options.container, | ||
self = this, | ||
apiStream, | ||
inputStream; | ||
inputStream, | ||
uploadOptions; | ||
@@ -55,6 +58,13 @@ if (container instanceof storage.Container) { | ||
uploadOptions = { | ||
method: 'PUT', | ||
upload: true, | ||
container: container, | ||
path: options.remote, | ||
headers: options.headers || {} | ||
}; | ||
if (options.local) { | ||
inputStream = filed(options.local); | ||
options.headers = options.headers || {}; | ||
options.headers['content-length'] = fs.statSync(options.local).size; | ||
uploadOptions.headers['content-length'] = fs.statSync(options.local).size; | ||
} | ||
@@ -65,4 +75,4 @@ else if (options.stream) { | ||
if (options.headers && !options.headers['content-type']) { | ||
options.headers['content-type'] = mime.lookup(options.remote); | ||
if (!uploadOptions.headers['content-type']) { | ||
uploadOptions.headers['content-type'] = mime.lookup(options.remote); | ||
} | ||
@@ -87,9 +97,8 @@ | ||
apiStream = this.request({ | ||
method: 'PUT', | ||
upload: true, | ||
container: container, | ||
path: options.remote, | ||
headers: options.headers || {} | ||
}, function (err, body, res) { | ||
if (options.metadata) { | ||
uploadOptions.headers = _.extend(uploadOptions.headers, | ||
self.serializeMetadata(self.OBJECT_META_PREFIX, options.metadata)); | ||
} | ||
apiStream = this.request(uploadOptions, function (err, body, res) { | ||
return err | ||
@@ -190,10 +199,86 @@ ? callback && callback(err) | ||
this.request(getFilesOpts, function (err, body) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
else if (!body || !(body instanceof Array)) { | ||
return new Error('Malformed API Response') | ||
} | ||
return callback(null, body.map(function (file) { | ||
file.container = container; | ||
return new storage.File(self, file); | ||
})); | ||
}); | ||
}; | ||
// | ||
// ### function updateFileMetadata (container, headers, callback) | ||
// #### @container {Container} Container to update said file in | ||
// #### @file {File} File to update metadata for in Rackspace Cloudfiles. | ||
// #### @callback {function} Continuation to respond to when complete. | ||
// Updates the specified `file` with the provided metadata `headers` in the Rackspace Cloudfiles associated | ||
// with this instance. | ||
// | ||
exports.updateFileMetadata = function (container, file, callback) { | ||
var self = this, | ||
containerName = container instanceof base.Container ? container.name : container; | ||
if (!file instanceof base.File) { | ||
throw new Error('Must update an existing file instance'); | ||
} | ||
var updateFileOpts = { | ||
method: 'POST', | ||
container: containerName, | ||
path: file.name, | ||
headers: self.serializeMetadata(self.OBJECT_META_PREFIX, file.metadata) | ||
}; | ||
this.request(updateFileOpts, function (err) { | ||
return err | ||
? callback(err) | ||
: callback(null, body.map(function (file) { | ||
file.container = container; | ||
return new storage.File(self, file); | ||
})); | ||
: callback(null, file); | ||
}); | ||
}; | ||
// | ||
// ### function purgeFileFromCdn (container, file, emails, callback) | ||
// #### @container {string} Name of the container to destroy the file in | ||
// #### @file {string} Name of the file to destroy. | ||
// #### @emails {Array} Optional array of emails to notify on purging | ||
// #### @callback {function} Continuation to respond to when complete. | ||
// Destroys the `file` in the specified `container`. | ||
// | ||
exports.purgeFileFromCdn = function (container, file, emails, callback) { | ||
var containerName = container instanceof base.Container ? container.name : container, | ||
fileName = file instanceof base.File ? file.name : file; | ||
if (typeof emails === 'function') { | ||
callback = emails; | ||
emails = []; | ||
} | ||
else if (typeof emails === 'string') { | ||
emails = emails.split(','); | ||
} | ||
var purgeOptions = { | ||
method: 'DELETE', | ||
container: containerName, | ||
path: fileName, | ||
serviceType: this.cdnServiceType | ||
}; | ||
if (emails.length) { | ||
purgeOptions.headers = {}; | ||
purgeOptions.headers['x-purge-email'] = emails.join(','); | ||
} | ||
this.request(purgeOptions, function (err) { | ||
return err | ||
? callback(err) | ||
: callback(null, true); | ||
} | ||
); | ||
}; | ||
@@ -10,4 +10,10 @@ /* | ||
urlJoin = require('url-join'), | ||
rackspace = require('../../client'); | ||
rackspace = require('../../client'), | ||
_ = require('underscore'); | ||
const CONTAINER_META_PREFIX = 'x-container-meta-'; | ||
const CONTAINER_REMOVE_META_PREFIX = 'x-remove-container-meta-'; | ||
const OBJECT_META_PREFIX = 'x-object-meta-'; | ||
const OBJECT_REMOVE_META_PREFIX = 'x-object-remove-meta-'; | ||
var Client = exports.Client = function (options) { | ||
@@ -17,5 +23,7 @@ rackspace.Client.call(this, options); | ||
utile.mixin(this, require('./containers')); | ||
utile.mixin(this, require('./cdn-containers')); | ||
utile.mixin(this, require('./files')); | ||
this.serviceType = 'object-store'; | ||
this.cdnServiceType = 'rax:object-cdn'; | ||
}; | ||
@@ -28,3 +36,4 @@ | ||
var fragment = ''; | ||
var fragment = '', | ||
service = options.serviceType || this.serviceType; | ||
@@ -40,6 +49,43 @@ if (options.container) { | ||
if (fragment === '' || fragment === '/') { | ||
return this.getServiceUrl(this.serviceType); | ||
return this.getServiceUrl(service); | ||
} | ||
return urlJoin(this.getServiceUrl(this.serviceType), fragment); | ||
return urlJoin(this.getServiceUrl(service), fragment); | ||
}; | ||
Client.prototype.serializeMetadata = function(prefix, metadata) { | ||
if (!metadata) { | ||
return {}; | ||
} | ||
var serializedMetadata = {}; | ||
_.keys(metadata).forEach(function (key) { | ||
serializedMetadata[prefix + key] = metadata[key]; | ||
}); | ||
return serializedMetadata; | ||
}; | ||
Client.prototype.deserializeMetadata = function (prefix, metadata) { | ||
if (!metadata) { | ||
return {}; | ||
} | ||
var deserializedMetadata = {}; | ||
_.keys(metadata).forEach(function (key) { | ||
if (key.indexOf(prefix) !== -1) { | ||
deserializedMetadata[key.split(prefix)[1]] = metadata[key]; | ||
} | ||
}); | ||
return deserializedMetadata; | ||
}; | ||
Client.prototype.CONTAINER_META_PREFIX = CONTAINER_META_PREFIX; | ||
Client.prototype.CONTAINER_REMOVE_META_PREFIX = CONTAINER_REMOVE_META_PREFIX; | ||
Client.prototype.OBJECT_META_PREFIX = OBJECT_META_PREFIX; | ||
Client.prototype.OBJECT_REMOVE_META_PREFIX = OBJECT_REMOVE_META_PREFIX; |
@@ -9,3 +9,4 @@ /* | ||
var utile = require('utile'), | ||
base = require('../../core/storage/container'); | ||
base = require('../../core/storage/container'), | ||
_ = require('underscore'); | ||
@@ -18,11 +19,47 @@ var Container = exports.Container = function Container(client, details) { | ||
Container.prototype.updateMetadata = function (callback) { | ||
this.client.updateContainerMetadata(this.container, callback); | ||
}; | ||
Container.prototype.removeMetadata = function (metadataToRemove, callback) { | ||
this.client.removeContainerMetadata(this, metadataToRemove, callback); | ||
}; | ||
Container.prototype.refreshCdnDetails = function(callback) { | ||
var self = this; | ||
this.client._getCdnContainerDetails(this, function(err, details) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self._setProperties(details); | ||
return callback(err, self); | ||
}); | ||
}; | ||
Container.prototype.enableCdn = function(callback) { | ||
this.client.setCdnEnabled(this, callback); | ||
}; | ||
Container.prototype.updateCdn = function(options, callback) { | ||
this.client.updateCdnContainer(this, options, callback); | ||
}; | ||
Container.prototype._setProperties = function (details) { | ||
this.name = details.name; | ||
this.cdnEnabled = details.cdnEnabled || false; | ||
this.cdnUri = details.cdnUri; | ||
this.cdnSslUri = details.cdnSslUri; | ||
this.ttl = details.ttl; | ||
this.logRetention = details.logRetention; | ||
this.count = details.count || 0; | ||
this.bytes = details.bytes || 0; | ||
}; | ||
this.name = details.name || this.name; | ||
this.cdnEnabled = details.cdnEnabled || this.cdnEnabled || false; | ||
this.cdnUri = details.cdnUri || this.cdnUri; | ||
this.cdnSslUri = details.cdnSslUri || this.cdnSslUri; | ||
this.cdnStreamingUri = details.cdnStreamingUri || this.cdnStreamingUri; | ||
this.cdniOSUri = details.cdniOSUri || this.cdniOSUri; | ||
this.ttl = details.ttl || this.ttl; | ||
this.logRetention = details.logRetention || this.logRetention; | ||
this.count = details.count || this.count || 0 | ||
this.bytes = details.bytes || this.bytes || 0; | ||
this.metadata = details.metadata || this.metadata || {}; | ||
}; | ||
@@ -17,23 +17,8 @@ /* | ||
// Remark: Not fully implemented | ||
File.prototype.addMetadata = function (metadata, callback) { | ||
var newMetadata = utile.clone(this.metadata); | ||
Object.keys(metadata).forEach(function (key) { | ||
newMetadata[key] = metadata[key]; | ||
}); | ||
File.prototype.updateMetadata = function (callback) { | ||
this.client.updateFileMetadata(this.container, this, callback); | ||
}; | ||
var options = { | ||
uri: this.fullPath, | ||
method: 'POST', | ||
headers: this._createHeaders(newMetadata) | ||
}; | ||
this.request(options, function (err, body, res) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.metadata = newMetadata; | ||
callback(null, true); | ||
}); | ||
File.prototype.purgeFromCdn = function(emails, callback) { | ||
this.client.purgeFileFromCdn(this.container, this, emails, callback); | ||
}; | ||
@@ -80,3 +65,2 @@ | ||
Object.keys(details).forEach(function (header) { | ||
@@ -90,10 +74,1 @@ var match; | ||
File.prototype._createHeaders = function (metadata) { | ||
var headers = {}; | ||
Object.keys(metadata).forEach(function (key) { | ||
var header = "x-object-meta-" + key; | ||
headers[header] = metadata[key]; | ||
}); | ||
return headers; | ||
}; |
{ | ||
"name": "pkgcloud", | ||
"description": "An infrastructure-as-a-service agnostic cloud library for node.js", | ||
"version": "0.8.1", | ||
"version": "0.8.2", | ||
"author": "Nodejitsu Inc <info@nodejitsu.com>", | ||
@@ -45,9 +45,15 @@ "contributors": [ | ||
"devDependencies": { | ||
"hock" : "0.1.x", | ||
"hock" : "0.2.x", | ||
"mocha": "1.9.x", | ||
"should": "1.2.x" | ||
"should": "1.2.x", | ||
"mocha-lcov-reporter": "0.0.1", | ||
"coveralls": "2.x.x" | ||
}, | ||
"main": "./lib/pkgcloud", | ||
"scripts": { "test": "make test" }, | ||
"scripts": { | ||
"test": "make test", | ||
"test-cov": "make test-cov", | ||
"test-coveralls": "make test-coveralls" | ||
}, | ||
"engines": { "node": "0.8.x || 0.10.x" } | ||
} |
@@ -17,2 +17,3 @@ # pkgcloud [![Build Status](https://secure.travis-ci.org/nodejitsu/pkgcloud.png?branch=master)](http://travis-ci.org/nodejitsu/pkgcloud) [![NPM version](https://badge.fury.io/js/pkgcloud.png)](http://badge.fury.io/js/pkgcloud) | ||
* [Tests](#tests) | ||
* [Code Coverage](#coverage) | ||
* [Contribute!](#contributing) | ||
@@ -325,3 +326,33 @@ * [Roadmap](#roadmap) | ||
<a name="coverage"></a> | ||
## Code Coverage | ||
You will need jscoverage installed in order to run code coverage. There seems to be many forks of the jscoverage project, but the recommended one is [node-jscoverage](https://github.com/visionmedia/node-jscoverage), because we use [node-coveralls](https://github.com/cainus/node-coveralls) to report coverage to http://coveralls.io. node-coveralls requires output from [mocha-lcov-reporter](https://github.com/StevenLooman/mocha-lcov-reporter), whose documentation mentions node-jscoverage. | ||
### Warning | ||
**Running coverage will mess with your lib folder. It will make a backup lib-bak before running and restore it if the coverage task runs successfully.** | ||
In order to simplify cleanup if something goes wrong, it is recommended to have all all new files added and all changes committed before running coverage, so you'll be able to restore with these commands if something goes wrong: | ||
``` bash | ||
git clean -fd | ||
git checkout lib | ||
``` | ||
### Coverage Pre-requisites | ||
Please make sure jscoverage has been installed following the instructions at [node-jscoverage](https://github.com/visionmedia/node-jscoverage). | ||
### Local Coverage | ||
<code>make test-cov</code> | ||
### Run Coverage locally and send to coveralls.io | ||
Travis takes care of coveralls, so this shouldn't be necessary unless you're troubleshooting a problem with Travis/Coveralls. | ||
You'll need to have access to the coveralls repo_token, which should only be visible to nodejitsu/pkgcloud admins. | ||
1. Create a .coveralls.yml containing the repo_token from https://coveralls.io/r/nodejitsu/pkgcloud | ||
2. Run <code>make test-coveralls</code> | ||
<a name="contributing"></a> | ||
@@ -328,0 +359,0 @@ ## Contribute! |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
456425
13058
373
5
181