diff --git a/README.md b/README.md index 2d59296..8ac6756 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,14 @@ Simplified Python library for BMC Discovery API Interface that makes use of the "api_versions": [ "1.0", "1.1", - "1.2" + "1.2", + "1.3", + "1.4", + "1.5" ], "component": "REST API", "product": "BMC Discovery", - "version": "12.2" + "version": "12.5" } ``` @@ -33,11 +36,11 @@ Documentation can be found at [https://traversys.github.io/Tideway/](https://tra ## Releases -| Version | Summary | Known Issues | Fixed | -| :-----: | ------------------------------------------------------ | -------------------------------------------------------------- | ------------------------------ | -| 0.1.0 | Initial release, compatible with API v1.1 | | | -| 0.1.1 | Updated to API v1.2
Added `help()`, `search_bulk()` | search call retains last parameters for `offset`, `results_id` | | -| 0.1.2 | Bug Fixes | Bulk search with larger limit than dataset will fail on missing `next_offset` | Fixed issue with `offset` and `results_id` values
Fixed issue with bulk search parameter lower limit. | -| 0.1.3 | Bug Fixes | | Added check for `next_offset`. | -| 0.1.4 | Search bulk update | Discovery 12.3 (21.3) enforces strict case for "Bearer" header - api calls will not current work. | Now includes headers for non-formatted search. | -| 0.1.5 | Updated to support Discovery 12.3 (API version 1.3) | | Fixed issue with Bearer capitalisation.
Search Bulk will now return the full response on failure | +| Version | Summary | Known Issues | Fixed | +| :-----: | ------------------------- | -------------------------------------------------- | -------------------------------- | +| 0.1.1 | - Updated to API v1.2
- Added `help()`, `search_bulk()` | search call retains last parameters for `offset`, `results_id` | | +| 0.1.2 | Bug Fixes | Bulk search with larger limit than dataset will fail on missing `next_offset` | - Fixed issue with `offset` and `results_id` values
- Fixed issue with bulk search parameter lower limit. | +| 0.1.3 | Bug Fixes | | Added check for `next_offset`. | +| 0.1.4 | Search bulk update | Discovery 12.3 (21.3) enforces strict case for "Bearer" header - api calls will not current work. | Now includes headers for non-formatted search. | +| 0.1.5 | Updated to support Discovery 12.3 (API version 1.3) | - Missing 'complete' parameter option on graphNode() function. | - Fixed issue with Bearer capitalisation.
- Search Bulk will now return the full response on failure | +| 0.2.0 | Updated to include Kerberos, Models and Taxonomy endpoints.

Added new high level generic endpoint function calls

Refactored function names/decorators to match API endpoints as close as possible.

Supports Discovery 22.2 (12.5) (API version 1.5) and Outpost API version 1.0 | Not all new unctions have been tested. | Added 'complete' parameter to `get_data_nodes_graph()` (replaces `graphNode()`) | diff --git a/docs/endpoints/admin.md b/docs/endpoints/admin.md index e5e9ae6..ed79d36 100644 --- a/docs/endpoints/admin.md +++ b/docs/endpoints/admin.md @@ -1,5 +1,5 @@ --- -sort: 9 +sort: 1 --- # Admin @@ -16,42 +16,54 @@ Initiation: ```python >>> import tideway ->>> tw = tideway.admin('appliance-hostname','auth-token') +>>> tw = tideway.admin('hostname','auth-token') ``` -## baseline() +## get_admin_baseline -- Get a summary of the appliance status, and details of which baseline checks have passed or failed. +Get a summary of the appliance status, and details of which baseline checks have passed or failed. Syntax: ``` -.baseline() +.get_admin_baseline ``` Example: ```python ->>> tw.baseline().json()['results']['FAILED'][0] +>>> tw.get_admin_baseline.json()['results']['FAILED'][0] {'enabled': True, 'message': 'MAJOR: This appliance has insufficent resources', 'name': 'Appliance Specification', 'severity': 'MAJOR'} ``` -## about() +## get_admin_about Get the versions of the API supported by a BMC Discovery version. Syntax: ``` -.about() +.get_admin_about ``` Example: ```python ->>> tw.about().json() +>>> tw.get_admin_about.json() {'api_versions': ['1.0', '1.1', '1.2'], 'component': 'REST API', 'product': 'BMC Discovery', 'version': '12.2'} ``` +## baseline() + +[Deprecated] See [get_admin_baseline](#get_admin_baseline) for usage. + +Syntax: `.baseline()` + +## about() + +[Deprecated] See [get_admin_about](#get_admin_about) for usage. + +Syntax: `.about()` + ## licensing() Get the latest signed licensing report. diff --git a/docs/endpoints/appliance.md b/docs/endpoints/appliance.md index e6b06df..4a7d8d2 100644 --- a/docs/endpoints/appliance.md +++ b/docs/endpoints/appliance.md @@ -1,53 +1,101 @@ --- -sort: 1 +sort: 2 --- -# Appliance +# Appliance or Outpost -Initiate an Appliance object for the instance of Discovery you intend to query. +Initiate an Appliance or Outpost object for the instance of Discovery you intend to query. Syntax: ``` tideway.appliance(__target__, __token__ [, _api_version_ ] [, _ssl_verify_ ] [, _limit_ ] [, _offset_ ]) +tideway.outpost(__target__, __token__ [, _api_version_ ] [, _ssl_verify_ ] [, _limit_ ] [, _offset_ ]) ``` Initiation: ```python >>> import tideway ->>> tw = tideway.appliance('appliance-hostname','auth-token') +>>> tw = tideway.appliance('hostname','auth-token') ``` -## about() +## api_about Get the versions of the API supported by a BMC Discovery version. Syntax: ``` -.about() +.api_about ``` Example: ```python ->>> tw.about().json() +>>> tw.api_about.json() {'api_versions': ['1.0', '1.1', '1.2'], 'component': 'REST API', 'product': 'BMC Discovery', 'version': '12.2'} ``` -## admin() +## api_swagger + +Get JSON swagger file which contains the API schema. + +Syntax: + +``` +.api_swagger +``` + +Example: + +```python +>>> swagger = tw.api_swagger +>>> from pprint import pprint +>>> pprint(api_swagger.json()['tags']) +[{'description': 'Control scanning and view results', 'name': 'discovery'}, + {'description': 'Read and import data', 'name': 'data'}, + {'description': 'Manage the credential vault', 'name': 'vault'}, + {'description': 'Manage credentials', 'name': 'credentials'}, + {'description': 'Upload new TKUs and pattern modules', 'name': 'knowledge'}, + {'description': 'Push events', 'name': 'events'}, + {'description': 'Manage the BMC Discovery appliance', 'name': 'admin'}, + {'description': 'Retrieve topology data from the datastore', 'name': 'topology'}] +``` + +## api_help + +Outputs full list of help methods see [help()](#help). + +## get_admin_baseline + +- Get a summary of the appliance status, and details of which baseline checks have passed or failed. + +Syntax: + +``` +.get_admin_baseline +``` + +Example: + +```python +>>> tw.get_admin_baseline.json()['results']['FAILED'][0] +{'enabled': True, 'message': 'MAJOR: This appliance has insufficent resources', 'name': 'Appliance Specification', 'severity': 'MAJOR'} +``` + +## get_admin_about Get information about the appliance, like its version and versions of the installed packages. Syntax: ``` -.admin() +.get_admin_about ``` Example: ```python ->>> details = tw.admin().text +>>> details = tw.get_admin_about.text >>> print(details) { "versions": { @@ -59,49 +107,208 @@ Example: } ``` -## swagger() +## get_admin_licensing -Get JSON swagger file which contains the API schema. +Get the latest signed licensing report in plain text. Syntax: ``` -.swagger() +.get_admin_licensing ``` Example: +```python +>>> tw.get_admin_licensing.text +-----BEGIN LICENSE REPORT----- +License report +============== + +Report start time: 2021-01-18 23:00:00.409987+00:00 +Report end time : 2021-01-21 23:00:00.410085+00:00 +... +``` + +## get_admin_licensing_csv + +Get the latest raw license data in CSV format as a zip file for offline analysis. + +Syntax: +``` +.get_admin_licensing_csv +``` + +Example: ```python ->>> swagger = tw.swagger() ->>> from pprint import pprint ->>> pprint(swagger.json()['tags']) -[{'description': 'Control scanning and view results', 'name': 'discovery'}, - {'description': 'Read and import data', 'name': 'data'}, - {'description': 'Manage the credential vault', 'name': 'vault'}, - {'description': 'Manage credentials', 'name': 'credentials'}, - {'description': 'Upload new TKUs and pattern modules', 'name': 'knowledge'}, - {'description': 'Push events', 'name': 'events'}, - {'description': 'Manage the BMC Discovery appliance', 'name': 'admin'}, - {'description': 'Retrieve topology data from the datastore', 'name': 'topology'}] +>>> tw.get_admin_licensing_csv + ``` -## baseline() +## get_admin_licensing_raw -- Get a summary of the appliance status, and details of which baseline checks have passed or failed. +Get the latest license data as encrypted raw license object for import to another appliance. + +Syntax: + +``` +.get_admin_licensing_raw +``` + +Example: +```python +>>> tw.get_admin_licensing_raw + +``` + +## get() + +Run a direct endpoint query using GET request. Syntax: ``` -.baseline() +.get(__endpoint__) ``` +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| endpoint | String | Yes | N/A | N/A | + Example: +```python +>>> tw.get("/vault") +{ + "open": true, + "passphrase_saved": false, + "passphrase_set": false +} +``` +## post() + +Run a direct endpoint query using POST. + +Syntax: + +``` +.post(__endpoint__, __body__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| endpoint | String | Yes | N/A | N/A | +| body | JSON Object | Yes | N/A | N/A | + +Example: ```python ->>> tw.baseline().json()['results']['FAILED'][0] -{'enabled': True, 'message': 'MAJOR: This appliance has insufficent resources', 'name': 'Appliance Specification', 'severity': 'MAJOR'} +>>> tw.post("/data/search",{"query": "search Host show os_class process with unique()"}) +[ + { + 'count': 3, + 'kind': 'Unique row', + 'offset': 0, + 'results': [ + { + 'os_class': 'UNIX' + }, + { + 'os_class': 'Windows' + }, + { + 'os_class': 'Other' + } + ] + } +] +``` + +## delete() + +Run a direct endpoint query using DELETE. The endpoint is assumed to contain a specific identifier parsed as a string query. + +Syntax: + +``` +.delete(__endpoint__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| endpoint | String | Yes | N/A | N/A | + +Example: +```python +>>> tw.delete("/discovery/runs/scheduled/{run_id}") + +``` + +## patch() + +Run a direct endpoint query using PATCH. + +Syntax: + +``` +.patch(__endpoint__, __body__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| endpoint | String | Yes | N/A | N/A | +| body | JSON Object | Yes | N/A | N/A | + +Example: +```python +>>> tw.patch("/discovery/runs/scheduled/{run_id}",{"enabled": true}) + +``` + +## put() + +Run a direct endpoint query using PUT. + +Syntax: + +``` +.put(__endpoint__, __body__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| endpoint | String | Yes | N/A | N/A | +| body | JSON Object | Yes | N/A | N/A | + +Example: +```python +>>> tw.put("/vault/credentials/{cred_id}",{"enabled": true}) + ``` +## about() + +[Deprecated] See [api_about](#api_about) for usage. + +Syntax: `.about()` + +## admin() + +[Deprecated] See [get_admin_about](#get_admin_about) for usage. + +Syntax: `.admin()` + +## swagger() + +[Deprecated] See [api_swagger](#api_swagger) for usage. + +Syntax: `.swagger()` + +## baseline() + +[Deprecated] See [get_admin_baseline](#get_admin_baseline) for usage. + +Syntax: `.baseline()` + ## licensing() Get the latest signed licensing report. @@ -137,7 +344,9 @@ Report end time : 2021-01-21 23:00:00.410085+00:00 Syntax: -```.help(([ _endpoint_ ]))``` +``` +.help([ _endpoint_ ]) +``` | Parameters | Type | Required | Default Value | Options | | ------------ | ------ | :------: | ------------- | ----------------------------------------------- | @@ -154,4 +363,4 @@ Endpoint Function Description /vault/credentials/{cred_id} updateCredential(cred_id, body) Updates partial resources of a credential. Missing properties are left unchanged. /vault/credentials/{cred_id} replaceCredential(cred_id, body) Replaces a single credential. All required credential properties must be present. -``` +``` \ No newline at end of file diff --git a/docs/endpoints/credentials.md b/docs/endpoints/credentials.md index d00cdc6..204c1b0 100644 --- a/docs/endpoints/credentials.md +++ b/docs/endpoints/credentials.md @@ -1,5 +1,5 @@ --- -sort: 5 +sort: 3 --- # Credentials @@ -20,14 +20,14 @@ Initiation: >>> credentials = tw.credentials() ``` -## listCredentialTypes() +## get_vault_credential_type() Get a list of all credential types and filter by group and/or category. Syntax: ``` -.listCredentialTypes([ _group_ ] [, _category_ ]) +.get_vault_credential_type([ _group_ ] [, _category_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -38,7 +38,7 @@ Syntax: Example: ```python ->>> db_creds = credentials.listCredentialTypes(category="Database") +>>> db_creds = credentials.get_vault_credential_type(category="Database") >>> from pprint import pprint >>> pprint(db_creds.json()) [ @@ -57,14 +57,18 @@ Example: ... ``` -## credentialType() +## get_vault_credential_types + +List all credential types. See [get_vault_credential_type](#get_vault_credential_type). + +## get_vault_credential_type_name() Get the properties of a specific credential type. Syntax: ``` -.credentialType(__cred_type_name__) +.get_vault_credential_type_name(__cred_type_name__) ``` | Parameters | Type | Required | Default Value | Options | @@ -72,7 +76,7 @@ Syntax: | cred_type_name | String | Yes | N/A | N/A | ```python ->>> ora_creds.credentials.credentialType("oracle").json() +>>> ora_creds.credentials.get_vault_credential_type_name("oracle").json() >>> from pprint import pprint >>> pprint(ora_creds.json()) { @@ -90,14 +94,14 @@ Syntax: } ``` -## listCredentials() +## get_vault_credential() Get a list of credentials. Syntax: ``` -.listCredentials([ _uuid_ ]) +.get_vault_credential([ _uuid_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -107,19 +111,23 @@ Syntax: Example: ```python ->>> creds = credentials.listCredentials("e7f00000106c1") +>>> creds = credentials.get_vault_credential("e7f00000106c1") >>> print(creds.json()['types']) ['ssh'] ``` -## newCredential() +## get_vault_credentials + +List all vault credentials. See [get_vault_credential](#get_vault_credential). + +## post_vault_credential() Create a new credential. Syntax: ``` -.newCredential(__json__) +.post_vault_credential(__json__) ``` | Parameters | Type | Required | Default Value | Options | @@ -129,17 +137,17 @@ Syntax: Example: ```python ->>> credentials.newCredential({"enabled": True,"username": "discovery_service","password": "password","label": "SSH Service Account","description": "Service Account for SSH","ip_range": "0.0.0.0/0,::/0","types": ["ssh"]}).ok +>>> credentials.post_vault_credential({"enabled": True,"username": "discovery_service","password": "password","label": "SSH Service Account","description": "Service Account for SSH","ip_range": "0.0.0.0/0,::/0","types": ["ssh"]}).ok True ``` -## deleteCredential() +## delete_vault_credential() Delete a credential. Syntax: ``` -.deleteCredential([ _uuid_ ]) +.delete_vault_credential([ _uuid_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -149,17 +157,17 @@ Syntax: Example: ```python ->>> credentials.deleteCredential("e7f00000106c1").ok +>>> credentials.delete_vault_credential("e7f00000106c1").ok True ``` -## updateCredential() +## patch_vault_credential() Updates partial resources of a credential. Missing properties are left unchanged. Syntax: ``` -.updateCredential(__uuid__, __json__) +.patch_vault_credential(__uuid__, __json__) ``` | Parameters | Type | Required | Default Value | Options | @@ -170,11 +178,11 @@ Syntax: Example: ```python ->>> credentials.updateCredential("a1b2c3d4e5f6",{ "enabled" : False }).ok +>>> credentials.patch_vault_credential("a1b2c3d4e5f6",{ "enabled" : False }).ok True ``` -## replaceCredential() +## put_vault_credential() Replaces a single credential. @@ -184,7 +192,7 @@ All required credential properties must be present. Optional properties that are Syntax: ``` -.replaceCredential(__uuid__, __json__) +.put_vault_credential(__uuid__, __json__) ``` | Parameters | Type | Required | Default Value | Options | @@ -195,6 +203,48 @@ Syntax: Example: ```python ->>> tc.replaceCredential("a1b2c3d4e5f6",{"enabled": True,"username": "discovery_service","password": "password","label": "Limited SSH Discovery","description": "Limited SSH Service Account","ip_range": "192.168.1.0/24","types":["ssh"]}).ok +>>> credentials.put_vault_credential("a1b2c3d4e5f6",{"enabled": True,"username": "discovery_service","password": "password","label": "Limited SSH Discovery","description": "Limited SSH Service Account","ip_range": "192.168.1.0/24","types":["ssh"]}).ok True -``` \ No newline at end of file +``` + +## listCredentialTypes() + +[Deprecated] See [get_vault_credential_type](#get_vault_credential_type) for usage. + +Syntax: `.listCredentialTypes([ _group_ ] [, _category_ ])` + +## credentialType() + +[Deprecated] See [get_vault_credential_type_name](#get_vault_credential_type_name) for usage. + +Syntax: `.credentialType(__cred_type_name__)` + +## listCredentials() + +[Deprecated] See [get_vault_credential](#get_vault_credential) for usage. + +Syntax: `.listCredentials([ _uuid_ ])` + +## newCredential() + +[Deprecated] See [post_vault_credential](#post_vault_credential) for usage. + +Syntax: `.newCredential(__json__)` + +## deleteCredential() + +[Deprecated] See [delete_vault_credential](#delete_vault_credential) for usage. + +Syntax: `.deleteCredential([ _uuid_ ])` + +## updateCredential() + +[Deprecated] See [patch_vault_credential](#patch_vault_credential) for usage. + +Syntax: `.updateCredential(__uuid__, __json__)` + +## replaceCredential() + +[Deprecated] See [put_vault_credential](#put_vault_credential) for usage. + +Syntax: `.replaceCredential(__uuid__, __json__)` \ No newline at end of file diff --git a/docs/endpoints/data.md b/docs/endpoints/data.md index 29a1cf3..35d99e5 100644 --- a/docs/endpoints/data.md +++ b/docs/endpoints/data.md @@ -1,5 +1,5 @@ --- -sort: 3 +sort: 4 --- # Data @@ -20,6 +20,30 @@ Initiation: >>> data = tw.data() ``` +## get_data_search() + +Default search. See [search](#search) for usage. + +## post_data_search() + +Alternative search method. See [search](#search) for usage. + +## get_data_search_object() + +Search defaulted to 'object' format. See [search](#search) for usage. + +## post_data_search_object() + +Alternative search method defaulted to 'object' format. See [search](#search) for usage. + +## get_data_search_tree() + +Search defaulted to 'tree' format. See [search](#search) for usage. + +## post_data_search_tree() + +Alternative search method defaulted to 'tree' format. See [search](#search) for usage. + ## search() Run a search query, receiving paginated results. @@ -32,7 +56,7 @@ Syntax: | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | -| query | | Yes | N/A | | +| query | | Yes | N/A | N/A | | offset | Integer | No | N/A | N/A | | results_id | String | No | N/A | N/A | | format | String | No | N/A | | @@ -96,59 +120,121 @@ Example: This search_bulk() returns 500 results each time, and makes 2 additiona 1510 ``` -## searchQuery() +## post_data_condition() -An alternative to GET /data/search, for search queries which are too long for urls. - -```note -This method is deprecated. You can use search() for both JSON arguments and search strings. -``` +Search using a condition, return tabular results as arrays. Syntax: ``` -.search(__json__ [, _offset_ ] [, _results_id_ ] [, _format_ ] [, _limit_ ] [, _delete_ ]) +.post_data_condition(__body__ [, _offset_ ] [, _results_id_ ] [, _format_ ] [, _limit_ ] [, _delete_ ]) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | -| json | JSON Object | Yes | N/A | {"query":"search string"} | +| body | JSON Object | Yes | N/A | N/A | | offset | Integer | No | N/A | N/A | | results_id | String | No | N/A | N/A | | format | String | No | N/A | | | limit | Integer | No | 100 | N/A | | delete | Boolean | No | False | | +## post_data_condition_param_values() + +Get possible parameter values for a condition. + +Syntax: + +``` +.post_data_condition_param_values(__body__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| body | JSON Object | Yes | N/A | N/A | + +## get_data_condition_template() + +Get a list of all available templates. + +Syntax: + +``` +.get_data_condition_template([ _template_id_ ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| template_id | String | No | N/A | N/A | + +Example: + ```python ->>> data.searchQuery({"query": "search Host show os_class process with unique()"}, format="object").json() -[ - { - 'count': 3, - 'kind': 'Unique row', - 'offset': 0, - 'results': [ - { - 'os_class': 'UNIX' - }, - { - 'os_class': 'Windows' - }, - { - 'os_class': 'Other' - } - ] - } -] +>>> templates = data.get_data_condition_template() +>>> print(templates.text) +[] ``` -## nodeLookup() +## get_data_condition_templates + +Get a list of all available templates. See [get_data_condition_template](#get_data_condition_template). + +## post_data_candidate() + +The node object of the best candidate based on the provided parameters. + +Syntax: + +``` +.post_data_candidate(__json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| json | JSON Object | Yes | N/A | N/A | + +Example: + +```python +>>> candidates = data.post_data_candidate({"hostname": "disco","kind" : "Host"}) +>>> print(candates.text) +{ + "#id": "30c577625e064d10300b17ea6e486f7374", + "__all_dns_names": [ + "disco.local" + ], + "__all_ip_addrs": [ + "10.16.15.99", + "fe80::4bcc:a31c:43a:c258" + ], + "__all_mac_addrs": [ + "02:11:32:23:29:f0" + ], +... +``` + +## post_data_candidates() + +Enter parameters to identify a device, the response is a list of candidate nodes ordered by descending score. + +Syntax: + +``` +.post_data_candidates(__json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| json | JSON Object | Yes | N/A | N/A | + +## get_data_nodes() Get the state of a node with specified id. Syntax: ``` -.nodeLookup(__node_id__ [, _relationships_ ] [, _traverse_ ] [, _flags_ ]) +.get_data_nodes(__node_id__ [, _relationships_ ] [, _traverse_ ] [, _flags_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -161,19 +247,35 @@ Syntax: Example: ```python ->>> node = data.nodeLookup("a1b2c3d4e5f6") +>>> node = data.get_data_nodes("a1b2c3d4e5f6") >>> print(node.json()['state']['os_type']) Windows Desktop ``` -## lookupNodeKind() +## get_data_nodes_graph() + +Graph data represents a set of nodes and relationships that are associated to the given node. + +Syntax: + +``` +.get_data_nodes_graph(__node_id__ [, _focus_ ] [, _apply_rules_ ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| node_id | JSON Object | Yes | N/A | N/A | +| focus | String | No | N/A | | +| apply_rules | Boolean | No | False | | + +## get_data_kinds() Finds all nodes of a specified node kind. Syntax: ``` -.lookupNodeKind(__kind__ [, _offset_ ] [, _results_id_ ] [, _format_ ] [, _limit_ ] [, _delete_ ]) +.get_data_kinds(__kind__ [, _offset_ ] [, _results_id_ ] [, _format_ ] [, _limit_ ] [, _delete_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -188,41 +290,25 @@ Syntax: Example: Gets result #50 from list of nodes ```python ->>> sis = data.lookupNodeKind("SoftwareInstance") +>>> sis = data.get_data_kinds("SoftwareInstance") >>> print(sis.json()[0]['results'][50]) ['0x7761771a5876f667606e53426', 'Apache Webserver', 'Apache Webserver 2.4 on batman3', '2.4', 'batman3'] ``` -## graphNode() +## get_data_partitions Graph data represents a set of nodes and relationships that are associated to the given node. Syntax: ``` -.graphNode(__node_id__ [, _focus_ ] [, _apply_rules_ ]) -``` - -| Parameters | Type | Required | Default Value | Options | -| ------------- | ----------- | :------: | ------------- | -------- | -| node_id | JSON Object | Yes | N/A | N/A | -| focus | String | No | N/A | | -| apply_rules | Boolean | No | False | | - -## partitions() - -Graph data represents a set of nodes and relationships that are associated to the given node. - -Syntax: - -``` -.partitions() +.get_data_partitions() ``` Example: ```python ->>> partitions = data.partions() +>>> partitions = data.get_data_partitions() >>> from pprint import pprint >>> pprint(partitions.json()) { @@ -236,58 +322,98 @@ Example: } ``` -## candidate() +## searchQuery() -The node object of the best candidate based on the provided parameters. +[Deprecated] See [search](#search) for usage. -Syntax: +Syntax: `.searchQuery(__json__ [, _offset_ ] [, _results_id_ ] [, _format_ ] [, _limit_ ] [, _delete_ ])` -``` -.candidate(__json__) -``` +## nodeLookup() -| Parameters | Type | Required | Default Value | Options | -| ------------- | ----------- | :------: | ------------- | -------- | -| json | JSON Object | Yes | N/A | N/A | +[Deprecated] See [get_data_nodes](#get_data_nodes) for usage. -## candidates() +Syntax: `.nodeLookup(__node_id__ [, _relationships_ ] [, _traverse_ ] [, _flags_ ])` -Enter parameters to identify a device, the response is a list of candidate nodes ordered by descending score. +## lookupNodeKind() + +[Deprecated] See [get_data_kinds](#get_data_kinds) for usage. + +Syntax: `.lookupNodeKind(__kind__ [, _offset_ ] [, _results_id_ ] [, _format_ ] [, _limit_ ] [, _delete_ ])` + +## graphNode() + +[Deprecated] See [get_data_nodes_graph](#get_data_nodes_graph) for usage. + +Syntax: `.graphNode(__node_id__ [, _focus_ ] [, _apply_rules_ ]))` + +## partitions() + +[Deprecated] See [get_data_nodes_graph](#get_data_nodes_graph) for usage. + +Syntax: `.partitions()` + +## post_data_partitions() + +Create a Partition. Syntax: ``` -.candidates(__json__) +.post_data_partitions(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | -## twImport() +## post_data_import() Imports data. Returns the import UUID. Syntax: ``` -.twImport(__json__) +.post_data_import(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | -## twWrite() +## post_data_write() Perform arbitrary write operations. Syntax: ``` -.twWrite(__json__) +.post_data_write(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | -| json | JSON Object | Yes | N/A | N/A | \ No newline at end of file +| json | JSON Object | Yes | N/A | N/A | + +## best_candidate() + +[Deprecated] See [post_data_candidate](#post_data_candidate) for usage. + +Syntax: `.post_data_candidate(__JSON__)` + +## top_candidates() + +[Deprecated] See [post_data_candidates](#post_data_candidates) for usage. + +Syntax: `.post_data_candidates(__json__)` + +## twImport() + +[Deprecated] See [post_data_import](#post_data_import) for usage. + +Syntax: `.twImport(__json__)` + +## twWrite() + +[Deprecated] See [post_data_write](#post_data_write) for usage. + +Syntax: `.twWrite(__json__)` \ No newline at end of file diff --git a/docs/endpoints/discovery.md b/docs/endpoints/discovery.md index 964b60f..3e154a1 100644 --- a/docs/endpoints/discovery.md +++ b/docs/endpoints/discovery.md @@ -1,5 +1,5 @@ --- -sort: 2 +sort: 5 --- # Discovery @@ -20,30 +20,30 @@ Initiation: >>> discovery = tw.discovery() ``` -## getDiscoveryStatus() +## get_discovery Get the current status of the discovery process. Syntax: ``` -.getDiscoveryStatus() +.get_discovery ``` Example: ```python ->>> >>> discovery.getDiscoveryStatus().json() +>>> >>> discovery.get_discovery.json() {'running': False, 'status': 'running'} ``` -## setDiscoveryStatus() +## patch_discovery() Start or stop the discovery process. Syntax: ``` -.setDiscoveryStatus(__json__) +.patch_discovery(__json__) ``` | Parameters | Type | Required | Default Value | Options | @@ -53,87 +53,139 @@ Syntax: Example: ```python ->>> >>> discovery.getDiscoveryStatus().json() +>>> >>> discovery.get_discovery.json() {'running': False, 'status': 'stopped'} ->>> discovery.setDiscoveryStatus({"status": "running"}).ok +>>> discovery.patch_discovery({"status": "running"}).ok True ->>> >>> discovery.getDiscoveryStatus().json() +>>> >>> discovery.get_discovery.json() {'running': False, 'status': 'running'} ``` -## getApiProviderMetadata() +## get_discovery_api_provider_metadata Get metadata for the API providers currently supported by BMC Discovery. Syntax: ``` -.getApiProviderMetadata() +.get_discovery_api_provider_metadata ``` ```python ->>> discovery.getApiProviderMetadata().json()[0]['cred_params'][0] +>>> discovery.get_discovery_api_provider_metadata.json()[0]['cred_params'][0] {'allowed_values': [], 'description': 'URL of the Kubernetes/OpenShift cluster with port', 'is_list': False, 'mandatory': False, 'name': 'kubernetes.cluster_url', 'type': 'str'} ``` -## getDiscoveryCloudMetaData() +## get_discovery_api_cloud_metadata Get metadata for the cloud providers currently supported by BMC Discovery. Syntax: ``` -.getDiscoveryCloudMetaData() +.get_discovery_api_cloud_metadata ``` ```python -discovery.getDiscoveryCloudMetaData().json()[0]['cred_params'][0] +discovery.get_discovery_api_cloud_metadata.json()[0]['cred_params'][0] {'allowed_values': [], 'description': 'Azure Directory ID (also known as the Tenant ID)', 'is_list': False, 'mandatory': True, 'name': 'azure.tenant_id', 'type': 'str'} ``` -## discoveryRun() +## getDiscoveryStatus() -Create a new snapshot discovery run. +[Deprecated] See [get_discovery](#get_discovery) for usage. + +Syntax: `.getDiscoveryStatus()` + +## setDiscoveryStatus() + +[Deprecated] See [patch_discovery](#patch_discovery) for usage. + +Syntax: `.setDiscoveryStatus(__json__)` + +## getApiProviderMetadata() + +[Deprecated] See [get_discovery_api_provider_metadata](#get_discovery_api_provider_metadata) for usage. + +Syntax: `.getApiProviderMetadata()` + +## getDiscoveryCloudMetaData() + +[Deprecated] See [get_discovery_api_cloud_metadata](#get_discovery_api_cloud_metadata) for usage. + +Syntax: `.getDiscoveryCloudMetaData()` + +## get_discovery_exclude() + +Get a list of all or specific excludes. Syntax: ``` -.discoveryRun(__json__) +.get_discovery_exclude([ _exclude_id_ ]) ``` | Parameters | Type | Required | Default Value | Options | | ------------ | ----------- | :------: | ------------- | --------| -| json | JSON Object | Yes | N/A | N/A | +| exclude_id | String | No | N/A | N/A | + +## get_discovery_excludes + +Get a list of all excludes. See [get_discovery_exclude](#get_discovery_exclude). + +Syntax: `.get_discovery_excludes` + +## post_discovery_exclude() + +Update an exclude list. + +Syntax: -Example: -```python ->>> discovery.discoveryRun({"ranges":[ "192.168.1.0/24" ],"label":"Network Snapshot","scan_level":"Full Discovery"}).ok -True ``` -## getDiscoveryRuns() +.post_discovery_exclude(__json__) +``` -Get details of all currently processing discovery runs. +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| json | JSON Object | Yes | N/A | N/A | + +## delete_discovery_exclude() + +Delete an exclude list. Syntax: ``` -.getDiscoveryRuns() +.delete_discovery_exclude(__exclude_id__) ``` -Example: -```python ->>> discovery.getDiscoveryRuns().json() -[] +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| exclude_id | String | Yes | N/A | N/A | + +## patch_discovery_exclude() + +Update an exclude list. + +Syntax: + +``` +.patch_discovery_exclude(__json__, __exclude_id__) ``` -## getDiscoveryRun() +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| json | JSON Object | Yes | N/A | N/A | +| exclude_id | String | Yes | N/A | N/A | + +## get_discovery_run() Get details of specific currently processing discovery run. Syntax: ``` -.getDiscoveryRun(__run_id__) +.get_discovery_run(__run_id__) ``` | Parameters | Type | Required | Default Value | Options | @@ -142,7 +194,7 @@ Syntax: Example: ```python ->>> run = discovery.getDiscoveryRun("1234567890") +>>> run = discovery.get_discovery_run("1234567890") >>> from pprint import pprint >>> pprint(run.json()) [ @@ -158,69 +210,85 @@ Example: ] ``` -## updateDiscoveryRun() +## get_discovery_runs -Update the state of a specific discovery run. +Get details of all currently processing discovery runs. See [get_discovery_run](#get_discovery_run). + +Syntax: `.get_discovery_runs` + +## post_discovery_run() + +Create a new snapshot discovery run. Syntax: ``` -.updateDiscoveryRun(__run_id__, __json__) +.post_discovery_run(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------ | ----------- | :------: | ------------- | --------| -| run_id | String | Yes | N/A | N/A | | json | JSON Object | Yes | N/A | N/A | Example: ```python ->>> discovery.updateDiscoveryRun("1234567890", {"cancelled": True}).ok +>>> discovery.post_discovery_run({"ranges":[ "192.168.1.0/24" ],"label":"Network Snapshot","scan_level":"Full Discovery"}).ok True ``` -## getDiscoveryRunResults() +## patch_discovery_run() -Get a summary of the results from scanning all endpoints in the run, partitioned by result type. +Update the state of a specific discovery run. Syntax: ``` -.getDiscoveryRunResults(__run_id__) +.patch_discovery_run(__run_id__, __json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------ | ----------- | :------: | ------------- | --------| | run_id | String | Yes | N/A | N/A | +| json | JSON Object | Yes | N/A | N/A | Example: ```python ->>> run = discovery.getDiscoveryRunResults("1234567890") ->>> print(run.text) -{ - "Dropped": { - "count": 204, - "uri": "https://appliance/api/v1.2/discovery/runs/1234567890/results/Dropped" - }, - "Skipped": { - "count": 3, - "uri": "https://appliance/api/v1.2/discovery/runs/1234567890/results/Skipped" - }, - "Success": { - "count": 47, - "uri": "https://appliance/api/v1.2/discovery/runs/1234567890/results/Success" - } -} +>>> discovery.patch_discovery_run("1234567890", {"cancelled": True}).ok +True ``` -## getDiscoveryRunResult() +## getDiscoveryRun() + +[Deprecated] See [get_discovery_run](#get_discovery_run) for usage. + +Syntax: `.getDiscoveryRun(__run_id__)` + +## getDiscoveryRuns() + +[Deprecated] See [get_discovery_runs](#get_discovery_runs) for usage. + +Syntax: `.getDiscoveryRuns()` + +## discoveryRun() + +[Deprecated] See [post_discovery_run](#post_discovery_run) for usage. -Get a summary of the results from scanning all endpoints in the run that had a specific type of result. +Syntax: `.discoveryRun(__json__)` + +## updateDiscoveryRun() + +[Deprecated] See [patch_discovery_run](#patch_discovery_run) for usage. + +Syntax: `.updateDiscoveryRun(__run_id__, __json__)` + +## get_discovery_run_results() + +Get a summary of the results from scanning all endpoints in the run, partitioned by result type that had a specific type of result. Syntax: ``` -.getDiscoveryRunResult(__run_id__ [, result ] [, offset ] [, results_id ] [, format ] [, limit ] [, delete ]) +.get_discovery_run_results(__run_id__ [, result ] [, offset ] [, results_id ] [, format ] [, limit ] [, delete ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -233,43 +301,52 @@ Syntax: | limit | Integer | No | 100 | N/A | | delete | Boolean | No | False | | -Example: Retrieve DiscoveryRuns which ended with an Error, and retrieve result rows 51-100. +Example: ```python ->>> discovery.getDiscoveryRunResult("1234567890", result="Error", offset=50, results_id="a12b3cd4e5f6", limit=50) +>>> run = discovery.get_discovery_run_results("1234567890") +>>> print(run.text) +{ + "Dropped": { + "count": 204, + "uri": "https://appliance/api/v1.2/discovery/runs/1234567890/results/Dropped" + }, + "Skipped": { + "count": 3, + "uri": "https://appliance/api/v1.2/discovery/runs/1234567890/results/Skipped" + }, + "Success": { + "count": 47, + "uri": "https://appliance/api/v1.2/discovery/runs/1234567890/results/Success" + } +} ``` -## getDiscoveryRunInferred() -Get a summary of all inferred devices from a discovery run, partitioned by device type. +## getDiscoveryRunResults() -Syntax: +[Deprecated] See [get_discovery_run_results](#get_discovery_run_results) for usage. -``` -.getDiscoveryRunInferred(__run_id__) -``` +Syntax: `.getDiscoveryRunResults(__run_id__)` -| Parameters | Type | Required | Default Value | Options | -| ------------ | ----------- | :------: | ------------- | -------- | -| run_id | String | Yes | N/A | N/A | +## getDiscoveryRunResult() -Example: -```python ->>> discovery.getDiscoveryRunInferred("1234567890") -``` +[Deprecated] See [get_discovery_run_results](#get_discovery_run_results) for usage. -## getDiscoveryRunInferredKind() +Syntax: `.getDiscoveryRunResults(__run_id__, __result__ [, offset ] [, results_id ] [, format ] [, limit ] [, delete ])` -Get a summary of the devices inferred by a discovery run which have a specific inferred kind. +## get_discovery_run_inferred() + +Get a summary of all inferred devices from a discovery run, partitioned by device type and/or which have a specific inferred kind. Syntax: ``` -.getDiscoveryRunInferredKind(__run_id__ , __inferred_kind__ [, offset ] [, results_id ] [, format ] [, limit ] [, delete ]) +.get_discovery_run_inferred(__run_id__ [, inferred_kind ] [, offset ] [, results_id ] [, format ] [, limit ] [, delete ]) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | run_id | String | Yes | N/A | N/A | -| inferred_kind | String | Yes | N/A | N/A | +| inferred_kind | String | No | N/A | N/A | | offset | Integer | No | N/A | N/A | | results_id | String | No | N/A | N/A | | format | String | No | N/A | | @@ -278,7 +355,7 @@ Syntax: Example: ```python ->>> result = discovery.getDiscoveryRunResult("1234567890", "Host", format="object") +>>> result = discovery.get_discovery_run_inferred("1234567890", "Host", format="object") >>> print(result.text) [ { @@ -295,4 +372,79 @@ Example: ], '#id': 'A1B2C3D4E5F6' ... -``` \ No newline at end of file +``` + +## getDiscoveryRunInferred() + +[Deprecated] See [get_discovery_run_inferred](#get_discovery_run_inferred) for usage. + +Syntax: `.getDiscoveryRunInferred(__run_id__)` + +## getDiscoveryRunInferredKind() + +[Deprecated] See [get_discovery_run_inferred](#get_discovery_run_inferred) for usage. + +Syntax: `.getDiscoveryRunInferredKind(__run_id__ , __inferred_kind__ [, offset ] [, results_id ] [, format ] [, limit ] [, delete ])` + +## get_discovery_run_schedule() + +Get a list of all or specific scan schedules. + +Syntax: + +``` +.get_discovery_run_schedule([ _run_id_ ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| run_id | String | No | N/A | N/A | + +## get_discovery_run_schedules() + +Get a list of all or specific scan schedules. See [get_discovery_run_schedule](#get_discovery_run_schedule). + +Syntax: `.get_discovery_run_schedules` + +## post_discovery_run_schedule() + +Add a new scan schedule. + +Syntax: + +``` +.post_discovery_run_schedule(__json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| json | JSON Object | Yes | N/A | N/A | + +## delete_discovery_run_schedule() + +Delete a specific scan schedule. + +Syntax: + +``` +.delete_discovery_run_schedule(__run_id__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| run_id | String | Yes | N/A | N/A | + +## patch_discovery_run_schedule() + +Update a specific scan schedule. + +Syntax: + +``` +.patch_discovery_run_schedule(__run_id__, __json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | --------| +| run_id | String | Yes | N/A | N/A | +| json | JSON Object | Yes | N/A | N/A | \ No newline at end of file diff --git a/docs/endpoints/events.md b/docs/endpoints/events.md index 8e6f89e..4592449 100644 --- a/docs/endpoints/events.md +++ b/docs/endpoints/events.md @@ -1,5 +1,5 @@ --- -sort: 7 +sort: 6 --- # Events @@ -20,16 +20,22 @@ Initiation: >>> events = tw.events() ``` -## status() +## post_events() Returns a unique ID if the event has been recorded, otherwise an empty string is returned e.g. if the event source has been disabled. Syntax: ``` -.status(__json__) +.post_events(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | + +## status() + +[Deprecated] See [post_events](#post_events) for usage. + +Syntax: `.status(__json__)` \ No newline at end of file diff --git a/docs/endpoints/kerberos.md b/docs/endpoints/kerberos.md new file mode 100644 index 0000000..cf1eb30 --- /dev/null +++ b/docs/endpoints/kerberos.md @@ -0,0 +1,172 @@ +--- +sort: 7 +--- + +# Kerberos + +Initiate a kerberos object for the instance of Discovery you intend to query. + +Syntax: + +``` +tideway.kerberos(__target__, __token__ [, _api_version_ ] [, _ssl_verify_ ]) +``` + +Initiation: + +```python +>>> import tideway +>>> tw = tideway.appliance('appliance-hostname','auth-token') +>>> kerberos = tw.kerberos() +``` + +## get_vault_kerberos_realm() + +Retrieve all or specific realm. + +Syntax: + +``` +.get_vault_kerberos_realm([ _realm_name_ ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | No | N/A | N/A | + +## get_vault_kerberos_realms + +Retrieve all realms. See [get_vault_kerberos_realm](#get_vault_kerberos_realm). + +Syntax: `.get_vault_kerberos_realms` + +## post_vault_kerberos_realm() + +Create a realm and Test user credentials by attempting to acquire a new Kerberos Ticket Granting Ticket (TGT) + +Syntax: + +``` +.post_vault_kerberos_realm(__realm_name__, __json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| json | JSON Object | Yes | N/A | N/A | + +## delete_vault_kerberos_realm() + +Delete a realm. + +Syntax: +``` +.delete_vault_kerberos_realm(__realm_name__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | + +## patch_vault_kerberos_realm() + +Update a Kerberos realm. + +Syntax: +``` +.patch_vault_kerberos_realm(__realm_name__, __json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| json | JSON Object | Yes | N/A | N/A | + +## get_vault_kerberos_keytabs() + +List users with a Kerberos keytab file. + +Syntax: + +``` +.get_vault_kerberos_keytabs(__realm_name__, __username__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| username | String | Yes | N/A | N/A | + +## post_vault_kerberos_keytab() + +Upload a Kerberos keytab file. + +Syntax: + +``` +.post_vault_kerberos_keytab(__realm_name__, __username__, __keytab_file__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| username | String | Yes | N/A | N/A | +| keytab_file | File Object | Yes | N/A | N/A | + +## delete_vault_kerberos_keytab() + +Delete a keytab file. + +Syntax: +``` +.delete_vault_kerberos_keytab(__realm_name__, __username__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| username | String | Yes | N/A | N/A | + +## get_vault_kerberos_ccaches() + +List users with a Kerberos credential cache file. + +Syntax: + +``` +.get_vault_kerberos_ccaches(__realm_name__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | + +## post_vault_kerberos_ccache() + +Upload a Kerberos credential cache file. + +Syntax: + +``` +.post_vault_kerberos_ccache(__realm_name__, __username__, __cache_file__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| username | String | Yes | N/A | N/A | +| cache_file | File Object | Yes | N/A | N/A | + +## delete_vault_kerberos_ccache() + +Delete a cedential cache file. + +Syntax: +``` +.delete_vault_kerberos_ccache(__realm_name__, __username__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| realm_name | String | Yes | N/A | N/A | +| username | String | Yes | N/A | N/A | \ No newline at end of file diff --git a/docs/endpoints/knowledge.md b/docs/endpoints/knowledge.md index 8534e9f..0652108 100644 --- a/docs/endpoints/knowledge.md +++ b/docs/endpoints/knowledge.md @@ -1,5 +1,5 @@ --- -sort: 6 +sort: 8 --- # Knowledge @@ -20,37 +20,37 @@ Initiation: >>> knowledge = tw.knowledge() ``` -## getKnowledgeManagement() +## get_knowledge Get the current state of the appliance's knowledge, including TKU versions. Syntax: ``` -.getKnowledgeManagement() +.get_knowledge ``` Example: ```python ->>> >>> knowledge.getKnowledgeManagement().json()['latest_tku']['submission_date'] +>>> >>> knowledge.get_knowledge.json()['latest_tku']['submission_date'] '2021-05-24T23:06:00.350840+00:00' ``` -## getUploadStatus() +## get_knowledge_status Get the current state of a knowledge upload. Syntax: ``` -.getUploadStatus() +.get_knowledge_status ``` Example: ```python ->>> upload = knowledge.getUploadStatus() +>>> upload = knowledge.get_knowledge_status >>> from pprint import pprint >>> pprint(upload.json()) { @@ -68,14 +68,14 @@ Example: } ``` -## uploadKnowledge() +## post_knowledge() Upload a TKU or pattern module to the appliance. Syntax: ``` -.uploadKnowledge(__filename__, __file__ [, _activate_ ] [, _allow_restart_ ]) +.post_knowledge(__filename__, __file__ [, _activate_ ] [, _allow_restart_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -88,6 +88,24 @@ Syntax: Example: ```python ->>> knowledge.uploadKnowledge("TestPattern.tpl","C:/Users/User001/Documents/TestPattern.tpl").ok +>>> knowledge.post_knowledge("TestPattern.tpl","C:/Users/User001/Documents/TestPattern.tpl").ok True -``` \ No newline at end of file +``` + +## getKnowledgeManagement() + +[Deprecated] See [get_knowledge](#get_knowledge) for usage. + +Syntax: `.getKnowledgeManagement()` + +## getUploadStatus() + +[Deprecated] See [get_knowledge_status](#get_knowledge_status) for usage. + +Syntax: `.getUploadStatus()` + +## uploadKnowledge() + +[Deprecated] See [post_knowledge](#post_knowledge) for usage. + +Syntax: `.uploadKnowledge(__filename__, __file__ [, _activate_ ] [, _allow_restart_ ])` \ No newline at end of file diff --git a/docs/endpoints/models.md b/docs/endpoints/models.md new file mode 100644 index 0000000..0764365 --- /dev/null +++ b/docs/endpoints/models.md @@ -0,0 +1,250 @@ +--- +sort: 9 +--- + +# Models + +Initiate a Model object for the instance of Discovery you intend to query. + +Syntax: + +``` +tideway.models(__target__, __token__ [, _api_version_ ] [, _ssl_verify_ ]) +``` + +Initiation: + +```python +>>> import tideway +>>> tw = tideway.appliance('appliance-hostname','auth-token') +>>> model = tw.models() +``` + +## get_model() + +Retrieve service and application models. + +Syntax: + +``` +.get_model([ _name_ ] [, type ] [, kind ] [, published ] [, review_suggested ] [, version ] [, favorite ] [, compatibility ] [, results_id ] [, delete ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | -------- | +| name | String | No | N/A | N/A | +| type | String | No | N/A | | +| kind | String | No | N/A | | +| published | Boolean | No | N/A | | +| review_suggested | Boolean | No | N/A | | +| version | String | No | N/A | N/A | +| favorite | Boolean | No | N/A | | +| compatibility | String | No | N/A | N/A | +| results_id | String | No | N/A | N/A | +| delete | Boolean | No | False | | + +## get_models + +Retrieve all models. See [get_model](#get_model). + +Syntax: `.get_models` + +## post_model() + +Create a new model. + +Syntax: + +``` +.post_model(__json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| json | JSON Object | Yes | N/A | N/A | + +## post_model_multi() + +Create multiple new models. + +Syntax: + +``` +.post_model_multi(__json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| json | JSON Object | Yes | N/A | N/A | + +## get_model_key() + +Get model definition for the specified key. + +Syntax: + +``` +.get_model_key(__key__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | + +## delete_model() + +Delete a model. + +Syntax: +``` +.delete_model(__key__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | + +## patch_model() + +Update a model. + +Syntax: +``` +.patch_model(__key__, __json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | +| json | JSON Object | Yes | N/A | N/A | + +## get_model_topology() + +Get topology for the model definition specified by key. + +Syntax: + +``` +.get_model_topology(__key__ [, attributes ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | +| attributes | String (CSV) | No | N/A | N/A | + +## get_model_nodecount() + +Get node count for the model definition specified by key. + +Syntax: + +``` +.get_model_nodecount(__key__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | + +## get_model_nodes() + +Retrieve service and application models. + +Syntax: + +``` +.get_model_nodes(__key__ [, results_id ] [, delete ] [, kind ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | +| results_id | String | No | N/A | N/A | +| delete | Boolean | No | False | | +| kind | String | No | N/A | N/A | + +## get_model_by_node_id() + +Get model definition for the specified node id. + +Syntax: +``` +.get_model_by_node_id(__node_id__ [, expand_related ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| node_id | String | Yes | N/A | N/A | +| expand_related | Boolean | Yes | N/A | | + +## delete_model_by_node_id() + +Delete a model. + +Syntax: +``` +.delete_model_by_node_id(__node_id__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| node_id | String | Yes | N/A | N/A | + +## patch_model_by_node_id() + +Delete a model. + +Syntax: +``` +.patch_model_by_node_id(__node_id__, __json__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| node_id | String | Yes | N/A | N/A | +| json | JSON Object | Yes | N/A | N/A | + +## get_topology_by_node_id() + +Delete a model. + +Syntax: +``` +.get_topology_by_node_id(__node_id__ [, attributes ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| node_id | String | Yes | N/A | N/A | +| attributes | String (CSV) | No | N/A | N/A | + +## get_nodecount_by_node_id() + +Get node count for the model definition specified by node id. + +Syntax: +``` +.get_nodecount_by_node_id(__node_id__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| node_id | String | Yes | N/A | N/A | + +## get_nodes_by_node_id() + +Get nodes for the model definition specified by node id. + +Syntax: + +``` +.get_nodes_by_node_id(__node_id__ [, results_id ] [, delete ] [, kind ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------ | ----------- | :------: | ------------- | -------- | +| key | String | Yes | N/A | N/A | +| results_id | String | No | N/A | N/A | +| delete | Boolean | No | False | | +| kind | String | No | N/A | N/A | \ No newline at end of file diff --git a/docs/endpoints/taxonomy.md b/docs/endpoints/taxonomy.md new file mode 100644 index 0000000..a311fae --- /dev/null +++ b/docs/endpoints/taxonomy.md @@ -0,0 +1,98 @@ +--- +sort: 10 +--- + +# Taxonomy + +Initiate a Taxonomy object for the instance of Discovery you intend to query. + +Syntax: + +``` +tideway.taxonomy(__target__, __token__ [, _api_version_ ] [, _ssl_verify_ ]) +``` + +Initiation: + +```python +>>> import tideway +>>> tw = tideway.appliance('appliance-hostname','auth-token') +>>> taxonomy = tw.taxonomy() +``` + +## get_taxonomy_sections + +Get list of taxonomy model sections. + +Syntax: + +``` +.get_taxonomy_sections +``` + +## get_taxonomy_locales + +Get list of known taxonomy locales. + +Syntax: + +``` +.get_taxonomy_locales +``` + +## get_taxonomy_nodekind() + +Get list of defined node kinds with kind info. + +Syntax: +``` +.get_taxonomy_nodekind([ format ] [, section ] [, locale ] [, kind ] [, fieldlists ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| format | String | No | N/A | N/A | +| section | String | No | N/A | N/A | +| kind | String | No | N/A | N/A | +| fieldlists | Boolean | No | False | | + +## get_taxonomy_nodekinds + +Get list of all node kinds with kind info. See [get_taxonomy_nodekind](#get_taxonomy_nodekind). + +Syntax: `.get_taxonomy_nodekinds` + +## get_taxonomy_nodekind_fieldlist() + +Get list of fields for a node kind field list. + +Syntax: +``` +.get_taxonomy_nodekind_fieldlist(__kind__, __fieldlists__) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| kind | String | Yes | N/A | N/A | +| fieldlists | String | Yes | N/A | N/A | + +## get_taxonomy_relkind() + +Get list of defined node kinds with kind info. + +Syntax: +``` +.get_taxonomy_relkind( [ format, locale ] [, kind ]) +``` + +| Parameters | Type | Required | Default Value | Options | +| ------------- | ----------- | :------: | ------------- | -------- | +| format | String | No | N/A | N/A | +| locale | String | No | N/A | N/A | +| kind | String | No | N/A | N/A | + +## get_taxonomy_relkinds + +Get list of all node kinds with kind info. See [get_taxonomy_relkinds](#get_taxonomy_relkinds). + +Syntax: `.get_taxonomy_relkinds` \ No newline at end of file diff --git a/docs/endpoints/topology.md b/docs/endpoints/topology.md index f47e96e..ac6a2df 100644 --- a/docs/endpoints/topology.md +++ b/docs/endpoints/topology.md @@ -1,5 +1,5 @@ --- -sort: 8 +sort: 11 --- # Topology @@ -20,14 +20,14 @@ Initiation: >>> topo = tw.topology() ``` -## graphNode() +## get_data_nodes_graph() Graph data represents a set of nodes and relationships that are associated to the given node. Syntax: ``` -.graphNode(__node_id__ [, _focus_ ] [, _apply_rules_ ]) +.get_data_nodes_graph(__node_id__ [, _focus_ ] [, _apply_rules_ ]) ``` | Parameters | Type | Required | Default Value | Options | @@ -36,66 +36,103 @@ Syntax: | focus | String | No | N/A | | | apply_rules | Boolean | No | False | | -## getNodes() +## post_topology_nodes() Get topology data from one or more starting nodes. Syntax: ``` -.getNodes(__json__) +.post_topology_nodes(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | -## getNodeKinds() +## post_topology_nodes_kinds() Get nodes of the specified kinds which are related to a given set of nodes. Syntax: ``` -.getNodeKinds(__json__) +.post_topology_nodes_kinds(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | -## visualizationState() +## graphNode() + +[Deprecated] See [get_data_nodes_graph](#get_data_nodes_graph) for usage. + +Syntax: `.graphNode(__node_id__ [, _focus_ ] [, _apply_rules_ ])` + +## getNodes() + +[Deprecated] See [post_topology_nodes](#post_topology_nodes) for usage. + +Syntax: `.getNodes(__json__)` + +## getNodeKinds() + +[Deprecated] See [post_topology_nodes_kinds](#post_topology_nodes_kinds) for usage. + +Syntax: `.getNodeKinds(__json__)` + +## get_topology_viz_state Get the current state of the visualization for the authenticated user. Syntax: ``` -.visualizationState() +.get_topology_viz_state ``` -## updateVizState() +## patch_topology_viz_state() Update one or more attributes of the current state of the visualization for the authenticated user. Syntax: ``` -.updateVizState(__json__) +.patch_topology_viz_state(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | -## replaceVizState() + +## put_topology_viz_state() Update any or all of the attributes of the current state of the visualization for the authenticated user. Syntax: ``` -replaceVizState(__json__) +put_topology_viz_state(__json__) ``` | Parameters | Type | Required | Default Value | Options | | ------------- | ----------- | :------: | ------------- | -------- | | json | JSON Object | Yes | N/A | N/A | + +## visualizationState() + +[Deprecated] See [get_topology_viz_state](#get_topology_viz_state) for usage. + +Syntax: `.visualizationState()` + +## updateVizState() + +[Deprecated] See [patch_topology_viz_state](#patch_topology_viz_state) for usage. + +Syntax: `.updateVizState(__json__)` + +## replaceVizState() + +[Deprecated] See [put_topology_viz_state](#put_topology_viz_state) for usage. + +Syntax: `.replaceVizState(__json__)` \ No newline at end of file diff --git a/docs/endpoints/vault.md b/docs/endpoints/vault.md index 700d85c..8bfa8bc 100644 --- a/docs/endpoints/vault.md +++ b/docs/endpoints/vault.md @@ -1,5 +1,5 @@ --- -sort: 4 +sort: 12 --- # Vault @@ -20,31 +20,31 @@ Initiation: >>> vault = tw.vault() ``` -## getVault() +## get_vault Get details of the state of the vault. Syntax: ``` -.getVault() +.get_vault ``` Example: ```python ->>> vault.getVault().json() +>>> vault.get_vault.json() {'open': True, 'passphrase_saved': False, 'passphrase_set': False} ``` -## updateVault() +## patch_vault() Change the state of the vault. Syntax: ``` -.updateVault(__json__) +.patch_vault(__json__) ``` | Parameters | Type | Required | Default Value | Options | @@ -54,6 +54,18 @@ Syntax: Example: ```python ->>> vault.updateVault({"open": True,"passphrase":"long pass phrase"}).ok +>>> vault.patch_vault({"open": True,"passphrase":"long pass phrase"}).ok True -``` \ No newline at end of file +``` + +## getVault() + +[Deprecated] See [get_vault](#get_vault) for usage. + +Syntax: `.getVault()` + +## updateVault() + +[Deprecated] See [patch_vault](#patch_vault) for usage. + +Syntax: `.updateVault(__json__)` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index c5e696e..669c3de 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,11 +15,14 @@ Simplified Python library for BMC Discovery API Interface that makes use of the "api_versions": [ "1.0", "1.1", - "1.2" + "1.2", + "1.3", + "1.4", + "1.5" ], "component": "REST API", "product": "BMC Discovery", - "version": "12.2" + "version": "12.5" } ``` @@ -35,7 +38,7 @@ Tideway removes the extra layer of manually constructing a URL and parameters fo $ python -m pip install tideway ``` -- Tideway supports BMC Discovery 11.3+, API v1.2 using Python 3. +- Tideway supports BMC Discovery 11.3+, API v1.0-1.5 using Python 3. ## Contents @@ -43,11 +46,11 @@ $ python -m pip install tideway ## Releases -| Version | Summary | Known Issues | Fixed | -| :-----: | ------------------------------------------------------ | -------------------------------------------------------------- | ------------------------------ | -| 0.1.0 | Initial release, compatible with API v1.1 | | | -| 0.1.1 | Updated to API v1.2
Added `help()`, `search_bulk()` | search call retains last parameters for `offset`, `results_id` | | -| 0.1.2 | Bug Fixes | Bulk search with larger limit than dataset will fail on missing `next_offset` | Fixed issue with `offset` and `results_id` values
Fixed issue with bulk search parameter lower limit. | -| 0.1.3 | Bug Fixes | | Added check for `next_offset`. | -| 0.1.4 | Search bulk update | Discovery 12.3 (21.3) enforces strict case for "Bearer" header - api calls will not current work. | Now includes headers for non-formatted search. | -| 0.1.5 | Updated to support Discovery 12.3 (API version 1.3) | | Fixed issue with Bearer capitalisation.
Search Bulk will now return the full response on failure | +| Version | Summary | Known Issues | Fixed | +| :-----: | ------------------------- | -------------------------------------------------- | -------------------------------- | +| 0.1.1 | - Updated to API v1.2
- Added `help()`, `search_bulk()` | search call retains last parameters for `offset`, `results_id` | | +| 0.1.2 | Bug Fixes | Bulk search with larger limit than dataset will fail on missing `next_offset` | - Fixed issue with `offset` and `results_id` values
- Fixed issue with bulk search parameter lower limit. | +| 0.1.3 | Bug Fixes | | Added check for `next_offset`. | +| 0.1.4 | Search bulk update | Discovery 12.3 (21.3) enforces strict case for "Bearer" header - api calls will not current work. | Now includes headers for non-formatted search. | +| 0.1.5 | Updated to support Discovery 12.3 (API version 1.3) | - Missing 'complete' parameter option on graphNode() function. | - Fixed issue with Bearer capitalisation.
- Search Bulk will now return the full response on failure | +| 0.2.0 | Updated to include Kerberos, Models and Taxonomy endpoints.

Added new high level generic endpoint function calls

Refactored function names/decorators to match API endpoints as close as possible.

Supports Discovery 22.2 (12.5) (API version 1.5) and Outpost API version 1.0 | Not all new functions have been tested. | Added 'complete' parameter to `get_data_nodes_graph()` (replaces `graphNode()`) | diff --git a/docs/quickstart/initiation.md b/docs/quickstart/initiation.md index 8684f16..3079ac6 100644 --- a/docs/quickstart/initiation.md +++ b/docs/quickstart/initiation.md @@ -6,21 +6,25 @@ sort: 1 In order to make use of an API endpoint, you will need to initiate an object representing an instance of Discovery using an authentication token (generated in the GUI) and a hostname, fqdn or ip address. -Initiating an instance is done by creating an 'appliance' object: +Initiating an instance is done by creating an discovery or outpost object: -`tideway.appliance(,)` +`tideway.appliance(,)` +`tideway.outpost(,)` Or you can specify one of the following top-level endpoints: ```python -tideway.discovery() -tideway.data() -tideway.vault() +tideway.admin() tideway.credential() -tideway.knowledge() +tideway.data() +tideway.discovery() tideway.events() -tideway.admin() +tideway.kerberos() +tideway.knowledge() +tideway.models() +tideway.taxonomy() tideway.topology() +tideway.vault() ``` Upon initiation the following parameters can be used: @@ -28,5 +32,5 @@ Upon initiation the following parameters can be used: | - | - | - | - | - | target | Required | String | | The Hostname, FQDN or IP Address of the Discovery instance. | token | Required | String | | The authentication token of the API user. It is not necessary to include the "bearer" pre-text. -| api_version | | String | "1.3" | This should be the supported version of the API. Discovery 12.3 supports API versions up to 1.3. +| api_version | | String | "1.5" | This should be the supported version of the API. Discovery 22.2 supports API versions up to 1.5 (outpost 1.0). | ssl_verify | | Boolean | False | Choose whether to query the API using a valid SSL certificate. If you are using self-signed HTTPS then you should leave this with the default value. \ No newline at end of file diff --git a/docs/quickstart/responses.md b/docs/quickstart/responses.md index 5a1f3e1..e2e5d09 100644 --- a/docs/quickstart/responses.md +++ b/docs/quickstart/responses.md @@ -8,7 +8,7 @@ sort: 2 ## Input ```python ->>> tw = tideway.appliance('appliance-hostname','auth-token') +>>> tw = tideway.appliance('appliance-hostname','auth-token',api_version='1.2') >>> response = tw.about() ``` diff --git a/setup.py b/setup.py index 132a1c2..ac5520f 100644 --- a/setup.py +++ b/setup.py @@ -5,10 +5,10 @@ setuptools.setup( name="tideway", - version="0.1.5", + version="0.2.0", author="Wes Moskal-Fitzpatrick", author_email="wes@traversys.io", - description="library for BMC Discovery API Interface.", + description="Library for BMC Discovery API Interface.", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/traversys/tideway", diff --git a/tideway/__init__.py b/tideway/__init__.py index 3d624ab..8e6c906 100644 --- a/tideway/__init__.py +++ b/tideway/__init__.py @@ -9,19 +9,26 @@ credentials, \ knowledge, \ events, \ + kerberos, \ + models, \ + taxonomy, \ topology # Main declaration to create an appliance object appliance = main.Appliance +outpost = main.Appliance # For the previous version classes single file - moved to main.py # Method 1: tideway._________(appliance,token) # method 2: tideway.________.func(appliance) -discovery = discovery.Discovery -data = data.Data -vault = vault.Vault +admin = admin.Admin credentials = credentials.Credentials -knowledge = knowledge.Knowledge +data = data.Data +discovery = discovery.Discovery events = events.Events -admin = admin.Admin +kerberos = kerberos.Kerberos +knowledge = knowledge.Knowledge +models = models.Models +taxonomy = taxonomy.Taxonomy topology = topology.Topology +vault = vault.Vault diff --git a/tideway/admin.py b/tideway/admin.py index 6059d95..dea98f9 100644 --- a/tideway/admin.py +++ b/tideway/admin.py @@ -1,15 +1,10 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests appliance = tideway.main.Appliance -# class Test: -# def __init__(self): -# self.help = "Help!" - class Admin(appliance): '''Manage the BMC Discovery appliance.''' @@ -17,11 +12,13 @@ def baseline(self): '''Get a summary of the appliance status, and details of which baseline checks have passed or failed.''' response = dr.discoRequest(self, "/admin/baseline") return response + get_admin_baseline = property(baseline) def admin(self): '''Get information about the appliance, like its version and versions of the installed packages.''' response = dr.discoRequest(self, "/admin/about") return response + get_admin_about = property(admin) def licensing(self,content_type="text/plain"): '''Get the latest signed licensing report.''' diff --git a/tideway/credentials.py b/tideway/credentials.py index 78c68db..84301f6 100644 --- a/tideway/credentials.py +++ b/tideway/credentials.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests @@ -9,6 +8,14 @@ class Credentials(appliance): '''Manage credentials.''' + def get_vault_credential_type(self, group=None, category=None): + '''Altnernate API call for /vault/credential_types.''' + self.params['group'] = group + self.params['category'] = category + req = dr.discoRequest(self, "/vault/credential_types") + return req + get_vault_credential_types = property(get_vault_credential_type) + def listCredentialTypes(self, group=None, category=None): '''Get a list of all credential types and filter by group and/or category.''' self.params['group'] = group @@ -16,11 +23,25 @@ def listCredentialTypes(self, group=None, category=None): response = dr.discoRequest(self, "/vault/credential_types") return response + def get_vault_credential_type_name(self, cred_type_name): + '''Altnernate API call for /vault/credential_types/cred_type_name.''' + req = dr.discoRequest(self, "/vault/credential_types/{}".format(cred_type_name)) + return req + def credentialType(self, cred_type_name): '''Get the properties of a specific credential type.''' response = dr.discoRequest(self, "/vault/credential_types/{}".format(cred_type_name)) return response + def get_vault_credential(self, cred_id=None): + '''Altnernate API call for /vault/credentials.''' + if cred_id: + req = dr.discoRequest(self, "/vault/credentials/{}".format(cred_id)) + else: + req = dr.discoRequest(self, "/vault/credentials") + return req + get_vault_credentials = property(get_vault_credential) + def listCredentials(self, cred_id=None): '''Get a list of all credentials.''' if cred_id: @@ -29,21 +50,41 @@ def listCredentials(self, cred_id=None): response = dr.discoRequest(self, "/vault/credentials") return response + def post_vault_credential(self, body): + '''Altnernate API call for /vault/credentials.''' + req = dr.discoPost(self, "/vault/credentials", body) + return req + def newCredential(self, body): '''Create a new credential.''' response = dr.discoPost(self, "/vault/credentials", body) return response + def delete_vault_credential(self, cred_id): + '''Altnernate API call for /vault/credentials.''' + req = dr.discoDelete(self, "/vault/credentials/{}".format(cred_id)) + return req + def deleteCredential(self, cred_id): '''Delete a credential.''' response = dr.discoDelete(self, "/vault/credentials/{}".format(cred_id)) return response + def patch_vault_credential(self, cred_id, body): + '''Altnernate API call for /vault/credentials.''' + req = dr.discoPatch(self, "/vault/credentials/{}".format(cred_id), body) + return req + def updateCredential(self, cred_id, body): '''Updates partial resources of a credential. Missing properties are left unchanged.''' response = dr.discoPatch(self, "/vault/credentials/{}".format(cred_id), body) return response + def put_vault_credential(self, cred_id, body): + '''Altnernate API call for /vault/credentials.''' + req = dr.discoPut(self, "/vault/credentials/{}".format(cred_id), body) + return req + def replaceCredential(self, cred_id, body): '''Replaces a single credential. All required credential properties must be present. Optional properties that are missing will be reset to their defaults.''' response = dr.discoPut(self, "/vault/credentials/{}".format(cred_id), body) diff --git a/tideway/data.py b/tideway/data.py index ada81c7..f3de27b 100644 --- a/tideway/data.py +++ b/tideway/data.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway import warnings import json @@ -11,6 +10,30 @@ class Data(appliance): '''Retrieve data from the model.''' + def get_data_search(self, query, offset=None, results_id=None, format=None, limit = 100, delete = False): + '''Alternate API call for GET /data/search.''' + return Data.search(self, query, offset, results_id, format, limit, delete) + + def post_data_search(self, query, offset=None, results_id=None, format=None, limit = 100, delete = False): + '''Alternate API call for POST /data/search.''' + return Data.search(self, query, offset, results_id, format, limit, delete) + + def get_data_search_object(self, query, offset=None, results_id=None, format="object", limit = 100, delete = False): + '''Alternate API call for GET /data/search?format=object.''' + return Data.search(self, query, offset, results_id, format, limit, delete) + + def post_data_search_object(self, query, offset=None, results_id=None, format="object", limit = 100, delete = False): + '''Alternate API call for POST /data/search?format=object''' + return Data.search(self, query, offset, results_id, format, limit, delete) + + def get_data_search_tree(self, query, offset=None, results_id=None, format="tree", limit = 100, delete = False): + '''Alternate API call for GET /data/search?format=tree.''' + return Data.search(self, query, offset, results_id, format, limit, delete) + + def post_data_search_tree(self, query, offset=None, results_id=None, format="tree", limit = 100, delete = False): + '''Alternate API call for POST /data/search?format=tree.''' + return Data.search(self, query, offset, results_id, format, limit, delete) + def search(self, query, offset=None, results_id=None, format=None, limit = 100, delete = False): '''Run a search query, receiving paginated results.''' self.params['offset'] = offset @@ -65,20 +88,64 @@ def search_bulk(self, query, format = None, limit = 100, delete = False): else: return initial - def candidate(self, body): + def post_data_condition(self, body, offset=None, results_id=None, format=None, limit = 100, delete = False): + '''Search using a condition, retrieving tabular data as arrays''' + self.params['offset'] = offset + self.params['results_id'] = results_id + self.params['format'] = format + self.params['delete'] = delete + self.params['limit'] = limit + response = dr.discoPost(self, "/data/condition", body) + return response + + def post_data_condition_param_values(self, body): + '''Get possible parameter values for a condition''' + response = dr.discoPost(self, "/data/condition/param_values", body) + return response + + def get_data_condition_template(self,template_id): + '''Get a list of all templates''' + if template_id: + req = dr.discoRequest(self, "/data/condition/templates/{}".format(template_id)) + else: + req = dr.discoRequest(self, "/data/condition/templates") + return req + get_data_condition_templates = property(get_data_condition_template) + + def post_data_candidate(self, body): + '''Alternate API call for POST /data/candidate.''' + response = dr.discoPost(self, "/data/candidate", body) + return response + + def best_candidate(self, body): ''' - The node object of the best candidate based on the provided - parameters. + The node object of the best candidate based on the provided parameters. ''' response = dr.discoPost(self, "/data/candidate", body) return response - def candidates(self, body): + def post_data_candidates(self, body): + '''Alternate API call for POST /data/candidates.''' + response = dr.discoPost(self, "/data/candidates", body) + return response + + def top_candidates(self, body): ''' Enter parameters to identify a device, the response is a list of candidate nodes ordered by descending score. ''' - response = dr.discoPost(self, "/data/candidate", body) + response = dr.discoPost(self, "/data/candidates", body) + return response + + def get_data_nodes(self, node_id, relationships=False, traverse=None, flags=None, attributes=None): + '''Alternate API call for /data/nodes/node_id''' + self.params['traverse'] = traverse + self.params['flags'] = flags + self.params['attributes'] = attributes + if relationships: + response = dr.discoRequest(self, "/data/nodes/{}?relationships=true".format(node_id)) + else: + response = dr.discoRequest(self, "/data/nodes/{}".format(node_id)) return response def nodeLookup(self, node_id, relationships=False, traverse=None, flags=None, attributes=None): @@ -92,6 +159,14 @@ def nodeLookup(self, node_id, relationships=False, traverse=None, flags=None, at response = dr.discoRequest(self, "/data/nodes/{}".format(node_id)) return response + def get_data_nodes_graph(self, node_id, focus="sofware-connected", apply_rules=True): + '''Alternate API call for /data/nodes/node_id/graph''' + self.params['focus'] = focus + self.params['apply_rules'] = apply_rules + self.params['complete'] = False + response = dr.discoRequest(self, "/data/nodes/{}/graph".format(node_id)) + return response + def graphNode(self, node_id, focus="sofware-connected", apply_rules=True): '''Graph data represents a set of nodes and relationships that are associated to the given node.''' self.params['focus'] = focus @@ -99,6 +174,16 @@ def graphNode(self, node_id, focus="sofware-connected", apply_rules=True): response = dr.discoRequest(self, "/data/nodes/{}/graph".format(node_id)) return response + def get_data_kinds(self, kind, offset=None, results_id=None, format=None, limit = 100, delete = False): + '''Alternate API call for /data/kinds.''' + self.params['offset'] = offset + self.params['results_id'] = results_id + self.params['format'] = format + self.params['limit'] = limit + self.params['delete'] = delete + response = dr.discoRequest(self, "/data/kinds/{}".format(kind)) + return response + def lookupNodeKind(self, kind, offset=None, results_id=None, format=None, limit = 100, delete = False): '''Finds all nodes of a specified node kind.''' self.params['offset'] = offset @@ -113,6 +198,17 @@ def partitions(self): '''Get names and ids of partitions.''' response = dr.discoRequest(self, "/data/partitions") return response + get_data_partitions = property(partitions) + + def post_data_partitions(self, body): + '''Create a partition.''' + response = dr.discoPost(self, "/data/partitions", body) + return response + + def post_data_import(self, body): + '''Alternate API call for /data/import.''' + response = dr.discoPost(self, "/data/import", body) + return response def twImport(self, body): ''' @@ -121,6 +217,11 @@ def twImport(self, body): response = dr.discoPost(self, "/data/import", body) return response + def post_data_write(self, body): + '''Alternate API call for /data/write.''' + response = dr.discoPost(self, "/data/write", body) + return response + def twWrite(self, body): ''' Perform arbitrary write operations. diff --git a/tideway/discoRequests.py b/tideway/discoRequests.py index beb3957..ac61a29 100644 --- a/tideway/discoRequests.py +++ b/tideway/discoRequests.py @@ -25,6 +25,13 @@ def filePost(appliance, api_endpoint, file, response="text/html"): req = requests.post(url, files=files, headers=heads, params=appliance.params, verify=appliance.verify) return req +def keytabPost(appliance, api_endpoint, file, username, response="application/json", content_type="multipart/form-data"): + form_data= {"keytab":open(file,'rb'),"username":username} + url, heads = url_and_headers(appliance.url,appliance.token,api_endpoint,response) + heads['Content-type']=content_type + req = requests.post(url, files=form_data, headers=heads, params=appliance.params, verify=appliance.verify) + return req + def discoPatch(appliance, api_endpoint, jsoncode, response="application/json"): url, heads = url_and_headers(appliance.url,appliance.token,api_endpoint,response) req = requests.patch(url, json=jsoncode, headers=heads, params=appliance.params, verify=appliance.verify) diff --git a/tideway/discovery.py b/tideway/discovery.py index ddf595f..149bf16 100644 --- a/tideway/discovery.py +++ b/tideway/discovery.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests @@ -10,17 +9,22 @@ class Discovery(appliance): '''Control scanning and view results.''' def getDiscoveryStatus(self): - '''Get the current status of the discovery process.''' + '''Get the current status of the discovery process. JSON Output.''' response = dr.discoRequest(self, "/discovery") return response + get_discovery = property(getDiscoveryStatus) + + def patch_discovery(self, body): + '''Alternate API call for PATCH /discovery.''' + response = dr.discoPatch(self, "/discovery", body) + return response def setDiscoveryStatus(self, body): ''' - Either start or stop the discovery process. Note this call can - return before the desired state has been reached. + Set the Discovery status using JSON format. ''' response = dr.discoPatch(self, "/discovery", body) - return response + return response.ok def getApiProviderMetadata(self): ''' @@ -31,6 +35,7 @@ def getApiProviderMetadata(self): ''' response = dr.discoRequest(self, "/discovery/api_provider_metadata") return response + get_discovery_api_provider_metadata = property(getApiProviderMetadata) def getDiscoveryCloudMetaData(self): ''' @@ -39,6 +44,40 @@ def getDiscoveryCloudMetaData(self): ''' response = dr.discoRequest(self, "/discovery/cloud_metadata") return response + get_discovery_api_cloud_metadata = property(getDiscoveryCloudMetaData) + + def get_discovery_exclude(self, exclude_id=None): + '''Get a list of all excludes or specific.''' + if exclude_id: + req = dr.discoRequest(self, "/discovery/excludes/{}".format(exclude_id)) + else: + req = dr.discoRequest(self, "/discovery/excludes") + return req + get_discovery_excludes = property(get_discovery_exclude) + + def post_discovery_exclude(self, body): + '''Create an exclude.''' + response = dr.discoPost(self, "/discovery/excludes", body) + return response + + def delete_discovery_exclude(self, exclude_id): + '''Delete an exclude.''' + response = dr.discoDelete(self, "/discovery/excludes/{}".format(exclude_id)) + return response + + def patch_discovery_exclude(self, exclude_id, body): + '''Update an exclude.''' + response = dr.discoPatch(self, "/discovery/excludes/{}".format(exclude_id), body) + return response + + def get_discovery_run(self, run_id=None): + '''Get details of all or specific currently processing discovery runs.''' + if run_id: + req = dr.discoRequest(self, "/discovery/runs/{}".format(run_id)) + else: + req = dr.discoRequest(self, "/discovery/runs") + return req + get_discovery_runs = property(get_discovery_run) def getDiscoveryRuns(self): '''Get details of all currently processing discovery runs.''' @@ -50,16 +89,39 @@ def getDiscoveryRun(self, runid): response = dr.discoRequest(self, "/discovery/runs/{}".format(runid)) return response + def post_discovery_run(self, body): + '''Alternative API call for POST /discovery/runs.''' + response = dr.discoPost(self, "/discovery/runs", body) + return response + def discoveryRun(self, body): '''Create a new snapshot discovery run.''' response = dr.discoPost(self, "/discovery/runs", body) return response + def patch_discovery_run(self, run_id, body): + '''Alternate API call for PATCH /discovery/runs.''' + response = dr.discoPatch(self, "/discovery/runs/{}".format(run_id), body) + return response + def updateDiscoveryRun(self, runid, body): '''Update the state of a specific discovery run.''' response = dr.discoPatch(self, "/discovery/runs/{}".format(runid), body) return response + def get_discovery_run_results(self, run_id, result=None, offset=None, results_id=None, format=None, limit = 100, delete = False): + '''Get a summary of the results from scanning all endpoints in the run that had a specific type of result.''' + if result: + self.params['offset'] = offset + self.params['results_id'] = results_id + self.params['format'] = format + self.params['limit'] = limit + self.params['delete'] = delete + response = dr.discoRequest(self, "/discovery/runs/{}/results/{}".format(run_id,result)) + else: + response = dr.discoRequest(self, "/discovery/runs/{}/results".format(run_id)) + return response + def getDiscoveryRunResults(self, runid): '''Get a summary of the results from scanning all endpoints in the run, partitioned by result type.''' response = dr.discoRequest(self, "/discovery/runs/{}/results".format(runid)) @@ -75,6 +137,19 @@ def getDiscoveryRunResult(self, runid, result="Success", offset=None, results_id response = dr.discoRequest(self, "/discovery/runs/{}/results/{}".format(runid,result)) return response + def get_discovery_run_inferred(self, run_id, inferred_kind, offset=None, results_id=None, format=None, limit = 100, delete = False): + '''Get a summary of the devices inferred by a discovery run which have a specific inferred kind.''' + if inferred_kind: + self.params['offset'] = offset + self.params['results_id'] = results_id + self.params['format'] = format + self.params['limit'] = limit + self.params['delete'] = delete + response = dr.discoRequest(self, "/discovery/runs/{}/inferred/{}".format(run_id,inferred_kind)) + else: + response = dr.discoRequest(self, "/discovery/runs/{}/inferred".format(run_id)) + return response + def getDiscoveryRunInferred(self, runid): '''Get a summary of all inferred devices from a discovery run, partitioned by device type.''' response = dr.discoRequest(self, "/discovery/runs/{}/inferred".format(runid)) @@ -89,3 +164,27 @@ def getDiscoveryRunInferredKind(self, runid, inferred_kind, offset=None, results self.params['delete'] = delete response = dr.discoRequest(self, "/discovery/runs/{}/inferred/{}".format(runid,inferred_kind)) return response + + def get_discovery_run_schedule(self, run_id=None): + '''Get a list of all scheduled runs or specific.''' + if run_id: + req = dr.discoRequest(self, "/discovery/runs/scheduled/{}".format(run_id)) + else: + req = dr.discoRequest(self, "/discovery/runs/scheduled") + return req + get_discovery_run_schedules = property(get_discovery_run_schedule) + + def post_discovery_run_schedule(self, body): + '''Add a new scheduled run.''' + response = dr.discoPost(self, "/discovery/runs/scheduled", body) + return response + + def delete_discovery_run_schedule(self, run_id): + '''Delete a specific scheduled discovery run.''' + response = dr.discoDelete(self, "/discovery/runs/scheduled/{}".format(run_id)) + return response + + def patch_discovery_run_schedule(self, run_id, body): + '''Update the parameters of a specific scheduled discovery run.''' + response = dr.discoPatch(self, "/discovery/runs/scheduled/{}".format(run_id), body) + return response \ No newline at end of file diff --git a/tideway/endpoints.py b/tideway/endpoints.py index 0a1f34d..538c00b 100644 --- a/tideway/endpoints.py +++ b/tideway/endpoints.py @@ -5,308 +5,698 @@ docTable = [ [ - "/swagger.json", - "swagger()", - "Get swagger file." + "GET", "/swagger.json", "- swagger()\n- api_swagger", "Get swagger file." ], [ - "/about", - "about()", - "Return about info for API." + "GET", "/about", "- about()\n- api_about", "Return about info for API." ], [ + "GET", "/admin/baseline", - "baseline()", + "- baseline()\n- get_admin_baseline", "Get a summary of the appliance status, and details of which baseline checks have passed or failed." ], [ + "GET", "/admin/about", - "admin()", + "- admin()\n- get_admin_about", "Get information about the appliance, like its version and versions of the installed packages." ], [ + "GET", "/admin/licensing", - "licensing()", + "- licensing()\n- get_admin_licensing", "Get the latest signed licensing report." ], [ + "GET", "/admin/licensing/raw", - "licensing(content_type='raw')", + "- licensing(content_type='raw')\n- get_admin_licensing_raw", "Download the encrypted raw license data on this appliance for import on another appliance." ], [ + "GET", "/admin/licensing/csv", - "licensing(content_type='csv')", + "- licensing(content_type='csv')\n- get_admin_licensing_csv", "Download raw license data in CSV format as a zip file for offline analysis." ], [ + "GET", "/vault/credential_types", - "listCredentialTypes()", + "- listCredentialTypes()\n- get_vault_credential_type(group, cagetory)\n- get_vault_credential_types", "Get a list of all credential types and filter by group and/or category." ], [ + "GET", "/vault/credential_types/{cred_type_name}", - "credentialType(cred_type_name)", + "- credentialType(cred_type_name)\n- get_vault_credential_type_name(cred_type_name)", "Get the properties of a specific credential type." ], [ + "GET", "/vault/credentials", - "listCredentials()", + "- listCredentials()\n- get_vault_credential()\n- get_vault_credentials", "Get a list of all credentials." ], [ + "POST", "/vault/credentials", - "newCredential(body)", + "- newCredential(body)\n- post_vault_credential(body)", "Create a new credential." ], [ + "DELETE", "/vault/credentials/{cred_id}", - "deleteCredential(cred_id)", + "- deleteCredential(cred_id)\n- delete_vault_credential(cred_id)", "Delete a credential." ], [ + "GET", "/vault/credentials/{cred_id}", - "listCredentials(cred_id)", + "- listCredentials(cred_id)\n- get_vault_credential(cred_id)", "Get the properties of a specific credential." ], [ + "PATCH", "/vault/credentials/{cred_id}", - "updateCredential(cred_id, body)", + "- updateCredential(cred_id, body)\n- patch_vault_credential(cred_id, body)", "Updates partial resources of a credential. Missing properties are left unchanged." ], [ + "PUT", "/vault/credentials/{cred_id}", - "replaceCredential(cred_id, body)", + "- replaceCredential(cred_id, body)\n- put_vault_credential(cred_id, body)", """Replaces a single credential. All required credential properties must be present.""" ], [ + "GET", "/data/search", - "search('query')", + "- search('query')\n- get_data_search('query')", "Run a search query, receiving paginated results." ], [ + "POST", "/data/search", - "search(body)", + "- search('query')\n- post_data_search('query')", "An alternative to GET /data/search, for search queries which are too long for urls." ], [ + "GET", "/data/search?format=object", - "search('query',format='object')", + "- search('query',format='object')\n- get_data_search_object('query',format='object')", "As /data/search but returns results as objects instead of rows of values." ], [ + "POST", "/data/search?format=object", - "search(body,format='object')", + "- search('query',format='object')\n- post_data_search_object('query',format='object')", "An alternative to GET /data/search?format=object, for search queries which are too long for urls." ], [ + "GET", "/data/search?format=tree", - "search('query',format='tree')", + "- search('query',format='tree')\n- get_data_search_tree('query',format='tree')", "As /data/search but returns results as a tree of objects." ], [ + "POST", "/data/search?format=tree", - "search(body,format='tree')", + "- search('query',format='tree')\n- post_data_search_tree('query',format='tree')", "An alternative to GET /data/search?format=tree, for search queries which are too long for urls." ], [ + "GET/POST", "/data/search", - "search_bulk(query/body)", + "- search_bulk(query/body)", "Run a bulk search query - loops through paginated results and returns a set of JSON results." ], [ + "POST", + "/data/condition", + "- post_data_condition('query')", + "Search using a condition, retrieving tabular data as arrays." + ], + [ + "POST", + "/data/condition?format=object", + "- post_data_condition('query',format='object')", + "Search using a condition, returning results as objects." + ], + [ + "POST", + "/data/condition?format=tree", + "- post_data_condition('query',format='tree')", + "Search using a condition, returning results as tree of objects." + ], + [ + "POST", + "/data/condition/param_values", + "- post_data_condition_param_values(body)", + "Get possible parameter values for a condition." + ], + [ + "GET", + "/data/condition/templates", + "- get_data_condition_templates\n- get_data_condition_template()", + "Get a list of all templates." + ], + [ + "GET", + "/data/condition/templates/{template_id}", + "- get_data_condition_template(template_id)", + "Get the properties of a specific template." + ], + [ + "POST", "/data/candidate", - "candidate(body)", + "- best_candidate(body)\n- post_data_candidate(body)", "The node object of the best candidate based on the provided parameters." ], [ + "POST", "/data/candidates", - "candidates(body)", + "- top_candidates(body)\n- post_data_candidates(body)", "Enter parameters to identify a device, the response is a list of candidate nodes ordered by descending score" ], [ + "GET", "/data/nodes/{node_id}", - "nodeLookup(node_id)", + "- nodeLookup(node_id)\n- get_data_nodes(node_id)", "Get the state of a node with specified id" ], [ + "GET", "/data/nodes/{node_id}?relationships=true", - "nodeLookup(node_id,relationships=True)", + "- nodeLookup(node_id,relationships=True)\n- get_data_nodes(node_id,relationships=True)", "Get the state of a node with specified id, along with the traversal specs of all current relationships it has." ], [ + "GET", "/data/nodes/{node_id}?traverse={traverse_spec}", - "nodeLookup(node_id,traverse='traverse_spec')", + "- nodeLookup(node_id,traverse='traverse_spec')\n- get_data_nodes(node_id,traverse='traverse_spec')", "Get the state of a node with specified id, along with the IDs of all nodes reached by following a traversal spec." ], [ + "GET", "/data/nodes/{node_id}?traverse={attributes}", - "nodeLookup(node_id,attributes='attributes')", + "- nodeLookup(node_id,attributes='attributes')\n- get_data_nodes(node_id,attributes='attributes')", "Get the state of a node with specified id, with only the attributes specified." ], [ + "GET", "/data/nodes/{node_id}/graph", - "graphNode(node_id)", + "- graphNode(node_id)\n- get_data_nodes_graph(node_id)", "Graph data represents a set of nodes and relationships that are associated to the given node." ], [ + "GET", "/data/kinds/{kind}", - "lookupNodeKind(kind)", + "- lookupNodeKind(kind)\n- get_data_kinds(kind)", "Finds all nodes of a specified node kind." ], [ + "GET", "/data/kinds/{kind}?format=object", - "lookupNodeKind(kind,format='object')", + "- lookupNodeKind(kind,format='object')\n- get_data_kinds(kind,format='object')", "As /data/kinds/{kind} but returns found nodes as objects instead of rows of attribute values." ], [ + "GET", "/data/partitions", - "partitions()", + "- partitions()\n- get_data_partitions", "Get names and ids of partitions." ], [ + "POST", + "/data/partitions", + "- post_data_partitions(body)", + "Create a partition." + ], + [ + "POST", "/data/import", - "twImport(body)", + "- twImport(body)\n- post_data_import(body)", "Imports data. Returns the import UUID." ], [ + "POST", "/data/write", - "twWrite(body)", + "- twWrite(body)\n- post_data_write(body)", "Perform arbitrary write operations." ], [ + "GET", "/discovery", - "getDiscoveryStatus()", + "- getDiscoveryStatus()\n- get_discovery", "Get the current status of the discovery process." ], [ + "PATCH", "/discovery", - "setDiscoveryStatus(body)", + "- setDiscoveryStatus(body)\n- patch_discovery(body)", "Either start or stop the discovery process. Note this call can return before the desired state has been reached." ], [ + "GET", "/discovery/api_provider_metadata", - "getApiProviderMetadata()", + "- getApiProviderMetadata()\n- get_discovery_api_provider_metadata", """Get metadata for the API providers currently supported by BMC Discovery""" ], [ + "GET", "/discovery/cloud_metadata", - "getDiscoveryCloudMetaData()", + "- getDiscoveryCloudMetaData()\n- get_discovery_api_cloud_metadata", """Get metadata for the cloud providers currently supported by BMC Discovery.""" ], [ + "GET", + "/discovery/excludes", + "- get_discovery_excludes\n- get_discovery_exclude()", + """Get a list of all excludes.""" + ], + [ + "POST", + "/discovery/excludes", + "- post_discovery_exclude(body)", + """Create an exclude.""" + ], + [ + "DELETE", + "/discovery/excludes/{exclude_id}", + "- delete_discovery_exclude(exclude_id)", + """Delete an exclude.""" + ], + [ + "GET", + "/discovery/excludes/{exclude_id}", + "- get_discovery_exclude(exclude_id)", + """Get a specific exclude.""" + ], + [ + "PATCH", + "/discovery/excludes/{exclude_id}", + "- patch_discovery_exclude(exclude_id, body)", + """Updates partial resources of an exclude. Missing properties are left unchanged.""" + ], + [ + "GET", "/discovery/runs", - "getDiscoveryRuns()", + "- getDiscoveryRuns()\n- get_discovery_run()\n- get_discovery_runs", """Get details of all currently processing discovery runs.""" ], [ + "POST", "/discovery/runs", - "discoveryRun(body)", + "- discoveryRun(body)\n- post_discovery_run(body)", """Create a new snapshot discovery run.""" ], [ + "GET", "/discovery/runs/{run_id}", - "getDiscoveryRun(runid)", + "- getDiscoveryRun(run_id)\n- get_discovery_run(run_id)", """Get details of specific currently processing discovery run.""" ], [ + "PATCH", "/discovery/runs/{run_id}", - "updateDiscoveryRun(runid, body)", + "- updateDiscoveryRun(run_id, body)\n- post_discovery_run(run_id, body)", """Update the state of a specific discovery run""" ], [ + "GET", "/discovery/runs/{run_id}/results", - "getDiscoveryRunResults(runid):", + "- getDiscoveryRunResults(run_id)\n- get_discovery_run_results(run_id)", """Get a summary of the results from scanning all endpoints in the run, partitioned by result type.""" ], [ + "GET", "/discovery/runs/{run_id}/results/{result_type}", - "getDiscoveryRunResult(runid, result='result_type')", + "- getDiscoveryRunResult(run_id, result='result_type')\n- get_discovery_run_results(run_id, result='result_type')", """Get a summary of the results from scanning all endpoints in the run that had a specific type of result.""" ], [ + "GET", "/discovery/runs/{run_id}/results/{result_type}?format=object", - "getDiscoveryRunResult(runid, format='object')", + "- getDiscoveryRunResult(run_id, format='object')\n- get_discovery_run_results(run_id, format='object')", """As /discovery/runs/{run_id}/results/{result_type} but returns found nodes as objects instead of rows of attribute values.""" ], [ + "GET", "/discovery/runs/{run_id}/inferred", - "getDiscoveryRunInferred(runid)", + "- getDiscoveryRunInferred(run_id)\n- get_discovery_run_inferred(run_id)", """Get a summary of all inferred devices from a discovery run, partitioned by device type.""" ], [ + "GET", "/discovery/runs/{run_id}/inferred/{inferred_kind}", - "getDiscoveryRunInferredKind(runid, inferred_kind)", + "- getDiscoveryRunInferredKind(run_id, inferred_kind)\n- get_discovery_run_inferred(run_id, inferred_kind)", """Get a summary of the devices inferred by a discovery run which have a specific inferred kind.""" ], [ + "GET", "/discovery/runs/{run_id}/inferred/{inferred_kind}?format=object", - "getDiscoveryRunInferredKind(runid, inferred_kind, format='object')", + "- getDiscoveryRunInferredKind(run_id, inferred_kind, format='object')\n- get_discovery_run_inferred(run_id, inferred_kind, format='object')", """As /discovery/runs/{run_id}/inferred/{inferred_kind} but returns found nodes as objects instead of rows of attribute values.""" ], [ + "GET", + "/discovery/runs/scheduled", + "- get_discovery_run_schedules\n- get_discovery_run_schedule()", + """Get details of all scheduled discovery runs.""" + ], + [ + "POST", + "/discovery/runs/scheduled", + "- post_discovery_run_schedule(body)", + """Create a new scheduled discovery run.""" + ], + [ + "DELETE", + "/discovery/runs/scheduled/{run_id}", + "- delete_discovery_run_schedule(run_id)", + """Delete a specific scheduled discovery run.""" + ], + [ + "GET", + "/discovery/runs/scheduled/{run_id}", + "- get_discovery_run_schedule(run_id)", + """Get details of a specific scheduled discovery run.""" + ], + [ + "PATCH", + "/discovery/runs/scheduled/{run_id}", + "- patch_discovery_run_schedule(run_id, body)", + """Get details of a specific scheduled discovery run.""" + ], + [ + "POST", "/events", - "status(body)", + "- status(body)\n- post_events(body)", """Returns a unique ID if the event has been recorded, otherwise an empty string is returned e.g. if the event source has been disabled.""" ], [ + "GET", + "/vault/kerberos/realms", + "- get_vault_kerberos_realms\n- get_vault_kerberos_realm()", + """Retrieve all available realms.""" + ], + [ + "DELETE", + "/vault/kerberos/realms/{realm_name}", + "- delete_vault_kerberos_realm(realm_name)", + """Delete a Kerberos realm.""" + ], + [ + "GET", + "/vault/kerberos/realms/{realm_name}", + "- get_vault_kerberos_realm(realm_name)", + """Retrieve a Kerberos realm by name.""" + ], + [ + "PATCH", + "/vault/kerberos/realms/{realm_name}", + "- patch_vault_kerberos_realm(realm_name)", + """Update a Kerberos realm.""" + ], + [ + "POST", + "/vault/kerberos/realms/{realm_name}", + "- post_vault_kerberos_realm(realm_name, body)", + """Create a Kerberos realm.""" + ], + [ + "POST", + "/vault/kerberos/realms/{realm_name}/test", + "- post_vault_kerberos_realm(realm_name, body, test=True)", + """Test user credentials by attempting to acquire a new Kerberos Ticket Granting Ticket (TGT).""" + ], + [ + "GET", + "/vault/kerberos/realms/{realm_name}/keytabs", + "- get_vault_kerberos_keytabs(realm_name)", + """Return a list of users with a Kerberos keytab file.""" + ], + [ + "POST", + "/vault/kerberos/realms/{realm_name}/keytabs", + "- post_vault_kerberos_keytab(realm_name, username, keytab)", + """Upload a Kerberos keytab file.""" + ], + [ + "DELETE", + "/vault/kerberos/realms/{realm_name}/keytabs", + "- delete_vault_kerberos_keytab(realm_name, username)", + """Delete the keytab file for a user.""" + ], + [ + "GET", + "/vault/kerberos/realms/{realm_name}/ccaches", + "- get_vault_kerberos_ccaches(realm_name)", + """Return a list of users with a Kerberos credential cache file.""" + ], + [ + "POST", + "/vault/kerberos/realms/{realm_name}/ccaches", + "- post_vault_kerberos_ccache(realm_name, username, ccache)", + """Upload a Kerberos credential cache file.""" + ], + [ + "DELETE", + "/vault/kerberos/realms/{realm_name}/ccaches", + "- delete_vault_kerberos_ccache(realm_name, username)", + """Deletes the credential cache file for a user.""" + ], + [ + "GET", "/knowledge", - "getKnowledgeManagement()", + "- getKnowledgeManagement()\n- get_knowledge", """Get the current state of the appliance's knowledge, including TKU versions.""" ], [ + "POST", "/knowledge/{filename}", - "uploadKnowledge(filename, file)", + "- uploadKnowledge(filename, file)\n- post_knowledge(filename, file)", """Upload a TKU or pattern module to the appliance.""" ], [ + "GET", "/knowledge/status", - "getUploadStatus()", - """Get the current state of a knowledge upload""" + "- getUploadStatus()\n- get_knowledge_status", + """Get the current state of a knowledge upload.""" + ], + [ + "GET", + "/models", + "- get_models\n- get_model()", + """Get model definitions.""" + ], + [ + "POST", + "/models", + "- post_model(body)", + """Create a new model.""" + ], + [ + "DELETE", + "/models/{key}", + "- delete_model(key)", + """Delete a model.""" + ], + [ + "GET", + "/models/{key}", + "- get_model_key(key)", + """Get model definition for the specified key.""" + ], + [ + "PATCH", + "/models/{key}", + "- patch_model(key, body)", + """Modify a model.""" + ], + [ + "GET", + "/models/{key}/topology", + "- get_model_topology(key)", + """Get topology for the model definition specified by key.""" + ], + [ + "GET", + "/models/{key}/nodecount", + "- get_model_nodecount(key)", + """Get node count for the model definition specified by key.""" + ], + [ + "GET", + "/models/{key}/nodes", + "- get_model_nodes(key)", + """Get nodes for the model definition specified by key.""" + ], + [ + "GET", + "/models/{key}/nodes/{kind}", + "- get_model_nodes(key, kind='kind')", + """Get nodes by kind for the model definition specified by key.""" + ], + [ + "DELETE", + "/models/by_node_id/{node_id}", + "- delete_model_by_node_id(node_id)", + """Delete a model.""" + ], + [ + "GET", + "/models/by_node_id/{node_id}", + "- get_model_by_node_id(node_id)", + """Get model definition for the specified node id.""" + ], + [ + "PATCH", + "/models/by_node_id/{node_id}", + "- patch_model_by_node_id(node_id, body)", + """Modify a model.""" + ], + [ + "GET", + "/models/by_node_id/{node_id}/topology", + "- get_topology_by_node_id(node_id)", + """Get topology for the model definition specified by node id.""" + ], + [ + "GET", + "/models/by_node_id/{node_id}/nodecount", + "- get_nodecount_by_node_id(node_id)", + """Get node count for the model definition specified by node id.""" + ], + [ + "GET", + "/models/by_node_id/{node_id}/nodes", + "- get_nodes_by_node_id(node_id)", + """Get nodes for the model definition specified by node id.""" + ], + [ + "GET", + "/models/by_node_id/{node_id}/nodes/{kind}", + "- get_nodes_by_node_id(node_id, kind='kind')", + """Get nodes by kind for the model definition specified by node id.""" + ], + [ + "POST", + "/models/multi", + "- post_model_multi(body)", + """Manipulate multiple models in a single request.""" + ], + [ + "GET", + "/taxonomy/sections", + "- get_taxonomy_sections", + """Get list of taxonomy model sections.""" + ], + [ + "GET", + "/taxonomy/sections", + "- get_taxonomy_locales", + """Get list of known taxonomy locales.""" + ], + [ + "GET", + "/taxonomy/nodekinds", + "- get_taxonomy_nodekinds\n- get_taxonomy_nodekind()", + """Get list of defined node kind names.""" + ], + [ + "GET", + "/taxonomy/nodekinds?format=info", + "- get_taxonomy_nodekind(format='info')", + """Get list of defined node kind names.""" + ], + [ + "GET", + "/taxonomy/nodekinds/{kind}", + "- get_taxonomy_nodekind(kind='kind')", + """Get defined node kind details.""" + ], + [ + "GET", + "/taxonomy/nodekinds/{kind}/fieldlists", + "- get_taxonomy_nodekind(kind='kind', fieldlists=True)", + """Get list of node kind field lists.""" + ], + [ + "GET", + "/taxonomy/nodekinds/{kind}/fieldlists/{fieldlist}", + "- get_taxonomy_nodekind_fieldlist(kind, fieldlist)", + """Get list of node kind field lists.""" + ], + [ + "GET", + "/taxonomy/relkinds", + "- get_taxonomy_relkinds\n- get_taxonomy_relkind()", + """Get list of defined relationship kinds.""" + ], + [ + "GET", + "/taxonomy/relkinds?format=info", + "- get_taxonomy_relkind(format='info')", + """Get list of defined relationship kinds with kind info.""" + ], + [ + "GET", + "/taxonomy/relkinds/{kind}", + "- get_taxonomy_relkind(kind='kind')", + """Get defined relationship kind details.""" ], [ + "GET", "/data/nodes/{node_id}/graph", - "graphNode(node_id)", + "- graphNode(node_id)\n- get_data_nodes_graph(node_id)", """Graph data represents a set of nodes and relationships that are associated to the given node.""" ], [ + "POST", "/topology/nodes", - "getNodes(body)", + "- getNodes(body)\n- post_topology_nodes", """Get topology data from one or more starting nodes.""" ], [ + "POST", "/topology/nodes/kinds", - "getNodeKinds(body)", + "- getNodeKinds(body)\n- post_topology_nodes_kinds", """Get nodes of the specified kinds which are related to a given set of nodes.""" ], [ + "GET", "/topology/visualization_state", - "visualizationState()", + "- visualizationState()\n- get_topology_viz_state", """Get the current state of the visualization for the authenticated user.""" ], [ + "PATCH", "/topology/visualization_state", - "updateVizState(body)", + "- updateVizState(body)\n- patch_topology_viz_state(body)", """Update one or more attributes of the current state of the visualization for the authenticated user.""" ], [ + "PUT", "/topology/visualization_state", - "replaceVizState(body)", + "- replaceVizState(body)\n- put_topology_viz_state", """Update any or all of the attributes of the current state of the visualization for the authenticated user.""" ], [ + "GET", "/vault", - "getVault()", + "- getVault()\n- get_vault", """Get details of the state of the vault.""" ], [ + "PATCH", "/vault", - "updateVault(body)", + "- updateVault(body)\n- patch_vault", """Change the state of the vault.""" ] ] -heads = [ "Endpoint", "Function", "Description" ] +heads = [ "Method", "Endpoint", "Function Calls", "Description" ] def docs(*endpoints): # Endpoint Docs @@ -314,12 +704,12 @@ def docs(*endpoints): tab = list() endpoint = endpoints[0] for line in docTable: - if line[0] == endpoint: + if line[1] == endpoint: tab.append(line) if len(tab) > 0: - print(tabulate(tab, headers=heads)) + print(tabulate(tab, headers=heads),"\n") else: - print("API endpoint not found or not yet documented.") + print("API endpoint not found or not yet documented.\n") else: # display table - print(tabulate(docTable, headers=heads)) + print(tabulate(docTable, headers=heads, tablefmt="fancy_grid"),"\n") diff --git a/tideway/events.py b/tideway/events.py index 316e67c..dbb7804 100644 --- a/tideway/events.py +++ b/tideway/events.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests @@ -9,6 +8,11 @@ class Events(appliance): '''Push events.''' + def post_events(self, body): + '''An alternate API call for POST /events''' + response = dr.discoPost(self, "/events", body) + return response + def status(self, body): ''' Returns a unique ID if the event has been recorded, otherwise an diff --git a/tideway/kerberos.py b/tideway/kerberos.py new file mode 100644 index 0000000..208af78 --- /dev/null +++ b/tideway/kerberos.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +import tideway + +dr = tideway.discoRequests +appliance = tideway.main.Appliance + +class Kerberos(appliance): + '''Manage Kerberos resources.''' + + def get_vault_kerberos_realm(self, realm_name=None): + '''Retrieve all or specific realm.''' + req = dr.discoRequest(self, "/vault/kerberos/realms") + if realm_name: + req = dr.discoRequest(self, "/vault/kerberos/realms/{}".format(realm_name)) + else: + req = dr.discoRequest(self, "/vault/kerberos/realms") + return req + get_vault_kerberos_realms = property(get_vault_kerberos_realm) + + def delete_vault_kerberos_realm(self, realm_name): + '''Delete a realm.''' + req = dr.discoDelete(self, "/vault/kerberos/realms/{}".format(realm_name)) + return req + + def patch_vault_kerberos_realm(self, realm_name, body): + '''Update a Kerberos realm.''' + req = dr.discoPatch(self, "/vault/kerberos/realms/{}".format(realm_name), body) + return req + + def post_vault_kerberos_realm(self, realm_name, body, test=False): + '''Create a realm and Test user credentials by attempting to acquire a new Kerberos Ticket Granting Ticket (TGT)''' + req = dr.discoPost(self, "/vault/kerberos/realms/{}".format(realm_name), body) + if test: + req = dr.discoPost(self, "/vault/kerberos/realms/{}/test".format(realm_name), body) + return req + + def get_vault_kerberos_keytabs(self, realm_name): + '''List users with a Kerberos keytab file''' + req = dr.discoRequest(self, "/vault/kerberos/realms/{}/keytabs".format(realm_name)) + return req + + def post_vault_kerberos_keytab(self, realm_name, username, keytab): + '''Upload a Kerberos keytab file''' + # Not Tested + req = dr.keytabPost(self, "/vault/kerberos/realms/{}/keytabs".format(realm_name), keytab, username) + return req + + def delete_vault_kerberos_keytab(self, realm_name, username): + '''Delete a keytab file''' + # Not Tested + req = dr.discoDelete(self, "/vault/kerberos/realms/{}/keytabs/{}".format(realm_name, username)) + return req + + def get_vault_kerberos_ccaches(self, realm_name): + '''List users with a Kerberos credential cache file.''' + req = dr.discoRequest(self, "/vault/kerberos/realms/{}/ccaches".format(realm_name)) + return req + + def post_vault_kerberos_ccache(self, realm_name, username, ccache): + '''Upload a Kerberos credential cache file''' + # Not Tested + req = dr.keytabPost(self, "/vault/kerberos/realms/{}/ccaches".format(realm_name), ccache, username) + return req + + def delete_vault_kerberos_ccache(self, realm_name, username): + '''Delete a cedential cache file''' + req = dr.discoDelete(self, "/vault/kerberos/realms/{}/keytabs/{}".format(realm_name, username)) + return req \ No newline at end of file diff --git a/tideway/knowledge.py b/tideway/knowledge.py index 8dd94fe..f19850b 100644 --- a/tideway/knowledge.py +++ b/tideway/knowledge.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests @@ -13,11 +12,20 @@ def getKnowledgeManagement(self): '''Get the current state of the appliance's knowledge, including TKU versions.''' response = dr.discoRequest(self, "/knowledge") return response + get_knowledge = property(getKnowledgeManagement) def getUploadStatus(self): '''Get the current state of a knowledge upload.''' response = dr.discoRequest(self, "/knowledge/status") return response + get_knowledge_status = property(getUploadStatus) + + def post_knowledge(self, filename, file, activate=True, allow_restart=False): + '''Alternate API call for POST /knowledge/filename''' + self.params['activate'] = activate + self.params['allow_restart'] = allow_restart + response = dr.filePost(self, "/knowledge/{}".format(filename), file) + return response def uploadKnowledge(self, filename, file, activate=True, allow_restart=False): '''Upload a TKU or pattern module to the appliance.''' diff --git a/tideway/main.py b/tideway/main.py index b8f7bd9..83dfb64 100644 --- a/tideway/main.py +++ b/tideway/main.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from tkinter import BASELINE import requests from . import discoRequests as dr from . import endpoints @@ -9,17 +10,43 @@ class Appliance: '''An appliance instance.''' - def __init__(self, target, token, limit = 100, delete = False, api_version = "1.3", ssl_verify = False): + def __init__(self, target, token, limit = 100, delete = False, api_version = "1.5", ssl_verify = False): self.target = target self.token = token self.params = {} self.params['limit'] = limit self.params['delete'] = delete self.api_version = api_version - self.api = "https://" + str(target) + "/api" + self.target_url = "https://" + str(target) + self.api = self.target_url + "/api" self.url = self.api + "/v" + self.api_version self.verify = ssl_verify + def get(self,endpoint): + '''Request any endpoint.''' + req = dr.discoRequest(self,endpoint) + return req + + def post(self,endpoint,body): + '''Post any endpoint.''' + req = dr.discoPost(self, endpoint, body) + return req + + def delete(self,endpoint): + '''Delete any endpoint.''' + req = dr.discoDelete(self, endpoint) + return req + + def patch(self,endpoint,body): + '''Patch any endpoint.''' + req = dr.discoPatch(self, endpoint, body) + return req + + def put(self,endpoint,body): + '''Update any endpoint.''' + req = dr.discoPut(self, endpoint, body) + return req + def credentials(self): c = tideway.credentials(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) return c @@ -36,10 +63,22 @@ def events(self): e = tideway.events(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) return e + def kerberos(self): + ks = tideway.kerberos(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) + return ks + def knowledge(self): k = tideway.knowledge(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) return k + def models(self): + m = tideway.models(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) + return m + + def taxonomy(self): + tx = tideway.topology(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) + return tx + def topology(self): t = tideway.topology(self.target, self.token, api_version=self.api_version, ssl_verify=self.verify) return t @@ -50,28 +89,72 @@ def vault(self): ### Admin ### + @property + def api_about(self): + '''Altnernate API call for /about.''' + url = self.api + "/about" + req = requests.get(url, verify=self.verify) + return req + def about(self): - '''Return about info for API.''' + '''Return about data.''' url = self.api + "/about" req = requests.get(url, verify=self.verify) return req + @property + def api_swagger(self): + '''Alternate API call for swagger.''' + url = self.url + "/swagger.json" + req = requests.get(url, verify=self.verify) + return req + def swagger(self): '''Get swagger file.''' url = self.url + "/swagger.json" req = requests.get(url, verify=self.verify) return req + @property + def get_admin_baseline(self): + '''Alternate API call for baseline.''' + response = dr.discoRequest(self, "/admin/baseline") + return response + def baseline(self): '''Get a summary of the appliance status, and details of which baseline checks have passed or failed.''' response = dr.discoRequest(self, "/admin/baseline") return response + @property + def get_admin_about(self): + '''Alternate API call for /admin/about.''' + response = dr.discoRequest(self, "/admin/about") + return response + def admin(self): '''Get information about the appliance, like its version and versions of the installed packages.''' response = dr.discoRequest(self, "/admin/about") return response + @property + def get_admin_licensing(self): + '''Alternate API call for licensing report.''' + response = dr.discoRequest(self, "/admin/licensing",response="text/plain") + return response + + @property + def get_admin_licensing_csv(self): + '''Alternate API call for licensing report CSV.''' + response = dr.discoRequest(self, "/admin/licensing/csv",response="application/zip") + return response + + @property + def get_admin_licensing_raw(self): + '''Alternate API call for licensing report raw.''' + response = dr.discoRequest(self, "/admin/licensing/raw",response="application/zip") + return response + def licensing(self,content_type="text/plain"): '''Get the latest signed licensing report.''' if content_type == "csv": @@ -82,10 +165,16 @@ def licensing(self,content_type="text/plain"): response = dr.discoRequest(self, "/admin/licensing",response=content_type) return response + @property + def api_help(self): + '''Help on endpoints.''' + endpoints.docs() + #print("") + def help(*args): '''Help on endpoints.''' if len(args) > 1: endpoints.docs(args[1]) else: endpoints.docs() - print("") + #print("\n") \ No newline at end of file diff --git a/tideway/models.py b/tideway/models.py new file mode 100644 index 0000000..a78fb91 --- /dev/null +++ b/tideway/models.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- + +import tideway + +dr = tideway.discoRequests +appliance = tideway.main.Appliance + +class Models(appliance): + '''Manage service and application models.''' + + def get_model(self,name=None,type=None,kind=None,published=None,review_suggested=None,version=None,favorite=None,compatibility=None,results_id=None,delete=False): + '''Get model definitions.''' + if name: + self.params['name'] = name + if type: + self.params['type'] = type + if kind: + self.params['kind'] = kind + if published: + self.params['published'] = published + if review_suggested: + self.params['review_suggested'] = review_suggested + if version: + self.params['version'] = version + if favorite: + self.params['favorite'] = favorite + if compatibility: + self.params['compatibility'] = compatibility + if results_id: + self.params['results_id'] = results_id + if delete: + self.params['delete'] = delete + response = dr.discoRequest(self, "/models") + return response + get_models = property(get_model) + + def post_model(self, body): + '''Create a new model.''' + response = dr.discoPost(self, "/models", body) + return response + + def post_model_multi(self, body): + '''Manipulate multiple models in a single request.''' + response = dr.discoPost(self, "/models/multi", body) + return response + + def delete_model(self, key): + '''Delete a model.''' + response = dr.discoDelete(self, "/models/{}".format(key)) + return response + + def get_model_key(self, key): + '''Get model definition for the specified key.''' + req = dr.discoRequest(self, "/models/{}".format(key)) + return req + + def patch_model(self, key, body): + '''Modify a model.''' + response = dr.discoPatch(self, "/models/{}".format(key), body) + return response + + def get_model_topology(self, key, attributes=None): + '''Get topology for the model definition specified by key.''' + if attributes: + self.params['attributes']=attributes + req = dr.discoRequest(self, "/models/{}/topology".format(key)) + return req + + def get_model_nodecount(self, key): + '''Get node count for the model definition specified by key.''' + req = dr.discoRequest(self, "/models/{}/nodecount".format(key)) + return req + + def get_model_nodes(self, key, format=None, limit=100, results_id=None, delete=False, kind=None): + '''Get nodes for the model definition specified by key.''' + if format: + self.params['format'] = format + if results_id: + self.params['results_id'] = results_id + self.params['limit'] = limit + self.params['delete'] = delete + if kind: + response = dr.discoRequest(self, "/models/{}/nodes/{}".format(key,kind)) + else: + response = dr.discoRequest(self, "/models/{}/nodes".format(key)) + return response + + def delete_model_by_node_id(self, node_id): + '''Delete a model.''' + response = dr.discoDelete(self, "/models/by_node_id/{}".format(node_id)) + return response + + def get_model_by_node_id(self, node_id, expand_related=None): + '''Get model definition for the specified node id.''' + if expand_related: + self.params['expand_related'] = expand_related + response = dr.discoRequest(self, "/models/by_node_id/{}".format(node_id)) + return response + + def patch_model_by_node_id(self, node_id, body): + '''Modify a model.''' + response = dr.discoPatch(self, "/models/by_node_id/{}".format(node_id), body) + return response + + def get_topology_by_node_id(self, node_id, attributes=None): + '''Get topology for the model definition specified by node id.''' + if attributes: + self.params['attributes']=attributes + response = dr.discoRequest(self, "/models/by_node_id/{}/topology".format(node_id)) + return response + + def get_nodecount_by_node_id(self, node_id): + '''Get node count for the model definition specified by node id.''' + response = dr.discoRequest(self, "/models/by_node_id/{}/nodecount".format(node_id)) + return response + + def get_nodes_by_node_id(self, node_id, format=None, limit=100, results_id=None, delete=False, kind=None): + '''Get nodes for the model definition specified by node id.''' + if format: + self.params['format'] = format + if results_id: + self.params['results_id'] = results_id + self.params['limit'] = limit + self.params['delete'] = delete + if kind: + response = dr.discoRequest(self, "/models/by_node_id/{}/nodes/{}".format(node_id,kind)) + else: + response = dr.discoRequest(self, "/models/by_node_id/{}/nodes".format(node_id)) + return response + \ No newline at end of file diff --git a/tideway/taxonomy.py b/tideway/taxonomy.py new file mode 100644 index 0000000..6ac8848 --- /dev/null +++ b/tideway/taxonomy.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +import tideway + +dr = tideway.discoRequests +appliance = tideway.main.Appliance + +class Taxonomy(appliance): + '''Retrieve taxonomy data.''' + + @property + def get_taxonomy_sections(self): + '''Get list of taxonomy model sections.''' + req = dr.discoRequest(self, "/taxonomy/sections") + return req + + @property + def get_taxonomy_locales(self): + '''Get list of known taxonomy locales.''' + req = dr.discoRequest(self, "/taxonomy/locales") + return req + + def get_taxonomy_nodekind(self, format=None, section=None, locale=None, kind=None, fieldlists=False): + '''Get list of defined node kinds with kind info.''' + if format: + self.params['format']=format + self.params['section']=section + self.params['locale']=locale + req = dr.discoRequest(self, "/taxonomy/nodekinds") + elif kind: + self.params['locale']=locale + if fieldlists: + req = dr.discoRequest(self, "/taxonomy/nodekinds/{}/fieldlists".format(kind)) + else: + req = dr.discoRequest(self, "/taxonomy/nodekinds/{}".format(kind)) + else: + req = dr.discoRequest(self, "/taxonomy/nodekinds") + return req + get_taxonomy_nodekinds = property(get_taxonomy_nodekind) + + def get_taxonomy_nodekind_fieldlist(self, kind, fieldlist): + '''Get list of fields for a node kind field list.''' + req = dr.discoRequest(self, "/taxonomy/nodekinds/{}/fieldlists/{}".format(kind,fieldlist)) + return req + + def get_taxonomy_relkind(self, format=None, locale=None, kind=None): + '''Get list of defined node kinds with kind info.''' + if format: + self.params['format']=format + self.params['locale']=locale + req = dr.discoRequest(self, "/taxonomy/relkinds") + elif kind: + self.params['locale']=locale + req = dr.discoRequest(self, "/taxonomy/relkinds/{}".format(kind)) + else: + req = dr.discoRequest(self, "/taxonomy/relkinds") + return req + get_taxonomy_relkinds = property(get_taxonomy_relkind) \ No newline at end of file diff --git a/tideway/topology.py b/tideway/topology.py index ce92f1a..36528b0 100644 --- a/tideway/topology.py +++ b/tideway/topology.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests @@ -9,22 +8,39 @@ class Topology(appliance): '''Retrieve topology data from the datastore.''' + def get_data_nodes_graph(self, node_id, focus="sofware-connected", apply_rules=True, complete=False): + '''Alternate API call for /data/nodes/node_id/graph''' + self.params['focus'] = focus + self.params['apply_rules'] = apply_rules + self.params['complete'] = complete + response = dr.discoRequest(self, "/data/nodes/{}/graph".format(node_id)) + return response + def graphNode(self, node_id, focus="sofware-connected", apply_rules=True): ''' Graph data represents a set of nodes and relationships that are associated to the given node. ''' - # TODO: add complete attribute self.params['focus'] = focus self.params['apply_rules'] = apply_rules response = dr.discoRequest(self, "/data/nodes/{}/graph".format(node_id)) return response + def post_topology_nodes(self, body): + '''Alternate API call for POST /topology/nodes.''' + response = dr.discoPost(self, "/topology/nodes", body) + return response + def getNodes(self, body): '''Get topology data from one or more starting nodes.''' response = dr.discoPost(self, "/topology/nodes", body) return response + def post_topology_nodes_kinds(self, body): + '''Alternate API call for POST /topology/nodes/kinds.''' + response = dr.discoPost(self, "/topology/nodes/kinds", body) + return response + def getNodeKinds(self, body): ''' Get nodes of the specified kinds which are related to a given set of @@ -40,6 +56,12 @@ def visualizationState(self): ''' response = dr.discoRequest(self, "/topology/visualization_state") return response + get_topology_viz_state = property(visualizationState) + + def patch_topology_viz_state(self, body): + '''Alternate API call for PATCH /topology/visualization_state''' + response = dr.discoPatch(self, "/topology/visualization_state", body) + return response def updateVizState(self, body): ''' @@ -49,6 +71,11 @@ def updateVizState(self, body): response = dr.discoPatch(self, "/topology/visualization_state", body) return response + def put_topology_viz_state(self, body): + '''Alternate API call for PUT /topology/visualization_state''' + response = dr.discoPut(self, "/topology/visualization_state", body) + return response + def replaceVizState(self, body): ''' Update any or all of the attributes of the current state of the diff --git a/tideway/vault.py b/tideway/vault.py index ac2d18c..50d47e8 100644 --- a/tideway/vault.py +++ b/tideway/vault.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import requests import tideway dr = tideway.discoRequests @@ -13,6 +12,12 @@ def getVault(self): '''Get details of the state of the vault.''' response = dr.discoRequest(self, "/vault") return response + get_vault = property(getVault) + + def patch_vault(self, body): + '''Alternate API call for PATCH /vault''' + response = dr.discoPatch(self, "/vault", body) + return response def updateVault(self, body): '''Change the state of the vault.'''