ucmdb-rest 2.0.1__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 (42) hide show
  1. ucmdb_rest-2.0.1/LICENSE +19 -0
  2. ucmdb_rest-2.0.1/PKG-INFO +131 -0
  3. ucmdb_rest-2.0.1/README.md +116 -0
  4. ucmdb_rest-2.0.1/pyproject.toml +37 -0
  5. ucmdb_rest-2.0.1/setup.cfg +4 -0
  6. ucmdb_rest-2.0.1/tests/__init__.py +3 -0
  7. ucmdb_rest-2.0.1/tests/conftest.py +27 -0
  8. ucmdb_rest-2.0.1/tests/test_client.py +40 -0
  9. ucmdb_rest-2.0.1/tests/test_dataflowmanagement.py +149 -0
  10. ucmdb_rest-2.0.1/tests/test_datamodel.py +67 -0
  11. ucmdb_rest-2.0.1/tests/test_discovery.py +80 -0
  12. ucmdb_rest-2.0.1/tests/test_exposeCI.py +29 -0
  13. ucmdb_rest-2.0.1/tests/test_integration.py +56 -0
  14. ucmdb_rest-2.0.1/tests/test_ldap.py +15 -0
  15. ucmdb_rest-2.0.1/tests/test_mgmtzone.py +74 -0
  16. ucmdb_rest-2.0.1/tests/test_packages.py +50 -0
  17. ucmdb_rest-2.0.1/tests/test_policies.py +61 -0
  18. ucmdb_rest-2.0.1/tests/test_report.py +82 -0
  19. ucmdb_rest-2.0.1/tests/test_settings.py +67 -0
  20. ucmdb_rest-2.0.1/tests/test_system.py +17 -0
  21. ucmdb_rest-2.0.1/tests/test_topology.py +29 -0
  22. ucmdb_rest-2.0.1/ucmdb_rest/__init__.py +6 -0
  23. ucmdb_rest-2.0.1/ucmdb_rest/client.py +236 -0
  24. ucmdb_rest-2.0.1/ucmdb_rest/data_flow_management.py +969 -0
  25. ucmdb_rest-2.0.1/ucmdb_rest/datamodel.py +229 -0
  26. ucmdb_rest-2.0.1/ucmdb_rest/discovery.py +608 -0
  27. ucmdb_rest-2.0.1/ucmdb_rest/expose_ci.py +119 -0
  28. ucmdb_rest-2.0.1/ucmdb_rest/integration.py +308 -0
  29. ucmdb_rest-2.0.1/ucmdb_rest/ldap.py +43 -0
  30. ucmdb_rest-2.0.1/ucmdb_rest/management_zone.py +188 -0
  31. ucmdb_rest-2.0.1/ucmdb_rest/packages.py +428 -0
  32. ucmdb_rest-2.0.1/ucmdb_rest/policies.py +318 -0
  33. ucmdb_rest-2.0.1/ucmdb_rest/report.py +230 -0
  34. ucmdb_rest-2.0.1/ucmdb_rest/settings.py +235 -0
  35. ucmdb_rest-2.0.1/ucmdb_rest/system.py +163 -0
  36. ucmdb_rest-2.0.1/ucmdb_rest/topology.py +218 -0
  37. ucmdb_rest-2.0.1/ucmdb_rest/utils.py +43 -0
  38. ucmdb_rest-2.0.1/ucmdb_rest.egg-info/PKG-INFO +131 -0
  39. ucmdb_rest-2.0.1/ucmdb_rest.egg-info/SOURCES.txt +40 -0
  40. ucmdb_rest-2.0.1/ucmdb_rest.egg-info/dependency_links.txt +1 -0
  41. ucmdb_rest-2.0.1/ucmdb_rest.egg-info/requires.txt +1 -0
  42. ucmdb_rest-2.0.1/ucmdb_rest.egg-info/top_level.txt +1 -0
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2026 Keith Paschal
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.4
2
+ Name: ucmdb_rest
3
+ Version: 2.0.1
4
+ Summary: A modular Python client for the UCMDB REST API
5
+ Author-email: Keith Paschal <kw.paschal@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/kwpaschal/ucmdb_rest
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.6
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: requests>=2.25.0
14
+ Dynamic: license-file
15
+
16
+ # UCMDB REST Python Library
17
+
18
+ A modern, object-oriented Python 3.6+ wrapper for the OpenText Universal Configuration Management Database (UCMDB) REST API. This library centralizes UCMDB interactions through a unified client, providing type-safe Enums and automated pagination.
19
+ ## Setup and Authentication
20
+ This library contains some examples that assume a `credentials.json` file is in the same direcory as the code.
21
+
22
+ 1. Copy `credentials.json.example` to `credentials.json`
23
+ 2. Update the values with your UCMDB server details
24
+
25
+ | Key | Description |
26
+ | :--- | :--- |
27
+ | **user** | UCMDB Username |
28
+ | **password** | UCMDB Password |
29
+ | **server** | FQDN or IP of the UCMDB Server |
30
+ | **port** | REST API port (Default 8443) |
31
+ | **ssl_validation** | Boolean (false to skip certificate checks) |
32
+
33
+ ## Quick Start
34
+
35
+ The library uses a central `UCMDBServer` to manage authentication and session persistence.
36
+
37
+ ```python
38
+ from ucmdb_rest import UCMDBServer
39
+
40
+ # Initialize client (assumes credentials.json exists)
41
+ client = UCMDBServer.from_json('credentials.json')
42
+
43
+ # Quick connectivity check
44
+ print(f"Connected to: {client.server_version}")
45
+
46
+ # Get detailed version info
47
+ version = client.system.getUCMDBVersion().json()
48
+ print(f"Product: {version['productName']}")
49
+ print(f"Content Pack: {version['contentPackVersion']}")
50
+ ```
51
+ ## Practical Examples
52
+ To help you get started quickly, here are some example standalone scripts
53
+ * **`add_cis.py`**: Create CIs and Relationships with custom properties
54
+ * **`delete_cis.py`**: Delete CIs by their UCMDB ID
55
+ * **`get_recon_rule.py`**: Display a reconciliation rule for a CI Type
56
+ * **`initialize_get_version.py`**: Display version information about the UCMDB Server
57
+ * **`query_topology`**: Run a UCMDB View and get the information
58
+ * **`search_and_expose_ci.py`**: Search for a CI by name and get specific properties
59
+ * **`show_content_packs.py`**: Display current content pack information
60
+ * **`show_license_report.py`**: Display a license report from UCMDB
61
+
62
+ see [Examplese Documentation](./examples/index.md) for detailed setup and usage.
63
+ ## Functional Modules
64
+
65
+ The library is organized into specialized modules to mirror the UCMDB API ecosystem:
66
+
67
+ | Module | Description |
68
+ | :--- | :--- |
69
+ | **client** | `UCMDBServer` class which acts as the entry point. |
70
+ | **data_flow_management** | Operations affecting Data Flow Probes. |
71
+ | **datamodel** | CRUD operations for Configuration Items (CIs) and Relations. |
72
+ | **discovery** | Management of discovery jobs, probe status, and results. |
73
+ | **expose_ci** | On-demand queries of the UCMDB database. |
74
+ | **integration** | Operations affecting integration points. |
75
+ | **ldap** | Operations affecting LDAP integration in UCMDB. |
76
+ | **management_zone** | Operations affecting UCMDB UI zone-based discovery. |
77
+ | **packages** | Deployment and management of UCMDB Content Packs. |
78
+ | **policies** | Policy calculation and automated result chunking. |
79
+ | **report** | Operations involving reports and data exports. |
80
+ | **settings** | Operations involving infrastructure settings and recipients. |
81
+ | **system** | Licensing, versioning, and ping operations. |
82
+ | **topology** | TQL execution, ad-hoc queries, and fetching CI attributes. |
83
+ | **utils** | Shared helper functions and internal constants. |
84
+
85
+ ## Documentation
86
+
87
+ For detailed API references, view our [Interactive Documentation](reference/data_flow_management.md).
88
+
89
+ ### Documentation Workflow
90
+ The docs are powered by `mkdocs` and `mkdocstrings`.
91
+ - **Source**: Python Docstrings (numpy Style)
92
+ - **Theme**: Material for MkDocs
93
+ - **Customization**: Located in `docs/stylesheets/extra.css`
94
+
95
+ ## Development and Testing
96
+
97
+ We use `pytest` for functional validation. To run the suite:
98
+ ```bash
99
+ # Run all tests with coverage
100
+ pytest --cov=ucmdb_rest
101
+
102
+ # Preview documentation locally
103
+ mkdocs serve
104
+
105
+ ## Release History
106
+
107
+ ## Release History
108
+ * **2.0.1 (Current)**
109
+ * Fixed a bunch of failing tests
110
+ * Beginning to add Examples
111
+ * **2.0.0**
112
+ * **Major Architecture Milestone**: Completed the migration of all legacy `rest.py` components.
113
+ * Re-engineered core modules into a modular, object-oriented framework.
114
+ * Standardized response handling using `requests.Response` objects across all modules.
115
+ * Enhanced code discoverability via the unified `UCMDBServer` entry point.
116
+ * **1.7.0**
117
+ * (Internal version alignment release)
118
+ * **1.6.0**
119
+ * Added Settings and Recipients management.
120
+ * **1.5.0**
121
+ * Added Reports functionality and tests.
122
+ * **1.4.0**
123
+ * Added Management Zone functionality and tests.
124
+ * **1.3.0**
125
+ * Added LDAP configuration retrieval.
126
+ * **1.2.0**
127
+ * Added integration point retrieval.
128
+ * **1.1.0**
129
+ * Added ExposeCI ad-hoc query support.
130
+ * **1.0.0**
131
+ * Initial stable release: Topology and Discovery modules complete.
@@ -0,0 +1,116 @@
1
+ # UCMDB REST Python Library
2
+
3
+ A modern, object-oriented Python 3.6+ wrapper for the OpenText Universal Configuration Management Database (UCMDB) REST API. This library centralizes UCMDB interactions through a unified client, providing type-safe Enums and automated pagination.
4
+ ## Setup and Authentication
5
+ This library contains some examples that assume a `credentials.json` file is in the same direcory as the code.
6
+
7
+ 1. Copy `credentials.json.example` to `credentials.json`
8
+ 2. Update the values with your UCMDB server details
9
+
10
+ | Key | Description |
11
+ | :--- | :--- |
12
+ | **user** | UCMDB Username |
13
+ | **password** | UCMDB Password |
14
+ | **server** | FQDN or IP of the UCMDB Server |
15
+ | **port** | REST API port (Default 8443) |
16
+ | **ssl_validation** | Boolean (false to skip certificate checks) |
17
+
18
+ ## Quick Start
19
+
20
+ The library uses a central `UCMDBServer` to manage authentication and session persistence.
21
+
22
+ ```python
23
+ from ucmdb_rest import UCMDBServer
24
+
25
+ # Initialize client (assumes credentials.json exists)
26
+ client = UCMDBServer.from_json('credentials.json')
27
+
28
+ # Quick connectivity check
29
+ print(f"Connected to: {client.server_version}")
30
+
31
+ # Get detailed version info
32
+ version = client.system.getUCMDBVersion().json()
33
+ print(f"Product: {version['productName']}")
34
+ print(f"Content Pack: {version['contentPackVersion']}")
35
+ ```
36
+ ## Practical Examples
37
+ To help you get started quickly, here are some example standalone scripts
38
+ * **`add_cis.py`**: Create CIs and Relationships with custom properties
39
+ * **`delete_cis.py`**: Delete CIs by their UCMDB ID
40
+ * **`get_recon_rule.py`**: Display a reconciliation rule for a CI Type
41
+ * **`initialize_get_version.py`**: Display version information about the UCMDB Server
42
+ * **`query_topology`**: Run a UCMDB View and get the information
43
+ * **`search_and_expose_ci.py`**: Search for a CI by name and get specific properties
44
+ * **`show_content_packs.py`**: Display current content pack information
45
+ * **`show_license_report.py`**: Display a license report from UCMDB
46
+
47
+ see [Examplese Documentation](./examples/index.md) for detailed setup and usage.
48
+ ## Functional Modules
49
+
50
+ The library is organized into specialized modules to mirror the UCMDB API ecosystem:
51
+
52
+ | Module | Description |
53
+ | :--- | :--- |
54
+ | **client** | `UCMDBServer` class which acts as the entry point. |
55
+ | **data_flow_management** | Operations affecting Data Flow Probes. |
56
+ | **datamodel** | CRUD operations for Configuration Items (CIs) and Relations. |
57
+ | **discovery** | Management of discovery jobs, probe status, and results. |
58
+ | **expose_ci** | On-demand queries of the UCMDB database. |
59
+ | **integration** | Operations affecting integration points. |
60
+ | **ldap** | Operations affecting LDAP integration in UCMDB. |
61
+ | **management_zone** | Operations affecting UCMDB UI zone-based discovery. |
62
+ | **packages** | Deployment and management of UCMDB Content Packs. |
63
+ | **policies** | Policy calculation and automated result chunking. |
64
+ | **report** | Operations involving reports and data exports. |
65
+ | **settings** | Operations involving infrastructure settings and recipients. |
66
+ | **system** | Licensing, versioning, and ping operations. |
67
+ | **topology** | TQL execution, ad-hoc queries, and fetching CI attributes. |
68
+ | **utils** | Shared helper functions and internal constants. |
69
+
70
+ ## Documentation
71
+
72
+ For detailed API references, view our [Interactive Documentation](reference/data_flow_management.md).
73
+
74
+ ### Documentation Workflow
75
+ The docs are powered by `mkdocs` and `mkdocstrings`.
76
+ - **Source**: Python Docstrings (numpy Style)
77
+ - **Theme**: Material for MkDocs
78
+ - **Customization**: Located in `docs/stylesheets/extra.css`
79
+
80
+ ## Development and Testing
81
+
82
+ We use `pytest` for functional validation. To run the suite:
83
+ ```bash
84
+ # Run all tests with coverage
85
+ pytest --cov=ucmdb_rest
86
+
87
+ # Preview documentation locally
88
+ mkdocs serve
89
+
90
+ ## Release History
91
+
92
+ ## Release History
93
+ * **2.0.1 (Current)**
94
+ * Fixed a bunch of failing tests
95
+ * Beginning to add Examples
96
+ * **2.0.0**
97
+ * **Major Architecture Milestone**: Completed the migration of all legacy `rest.py` components.
98
+ * Re-engineered core modules into a modular, object-oriented framework.
99
+ * Standardized response handling using `requests.Response` objects across all modules.
100
+ * Enhanced code discoverability via the unified `UCMDBServer` entry point.
101
+ * **1.7.0**
102
+ * (Internal version alignment release)
103
+ * **1.6.0**
104
+ * Added Settings and Recipients management.
105
+ * **1.5.0**
106
+ * Added Reports functionality and tests.
107
+ * **1.4.0**
108
+ * Added Management Zone functionality and tests.
109
+ * **1.3.0**
110
+ * Added LDAP configuration retrieval.
111
+ * **1.2.0**
112
+ * Added integration point retrieval.
113
+ * **1.1.0**
114
+ * Added ExposeCI ad-hoc query support.
115
+ * **1.0.0**
116
+ * Initial stable release: Topology and Discovery modules complete.
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ucmdb_rest"
7
+ version = "2.0.1"
8
+ description = "A modular Python client for the UCMDB REST API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [
12
+ { name = "Keith Paschal", email = "kw.paschal@gmail.com" }
13
+ ]
14
+ requires-python = ">=3.6"
15
+ dependencies = [
16
+ "requests>=2.25.0",
17
+ ]
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "Operating System :: OS Independent",
21
+ ]
22
+
23
+ [project.urls]
24
+ Homepage = "https://github.com/kwpaschal/ucmdb_rest"
25
+
26
+ [tool.setuptools.packages.find]
27
+ include = ["ucmdb_rest*"]
28
+
29
+ [tool.ruff]
30
+ src = ["ucmdb_rest"]
31
+ line-length = 100
32
+
33
+ [tool.ruff.lint]
34
+ select = ["E", "F", "I"]
35
+
36
+ [tool.ruff.lint.per-file-ignores]
37
+ "tests/*" = ["F401"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """
2
+ Test suite for ucmdb_rest library
3
+ """
@@ -0,0 +1,27 @@
1
+ import json
2
+ import os
3
+
4
+ import pytest
5
+ import urllib3
6
+ from ucmdb_rest.client import UCMDBServer
7
+
8
+ # Suppress SSL warnings globally for all tests
9
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
10
+
11
+ @pytest.fixture(scope="session")
12
+ def creds():
13
+ """Load credentials from JSON."""
14
+ cred_path = os.path.join(os.path.dirname(__file__), 'credentials.json')
15
+ with open(cred_path, 'r') as f:
16
+ return json.load(f)
17
+
18
+ @pytest.fixture(scope="session")
19
+ def ucmdb_client(creds):
20
+ """Pass the 'creds' fixture into the client fixture."""
21
+ return UCMDBServer(
22
+ user=creds['user'],
23
+ password=creds['password'],
24
+ server=creds['server'],
25
+ port=creds.get('port', 8443),
26
+ ssl_validation=creds.get('ssl_validation', False)
27
+ )
@@ -0,0 +1,40 @@
1
+ import pytest
2
+ from ucmdb_rest.client import UCMDBAuthError, UCMDBServer
3
+
4
+
5
+ def test_connection_and_auth(ucmdb_client):
6
+ """
7
+ This test verifies that the fixture in conftest.py successfully
8
+ authenticated and returned a working client object.
9
+ """
10
+ # Verify the base URL was built
11
+ assert ucmdb_client.base_url.startswith("https://")
12
+
13
+ # Verify the token is present in the session headers
14
+ auth_header = ucmdb_client.session.headers.get('Authorization')
15
+ assert auth_header is not None
16
+ assert auth_header.startswith("Bearer ")
17
+
18
+ # Optional: Verify the token isn't just an empty string
19
+ assert len(auth_header) > 20
20
+
21
+ def test_failed_connection_bad_server():
22
+ with pytest.raises(UCMDBAuthError) as excinfo:
23
+ UCMDBServer(
24
+ user="admin",
25
+ password="ucmdbadmin",
26
+ server="bad.server.local"
27
+ )
28
+ assert "Failed to resolve" in str(excinfo.value)
29
+
30
+ # def test_failed_auth_bad_password(creds):
31
+ # with pytest.raises(UCMDBAuthError) as excinfo:
32
+ # UCMDBServer(
33
+ # user=creds['user'],
34
+ # password="wrong_password",
35
+ # server=creds['server']
36
+ # )
37
+ #
38
+ # error_msg = str(excinfo.value)
39
+ # assert "Auth Failed" in error_msg
40
+ # assert "401" in error_msg
@@ -0,0 +1,149 @@
1
+ import pytest
2
+
3
+
4
+ @pytest.fixture(scope="module")
5
+ def active_probe_name(ucmdb_client):
6
+ """Fetches the first available probe name from the server."""
7
+ probes = ucmdb_client.data_flow.getProbeInfo()
8
+ probe_list = probes.json()
9
+ items = probe_list.get('items',[])
10
+ if not items:
11
+ pytest.skip("No probes found on the UCMDB server; skipping dependent tests.")
12
+ return items[0]['probeName']
13
+
14
+ def test_getProbeRanges(ucmdb_client, active_probe_name):
15
+ ranges = ucmdb_client.data_flow.getProbeRanges(active_probe_name)
16
+ assert ranges.status_code == 200
17
+
18
+ def test_addRange(ucmdb_client,active_probe_name):
19
+ RANGE_TO_ADD = [{
20
+ 'range': '15.1.1.1-15.1.1.2',
21
+ 'definitionType': 'IP_RANGE',
22
+ 'ipVersion': 'IPV4',
23
+ 'isIncluded': True,
24
+ 'rangeType': 'DATA_CENTER',
25
+ 'description': 'Test Range'
26
+ }]
27
+ result = ucmdb_client.data_flow.addRange(RANGE_TO_ADD, active_probe_name)
28
+ assert result.status_code == 200
29
+
30
+ def test_updateRange(ucmdb_client, active_probe_name):
31
+ RANGE_TO_UPDATE = {
32
+ "oldRanges": [{
33
+ "probe": active_probe_name,
34
+ "range": "15.1.1.1-15.1.1.2",
35
+ "definitionType": "IP_RANGE",
36
+ "ipVersion": "IPV4",
37
+ "isIncluded": True
38
+ }],
39
+ "newRanges": [{
40
+ "probe": active_probe_name,
41
+ "range": "15.1.1.1-15.1.1.3",
42
+ "definitionType": "IP_RANGE",
43
+ "ipVersion": "IPV4",
44
+ "isIncluded": True,
45
+ "rangeType": "DATA_CENTER",
46
+ "description": "Updated via Test"
47
+ }]
48
+ }
49
+ result = ucmdb_client.data_flow.updateRange(RANGE_TO_UPDATE, active_probe_name)
50
+ assert result.status_code == 200
51
+
52
+ def test_deleteRange(ucmdb_client,active_probe_name):
53
+ RANGE_TO_DELETE = [
54
+ {
55
+ "range": "15.1.1.1-15.1.1.3",
56
+ "definitionType": "IP_RANGE",
57
+ "ipVersion": "IPV4",
58
+ "isIncluded": True
59
+ }
60
+ ]
61
+ result = ucmdb_client.data_flow.deleteRange(RANGE_TO_DELETE, active_probe_name)
62
+ assert result.status_code == 200
63
+
64
+ def test_getAllDomains(ucmdb_client):
65
+ result = ucmdb_client.data_flow.getAllDomains()
66
+ assert result.status_code == 200
67
+
68
+ def test_getAllCredentials(ucmdb_client):
69
+ result = ucmdb_client.data_flow.getAllCredentials()
70
+ assert result.status_code == 200
71
+
72
+ def test_getProbeInfo(ucmdb_client):
73
+ result = ucmdb_client.data_flow.getProbeInfo()
74
+ assert result.status_code == 200
75
+
76
+ def test_getProtocol(ucmdb_client):
77
+ result = ucmdb_client.data_flow.getProtocol('ntadminprotocol')
78
+ assert result.status_code == 200
79
+
80
+ def test_probeStatusDetails(ucmdb_client,active_probe_name):
81
+ result = ucmdb_client.data_flow.probeStatusDetails('DefaultDomain', active_probe_name)
82
+ assert result.status_code == 200
83
+
84
+ def test_checkCredential_ad_hoc(ucmdb_client, active_probe_name):
85
+ query_body = {
86
+ "nodes": [
87
+ {
88
+ "type": "ntcmd",
89
+ "queryIdentifier": "ntcmd",
90
+ "visible": True,
91
+ "includeSubtypes": True,
92
+ "layout": ["display_label", "application_ip", "last_discovered_by_probe", "credentials_id"], # noqa: E501
93
+ "attributesConditions": [
94
+ {
95
+ "attributeName": "last_discovered_by_probe",
96
+ "operator": "equals",
97
+ "value": active_probe_name
98
+ }
99
+ ]
100
+ }
101
+ ],
102
+ "relations": []
103
+ }
104
+
105
+ response = ucmdb_client.topology.queryCIs(query_body)
106
+ all_cis = response.json().get("cis", [])
107
+
108
+ matching_cis = [
109
+ ci for ci in all_cis
110
+ if ci.get("properties", {}).get("last_discovered_by_probe") == active_probe_name
111
+ ]
112
+
113
+ assert len(matching_cis) > 0, (
114
+ f"Filtered out all {len(all_cis)} CIs because none matched probe: {active_probe_name}"
115
+ )
116
+
117
+ target_ci = matching_cis[0]
118
+ props = target_ci.get("properties", {})
119
+
120
+ cred_id = props.get("credentials_id")
121
+ ip_addr = props.get("application_ip")
122
+ probe_name = props.get("last_discovered_by_probe")
123
+
124
+ print(f"Found {len(matching_cis)} matches. Testing Credential: {cred_id} on {ip_addr}")
125
+
126
+ result = ucmdb_client.data_flow.checkCredential(cred_id, probe_name, ip_addr)
127
+
128
+ assert result.status_code == 200
129
+ print(f"Successfully validated credential for {ip_addr} via {probe_name}")
130
+
131
+ def test_getAllProtocols(ucmdb_client):
132
+ result = ucmdb_client.data_flow.getAllProtocols()
133
+ assert result.status_code == 200
134
+
135
+ def test_getCredentialProfiles(ucmdb_client):
136
+ result = ucmdb_client.data_flow.getCredentialProfiles()
137
+ assert result.status_code == 200
138
+
139
+ def test_probeStatus(ucmdb_client):
140
+ result = ucmdb_client.data_flow.probeStatus()
141
+ assert result.status_code == 200
142
+
143
+ def test_queryIPs(ucmdb_client):
144
+ result = ucmdb_client.data_flow.queryIPs('10.1.1.')
145
+ assert result.status_code == 200
146
+
147
+ def test_queryProbe(ucmdb_client):
148
+ result = ucmdb_client.data_flow.queryProbe()
149
+ assert result.status_code == 200
@@ -0,0 +1,67 @@
1
+ import pytest #noqa
2
+
3
+ myCI = {
4
+ "cis": [
5
+ {
6
+ "ucmdbId": "1",
7
+ "type": "node",
8
+ "properties": {"name":"Test6",
9
+ "os_family":"windows"}
10
+ }
11
+ ],
12
+ "relations": []
13
+ }
14
+
15
+ ci_list = []
16
+ node_global_id = None
17
+
18
+ def test_addCIs(ucmdb_client):
19
+ global ci_list, node_global_id
20
+ result = ucmdb_client.data_model.addCIs(myCI, returnIdsMap=True)
21
+
22
+ assert result.status_code == 200
23
+ data = result.json()
24
+ print(data)
25
+
26
+ if "idsMap" in data:
27
+ ci_list = list(data["idsMap"].values())
28
+ node_global_id = data["idsMap"].get("1")
29
+ else:
30
+ ci_list = data.get("addedCis", []) + data.get("ignoredCis", [])
31
+ if ci_list:
32
+ node_global_id = ci_list[0]
33
+
34
+ assert len(ci_list) > 0
35
+ assert node_global_id is not None
36
+
37
+ def test_updateCI(ucmdb_client):
38
+ global node_global_id
39
+ updatedCI = {"ucmdbId":node_global_id,
40
+ "type":"node",
41
+ "properties" : {"data_note":"Updated by REST"}}
42
+ response = ucmdb_client.data_model.updateCI(node_global_id, updatedCI)
43
+
44
+ assert response.status_code == 200
45
+ data = response.json()
46
+ assert node_global_id in data.get("updatedCis", []) or node_global_id in data.get("ignoredCis", []) # noqa: E501
47
+
48
+ def test_deleteCIs(ucmdb_client):
49
+ global ci_list
50
+ for ci_id in ci_list:
51
+ response = ucmdb_client.data_model.deleteCIs(ci_id, isGlobalId=True)
52
+ assert response.status_code == 200
53
+
54
+ def test_getClass(ucmdb_client):
55
+ response = ucmdb_client.data_model.getClass("node")
56
+ assert response.status_code == 200
57
+
58
+ def test_retrieveIdentificationRule(ucmdb_client):
59
+ response = ucmdb_client.data_model.retrieveIdentificationRule("node")
60
+ assert response.status_code == 200
61
+
62
+ def test_convertFromBase64_logic(ucmdb_client):
63
+ sample_input = "SGVsbG8gVUNNREI="
64
+ expected_output = "Hello UCMDB"
65
+
66
+ result = ucmdb_client.data_model.convertFromBase64(sample_input)
67
+ assert result == expected_output
@@ -0,0 +1,80 @@
1
+ import pytest
2
+
3
+
4
+ # 1. Metadata Tests
5
+ def test_get_module_tree(ucmdb_client):
6
+ response = ucmdb_client.discovery.getModuleTree()
7
+ assert response.status_code == 200
8
+ assert "children" in response.json()
9
+
10
+ def test_get_use_cases(ucmdb_client):
11
+ response = ucmdb_client.discovery.getDiscoveryUseCases()
12
+ assert response.status_code == 200
13
+ data = response.json()
14
+ assert isinstance(data, dict)
15
+ assert "children" in data
16
+
17
+ def test_get_job_metadata(ucmdb_client):
18
+ response = ucmdb_client.discovery.getJobMetaData()
19
+ assert response.status_code == 200
20
+ assert "items" in response.json()
21
+
22
+ # 2. IP Range Tests
23
+ def test_get_ip_ranges(ucmdb_client):
24
+ response = ucmdb_client.discovery.getIPRange()
25
+ assert response.status_code == 200
26
+ assert "items" in response.json()
27
+
28
+ def test_get_ip_range_for_specific_ip(ucmdb_client):
29
+ # Testing with a common loopback or local IP
30
+ response = ucmdb_client.discovery.getIPRangeForIP("127.0.0.1")
31
+ assert response.status_code == 200
32
+
33
+ # 3. Job Group & Parameter Tests
34
+ def test_get_job_group_with_fields(ucmdb_client):
35
+ # This specifically tests the fix you just made
36
+ response = ucmdb_client.discovery.getJobGroup(fields="name,id")
37
+ assert response.status_code == 200
38
+ data = response.json()
39
+ if data.get("items"):
40
+ assert "name" in data["items"][0]
41
+ assert "id" in data["items"][0]
42
+
43
+ def test_get_questions(ucmdb_client):
44
+ job_name = "Host Connection by Shell"
45
+ response = ucmdb_client.discovery.getQuestions(job_name)
46
+ assert response.status_code == 200
47
+
48
+ def test_get_schedules(ucmdb_client):
49
+ response = ucmdb_client.discovery.getSchedules()
50
+ assert response.status_code == 200
51
+
52
+ # 4. Lifecycle Test
53
+ def test_job_group_lifecycle(ucmdb_client):
54
+ name = "Pytest_Discovery_Test"
55
+ payload = {
56
+ "name": name,
57
+ "type": "CMS",
58
+ "description": "Test Group",
59
+ # discoveryType often defaults to null on the server
60
+ "discoveryType": None,
61
+ "jobs": [
62
+ {
63
+ "jobName": "Call Home Processing",
64
+ "jobDisplayName": "Call Home Processing",
65
+ "adapterName": "CallHomeProcessing",
66
+ "inputCI": "callhome_event",
67
+ "jobType": "DynamicService",
68
+ "protocols": [],
69
+ "jobParameters": {},
70
+ "triggerQueries": [],
71
+ "jobInvokeOnNewTrigger": True
72
+ }
73
+ ]
74
+ }
75
+ # Create
76
+ assert ucmdb_client.discovery.createJobGroup(payload).status_code in [200, 201]
77
+ # Get Specific
78
+ assert ucmdb_client.discovery.getSpecificJobGroup(name).status_code == 200
79
+ # Delete
80
+ assert ucmdb_client.discovery.deleteSpecificJobGroup(name).status_code == 200