-
Notifications
You must be signed in to change notification settings - Fork 38
/
s3-website.js
executable file
·203 lines (187 loc) · 8.16 KB
/
s3-website.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#!/usr/bin/env node
var AWS = require('aws-sdk')
var s3Website = require('./')
var program = require('commander')
var url = require('url')
var s3site = s3Website.s3site
var deploy = s3Website.deploy
var getConfig = s3Website.config
var templateConfig = s3Website.templateConfig
require('console.table')
require('colors')
/**
* Filter out commander specific properties from options hash, and merge command
* line parameters into single hash.
*/
function getCLArguments (params, options) {
var fromCL = {}
var fromCLKeys = Object.keys(options).filter(function (item) {
var toRemove = ['commands', 'parent', 'options']
if (item.startsWith('_')) return false
return toRemove.indexOf(item) < 0
})
var paramKeys = Object.keys(params)
fromCLKeys.forEach(function (key) { if (options[key]) fromCL[key] = options[key] })
paramKeys.forEach(function (key) { if (params[key]) fromCL[key] = params[key] })
return fromCL
}
function printDeployResults (err, website, results) {
if (err) {
console.error(err.message)
process.exit(1)
}
var numRows = Object.keys(results).reduce(function (prev, current) {
if (results[current].length > prev) { prev = results[current].length }
return prev
}, 0)
var values = new Array(numRows)
values.fill(0)
values = values.map(function (_, index) {
var row = {}
Object.keys(results).forEach(function (key) {
if (results[key][index]) {
row[key] = results[key][index]
} else {
row[key] = ' '
}
})
return row
})
if (values.length > 0) {
console.table('\n\nDeployment Report'.yellow, values)
}
var isEmpty = Object.keys(results).reduce(function (prev, current) {
if (results[current].length > 0) { return false }
return prev
}, true)
if (isEmpty) {
console.log('There were no changes to deploy'.yellow)
} else {
if (website.url) console.log(('Updated site: ' + website.url).green)
}
}
function exclude (val, excludedList) {
excludedList.push(val)
return excludedList
}
program
.usage('<command> [option]')
.description(
'Use one of commands below to create an s3-website or deploy content to an existing bucket.'
).on('--help', function () {
console.log(' Credentials:')
console.log('')
console.log(' Aws Credentials should either be supplied in a local .env file or in ~/.aws/credentials')
console.log(' Credentials should follow this format:')
console.log(' AWS_ACCESS_KEY_ID=MY_KEY_ID')
console.log(' AWS_SECRET_ACCESS_KEY=MY_SECRET_KEY')
console.log(' ')
console.log(' Config file: ')
console.log('')
console.log(' Should be specified using the -f flag. The default config file is .s3-website.json')
console.log(' Should contain only a JSON object containing at least the keys: region, domain, uploadDir')
console.log('')
console.log(' To see more information about a specific command:')
console.log(' s3-website <command> -h'.green)
})
.version(require('./package.json').version)
program
.command('create [domain]')
.usage('[domain [options]]')
.description('Will create and configure an s3 website')
.option('-r, --region <region>', 'Region [us-east-1].')
.option('-i, --index <index>', 'Index Document [index.html].')
.option('-e, --error <error>', 'Error Document.')
.option('-t, --routes <routes>', 'Path to routing rules file.')
.option('--json', 'Output JSON.')
.option('--cert-id <IAM ServerCertId>', 'The ID of your cert in IAM.')
.option('-c, --cert <cert>', 'Path to the public key certificate.')
.option('-k, --key <key>', 'Path to the private key.')
.option('-n, --cert-name <certificate name>', 'A unique name for the server certificate.')
.option('-u, --upload-dir <upload directory>', 'Set directory to upload when site is deployed.')
.option('-d, --deploy', 'Will upload uploadDir immediately after site creation')
.option('-p, --prefix <prefix>', 'Will upload files with the prefix [name/of/folder/to/sync/on/s3]')
.option('-l, --lock-config', 'Will prevent config file from being changed')
.option('--intermediate <intermediate certs>', 'Path to the concatenated intermediate certificates.')
.option('-f, --config-file <file>', 'Path to the config file to read. Default is .s3-website.json')
.option('--exclude <path-pattern>', 'Path pattern to excluded files from being created/updated/removed. This option is repeatable', exclude, [])
.action(function (domain, options) {
var fromCL = getCLArguments({domain: domain}, options)
if (fromCL.configFile == null) fromCL.configFile = '.s3-website.json'
getConfig(fromCL.configFile, fromCL, function (err, config) { // eslint-disable-line handle-callback-err
s3site(config, function (err, website, uploadResults) {
if (err) {
if (options.json) {
console.error(JSON.stringify({ code: err.code, message: err.message }))
} else {
console.error('Error:', err.message)
}
process.exit(1)
}
if (options.json) {
console.log(JSON.stringify(website))
} else {
console.log('Successfully created your website.\n'.green)
console.log(' URL:')
console.log(' ' + website.url)
console.log(' DNS:')
console.log(' ' + config.domain + '. CNAME ' + url.parse(website.url).host + '.\n')
if (website.certId) {
console.log(' Certificate ID:\n ' + website.certId + '\n')
}
printDeployResults(null, website, uploadResults)
}
})
})
})
program
.command('deploy [upload-dir]')
.usage('[dir] [options]')
.description('Will push contents of directory to specified s3 website')
.option('-r, --region <region>', 'Region [us-east-1].')
.option('-p, --prefix <prefix>', 'Will upload files with the prefix [name/of/folder/to/sync/on/s3]')
.option('-l, --lock-config', 'Will prevent config file from being changed')
.option('-d, --domain <domain>', 'Name of bucket [example.bucket] - put always this parameter last one')
.option(
'-f, --config-file <file>',
'Path to the config file to read. Default is .s3-website.json. Note: Using non-standard config file will require passing "-f myConfigFile" with subsequent operations'
)
.option('--exclude <path-pattern>', 'Path pattern to excluded files from being created/updated/removed. This option is repeatable', exclude, [])
.action(function (uploadDir, options) {
var fromCL = getCLArguments({uploadDir: uploadDir}, options)
if (fromCL.configFile == null) fromCL.configFile = '.s3-website.json'
getConfig(fromCL.configFile, fromCL, function (err, config) { // eslint-disable-line handle-callback-err
var s3 = new AWS.S3({ region: config.region })
deploy(s3, config, printDeployResults)
})
}).on('--help', function () {
console.log(' ')
console.log(' Successful deployment requires: '.yellow)
console.log('')
console.log(' Correct config: - passed from commandline or from config file specified with -f flag')
console.log(' region: the region where your bucket lives, can be set by commandline flag or in config file')
console.log(' domain: the name of your bucket, can be set by commandline flag or in config file')
console.log(' uploadDir: the name of the directory whose contents you want to upload,' +
'can be supplied as first argument to deploy or in config file')
console.log('')
console.log(' Valid AWS credentials: - run s3-website -h for more info')
console.log(' ')
console.log(' These can be supplied as command line arguments, or in a json config file specified with -f flag'.green)
})
program
.command('configTemplate')
.usage('')
.description('Creates a configuration file template, which can be used to create site by setting config details and running s3-website create')
.action(function () {
getConfig('.s3-website.json', templateConfig, function (err, config) { // eslint-disable-line handle-callback-er
if (err) { console.err(err) }
})
})
program
.command('*')
.description('Output usage message')
.action(function (env) {
program.help()
})
program.parse(process.argv)
if (!program.args.length) program.outputHelp()