PyReverseETL 3.1.7__tar.gz → 3.3.0__tar.gz
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.
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/Cargo.lock +2 -2
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/Cargo.toml +1 -1
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/PKG-INFO +16 -1
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/README.md +15 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/pyproject.toml +1 -1
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/python/pyreverseetl/cli.py +141 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/LICENSE +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/Cargo.toml +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/benches/load_test.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/bin/pyreverseetl_dashboard.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/activation.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/alert_compat.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/error.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/http_client.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/hubspot.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/mapping.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/marketo.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/oauth_manager.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/retry_policy.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/salesforce.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/schema_detect.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/adapters/webhook.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/cdc/change_detector.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/cdc/changelog.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/cdc/checkpoint.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/cdc/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/config.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/connectors_db.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/database_advanced.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/destination.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/error.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/hdfs.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/mysql.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/object_storage.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/postgres.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/rate_limiting.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/registry.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/saas.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/source.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/connectors/web.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/destination.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/dlq.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/entity.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/error.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/executor.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/cached_gate.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/compliance_rules.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/credentials.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/quality_gate.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/retry_policy.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/schema_evolution.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/governance/statguardian_client.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/idempotency.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/lib.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/lineage.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/observability/dashboard_launcher.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/observability/logs.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/observability/metrics.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/observability/metrics_server.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/observability/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/observability/traces.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/pipeline/activation_pipeline.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/pipeline/backpressure.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/pipeline/latency_tracker.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/pipeline/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/sources/kafka.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/sources/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/sources/polling.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/sources/sync_config.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/statguardian.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/storage/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/storage/repository.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/storage/schema.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/streaming/event_processor.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/streaming/event_schema.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/streaming/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/streampdf.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/streamxl.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/sync.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/testing/connector_test.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/testing/harness.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/testing/metrics.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/testing/mock_http.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/testing/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/testing/test_data.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/transformers/mod.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/transformers/spark.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/core/src/workflow.rs +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/python/Cargo.toml +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/python/pyreverseetl/__init__.py +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/python/pyreverseetl/server.py +0 -0
- {pyreverseetl-3.1.7 → pyreverseetl-3.3.0}/python/src/lib.rs +0 -0
|
@@ -3199,7 +3199,7 @@ dependencies = [
|
|
|
3199
3199
|
|
|
3200
3200
|
[[package]]
|
|
3201
3201
|
name = "pyreverseetl"
|
|
3202
|
-
version = "3.
|
|
3202
|
+
version = "3.3.0"
|
|
3203
3203
|
dependencies = [
|
|
3204
3204
|
"chrono",
|
|
3205
3205
|
"pyo3",
|
|
@@ -3210,7 +3210,7 @@ dependencies = [
|
|
|
3210
3210
|
|
|
3211
3211
|
[[package]]
|
|
3212
3212
|
name = "pyreverseetl-core"
|
|
3213
|
-
version = "3.
|
|
3213
|
+
version = "3.3.0"
|
|
3214
3214
|
dependencies = [
|
|
3215
3215
|
"async-trait",
|
|
3216
3216
|
"aws-config",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyReverseETL
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -249,6 +249,21 @@ Python CLI / API → pyreverseetl._core (PyO3 bindings) → pyreverseetl_cor
|
|
|
249
249
|
- **`python/pyreverseetl/`** — the installed Python package: `cli.py` (the `pyreverseetl`
|
|
250
250
|
command) and `server.py` (an optional Flask REST wrapper around the same engine).
|
|
251
251
|
|
|
252
|
+
## Validation gate
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# File-based report
|
|
256
|
+
pyreverseetl execute-activation my-activation --validation-report statguardian-report.json
|
|
257
|
+
|
|
258
|
+
# Live StatGuardian service: validate a sample before the real sync
|
|
259
|
+
pyreverseetl execute-activation my-activation --statguardian-url http://127.0.0.1:8000
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
A file report must have `"passed": true`; anything else blocks the sync. The
|
|
263
|
+
live `--statguardian-url` gate dry-runs a sample and calls the service's
|
|
264
|
+
`/validate`; a failure or network error blocks the real sync. It is a sample
|
|
265
|
+
gate, not a full-table scan.
|
|
266
|
+
|
|
252
267
|
## Documentation
|
|
253
268
|
|
|
254
269
|
- [ROADMAP_HONEST.md](ROADMAP_HONEST.md) — what's tested vs. untested vs. broken vs. not
|
|
@@ -226,6 +226,21 @@ Python CLI / API → pyreverseetl._core (PyO3 bindings) → pyreverseetl_cor
|
|
|
226
226
|
- **`python/pyreverseetl/`** — the installed Python package: `cli.py` (the `pyreverseetl`
|
|
227
227
|
command) and `server.py` (an optional Flask REST wrapper around the same engine).
|
|
228
228
|
|
|
229
|
+
## Validation gate
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# File-based report
|
|
233
|
+
pyreverseetl execute-activation my-activation --validation-report statguardian-report.json
|
|
234
|
+
|
|
235
|
+
# Live StatGuardian service: validate a sample before the real sync
|
|
236
|
+
pyreverseetl execute-activation my-activation --statguardian-url http://127.0.0.1:8000
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
A file report must have `"passed": true`; anything else blocks the sync. The
|
|
240
|
+
live `--statguardian-url` gate dry-runs a sample and calls the service's
|
|
241
|
+
`/validate`; a failure or network error blocks the real sync. It is a sample
|
|
242
|
+
gate, not a full-table scan.
|
|
243
|
+
|
|
229
244
|
## Documentation
|
|
230
245
|
|
|
231
246
|
- [ROADMAP_HONEST.md](ROADMAP_HONEST.md) — what's tested vs. untested vs. broken vs. not
|
|
@@ -27,10 +27,71 @@ from __future__ import annotations
|
|
|
27
27
|
import json
|
|
28
28
|
import os
|
|
29
29
|
import sys
|
|
30
|
+
import urllib.error
|
|
31
|
+
import urllib.request
|
|
30
32
|
|
|
31
33
|
DEFAULT_STATE_PATH = os.path.join(os.path.expanduser("~"), ".pyreverseetl", "state.json")
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
def validate_activation_rows(
|
|
37
|
+
rows: list[dict],
|
|
38
|
+
service_url: str,
|
|
39
|
+
*,
|
|
40
|
+
limit: int = 100,
|
|
41
|
+
timeout_seconds: float = 10.0,
|
|
42
|
+
) -> tuple[bool, dict]:
|
|
43
|
+
"""POST sample rows to StatGuardian's ``/validate`` endpoint.
|
|
44
|
+
|
|
45
|
+
Fails closed on network/HTTP/parse errors. Only the first ``limit`` rows
|
|
46
|
+
are checked; this is a pre-activation sample gate, not a full-table scan.
|
|
47
|
+
"""
|
|
48
|
+
url = service_url.rstrip("/") + "/validate"
|
|
49
|
+
checked = 0
|
|
50
|
+
for row in rows[: max(1, limit)]:
|
|
51
|
+
checked += 1
|
|
52
|
+
body = json.dumps({"entity": {"attributes": row}}).encode("utf-8")
|
|
53
|
+
request = urllib.request.Request(
|
|
54
|
+
url,
|
|
55
|
+
data=body,
|
|
56
|
+
headers={"Content-Type": "application/json"},
|
|
57
|
+
method="POST",
|
|
58
|
+
)
|
|
59
|
+
try:
|
|
60
|
+
with urllib.request.urlopen(request, timeout=timeout_seconds) as response:
|
|
61
|
+
payload = json.loads(response.read().decode("utf-8"))
|
|
62
|
+
except (urllib.error.URLError, OSError, ValueError) as exc:
|
|
63
|
+
return False, {"reason": f"StatGuardian request failed: {exc}", "checked": checked}
|
|
64
|
+
if payload.get("passed") is not True:
|
|
65
|
+
return False, {
|
|
66
|
+
"reason": "StatGuardian rejected a sample row",
|
|
67
|
+
"checked": checked,
|
|
68
|
+
"issues": payload.get("issues", []),
|
|
69
|
+
}
|
|
70
|
+
return True, {"checked": checked}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def validation_report_allows(path: str) -> tuple[bool, dict]:
|
|
74
|
+
"""Read a StatGuardian-style JSON report and decide whether sync may run.
|
|
75
|
+
|
|
76
|
+
Expected shape: ``{"passed": bool, "violations": [...], ...}``. A missing
|
|
77
|
+
or malformed file fails closed. This is a file-based gate until
|
|
78
|
+
StatGuardian exposes a service endpoint; it does not call StatGuardian.
|
|
79
|
+
"""
|
|
80
|
+
try:
|
|
81
|
+
with open(path, encoding="utf-8") as handle:
|
|
82
|
+
report = json.load(handle)
|
|
83
|
+
except (OSError, ValueError) as exc:
|
|
84
|
+
return False, {"reason": f"cannot read validation report: {exc}"}
|
|
85
|
+
if not isinstance(report, dict) or "passed" not in report:
|
|
86
|
+
return False, {"reason": "validation report must be a JSON object with a 'passed' field"}
|
|
87
|
+
if report.get("passed") is not True:
|
|
88
|
+
return False, {
|
|
89
|
+
"reason": "validation report did not pass",
|
|
90
|
+
"violations": report.get("violations", []),
|
|
91
|
+
}
|
|
92
|
+
return True, {}
|
|
93
|
+
|
|
94
|
+
|
|
34
95
|
class CLIInterface:
|
|
35
96
|
"""Command-line interface for PyReverseETL workflow integration."""
|
|
36
97
|
|
|
@@ -162,6 +223,9 @@ class CLIInterface:
|
|
|
162
223
|
schema_store_path: str | None = None,
|
|
163
224
|
idempotency_store_path: str | None = None,
|
|
164
225
|
dlq_store_path: str | None = None,
|
|
226
|
+
validation_report_path: str | None = None,
|
|
227
|
+
statguardian_url: str | None = None,
|
|
228
|
+
statguardian_limit: int = 100,
|
|
165
229
|
) -> dict:
|
|
166
230
|
"""Execute an activation: run a real sync through the Rust engine.
|
|
167
231
|
|
|
@@ -200,6 +264,16 @@ class CLIInterface:
|
|
|
200
264
|
changed is still sent. Only applies to the adapter-based
|
|
201
265
|
destinations (webhook/salesforce/hubspot/marketo). Omit to
|
|
202
266
|
disable idempotency checking entirely (default).
|
|
267
|
+
validation_report_path: Optional path to a JSON validation report
|
|
268
|
+
(``{"passed": bool, ...}``). If supplied and not passing, the
|
|
269
|
+
sync is blocked before any source read or destination write.
|
|
270
|
+
This is a file-based StatGuardian gate.
|
|
271
|
+
statguardian_url: Optional base URL of a running StatGuardian
|
|
272
|
+
service. A dry-run reads a sample of source rows and POSTs them
|
|
273
|
+
to ``/validate``; any failure (or network error) blocks the real
|
|
274
|
+
sync. This doubles the source read for the sample pass.
|
|
275
|
+
statguardian_limit: Maximum sample rows sent to StatGuardian
|
|
276
|
+
(default 100).
|
|
203
277
|
dlq_store_path: Optional path to a SQLite file used as a
|
|
204
278
|
dead-letter queue (quarantine) for records the destination
|
|
205
279
|
rejects. Each failed record is stored with its run id, the
|
|
@@ -220,6 +294,15 @@ class CLIInterface:
|
|
|
220
294
|
}
|
|
221
295
|
|
|
222
296
|
activation = self.activations[activation_id]
|
|
297
|
+
if validation_report_path:
|
|
298
|
+
allowed, detail = validation_report_allows(validation_report_path)
|
|
299
|
+
if not allowed:
|
|
300
|
+
return {
|
|
301
|
+
"status": "error",
|
|
302
|
+
"activation_id": activation_id,
|
|
303
|
+
"message": "Blocked by validation gate",
|
|
304
|
+
"validation": detail,
|
|
305
|
+
}
|
|
223
306
|
workflow = self.workflows.get(activation["workflow_id"])
|
|
224
307
|
if workflow is None:
|
|
225
308
|
return {
|
|
@@ -239,6 +322,38 @@ class CLIInterface:
|
|
|
239
322
|
source_config.setdefault("table", workflow.get("table"))
|
|
240
323
|
destination_config = activation.get("destination_config") or {}
|
|
241
324
|
|
|
325
|
+
if statguardian_url:
|
|
326
|
+
try:
|
|
327
|
+
preview = _core.run_sync(
|
|
328
|
+
source_type=workflow["source"],
|
|
329
|
+
source_config=json.dumps(source_config),
|
|
330
|
+
destination_type=activation["destination"],
|
|
331
|
+
destination_config=json.dumps(destination_config),
|
|
332
|
+
limit=limit,
|
|
333
|
+
compliance_rules=json.dumps(compliance_rules) if compliance_rules else None,
|
|
334
|
+
dry_run=True,
|
|
335
|
+
schema_store_path=None,
|
|
336
|
+
idempotency_store_path=None,
|
|
337
|
+
dlq_store_path=None,
|
|
338
|
+
)
|
|
339
|
+
except Exception as exc: # noqa: BLE001
|
|
340
|
+
return {
|
|
341
|
+
"status": "error",
|
|
342
|
+
"activation_id": activation_id,
|
|
343
|
+
"message": f"StatGuardian sample read failed: {exc}",
|
|
344
|
+
}
|
|
345
|
+
sample_rows = [json.loads(row) for row in preview.dry_run_preview]
|
|
346
|
+
allowed, detail = validate_activation_rows(
|
|
347
|
+
sample_rows, statguardian_url, limit=statguardian_limit
|
|
348
|
+
)
|
|
349
|
+
if not allowed:
|
|
350
|
+
return {
|
|
351
|
+
"status": "error",
|
|
352
|
+
"activation_id": activation_id,
|
|
353
|
+
"message": "Blocked by StatGuardian sample validation",
|
|
354
|
+
"validation": detail,
|
|
355
|
+
}
|
|
356
|
+
|
|
242
357
|
try:
|
|
243
358
|
result = _core.run_sync(
|
|
244
359
|
source_type=workflow["source"],
|
|
@@ -501,6 +616,29 @@ def main():
|
|
|
501
616
|
sys.exit(1)
|
|
502
617
|
dlq_store_path = sys.argv[idx + 1]
|
|
503
618
|
|
|
619
|
+
validation_report_path = None
|
|
620
|
+
if "--validation-report" in sys.argv:
|
|
621
|
+
idx = sys.argv.index("--validation-report")
|
|
622
|
+
if idx + 1 >= len(sys.argv):
|
|
623
|
+
print(json.dumps({"error": "--validation-report requires a file path"}))
|
|
624
|
+
sys.exit(1)
|
|
625
|
+
validation_report_path = sys.argv[idx + 1]
|
|
626
|
+
|
|
627
|
+
statguardian_url = None
|
|
628
|
+
if "--statguardian-url" in sys.argv:
|
|
629
|
+
idx = sys.argv.index("--statguardian-url")
|
|
630
|
+
if idx + 1 >= len(sys.argv):
|
|
631
|
+
print(json.dumps({"error": "--statguardian-url requires a URL"}))
|
|
632
|
+
sys.exit(1)
|
|
633
|
+
statguardian_url = sys.argv[idx + 1]
|
|
634
|
+
statguardian_limit = 100
|
|
635
|
+
if "--statguardian-limit" in sys.argv:
|
|
636
|
+
idx = sys.argv.index("--statguardian-limit")
|
|
637
|
+
if idx + 1 >= len(sys.argv):
|
|
638
|
+
print(json.dumps({"error": "--statguardian-limit requires a number"}))
|
|
639
|
+
sys.exit(1)
|
|
640
|
+
statguardian_limit = int(sys.argv[idx + 1])
|
|
641
|
+
|
|
504
642
|
result = cli.execute_activation(
|
|
505
643
|
activation_id,
|
|
506
644
|
limit,
|
|
@@ -509,6 +647,9 @@ def main():
|
|
|
509
647
|
schema_store_path,
|
|
510
648
|
idempotency_store_path,
|
|
511
649
|
dlq_store_path,
|
|
650
|
+
validation_report_path,
|
|
651
|
+
statguardian_url,
|
|
652
|
+
statguardian_limit,
|
|
512
653
|
)
|
|
513
654
|
print(json.dumps(result))
|
|
514
655
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|