forked from eleven41/aws-lambda-copy-s3-objects
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
157 lines (130 loc) · 5.18 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
console.log("Version 0.2.0");
// Load up all dependencies
var AWS = require('aws-sdk');
var async = require('async');
// CreateS3
//
// Create a reference to an S3 client
// in the desired region.
function createS3(regionName) {
var config = { apiVersion: '2006-03-01' };
if (regionName != null)
config.region = regionName;
var s3 = new AWS.S3(config);
return s3;
}
// This is the entry-point to the Lambda function.
exports.handler = function (event, context) {
if (event.Records == null) {
context.fail('Error', "Event has no records.");
return;
}
// Process all records in the event asynchronously.
async.each(event.Records, processRecord, function (err) {
if (err) {
context.fail('Error', "One or more objects could not be copied.");
} else {
context.succeed();
}
});
};
// processRecord
//
// Iterator function for async.each (called by the handler above).
//
// 1. Get the target bucket from the source bucket's tags
// 2. Copy the object to each of the desired buckets.
function processRecord(record, callback) {
// The source bucket and source key are part of the event data
var srcBucket = record.s3.bucket.name;
var srcKey = decodeURIComponent(record.s3.object.key.replace(/\+/g, " "));
// Get the target bucket(s) based on the source bucket.
// Once we have that, perform the copy.
getTargetBuckets(srcBucket, function (err, targets) {
if (err) {
console.log("Error getting target bucket: "); // an error occurred
console.log(err, err.stack); // an error occurred
callback("Error getting target bucket from source bucket '" + srcBucket + "'");
return;
}
async.each(targets, function (target, callback) {
var targetBucket = target.bucketName;
var regionName = target.regionName;
var targetBucketName = targetBucket;
if (regionName != null)
targetBucketName = targetBucketName + "@" + regionName;
var targetKey = srcKey;
console.log("Copying '" + srcKey + "' from '" + srcBucket + "' to '" + targetBucketName + "'");
// Copy the object from the source bucket
var s3 = createS3(regionName);
s3.copyObject({
Bucket: targetBucket,
Key: targetKey,
CopySource: encodeURIComponent(srcBucket + '/' + srcKey),
MetadataDirective: 'COPY'
}, function (err, data) {
if (err) {
console.log("Error copying '" + srcKey + "' from '" + srcBucket + "' to '" + targetBucketName + "'");
console.log(err, err.stack); // an error occurred
callback("Error copying '" + srcKey + "' from '" + srcBucket + "' to '" + targetBucketName + "'");
} else {
callback();
}
});
}, function (err) {
if (err) {
callback(err);
} else {
callback();
}
});
});
};
// getTargetBuckets
//
// Gets the tags for the named bucket, and
// from those tags, finds the "TargetBucket" tag.
// Once found, it calls the callback function passing
// the tag value as the single parameter.
function getTargetBuckets(bucketName, callback) {
console.log("Getting tags for bucket '" + bucketName + "'");
var s3 = createS3();
s3.getBucketTagging({
Bucket: bucketName
}, function (err, data) {
if (err) {
if (err.code == 'NoSuchTagSet') {
// No tags on the bucket, so the bucket is not configured properly.
callback("Source bucket '" + bucketName + "' is missing 'TargetBucket' tag.", null);
} else {
// Some other error
callback(err, null);
}
return;
}
console.log(data);
var tags = data.TagSet;
console.log("Looking for 'TargetBucket' tag");
for (var i = 0; i < tags.length; ++i) {
var tag = tags[i];
if (tag.Key == 'TargetBucket') {
console.log("Tag 'TargetBucket' found with value '" + tag.Value + "'");
var tagValue = tag.Value.trim();
var buckets = tag.Value.split(' ');
var targets = [];
for (var i = 0; i < buckets.length; ++i) {
var bucketSpec = buckets[i].trim();
if (bucketSpec.length == 0)
continue;
var specParts = bucketSpec.split('@');
var bucketName = specParts[0];
var regionName = specParts[1]
targets.push({ bucketName: bucketName, regionName: regionName });
}
callback(null, targets);
return;
}
}
callback("Tag 'TargetBucket' not found", null);
});
}