erambactl 0.1.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.
Files changed (60) hide show
  1. erambactl-0.1.0/.github/release-notes.md +21 -0
  2. erambactl-0.1.0/.github/workflows/ci.yml +69 -0
  3. erambactl-0.1.0/.github/workflows/release.yml +144 -0
  4. erambactl-0.1.0/PKG-INFO +482 -0
  5. erambactl-0.1.0/README.md +452 -0
  6. erambactl-0.1.0/docker/eramba-a.env +18 -0
  7. erambactl-0.1.0/docker/eramba-a.yml +22 -0
  8. erambactl-0.1.0/docker/eramba-b.env +18 -0
  9. erambactl-0.1.0/docker/eramba-b.yml +22 -0
  10. erambactl-0.1.0/docs/api-v2-commands.md +242 -0
  11. erambactl-0.1.0/docs/api-v2-smoke.md +19 -0
  12. erambactl-0.1.0/docs/real-api-check.md +46 -0
  13. erambactl-0.1.0/erambactl/__init__.py +37 -0
  14. erambactl-0.1.0/erambactl/__main__.py +10 -0
  15. erambactl-0.1.0/erambactl/_http.py +68 -0
  16. erambactl-0.1.0/erambactl/_shared.py +57 -0
  17. erambactl-0.1.0/erambactl/api_v2_data.py +1298 -0
  18. erambactl-0.1.0/erambactl/api_v2_fields.py +122 -0
  19. erambactl-0.1.0/erambactl/cli.py +365 -0
  20. erambactl-0.1.0/erambactl/cli_payload.py +107 -0
  21. erambactl-0.1.0/erambactl/client.py +433 -0
  22. erambactl-0.1.0/erambactl/commands.py +66 -0
  23. erambactl-0.1.0/erambactl/config.py +88 -0
  24. erambactl-0.1.0/erambactl/py.typed +1 -0
  25. erambactl-0.1.0/erambactl/real_cli_check.py +210 -0
  26. erambactl-0.1.0/erambactl/real_cli_values.py +273 -0
  27. erambactl-0.1.0/erambactl/route_data.py +9871 -0
  28. erambactl-0.1.0/erambactl/route_parser.py +130 -0
  29. erambactl-0.1.0/erambactl/seed.py +135 -0
  30. erambactl-0.1.0/erambactl/smoke.py +252 -0
  31. erambactl-0.1.0/erambactl/types.py +16 -0
  32. erambactl-0.1.0/examples/instances.json +18 -0
  33. erambactl-0.1.0/examples/seed-data.json +13 -0
  34. erambactl-0.1.0/pyproject.toml +63 -0
  35. erambactl-0.1.0/scripts/eramba-api-smoke +6 -0
  36. erambactl-0.1.0/scripts/eramba-api-smoke.cmd +6 -0
  37. erambactl-0.1.0/scripts/eramba-api-v2-smoke +16 -0
  38. erambactl-0.1.0/scripts/eramba-api-v2-smoke.cmd +16 -0
  39. erambactl-0.1.0/scripts/eramba-fill-real-data +23 -0
  40. erambactl-0.1.0/scripts/eramba-fill-real-data.cmd +12 -0
  41. erambactl-0.1.0/scripts/eramba-fill-real-data.sql +66 -0
  42. erambactl-0.1.0/scripts/eramba-lab +56 -0
  43. erambactl-0.1.0/scripts/eramba-lab.cmd +38 -0
  44. erambactl-0.1.0/scripts/eramba-package-check +25 -0
  45. erambactl-0.1.0/scripts/eramba-package-check.cmd +26 -0
  46. erambactl-0.1.0/scripts/eramba-real-api-check +60 -0
  47. erambactl-0.1.0/scripts/eramba-real-api-check.cmd +54 -0
  48. erambactl-0.1.0/scripts/eramba-real-cli-check +9 -0
  49. erambactl-0.1.0/scripts/eramba-real-cli-check.cmd +9 -0
  50. erambactl-0.1.0/scripts/eramba-seed-data +6 -0
  51. erambactl-0.1.0/scripts/eramba-seed-data.cmd +6 -0
  52. erambactl-0.1.0/tests/__init__.py +1 -0
  53. erambactl-0.1.0/tests/helpers.py +486 -0
  54. erambactl-0.1.0/tests/test_cli.py +1075 -0
  55. erambactl-0.1.0/tests/test_client.py +767 -0
  56. erambactl-0.1.0/tests/test_config.py +293 -0
  57. erambactl-0.1.0/tests/test_real_cli_check.py +742 -0
  58. erambactl-0.1.0/tests/test_route_parser.py +145 -0
  59. erambactl-0.1.0/tests/test_seed.py +188 -0
  60. erambactl-0.1.0/tests/test_smoke.py +467 -0
