Skip to content

Commit

Permalink
Merge pull request #37 from mpvosseller/mpv/add-bucketNameKey-support
Browse files Browse the repository at this point in the history
Adds support for fetching the bucket name from the stack output
  • Loading branch information
k1LoW authored Jan 3, 2020
2 parents 7cf567a + 1408513 commit d3f8945
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 71 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ custom:
CacheControl: 'no-cache'
- "*.js":
CacheControl: 'public, max-age=31536000'
- bucketNameKey: AnotherBucketNameOutputKey
localDir: path/to/another

resources:
Resources:
Expand All @@ -55,6 +57,11 @@ resources:
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
AnotherBucket:
Type: AWS::S3::Bucket
Outputs:
AnotherBucketNameOutputKey:
Value: !Ref AnotherBucket
```
## Usage
Expand Down
159 changes: 88 additions & 71 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const s3 = require('@auth0/s3');
const chalk = require('chalk');
const minimatch = require('minimatch');
const path = require('path');
const resolveStackOutput = require('./resolveStackOutput')

const messagePrefix = 'S3 Sync: ';

Expand Down Expand Up @@ -67,64 +68,67 @@ class ServerlessS3Sync {
if (s.hasOwnProperty('defaultContentType')) {
defaultContentType = s.defaultContentType;
}
if (!s.bucketName || !s.localDir) {
if ((!s.bucketName && !s.bucketNameKey) || !s.localDir) {
throw 'Invalid custom.s3Sync';
}
let deleteRemoved = true;
if (s.hasOwnProperty('deleteRemoved')) {
deleteRemoved = s.deleteRemoved;
}

return new Promise((resolve) => {
const localDir = [servicePath, s.localDir].join('/');

const params = {
maxAsyncS3: 5,
localDir,
deleteRemoved,
followSymlinks: followSymlinks,
getS3Params: (localFile, stat, cb) => {
const s3Params = {};

if(Array.isArray(s.params)) {
s.params.forEach((param) => {
const glob = Object.keys(param)[0];
if(minimatch(localFile, `${path.resolve(localDir)}/${glob}`)) {
Object.assign(s3Params, this.extractMetaParams(param) || {});
return this.getBucketName(s)
.then(bucketName => {
return new Promise((resolve) => {
const localDir = [servicePath, s.localDir].join('/');

const params = {
maxAsyncS3: 5,
localDir,
deleteRemoved,
followSymlinks: followSymlinks,
getS3Params: (localFile, stat, cb) => {
const s3Params = {};

if(Array.isArray(s.params)) {
s.params.forEach((param) => {
const glob = Object.keys(param)[0];
if(minimatch(localFile, `${path.resolve(localDir)}/${glob}`)) {
Object.assign(s3Params, this.extractMetaParams(param) || {});
}
});
}
});
}

cb(null, s3Params);
},
s3Params: {
Bucket: s.bucketName,
Prefix: bucketPrefix,
ACL: acl
}
};
if (typeof(defaultContentType) != 'undefined') {
Object.assign(params, {defaultContentType: defaultContentType})
}
const uploader = this.client().uploadDir(params);
uploader.on('error', (err) => {
throw err;
});
let percent = 0;
uploader.on('progress', () => {
if (uploader.progressTotal === 0) {
return;
}
const current = Math.round((uploader.progressAmount / uploader.progressTotal) * 10) * 10;
if (current > percent) {
percent = current;
cli.printDot();
}
});
uploader.on('end', () => {
resolve('done');
cb(null, s3Params);
},
s3Params: {
Bucket: bucketName,
Prefix: bucketPrefix,
ACL: acl
}
};
if (typeof(defaultContentType) != 'undefined') {
Object.assign(params, {defaultContentType: defaultContentType})
}
const uploader = this.client().uploadDir(params);
uploader.on('error', (err) => {
throw err;
});
let percent = 0;
uploader.on('progress', () => {
if (uploader.progressTotal === 0) {
return;
}
const current = Math.round((uploader.progressAmount / uploader.progressTotal) * 10) * 10;
if (current > percent) {
percent = current;
cli.printDot();
}
});
uploader.on('end', () => {
resolve('done');
});
});
});
});
});
return Promise.all(promises)
.then(() => {
Expand All @@ -146,30 +150,33 @@ class ServerlessS3Sync {
if (s.hasOwnProperty('bucketPrefix')) {
bucketPrefix = s.bucketPrefix;
}
return new Promise((resolve) => {
const params = {
Bucket: s.bucketName,
Prefix: bucketPrefix
};
const uploader = this.client().deleteDir(params);
uploader.on('error', (err) => {
throw err;
return this.getBucketName(s)
.then(bucketName => {
return new Promise((resolve) => {
const params = {
Bucket: bucketName,
Prefix: bucketPrefix
};
const uploader = this.client().deleteDir(params);
uploader.on('error', (err) => {
throw err;
});
let percent = 0;
uploader.on('progress', () => {
if (uploader.progressTotal === 0) {
return;
}
const current = Math.round((uploader.progressAmount / uploader.progressTotal) * 10) * 10;
if (current > percent) {
percent = current;
cli.printDot();
}
});
uploader.on('end', () => {
resolve('done');
});
});
});
let percent = 0;
uploader.on('progress', () => {
if (uploader.progressTotal === 0) {
return;
}
const current = Math.round((uploader.progressAmount / uploader.progressTotal) * 10) * 10;
if (current > percent) {
percent = current;
cli.printDot();
}
});
uploader.on('end', () => {
resolve('done');
});
});
});
return Promise.all(promises)
.then(() => {
Expand All @@ -187,6 +194,16 @@ class ServerlessS3Sync {
}
return validParams;
}

getBucketName(s) {
if (s.bucketName) {
return Promise.resolve(s.bucketName)
} else if (s.bucketNameKey) {
return resolveStackOutput(this, s.bucketNameKey)
} else {
return Promise.reject("Unable to find bucketName. Please provide a value for bucketName or bucketNameKey")
}
}
}

module.exports = ServerlessS3Sync;
24 changes: 24 additions & 0 deletions resolveStackOutput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function resolveStackOutput(plugin, outputKey) {
const provider = plugin.serverless.getProvider('aws');
const awsCredentials = provider.getCredentials();
const cfn = new provider.sdk.CloudFormation({
region: awsCredentials.region,
credentials: awsCredentials.credentials
});
const stackName = provider.naming.getStackName();

return cfn
.describeStacks({ StackName: stackName })
.promise()
.then(data => {
const output = data.Stacks[0].Outputs.find(
e => e.OutputKey === outputKey
);
if (!output) {
throw `Failed to resolve stack Output '${outputKey}' in stack '${stackName}'`;
}
return output.OutputValue;
});
}

module.exports = resolveStackOutput;

0 comments on commit d3f8945

Please sign in to comment.