Skip to content

Commit 286e063

Browse files
abetomoDeviaVir
authored andcommitted
Added class to set S3 events (#393)
* Update lint and test settings * Add S3Events class * Fix comment * Fix info message
1 parent d17b169 commit 286e063

File tree

4 files changed

+233
-2
lines changed

4 files changed

+233
-2
lines changed

lib/s3_events.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
'use strict'
2+
3+
/**
4+
* Do not create S3 bucket.
5+
* Put the Notification Configuration in the existing Bucket.
6+
*/
7+
class S3Events {
8+
constructor (aws) {
9+
// Authenticated `aws` object in `lib/main.js`
10+
this.lambda = new aws.Lambda({
11+
apiVersion: '2015-03-31'
12+
})
13+
this.s3 = new aws.S3({
14+
apiVersion: '2006-03-01'
15+
})
16+
}
17+
18+
_functionName (params) {
19+
return params.FunctionArn.split(':').pop()
20+
}
21+
22+
_addPermissionParams (params) {
23+
return {
24+
Action: 'lambda:InvokeFunction',
25+
FunctionName: this._functionName(params),
26+
Principal: 's3.amazonaws.com',
27+
SourceArn: 'arn:aws:s3:::' + params.Bucket,
28+
StatementId: params.Bucket
29+
}
30+
}
31+
32+
_addPermission (params) {
33+
return new Promise((resolve, reject) => {
34+
const _params = this._addPermissionParams(params)
35+
this.lambda.addPermission(_params, (err, data) => {
36+
if (err) {
37+
if (err.code !== 'ResourceConflictException') reject(err)
38+
// If it exists it will result in an error but there is no problem.
39+
resolve('Permission already set')
40+
}
41+
resolve(data)
42+
})
43+
})
44+
}
45+
46+
_putBucketNotificationConfigurationParams (params) {
47+
const lambdaFunctionConfiguration = {
48+
Events: params.Events,
49+
LambdaFunctionArn: params.FunctionArn
50+
}
51+
if (params.Filter != null) {
52+
lambdaFunctionConfiguration.Filter = params.Filter
53+
}
54+
55+
return {
56+
Bucket: params.Bucket,
57+
NotificationConfiguration: {
58+
LambdaFunctionConfigurations: [
59+
lambdaFunctionConfiguration
60+
]
61+
}
62+
}
63+
}
64+
65+
_putBucketNotificationConfiguration (params) {
66+
return new Promise((resolve, reject) => {
67+
const _params = this._putBucketNotificationConfigurationParams(params)
68+
this.s3.putBucketNotificationConfiguration(_params, (err, data) => {
69+
if (err) reject(err)
70+
resolve(data)
71+
})
72+
})
73+
}
74+
75+
add (params) {
76+
return this._addPermission(params).then(() => {
77+
return this._putBucketNotificationConfiguration(params)
78+
})
79+
}
80+
}
81+
82+
module.exports = S3Events

lib/schedule_events.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class ScheduleEvents {
5959
if (err) {
6060
if (err.code !== 'ResourceConflictException') throw err
6161
// If it exists it will result in an error but there is no problem.
62-
resolve('Already exists permission')
62+
resolve('Permission already set')
6363
}
6464
resolve(data)
6565
})

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"test": "test"
88
},
99
"scripts": {
10-
"test": "standard && standard bin/node-lambda && mocha"
10+
"lint": "standard && standard bin/node-lambda",
11+
"test": "npm run lint && npm run unit",
12+
"unit": "mocha"
1113
},
1214
"bin": {
1315
"node-lambda": "./bin/node-lambda"

test/s3_events.js

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
'use strict'
2+
3+
const assert = require('chai').assert
4+
const path = require('path')
5+
const aws = require('aws-sdk-mock')
6+
aws.setSDK(path.resolve('node_modules/aws-sdk'))
7+
const S3Events = require('../lib/s3_events')
8+
9+
const params = {
10+
FunctionArn: 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function',
11+
Bucket: 'node-lambda-test-bucket',
12+
Events: ['s3:ObjectCreated:*'],
13+
Filter: null
14+
}
15+
16+
const mockResponse = {
17+
addPermission: {
18+
Statement: JSON.stringify({
19+
Sid: 'node-lambda-test-bucket',
20+
Resource: 'arn:aws:lambda:node-lambda-test-function',
21+
Effect: 'Allow',
22+
Principal: { Service: 's3.amazonaws.com' },
23+
Action: [ 'lambda:InvokeFunction' ],
24+
Condition: { ArnLike: { 'AWS:SourceArn': 'arn:aws:s3:::node-lambda-test-bucket' } }
25+
})
26+
},
27+
28+
putBucketNotificationConfiguration: {}
29+
}
30+
31+
var s3Events = null
32+
33+
/* global before, after, describe, it */
34+
describe('lib/s3_events', () => {
35+
before(() => {
36+
aws.mock('Lambda', 'addPermission', (params, callback) => {
37+
callback(null, mockResponse.addPermission)
38+
})
39+
aws.mock('S3', 'putBucketNotificationConfiguration', (params, callback) => {
40+
callback(null, mockResponse.putBucketNotificationConfiguration)
41+
})
42+
43+
s3Events = new S3Events(require('aws-sdk'))
44+
})
45+
46+
after(() => {
47+
aws.restore('Lambda')
48+
aws.restore('S3')
49+
})
50+
51+
describe('_functionName', () => {
52+
it('Extract name from FunctionArn', () => {
53+
assert.equal(
54+
s3Events._functionName(params),
55+
'node-lambda-test-function'
56+
)
57+
})
58+
})
59+
60+
describe('_addPermissionParams', () => {
61+
it('Return parameters for lambda.addPermission()', () => {
62+
const expected = {
63+
Action: 'lambda:InvokeFunction',
64+
FunctionName: 'node-lambda-test-function',
65+
Principal: 's3.amazonaws.com',
66+
SourceArn: 'arn:aws:s3:::node-lambda-test-bucket',
67+
StatementId: 'node-lambda-test-bucket'
68+
}
69+
assert.deepEqual(s3Events._addPermissionParams(params), expected)
70+
})
71+
})
72+
73+
describe('_putBucketNotificationConfigurationParams', () => {
74+
it('Return parameters for s3.putBucketNotificationConfiguration(). No Filter', () => {
75+
const expected = {
76+
Bucket: 'node-lambda-test-bucket',
77+
NotificationConfiguration: {
78+
LambdaFunctionConfigurations: [{
79+
Events: ['s3:ObjectCreated:*'],
80+
LambdaFunctionArn: 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function'
81+
}]
82+
}
83+
}
84+
assert.deepEqual(
85+
s3Events._putBucketNotificationConfigurationParams(params),
86+
expected
87+
)
88+
})
89+
90+
it('Return parameters for s3.putBucketNotificationConfiguration(). Use Filter', () => {
91+
const expected = {
92+
Bucket: 'node-lambda-test-bucket',
93+
NotificationConfiguration: {
94+
LambdaFunctionConfigurations: [{
95+
Events: ['s3:ObjectCreated:*'],
96+
LambdaFunctionArn: 'arn:aws:lambda:us-west-2:XXX:function:node-lambda-test-function',
97+
Filter: {
98+
Key: {
99+
FilterRules: [{
100+
Name: 'prefix',
101+
Value: 'test-prefix'
102+
}]
103+
}
104+
}
105+
}]
106+
}
107+
}
108+
const _params = Object.assign({}, params)
109+
_params.Filter = {
110+
Key: {
111+
FilterRules: [{
112+
Name: 'prefix',
113+
Value: 'test-prefix'
114+
}]
115+
}
116+
}
117+
assert.deepEqual(
118+
s3Events._putBucketNotificationConfigurationParams(_params),
119+
expected
120+
)
121+
})
122+
})
123+
124+
describe('_addPermission', () => {
125+
it('using mock', () => {
126+
return s3Events._addPermission(params).then(data => {
127+
assert.deepEqual(data, mockResponse.addPermission)
128+
})
129+
})
130+
})
131+
132+
describe('_putBucketNotificationConfiguration', () => {
133+
it('using mock', () => {
134+
return s3Events._putBucketNotificationConfiguration(params).then(data => {
135+
assert.deepEqual(data, mockResponse.putBucketNotificationConfiguration)
136+
})
137+
})
138+
})
139+
140+
describe('add', () => {
141+
it('using mock', () => {
142+
return s3Events.add(params).then(data => {
143+
assert.deepEqual(data, mockResponse.putBucketNotificationConfiguration)
144+
})
145+
})
146+
})
147+
})

0 commit comments

Comments
 (0)