@reventlessdev/reventless-seed-aws 1.0.0-alpha.4 → 1.0.0-alpha.40
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/CHANGELOG.md +279 -0
- package/lib/bs/.compiler.log +2 -2
- package/lib/bs/.sourcedirs.json +1 -0
- package/lib/bs/compiler-info.json +4 -4
- package/lib/bs/src/ReventlessSeedAws.ast +0 -0
- package/lib/bs/src/ReventlessSeedAws.cmi +0 -0
- package/lib/bs/src/ReventlessSeedAws.cmj +0 -0
- package/lib/bs/src/ReventlessSeedAws.cmt +0 -0
- package/lib/bs/src/ReventlessSeedAws.res +198 -134
- package/lib/bs/src/ReventlessSeedAws.res.mjs +59 -33
- package/lib/bs/src/ReventlessSeedAws_Quiesce.ast +0 -0
- package/lib/bs/src/ReventlessSeedAws_Quiesce.cmi +0 -0
- package/lib/bs/src/ReventlessSeedAws_Quiesce.cmj +0 -0
- package/lib/bs/src/ReventlessSeedAws_Quiesce.cmt +0 -0
- package/lib/bs/src/ReventlessSeedAws_Quiesce.res +307 -0
- package/lib/bs/src/ReventlessSeedAws_Quiesce.res.mjs +217 -0
- package/lib/bs/src/ReventlessSeedAws_Reconcile.ast +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reconcile.cmi +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reconcile.cmj +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reconcile.cmt +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reconcile.res +391 -0
- package/lib/bs/src/ReventlessSeedAws_Reconcile.res.mjs +318 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.ast +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.cmi +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.cmj +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.cmt +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.res +497 -94
- package/lib/bs/src/ReventlessSeedAws_Reset.res.mjs +385 -69
- package/lib/bs/tests/EndpointResolutionTest.ast +0 -0
- package/lib/bs/tests/EndpointResolutionTest.cmi +0 -0
- package/lib/bs/tests/EndpointResolutionTest.cmj +0 -0
- package/lib/bs/tests/EndpointResolutionTest.cmt +0 -0
- package/lib/bs/tests/EndpointResolutionTest.res +83 -0
- package/lib/bs/tests/EndpointResolutionTest.res.mjs +115 -0
- package/lib/bs/tests/ObjectStoreReconcileTest.ast +0 -0
- package/lib/bs/tests/ObjectStoreReconcileTest.cmi +0 -0
- package/lib/bs/tests/ObjectStoreReconcileTest.cmj +0 -0
- package/lib/bs/tests/ObjectStoreReconcileTest.cmt +0 -0
- package/lib/bs/tests/ObjectStoreReconcileTest.res +83 -0
- package/lib/bs/tests/ObjectStoreReconcileTest.res.mjs +102 -0
- package/lib/bs/tests/ObjectStoreResetTest.ast +0 -0
- package/lib/bs/tests/ObjectStoreResetTest.cmi +0 -0
- package/lib/bs/tests/ObjectStoreResetTest.cmj +0 -0
- package/lib/bs/tests/ObjectStoreResetTest.cmt +0 -0
- package/lib/bs/tests/ObjectStoreResetTest.res +191 -0
- package/lib/bs/tests/ObjectStoreResetTest.res.mjs +211 -0
- package/lib/bs/tests/QuiesceResetTest.ast +0 -0
- package/lib/bs/tests/QuiesceResetTest.cmi +0 -0
- package/lib/bs/tests/QuiesceResetTest.cmj +0 -0
- package/lib/bs/tests/QuiesceResetTest.cmt +0 -0
- package/lib/bs/tests/QuiesceResetTest.res +169 -0
- package/lib/bs/tests/QuiesceResetTest.res.mjs +157 -0
- package/lib/ocaml/.compiler.log +2 -2
- package/lib/ocaml/EndpointResolutionTest.ast +0 -0
- package/lib/ocaml/EndpointResolutionTest.cmi +0 -0
- package/lib/ocaml/EndpointResolutionTest.cmj +0 -0
- package/lib/ocaml/EndpointResolutionTest.cmt +0 -0
- package/lib/ocaml/EndpointResolutionTest.res +83 -0
- package/lib/ocaml/ObjectStoreReconcileTest.ast +0 -0
- package/lib/ocaml/ObjectStoreReconcileTest.cmi +0 -0
- package/lib/ocaml/ObjectStoreReconcileTest.cmj +0 -0
- package/lib/ocaml/ObjectStoreReconcileTest.cmt +0 -0
- package/lib/ocaml/ObjectStoreReconcileTest.res +83 -0
- package/lib/ocaml/ObjectStoreResetTest.ast +0 -0
- package/lib/ocaml/ObjectStoreResetTest.cmi +0 -0
- package/lib/ocaml/ObjectStoreResetTest.cmj +0 -0
- package/lib/ocaml/ObjectStoreResetTest.cmt +0 -0
- package/lib/ocaml/ObjectStoreResetTest.res +191 -0
- package/lib/ocaml/QuiesceResetTest.ast +0 -0
- package/lib/ocaml/QuiesceResetTest.cmi +0 -0
- package/lib/ocaml/QuiesceResetTest.cmj +0 -0
- package/lib/ocaml/QuiesceResetTest.cmt +0 -0
- package/lib/ocaml/QuiesceResetTest.res +169 -0
- package/lib/ocaml/ReventlessSeedAws.ast +0 -0
- package/lib/ocaml/ReventlessSeedAws.cmi +0 -0
- package/lib/ocaml/ReventlessSeedAws.cmj +0 -0
- package/lib/ocaml/ReventlessSeedAws.cmt +0 -0
- package/lib/ocaml/ReventlessSeedAws.res +198 -134
- package/lib/ocaml/ReventlessSeedAws_Quiesce.ast +0 -0
- package/lib/ocaml/ReventlessSeedAws_Quiesce.cmi +0 -0
- package/lib/ocaml/ReventlessSeedAws_Quiesce.cmj +0 -0
- package/lib/ocaml/ReventlessSeedAws_Quiesce.cmt +0 -0
- package/lib/ocaml/ReventlessSeedAws_Quiesce.res +307 -0
- package/lib/ocaml/ReventlessSeedAws_Reconcile.ast +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reconcile.cmi +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reconcile.cmj +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reconcile.cmt +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reconcile.res +391 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.ast +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.cmi +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.cmj +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.cmt +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.res +497 -94
- package/package.json +7 -5
- package/rescript.json +8 -1
- package/src/ReventlessSeedAws.res +198 -134
- package/src/ReventlessSeedAws.res.mjs +59 -33
- package/src/ReventlessSeedAws_Quiesce.res +307 -0
- package/src/ReventlessSeedAws_Quiesce.res.mjs +217 -0
- package/src/ReventlessSeedAws_Reconcile.res +391 -0
- package/src/ReventlessSeedAws_Reconcile.res.mjs +318 -0
- package/src/ReventlessSeedAws_Reset.res +497 -94
- package/src/ReventlessSeedAws_Reset.res.mjs +385 -69
- package/tests/EndpointResolutionTest.res +83 -0
- package/tests/EndpointResolutionTest.res.mjs +115 -0
- package/tests/ObjectStoreReconcileTest.res +83 -0
- package/tests/ObjectStoreReconcileTest.res.mjs +102 -0
- package/tests/ObjectStoreResetTest.res +191 -0
- package/tests/ObjectStoreResetTest.res.mjs +211 -0
- package/tests/QuiesceResetTest.res +169 -0
- package/tests/QuiesceResetTest.res.mjs +157 -0
|
@@ -4,7 +4,9 @@ import * as Nodefs from "node:fs";
|
|
|
4
4
|
import * as S3$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/S3.res.mjs";
|
|
5
5
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
6
6
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
7
|
+
import * as Lambda$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/Lambda.res.mjs";
|
|
7
8
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
9
|
+
import * as Stdlib_String from "@rescript/runtime/lib/es6/Stdlib_String.js";
|
|
8
10
|
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
9
11
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
10
12
|
import * as ReventlessSeedAws from "./ReventlessSeedAws.res.mjs";
|
|
@@ -14,6 +16,7 @@ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_excep
|
|
|
14
16
|
import * as LibDynamodb from "@aws-sdk/lib-dynamodb";
|
|
15
17
|
import * as ClientDynamodb from "@aws-sdk/client-dynamodb";
|
|
16
18
|
import * as DynamoDb_DynamoDb$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/DynamoDb_DynamoDb.res.mjs";
|
|
19
|
+
import * as ReventlessSeedAws_Quiesce from "./ReventlessSeedAws_Quiesce.res.mjs";
|
|
17
20
|
import * as Seed_Prompt$ReventlessSeed from "@reventlessdev/reventless-seed/src/Seed_Prompt.res.mjs";
|
|
18
21
|
import * as Seed_Runner$ReventlessSeed from "@reventlessdev/reventless-seed/src/Seed_Runner.res.mjs";
|
|
19
22
|
import * as DynamoDb_DocumentClient$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/DynamoDb_DocumentClient.res.mjs";
|
|
@@ -109,25 +112,52 @@ function configValue(cfg, key) {
|
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
function classify(arn) {
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
TAG: "Bucket",
|
|
116
|
-
_0: arn.slice("arn:aws:s3:::".length, arn.length)
|
|
117
|
-
};
|
|
118
|
-
} else {
|
|
115
|
+
if (arn.startsWith("arn:aws:dynamodb:")) {
|
|
116
|
+
let match = arn.split(":table/");
|
|
117
|
+
if (match.length !== 2) {
|
|
119
118
|
return "Other";
|
|
120
119
|
}
|
|
120
|
+
let name = match[1];
|
|
121
|
+
return {
|
|
122
|
+
TAG: "Table",
|
|
123
|
+
_0: name
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (arn.startsWith("arn:aws:s3:::")) {
|
|
127
|
+
return {
|
|
128
|
+
TAG: "Bucket",
|
|
129
|
+
_0: arn.slice("arn:aws:s3:::".length, arn.length)
|
|
130
|
+
};
|
|
121
131
|
}
|
|
122
|
-
|
|
123
|
-
if (match.length !== 2) {
|
|
132
|
+
if (!arn.startsWith("arn:aws:lambda:")) {
|
|
124
133
|
return "Other";
|
|
125
134
|
}
|
|
126
|
-
let
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
let match$1 = arn.split(":function:");
|
|
136
|
+
if (match$1.length !== 2) {
|
|
137
|
+
return "Other";
|
|
138
|
+
}
|
|
139
|
+
let rest = match$1[1];
|
|
140
|
+
let match$2 = rest.split(":");
|
|
141
|
+
let len = match$2.length;
|
|
142
|
+
if (len >= 3) {
|
|
143
|
+
return "Other";
|
|
144
|
+
}
|
|
145
|
+
switch (len) {
|
|
146
|
+
case 0 :
|
|
147
|
+
return "Other";
|
|
148
|
+
case 1 :
|
|
149
|
+
let name$1 = match$2[0];
|
|
150
|
+
return {
|
|
151
|
+
TAG: "Function",
|
|
152
|
+
_0: name$1
|
|
153
|
+
};
|
|
154
|
+
case 2 :
|
|
155
|
+
let name$2 = match$2[0];
|
|
156
|
+
return {
|
|
157
|
+
TAG: "Function",
|
|
158
|
+
_0: name$2
|
|
159
|
+
};
|
|
160
|
+
}
|
|
131
161
|
}
|
|
132
162
|
|
|
133
163
|
function tagValue(tags, key) {
|
|
@@ -142,6 +172,7 @@ async function discover(region, stack, platform) {
|
|
|
142
172
|
let client = ResourceGroupsTaggingApi$AwsSdk.client(region, undefined);
|
|
143
173
|
let tables = [];
|
|
144
174
|
let buckets = [];
|
|
175
|
+
let functions = [];
|
|
145
176
|
let loop = async token => {
|
|
146
177
|
let out = await client.send(new ClientResourceGroupsTaggingApi.GetResourcesCommand({
|
|
147
178
|
TagFilters: [
|
|
@@ -156,7 +187,8 @@ async function discover(region, stack, platform) {
|
|
|
156
187
|
],
|
|
157
188
|
ResourceTypeFilters: [
|
|
158
189
|
"dynamodb:table",
|
|
159
|
-
"s3"
|
|
190
|
+
"s3",
|
|
191
|
+
"lambda:function"
|
|
160
192
|
],
|
|
161
193
|
ResourcesPerPage: 100,
|
|
162
194
|
PaginationToken: token
|
|
@@ -180,11 +212,17 @@ async function discover(region, stack, platform) {
|
|
|
180
212
|
if (typeof name !== "object") {
|
|
181
213
|
return;
|
|
182
214
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
215
|
+
switch (name.TAG) {
|
|
216
|
+
case "Table" :
|
|
217
|
+
tables.push(name._0);
|
|
218
|
+
return;
|
|
219
|
+
case "Bucket" :
|
|
220
|
+
buckets.push(name._0);
|
|
221
|
+
return;
|
|
222
|
+
case "Function" :
|
|
223
|
+
functions.push(name._0);
|
|
224
|
+
return;
|
|
186
225
|
}
|
|
187
|
-
buckets.push(name._0);
|
|
188
226
|
});
|
|
189
227
|
let t = out.PaginationToken;
|
|
190
228
|
if (t !== undefined && t !== "") {
|
|
@@ -192,10 +230,102 @@ async function discover(region, stack, platform) {
|
|
|
192
230
|
}
|
|
193
231
|
};
|
|
194
232
|
await loop(undefined);
|
|
195
|
-
return
|
|
196
|
-
tables,
|
|
197
|
-
buckets
|
|
198
|
-
|
|
233
|
+
return {
|
|
234
|
+
tables: tables,
|
|
235
|
+
buckets: buckets,
|
|
236
|
+
functions: functions
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function splitQualified(key) {
|
|
241
|
+
return Stdlib_Option.map(Stdlib_String.indexOfOpt(key, "."), i => [
|
|
242
|
+
key.slice(0, i),
|
|
243
|
+
key.slice(i + 1 | 0, key.length)
|
|
244
|
+
]);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function parseObjectStores(json) {
|
|
248
|
+
if (json !== undefined) {
|
|
249
|
+
if (typeof json === "object" && json !== null && !Array.isArray(json)) {
|
|
250
|
+
return Stdlib_Array.reduce(Object.entries(json), {
|
|
251
|
+
TAG: "Ok",
|
|
252
|
+
_0: []
|
|
253
|
+
}, (acc, param) => {
|
|
254
|
+
let entry = param[1];
|
|
255
|
+
let qualified = param[0];
|
|
256
|
+
if (acc.TAG !== "Ok") {
|
|
257
|
+
return acc;
|
|
258
|
+
}
|
|
259
|
+
let match = splitQualified(qualified);
|
|
260
|
+
let match$1 = Stdlib_Option.flatMap(field(entry, "bucketName"), asString);
|
|
261
|
+
let match$2 = Stdlib_Option.flatMap(field(entry, "keyPrefix"), asString);
|
|
262
|
+
if (match !== undefined && match$1 !== undefined && match$2 !== undefined) {
|
|
263
|
+
return {
|
|
264
|
+
TAG: "Ok",
|
|
265
|
+
_0: acc._0.concat([{
|
|
266
|
+
qualified: qualified,
|
|
267
|
+
plugin: match[0],
|
|
268
|
+
store: match[1],
|
|
269
|
+
bucketName: match$1,
|
|
270
|
+
keyPrefix: match$2
|
|
271
|
+
}])
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
TAG: "Error",
|
|
276
|
+
_0: `the platform stack's \`objectStores\` output has a malformed entry for "` + qualified + `" — expected a {plugin}.{store} key carrying bucketName and keyPrefix.`
|
|
277
|
+
};
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
return {
|
|
281
|
+
TAG: "Error",
|
|
282
|
+
_0: "the platform stack's `objectStores` output is not an object."
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
return {
|
|
287
|
+
TAG: "Ok",
|
|
288
|
+
_0: []
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function validateStores(stores) {
|
|
294
|
+
let s = stores.find(s => {
|
|
295
|
+
if (s.keyPrefix === "") {
|
|
296
|
+
return true;
|
|
297
|
+
} else {
|
|
298
|
+
return s.store.includes("/");
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
if (s !== undefined) {
|
|
302
|
+
return {
|
|
303
|
+
TAG: "Error",
|
|
304
|
+
_0: `store "` + s.qualified + `" has an unusable key prefix ("` + s.keyPrefix + `") — a store name may not be empty or contain "/".`
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
let message = Stdlib_Array.findMap(stores, a => Stdlib_Array.findMap(stores, b => {
|
|
308
|
+
if (a.qualified === b.qualified || a.bucketName !== b.bucketName) {
|
|
309
|
+
return;
|
|
310
|
+
} else if (a.keyPrefix === b.keyPrefix) {
|
|
311
|
+
return `stores "` + a.qualified + `" and "` + b.qualified + `" both live at ` + (a.bucketName + `/` + a.keyPrefix + `/ — a prefix-scoped wipe cannot tell their objects `) + `apart. Rename one store, or qualify the \`@storageRef\` annotation if they were meant to be one shared store.`;
|
|
312
|
+
} else if (b.keyPrefix.startsWith(a.keyPrefix + "/")) {
|
|
313
|
+
return `store "` + a.qualified + `" (` + a.bucketName + `/` + a.keyPrefix + `/) encloses "` + b.qualified + `" ` + (`(` + b.keyPrefix + `/) — wiping the first would delete the second's objects. Rename one.`);
|
|
314
|
+
} else {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
}));
|
|
318
|
+
if (message !== undefined) {
|
|
319
|
+
return {
|
|
320
|
+
TAG: "Error",
|
|
321
|
+
_0: message
|
|
322
|
+
};
|
|
323
|
+
} else {
|
|
324
|
+
return {
|
|
325
|
+
TAG: "Ok",
|
|
326
|
+
_0: undefined
|
|
327
|
+
};
|
|
328
|
+
}
|
|
199
329
|
}
|
|
200
330
|
|
|
201
331
|
async function countTable(table) {
|
|
@@ -216,10 +346,11 @@ async function countTable(table) {
|
|
|
216
346
|
return await loop(undefined, 0);
|
|
217
347
|
}
|
|
218
348
|
|
|
219
|
-
async function countBucket(bucket) {
|
|
349
|
+
async function countBucket(bucket, prefix) {
|
|
220
350
|
let loop = async (keyMarker, versionMarker, acc) => {
|
|
221
351
|
let out = await S3$AwsSdk.ListObjectVersionsCommand.send(new ClientS3.ListObjectVersionsCommand({
|
|
222
352
|
Bucket: bucket,
|
|
353
|
+
Prefix: prefix,
|
|
223
354
|
KeyMarker: keyMarker,
|
|
224
355
|
VersionIdMarker: versionMarker
|
|
225
356
|
}));
|
|
@@ -306,10 +437,11 @@ async function truncateTable(table) {
|
|
|
306
437
|
return await loop(undefined);
|
|
307
438
|
}
|
|
308
439
|
|
|
309
|
-
async function emptyBucket(bucket) {
|
|
440
|
+
async function emptyBucket(bucket, prefix) {
|
|
310
441
|
let loop = async (keyMarker, versionMarker) => {
|
|
311
442
|
let out = await S3$AwsSdk.ListObjectVersionsCommand.send(new ClientS3.ListObjectVersionsCommand({
|
|
312
443
|
Bucket: bucket,
|
|
444
|
+
Prefix: prefix,
|
|
313
445
|
KeyMarker: keyMarker,
|
|
314
446
|
VersionIdMarker: versionMarker
|
|
315
447
|
}));
|
|
@@ -341,6 +473,10 @@ async function emptyBucket(bucket) {
|
|
|
341
473
|
return await loop(undefined, undefined);
|
|
342
474
|
}
|
|
343
475
|
|
|
476
|
+
function pluginOf(t) {
|
|
477
|
+
return Stdlib_Option.getOr(t.plugin, t.label);
|
|
478
|
+
}
|
|
479
|
+
|
|
344
480
|
async function chooseScope(targets) {
|
|
345
481
|
let domain = targets.filter(t => t.group === "Domain");
|
|
346
482
|
let platform = targets.filter(t => t.group === "Platform");
|
|
@@ -395,7 +531,7 @@ async function chooseScope(targets) {
|
|
|
395
531
|
targets
|
|
396
532
|
]);
|
|
397
533
|
}
|
|
398
|
-
return await Seed_Prompt$ReventlessSeed.select("Reset scope:", options, undefined);
|
|
534
|
+
return await Seed_Prompt$ReventlessSeed.select("Reset scope:", options, undefined, undefined);
|
|
399
535
|
}
|
|
400
536
|
}
|
|
401
537
|
|
|
@@ -454,6 +590,28 @@ function gateTarget(target, backend, stack) {
|
|
|
454
590
|
}
|
|
455
591
|
}
|
|
456
592
|
|
|
593
|
+
function noQuiesce() {
|
|
594
|
+
let match = Stdlib_Option.map(Seed_Prompt$ReventlessSeed.envValue("SEED_RESET_NO_QUIESCE"), v => v.trim().toLowerCase());
|
|
595
|
+
if (match === undefined) {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
switch (match) {
|
|
599
|
+
case "1" :
|
|
600
|
+
case "true" :
|
|
601
|
+
case "yes" :
|
|
602
|
+
return true;
|
|
603
|
+
default:
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function refillMessage(refilled, heldCount) {
|
|
609
|
+
let total = Stdlib_Array.reduce(refilled, 0, (acc, param) => acc + param[1] | 0);
|
|
610
|
+
let lines = refilled.map(param => `\n ` + param[1].toString().padStart(8, " ") + ` ` + param[0]).join("");
|
|
611
|
+
let diagnosis = heldCount > 0 ? `\n\n The wipe deleted these and something wrote them back. All ` + heldCount.toString() + ` runtime(s) in scope were held at zero concurrency for the whole wipe, so the writer was an invocation already in flight when the hold took effect. Re-running clears it.` : `\n\n The wipe deleted these and a running runtime wrote them back. The stack was NOT held (SEED_RESET_NO_QUIESCE), so nothing stopped it, and re-running will not help: the writer keeps the state in memory and restores it on every invocation, identical each time. Re-run without SEED_RESET_NO_QUIESCE so the runtimes are held and recycled.`;
|
|
612
|
+
return total.toString() + ` item(s)/object(s) came back after the wipe:` + lines + diagnosis;
|
|
613
|
+
}
|
|
614
|
+
|
|
457
615
|
function reportAll(resolvedList, stack, region) {
|
|
458
616
|
Seed_Runner$ReventlessSeed.heading(`Reset target: stack "` + stack + `" in ` + region);
|
|
459
617
|
let total = {
|
|
@@ -479,6 +637,15 @@ function reportAll(resolvedList, stack, region) {
|
|
|
479
637
|
});
|
|
480
638
|
if (r.bucketCounts.length === 0) {
|
|
481
639
|
console.log(" (none)");
|
|
640
|
+
}
|
|
641
|
+
if (r.storeCounts.length !== 0) {
|
|
642
|
+
console.log(" Object stores:");
|
|
643
|
+
r.storeCounts.forEach(param => {
|
|
644
|
+
let c = param[1];
|
|
645
|
+
let s = param[0];
|
|
646
|
+
total.contents = total.contents + c | 0;
|
|
647
|
+
console.log(` ` + c.toString().padStart(8, " ") + ` ` + s.qualified + ` ` + (s.bucketName + `/` + s.keyPrefix + `/`));
|
|
648
|
+
});
|
|
482
649
|
return;
|
|
483
650
|
}
|
|
484
651
|
});
|
|
@@ -507,7 +674,38 @@ function run(stack, backend, targets, param) {
|
|
|
507
674
|
};
|
|
508
675
|
}
|
|
509
676
|
let selected = await chooseScope(targets);
|
|
510
|
-
let
|
|
677
|
+
let platformTarget = targets.find(t => t.group === "Platform");
|
|
678
|
+
let allStores;
|
|
679
|
+
if (platformTarget !== undefined) {
|
|
680
|
+
let output = ReventlessSeedAws.stackOutputs(platformTarget.projectDir, backend$1, stack$1);
|
|
681
|
+
let stores = parseObjectStores(field(output, "objectStores"));
|
|
682
|
+
if (stores.TAG === "Ok") {
|
|
683
|
+
allStores = stores._0;
|
|
684
|
+
} else {
|
|
685
|
+
throw {
|
|
686
|
+
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
687
|
+
_1: stores._0,
|
|
688
|
+
Error: new Error()
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
} else {
|
|
692
|
+
console.log("");
|
|
693
|
+
console.log("Note: no `platform` target is declared, so declared object stores could not be resolved — any uploaded objects will be left in place.");
|
|
694
|
+
allStores = [];
|
|
695
|
+
}
|
|
696
|
+
let message = validateStores(allStores);
|
|
697
|
+
if (message.TAG !== "Ok") {
|
|
698
|
+
throw {
|
|
699
|
+
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
700
|
+
_1: `refusing: ` + message._0,
|
|
701
|
+
Error: new Error()
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
let storeBucketNames = allStores.map(s => s.bucketName);
|
|
705
|
+
let selectedStores = allStores.filter(s => selected.some(t => pluginOf(t) === s.plugin));
|
|
706
|
+
let match = selectedStores.length !== 0;
|
|
707
|
+
let gated = match && platformTarget !== undefined && !selected.some(t => t.projectDir === platformTarget.projectDir) ? selected.concat([platformTarget]) : selected;
|
|
708
|
+
let regions = gated.map(t => gateTarget(t, backend$1, stack$1));
|
|
511
709
|
let region = regions[0];
|
|
512
710
|
if (regions.some(r => r !== region)) {
|
|
513
711
|
throw {
|
|
@@ -517,14 +715,28 @@ function run(stack, backend, targets, param) {
|
|
|
517
715
|
};
|
|
518
716
|
}
|
|
519
717
|
process.env["AWS_REGION"] = region;
|
|
718
|
+
if (selectedStores.length !== 0 && platformTarget !== undefined) {
|
|
719
|
+
let platformProject = projectName(platformTarget.projectDir);
|
|
720
|
+
let platformFound = await discover(region, stack$1, platformProject);
|
|
721
|
+
selectedStores.forEach(s => {
|
|
722
|
+
if (platformFound.buckets.includes(s.bucketName)) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
throw {
|
|
726
|
+
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
727
|
+
_1: `refusing: store "` + s.qualified + `" names bucket ` + s.bucketName + `, which does not ` + (`carry reventless:platform=` + platformProject + ` + reventless:environment=` + stack$1 + `.`),
|
|
728
|
+
Error: new Error()
|
|
729
|
+
};
|
|
730
|
+
});
|
|
731
|
+
}
|
|
520
732
|
let resolvedList = [];
|
|
521
733
|
for (let i = 0, i_finish = selected.length; i < i_finish; ++i) {
|
|
522
734
|
let target = selected[i];
|
|
523
735
|
if (target !== undefined) {
|
|
524
736
|
let platform = projectName(target.projectDir);
|
|
525
|
-
let
|
|
526
|
-
let tables =
|
|
527
|
-
let buckets =
|
|
737
|
+
let found = await discover(region, stack$1, platform);
|
|
738
|
+
let tables = found.tables.toSorted(Primitive_string.compare);
|
|
739
|
+
let buckets = found.buckets.filter(b => !storeBucketNames.includes(b)).toSorted(Primitive_string.compare);
|
|
528
740
|
let tableCounts = [];
|
|
529
741
|
for (let j = 0, j_finish = tables.length; j < j_finish; ++j) {
|
|
530
742
|
let t = tables[j];
|
|
@@ -538,7 +750,18 @@ function run(stack, backend, targets, param) {
|
|
|
538
750
|
if (b !== undefined) {
|
|
539
751
|
bucketCounts.push([
|
|
540
752
|
b,
|
|
541
|
-
await countBucket(b)
|
|
753
|
+
await countBucket(b, undefined)
|
|
754
|
+
]);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
let stores$1 = selectedStores.filter(s => s.plugin === pluginOf(target));
|
|
758
|
+
let storeCounts = [];
|
|
759
|
+
for (let j$2 = 0, j_finish$2 = stores$1.length; j$2 < j_finish$2; ++j$2) {
|
|
760
|
+
let s = stores$1[j$2];
|
|
761
|
+
if (s !== undefined) {
|
|
762
|
+
storeCounts.push([
|
|
763
|
+
s,
|
|
764
|
+
await countBucket(s.bucketName, s.keyPrefix + `/`)
|
|
542
765
|
]);
|
|
543
766
|
}
|
|
544
767
|
}
|
|
@@ -547,7 +770,9 @@ function run(stack, backend, targets, param) {
|
|
|
547
770
|
platform: platform,
|
|
548
771
|
tables: tables,
|
|
549
772
|
tableCounts: tableCounts,
|
|
550
|
-
bucketCounts: bucketCounts
|
|
773
|
+
bucketCounts: bucketCounts,
|
|
774
|
+
storeCounts: storeCounts,
|
|
775
|
+
functions: found.functions.toSorted(Primitive_string.compare)
|
|
551
776
|
});
|
|
552
777
|
}
|
|
553
778
|
}
|
|
@@ -572,49 +797,128 @@ function run(stack, backend, targets, param) {
|
|
|
572
797
|
console.log(interactive ? "Dry run — nothing was deleted." : `Dry run — nothing was deleted. Set REVENTLESS_WIPE_CONFIRM=` + stack$1 + ` to empty this scope non-interactively.`);
|
|
573
798
|
process.exit(0);
|
|
574
799
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
800
|
+
let functionNames = Stdlib_Array.reduce(resolvedList, [], (acc, r) => acc.concat(r.functions.filter(f => !acc.includes(f))));
|
|
801
|
+
let quiesce = !noQuiesce() && functionNames.length !== 0;
|
|
802
|
+
let lambdaClient = Lambda$AwsSdk.client(region, undefined);
|
|
803
|
+
let held = quiesce ? (Seed_Runner$ReventlessSeed.heading(`Holding ` + functionNames.length.toString() + ` runtime(s) at zero concurrency …`), await ReventlessSeedAws_Quiesce.hold(lambdaClient, functionNames)) : (functionNames.length !== 0 ? (console.log(""), console.log("Note: SEED_RESET_NO_QUIESCE is set — the stack's runtimes keep running through the wipe. A runtime that holds state across invocations can write it straight back over an emptied store."), undefined) : undefined, []);
|
|
804
|
+
let outcome;
|
|
805
|
+
try {
|
|
806
|
+
for (let i$1 = 0, i_finish$1 = resolvedList.length; i$1 < i_finish$1; ++i$1) {
|
|
807
|
+
let r = resolvedList[i$1];
|
|
808
|
+
if (r !== undefined) {
|
|
809
|
+
Seed_Runner$ReventlessSeed.heading(`Emptying ` + r.target.label + ` …`);
|
|
810
|
+
for (let j$3 = 0, j_finish$3 = r.tables.length; j$3 < j_finish$3; ++j$3) {
|
|
811
|
+
let t$1 = r.tables[j$3];
|
|
812
|
+
if (t$1 !== undefined) {
|
|
813
|
+
await truncateTable(t$1);
|
|
814
|
+
console.log(` truncated ` + t$1);
|
|
815
|
+
}
|
|
584
816
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
817
|
+
for (let j$4 = 0, j_finish$4 = r.bucketCounts.length; j$4 < j_finish$4; ++j$4) {
|
|
818
|
+
let match$1 = r.bucketCounts[j$4];
|
|
819
|
+
if (match$1 !== undefined) {
|
|
820
|
+
let b$1 = match$1[0];
|
|
821
|
+
await emptyBucket(b$1, undefined);
|
|
822
|
+
console.log(` emptied ` + b$1);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
for (let j$5 = 0, j_finish$5 = r.storeCounts.length; j$5 < j_finish$5; ++j$5) {
|
|
826
|
+
let match$2 = r.storeCounts[j$5];
|
|
827
|
+
if (match$2 !== undefined) {
|
|
828
|
+
let s$1 = match$2[0];
|
|
829
|
+
await emptyBucket(s$1.bucketName, s$1.keyPrefix + `/`);
|
|
830
|
+
console.log(` emptied ` + s$1.qualified + ` — ` + match$2[1].toString() + ` object(s) removed from ` + (s$1.bucketName + `/` + s$1.keyPrefix + `/`));
|
|
831
|
+
}
|
|
592
832
|
}
|
|
593
833
|
}
|
|
594
834
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
835
|
+
let refilled = [];
|
|
836
|
+
for (let i$2 = 0, i_finish$2 = resolvedList.length; i$2 < i_finish$2; ++i$2) {
|
|
837
|
+
let r$1 = resolvedList[i$2];
|
|
838
|
+
if (r$1 !== undefined) {
|
|
839
|
+
for (let j$6 = 0, j_finish$6 = r$1.tables.length; j$6 < j_finish$6; ++j$6) {
|
|
840
|
+
let t$2 = r$1.tables[j$6];
|
|
841
|
+
if (t$2 !== undefined) {
|
|
842
|
+
let left = await countTable(t$2);
|
|
843
|
+
if (left !== 0) {
|
|
844
|
+
refilled.push([
|
|
845
|
+
t$2,
|
|
846
|
+
left
|
|
847
|
+
]);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
604
850
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
851
|
+
for (let j$7 = 0, j_finish$7 = r$1.bucketCounts.length; j$7 < j_finish$7; ++j$7) {
|
|
852
|
+
let match$3 = r$1.bucketCounts[j$7];
|
|
853
|
+
if (match$3 !== undefined) {
|
|
854
|
+
let b$2 = match$3[0];
|
|
855
|
+
let left$1 = await countBucket(b$2, undefined);
|
|
856
|
+
if (left$1 !== 0) {
|
|
857
|
+
refilled.push([
|
|
858
|
+
b$2,
|
|
859
|
+
left$1
|
|
860
|
+
]);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
for (let j$8 = 0, j_finish$8 = r$1.storeCounts.length; j$8 < j_finish$8; ++j$8) {
|
|
865
|
+
let match$4 = r$1.storeCounts[j$8];
|
|
866
|
+
if (match$4 !== undefined) {
|
|
867
|
+
let s$2 = match$4[0];
|
|
868
|
+
let left$2 = await countBucket(s$2.bucketName, s$2.keyPrefix + `/`);
|
|
869
|
+
if (left$2 !== 0) {
|
|
870
|
+
refilled.push([
|
|
871
|
+
s$2.qualified + ` (` + s$2.bucketName + `/` + s$2.keyPrefix + `/)`,
|
|
872
|
+
left$2
|
|
873
|
+
]);
|
|
874
|
+
}
|
|
875
|
+
console.log(` verified empty: ` + s$2.qualified + ` — ` + left$2.toString() + ` object(s) remain under ` + (s$2.bucketName + `/` + s$2.keyPrefix + `/`));
|
|
876
|
+
}
|
|
610
877
|
}
|
|
611
878
|
}
|
|
612
879
|
}
|
|
880
|
+
outcome = {
|
|
881
|
+
TAG: "Ok",
|
|
882
|
+
_0: refilled
|
|
883
|
+
};
|
|
884
|
+
} catch (raw_message) {
|
|
885
|
+
let message$1 = Primitive_exceptions.internalToException(raw_message);
|
|
886
|
+
outcome = message$1.RE_EXN_ID === Seed$ReventlessSeed.Failed ? ({
|
|
887
|
+
TAG: "Error",
|
|
888
|
+
_0: message$1._1
|
|
889
|
+
}) : ({
|
|
890
|
+
TAG: "Error",
|
|
891
|
+
_0: `the wipe failed: ` + Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(message$1), Stdlib_JsExn.message), "unknown error")
|
|
892
|
+
});
|
|
613
893
|
}
|
|
614
|
-
|
|
894
|
+
let warnings;
|
|
895
|
+
if (held.length !== 0) {
|
|
896
|
+
Seed_Runner$ReventlessSeed.heading(`Recycling ` + held.length.toString() + ` runtime(s) …`);
|
|
897
|
+
let recycled = await ReventlessSeedAws_Quiesce.recycle(lambdaClient, held);
|
|
898
|
+
let released = await ReventlessSeedAws_Quiesce.release(lambdaClient, held);
|
|
899
|
+
warnings = recycled.concat(released);
|
|
900
|
+
} else {
|
|
901
|
+
warnings = [];
|
|
902
|
+
}
|
|
903
|
+
if (warnings.length !== 0) {
|
|
904
|
+
console.error("");
|
|
905
|
+
warnings.forEach(w => {
|
|
906
|
+
console.error(` warning: ` + w);
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
if (outcome.TAG === "Ok") {
|
|
910
|
+
let refilled$1 = outcome._0;
|
|
911
|
+
if (refilled$1.length !== 0) {
|
|
912
|
+
throw {
|
|
913
|
+
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
914
|
+
_1: refillMessage(refilled$1, held.length),
|
|
915
|
+
Error: new Error()
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
} else {
|
|
615
919
|
throw {
|
|
616
920
|
RE_EXN_ID: Seed$ReventlessSeed.Failed,
|
|
617
|
-
_1:
|
|
921
|
+
_1: outcome._0,
|
|
618
922
|
Error: new Error()
|
|
619
923
|
};
|
|
620
924
|
}
|
|
@@ -622,18 +926,18 @@ function run(stack, backend, targets, param) {
|
|
|
622
926
|
console.log(`Reset complete — the selected scope of "` + stack$1 + `" reads empty and is re-seedable.`);
|
|
623
927
|
process.exit(0);
|
|
624
928
|
return;
|
|
625
|
-
} catch (raw_message) {
|
|
626
|
-
let message = Primitive_exceptions.internalToException(raw_message);
|
|
627
|
-
if (message.RE_EXN_ID === Seed$ReventlessSeed.Failed) {
|
|
929
|
+
} catch (raw_message$1) {
|
|
930
|
+
let message$2 = Primitive_exceptions.internalToException(raw_message$1);
|
|
931
|
+
if (message$2.RE_EXN_ID === Seed$ReventlessSeed.Failed) {
|
|
628
932
|
Seed_Prompt$ReventlessSeed.close();
|
|
629
933
|
console.error("");
|
|
630
|
-
console.error(`Reset aborted — ` + message._1);
|
|
934
|
+
console.error(`Reset aborted — ` + message$2._1);
|
|
631
935
|
process.exit(1);
|
|
632
936
|
} else {
|
|
633
937
|
Seed_Prompt$ReventlessSeed.close();
|
|
634
938
|
console.error("");
|
|
635
939
|
console.error("Reset aborted with an unexpected error:");
|
|
636
|
-
console.error(Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(message), Stdlib_JsExn.message), "unknown"));
|
|
940
|
+
console.error(Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(message$2), Stdlib_JsExn.message), "unknown"));
|
|
637
941
|
process.exit(1);
|
|
638
942
|
}
|
|
639
943
|
return;
|
|
@@ -648,10 +952,16 @@ let Rgt;
|
|
|
648
952
|
|
|
649
953
|
let S3;
|
|
650
954
|
|
|
955
|
+
let Lambda;
|
|
956
|
+
|
|
957
|
+
let Quiesce;
|
|
958
|
+
|
|
651
959
|
export {
|
|
652
960
|
Ddb,
|
|
653
961
|
Rgt,
|
|
654
962
|
S3,
|
|
963
|
+
Lambda,
|
|
964
|
+
Quiesce,
|
|
655
965
|
projectName,
|
|
656
966
|
field,
|
|
657
967
|
asString,
|
|
@@ -662,13 +972,19 @@ export {
|
|
|
662
972
|
classify,
|
|
663
973
|
tagValue,
|
|
664
974
|
discover,
|
|
975
|
+
splitQualified,
|
|
976
|
+
parseObjectStores,
|
|
977
|
+
validateStores,
|
|
665
978
|
countTable,
|
|
666
979
|
countBucket,
|
|
667
980
|
sendBatch,
|
|
668
981
|
truncateTable,
|
|
669
982
|
emptyBucket,
|
|
983
|
+
pluginOf,
|
|
670
984
|
chooseScope,
|
|
671
985
|
gateTarget,
|
|
986
|
+
noQuiesce,
|
|
987
|
+
refillMessage,
|
|
672
988
|
reportAll,
|
|
673
989
|
run,
|
|
674
990
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|