29
29
* Modifications Copyright OpenSearch Contributors. See
30
30
* GitHub history for details.
31
31
*/
32
-
33
32
const fetch = require ( 'node-fetch' ) ;
34
33
const AbortController = require ( 'abort-controller' ) ;
35
34
const fs = require ( 'fs' ) ;
@@ -40,8 +39,11 @@ const { createHash } = require('crypto');
40
39
const path = require ( 'path' ) ;
41
40
42
41
const asyncPipeline = promisify ( pipeline ) ;
43
- const DAILY_SNAPSHOTS_BASE_URL = '' ;
42
+ const DAILY_SNAPSHOTS_BASE_URL = 'https://artifacts.opensearch.org/snapshots/core/opensearch' ;
43
+ // TODO: [RENAMEME] currently do not have an existing replacement
44
44
const PERMANENT_SNAPSHOTS_BASE_URL = '' ;
45
+ // Since we do not have a manifest URL, limiting how many RC checks to 5 should be more than enough
46
+ const MAX_RC_CHECK = 5 ;
45
47
46
48
const { cache } = require ( './utils' ) ;
47
49
const { resolveCustomSnapshotUrl } = require ( './custom_snapshots' ) ;
@@ -96,6 +98,22 @@ async function fetchSnapshotManifest(url, log) {
96
98
return { abc, resp, json } ;
97
99
}
98
100
101
+ async function verifySnapshotUrl ( url , log ) {
102
+ log . info ( 'Verifying snapshot URL at %s' , chalk . bold ( url ) ) ;
103
+
104
+ const abc = new AbortController ( ) ;
105
+ const resp = await retry (
106
+ log ,
107
+ async ( ) => await fetch ( url , { signal : abc . signal } , { method : 'HEAD' } )
108
+ ) ;
109
+
110
+ return { abc, resp } ;
111
+ }
112
+
113
+ /**
114
+ * @deprecated This method should not be used, uses logic for resources we do not have access to.
115
+ */
116
+ // eslint-disable-next-line no-unused-vars
99
117
async function getArtifactSpecForSnapshot ( urlVersion , license , log ) {
100
118
const desiredVersion = urlVersion . replace ( '-SNAPSHOT' , '' ) ;
101
119
const desiredLicense = license === 'oss' ? 'oss' : 'default' ;
@@ -153,6 +171,76 @@ async function getArtifactSpecForSnapshot(urlVersion, license, log) {
153
171
} ;
154
172
}
155
173
174
+ async function getArtifactSpecForSnapshotFromUrl ( urlVersion , log ) {
175
+ const desiredVersion = urlVersion . replace ( '-SNAPSHOT' , '' ) ;
176
+
177
+ // [RENAMEME] Need replacement for other platforms.
178
+ const platform = process . platform === 'win32' ? 'windows' : process . platform ;
179
+ const arch = process . arch === 'arm64' ? 'arm64' : 'x64' ;
180
+ if ( platform !== 'linux' || arch !== 'x64' ) {
181
+ throw createCliError ( `Snapshots are only available for Linux x64` ) ;
182
+ }
183
+
184
+ if ( process . env . OPENSEARCH_SNAPSHOT_MANIFEST ) {
185
+ log . warning ( 'Custom manifest URLs are currently not supported.' ) ;
186
+ }
187
+
188
+ const latestUrl = `${ DAILY_SNAPSHOTS_BASE_URL } /${ desiredVersion } /` ;
189
+ const latestFile = `opensearch-${ desiredVersion } -SNAPSHOT-${ platform } -${ arch } -latest.tar.gz` ;
190
+ const completeLatestUrl = latestUrl + latestFile ;
191
+
192
+ let { abc, resp } = await verifySnapshotUrl ( completeLatestUrl , log ) ;
193
+
194
+ if ( resp . ok ) {
195
+ return {
196
+ url : completeLatestUrl ,
197
+ checksumUrl : completeLatestUrl + '.sha512' ,
198
+ checksumType : 'sha512' ,
199
+ filename : latestFile ,
200
+ } ;
201
+ }
202
+
203
+ log . info (
204
+ 'Daily general-availability snapshot URL not found for current version, falling back to release-candidate snapshot URL.'
205
+ ) ;
206
+
207
+ let completeUrl = null ;
208
+ let snapshotFile = null ;
209
+
210
+ // This checks and uses an RC if a RC exists at a higher increment than RC1 or it tries to use RC1
211
+ // This is in replacement of having a manifest URL, so the exact RC number is unknown but expect it not to be a large number
212
+ let rcCheck = MAX_RC_CHECK ;
213
+ do {
214
+ const secondaryLatestUrl = `${ DAILY_SNAPSHOTS_BASE_URL } /${ desiredVersion } -rc${ rcCheck } /` ;
215
+ const secondaryLatestFile = `opensearch-${ desiredVersion } -rc${ rcCheck } -SNAPSHOT-${ platform } -${ arch } -latest.tar.gz` ;
216
+ const completeSecondaryLatestUrl = secondaryLatestUrl + secondaryLatestFile ;
217
+ ( { abc, resp } = await verifySnapshotUrl ( completeSecondaryLatestUrl , log ) ) ;
218
+
219
+ if ( resp . ok ) {
220
+ completeUrl = completeSecondaryLatestUrl ;
221
+ snapshotFile = secondaryLatestFile ;
222
+ break ;
223
+ }
224
+ } while ( rcCheck -- >= 1 ) ;
225
+
226
+ if ( resp . status === 404 || ! completeUrl || ! snapshotFile ) {
227
+ abc . abort ( ) ;
228
+ throw createCliError ( `Snapshots for ${ desiredVersion } are not available` ) ;
229
+ }
230
+
231
+ if ( ! resp . ok ) {
232
+ abc . abort ( ) ;
233
+ throw new Error ( `Unable to read snapshot url: ${ resp . statusText } ` ) ;
234
+ }
235
+
236
+ return {
237
+ url : completeUrl ,
238
+ checksumUrl : completeUrl + '.sha512' ,
239
+ checksumType : 'sha512' ,
240
+ filename : snapshotFile ,
241
+ } ;
242
+ }
243
+
156
244
exports . Artifact = class Artifact {
157
245
/**
158
246
* Fetch an Artifact from the Artifact API for a license level and version
@@ -168,7 +256,7 @@ exports.Artifact = class Artifact {
168
256
return new Artifact ( customSnapshotArtifactSpec , log ) ;
169
257
}
170
258
171
- const artifactSpec = await getArtifactSpecForSnapshot ( urlVersion , license , log ) ;
259
+ const artifactSpec = await getArtifactSpecForSnapshotFromUrl ( urlVersion , log ) ;
172
260
return new Artifact ( artifactSpec , log ) ;
173
261
}
174
262
0 commit comments