1 | 'use strict'
|
2 |
|
3 | const crypto = require('crypto')
|
4 |
|
5 | const S3_LOCATION_POSSIBLE_VALUES = [
|
6 | 'EU',
|
7 | 'ap-northeast-1',
|
8 | 'ap-south-1',
|
9 | 'ap-southeast-1',
|
10 | 'ap-southeast-2',
|
11 | 'cn-north-1',
|
12 | 'eu-central-1',
|
13 | 'eu-west-1',
|
14 | 'sa-east-1',
|
15 | 'us-west-1',
|
16 | 'us-west-2'
|
17 | ]
|
18 |
|
19 | class S3Deploy {
|
20 | constructor (aws, region) {
|
21 |
|
22 | this.s3 = new aws.S3({
|
23 | region: region,
|
24 | apiVersion: '2006-03-01'
|
25 | })
|
26 | }
|
27 |
|
28 | _md5 (str) {
|
29 | return crypto
|
30 | .createHash('md5')
|
31 | .update(str, 'utf8')
|
32 | .digest('hex')
|
33 | }
|
34 |
|
35 | _convertRegionStringToEnvVarName (region) {
|
36 | if (region == null) return 'undefined'
|
37 | return region.replace(/-/g, '_').toUpperCase()
|
38 | }
|
39 |
|
40 | _getBucketNameFromEnvVar (region) {
|
41 | const key = [
|
42 | 'S3',
|
43 | this._convertRegionStringToEnvVarName(region),
|
44 | 'BUCKET'
|
45 | ].join('_')
|
46 | return process.env[key]
|
47 | }
|
48 |
|
49 | _getS3KeyPrefixFromEnvVar (region) {
|
50 | const key = [
|
51 | 'S3',
|
52 | this._convertRegionStringToEnvVarName(region),
|
53 | 'PREFIX'
|
54 | ].join('_')
|
55 | return process.env[key]
|
56 | }
|
57 |
|
58 | _bucketName (params) {
|
59 | const bucketNameFromEnvVar = this._getBucketNameFromEnvVar(params.region)
|
60 | if (bucketNameFromEnvVar != null) return bucketNameFromEnvVar
|
61 |
|
62 | return [
|
63 | params.FunctionName,
|
64 | params.region,
|
65 | this._md5(params.FunctionName + params.region)
|
66 | ]
|
67 | .join('-')
|
68 | .substr(0, 63)
|
69 | }
|
70 |
|
71 | _s3Key (params) {
|
72 | const s3Prefix = this._getS3KeyPrefixFromEnvVar(params.region)
|
73 | const keys = [`deploy-package-${params.FunctionName}.zip`]
|
74 | if (s3Prefix != null) {
|
75 | keys.unshift(s3Prefix.replace(/\/$/, ''))
|
76 | }
|
77 | return keys.join('/')
|
78 | }
|
79 |
|
80 | _getS3Location (region) {
|
81 | return S3_LOCATION_POSSIBLE_VALUES.includes(region) ? region : null
|
82 | }
|
83 |
|
84 | _createBucket (params) {
|
85 | const _params = {
|
86 | Bucket: params.bucketName
|
87 | }
|
88 | const s3Locatoin = this._getS3Location(params.region)
|
89 | if (s3Locatoin != null) {
|
90 | _params.CreateBucketConfiguration = {
|
91 | LocationConstraint: s3Locatoin
|
92 | }
|
93 | }
|
94 | return new Promise((resolve, reject) => {
|
95 | this.s3.createBucket(_params, (err, data) => {
|
96 | if (err) {
|
97 |
|
98 | if (err.code === 'BucketAlreadyOwnedByYou') return resolve({})
|
99 | return reject(err)
|
100 | }
|
101 | resolve(data)
|
102 | })
|
103 | })
|
104 | }
|
105 |
|
106 | _putObject (params, buffer) {
|
107 | const _params = {
|
108 | Body: buffer,
|
109 | Bucket: params.bucketName,
|
110 | Key: params.s3Key
|
111 | }
|
112 | return new Promise((resolve, reject) => {
|
113 | this.s3.putObject(_params, (err, data) => {
|
114 | if (err) reject(err)
|
115 | resolve(data)
|
116 | })
|
117 | })
|
118 | }
|
119 |
|
120 | putPackage (params, region, buffer) {
|
121 | const _params = Object.assign({region: region}, params)
|
122 | _params.bucketName = this._bucketName(_params)
|
123 | _params.s3Key = this._s3Key(_params)
|
124 |
|
125 | return this._createBucket(_params).then((result) => {
|
126 | if (result.Location != null) {
|
127 | console.log('=> S3 Bucket created:')
|
128 | console.log(`===> ${_params.bucketName}`)
|
129 | }
|
130 | return this._putObject(_params, buffer)
|
131 | }).then((result) => {
|
132 | console.log('=> Deploy the zip file to S3:')
|
133 | console.log(`===> ${_params.bucketName}/${_params.s3Key}`)
|
134 | return {
|
135 | S3Bucket: _params.bucketName,
|
136 | S3Key: _params.s3Key
|
137 | }
|
138 | })
|
139 | }
|
140 | }
|
141 |
|
142 | module.exports = S3Deploy
|