presidium 4.0.0 → 4.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DynamoDBGlobalSecondaryIndex.js +5 -4
- package/DynamoDBStream.js +6 -5
- package/DynamoDBTable.js +5 -4
- package/ECR.js +5 -4
- package/GoogleChromeForTesting.js +25 -83
- package/HTTP.js +1 -1
- package/S3Bucket.js +8 -14
- package/SecretsManager.js +64 -46
- package/internal/createS3DeleteAllObjectsAggregateError.js +16 -0
- package/internal/createS3DeleteAllObjectsAggregateError.test.js +50 -0
- package/internal/dynamoDBStreamListStreams.js +1 -0
- package/internal/getAbsoluteFilePath.js +17 -0
- package/internal/getAbsoluteFilePath.test.js +19 -0
- package/internal/getChromeBinaryOrExecutableFilePath.js +15 -0
- package/internal/getChromeBinaryOrExecutableFilePath.test.js +17 -0
- package/internal/getChromeUrl.js +20 -0
- package/internal/getChromeUrl.test.js +22 -0
- package/internal/getChromeVersions.js +19 -0
- package/internal/getPlatform.js +22 -0
- package/internal/getPlatform.test.js +33 -0
- package/internal/retryHTTPRequest.js +17 -0
- package/internal/retryHTTPRequest.test.js +40 -0
- package/package.json +1 -1
|
@@ -24,6 +24,7 @@ const DynamoDBAttributeValueJSON =
|
|
|
24
24
|
require('./internal/DynamoDBAttributeValueJSON')
|
|
25
25
|
const hashJSON = require('./internal/hashJSON')
|
|
26
26
|
const sleep = require('./internal/sleep')
|
|
27
|
+
const retryHTTPRequest = require('./internal/retryHTTPRequest')
|
|
27
28
|
const createExpressionAttributeNames =
|
|
28
29
|
require('./internal/createExpressionAttributeNames')
|
|
29
30
|
const createExpressionAttributeValues =
|
|
@@ -97,9 +98,9 @@ class DynamoDBGlobalSecondaryIndex {
|
|
|
97
98
|
this.key = options.key
|
|
98
99
|
this.name = DynamoDBIndexname(this.key)
|
|
99
100
|
|
|
100
|
-
this.accessKeyId = options.accessKeyId
|
|
101
|
-
this.secretAccessKey = options.secretAccessKey
|
|
102
|
-
this.region = options.region
|
|
101
|
+
this.accessKeyId = options.accessKeyId
|
|
102
|
+
this.secretAccessKey = options.secretAccessKey
|
|
103
|
+
this.region = options.region
|
|
103
104
|
this.apiVersion = '2012-08-10'
|
|
104
105
|
|
|
105
106
|
this.endpoint = `dynamodb.${this.region}.amazonaws.com`
|
|
@@ -227,7 +228,7 @@ class DynamoDBGlobalSecondaryIndex {
|
|
|
227
228
|
}
|
|
228
229
|
})
|
|
229
230
|
|
|
230
|
-
return this.http
|
|
231
|
+
return retryHTTPRequest(this.http, method, url, { headers, body: payload })
|
|
231
232
|
}
|
|
232
233
|
|
|
233
234
|
/**
|
package/DynamoDBStream.js
CHANGED
|
@@ -16,6 +16,7 @@ const AwsAuthorization = require('./internal/AwsAuthorization')
|
|
|
16
16
|
const AmzDate = require('./internal/AmzDate')
|
|
17
17
|
const Readable = require('./Readable')
|
|
18
18
|
const sleep = require('./internal/sleep')
|
|
19
|
+
const retryHTTPRequest = require('./internal/retryHTTPRequest')
|
|
19
20
|
const dynamoDBStreamGetStreamsIterator =
|
|
20
21
|
require('./internal/dynamoDBStreamGetStreamsIterator')
|
|
21
22
|
const dynamoDBStreamGetShardsIterator =
|
|
@@ -115,9 +116,9 @@ class DynamoDBStream {
|
|
|
115
116
|
this.ListStreamsLimit = options.ListStreamsLimit ?? 100
|
|
116
117
|
this.JSON = options.JSON ?? false
|
|
117
118
|
|
|
118
|
-
this.accessKeyId = options.accessKeyId
|
|
119
|
-
this.secretAccessKey = options.secretAccessKey
|
|
120
|
-
this.region = options.region
|
|
119
|
+
this.accessKeyId = options.accessKeyId
|
|
120
|
+
this.secretAccessKey = options.secretAccessKey
|
|
121
|
+
this.region = options.region
|
|
121
122
|
this.apiVersion = '2012-08-10'
|
|
122
123
|
|
|
123
124
|
this.endpoint = `dynamodb.${this.region}.amazonaws.com`
|
|
@@ -238,7 +239,7 @@ class DynamoDBStream {
|
|
|
238
239
|
}
|
|
239
240
|
})
|
|
240
241
|
|
|
241
|
-
return this.http
|
|
242
|
+
return retryHTTPRequest(this.http, method, url, { headers, body: payload })
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
/**
|
|
@@ -296,7 +297,7 @@ class DynamoDBStream {
|
|
|
296
297
|
}
|
|
297
298
|
})
|
|
298
299
|
|
|
299
|
-
return this.streamsHttp
|
|
300
|
+
return retryHTTPRequest(this.streamsHttp, method, url, { headers, body: payload })
|
|
300
301
|
}
|
|
301
302
|
|
|
302
303
|
/**
|
package/DynamoDBTable.js
CHANGED
|
@@ -25,6 +25,7 @@ const AwsError = require('./internal/AwsError')
|
|
|
25
25
|
const hashJSON = require('./internal/hashJSON')
|
|
26
26
|
const sleep = require('./internal/sleep')
|
|
27
27
|
const join = require('./internal/join')
|
|
28
|
+
const retryHTTPRequest = require('./internal/retryHTTPRequest')
|
|
28
29
|
const createExpressionAttributeNames =
|
|
29
30
|
require('./internal/createExpressionAttributeNames')
|
|
30
31
|
const createExpressionAttributeValues =
|
|
@@ -93,9 +94,9 @@ class DynamoDBTable {
|
|
|
93
94
|
this.name = options.name
|
|
94
95
|
this.key = options.key
|
|
95
96
|
|
|
96
|
-
this.accessKeyId = options.accessKeyId
|
|
97
|
-
this.secretAccessKey = options.secretAccessKey
|
|
98
|
-
this.region = options.region
|
|
97
|
+
this.accessKeyId = options.accessKeyId
|
|
98
|
+
this.secretAccessKey = options.secretAccessKey
|
|
99
|
+
this.region = options.region
|
|
99
100
|
this.apiVersion = '2012-08-10'
|
|
100
101
|
|
|
101
102
|
this.endpoint = `dynamodb.${this.region}.amazonaws.com`
|
|
@@ -216,7 +217,7 @@ class DynamoDBTable {
|
|
|
216
217
|
}
|
|
217
218
|
})
|
|
218
219
|
|
|
219
|
-
return this.http
|
|
220
|
+
return retryHTTPRequest(this.http, method, url, { headers, body: payload })
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
/**
|
package/ECR.js
CHANGED
|
@@ -13,6 +13,7 @@ const AwsAuthorization = require('./internal/AwsAuthorization')
|
|
|
13
13
|
const AwsError = require('./internal/AwsError')
|
|
14
14
|
const userAgent = require('./userAgent')
|
|
15
15
|
const Readable = require('./Readable')
|
|
16
|
+
const retryHTTPRequest = require('./internal/retryHTTPRequest')
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* @name ECR
|
|
@@ -45,9 +46,9 @@ const Readable = require('./Readable')
|
|
|
45
46
|
*/
|
|
46
47
|
class ECR {
|
|
47
48
|
constructor(options) {
|
|
48
|
-
this.accessKeyId = options.accessKeyId
|
|
49
|
-
this.secretAccessKey = options.secretAccessKey
|
|
50
|
-
this.region = options.region
|
|
49
|
+
this.accessKeyId = options.accessKeyId
|
|
50
|
+
this.secretAccessKey = options.secretAccessKey
|
|
51
|
+
this.region = options.region
|
|
51
52
|
this.apiVersion = '2015-09-21'
|
|
52
53
|
|
|
53
54
|
this.endpoint = `ecr.${this.region}.amazonaws.com`
|
|
@@ -112,7 +113,7 @@ class ECR {
|
|
|
112
113
|
}
|
|
113
114
|
})
|
|
114
115
|
|
|
115
|
-
return this.http
|
|
116
|
+
return retryHTTPRequest(this.http, method, url, { headers, body: payload })
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
/**
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const https = require('https')
|
|
9
|
+
const EventEmitter = require('events')
|
|
9
10
|
const os = require('os')
|
|
10
11
|
const fs = require('fs')
|
|
11
12
|
const path = require('path')
|
|
@@ -15,15 +16,12 @@ const extract = require('extract-zip')
|
|
|
15
16
|
const HTTP = require('./HTTP')
|
|
16
17
|
const XML = require('./XML')
|
|
17
18
|
const Readable = require('./Readable')
|
|
19
|
+
const getPlatform = require('./internal/getPlatform')
|
|
18
20
|
const walk = require('./internal/walk')
|
|
19
21
|
const sleep = require('./internal/sleep')
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const response = await http.GET('https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json')
|
|
24
|
-
const data = await Readable.JSON(response)
|
|
25
|
-
return data
|
|
26
|
-
}
|
|
22
|
+
const getChromeUrl = require('./internal/getChromeUrl')
|
|
23
|
+
const getAbsoluteFilePath = require('./internal/getAbsoluteFilePath')
|
|
24
|
+
const getChromeBinaryOrExecutableFilePath = require('./internal/getChromeBinaryOrExecutableFilePath')
|
|
27
25
|
|
|
28
26
|
function updateConsoleLog(message, platform) {
|
|
29
27
|
readline.cursorTo(process.stdout, 0, undefined);
|
|
@@ -31,66 +29,16 @@ function updateConsoleLog(message, platform) {
|
|
|
31
29
|
process.stdout.write(message);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
function
|
|
35
|
-
let platform = os.platform()
|
|
36
|
-
if (platform == 'darwin') {
|
|
37
|
-
platform = 'mac'
|
|
38
|
-
}
|
|
39
|
-
const arch = os.arch()
|
|
40
|
-
|
|
41
|
-
if (platform == 'mac') {
|
|
42
|
-
platform = `${platform}-${arch}`
|
|
43
|
-
}
|
|
44
|
-
else if (platform == 'win32') {
|
|
45
|
-
platform = `win${arch.slice(1)}`
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
platform = `${platform}${arch.slice(1)}`
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return platform
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function getChromeUrl() {
|
|
32
|
+
async function installChrome() {
|
|
55
33
|
const platform = getPlatform()
|
|
34
|
+
const url = await getChromeUrl.call(this, platform)
|
|
56
35
|
|
|
57
|
-
let url
|
|
58
|
-
|
|
59
|
-
const chromeVersions = await getChromeVersions()
|
|
60
|
-
const channel = `${this.chromeVersion[0].toUpperCase()}${this.chromeVersion.slice(1)}`
|
|
61
|
-
const chromeVersionNumber = chromeVersions.channels[channel].version
|
|
62
|
-
url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
63
|
-
} else {
|
|
64
|
-
const chromeVersionNumber = this.chromeVersion
|
|
65
|
-
url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return url
|
|
69
|
-
}
|
|
36
|
+
let filepath = `${this.chromeDir}/${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
|
|
37
|
+
filepath = getAbsoluteFilePath(filepath, platform)
|
|
70
38
|
|
|
71
|
-
async function installChrome() {
|
|
72
|
-
const platform = getPlatform()
|
|
73
39
|
const delimiter = platform.startsWith('win') ? '\\' : '/'
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
let filepath = `${this.chromeDir}${delimiter}${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
|
|
77
|
-
if (platform.startsWith('win')) {
|
|
78
|
-
filepath = filepath.replace(/\//g, '\\')
|
|
79
|
-
if (!filepath.startsWith(`${__dirname[0]}:`)) {
|
|
80
|
-
filepath = path.join(process.cwd(), filepath)
|
|
81
|
-
}
|
|
82
|
-
} else if (!filepath.startsWith('/')) {
|
|
83
|
-
filepath = path.join(process.cwd(), filepath)
|
|
84
|
-
}
|
|
40
|
+
const parentDir = `${filepath.split(delimiter).slice(0, -1).join(delimiter)}`
|
|
85
41
|
|
|
86
|
-
let parentDir = `${filepath.split(delimiter).slice(0, -1).join(delimiter)}`
|
|
87
|
-
if (platform.startsWith('win')) {
|
|
88
|
-
if (!filepath.startsWith(`${__dirname[0]}:`)) {
|
|
89
|
-
parentDir = path.join(process.cwd(), parentDir)
|
|
90
|
-
}
|
|
91
|
-
} else if (!parentDir.startsWith('/')) {
|
|
92
|
-
parentDir = path.join(process.cwd(), parentDir)
|
|
93
|
-
}
|
|
94
42
|
await fs.promises.mkdir(parentDir, { recursive: true })
|
|
95
43
|
|
|
96
44
|
const http = new HTTP()
|
|
@@ -113,27 +61,26 @@ async function installChrome() {
|
|
|
113
61
|
fileStream.write(chunk)
|
|
114
62
|
})
|
|
115
63
|
|
|
64
|
+
response.on('end', () => {
|
|
65
|
+
fileStream.end()
|
|
66
|
+
})
|
|
67
|
+
|
|
116
68
|
let resolve
|
|
117
69
|
const promise = new Promise(_resolve => {
|
|
118
70
|
resolve = _resolve
|
|
119
71
|
})
|
|
120
|
-
|
|
72
|
+
fileStream.on('finish', () => {
|
|
121
73
|
resolve()
|
|
122
74
|
})
|
|
123
75
|
await promise
|
|
124
76
|
|
|
125
77
|
console.log('Extracting', filepath)
|
|
126
|
-
|
|
127
|
-
await extract(filepath, { dir: parentDir })
|
|
128
|
-
} catch (_error) {
|
|
129
|
-
await sleep(1000)
|
|
130
|
-
await extract(filepath, { dir: parentDir })
|
|
131
|
-
}
|
|
78
|
+
await extract(filepath, { dir: parentDir })
|
|
132
79
|
}
|
|
133
80
|
|
|
134
81
|
async function getChromeFilepath() {
|
|
135
82
|
const platform = getPlatform()
|
|
136
|
-
const url = await getChromeUrl.call(this)
|
|
83
|
+
const url = await getChromeUrl.call(this, platform)
|
|
137
84
|
const filepath = `${this.chromeDir}/${url.replace('https://storage.googleapis.com/chrome-for-testing-public/', '')}`
|
|
138
85
|
const parentDir = `${filepath.split('/').slice(0, -1).join('/')}`
|
|
139
86
|
|
|
@@ -144,16 +91,13 @@ async function getChromeFilepath() {
|
|
|
144
91
|
}
|
|
145
92
|
|
|
146
93
|
for await (const filepath of walk(parentDir)) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return filepath
|
|
152
|
-
}
|
|
153
|
-
if (platform.startsWith('win') && filepath.endsWith('chrome.exe')) {
|
|
154
|
-
return filepath
|
|
94
|
+
const chromeBinaryOrExecutableFilePath =
|
|
95
|
+
getChromeBinaryOrExecutableFilePath(filepath, platform)
|
|
96
|
+
if (chromeBinaryOrExecutableFilePath) {
|
|
97
|
+
return chromeBinaryOrExecutableFilePath
|
|
155
98
|
}
|
|
156
99
|
}
|
|
100
|
+
throw new Error('chrome binary or executable not found.')
|
|
157
101
|
} catch (error) {
|
|
158
102
|
if (error.code == 'ENOENT') {
|
|
159
103
|
await installChrome.call(this)
|
|
@@ -162,8 +106,6 @@ async function getChromeFilepath() {
|
|
|
162
106
|
}
|
|
163
107
|
throw error
|
|
164
108
|
}
|
|
165
|
-
|
|
166
|
-
throw new Error('unable to find Google Chrome for Testing executable.')
|
|
167
109
|
}
|
|
168
110
|
|
|
169
111
|
/**
|
|
@@ -220,8 +162,9 @@ async function getChromeFilepath() {
|
|
|
220
162
|
* sudo apt-get update && sudo apt-get install -y libcairo2 libpango-1.0-0 libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libatspi2.0-0 libcups2 libdrm-dev libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm-dev libasound2-dev
|
|
221
163
|
* ```
|
|
222
164
|
*/
|
|
223
|
-
class GoogleChromeForTesting {
|
|
165
|
+
class GoogleChromeForTesting extends EventEmitter {
|
|
224
166
|
constructor(options = {}) {
|
|
167
|
+
super()
|
|
225
168
|
this.chromeVersion = options.chromeVersion ?? 'stable'
|
|
226
169
|
this.chromeDir = options.chromeDir ?? 'google-chrome-for-testing'
|
|
227
170
|
this.remoteDebuggingPort = options.remoteDebuggingPort ?? 9222
|
|
@@ -295,8 +238,7 @@ class GoogleChromeForTesting {
|
|
|
295
238
|
})
|
|
296
239
|
|
|
297
240
|
cmd.on('error', error => {
|
|
298
|
-
|
|
299
|
-
process.exit(1)
|
|
241
|
+
this.emit('error', error)
|
|
300
242
|
})
|
|
301
243
|
|
|
302
244
|
cmd.on('exit', code => {
|
package/HTTP.js
CHANGED
|
@@ -141,7 +141,7 @@ class HTTP {
|
|
|
141
141
|
resolve(response)
|
|
142
142
|
})
|
|
143
143
|
|
|
144
|
-
/* TODO remove this
|
|
144
|
+
/* TODO remove this and closeConnections from codebase (breaking)
|
|
145
145
|
request.on('socket', socket => {
|
|
146
146
|
this._sockets.add(socket)
|
|
147
147
|
})
|
package/S3Bucket.js
CHANGED
|
@@ -14,7 +14,9 @@ const AwsAuthorization = require('./internal/AwsAuthorization')
|
|
|
14
14
|
const AmzDate = require('./internal/AmzDate')
|
|
15
15
|
const AwsError = require('./internal/AwsError')
|
|
16
16
|
const parseURL = require('./internal/parseURL')
|
|
17
|
+
const retryHTTPRequest = require('./internal/retryHTTPRequest')
|
|
17
18
|
const createS3DeleteObjectError = require('./internal/createS3DeleteObjectError')
|
|
19
|
+
const createS3DeleteAllObjectsAggregateError = require('./internal/createS3DeleteAllObjectsAggregateError')
|
|
18
20
|
const XML = require('./XML')
|
|
19
21
|
const HTMLEntities = require('html-entities')
|
|
20
22
|
const encodeURIComponentRFC3986 = require('./internal/encodeURIComponentRFC3986')
|
|
@@ -89,9 +91,9 @@ class S3Bucket {
|
|
|
89
91
|
constructor(options) {
|
|
90
92
|
this.name = options.name
|
|
91
93
|
|
|
92
|
-
this.accessKeyId = options.accessKeyId
|
|
93
|
-
this.secretAccessKey = options.secretAccessKey
|
|
94
|
-
this.region = options.region
|
|
94
|
+
this.accessKeyId = options.accessKeyId
|
|
95
|
+
this.secretAccessKey = options.secretAccessKey
|
|
96
|
+
this.region = options.region
|
|
95
97
|
this.apiVersion = '2012-08-10'
|
|
96
98
|
|
|
97
99
|
this.host0 = 's3.amazonaws.com'
|
|
@@ -255,7 +257,7 @@ class S3Bucket {
|
|
|
255
257
|
headers: authorizationHeaders,
|
|
256
258
|
})
|
|
257
259
|
|
|
258
|
-
return this.http0
|
|
260
|
+
return retryHTTPRequest(this.http0, method, url, { headers, body })
|
|
259
261
|
}
|
|
260
262
|
|
|
261
263
|
/**
|
|
@@ -319,7 +321,7 @@ class S3Bucket {
|
|
|
319
321
|
headers: authorizationHeaders,
|
|
320
322
|
})
|
|
321
323
|
|
|
322
|
-
return this.http1
|
|
324
|
+
return retryHTTPRequest(this.http1, method, url, { headers, body })
|
|
323
325
|
}
|
|
324
326
|
|
|
325
327
|
// _putBucketEncryption() -> Promise<>
|
|
@@ -2242,15 +2244,9 @@ class S3Bucket {
|
|
|
2242
2244
|
}
|
|
2243
2245
|
|
|
2244
2246
|
if (response1.Errors.length > 0) {
|
|
2245
|
-
const errors = response1.Errors.map(
|
|
2246
|
-
if (VersionId) {
|
|
2247
|
-
return new Error(`${Key} (VersionId ${VersionId}): ${Code}: ${Message}`)
|
|
2248
|
-
}
|
|
2249
|
-
return new Error(`${Key}: ${Code}: ${Message}`)
|
|
2250
|
-
})
|
|
2247
|
+
const errors = response1.Errors.map(createS3DeleteObjectError)
|
|
2251
2248
|
throw new AggregateError(errors)
|
|
2252
2249
|
}
|
|
2253
|
-
|
|
2254
2250
|
}
|
|
2255
2251
|
|
|
2256
2252
|
let versions = await this.listObjectVersions({ MaxKeys: BatchSize }).then(get('Versions'))
|
|
@@ -2271,7 +2267,6 @@ class S3Bucket {
|
|
|
2271
2267
|
const errors = response1.Errors.map(createS3DeleteObjectError)
|
|
2272
2268
|
throw new AggregateError(errors)
|
|
2273
2269
|
}
|
|
2274
|
-
|
|
2275
2270
|
}
|
|
2276
2271
|
|
|
2277
2272
|
let deleteMarkers = await this.listObjectVersions({ MaxKeys: BatchSize }).then(get('DeleteMarkers'))
|
|
@@ -2292,7 +2287,6 @@ class S3Bucket {
|
|
|
2292
2287
|
const errors = response1.Errors.map(createS3DeleteObjectError)
|
|
2293
2288
|
throw new AggregateError(errors)
|
|
2294
2289
|
}
|
|
2295
|
-
|
|
2296
2290
|
}
|
|
2297
2291
|
|
|
2298
2292
|
return response
|
package/SecretsManager.js
CHANGED
|
@@ -15,6 +15,8 @@ const userAgent = require('./userAgent')
|
|
|
15
15
|
const Readable = require('./Readable')
|
|
16
16
|
const handleAwsResponse = require('./internal/handleAwsResponse')
|
|
17
17
|
const retryableErrorNames = require('./internal/retryableErrorNames')
|
|
18
|
+
const retryHTTPRequest = require('./internal/retryHTTPRequest')
|
|
19
|
+
const sleep = require('./internal/sleep')
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* @name SecretsManager
|
|
@@ -48,9 +50,9 @@ const retryableErrorNames = require('./internal/retryableErrorNames')
|
|
|
48
50
|
*/
|
|
49
51
|
class SecretsManager {
|
|
50
52
|
constructor(options) {
|
|
51
|
-
this.accessKeyId = options.accessKeyId
|
|
52
|
-
this.secretAccessKey = options.secretAccessKey
|
|
53
|
-
this.region = options.region
|
|
53
|
+
this.accessKeyId = options.accessKeyId
|
|
54
|
+
this.secretAccessKey = options.secretAccessKey
|
|
55
|
+
this.region = options.region
|
|
54
56
|
this.apiVersion = '2017-10-17'
|
|
55
57
|
|
|
56
58
|
this.endpoint = `secretsmanager.${this.region}.amazonaws.com`
|
|
@@ -114,7 +116,54 @@ class SecretsManager {
|
|
|
114
116
|
}
|
|
115
117
|
})
|
|
116
118
|
|
|
117
|
-
return this.http
|
|
119
|
+
return retryHTTPRequest(this.http, method, url, { headers, body: payload })
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// _createSecret(name string, secretString string) -> Promise<{
|
|
123
|
+
// ARN: string,
|
|
124
|
+
// Name: string,
|
|
125
|
+
// VersionId: string,
|
|
126
|
+
// }>
|
|
127
|
+
async _createSecret(name, secretString) {
|
|
128
|
+
const payload = JSON.stringify({
|
|
129
|
+
ClientRequestToken: crypto.randomUUID(),
|
|
130
|
+
Name: name,
|
|
131
|
+
SecretString: secretString,
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
const response = await this._awsRequest('POST', '/', 'CreateSecret', payload)
|
|
135
|
+
|
|
136
|
+
if (response.ok) {
|
|
137
|
+
const data = await Readable.JSON(response)
|
|
138
|
+
return data
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
throw new AwsError(await Readable.Text(response), response.status)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// _createSecret(name string, secretString string) -> Promise<{
|
|
145
|
+
// ARN: string,
|
|
146
|
+
// Name: string,
|
|
147
|
+
// VersionId: string,
|
|
148
|
+
// }>
|
|
149
|
+
async _updateSecret(name, secretString) {
|
|
150
|
+
const secret = await this.getSecret(name)
|
|
151
|
+
|
|
152
|
+
const payload = JSON.stringify({
|
|
153
|
+
ClientRequestToken: crypto.randomUUID(),
|
|
154
|
+
SecretId: secret.ARN,
|
|
155
|
+
SecretString: secretString,
|
|
156
|
+
})
|
|
157
|
+
const updateSecretResponse =
|
|
158
|
+
await this._awsRequest('POST', '/', 'UpdateSecret', payload)
|
|
159
|
+
|
|
160
|
+
return handleAwsResponse.call(
|
|
161
|
+
this,
|
|
162
|
+
updateSecretResponse,
|
|
163
|
+
this.putSecret,
|
|
164
|
+
name,
|
|
165
|
+
secretString
|
|
166
|
+
)
|
|
118
167
|
}
|
|
119
168
|
|
|
120
169
|
/**
|
|
@@ -151,50 +200,19 @@ class SecretsManager {
|
|
|
151
200
|
* ```
|
|
152
201
|
*/
|
|
153
202
|
async putSecret(name, secretString) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Name: name,
|
|
157
|
-
SecretString: secretString,
|
|
158
|
-
})
|
|
159
|
-
const createSecretResponse =
|
|
160
|
-
await this._awsRequest('POST', '/', 'CreateSecret', createSecretPayload)
|
|
161
|
-
|
|
162
|
-
if (createSecretResponse.ok) {
|
|
163
|
-
const data = await Readable.JSON(createSecretResponse)
|
|
203
|
+
try {
|
|
204
|
+
const data = await this._createSecret(name, secretString)
|
|
164
205
|
return data
|
|
206
|
+
} catch (error) {
|
|
207
|
+
if (error.name == 'ResourceExistsException') {
|
|
208
|
+
return this._updateSecret(name, secretString)
|
|
209
|
+
} else if (retryableErrorNames.includes(error.name)) {
|
|
210
|
+
await sleep(1000)
|
|
211
|
+
return this.putSecret.call(this, name, secretString)
|
|
212
|
+
} else {
|
|
213
|
+
throw error
|
|
214
|
+
}
|
|
165
215
|
}
|
|
166
|
-
|
|
167
|
-
const createSecretAwsError = new AwsError(
|
|
168
|
-
await Readable.Text(createSecretResponse),
|
|
169
|
-
createSecretResponse.status
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
if (createSecretAwsError.name == 'ResourceExistsException') {
|
|
173
|
-
// continue
|
|
174
|
-
} else if (retryableErrorNames.includes(createSecretAwsError.name)) {
|
|
175
|
-
await sleep(1000)
|
|
176
|
-
return putSecret.call(this, name, secretString)
|
|
177
|
-
} else {
|
|
178
|
-
throw createSecretAwsError
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const secret = await this.getSecret(name)
|
|
182
|
-
|
|
183
|
-
const updateSecretPayload = JSON.stringify({
|
|
184
|
-
ClientRequestToken: crypto.randomUUID(),
|
|
185
|
-
SecretId: secret.ARN,
|
|
186
|
-
SecretString: secretString,
|
|
187
|
-
})
|
|
188
|
-
const updateSecretResponse =
|
|
189
|
-
await this._awsRequest('POST', '/', 'UpdateSecret', updateSecretPayload)
|
|
190
|
-
|
|
191
|
-
return handleAwsResponse.call(
|
|
192
|
-
this,
|
|
193
|
-
updateSecretResponse,
|
|
194
|
-
this.putSecret,
|
|
195
|
-
name,
|
|
196
|
-
secretString
|
|
197
|
-
)
|
|
198
216
|
}
|
|
199
217
|
|
|
200
218
|
/**
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// createS3DeleteAllObjectsAggregateError(Errors Array<{ Key: string, VersionId: string, Code: string, Message: string }>) -> AggregateError
|
|
2
|
+
function createS3DeleteAllObjectsAggregateError(Errors) {
|
|
3
|
+
const errors = Errors.map(({ Key, VersionId, Code, Message }) => {
|
|
4
|
+
if (VersionId) {
|
|
5
|
+
const error = new Error(`${Key}/${VersionId}: ${Message}`)
|
|
6
|
+
error.name = Code
|
|
7
|
+
return error
|
|
8
|
+
}
|
|
9
|
+
const error = new Error(`${Key}: ${Message}`)
|
|
10
|
+
error.name = Code
|
|
11
|
+
return error
|
|
12
|
+
})
|
|
13
|
+
return new AggregateError(errors)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = createS3DeleteAllObjectsAggregateError
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const createS3DeleteAllObjectsAggregateError = require('./createS3DeleteAllObjectsAggregateError')
|
|
3
|
+
|
|
4
|
+
const test = new Test('createS3DeleteAllObjectsAggregateError', createS3DeleteAllObjectsAggregateError)
|
|
5
|
+
|
|
6
|
+
function createError(name, message) {
|
|
7
|
+
const error = new Error(message)
|
|
8
|
+
error.name = name
|
|
9
|
+
return error
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
test.case([
|
|
13
|
+
{
|
|
14
|
+
Key: 'testkey1',
|
|
15
|
+
Code: 'AccessDenied',
|
|
16
|
+
Message: 'Access Denied',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
Key: 'testkey1',
|
|
20
|
+
Code: 'AllAccessDisabled',
|
|
21
|
+
Message: 'All access to this Amazon S3 resource has been disabled. Contact AWS Support for further assistance.',
|
|
22
|
+
},
|
|
23
|
+
], new AggregateError([
|
|
24
|
+
createError('AccessDenied', 'testkey1: Access Denied'),
|
|
25
|
+
createError('AllAccessDisabled', 'testkey1: All access to this Amazon S3 resource has been disabled. Contact AWS Support for further assistance.'),
|
|
26
|
+
]))
|
|
27
|
+
|
|
28
|
+
test.case([
|
|
29
|
+
{
|
|
30
|
+
Key: 'testkey1',
|
|
31
|
+
VersionId: '1',
|
|
32
|
+
Code: 'AccessDenied',
|
|
33
|
+
Message: 'Access Denied',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
Key: 'testkey1',
|
|
37
|
+
VersionId: '1',
|
|
38
|
+
Code: 'AllAccessDisabled',
|
|
39
|
+
Message: 'All access to this Amazon S3 resource has been disabled. Contact AWS Support for further assistance.',
|
|
40
|
+
},
|
|
41
|
+
], new AggregateError([
|
|
42
|
+
createError('AccessDenied', 'testkey1/1: Access Denied'),
|
|
43
|
+
createError('AllAccessDisabled', 'testkey1/1: All access to this Amazon S3 resource has been disabled. Contact AWS Support for further assistance.'),
|
|
44
|
+
]))
|
|
45
|
+
|
|
46
|
+
if (process.argv[1] == __filename) {
|
|
47
|
+
test()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = test
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
// getAbsoluteFilePath(filepath string, platform string) -> absoluteFilePath string
|
|
4
|
+
function getAbsoluteFilePath(filepath, platform) {
|
|
5
|
+
if (platform.startsWith('win')) {
|
|
6
|
+
if (/^[A-Z]:/.test(filepath)) {
|
|
7
|
+
filepath = filepath.replace(/\//g, '\\')
|
|
8
|
+
} else {
|
|
9
|
+
filepath = path.join(process.cwd(), filepath).replace(/\//g, '\\')
|
|
10
|
+
}
|
|
11
|
+
} else if (!filepath.startsWith('/')) {
|
|
12
|
+
filepath = path.join(process.cwd(), filepath)
|
|
13
|
+
}
|
|
14
|
+
return filepath
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = getAbsoluteFilePath
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
const getAbsoluteFilePath = require('./getAbsoluteFilePath')
|
|
4
|
+
|
|
5
|
+
const test = new Test('getAbsoluteFilePath', getAbsoluteFilePath)
|
|
6
|
+
|
|
7
|
+
const cwd = process.cwd()
|
|
8
|
+
|
|
9
|
+
test.case('/test', 'linux64', '/test')
|
|
10
|
+
test.case('test', 'linux64', `${cwd}/test`)
|
|
11
|
+
test.case('/test', 'win64', `${cwd.replace(/\//g, '\\')}\\test`)
|
|
12
|
+
test.case('C:\\test', 'win64', 'C:\\test')
|
|
13
|
+
test.case('D:\\test', 'win64', 'D:\\test')
|
|
14
|
+
|
|
15
|
+
if (process.argv[1] == __filename) {
|
|
16
|
+
test()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = test
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// getChromeBinaryOrExecutableFilePath(filepath string, platform string) -> string
|
|
2
|
+
function getChromeBinaryOrExecutableFilePath(filepath, platform) {
|
|
3
|
+
if (platform.startsWith('mac') && filepath.endsWith('Google Chrome for Testing')) {
|
|
4
|
+
return filepath
|
|
5
|
+
}
|
|
6
|
+
if (platform.startsWith('linux') && filepath.endsWith('chrome')) {
|
|
7
|
+
return filepath
|
|
8
|
+
}
|
|
9
|
+
if (platform.startsWith('win') && filepath.endsWith('chrome.exe')) {
|
|
10
|
+
return filepath
|
|
11
|
+
}
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = getChromeBinaryOrExecutableFilePath
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const getChromeBinaryOrExecutableFilePath = require('./getChromeBinaryOrExecutableFilePath.js')
|
|
3
|
+
|
|
4
|
+
const test = new Test('getChromeBinaryOrExecutableFilePath', getChromeBinaryOrExecutableFilePath)
|
|
5
|
+
|
|
6
|
+
test.case('/path/to/Google Chrome for Testing', 'mac-x64', '/path/to/Google Chrome for Testing')
|
|
7
|
+
test.case('/path/to/other', 'mac-x64', undefined)
|
|
8
|
+
test.case('/path/to/chrome', 'linux64', '/path/to/chrome')
|
|
9
|
+
test.case('/path/to/other', 'linux64', undefined)
|
|
10
|
+
test.case('C:\\path\\to\\chrome.exe', 'win64', 'C:\\path\\to\\chrome.exe')
|
|
11
|
+
test.case('C:\\path\\to\\other.exe', 'win64', undefined)
|
|
12
|
+
|
|
13
|
+
if (process.argv[1] == __filename) {
|
|
14
|
+
test()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = test
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const getChromeVersions = require('./getChromeVersions')
|
|
2
|
+
|
|
3
|
+
// getChromeUrl(platform string) -> chromeUrl string
|
|
4
|
+
async function getChromeUrl(platform) {
|
|
5
|
+
|
|
6
|
+
let url
|
|
7
|
+
if (['stable', 'beta', 'dev', 'canary'].includes(this.chromeVersion)) {
|
|
8
|
+
const chromeVersions = await getChromeVersions()
|
|
9
|
+
const channel = `${this.chromeVersion[0].toUpperCase()}${this.chromeVersion.slice(1)}`
|
|
10
|
+
const chromeVersionNumber = chromeVersions.channels[channel].version
|
|
11
|
+
url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
12
|
+
} else {
|
|
13
|
+
const chromeVersionNumber = this.chromeVersion
|
|
14
|
+
url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return url
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = getChromeUrl
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
const getChromeUrl = require('./getChromeUrl')
|
|
4
|
+
const getChromeVersions = require('./getChromeVersions')
|
|
5
|
+
|
|
6
|
+
const test = new Test('getChromeUrl', async function integration() {
|
|
7
|
+
const chromeVersions = await getChromeVersions()
|
|
8
|
+
|
|
9
|
+
const chromeVersionNumber = chromeVersions.channels.Stable.version
|
|
10
|
+
const platform = 'linux64'
|
|
11
|
+
const url = `https://storage.googleapis.com/chrome-for-testing-public/${chromeVersionNumber}/${platform}/chrome-${platform}.zip`
|
|
12
|
+
|
|
13
|
+
assert.equal(await getChromeUrl.call({ chromeVersion: 'stable' }, 'linux64'), url)
|
|
14
|
+
assert.equal(await getChromeUrl.call({ chromeVersion: chromeVersionNumber }, 'linux64'), url)
|
|
15
|
+
|
|
16
|
+
}).case()
|
|
17
|
+
|
|
18
|
+
if (process.argv[1] == __filename) {
|
|
19
|
+
test()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = test
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const HTTP = require('../HTTP')
|
|
2
|
+
const Readable = require('../Readable')
|
|
3
|
+
|
|
4
|
+
// getChromeVersions() -> Promise<{
|
|
5
|
+
// channels: {
|
|
6
|
+
// Stable: { version: string },
|
|
7
|
+
// Beta: { version: string },
|
|
8
|
+
// Dev: { version: string },
|
|
9
|
+
// Canary: { version: string },
|
|
10
|
+
// },
|
|
11
|
+
// }>
|
|
12
|
+
async function getChromeVersions() {
|
|
13
|
+
const http = new HTTP()
|
|
14
|
+
const response = await http.GET('https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json')
|
|
15
|
+
const data = await Readable.JSON(response)
|
|
16
|
+
return data
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = getChromeVersions
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const os = require('os')
|
|
2
|
+
|
|
3
|
+
// getPlatform() -> platform string
|
|
4
|
+
function getPlatform() {
|
|
5
|
+
let platform = os.platform()
|
|
6
|
+
if (platform == 'darwin') {
|
|
7
|
+
platform = 'mac'
|
|
8
|
+
}
|
|
9
|
+
const arch = os.arch()
|
|
10
|
+
|
|
11
|
+
if (platform == 'mac') {
|
|
12
|
+
platform = `${platform}-${arch}`
|
|
13
|
+
} else if (platform == 'win32') {
|
|
14
|
+
platform = `win${arch.slice(1)}`
|
|
15
|
+
} else {
|
|
16
|
+
platform = `${platform}${arch.slice(1)}`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return platform
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = getPlatform
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
const getPlatform = require('./getPlatform')
|
|
4
|
+
|
|
5
|
+
const test = new Test('getPlatform', async function integration() {
|
|
6
|
+
const os = require('os')
|
|
7
|
+
|
|
8
|
+
const osPlatform = os.platform
|
|
9
|
+
const osArch = os.arch
|
|
10
|
+
|
|
11
|
+
os.platform = () => 'darwin'
|
|
12
|
+
os.arch = () => 'x64'
|
|
13
|
+
|
|
14
|
+
assert.equal(getPlatform(), 'mac-x64')
|
|
15
|
+
|
|
16
|
+
os.platform = () => 'win32'
|
|
17
|
+
|
|
18
|
+
assert.equal(getPlatform(), 'win64')
|
|
19
|
+
|
|
20
|
+
os.platform = () => 'linux'
|
|
21
|
+
|
|
22
|
+
assert.equal(getPlatform(), 'linux64')
|
|
23
|
+
|
|
24
|
+
os.platform = osPlatform
|
|
25
|
+
os.arch = osArch
|
|
26
|
+
|
|
27
|
+
}).case()
|
|
28
|
+
|
|
29
|
+
if (process.argv[1] == __filename) {
|
|
30
|
+
test()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = test
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const sleep = require('./sleep')
|
|
2
|
+
|
|
3
|
+
// retryHTTPRequest(http HTTP, method string, url string, options {
|
|
4
|
+
// headers: Object<string>,
|
|
5
|
+
// body: string,
|
|
6
|
+
// }) -> http.ServerResponse
|
|
7
|
+
async function retryHTTPRequest(http, method, url, options) {
|
|
8
|
+
try {
|
|
9
|
+
const response = await http[method](url, options)
|
|
10
|
+
return response
|
|
11
|
+
} catch {
|
|
12
|
+
await sleep(1000)
|
|
13
|
+
return retryHTTPRequest(http, method, url, options)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = retryHTTPRequest
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
const retryHTTPRequest = require('./retryHTTPRequest')
|
|
4
|
+
|
|
5
|
+
const test = new Test('retryHTTPRequest', async function integration() {
|
|
6
|
+
const http1 = {
|
|
7
|
+
async GET(url, options) {
|
|
8
|
+
return 'ok'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
{
|
|
13
|
+
const response = await retryHTTPRequest(http1, 'GET', '/test', {})
|
|
14
|
+
assert.equal(response, 'ok')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let retries = 0
|
|
18
|
+
const http2 = {
|
|
19
|
+
async GET(url, options) {
|
|
20
|
+
if (retries === 0) {
|
|
21
|
+
retries += 1
|
|
22
|
+
throw new Error('test')
|
|
23
|
+
}
|
|
24
|
+
return 'ok'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
const response = await retryHTTPRequest(http2, 'GET', '/test', {})
|
|
30
|
+
assert.equal(response, 'ok')
|
|
31
|
+
assert.strictEqual(retries, 1)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}).case()
|
|
35
|
+
|
|
36
|
+
if (process.argv[1] == __filename) {
|
|
37
|
+
test()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = test
|