@@ -0,0 +1,21 @@
1
+ # erambactl 0.1.0
2
+
3
+ This is the first public release of erambactl, a small Python tool for working
4
+ with eramba from the command line or from Python code.
5
+
6
+ ## Highlights
7
+
8
+ - Command catalog for eramba API routes, including 209 API v2 commands.
9
+ - Multi-instance support for running the same command across several eramba
10
+ deployments.
11
+ - Authentication with bearer tokens, session login, cookies, and HTTP Basic.
12
+ - Request support for path parameters, query strings, JSON bodies, form fields,
13
+ file uploads, custom headers, and eramba dry-run requests.
14
+ - Local two-instance Docker lab based on eramba's official Docker deployment.
15
+ - Seed, smoke, and real CLI checks for validating API behavior against running
16
+ eramba instances.
17
+ - No runtime Python dependencies.
18
+ - CI coverage for Ubuntu, Windows, and macOS on Python 3.14.
19
+
20
+ The package is published to PyPI and the GitHub release includes the source
21
+ distribution and wheel built by the release workflow.
@@ -0,0 +1,69 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ name: Python 3.14 on ${{ matrix.os }}
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os:
20
+ - ubuntu-latest
21
+ - windows-latest
22
+ - macos-latest
23
+
24
+ steps:
25
+ - name: Check out repository
26
+ uses: actions/checkout@v7
27
+ with:
28
+ persist-credentials: false
29
+
30
+ - name: Set up Python
31
+ uses: actions/setup-python@v7
32
+ with:
33
+ python-version: "3.14"
34
+ cache: pip
35
+ cache-dependency-path: pyproject.toml
36
+
37
+ - name: Install package and tooling
38
+ run: python -m pip install -e ".[dev]"
39
+
40
+ - name: Check formatting
41
+ run: black --check .
42
+
43
+ - name: Lint
44
+ run: ruff check .
45
+
46
+ - name: Type check
47
+ run: mypy .
48
+
49
+ - name: Security scan
50
+ run: bandit -r .
51
+
52
+ - name: Dependency audit
53
+ run: pip-audit .
54
+
55
+ - name: Test
56
+ run: pytest -q
57
+
58
+ - name: Package check
59
+ if: runner.os != 'Windows'
60
+ run: scripts/eramba-package-check
61
+ env:
62
+ PYTHON: python
63
+
64
+ - name: Package check on Windows
65
+ if: runner.os == 'Windows'
66
+ shell: cmd
67
+ run: scripts\eramba-package-check.cmd
68
+ env:
69
+ PYTHON: python
@@ -0,0 +1,144 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ ci:
13
+ name: Release checks on ${{ matrix.os }}
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os:
19
+ - ubuntu-latest
20
+ - windows-latest
21
+ - macos-latest
22
+
23
+ steps:
24
+ - name: Check out repository
25
+ uses: actions/checkout@v7
26
+ with:
27
+ persist-credentials: false
28
+
29
+ - name: Set up Python
30
+ uses: actions/setup-python@v7
31
+ with:
32
+ python-version: "3.14"
33
+ cache: pip
34
+ cache-dependency-path: pyproject.toml
35
+
36
+ - name: Install package and tooling
37
+ run: python -m pip install -e ".[dev]"
38
+
39
+ - name: Check formatting
40
+ run: black --check .
41
+
42
+ - name: Lint
43
+ run: ruff check .
44
+
45
+ - name: Type check
46
+ run: mypy .
47
+
48
+ - name: Security scan
49
+ run: bandit -r .
50
+
51
+ - name: Dependency audit
52
+ run: pip-audit .
53
+
54
+ - name: Test
55
+ run: pytest -q
56
+
57
+ - name: Package check
58
+ if: runner.os != 'Windows'
59
+ run: scripts/eramba-package-check
60
+ env:
61
+ PYTHON: python
62
+
63
+ - name: Package check on Windows
64
+ if: runner.os == 'Windows'
65
+ shell: cmd
66
+ run: scripts\eramba-package-check.cmd
67
+ env:
68
+ PYTHON: python
69
+
70
+ build:
71
+ name: Build distribution
72
+ runs-on: ubuntu-latest
73
+ needs:
74
+ - ci
75
+ steps:
76
+ - name: Check out repository
77
+ uses: actions/checkout@v7
78
+ with:
79
+ persist-credentials: false
80
+
81
+ - name: Set up Python
82
+ uses: actions/setup-python@v7
83
+ with:
84
+ python-version: "3.14"
85
+ cache: pip
86
+ cache-dependency-path: pyproject.toml
87
+
88
+ - name: Install build frontend
89
+ run: python -m pip install -e ".[dev]"
90
+
91
+ - name: Build source and wheel distributions
92
+ run: python -m build
93
+
94
+ - name: Store distribution packages
95
+ uses: actions/upload-artifact@v5
96
+ with:
97
+ name: python-package-distributions
98
+ path: dist/
99
+
100
+ github-release:
101
+ name: Publish GitHub release
102
+ runs-on: ubuntu-latest
103
+ needs:
104
+ - build
105
+ permissions:
106
+ actions: read
107
+ contents: write
108
+ steps:
109
+ - name: Check out repository
110
+ uses: actions/checkout@v7
111
+ with:
112
+ persist-credentials: false
113
+
114
+ - name: Download distributions
115
+ uses: actions/download-artifact@v6
116
+ with:
117
+ name: python-package-distributions
118
+ path: dist/
119
+
120
+ - name: Create release from tag
121
+ run: gh release create "$GITHUB_REF_NAME" dist/* --verify-tag --notes-file .github/release-notes.md
122
+ env:
123
+ GH_TOKEN: ${{ github.token }}
124
+
125
+ pypi-publish:
126
+ name: Publish to PyPI
127
+ runs-on: ubuntu-latest
128
+ needs:
129
+ - build
130
+ environment:
131
+ name: pypi
132
+ url: https://pypi.org/p/erambactl
133
+ permissions:
134
+ actions: read
135
+ id-token: write
136
+ steps:
137
+ - name: Download distributions
138
+ uses: actions/download-artifact@v6
139
+ with:
140
+ name: python-package-distributions
141
+ path: dist/
142
+
143
+ - name: Publish distributions to PyPI
144
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,482 @@
1
+ Metadata-Version: 2.5
2
+ Name: erambactl
3
+ Version: 0.1.0
4
+ Summary: CLI and Python client for eramba API.
5
+ Project-URL: Repository, https://github.com/seifreed/erambactl
6
+ Author: Marc Rivero
7
+ License-Expression: MIT
8
+ Keywords: api,cli,compliance,eramba,grc
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Utilities
18
+ Requires-Python: ==3.14.*
19
+ Provides-Extra: dev
20
+ Requires-Dist: bandit==1.9.4; extra == 'dev'
21
+ Requires-Dist: black==26.5.1; extra == 'dev'
22
+ Requires-Dist: build==1.6.1; extra == 'dev'
23
+ Requires-Dist: hatchling==1.32.0; extra == 'dev'
24
+ Requires-Dist: mypy==2.3.1; extra == 'dev'
25
+ Requires-Dist: pip-audit==2.10.1; extra == 'dev'
26
+ Requires-Dist: pytest-cov==7.1.0; extra == 'dev'
27
+ Requires-Dist: pytest==9.1.1; extra == 'dev'
28
+ Requires-Dist: ruff==0.16.7; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ <p align="center">
32
+ <img src="https://img.shields.io/badge/erambactl-eramba%20API%20CLI-blue?style=for-the-badge" alt="erambactl">
33
+ </p>
34
+
35
+ <h1 align="center">erambactl</h1>
36
+
37
+ <p align="center">
38
+ <strong>Command-line access to eramba's API, with multi-instance support</strong>
39
+ </p>
40
+
41
+ <p align="center">
42
+ <a href="https://pypi.org/project/erambactl/"><img src="https://img.shields.io/pypi/v/erambactl?style=flat-square&logo=pypi&logoColor=white" alt="PyPI Version"></a>
43
+ <a href="https://pypi.org/project/erambactl/"><img src="https://img.shields.io/pypi/pyversions/erambactl?style=flat-square&logo=python&logoColor=white" alt="Python Versions"></a>
44
+ <a href="https://github.com/seifreed/erambactl/blob/main/pyproject.toml"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License"></a>
45
+ <a href="https://github.com/seifreed/erambactl/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/seifreed/erambactl/ci.yml?style=flat-square&logo=github&label=CI" alt="CI Status"></a>
46
+ <a href="https://github.com/seifreed/erambactl"><img src="https://img.shields.io/badge/runtime%20deps-none-brightgreen?style=flat-square" alt="Runtime Dependencies"></a>
47
+ <a href="https://github.com/seifreed/erambactl"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square" alt="Coverage"></a>
48
+ </p>
49
+
50
+ <p align="center">
51
+ <a href="https://github.com/seifreed/erambactl/stargazers"><img src="https://img.shields.io/github/stars/seifreed/erambactl?style=flat-square" alt="GitHub Stars"></a>
52
+ <a href="https://github.com/seifreed/erambactl/issues"><img src="https://img.shields.io/github/issues/seifreed/erambactl?style=flat-square" alt="GitHub Issues"></a>
53
+ <a href="https://buymeacoffee.com/seifreed"><img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-yellow?style=flat-square&logo=buy-me-a-coffee&logoColor=white" alt="Buy Me a Coffee"></a>
54
+ </p>
55
+
56
+ ---
57
+
58
+ ## Overview
59
+
60
+ **erambactl** is a Python 3.14 command-line tool and library for automating
61
+ eramba through its HTTP API. It ships with a checked-in catalog of eramba API
62
+ routes, including API v2, and does not depend on OpenAPI at runtime.
63
+
64
+ Use it against one eramba instance, or run the same command across several
65
+ configured instances for lab work, regression checks, and repeatable admin
66
+ tasks.
67
+
68
+ ### Key Features
69
+
70
+ | Feature | Description |
71
+ |---------|-------------|
72
+ | **Route Commands** | One CLI command per checked-in eramba route catalog entry |
73
+ | **API v2 Catalog** | 209 `api-v2` commands with documented methods, paths, and flags |
74
+ | **Full API Catalog** | 1592 total commands across legacy `api` and `api-v2` groups |
75
+ | **No Runtime OpenAPI** | Commands use the local catalog, not a live OpenAPI schema |
76
+ | **Multi-instance** | Run login, API, seed, smoke, and real CLI checks against one or all instances |
77
+ | **Auth Modes** | Bearer token, web session login, Cookie support, and HTTP Basic header mode |
78
+ | **Payload Support** | Query params, JSON bodies, raw files, forms, uploads, headers, and dry-run |
79
+ | **Local Lab** | Two-instance Docker lab based on eramba's official Docker deployment |
80
+ | **CLI + Library** | Use it from a shell or import it as a Python package |
81
+
82
+ ### What It Covers
83
+
84
+ ```text
85
+ Commands api, api-v2, login, commands
86
+ Inputs path params, query params, JSON, files, forms, uploads
87
+ Auth bearer, session login, basic, cookie
88
+ Instances single instance, named instance, all instances
89
+ Checks smoke checks, real CLI checks, route catalog checks
90
+ Packaging wheel build and installed-console-script verification
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Installation
96
+
97
+ ### From PyPI
98
+
99
+ ```bash
100
+ pip install erambactl
101
+ ```
102
+
103
+ ### From Source
104
+
105
+ ```bash
106
+ git clone https://github.com/seifreed/erambactl.git
107
+ cd erambactl
108
+ python3.14 -m venv venv
109
+ source venv/bin/activate # Windows: venv\Scripts\activate
110
+ python -m pip install -e ".[dev]"
111
+ ```
112
+
113
+ ### Optional Extras
114
+
115
+ The regular package has no runtime Python dependencies. Development tooling is
116
+ defined in the same `pyproject.toml` dependency file:
117
+
118
+ ```bash
119
+ python -m pip install -e ".[dev]"
120
+ ```
121
+
122
+ ### Build a Wheel
123
+
124
+ ```bash
125
+ python -m pip wheel . --wheel-dir dist
126
+ PYTHON=python3.14 scripts/eramba-package-check
127
+ ```
128
+
129
+ ```bat
130
+ scripts\eramba-package-check.cmd
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Quick Start
136
+
137
+ ```bash
138
+ # List API v2 commands
139
+ erambactl commands --group api-v2
140
+
141
+ # Run an API v2 command against one instance
142
+ erambactl --config examples/instances.json --instance local-a api-v2 get-assets-index
143
+
144
+ # Run a command across all configured instances
145
+ erambactl --config examples/instances.json --all-instances api get-assets-index
146
+
147
+ # Send query params and eramba's dry-run header
148
+ erambactl --config examples/instances.json --instance local-a api get-assets-bulk-update-get --query "ids[]=1" --dry-run
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Usage
154
+
155
+ ### Command Line Interface
156
+
157
+ ```bash
158
+ # Bearer token auth
159
+ erambactl --base-url https://localhost:8443 --token "$ERAMBA_TOKEN" api-v2 get-assets-index
160
+
161
+ # Session login
162
+ erambactl --base-url https://localhost:8443 --username "$ERAMBA_USER" --password "$ERAMBA_PASS" login
163
+
164
+ # Cookie auth
165
+ erambactl --base-url https://localhost:8443 --cookie "$ERAMBA_COOKIE" --timeout 5 api-v2 get-settings-version
166
+
167
+ # JSON body from a file
168
+ erambactl --config examples/instances.json --instance local-a api-v2 put-assets-edit-id --id 1 --data-file asset.json
169
+
170
+ # Multipart form upload
171
+ erambactl --config examples/instances.json --instance local-a api post-attachments-store-form-create Assets file --form name=Evidence --file attachment=evidence.pdf
172
+ ```
173
+
174
+ ### Commands
175
+
176
+ | Command | Description |
177
+ |---------|-------------|
178
+ | `erambactl login` | Authenticate and print the session result |
179
+ | `erambactl api <command>` | Run an eramba API command |
180
+ | `erambactl api-v2 <command>` | Run an eramba API v2 command |
181
+ | `erambactl commands` | Print or filter the static command catalog |
182
+ | `erambactl-route-data` | Parse Laravel routes and verify the route catalog |
183
+ | `erambactl-seed` | Execute JSON seed fixtures against eramba |
184
+ | `erambactl-smoke` | Probe command catalogs against real eramba instances |
185
+ | `erambactl-real-cli-check` | Run the real CLI parser/request path command by command |
186
+
187
+ ### Request Flags
188
+
189
+ | Option | Description |
190
+ |--------|-------------|
191
+ | `--query name=value` | Add query parameters |
192
+ | `--data <json>` | Send a JSON request body |
193
+ | `--data-file <file>` | Read a JSON or raw request body from disk |
194
+ | `--form name=value` | Add multipart form fields |
195
+ | `--file field=path` | Upload files in multipart requests |
196
+ | `--header name=value` | Add custom HTTP headers |
197
+ | `--dry-run` | Send eramba's Swagger dry-run header |
198
+
199
+ Path parameters can be passed positionally or with endpoint-specific flags such
200
+ as `--id`. API v2 commands with a request body accept the generic payload flags
201
+ above; commands with known body fields can also build JSON from field flags.
202
+
203
+ ### API v2 Coverage
204
+
205
+ ```text
206
+ API v2 commands 209
207
+ Methods DELETE 1, GET 177, POST 11, PUT 20
208
+ Commands with path parameters 39
209
+ Commands accepting a request body 32
210
+ Body command specs covered 32
211
+ Body commands with payload field flags 28
212
+ Body action commands without fields 4
213
+ ```
214
+
215
+ See [docs/api-v2-commands.md](docs/api-v2-commands.md) for the generated API v2
216
+ command reference.
217
+
218
+ ---
219
+
220
+ ## Local eramba Lab
221
+
222
+ The repository includes a two-instance lab for testing multi-instance runs:
223
+
224
+ ```text
225
+ local-a https://localhost:8443
226
+ local-b https://localhost:9443
227
+ ```
228
+
229
+ ```bash
230
+ scripts/eramba-lab up
231
+ scripts/eramba-lab bootstrap
232
+ scripts/eramba-lab ps
233
+ scripts/eramba-lab down
234
+ ```
235
+
236
+ ```bat
237
+ scripts\eramba-lab.cmd up
238
+ scripts\eramba-lab.cmd bootstrap
239
+ scripts\eramba-lab.cmd ps
240
+ scripts\eramba-lab.cmd down
241
+ ```
242
+
243
+ The lab uses `https://github.com/eramba/docker` as the upstream source. The
244
+ project overrides bind public ports to `127.0.0.1` and pin eramba lab images by
245
+ digest.
246
+
247
+ ---
248
+
249
+ ## Seed and Smoke Checks
250
+
251
+ ### Seed Data
252
+
253
+ ```bash
254
+ ERAMBA_A_PASSWORD=admin ERAMBA_B_PASSWORD=admin scripts/eramba-seed-data --all-instances
255
+ erambactl-seed --config examples/instances.json --fixture examples/seed-data.json --all-instances
256
+ ```
257
+
258
+ ```bat
259
+ scripts\eramba-seed-data.cmd --all-instances
260
+ ```
261
+
262
+ Seed fixtures are JSON command lists executed through the real erambactl client
263
+ against one or every configured eramba instance. No mock clients, no OpenAPI.
264
+
265
+ ### Smoke Checks
266
+
267
+ ```bash
268
+ ERAMBA_A_PASSWORD=admin scripts/eramba-api-smoke --instance local-a --limit 25
269
+ ERAMBA_B_PASSWORD=admin scripts/eramba-api-smoke --instance local-b --limit 25
270
+ ERAMBA_A_PASSWORD=admin ERAMBA_B_PASSWORD=admin erambactl-smoke --all-instances --all --group api-v2 --summary-only
271
+ ERAMBA_A_PASSWORD=admin ERAMBA_B_PASSWORD=admin scripts/eramba-api-v2-smoke
272
+ ERAMBA_A_PASSWORD=admin ERAMBA_B_PASSWORD=admin scripts/eramba-real-api-check
273
+ ```
274
+
275
+ ```bat
276
+ scripts\eramba-api-smoke.cmd --instance local-a --limit 25
277
+ scripts\eramba-api-v2-smoke.cmd
278
+ scripts\eramba-real-api-check.cmd
279
+ ```
280
+
281
+ `erambactl-smoke` reports JSON, binary responses, HTTP errors, route 404s, and
282
+ transport failures. Use `--offset`, `--limit`, `--method`, `--resource`,
283
+ `--group`, `--path-value`, `--skip-method`, and `--summary-only` for batching.
284
+
285
+ ### Real CLI Checks
286
+
287
+ ```bash
288
+ ERAMBA_A_PASSWORD=admin ERAMBA_B_PASSWORD=admin scripts/eramba-real-api-check
289
+ ERAMBA_A_PASSWORD=admin ERAMBA_B_PASSWORD=admin scripts/eramba-real-cli-check --all-instances --group api-v2 --dry-run --path-value id=0
290
+ ```
291
+
292
+ ```bat
293
+ scripts\eramba-real-api-check.cmd
294
+ scripts\eramba-real-cli-check.cmd --all-instances --group api-v2 --dry-run --path-value id=0
295
+ ```
296
+
297
+ `erambactl-real-cli-check` runs the real CLI parser and request path against
298
+ configured eramba instances. See [docs/api-v2-smoke.md](docs/api-v2-smoke.md)
299
+ and [docs/real-api-check.md](docs/real-api-check.md) for lab evidence.
300
+
301
+ ---
302
+
303
+ ## Route Catalog Maintenance
304
+
305
+ ```bash
306
+ docker cp erambactl-a-eramba:/var/www/eramba/laravel/routes/api.php /tmp/eramba-api.php
307
+ erambactl-route-data /tmp/eramba-api.php
308
+ erambactl-route-data /tmp/eramba-api.php --print > erambactl/route_data.py
309
+ ```
310
+
311
+ `erambactl-route-data` parses eramba's Laravel routes directly and verifies the
312
+ static catalog command by command. It does not use OpenAPI.
313
+
314
+ ---
315
+
316
+ ## Python Library
317
+
318
+ ### Basic Usage
319
+
320
+ ```python
321
+ from erambactl import ErambaClient, ErambaInstance, get_command
322
+
323
+ client = ErambaClient(
324
+ ErambaInstance(
325
+ name="local-a",
326
+ base_url="https://localhost:8443",
327
+ username="admin",
328
+ password="admin",
329
+ verify_tls=False,
330
+ timeout=5,
331
+ )
332
+ )
333
+
334
+ assets = client.request("GET", "/laravel/api/assets/index")
335
+ assets_v2 = client.run(get_command("get-assets-index", group="api-v2"))
336
+ ```
337
+
338
+ ### Multi-instance Usage
339
+
340
+ ```python
341
+ from erambactl import ErambaFleet, ErambaInstance, get_command
342
+
343
+ fleet = ErambaFleet(
344
+ (
345
+ ErambaInstance(
346
+ name="local-a",
347
+ base_url="https://localhost:8443",
348
+ username="admin",
349
+ password="admin",
350
+ verify_tls=False,
351
+ timeout=5,
352
+ ),
353
+ ErambaInstance(
354
+ name="local-b",
355
+ base_url="https://localhost:9443",
356
+ username="admin",
357
+ password="admin",
358
+ verify_tls=False,
359
+ timeout=5,
360
+ ),
361
+ )
362
+ )
363
+
364
+ command = get_command("get-assets-index", group="api-v2")
365
+ assets = fleet.run("local-a", command)
366
+ all_assets = fleet.run_all(command)
367
+ ```
368
+
369
+ ### File Uploads
370
+
371
+ ```python
372
+ from pathlib import Path
373
+
374
+ from erambactl import ErambaClient, ErambaInstance, UploadFile
375
+
376
+ client = ErambaClient(
377
+ ErambaInstance(
378
+ name="local-a",
379
+ base_url="https://localhost:8443",
380
+ token="token",
381
+ verify_tls=False,
382
+ )
383
+ )
384
+
385
+ client.request(
386
+ "POST",
387
+ "/laravel/api/attachments/form-add/Assets/file",
388
+ form={"name": "Evidence"},
389
+ files=(UploadFile("attachment", Path("evidence.pdf")),),
390
+ )
391
+ ```
392
+
393
+ ---
394
+
395
+ ## CI
396
+
397
+ The project CI runs on Ubuntu, Windows, and macOS with Python 3.14:
398
+
399
+ ```bash
400
+ black --check .
401
+ ruff check .
402
+ mypy .
403
+ bandit -r .
404
+ pip-audit .
405
+ pytest -q
406
+ scripts/eramba-package-check
407
+ ```
408
+
409
+ The test suite is configured to fail below 100% coverage.
410
+
411
+ ---
412
+
413
+ ## Releases
414
+
415
+ Tagged releases build a source distribution and wheel, create a GitHub Release,
416
+ and publish to PyPI with Trusted Publishing/OIDC:
417
+
418
+ ```bash
419
+ git tag v0.1.0
420
+ git push origin v0.1.0
421
+ ```
422
+
423
+ Configure the PyPI trusted publisher with:
424
+
425
+ ```text
426
+ Project name: erambactl
427
+ Owner: seifreed
428
+ Repository: erambactl
429
+ Workflow: release.yml
430
+ Environment: pypi
431
+ ```
432
+
433
+ The release workflow does not use a PyPI API token.
434
+
435
+ ---
436
+
437
+ ## Requirements
438
+
439
+ - Python 3.14 exactly
440
+ - Windows, Linux, and macOS support
441
+ - No runtime Python dependencies
442
+ - Docker, when using the local eramba lab
443
+ - See [pyproject.toml](pyproject.toml) for development tooling
444
+
445
+ ---
446
+
447
+ ## Contributing
448
+
449
+ Contributions are welcome.
450
+
451
+ 1. Fork the repository
452
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
453
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
454
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
455
+ 5. Open a Pull Request
456
+
457
+ ---
458
+
459
+ ## Support the Project
460
+
461
+ If this project is useful in your workflows, you can support development:
462
+
463
+ <a href="https://buymeacoffee.com/seifreed" target="_blank">
464
+ <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50">
465
+ </a>
466
+
467
+ ---
468
+
469
+ ## License
470
+
471
+ This project is licensed under the MIT license. See [pyproject.toml](pyproject.toml).
472
+
473
+ **Attribution**
474
+
475
+ - Author: **Marc Rivero** | [@seifreed](https://github.com/seifreed)
476
+ - Repository: [github.com/seifreed/erambactl](https://github.com/seifreed/erambactl)
477
+
478
+ ---
479
+
480
+ <p align="center">
481
+ <sub>Made for eramba API checks, lab setup, and day-to-day automation</sub>
482
+ </p>