-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
executable file
·147 lines (128 loc) · 3.38 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
#!/usr/bin/env node
/*
* High-level overview of the migration process:
*
* list all app files
* read file content and upload file to S3 (concurrency: 10 files)
*
*/
const AWS = require('aws-sdk')
const Promise = require('bluebird')
const mongodb = require('mongodb')
const MongoClient = mongodb.MongoClient
const GridFSBucket = mongodb.GridFSBucket
const mime = require('mime')
const yargs = require('yargs')
const args = yargs
.version('0.0.1')
.option('mongoUri', {
alias: 'm',
required: true,
describe: 'Mongo URI (mongodb://...)'
})
.option('dbName', {
alias: 'd',
describe: 'Database name (default: the mongoUri db)'
})
.option('folder', {
alias: 'f',
describe: 'folder'
})
.option('bucket', {
alias: 'b',
describe: 'bucket name',
required: true
})
.option('region', {
alias: 'r',
describe: 'bucket region',
default: 'us-east-1'
})
.option('accessKeyId', {
alias: 'k',
describe: 'AWS access key id (default: system config)'
})
.option('secretAccessKey', {
alias: 's',
describe: 'AWS secret access key (default: system config)'
})
.option('concurrency', {
alias: 'c',
describe: 'Number of uploads at same time',
default: 10,
type: 'number'
})
.implies('accessKeyId', 'secretAccessKey')
.help()
.alias('help', 'h')
.alias('version', 'v')
.argv
const {mongoUri, dbName, folder, bucket, region, concurrency, accessKeyId, secretAccessKey} = args
console.log('Your options: ', {mongoUri, dbName, folder, bucket, region, concurrency, accessKeyId, secretAccessKey})
const dbOptions = {useNewUrlParser: true, useUnifiedTopology: true}
// setup AWS credentials
if (secretAccessKey && accessKeyId) {
AWS.config.update({accessKeyId, secretAccessKey})
}
// setup AWS clients
const s3 = new AWS.S3({
params: {Bucket: bucket},
region: region
})
let db
let connection
let gridFs
connectToMongoDB()
.then(migrateAppFiles)
.then(closeConnections)
.catch(function (err) {
logError(err)
return closeConnections()
})
function connectToMongoDB () {
console.log('Opening connection to MongoDB')
return MongoClient.connect(mongoUri, dbOptions)
.then(function (_connection) {
connection = _connection
db = dbName ? connection.db(dbName) : connection.db()
})
}
function migrateAppFiles () {
return listAppFiles().then(function (files) {
console.log('Copying', files.length, 'files')
// migrate 10 files at a time
return Promise.map(files, migrateFile, {concurrency})
})
}
function listAppFiles () {
gridFs = new GridFSBucket(db)
const cursor = gridFs.find()
return cursor.toArray()
}
function migrateFile (file) {
console.log('getting file from mongo', file.filename)
const stream = readFileFromMongo(file)
return writeFileToS3(file, stream)
}
function readFileFromMongo (file) {
return gridFs.openDownloadStreamByName(file.filename)
}
function writeFileToS3 (file, data) {
const params = {
ACL: 'public-read',
Key: folder ? `${folder}/${file.filename}`: file.filename,
Body: data,
ContentType: mime.getType(file.filename)
}
return s3.upload(params).promise().then(() => {
console.log(`copied to s3 https://${bucket}/${params.Key}`)
})
}
function closeConnections () {
console.log('Closing connections')
return connection && connection.close()
}
function logError (err) {
console.error(err)
yargs.showHelp()
}