opennms-api-wrapper 0.2.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 (76) hide show
  1. opennms_api_wrapper-0.2.0/CHANGELOG.md +54 -0
  2. opennms_api_wrapper-0.2.0/CLAUDE.md +149 -0
  3. opennms_api_wrapper-0.2.0/LICENSE +21 -0
  4. opennms_api_wrapper-0.2.0/MANIFEST.in +2 -0
  5. opennms_api_wrapper-0.2.0/PKG-INFO +232 -0
  6. opennms_api_wrapper-0.2.0/README.md +176 -0
  7. opennms_api_wrapper-0.2.0/opennms_api_wrapper/__init__.py +10 -0
  8. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_acks.py +52 -0
  9. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_alarm_history.py +30 -0
  10. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_alarm_stats.py +24 -0
  11. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_alarms.py +130 -0
  12. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_base.py +104 -0
  13. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_business_services.py +42 -0
  14. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_categories.py +73 -0
  15. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_device_config.py +102 -0
  16. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_discovery.py +48 -0
  17. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_events.py +83 -0
  18. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_flows.py +235 -0
  19. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_foreign_sources.py +123 -0
  20. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_graphs.py +65 -0
  21. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_groups.py +69 -0
  22. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_heatmap.py +63 -0
  23. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_info.py +12 -0
  24. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_ipinterfaces_v2.py +22 -0
  25. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_ksc_reports.py +49 -0
  26. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_maps.py +36 -0
  27. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_measurements.py +75 -0
  28. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_metadata.py +207 -0
  29. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_nodes.py +301 -0
  30. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_notifications.py +35 -0
  31. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_outages.py +35 -0
  32. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_requisitions.py +249 -0
  33. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_resources.py +66 -0
  34. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_sched_outages.py +81 -0
  35. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_situations.py +81 -0
  36. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_snmp_config.py +31 -0
  37. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_snmpinterfaces_v2.py +22 -0
  38. opennms_api_wrapper-0.2.0/opennms_api_wrapper/_users.py +53 -0
  39. opennms_api_wrapper-0.2.0/opennms_api_wrapper/client.py +122 -0
  40. opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/PKG-INFO +232 -0
  41. opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/SOURCES.txt +74 -0
  42. opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/dependency_links.txt +1 -0
  43. opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/requires.txt +5 -0
  44. opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/top_level.txt +1 -0
  45. opennms_api_wrapper-0.2.0/pyproject.toml +51 -0
  46. opennms_api_wrapper-0.2.0/setup.cfg +4 -0
  47. opennms_api_wrapper-0.2.0/tests/test_acks.py +86 -0
  48. opennms_api_wrapper-0.2.0/tests/test_alarm_history.py +44 -0
  49. opennms_api_wrapper-0.2.0/tests/test_alarm_stats.py +36 -0
  50. opennms_api_wrapper-0.2.0/tests/test_alarms.py +147 -0
  51. opennms_api_wrapper-0.2.0/tests/test_business_services.py +65 -0
  52. opennms_api_wrapper-0.2.0/tests/test_categories.py +103 -0
  53. opennms_api_wrapper-0.2.0/tests/test_device_config.py +127 -0
  54. opennms_api_wrapper-0.2.0/tests/test_discovery.py +63 -0
  55. opennms_api_wrapper-0.2.0/tests/test_events.py +92 -0
  56. opennms_api_wrapper-0.2.0/tests/test_flows.py +139 -0
  57. opennms_api_wrapper-0.2.0/tests/test_foreign_sources.py +149 -0
  58. opennms_api_wrapper-0.2.0/tests/test_graphs.py +72 -0
  59. opennms_api_wrapper-0.2.0/tests/test_groups.py +95 -0
  60. opennms_api_wrapper-0.2.0/tests/test_heatmap.py +94 -0
  61. opennms_api_wrapper-0.2.0/tests/test_info.py +18 -0
  62. opennms_api_wrapper-0.2.0/tests/test_ipinterfaces_v2.py +53 -0
  63. opennms_api_wrapper-0.2.0/tests/test_ksc_reports.py +48 -0
  64. opennms_api_wrapper-0.2.0/tests/test_maps.py +56 -0
  65. opennms_api_wrapper-0.2.0/tests/test_measurements.py +87 -0
  66. opennms_api_wrapper-0.2.0/tests/test_metadata.py +223 -0
  67. opennms_api_wrapper-0.2.0/tests/test_nodes.py +355 -0
  68. opennms_api_wrapper-0.2.0/tests/test_notifications.py +50 -0
  69. opennms_api_wrapper-0.2.0/tests/test_outages.py +49 -0
  70. opennms_api_wrapper-0.2.0/tests/test_requisitions.py +294 -0
  71. opennms_api_wrapper-0.2.0/tests/test_resources.py +58 -0
  72. opennms_api_wrapper-0.2.0/tests/test_sched_outages.py +113 -0
  73. opennms_api_wrapper-0.2.0/tests/test_situations.py +123 -0
  74. opennms_api_wrapper-0.2.0/tests/test_snmp_config.py +54 -0
  75. opennms_api_wrapper-0.2.0/tests/test_snmpinterfaces_v2.py +54 -0
  76. opennms_api_wrapper-0.2.0/tests/test_users.py +76 -0
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-03-07
9
+
10
+ ### Fixed
11
+
12
+ - Accept header now includes `text/plain;q=0.9` to prevent 406 errors on
13
+ `/count` endpoints in some OpenNMS versions.
14
+ - `get_node_count()` uses the v2 API (`GET /api/v2/nodes?limit=1`) and
15
+ extracts `totalCount`. The v1 `/rest/nodes` endpoint does not expose a
16
+ `/count` sub-resource.
17
+
18
+ ### Changed
19
+
20
+ - Smoke test: endpoints that depend on optional plugins (alarm history,
21
+ hardware inventory, flows, situations) or heavy queries (resources) now
22
+ report as WARN instead of FAIL. Each warning cites the required plugin
23
+ or feature.
24
+ - Smoke test: events query filters by lowest-ID node to avoid full table
25
+ scans on large databases.
26
+
27
+ ### Added
28
+
29
+ - Smoke test: `--skip` flag to skip tests by label prefix (e.g.,
30
+ `--skip get_flow` skips all flow tests).
31
+ - Smoke test: `OPENNMS_TIMEOUT` env var (default 60 seconds).
32
+ - Validated against OpenNMS Meridian 2024.3.0 (65 passed, 0 failed).
33
+
34
+ ## [0.1.0] - 2026-03-06
35
+
36
+ ### Added
37
+
38
+ - Initial release covering all OpenNMS Horizon 35 REST API endpoints (v1
39
+ and v2).
40
+ - Single `OpenNMS` client class importable as `import opennms_api_wrapper as
41
+ opennms`.
42
+ - JSON-only request/response handling throughout; no XML dependency.
43
+ - Synchronous, dependency-minimal design (only `requests` required at
44
+ runtime).
45
+ - 290-test suite with full method coverage; HTTP mocked at the adapter level
46
+ using the `responses` library — no live server required to run tests.
47
+ - Resource groups covered: alarms, alarm statistics, alarm history, events,
48
+ nodes (with IP interfaces, SNMP interfaces, monitored services, categories,
49
+ assets, and hardware inventory), outages, notifications, acknowledgements,
50
+ requisitions, foreign sources, SNMP configuration, groups, users,
51
+ categories, scheduled outages, KSC reports, resources, measurements,
52
+ heatmap, maps, topology graphs, flows, device configuration, situations
53
+ (v2), business services (v2), metadata (v2), server info, discovery (v2),
54
+ and global IP/SNMP interface views (v2).
@@ -0,0 +1,149 @@
1
+ # CLAUDE.md — opennms-api-wrapper
2
+
3
+ This file gives Claude Code the context needed to work on this project
4
+ without prior conversation history.
5
+
6
+ ## Project purpose
7
+
8
+ A thin, synchronous Python 3 wrapper for the OpenNMS REST API (Horizon 35).
9
+ Users `import opennms_api_wrapper as opennms` and get a single `OpenNMS`
10
+ client class with one method per API endpoint.
11
+
12
+ ## Repository layout
13
+
14
+ ```
15
+ opennms_api_wrapper/ # installable package
16
+ __init__.py # exports OpenNMS, __version__
17
+ client.py # OpenNMS class (combines all mixins)
18
+ _base.py # _OpenNMSBase: HTTP helpers (_get/_post/_put/_delete/_parse)
19
+ _alarms.py # AlarmsMixin
20
+ _alarm_stats.py # AlarmStatsMixin
21
+ _alarm_history.py # AlarmHistoryMixin
22
+ _events.py # EventsMixin
23
+ _nodes.py # NodesMixin (largest: nodes + sub-resources)
24
+ _outages.py # OutagesMixin
25
+ _notifications.py # NotificationsMixin
26
+ _acks.py # AcksMixin
27
+ _requisitions.py # RequisitionsMixin
28
+ _foreign_sources.py # ForeignSourcesMixin
29
+ _snmp_config.py # SnmpConfigMixin
30
+ _groups.py # GroupsMixin
31
+ _users.py # UsersMixin
32
+ _categories.py # CategoriesMixin
33
+ _sched_outages.py # SchedOutagesMixin
34
+ _ksc_reports.py # KscReportsMixin
35
+ _resources.py # ResourcesMixin
36
+ _measurements.py # MeasurementsMixin
37
+ _heatmap.py # HeatmapMixin
38
+ _maps.py # MapsMixin
39
+ _graphs.py # GraphsMixin
40
+ _flows.py # FlowsMixin
41
+ _device_config.py # DeviceConfigMixin
42
+ _situations.py # SituationsMixin (v2)
43
+ _business_services.py # BusinessServicesMixin (v2)
44
+ _metadata.py # MetadataMixin (v2, largest: node/iface/service metadata)
45
+ _info.py # InfoMixin
46
+ _discovery.py # DiscoveryMixin (v2)
47
+ _ipinterfaces_v2.py # IpInterfacesV2Mixin
48
+ _snmpinterfaces_v2.py # SnmpInterfacesV2Mixin
49
+
50
+ tests/
51
+ conftest.py # client fixture, V1/V2 URL constants, qs() helper
52
+ fixtures.py # all accurate OpenNMS Horizon 35 response shapes
53
+ test_*.py # one file per mixin (30 files, 290 tests total)
54
+
55
+ dist/ # built artifacts (gitignored)
56
+ pyproject.toml # build config + project metadata
57
+ smoke_test.py # live-server smoke test (read-only + --write mode)
58
+ # python smoke_test.py # read-only, safe for any server
59
+ # python smoke_test.py --write # write ops, prompts for confirmation
60
+ # python smoke_test.py --write --yes # skip prompt (CI only)
61
+ # python smoke_test.py --no-color # plain output for log files
62
+ # python smoke_test.py --skip get_flow # skip by label prefix
63
+ # env vars: OPENNMS_URL, OPENNMS_USER, OPENNMS_PASSWORD,
64
+ # OPENNMS_VERIFY_SSL, OPENNMS_TIMEOUT
65
+ ARCHITECTURE.md # architecture decision records (ADRs)
66
+ MERMAID.md # Mermaid architecture diagrams
67
+ CHANGELOG.md
68
+ README.md
69
+ CONTRIBUTING.md
70
+ ```
71
+
72
+ ## Architecture decisions (do not change without good reason)
73
+
74
+ - **Mixin pattern**: each resource group lives in its own `_<name>.py` mixin.
75
+ `client.py` combines them all via multiple inheritance into `OpenNMS`.
76
+ - **JSON only**: all request bodies are JSON. No XML anywhere.
77
+ The one exception: `POST /rest/acks` uses `application/x-www-form-urlencoded`
78
+ because the OpenNMS API requires it — handled via `form_data=` in `_post`.
79
+ - **Synchronous only**: no async. `requests.Session` is used throughout.
80
+ One runtime dependency: `requests>=2.28`.
81
+ - **v1 vs v2**: v1 endpoints live at `/opennms/rest/`, v2 at
82
+ `/opennms/api/v2/`. Every `_get/_post/_put/_delete` accepts `v2=True`.
83
+ - **Accept header**: `application/json, text/plain;q=0.9`. Some OpenNMS
84
+ versions return 406 if the Accept header does not include `text/plain` for
85
+ `/count` endpoints. JSON stays preferred via implicit q=1.0.
86
+ - **`_parse()`** handles three response types:
87
+ - `application/json` → `resp.json()`
88
+ - `text/plain` → `int(text)` if possible, else `str`
89
+ - empty body (204 No Content) → `None`
90
+ - **Node count via v2**: `get_node_count()` uses `GET /api/v2/nodes?limit=1`
91
+ and extracts `totalCount`. The v1 `/rest/nodes` endpoint does not have a
92
+ `/count` sub-resource — it routes all sub-paths as node criteria.
93
+ - **Timeout**: `_OpenNMSBase.__init__` accepts `timeout=30` (seconds). Passed
94
+ to every `_session.get/post/put/delete` call. `OpenNMS.__init__` exposes it
95
+ as a public parameter.
96
+ - **Smoke test warn level**: endpoints that depend on optional plugins or
97
+ heavy server-side queries use `warn()` instead of `run()`. Warnings are
98
+ non-fatal and include the required plugin/feature name. Only hard `FAIL`s
99
+ cause a non-zero exit code.
100
+
101
+ ## Development environment
102
+
103
+ ```bash
104
+ python3 -m venv .venv
105
+ source .venv/bin/activate
106
+ pip install -e ".[dev]" # installs requests + pytest + responses
107
+ pytest tests/ -v # run full suite (290 tests, ~0.2 s)
108
+ ```
109
+
110
+ Always activate the `.venv` before running any commands — never rely on the
111
+ system Python or system pip.
112
+
113
+ ## Test conventions
114
+
115
+ - HTTP mocking: `responses` library with `@responses.activate` decorator.
116
+ - `conftest.py` constants:
117
+ - `V1 = "http://opennms:8980/opennms/rest"`
118
+ - `V2 = "http://opennms:8980/opennms/api/v2"`
119
+ - `qs(url)` parses query params from a URL into a dict of lists.
120
+ - Fixture shapes in `tests/fixtures.py` mirror real OpenNMS Horizon 35
121
+ responses (singular resource name as list wrapper key, plus `totalCount`,
122
+ `count`, `offset`).
123
+ - **URL encoding gotcha**: `requests` percent-encodes spaces in URL path
124
+ segments as `%20`, not `+`. Mock URLs for paths with spaces must use `%20`
125
+ explicitly, e.g. `Do%20Not%20Persist%20Discovered%20IPs`.
126
+ - 204 responses return `None`; plain-text count endpoints return `int`.
127
+ - Verify request bodies with `json.loads(responses.calls[0].request.body)`.
128
+
129
+ ## Build / release
130
+
131
+ ```bash
132
+ pip install build
133
+ python -m build # produces dist/*.tar.gz and dist/*.whl
134
+ pip install twine
135
+ twine upload dist/* # publish to PyPI
136
+ ```
137
+
138
+ The build backend is `setuptools.build_meta` (in `pyproject.toml`).
139
+ The older path `setuptools.backends.legacy:build` does not work — do not use it.
140
+
141
+ ## Style
142
+
143
+ - PEP 8 throughout: 79-character line limit, 4-space indentation.
144
+ - Every public method has a Google-style docstring with `Args:` and `Returns:`
145
+ sections where non-trivial — required for autodoc compatibility (Sphinx,
146
+ pdoc, mkdocstrings). Private helpers have at minimum a one-line docstring.
147
+ - No inline comments on code that is self-evident.
148
+ - No error handling for scenarios that cannot happen.
149
+ - No abstractions introduced for one-off operations.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Richard "Chance" Newkirk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include CHANGELOG.md
2
+ include CLAUDE.md
@@ -0,0 +1,232 @@
1
+ Metadata-Version: 2.4
2
+ Name: opennms-api-wrapper
3
+ Version: 0.2.0
4
+ Summary: A thin Python wrapper for the OpenNMS REST API (Horizon 35)
5
+ Author-email: "Richard \"Chance\" Newkirk" <chance.newkirk+github@pm.me>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Richard "Chance" Newkirk
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/cnewkirk/opennms-api-wrapper
29
+ Project-URL: Repository, https://github.com/cnewkirk/opennms-api-wrapper
30
+ Project-URL: Bug Tracker, https://github.com/cnewkirk/opennms-api-wrapper/issues
31
+ Project-URL: Changelog, https://github.com/cnewkirk/opennms-api-wrapper/blob/main/CHANGELOG.md
32
+ Keywords: opennms,network-management,rest,api,wrapper,nms
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: System Administrators
36
+ Classifier: Intended Audience :: Telecommunications Industry
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Topic :: System :: Networking :: Monitoring
39
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
40
+ Classifier: Programming Language :: Python :: 3
41
+ Classifier: Programming Language :: Python :: 3.8
42
+ Classifier: Programming Language :: Python :: 3.9
43
+ Classifier: Programming Language :: Python :: 3.10
44
+ Classifier: Programming Language :: Python :: 3.11
45
+ Classifier: Programming Language :: Python :: 3.12
46
+ Classifier: Programming Language :: Python :: 3.13
47
+ Classifier: Operating System :: OS Independent
48
+ Requires-Python: >=3.8
49
+ Description-Content-Type: text/markdown
50
+ License-File: LICENSE
51
+ Requires-Dist: requests>=2.28
52
+ Provides-Extra: dev
53
+ Requires-Dist: pytest; extra == "dev"
54
+ Requires-Dist: responses; extra == "dev"
55
+ Dynamic: license-file
56
+
57
+ # opennms-api-wrapper
58
+
59
+ [![CI](https://github.com/cnewkirk/opennms-api-wrapper/actions/workflows/ci.yml/badge.svg)](https://github.com/cnewkirk/opennms-api-wrapper/actions/workflows/ci.yml)
60
+ [![GitHub release](https://img.shields.io/github/v/release/cnewkirk/opennms-api-wrapper)](https://github.com/cnewkirk/opennms-api-wrapper/releases)
61
+ [![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/)
62
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
63
+
64
+ A thin, dependency-minimal Python 3 wrapper for the
65
+ [OpenNMS](https://www.opennms.com/) REST API (Horizon 35+).
66
+ Validated against OpenNMS Meridian 2024.3.0 with a live-server smoke test
67
+ suite.
68
+
69
+ ## Features
70
+
71
+ - Covers every v1 (`/opennms/rest/`) and v2 (`/opennms/api/v2/`) endpoint
72
+ - JSON everywhere — no XML handling required
73
+ - Single runtime dependency: [`requests`](https://docs.python-requests.org/)
74
+ - Synchronous and straightforward — no async complexity
75
+ - 290-test suite with full method coverage (mocked HTTP — no live server required)
76
+ - Live-server smoke test validated against Meridian 2024.3.0
77
+
78
+ ## Installation
79
+
80
+ **From the GitHub release** (no clone required — recommended for most users):
81
+
82
+ ```bash
83
+ pip install https://github.com/cnewkirk/opennms-api-wrapper/archive/refs/tags/v0.2.0.tar.gz
84
+ ```
85
+
86
+ **From source** (clone first, then install):
87
+
88
+ ```bash
89
+ git clone https://github.com/cnewkirk/opennms-api-wrapper.git
90
+ cd opennms-api-wrapper
91
+ pip install .
92
+ ```
93
+
94
+ When the package is published to PyPI, installation will simplify to
95
+ `pip install opennms-api-wrapper`.
96
+
97
+ ## Quick start
98
+
99
+ ```python
100
+ import opennms_api_wrapper as opennms
101
+
102
+ client = opennms.OpenNMS(
103
+ url="https://opennms.example.com:8443",
104
+ username="admin",
105
+ password="admin",
106
+ )
107
+
108
+ # Server info
109
+ info = client.get_info()
110
+ print(info["displayVersion"])
111
+
112
+ # List alarms
113
+ alarms = client.get_alarms(limit=25, order_by="lastEventTime", order="desc")
114
+ for alarm in alarms["alarm"]:
115
+ print(alarm["id"], alarm["severity"], alarm["nodeLabel"])
116
+
117
+ # Acknowledge an alarm
118
+ client.ack_alarm(alarm_id=42)
119
+
120
+ # List alarms with FIQL filter (v2)
121
+ alarms = client.get_alarms_v2(fiql="severity==MAJOR")
122
+ ```
123
+
124
+ ## API coverage
125
+
126
+ | Resource group | Methods |
127
+ |---|---|
128
+ | Alarms (v1 + v2) | list, get, count, ack/unack/clear/escalate, bulk ops |
129
+ | Alarm statistics | stats, stats by severity |
130
+ | Alarm history | history, history at timestamp, state changes |
131
+ | Events | list, get, count, create, ack/unack, bulk ack/unack |
132
+ | Nodes | full CRUD + IP interfaces, SNMP interfaces, services, categories, assets, hardware |
133
+ | Outages | list, get, count, node outages |
134
+ | Notifications | list, get, count, trigger destination path |
135
+ | Acknowledgements | list, get, count, create, ack/unack notification |
136
+ | Requisitions | full CRUD including nodes, interfaces, services, categories, assets |
137
+ | Foreign sources | full CRUD including detectors and policies |
138
+ | SNMP configuration | get, set |
139
+ | Groups | full CRUD + user and category membership |
140
+ | Users | full CRUD + role assignment |
141
+ | Categories | full CRUD + node and group associations |
142
+ | Scheduled outages | full CRUD + daemon associations |
143
+ | KSC reports | list, get, count, create, update |
144
+ | Resources | list, get, get for node, select, delete |
145
+ | Measurements | single attribute (GET), multi-source (POST) |
146
+ | Heatmap | outages + alarms × categories / foreign sources / services / nodes |
147
+ | Maps | full CRUD + map elements |
148
+ | Topology graphs | containers, graph, graph view (POST), search suggestions, search results |
149
+ | Flows | count, exporters, applications, conversations, hosts |
150
+ | Device configuration | list, get, get by interface, latest, download, backup |
151
+ | Situations (v2) | list, create, add alarms, clear, accept, remove alarms |
152
+ | Business services (v2) | full CRUD |
153
+ | Metadata (v2) | full CRUD for node, interface, and service metadata |
154
+ | Server info | get |
155
+ | Discovery (v2) | submit scan configuration |
156
+ | IP interfaces (v2) | list with FIQL |
157
+ | SNMP interfaces (v2) | list with FIQL |
158
+
159
+ ## Authentication
160
+
161
+ Basic authentication is used. Pass `verify_ssl=False` to disable certificate
162
+ verification (useful for self-signed certs in lab environments):
163
+
164
+ ```python
165
+ client = opennms.OpenNMS(
166
+ url="https://opennms.example.com:8443",
167
+ username="admin",
168
+ password="admin",
169
+ verify_ssl=False,
170
+ )
171
+ ```
172
+
173
+ ## Smoke testing
174
+
175
+ `smoke_test.py` exercises the wrapper against a real OpenNMS server. It is
176
+ intended for use against a dev or staging instance before each release — not
177
+ as a substitute for the 290-test mocked unit suite.
178
+
179
+ Tests that depend on optional plugins or heavy endpoints are reported as
180
+ **WARN** (non-fatal) rather than FAIL. Each warning includes the specific
181
+ plugin or feature required.
182
+
183
+ **Read-only mode** (default) is safe to run against any server, including
184
+ production. It issues only GET requests and makes no changes.
185
+
186
+ ```bash
187
+ export OPENNMS_URL="https://opennms.example.com:8443"
188
+ export OPENNMS_USER="admin"
189
+ export OPENNMS_PASSWORD="secret"
190
+ export OPENNMS_VERIFY_SSL="false" # omit or set to "true" for valid certs
191
+ export OPENNMS_TIMEOUT="60" # per-request timeout in seconds (default 60)
192
+
193
+ python smoke_test.py
194
+ ```
195
+
196
+ **Write mode** creates and then deletes objects on the server (events,
197
+ categories, groups, requisitions, maps, etc.). It will prompt for explicit
198
+ confirmation and print the target URL before running a single write.
199
+ **Only use write mode against a dev or staging instance — never production.**
200
+
201
+ ```bash
202
+ python smoke_test.py --write # interactive prompt required
203
+ python smoke_test.py --write --yes # skip prompt (CI pipelines only)
204
+ python smoke_test.py --no-color # plain output for log files
205
+ python smoke_test.py --skip get_resources --skip get_flow # skip slow tests
206
+ ```
207
+
208
+ The `--skip` flag accepts a prefix — `--skip get_flow` skips all tests
209
+ whose label starts with `get_flow`.
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ git clone https://github.com/cnewkirk/opennms-api-wrapper.git
215
+ cd opennms-api-wrapper
216
+ python3 -m venv .venv
217
+ source .venv/bin/activate
218
+ pip install -e ".[dev]"
219
+ pytest tests/ -v
220
+ ```
221
+
222
+ ## Contributing
223
+
224
+ Bug reports and pull requests are welcome on GitHub at
225
+ https://github.com/cnewkirk/opennms-api-wrapper.
226
+
227
+ ## Acknowledgements
228
+
229
+ This library was designed and tested by a human, with implementation
230
+ assistance from [Claude Code](https://claude.ai/code) (Anthropic). All API
231
+ shapes are derived from the official OpenNMS Horizon 35 REST API
232
+ documentation.
@@ -0,0 +1,176 @@
1
+ # opennms-api-wrapper
2
+
3
+ [![CI](https://github.com/cnewkirk/opennms-api-wrapper/actions/workflows/ci.yml/badge.svg)](https://github.com/cnewkirk/opennms-api-wrapper/actions/workflows/ci.yml)
4
+ [![GitHub release](https://img.shields.io/github/v/release/cnewkirk/opennms-api-wrapper)](https://github.com/cnewkirk/opennms-api-wrapper/releases)
5
+ [![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ A thin, dependency-minimal Python 3 wrapper for the
9
+ [OpenNMS](https://www.opennms.com/) REST API (Horizon 35+).
10
+ Validated against OpenNMS Meridian 2024.3.0 with a live-server smoke test
11
+ suite.
12
+
13
+ ## Features
14
+
15
+ - Covers every v1 (`/opennms/rest/`) and v2 (`/opennms/api/v2/`) endpoint
16
+ - JSON everywhere — no XML handling required
17
+ - Single runtime dependency: [`requests`](https://docs.python-requests.org/)
18
+ - Synchronous and straightforward — no async complexity
19
+ - 290-test suite with full method coverage (mocked HTTP — no live server required)
20
+ - Live-server smoke test validated against Meridian 2024.3.0
21
+
22
+ ## Installation
23
+
24
+ **From the GitHub release** (no clone required — recommended for most users):
25
+
26
+ ```bash
27
+ pip install https://github.com/cnewkirk/opennms-api-wrapper/archive/refs/tags/v0.2.0.tar.gz
28
+ ```
29
+
30
+ **From source** (clone first, then install):
31
+
32
+ ```bash
33
+ git clone https://github.com/cnewkirk/opennms-api-wrapper.git
34
+ cd opennms-api-wrapper
35
+ pip install .
36
+ ```
37
+
38
+ When the package is published to PyPI, installation will simplify to
39
+ `pip install opennms-api-wrapper`.
40
+
41
+ ## Quick start
42
+
43
+ ```python
44
+ import opennms_api_wrapper as opennms
45
+
46
+ client = opennms.OpenNMS(
47
+ url="https://opennms.example.com:8443",
48
+ username="admin",
49
+ password="admin",
50
+ )
51
+
52
+ # Server info
53
+ info = client.get_info()
54
+ print(info["displayVersion"])
55
+
56
+ # List alarms
57
+ alarms = client.get_alarms(limit=25, order_by="lastEventTime", order="desc")
58
+ for alarm in alarms["alarm"]:
59
+ print(alarm["id"], alarm["severity"], alarm["nodeLabel"])
60
+
61
+ # Acknowledge an alarm
62
+ client.ack_alarm(alarm_id=42)
63
+
64
+ # List alarms with FIQL filter (v2)
65
+ alarms = client.get_alarms_v2(fiql="severity==MAJOR")
66
+ ```
67
+
68
+ ## API coverage
69
+
70
+ | Resource group | Methods |
71
+ |---|---|
72
+ | Alarms (v1 + v2) | list, get, count, ack/unack/clear/escalate, bulk ops |
73
+ | Alarm statistics | stats, stats by severity |
74
+ | Alarm history | history, history at timestamp, state changes |
75
+ | Events | list, get, count, create, ack/unack, bulk ack/unack |
76
+ | Nodes | full CRUD + IP interfaces, SNMP interfaces, services, categories, assets, hardware |
77
+ | Outages | list, get, count, node outages |
78
+ | Notifications | list, get, count, trigger destination path |
79
+ | Acknowledgements | list, get, count, create, ack/unack notification |
80
+ | Requisitions | full CRUD including nodes, interfaces, services, categories, assets |
81
+ | Foreign sources | full CRUD including detectors and policies |
82
+ | SNMP configuration | get, set |
83
+ | Groups | full CRUD + user and category membership |
84
+ | Users | full CRUD + role assignment |
85
+ | Categories | full CRUD + node and group associations |
86
+ | Scheduled outages | full CRUD + daemon associations |
87
+ | KSC reports | list, get, count, create, update |
88
+ | Resources | list, get, get for node, select, delete |
89
+ | Measurements | single attribute (GET), multi-source (POST) |
90
+ | Heatmap | outages + alarms × categories / foreign sources / services / nodes |
91
+ | Maps | full CRUD + map elements |
92
+ | Topology graphs | containers, graph, graph view (POST), search suggestions, search results |
93
+ | Flows | count, exporters, applications, conversations, hosts |
94
+ | Device configuration | list, get, get by interface, latest, download, backup |
95
+ | Situations (v2) | list, create, add alarms, clear, accept, remove alarms |
96
+ | Business services (v2) | full CRUD |
97
+ | Metadata (v2) | full CRUD for node, interface, and service metadata |
98
+ | Server info | get |
99
+ | Discovery (v2) | submit scan configuration |
100
+ | IP interfaces (v2) | list with FIQL |
101
+ | SNMP interfaces (v2) | list with FIQL |
102
+
103
+ ## Authentication
104
+
105
+ Basic authentication is used. Pass `verify_ssl=False` to disable certificate
106
+ verification (useful for self-signed certs in lab environments):
107
+
108
+ ```python
109
+ client = opennms.OpenNMS(
110
+ url="https://opennms.example.com:8443",
111
+ username="admin",
112
+ password="admin",
113
+ verify_ssl=False,
114
+ )
115
+ ```
116
+
117
+ ## Smoke testing
118
+
119
+ `smoke_test.py` exercises the wrapper against a real OpenNMS server. It is
120
+ intended for use against a dev or staging instance before each release — not
121
+ as a substitute for the 290-test mocked unit suite.
122
+
123
+ Tests that depend on optional plugins or heavy endpoints are reported as
124
+ **WARN** (non-fatal) rather than FAIL. Each warning includes the specific
125
+ plugin or feature required.
126
+
127
+ **Read-only mode** (default) is safe to run against any server, including
128
+ production. It issues only GET requests and makes no changes.
129
+
130
+ ```bash
131
+ export OPENNMS_URL="https://opennms.example.com:8443"
132
+ export OPENNMS_USER="admin"
133
+ export OPENNMS_PASSWORD="secret"
134
+ export OPENNMS_VERIFY_SSL="false" # omit or set to "true" for valid certs
135
+ export OPENNMS_TIMEOUT="60" # per-request timeout in seconds (default 60)
136
+
137
+ python smoke_test.py
138
+ ```
139
+
140
+ **Write mode** creates and then deletes objects on the server (events,
141
+ categories, groups, requisitions, maps, etc.). It will prompt for explicit
142
+ confirmation and print the target URL before running a single write.
143
+ **Only use write mode against a dev or staging instance — never production.**
144
+
145
+ ```bash
146
+ python smoke_test.py --write # interactive prompt required
147
+ python smoke_test.py --write --yes # skip prompt (CI pipelines only)
148
+ python smoke_test.py --no-color # plain output for log files
149
+ python smoke_test.py --skip get_resources --skip get_flow # skip slow tests
150
+ ```
151
+
152
+ The `--skip` flag accepts a prefix — `--skip get_flow` skips all tests
153
+ whose label starts with `get_flow`.
154
+
155
+ ## Development
156
+
157
+ ```bash
158
+ git clone https://github.com/cnewkirk/opennms-api-wrapper.git
159
+ cd opennms-api-wrapper
160
+ python3 -m venv .venv
161
+ source .venv/bin/activate
162
+ pip install -e ".[dev]"
163
+ pytest tests/ -v
164
+ ```
165
+
166
+ ## Contributing
167
+
168
+ Bug reports and pull requests are welcome on GitHub at
169
+ https://github.com/cnewkirk/opennms-api-wrapper.
170
+
171
+ ## Acknowledgements
172
+
173
+ This library was designed and tested by a human, with implementation
174
+ assistance from [Claude Code](https://claude.ai/code) (Anthropic). All API
175
+ shapes are derived from the official OpenNMS Horizon 35 REST API
176
+ documentation.
@@ -0,0 +1,10 @@
1
+ """opennms_api_wrapper – a thin Python wrapper for the OpenNMS REST API."""
2
+ from .client import OpenNMS
3
+ from importlib.metadata import version, PackageNotFoundError
4
+
5
+ __all__ = ["OpenNMS"]
6
+
7
+ try:
8
+ __version__ = version("opennms-api-wrapper")
9
+ except PackageNotFoundError:
10
+ __version__ = "unknown"