Skip to content

Commit

Permalink
New deleteAllVersions and listFiles functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dvonlehman committed Apr 10, 2015
1 parent 4cea8d7 commit 02e9ab9
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 50 deletions.
14 changes: 8 additions & 6 deletions README.md
Expand Up @@ -31,12 +31,6 @@ You can pass in any valid option accepted by the [AWS.config](http://docs.aws.am

~~~js
// Deploy an individual file
var fileInfo = {
path: '/js/app.js',
contents: fs.createReadStream('/js/app.js'),
size: fs.statSync('/js/app.js').size
};

s3Deployments.deployFile(appId, versionId, fileInfo, callback);

// Returns a readable stream
Expand All @@ -45,10 +39,18 @@ s3Deployments.readFileStream(appId, versionId, filePath);
// Delete version
s3Deployments.deleteVersion(appId, versionId, callback);

// Delete all deployed versions for an app
s3Deployments.deleteAllVersions(appId, callback);

// List all the files for a version
s3Deployments.listFiles(appId, versionId, callback);

// Check if file exists
s3Deployments.fileExists(appId, versionId, filePath, callback);
~~~

See the [unit tests](https://github.com/4front/s3-deployments/blob/master/test/s3.js) for example calls of all these functions.

## Running Tests
~~~
npm test
Expand Down
56 changes: 42 additions & 14 deletions lib/s3.js
Expand Up @@ -60,20 +60,7 @@ S3Deployments.prototype.readFileStream = function(appId, versionId, filePath) {

// Delete a deployed version of an app
S3Deployments.prototype.deleteVersion = function(appId, versionId, callback) {
var self = this;
var prefix = appId + '/' + versionId;

this._s3.listObjects({Bucket: this.options.bucket, Prefix: prefix}, function(err, data) {
if (err)
return callback(err);

// Now delete each object
var keys = _.map(data.Contents, "Key");

async.each(keys, function(key, cb) {
self._s3.deleteObject({Bucket: self.options.bucket, Key: key}, cb);
}, callback);
});
this._deleteObjects(appId + "/" + versionId, callback);
};

S3Deployments.prototype.fileExists = function(appId, versionId, filePath, callback) {
Expand All @@ -91,3 +78,44 @@ S3Deployments.prototype.fileExists = function(appId, versionId, filePath, callba
callback(null, true);
});
};

// Delete all deployed versions for a given application
S3Deployments.prototype.deleteAllVersions = function(appId, callback) {
this._deleteObjects(appId, callback);
};

// List the files deployed for a given version
S3Deployments.prototype.listFiles = function(appId, versionId, callback) {
var prefix = appId + '/' + versionId;
this._listKeys(prefix, function(err, keys) {
if (err) return callback(err);

var prefixLength = prefix.length;
var filePaths = _.map(keys, function(key) {
return key.slice(prefixLength + 1);
});

callback(null, filePaths);
});
};

S3Deployments.prototype._listKeys = function(prefix, callback) {
var self = this;
this._s3.listObjects({Bucket: this.options.bucket, Prefix: prefix}, function(err, data) {
if (err)
return callback(err);

callback(null, _.map(data.Contents, "Key"));
});
};

S3Deployments.prototype._deleteObjects = function(prefix, callback) {
var self = this;
this._listKeys(prefix, function(err, keys) {
if (err) return callback(err);

async.each(keys, function(key, cb) {
self._s3.deleteObject({Bucket: self.options.bucket, Key: key}, cb);
}, callback);
});
};
107 changes: 77 additions & 30 deletions test/s3.js
Expand Up @@ -12,21 +12,20 @@ require('dash-assert');
describe('S3Deployments', function() {
var self;

var port = 4658;
var bucket = "4front-deployments";

var s3Deployments = new S3Deployments({
bucket: bucket,
accessKeyId: "123",
secretAccessKey: "abc",
endpoint: "localhost:" + port,
sslEnabled: false,
s3ForcePathStyle: true
});

before(function(done) {
self = this;

var port = 4658;
var bucket = "4front-deployments";

this.s3 = new S3Deployments({
bucket: bucket,
accessKeyId: "123",
secretAccessKey: "abc",
endpoint: "localhost:" + port,
sslEnabled: false,
s3ForcePathStyle: true
});

var s3rver = new S3rver();

var fakeS3Dir = '/tmp/s3rver';
Expand All @@ -50,7 +49,7 @@ describe('S3Deployments', function() {
},
function(cb) {
// Ensure the bucket exists
self.s3._s3.createBucket({ACL: 'public-read', Bucket: bucket}, function(err) {
s3Deployments._s3.createBucket({ACL: 'public-read', Bucket: bucket}, function(err) {
if (err && err.code !== 'BucketAlreadyExists')
return cb(err);

Expand All @@ -76,10 +75,10 @@ describe('S3Deployments', function() {

async.series([
function(cb) {
self.s3.deployFile(self.appId, self.versionId, fileInfo, cb);
s3Deployments.deployFile(self.appId, self.versionId, fileInfo, cb);
},
function(cb) {
self.s3.fileExists(self.appId, self.versionId, fileInfo.path, function(err, exists) {
s3Deployments.fileExists(self.appId, self.versionId, fileInfo.path, function(err, exists) {
if (err) return cb(err);

assert.isTrue(exists);
Expand All @@ -88,7 +87,7 @@ describe('S3Deployments', function() {
},
function(cb) {
var output = '';
self.s3.readFileStream(self.appId, self.versionId, fileInfo.path)
s3Deployments.readFileStream(self.appId, self.versionId, fileInfo.path)
.on('data', function(chunk) {
output += chunk.toString();
})
Expand All @@ -104,7 +103,7 @@ describe('S3Deployments', function() {
});

it('fileExists returns false for missing file', function(done) {
self.s3.fileExists(this.appId, this.versionId, 'missingfile.txt', function(err, exists) {
s3Deployments.fileExists(this.appId, this.versionId, 'missingfile.txt', function(err, exists) {
if (err) return done(err);

assert.isFalse(exists);
Expand All @@ -113,7 +112,7 @@ describe('S3Deployments', function() {
});

it('read missing file', function(done) {
this.s3.readFileStream(this.appId, this.versionId, 'missingfile.txt')
s3Deployments.readFileStream(this.appId, this.versionId, 'missingfile.txt')
.on('missing', function(err) {
assert.equal(err.code, 'fileNotFound');
done();
Expand All @@ -123,29 +122,39 @@ describe('S3Deployments', function() {
});
});

it('delete version', function(done) {
it('listFiles()', function(done) {
var files = ["js/main.js", "css/styles.css", "index.html"];
async.series([
function(cb) {
deployTestFiles(self.appId, self.versionId, files, cb);
},
function(cb) {
s3Deployments.listFiles(self.appId, self.versionId, function(err, data) {
if (err) return cb(err);

assert.noDifferences(files, data);
cb();
})
}
], done);
});

it('deleteVersion()', function(done) {
var files = ['js/main.js', 'css/styles.css'];

async.series([
function(cb) {
// Upload some files
async.each(files, function(path, cb1) {
var fileInfo = {
path: path,
contents: sbuff(path),
size: path.length
};
self.s3.deployFile(self.appId, self.versionId, fileInfo, cb1);
}, cb);
deployTestFiles(self.appId, self.versionId, files, cb);
},
function(cb) {
// Delete the version
self.s3.deleteVersion(self.appId, self.versionId, cb);
s3Deployments.deleteVersion(self.appId, self.versionId, cb);
},
function(cb) {
// Verify that the files are gone.
async.each(files, function(filePath, cb1) {
self.s3.fileExists(self.appId, self.versionId, filePath, function(err, exists) {
s3Deployments.fileExists(self.appId, self.versionId, filePath, function(err, exists) {
if (err) return cb1(err);

assert.isFalse(exists);
Expand All @@ -155,4 +164,42 @@ describe('S3Deployments', function() {
}
], done);
});

it('deleteAllVersions()', function(done) {
var versions = _.times(3, function() {
return shortid.generate();
});

var files = ['js/main.js', 'css/styles.css'];

async.series([
function(cb) {
async.each(versions, function(versionId, cb1) {
deployTestFiles(self.appId, versionId, files, cb1);
}, cb);
},
function(cb) {
// Delete the application
s3Deployments.deleteAllVersions(self.appId, cb);
},
function(cb) {
// Verify that the versions are gone
s3Deployments._listKeys(self.appId, function(err, keys) {
assert.equal(0, keys.length);
cb();
});
}
], done);
});

function deployTestFiles(appId, versionId, files, callback) {
async.each(files, function(path, cb) {
var fileInfo = {
path: path,
contents: sbuff(path),
size: path.length
};
s3Deployments.deployFile(appId, versionId, fileInfo, cb);
}, callback);
}
});

0 comments on commit 02e9ab9

Please sign in to comment.