diff --git a/.coveragerc b/.coveragerc
index 954413c..ad0247b 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -19,4 +19,4 @@ exclude_lines =
raise NotImplementedError
# Don't complain if non-runnable code isn't run:
- if __name__ == .__main__.:
+ if __name__ == .__main__.:
\ No newline at end of file
diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml
index aaba681..feb1056 100644
--- a/.github/workflows/publish-to-pypi.yml
+++ b/.github/workflows/publish-to-pypi.yml
@@ -41,6 +41,14 @@ jobs:
--wheel
--outdir dist/
+ - name: Setup the GitHub user
+ run: |
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
+ git config --local user.name "github-actions[bot]"
+
+ - name: Update the GitHub pages documentation
+ run: cd docs && mkdocs gh-deploy --force && cd ..
+
- name: Publish distribution package to PyPI
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml
index 8fd1726..643a0d5 100644
--- a/.github/workflows/pull-request-checks.yml
+++ b/.github/workflows/pull-request-checks.yml
@@ -87,27 +87,30 @@ jobs:
hide-badge: true
create-new-commit: true
- - name: "Check if coverage badge file existence"
- id: check_files
- uses: andstor/file-existence-action@v1
- with:
- files: "docs/coverage.svg"
-
- name: Generate coverage badge
- if: steps.check_files.outputs.files_exists == 'false'
- run: coverage-badge -o docs/coverage.svg -f
+ run: coverage-badge -f -o docs/coverage.svg
+
+ - name: Generate documentation
+ run: pydoc-markdown --render-toc && mv build/docs/* docs
+
+ - name: Check changed files
+ uses: tj-actions/verify-changed-files@v8.8
+ id: verify-changed-files
+ with:
+ files: |
+ docs
- name: Commit files
- if: steps.check_files.outputs.files_exists == 'false'
+ if: steps.verify-changed-files.outputs.files_changed == 'true'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- git add --force docs/coverage.svg
- git commit -m "Add coverage badge"
+ git add --force docs
+ git commit -m "Add coverage badge and documentation"
- name: Push changes
- if: steps.check_files.outputs.files_exists == 'false'
uses: ad-m/github-push-action@master
+ if: steps.verify-changed-files.outputs.files_changed == 'true'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.head_ref }}
diff --git a/README.md b/README.md
index 2c52760..fa5524c 100644
--- a/README.md
+++ b/README.md
@@ -28,32 +28,94 @@ The repository includes an SDK for the Grafana API. It's possible to communicate
### Search
- Execute a custom query against the Grafana search endpoint
+### Datasource
+- Get all datasources
+- Get the datasource by id
+- Get the datasource by uid
+- Get the datasource by name
+- Get the datasource id by name
+- Create a new datasource
+- Update a datasource
+- Delete a datasource by id
+- Delete a datasource by uid
+- Delete a datasource by name
+- Query a datasource by id
+- Enabled datasource permissions
+- Disable datasource permissions
+- Get datasource permissions
+- Add datasource permissions
+- Delete datasource permissions
+
+### Legacy Alerting
+- Get alerts
+- Get alerts by dashboard ids
+- Get alert by id
+- Pause alert by id
+- Unpause alert by id
+
+### Alerting
+- Get all Alertmanager alerts
+- Create or update Alertmanager alerts
+- Get Alertmanager group alerts
+
+- Get all Alertmanager silences
+- Get Alertmanager silence by id
+- Create or update Alertmanager silence
+- Delete Alertmanager silence by id
+- Get Alertmanager status
+- Get the Alertmanager config
+- Create or update the Alertmanager config
+- Delete the Alertmanager config
+- Test the Alertmanager receivers
+- Get Prometheus alerts
+- Get Prometheus rules
+- Get Ruler rules
+- Get a Ruler group
+- Get Ruler groups by the namespace
+- Create or update the Ruler group by the namespace
+- Delete a Ruler group
+- Delete a Ruler namespace
+- Test a datasource rule
+- Test a recipient rule
+- Get the NGAlert organization configuration
+- Get the NGAlert Alertmanager configuration by the organization
+- Create or update the NGAlert organization configuration
+- Delete the NGAlert organization configuration
+
+### Alerting Channels
+- Get all notification channels
+- Get all notification channels (lookup)
+- Get a notification channel by id
+- Get a notification channel by uid
+- Create an notification channel
+- Update a notification channel by id
+- Update a notification channel by uid
+- Delete a notification channel by id
+- Delete a notification channel by uid
+- Test a notification channel
+
## Feature timeline
The following table describes the plan to implement the rest of the Grafana API functionality. Please, open an issue and vote them up, if you prefer a faster implementation of an API functionality.
| API endpoint group | Implementation week | Maintainer | PR | State |
|:------------------:|:-------------------:|:----------:|:--:|:-----:|
-| [Admin HTTP API](https://grafana.com/docs/grafana/latest/http_api/admin/) | | | | |
-| [Alerting HTTP API](https://grafana.com/docs/grafana/latest/http_api/alerting/) | 4 | [ZPascal](https://github.com/ZPascal) | | Planned |
-| [Alerting Notification Channels HTTP API](https://grafana.com/docs/grafana/latest/http_api/alerting_notification_channels/) | 4 | [ZPascal](https://github.com/ZPascal) | | Planned |
-| [Annotations HTTP API](https://grafana.com/docs/grafana/latest/http_api/annotations/) | | | | |
-| [Authentication HTTP API](https://grafana.com/docs/grafana/latest/http_api/auth/) | | | | |
-| [Data source HTTP API](https://grafana.com/docs/grafana/latest/http_api/data_source/) | 5 | [ZPascal](https://github.com/ZPascal) | | Planned |
-| [Datasource Permissions HTTP API](https://grafana.com/docs/grafana/latest/http_api/datasource_permissions/) | | | | |
-| [External Group Sync HTTP API](https://grafana.com/docs/grafana/latest/http_api/external_group_sync/) | | | | |
-| [Fine-grained access control HTTP API](https://grafana.com/docs/grafana/latest/http_api/access_control/) | | | | |
-| [HTTP Preferences API](https://grafana.com/docs/grafana/latest/http_api/preferences/) | | | | |
-| [HTTP Snapshot API](https://grafana.com/docs/grafana/latest/http_api/snapshot/) | | | | |
-| [Library Element HTTP API](https://grafana.com/docs/grafana/latest/http_api/library_element/) | | | | |
-| [Licensing HTTP API](https://grafana.com/docs/grafana/latest/http_api/licensing/) | | | | |
-| [Organization HTTP API](https://grafana.com/docs/grafana/latest/http_api/org/) | | | | |
-| [Other HTTP API](https://grafana.com/docs/grafana/latest/http_api/other/) | | | | |
-| [Playlist HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/) | | | | |
-| [Reporting API](https://grafana.com/docs/grafana/latest/http_api/reporting/) | | | | |
-| [Short URL HTTP API](https://grafana.com/docs/grafana/latest/http_api/short_url/) | | | | |
-| [Team HTTP API](https://grafana.com/docs/grafana/latest/http_api/team/) | | | | |
-| [User HTTP API](https://grafana.com/docs/grafana/latest/http_api/user/) | | | | |
+| [Admin HTTP API](https://grafana.com/docs/grafana/latest/http_api/admin/) | | | | |
+| [Annotations HTTP API](https://grafana.com/docs/grafana/latest/http_api/annotations/) | | | | |
+| [Authentication HTTP API](https://grafana.com/docs/grafana/latest/http_api/auth/) | | | | |
+| [External Group Sync HTTP API](https://grafana.com/docs/grafana/latest/http_api/external_group_sync/) | | | | |
+| [Fine-grained access control HTTP API](https://grafana.com/docs/grafana/latest/http_api/access_control/) | | | | |
+| [HTTP Preferences API](https://grafana.com/docs/grafana/latest/http_api/preferences/) | | | | |
+| [HTTP Snapshot API](https://grafana.com/docs/grafana/latest/http_api/snapshot/) | | | | |
+| [Library Element HTTP API](https://grafana.com/docs/grafana/latest/http_api/library_element/) | | | | |
+| [Licensing HTTP API](https://grafana.com/docs/grafana/latest/http_api/licensing/) | | | | |
+| [Organization HTTP API](https://grafana.com/docs/grafana/latest/http_api/org/) | 13 | | | In process |
+| [Other HTTP API](https://grafana.com/docs/grafana/latest/http_api/other/) | | | | |
+| [Playlist HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/) | | | | |
+| [Reporting API](https://grafana.com/docs/grafana/latest/http_api/reporting/) | | | | |
+| [Short URL HTTP API](https://grafana.com/docs/grafana/latest/http_api/short_url/) | 13 | | | In process |
+| [Team HTTP API](https://grafana.com/docs/grafana/latest/http_api/team/) | | | | |
+| [User HTTP API](https://grafana.com/docs/grafana/latest/http_api/user/) | | | | |
## Installation
diff --git a/docs/.placeholder b/docs/.placeholder
deleted file mode 100644
index e69de29..0000000
diff --git a/docs/content/grafana_api/alerting-notifications.md b/docs/content/grafana_api/alerting-notifications.md
new file mode 100644
index 0000000..6fc31b0
--- /dev/null
+++ b/docs/content/grafana_api/alerting-notifications.md
@@ -0,0 +1,280 @@
+# Table of Contents
+
+* [grafana\_api.alerting\_notifications](#grafana_api.alerting_notifications)
+ * [AlertingNotifications](#grafana_api.alerting_notifications.AlertingNotifications)
+ * [get\_all\_notification\_channels](#grafana_api.alerting_notifications.AlertingNotifications.get_all_notification_channels)
+ * [get\_all\_notification\_channels\_lookup](#grafana_api.alerting_notifications.AlertingNotifications.get_all_notification_channels_lookup)
+ * [get\_notification\_channel\_by\_uid](#grafana_api.alerting_notifications.AlertingNotifications.get_notification_channel_by_uid)
+ * [get\_notification\_channel\_by\_id](#grafana_api.alerting_notifications.AlertingNotifications.get_notification_channel_by_id)
+ * [create\_notification\_channel](#grafana_api.alerting_notifications.AlertingNotifications.create_notification_channel)
+ * [update\_notification\_channel\_by\_uid](#grafana_api.alerting_notifications.AlertingNotifications.update_notification_channel_by_uid)
+ * [update\_notification\_channel\_by\_id](#grafana_api.alerting_notifications.AlertingNotifications.update_notification_channel_by_id)
+ * [delete\_notification\_channel\_by\_uid](#grafana_api.alerting_notifications.AlertingNotifications.delete_notification_channel_by_uid)
+ * [delete\_notification\_channel\_by\_id](#grafana_api.alerting_notifications.AlertingNotifications.delete_notification_channel_by_id)
+ * [test\_notification\_channel](#grafana_api.alerting_notifications.AlertingNotifications.test_notification_channel)
+
+
+
+# grafana\_api.alerting\_notifications
+
+
+
+## AlertingNotifications Objects
+
+```python
+class AlertingNotifications()
+```
+
+The class includes all necessary methods to access the Grafana alerting notifications API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### get\_all\_notification\_channels
+
+```python
+def get_all_notification_channels() -> list
+```
+
+The method includes a functionality to get all alerting notification channels
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns all notification channels
+
+
+
+#### get\_all\_notification\_channels\_lookup
+
+```python
+def get_all_notification_channels_lookup() -> list
+```
+
+The method includes a functionality to lookup and get reduced information of all alerting notification channels
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns all notification channels as reduced information
+
+
+
+#### get\_notification\_channel\_by\_uid
+
+```python
+def get_notification_channel_by_uid(uid: str) -> dict
+```
+
+The method includes a functionality to get an alerting notification channel specified by the uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the notification channel
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the specified notification channel
+
+
+
+#### get\_notification\_channel\_by\_id
+
+```python
+def get_notification_channel_by_id(id: int) -> dict
+```
+
+The method includes a functionality to get an alerting notification channel specified by the id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the notification channel
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the specified notification channel
+
+
+
+#### create\_notification\_channel
+
+```python
+def create_notification_channel(notification_channel: dict) -> dict
+```
+
+The method includes a functionality to create an alerting notification channel specified by the notification channel dict
+
+**Arguments**:
+
+- `notification_channel` _dict_ - Specify the channel of the notification
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the newly created notification channel
+
+
+
+#### update\_notification\_channel\_by\_uid
+
+```python
+def update_notification_channel_by_uid(uid: str,
+ notification_channel: dict) -> dict
+```
+
+The method includes a functionality to update an alerting notification channel specified by the notification channel dict and the uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the notification channel
+- `notification_channel` _dict_ - Specify the channel of the notification
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the updated notification channel
+
+
+
+#### update\_notification\_channel\_by\_id
+
+```python
+def update_notification_channel_by_id(id: int,
+ notification_channel: dict) -> dict
+```
+
+The method includes a functionality to update an alerting notification channel specified by the notification channel dict and the id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the notification channel
+- `notification_channel` _dict_ - Specify the channel of the notification
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the updated notification channel
+
+
+
+#### delete\_notification\_channel\_by\_uid
+
+```python
+def delete_notification_channel_by_uid(uid: str)
+```
+
+The method includes a functionality to delete an alerting notification channel specified by the uid
+
+**Arguments**:
+
+- `uid` _uid_ - Specify the uid of the notification channel
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_notification\_channel\_by\_id
+
+```python
+def delete_notification_channel_by_id(id: int)
+```
+
+The method includes a functionality to delete an alerting notification channel specified by the id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the notification channel
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### test\_notification\_channel
+
+```python
+def test_notification_channel(notification_channel: dict)
+```
+
+The method includes a functionality to test an alerting notification channel specified by the notification_channel
+
+**Arguments**:
+
+- `notification_channel` _dict_ - Specify the channel of the notification
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
diff --git a/docs/content/grafana_api/alerting.md b/docs/content/grafana_api/alerting.md
new file mode 100644
index 0000000..8ed963e
--- /dev/null
+++ b/docs/content/grafana_api/alerting.md
@@ -0,0 +1,730 @@
+# Table of Contents
+
+* [grafana\_api.alerting](#grafana_api.alerting)
+ * [Alerting](#grafana_api.alerting.Alerting)
+ * [get\_alertmanager\_alerts](#grafana_api.alerting.Alerting.get_alertmanager_alerts)
+ * [create\_or\_update\_alertmanager\_alerts](#grafana_api.alerting.Alerting.create_or_update_alertmanager_alerts)
+ * [get\_alertmanager\_group\_alerts](#grafana_api.alerting.Alerting.get_alertmanager_group_alerts)
+ * [delete\_alertmanager\_silence\_by\_id](#grafana_api.alerting.Alerting.delete_alertmanager_silence_by_id)
+ * [get\_alertmanager\_silence\_by\_id](#grafana_api.alerting.Alerting.get_alertmanager_silence_by_id)
+ * [get\_alertmanager\_silences](#grafana_api.alerting.Alerting.get_alertmanager_silences)
+ * [create\_or\_update\_alertmanager\_silence](#grafana_api.alerting.Alerting.create_or_update_alertmanager_silence)
+ * [get\_alertmanager\_status](#grafana_api.alerting.Alerting.get_alertmanager_status)
+ * [delete\_alertmanager\_config](#grafana_api.alerting.Alerting.delete_alertmanager_config)
+ * [get\_alertmanager\_config](#grafana_api.alerting.Alerting.get_alertmanager_config)
+ * [create\_or\_update\_alertmanager\_config](#grafana_api.alerting.Alerting.create_or_update_alertmanager_config)
+ * [test\_alertmanager\_receivers](#grafana_api.alerting.Alerting.test_alertmanager_receivers)
+ * [get\_prometheus\_alerts](#grafana_api.alerting.Alerting.get_prometheus_alerts)
+ * [get\_prometheus\_rules](#grafana_api.alerting.Alerting.get_prometheus_rules)
+ * [get\_ruler\_rules](#grafana_api.alerting.Alerting.get_ruler_rules)
+ * [delete\_ruler\_namespace](#grafana_api.alerting.Alerting.delete_ruler_namespace)
+ * [get\_ruler\_groups\_by\_namespace](#grafana_api.alerting.Alerting.get_ruler_groups_by_namespace)
+ * [create\_or\_update\_ruler\_group\_by\_namespace](#grafana_api.alerting.Alerting.create_or_update_ruler_group_by_namespace)
+ * [delete\_ruler\_group](#grafana_api.alerting.Alerting.delete_ruler_group)
+ * [get\_ruler\_group](#grafana_api.alerting.Alerting.get_ruler_group)
+ * [test\_rule](#grafana_api.alerting.Alerting.test_rule)
+ * [test\_recipient\_rule](#grafana_api.alerting.Alerting.test_recipient_rule)
+ * [delete\_ngalert\_organization\_configuration](#grafana_api.alerting.Alerting.delete_ngalert_organization_configuration)
+ * [get\_ngalert\_organization\_configuration](#grafana_api.alerting.Alerting.get_ngalert_organization_configuration)
+ * [create\_or\_update\_ngalert\_organization\_configuration](#grafana_api.alerting.Alerting.create_or_update_ngalert_organization_configuration)
+ * [get\_ngalert\_alertmanagers\_by\_organization](#grafana_api.alerting.Alerting.get_ngalert_alertmanagers_by_organization)
+
+
+
+# grafana\_api.alerting
+
+
+
+## Alerting Objects
+
+```python
+class Alerting()
+```
+
+The class includes all necessary methods to access the Grafana alerting API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### get\_alertmanager\_alerts
+
+```python
+def get_alertmanager_alerts(recipient: any = "grafana") -> list
+```
+
+The method includes a functionality to get the Alertmanager alerts specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns the list of Alertmanager alerts
+
+
+
+#### create\_or\_update\_alertmanager\_alerts
+
+```python
+def create_or_update_alertmanager_alerts(alerts: list,
+ recipient: any = "grafana")
+```
+
+The method includes a functionality to create or update the Alertmanager alerts specified by the recipient and the alerts list
+
+**Arguments**:
+
+- `alerts` _list_ - Specify a list of the alert objects
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_alertmanager\_group\_alerts
+
+```python
+def get_alertmanager_group_alerts(recipient: any = "grafana") -> list
+```
+
+The method includes a functionality to get the Alertmanager group alerts specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns the list of Alertmanager group alerts
+
+
+
+#### delete\_alertmanager\_silence\_by\_id
+
+```python
+def delete_alertmanager_silence_by_id(silence_id: str,
+ recipient: any = "grafana")
+```
+
+The method includes a functionality to delete the Alertmanager silence specified by the silence id and the recipient
+
+**Arguments**:
+
+- `silence_id` _str_ - Specify the silence id of the alerts
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_alertmanager\_silence\_by\_id
+
+```python
+def get_alertmanager_silence_by_id(silence_id: str,
+ recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to get the Alertmanager silence specified by the silence id and the recipient
+
+**Arguments**:
+
+- `silence_id` _str_ - Specify the silence id of the alerts
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of Alertmanager silence alert
+
+
+
+#### get\_alertmanager\_silences
+
+```python
+def get_alertmanager_silences(recipient: any = "grafana") -> list
+```
+
+The method includes a functionality to get all Alertmanager silences specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns the list of Alertmanager silence alerts
+
+
+
+#### create\_or\_update\_alertmanager\_silence
+
+```python
+def create_or_update_alertmanager_silence(silence: Silence,
+ recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to create or update the Alertmanager silence specified by the silence object and the recipient
+
+**Arguments**:
+
+ silence -> Specify the silence object
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of newly created silence alert
+
+
+
+#### get\_alertmanager\_status
+
+```python
+def get_alertmanager_status(recipient: str = "grafana") -> dict
+```
+
+The method includes a functionality to get the Alertmanager status specified by the recipient
+
+**Arguments**:
+
+- `recipient` _str_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of the Alertmanager status
+
+
+
+#### delete\_alertmanager\_config
+
+```python
+def delete_alertmanager_config(recipient: any = "grafana")
+```
+
+The method includes a functionality to delete the Alertmanager config specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_alertmanager\_config
+
+```python
+def get_alertmanager_config(recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to get the Alertmanager config specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of the Alertmanager config
+
+
+
+#### create\_or\_update\_alertmanager\_config
+
+```python
+def create_or_update_alertmanager_config(
+ alertmanager_config: AlertmanagerConfig,
+ recipient: any = "grafana",
+ template_files: dict = None)
+```
+
+The method includes a functionality to create or update the Alertmanager config specified by the Alertmanager config object, recipient and template_files
+
+**Arguments**:
+
+- `alertmanager_config` _AlertmanagerConfig_ - Specify the Alertmanager config object
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+- `template_files(dict)` - Specify the optional template files (default None)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### test\_alertmanager\_receivers
+
+```python
+def test_alertmanager_receivers(alert: dict,
+ receivers: list,
+ recipient: any = "grafana")
+```
+
+The method includes a functionality to test the Alertmanager receivers specified by the alert dict, receivers object and the recipient
+
+**Arguments**:
+
+- `alert` _dict_ - Specify the alert dict
+- `receivers` _list_ - Specify the list of AlertmanagerReceivers objects
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_prometheus\_alerts
+
+```python
+def get_prometheus_alerts(recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to get all prometheus alerts specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of the prometheus alerts
+
+
+
+#### get\_prometheus\_rules
+
+```python
+def get_prometheus_rules(recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to get all prometheus rules specified by the recipient
+
+**Arguments**:
+
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of the prometheus rules
+
+
+
+#### get\_ruler\_rules
+
+```python
+def get_ruler_rules(recipient: str = "grafana") -> dict
+```
+
+The method includes a functionality to get all ruler rules specified by the recipient
+
+**Arguments**:
+
+- `recipient` _str_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of the ruler rules
+
+
+
+#### delete\_ruler\_namespace
+
+```python
+def delete_ruler_namespace(namespace: str, recipient: any = "grafana")
+```
+
+The method includes a functionality to delete a ruler namespace specified by the namespace name and the recipient
+
+**Arguments**:
+
+- `namespace` _str_ - Specify the namespace name
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_ruler\_groups\_by\_namespace
+
+```python
+def get_ruler_groups_by_namespace(namespace: str,
+ recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to get all ruler groups specified by the namespace name and the recipient
+
+**Arguments**:
+
+- `namespace` _str_ - Specify the namespace name
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of the ruler groups
+
+
+
+#### create\_or\_update\_ruler\_group\_by\_namespace
+
+```python
+def create_or_update_ruler_group_by_namespace(namespace: str,
+ group_name: str,
+ rules: list,
+ recipient: any = "grafana",
+ interval: int = 0)
+```
+
+The method includes a functionality to create or update a ruler group specified by the namespace name, a ruler group name, a ruler rule object list, the recipient and an interval
+
+**Arguments**:
+
+- `namespace` _str_ - Specify the namespace name
+- `group_name` _str_ - Specify the ruler group name
+- `rules` _list_ - Specify the ruler rule object list
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+- `interval` _int_ - Specify the interval of the ruler (default 0)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_ruler\_group
+
+```python
+def delete_ruler_group(namespace: str,
+ group_name: str,
+ recipient: any = "grafana")
+```
+
+The method includes a functionality to delete a ruler group specified by the namespace name, a ruler group name and the recipient
+
+**Arguments**:
+
+- `namespace` _str_ - Specify the namespace name
+- `group_name` _str_ - Specify the ruler group name
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_ruler\_group
+
+```python
+def get_ruler_group(namespace: str,
+ group_name: str,
+ recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to get a ruler group specified by the namespace name, a ruler group name and the recipient
+
+**Arguments**:
+
+- `namespace` _str_ - Specify the namespace name
+- `group_name` _str_ - Specify the ruler group name
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dict of all ruler groups
+
+
+
+#### test\_rule
+
+```python
+def test_rule(data_query: list) -> dict
+```
+
+The method includes a functionality to test a rule specified by a list of datasource rule query objects
+
+**Arguments**:
+
+- `data_query` _list_ - Specify a list of datasource rule query objects
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _str_ - Returns the result of the specified query
+
+
+
+#### test\_recipient\_rule
+
+```python
+def test_recipient_rule(expr: str,
+ condition: str,
+ data_query: list,
+ recipient: any = "grafana") -> dict
+```
+
+The method includes a functionality to test a recipient role specified by the expr, the condition, a list of data queries and the recipient
+
+**Arguments**:
+
+- `expr` _str_ - Specify a list of datasource rule query objects
+- `condition` _str_ - Specify the condition
+- `data_query` _list_ - Specify a list of datasource rule query objects
+- `recipient` _any_ - Specify the recipient datasource id of the alerts (default grafana)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the result of the specified recipient rule
+
+
+
+#### delete\_ngalert\_organization\_configuration
+
+```python
+def delete_ngalert_organization_configuration()
+```
+
+The method includes a functionality to delete the NGAlert organization admin configuration
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_ngalert\_organization\_configuration
+
+```python
+def get_ngalert_organization_configuration() -> dict
+```
+
+The method includes a functionality to get the NGAlert organization admin configuration
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the NGAlert organization configuration
+
+
+
+#### create\_or\_update\_ngalert\_organization\_configuration
+
+```python
+def create_or_update_ngalert_organization_configuration(
+ alert_managers: list, alertmanagers_choice: str = "all")
+```
+
+The method includes a functionality to create or update the NGAlert organization admin configuration
+
+**Arguments**:
+
+- `alert_managers` _list_ - Specify the list of alert manager names
+- `alertmanagers_choice` _str_ - Specify the Alertmanagers choice (default all)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_ngalert\_alertmanagers\_by\_organization
+
+```python
+def get_ngalert_alertmanagers_by_organization() -> dict
+```
+
+The method includes a functionality to get the discovered and dropped Alertmanagers of the user's organization and based on the specified configuration
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the NGAlert Alertmanagers
+
diff --git a/docs/content/grafana_api/api.md b/docs/content/grafana_api/api.md
new file mode 100644
index 0000000..e820a33
--- /dev/null
+++ b/docs/content/grafana_api/api.md
@@ -0,0 +1,57 @@
+# Table of Contents
+
+* [grafana\_api.api](#grafana_api.api)
+ * [Api](#grafana_api.api.Api)
+ * [call\_the\_api](#grafana_api.api.Api.call_the_api)
+
+
+
+# grafana\_api.api
+
+
+
+## Api Objects
+
+```python
+class Api()
+```
+
+The class includes all necessary methods to make API calls to the Grafana API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### call\_the\_api
+
+```python
+def call_the_api(api_call: str,
+ method: RequestsMethods = RequestsMethods.GET,
+ json_complete: str = None) -> any
+```
+
+The method execute a defined API call against the Grafana endpoints
+
+**Arguments**:
+
+- `api_call` _str_ - Specify the API call endpoint
+- `method` _RequestsMethods_ - Specify the used method (default GET)
+- `json_complete` _str_ - Specify the inserted JSON as string
+
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _any_ - Returns the value of the api call
+
diff --git a/docs/content/grafana_api/dashboard.md b/docs/content/grafana_api/dashboard.md
new file mode 100644
index 0000000..6743ddf
--- /dev/null
+++ b/docs/content/grafana_api/dashboard.md
@@ -0,0 +1,345 @@
+# Table of Contents
+
+* [grafana\_api.dashboard](#grafana_api.dashboard)
+ * [Dashboard](#grafana_api.dashboard.Dashboard)
+ * [create\_or\_update\_dashboard](#grafana_api.dashboard.Dashboard.create_or_update_dashboard)
+ * [delete\_dashboard\_by\_name\_and\_path](#grafana_api.dashboard.Dashboard.delete_dashboard_by_name_and_path)
+ * [get\_dashboard\_by\_uid](#grafana_api.dashboard.Dashboard.get_dashboard_by_uid)
+ * [get\_dashboard\_home](#grafana_api.dashboard.Dashboard.get_dashboard_home)
+ * [get\_dashboard\_tags](#grafana_api.dashboard.Dashboard.get_dashboard_tags)
+ * [get\_dashboard\_uid\_and\_id\_by\_name\_and\_folder](#grafana_api.dashboard.Dashboard.get_dashboard_uid_and_id_by_name_and_folder)
+ * [get\_dashboard\_permissions](#grafana_api.dashboard.Dashboard.get_dashboard_permissions)
+ * [update\_dashboard\_permissions](#grafana_api.dashboard.Dashboard.update_dashboard_permissions)
+ * [get\_dashboard\_versions](#grafana_api.dashboard.Dashboard.get_dashboard_versions)
+ * [get\_dashboard\_version](#grafana_api.dashboard.Dashboard.get_dashboard_version)
+ * [restore\_dashboard\_version](#grafana_api.dashboard.Dashboard.restore_dashboard_version)
+ * [calculate\_dashboard\_diff](#grafana_api.dashboard.Dashboard.calculate_dashboard_diff)
+
+
+
+# grafana\_api.dashboard
+
+
+
+## Dashboard Objects
+
+```python
+class Dashboard()
+```
+
+The class includes all necessary methods to access the Grafana dashboard API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### create\_or\_update\_dashboard
+
+```python
+def create_or_update_dashboard(dashboard_path: str,
+ dashboard_json: dict,
+ message: str,
+ overwrite: bool = False)
+```
+
+The method includes a functionality to create the specified dashboard
+
+**Arguments**:
+
+- `dashboard_path` _str_ - Specify the dashboard path in which the dashboard is to be placed
+- `dashboard_json` _dict_ - Specify the inserted dashboard as dict
+- `message` _str_ - Specify the message that should be injected as commit message inside the dashboard
+- `overwrite` _bool_ - Should the already existing dashboard be overwritten (default False)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_dashboard\_by\_name\_and\_path
+
+```python
+def delete_dashboard_by_name_and_path(dashboard_name: str,
+ dashboard_path: str)
+```
+
+The method includes a functionality to delete the specified dashboard inside the model
+
+**Arguments**:
+
+- `dashboard_name` _str_ - Specify the dashboard name of the deleted dashboard
+- `dashboard_path` _str_ - Specify the dashboard path in which the dashboard is to be placed
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_dashboard\_by\_uid
+
+```python
+def get_dashboard_by_uid(uid: str) -> dict
+```
+
+The method includes a functionality to get the dashboard from the specified uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the dashboard
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dashboard
+
+
+
+#### get\_dashboard\_home
+
+```python
+def get_dashboard_home() -> dict
+```
+
+The method includes a functionality to get the home dashboard
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the home dashboard
+
+
+
+#### get\_dashboard\_tags
+
+```python
+def get_dashboard_tags() -> list
+```
+
+The method includes a functionality to get the all tags of all dashboards
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns all dashboard tags
+
+
+
+#### get\_dashboard\_uid\_and\_id\_by\_name\_and\_folder
+
+```python
+def get_dashboard_uid_and_id_by_name_and_folder(dashboard_name: str,
+ dashboard_path: str) -> dict
+```
+
+The method includes a functionality to extract the dashboard uid specified inside the model
+
+**Arguments**:
+
+- `dashboard_name` _str_ - Specify the dashboard name of the dashboard
+- `dashboard_path` _str_ - Specify the dashboard path of the dashboard
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the dashboard uid and the id
+
+
+
+#### get\_dashboard\_permissions
+
+```python
+def get_dashboard_permissions(id: int) -> list
+```
+
+The method includes a functionality to extract the dashboard permissions based on the specified id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the dashboard
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns the dashboard permissions of a dashboard as list
+
+
+
+#### update\_dashboard\_permissions
+
+```python
+def update_dashboard_permissions(id: int, permission_json: dict)
+```
+
+The method includes a functionality to update the dashboard permissions based on the specified id and the permission json document
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the dashboard
+- `permission_json` _dict_ - Specify the inserted permissions as dict
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_dashboard\_versions
+
+```python
+def get_dashboard_versions(id: int) -> list
+```
+
+The method includes a functionality to extract the versions of a dashboard based on the specified id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the dashboard
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns all dashboard versions of a dashboard as list
+
+
+
+#### get\_dashboard\_version
+
+```python
+def get_dashboard_version(id: int, version_id: int) -> dict
+```
+
+The method includes a functionality to extract a specified version of a dashboard based on the specified dashboard id and a version_id of the dashboard
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the dashboard
+- `version_id` _int_ - Specify the version_id of a dashboard
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns a dashboard version of a dashboard as dict
+
+
+
+#### restore\_dashboard\_version
+
+```python
+def restore_dashboard_version(id: int, version: dict)
+```
+
+The method includes a functionality to restore a specified version of a dashboard based on the specified dashboard uid and a version as dict of the dashboard
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the dashboard
+- `version` _dict_ - Specify the version_id of a dashboard
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### calculate\_dashboard\_diff
+
+```python
+def calculate_dashboard_diff(dashboard_id_and_version_base: dict,
+ dashboard_id_and_version_new: dict,
+ diff_type: str = "json") -> str
+```
+
+The method includes a functionality to calculate the diff of specified versions of a dashboard based on the specified dashboard uid and the selected version of the base dashboard and the new dashboard and the diff type (basic or json)
+
+**Arguments**:
+
+- `dashboard_id_and_version_base` _dict_ - Specify the version and id of the base dashboard
+- `dashboard_id_and_version_new` _dict_ - Specify the version and id of the new dashboard
+- `diff_type` _str_ - Specify the diff type (basic or json) (default json)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _str_ - Returns the difference of the two specified dashboards
+
diff --git a/docs/content/grafana_api/datasource.md b/docs/content/grafana_api/datasource.md
new file mode 100644
index 0000000..e9c4d93
--- /dev/null
+++ b/docs/content/grafana_api/datasource.md
@@ -0,0 +1,506 @@
+# Table of Contents
+
+* [grafana\_api.datasource](#grafana_api.datasource)
+ * [Datasource](#grafana_api.datasource.Datasource)
+ * [get\_all\_datasources](#grafana_api.datasource.Datasource.get_all_datasources)
+ * [get\_datasource\_by\_id](#grafana_api.datasource.Datasource.get_datasource_by_id)
+ * [get\_datasource\_by\_uid](#grafana_api.datasource.Datasource.get_datasource_by_uid)
+ * [get\_datasource\_by\_name](#grafana_api.datasource.Datasource.get_datasource_by_name)
+ * [get\_datasource\_id\_by\_name](#grafana_api.datasource.Datasource.get_datasource_id_by_name)
+ * [create\_datasource](#grafana_api.datasource.Datasource.create_datasource)
+ * [update\_datasource](#grafana_api.datasource.Datasource.update_datasource)
+ * [delete\_datasource\_by\_id](#grafana_api.datasource.Datasource.delete_datasource_by_id)
+ * [delete\_datasource\_by\_uid](#grafana_api.datasource.Datasource.delete_datasource_by_uid)
+ * [delete\_datasource\_by\_name](#grafana_api.datasource.Datasource.delete_datasource_by_name)
+ * [query\_datasource\_by\_id](#grafana_api.datasource.Datasource.query_datasource_by_id)
+ * [enable\_datasource\_permissions](#grafana_api.datasource.Datasource.enable_datasource_permissions)
+ * [disable\_datasource\_permissions](#grafana_api.datasource.Datasource.disable_datasource_permissions)
+ * [get\_datasource\_permissions](#grafana_api.datasource.Datasource.get_datasource_permissions)
+ * [add\_datasource\_permissions](#grafana_api.datasource.Datasource.add_datasource_permissions)
+ * [delete\_datasource\_permissions](#grafana_api.datasource.Datasource.delete_datasource_permissions)
+
+
+
+# grafana\_api.datasource
+
+
+
+## Datasource Objects
+
+```python
+class Datasource()
+```
+
+The class includes all necessary methods to access the Grafana datasource API endpoints. It's required that the API token got the corresponding datasource access rights. Please check the used methods docstring for the necessary access rights
+
+HINT: Note Grafana Enterprise API need required permissions if fine-grained access control is enabled
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### get\_all\_datasources
+
+```python
+def get_all_datasources() -> list
+```
+
+The method includes a functionality to get all datasources
+
+Required Permissions:
+Action: datasources:read
+Scope: datasources:*
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns the list of all datasources
+
+
+
+#### get\_datasource\_by\_id
+
+```python
+def get_datasource_by_id(datasource_id: int) -> dict
+```
+
+The method includes a functionality to get the datasource specified by the datasource id
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+
+ Required Permissions:
+- `Action` - datasources:read
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns a datasource
+
+
+
+#### get\_datasource\_by\_uid
+
+```python
+def get_datasource_by_uid(uid: str) -> dict
+```
+
+The method includes a functionality to get the datasource specified by the datasource uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the datasource
+
+ Required Permissions:
+- `Action` - datasources:read
+- `Scope` - [datasources:*, datasources:uid:*, datasources:uid:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns a datasource
+
+
+
+#### get\_datasource\_by\_name
+
+```python
+def get_datasource_by_name(name: str) -> dict
+```
+
+The method includes a functionality to get the datasource specified by the datasource name
+
+**Arguments**:
+
+- `name` _str_ - Specify the name of the datasource
+
+ Required Permissions:
+- `Action` - datasources:read
+- `Scope` - [datasources:*, datasources:name:*, datasources:name:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns a datasource
+
+
+
+#### get\_datasource\_id\_by\_name
+
+```python
+def get_datasource_id_by_name(name: str) -> int
+```
+
+The method includes a functionality to get the datasource id specified by the datasource name
+
+**Arguments**:
+
+- `name` _str_ - Specify the name of the datasource
+
+ Required Permissions:
+- `Action` - datasources:read
+- `Scope` - [datasources:*, datasources:name:*, datasources:name:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _int_ - Returns a datasource id
+
+
+
+#### create\_datasource
+
+```python
+def create_datasource(data_source: dict)
+```
+
+The method includes a functionality to create a datasource specified by the datasource as dict
+
+**Arguments**:
+
+- `data_source` _dict_ - Specify the datasource as dict
+
+ Required Permissions:
+- `Action` - datasources:create
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### update\_datasource
+
+```python
+def update_datasource(datasource_id: int, data_source: dict)
+```
+
+The method includes a functionality to update a datasource specified by the datasource as dict and the datasource id
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+- `data_source` _dict_ - Specify the datasource as dict
+
+ Required Permissions:
+- `Action` - datasources:write
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_datasource\_by\_id
+
+```python
+def delete_datasource_by_id(datasource_id: int)
+```
+
+The method includes a functionality to delete a datasource specified by the datasource id
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+
+ Required Permissions:
+- `Action` - datasources:delete
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_datasource\_by\_uid
+
+```python
+def delete_datasource_by_uid(uid: str)
+```
+
+The method includes a functionality to delete a datasource specified by the datasource uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the datasource
+
+ Required Permissions:
+- `Action` - datasources:delete
+- `Scope` - [datasources:*, datasources:uid:*, datasources:uid:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_datasource\_by\_name
+
+```python
+def delete_datasource_by_name(name: str)
+```
+
+The method includes a functionality to delete a datasource specified by the datasource name
+
+**Arguments**:
+
+- `name` _str_ - Specify the name of the datasource
+
+ Required Permissions:
+- `Action` - datasources:delete
+- `Scope` - [datasources:*, datasources:name:*, datasources:name:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### query\_datasource\_by\_id
+
+```python
+def query_datasource_by_id(time: str, to: str,
+ datasource_queries: list) -> dict
+```
+
+The method includes a functionality to execute a queries inside the datasource itself specified by the datasource id
+
+**Arguments**:
+
+- `from` _str_ - Specify the name of the absolute in epoch timestamps in milliseconds or relative using Grafana time units. For example, now-1h
+- `to` _str_ - Specify the name of the absolute in epoch timestamps in milliseconds or relative using Grafana time units. For example, now-1h
+- `datasource_queries` _list_ - Specify a list of execution queries based on the DatasourceQuery class
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the result of the specified query
+
+
+
+#### enable\_datasource\_permissions
+
+```python
+def enable_datasource_permissions(datasource_id: int)
+```
+
+The method includes a functionality to enable datasource permissions specified by the datasource id. The functionality is a Grafana ENTERPRISE feature
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+
+ Required Permissions:
+- `Action` - datasources.permissions:write
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### disable\_datasource\_permissions
+
+```python
+def disable_datasource_permissions(datasource_id: int)
+```
+
+The method includes a functionality to disable datasource permissions specified by the datasource id. The functionality is a Grafana ENTERPRISE feature
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+
+ Required Permissions:
+- `Action` - datasources.permissions:write
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_datasource\_permissions
+
+```python
+def get_datasource_permissions(datasource_id: int) -> dict
+```
+
+The method includes a functionality to get the datasource permissions specified by the datasource id. The functionality is a Grafana ENTERPRISE feature
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+
+ Required Permissions:
+- `Action` - datasources.permissions:read
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns the datasource permissions
+
+
+
+#### add\_datasource\_permissions
+
+```python
+def add_datasource_permissions(datasource_id: int,
+ datasource_permission: dict)
+```
+
+The method includes a functionality to add datasource permission specified by the datasource id and the datasource permission dict. The functionality is a Grafana ENTERPRISE feature
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+- `datasource_permission` _dict_ - Specify the permission of the datasource
+
+ Required Permissions:
+- `Action` - datasources.permissions:write
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### delete\_datasource\_permissions
+
+```python
+def delete_datasource_permissions(datasource_id: int, permission_id: int)
+```
+
+The method includes a functionality to delete datasource permission specified by the datasource id and the permission id. The functionality is a Grafana ENTERPRISE feature
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the datasource
+- `permission_id` _id_ - Specify the permission id
+
+ Required Permissions:
+- `Action` - datasources.permissions:write
+- `Scope` - [datasources:*, datasources:id:*, datasources:id:]
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
diff --git a/docs/content/grafana_api/folder.md b/docs/content/grafana_api/folder.md
new file mode 100644
index 0000000..dc78603
--- /dev/null
+++ b/docs/content/grafana_api/folder.md
@@ -0,0 +1,279 @@
+# Table of Contents
+
+* [grafana\_api.folder](#grafana_api.folder)
+ * [Folder](#grafana_api.folder.Folder)
+ * [get\_folders](#grafana_api.folder.Folder.get_folders)
+ * [get\_folder\_by\_uid](#grafana_api.folder.Folder.get_folder_by_uid)
+ * [get\_folder\_by\_id](#grafana_api.folder.Folder.get_folder_by_id)
+ * [create\_folder](#grafana_api.folder.Folder.create_folder)
+ * [update\_folder](#grafana_api.folder.Folder.update_folder)
+ * [delete\_folder](#grafana_api.folder.Folder.delete_folder)
+ * [get\_folder\_permissions](#grafana_api.folder.Folder.get_folder_permissions)
+ * [update\_folder\_permissions](#grafana_api.folder.Folder.update_folder_permissions)
+ * [get\_folder\_id\_by\_dashboard\_path](#grafana_api.folder.Folder.get_folder_id_by_dashboard_path)
+ * [get\_all\_folder\_ids\_and\_names](#grafana_api.folder.Folder.get_all_folder_ids_and_names)
+
+
+
+# grafana\_api.folder
+
+
+
+## Folder Objects
+
+```python
+class Folder()
+```
+
+The class includes all necessary methods to access the Grafana folder API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### get\_folders
+
+```python
+def get_folders() -> list
+```
+
+The method includes a functionality to extract all folders inside the organization
+
+**Raises**:
+
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns all folders
+
+
+
+#### get\_folder\_by\_uid
+
+```python
+def get_folder_by_uid(uid: str) -> dict
+```
+
+The method includes a functionality to extract all folder information specified by the uid of the folder
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the folder
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns a folder
+
+
+
+#### get\_folder\_by\_id
+
+```python
+def get_folder_by_id(id: int) -> dict
+```
+
+The method includes a functionality to extract all folder information specified by the id of the folder
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the folder
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns a folder
+
+
+
+#### create\_folder
+
+```python
+def create_folder(title: str, uid: str = None) -> dict
+```
+
+The method includes a functionality to create a new folder inside the organization specified by the defined title and the optional uid
+
+**Arguments**:
+
+- `title` _str_ - Specify the title of the folder
+- `uid` _str_ - Specify the uid of the folder (default None)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns a newly created folder
+
+
+
+#### update\_folder
+
+```python
+def update_folder(title: str,
+ uid: str = None,
+ version: int = 0,
+ overwrite: bool = False) -> dict
+```
+
+The method includes a functionality to update a folder information inside the organization specified by the uid, the title, the version of the folder or if folder information be overwritten
+
+**Arguments**:
+
+- `title` _str_ - Specify the title of the folder
+- `uid` _str_ - Specify the uid of the folder
+- `version` _int_ - Specify the version of the folder (default 0)
+- `overwrite` _bool_ - Should the already existing folder information be overwritten (default False)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns an updated folder
+
+
+
+#### delete\_folder
+
+```python
+def delete_folder(uid: str)
+```
+
+The method includes a functionality to delete a folder inside the organization specified by the defined uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the folder
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_folder\_permissions
+
+```python
+def get_folder_permissions(uid: str) -> list
+```
+
+The method includes a functionality to extract the folder permissions inside the organization specified by the defined uid
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the folder
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns a list of folder permissions
+
+
+
+#### update\_folder\_permissions
+
+```python
+def update_folder_permissions(uid: str, permission_json: dict)
+```
+
+The method includes a functionality to update the folder permissions based on the specified uid and the permission json document
+
+**Arguments**:
+
+- `uid` _str_ - Specify the uid of the folder
+- `permission_json` _dict_ - Specify the inserted permissions as dict
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
+
+
+#### get\_folder\_id\_by\_dashboard\_path
+
+```python
+def get_folder_id_by_dashboard_path(dashboard_path: str) -> int
+```
+
+The method includes a functionality to extract the folder id specified inside model dashboard path
+
+**Arguments**:
+
+- `dashboard_path` _str_ - Specify the dashboard path
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `folder_id` _int_ - Returns the folder id
+
+
+
+#### get\_all\_folder\_ids\_and\_names
+
+```python
+def get_all_folder_ids_and_names() -> list
+```
+
+The method extract all folder id and names inside the complete organisation
+
+**Returns**:
+
+- `folders` _list_ - Returns a list of dicts with folder ids and the corresponding names
+
diff --git a/docs/content/grafana_api/legacy-alerting.md b/docs/content/grafana_api/legacy-alerting.md
new file mode 100644
index 0000000..103b22d
--- /dev/null
+++ b/docs/content/grafana_api/legacy-alerting.md
@@ -0,0 +1,133 @@
+# Table of Contents
+
+* [grafana\_api.legacy\_alerting](#grafana_api.legacy_alerting)
+ * [Alerting](#grafana_api.legacy_alerting.Alerting)
+ * [get\_alerts](#grafana_api.legacy_alerting.Alerting.get_alerts)
+ * [get\_alerts\_by\_dashboard\_ids](#grafana_api.legacy_alerting.Alerting.get_alerts_by_dashboard_ids)
+ * [get\_alert\_by\_id](#grafana_api.legacy_alerting.Alerting.get_alert_by_id)
+ * [pause\_alert\_by\_id](#grafana_api.legacy_alerting.Alerting.pause_alert_by_id)
+
+
+
+# grafana\_api.legacy\_alerting
+
+
+
+## Alerting Objects
+
+```python
+class Alerting()
+```
+
+The class includes all necessary methods to access the Grafana legacy alerting API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### get\_alerts
+
+```python
+def get_alerts(custom_querystring: str = None) -> list
+```
+
+The method includes a functionality to get the legacy alerts
+
+**Arguments**:
+
+- `custom_querystring` _str_ - Specify the custom querystring (default None)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns a list of all alerts
+
+
+
+#### get\_alerts\_by\_dashboard\_ids
+
+```python
+def get_alerts_by_dashboard_ids(dashboard_ids: list) -> list
+```
+
+The method includes a functionality to get legacy alerts specified by the dashboard ids
+
+**Arguments**:
+
+- `dashboard_ids` _list_ - Specify the list of dashboard ids
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns a list of alerts
+
+
+
+#### get\_alert\_by\_id
+
+```python
+def get_alert_by_id(id: int) -> dict
+```
+
+The method includes a functionality to get the legacy alert specified by the alert id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the legacy alert
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _dict_ - Returns an alert
+
+
+
+#### pause\_alert\_by\_id
+
+```python
+def pause_alert_by_id(id: int, paused: bool = True)
+```
+
+The method includes a functionality to pause/ unpause a legacy alert specified by the alert id
+
+**Arguments**:
+
+- `id` _int_ - Specify the id of the legacy alert
+- `paused` _bool_ - Specify the pause/ unpause parameter (default True)
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+ None
+
diff --git a/docs/content/grafana_api/model.md b/docs/content/grafana_api/model.md
new file mode 100644
index 0000000..3b81c75
--- /dev/null
+++ b/docs/content/grafana_api/model.md
@@ -0,0 +1,189 @@
+# Table of Contents
+
+* [grafana\_api.model](#grafana_api.model)
+ * [APIEndpoints](#grafana_api.model.APIEndpoints)
+ * [RequestsMethods](#grafana_api.model.RequestsMethods)
+ * [APIModel](#grafana_api.model.APIModel)
+ * [DatasourceQuery](#grafana_api.model.DatasourceQuery)
+ * [DatasourceRuleQuery](#grafana_api.model.DatasourceRuleQuery)
+ * [Alert](#grafana_api.model.Alert)
+ * [Silence](#grafana_api.model.Silence)
+ * [AlertmanagerConfig](#grafana_api.model.AlertmanagerConfig)
+ * [AlertmanagerReceivers](#grafana_api.model.AlertmanagerReceivers)
+ * [RulerRule](#grafana_api.model.RulerRule)
+
+
+
+# grafana\_api.model
+
+
+
+## APIEndpoints Objects
+
+```python
+class APIEndpoints(Enum)
+```
+
+The class includes all necessary API endpoint strings to connect the Grafana API
+
+
+
+## RequestsMethods Objects
+
+```python
+class RequestsMethods(Enum)
+```
+
+The class includes all necessary methods to establish an HTTP/ HTTPS connection to the Grafana API endpoints
+
+
+
+## APIModel Objects
+
+```python
+class APIModel(NamedTuple)
+```
+
+The class includes all necessary variables to establish a connection to the Grafana API endpoints
+
+**Arguments**:
+
+- `host` _str_ - Specify the host of the Grafana system
+- `token` _str_ - Specify the access token of the Grafana system
+
+
+
+## DatasourceQuery Objects
+
+```python
+class DatasourceQuery(NamedTuple)
+```
+
+The class includes all necessary variables to specify a query for the datasource search endpoint
+
+**Arguments**:
+
+- `datasource_id` _int_ - Specify the id of the data source
+- `raw_sql` _str_ - Specify the raw SQL string to search inside the Grafana system
+- `ref_id` _str_ - Specify a reference id of the search command (default A)
+- `interval_ms` _int_ - Specify the time interval in milliseconds of output format (default 1000)
+- `max_data_points` _int_ - Specify maximum amount of data points that dashboard panel can render (default 100)
+- `output_format` _str_ - Specify the output format of the query (default time_series)
+
+
+
+## DatasourceRuleQuery Objects
+
+```python
+class DatasourceRuleQuery(NamedTuple)
+```
+
+The class includes all necessary variables to specify a query for the datasource rule search endpoint
+
+**Arguments**:
+
+- `datasource_uid` _str_ - Specify the uid of the data source
+- `model` _dict_ - Specify the model of the search command
+- `query_type` _str_ - Specify the query time of the search command
+- `ref_id` _str_ - Specify a reference id of the search command
+- `relative_time_range` _dict_ - Specify the related time range of the search command
+
+
+
+## Alert Objects
+
+```python
+class Alert(NamedTuple)
+```
+
+The class includes all necessary variables to generate an alert object that is necessary to communicate with the Grafana alert endpoint
+
+**Arguments**:
+
+- `starts_at` _str_ - Specify the start date of the alert
+- `ends_at` _str_ - Specify end date of the alert
+- `annotations` _dict_ - Specify the annotations of the alert
+- `generator_url` _str_ - Specify the url of the generator endpoint
+- `labels` _dict_ - Specify labels of the alert
+
+
+
+## Silence Objects
+
+```python
+class Silence(NamedTuple)
+```
+
+The class includes all necessary variables to generate a silence object that is necessary to communicate with the Grafana silence endpoint
+
+**Arguments**:
+
+- `starts_at` _str_ - Specify the start date of the silence
+- `created_by` _str_ - Specify the name of the silence creator
+- `ends_at` _str_ - Specify end date of the silence
+- `comment` _str_ - Specify a custom comment for the silence
+- `id` _str_ - Specify an id for the silence
+- `matchers` _dict_ - Specify matchers for the silence
+
+
+
+## AlertmanagerConfig Objects
+
+```python
+class AlertmanagerConfig(NamedTuple)
+```
+
+The class includes all necessary variables to generate an Alertmanager config object that is necessary to communicate and set up the Grafana Alertmanager endpoint
+
+**Arguments**:
+
+- `global_config` _dict_ - Specify the global config of the Alertmanager
+- `inhibit_rules` _list_ - Specify the inhibit rules of the Alertmanager
+- `mute_time_intervals` _list_ - Specify the mute time intervals of the Alertmanager
+- `receivers` _list_ - Specify the receivers of the Alertmanager
+- `route` _dict_ - Specify the route of the Alertmanager
+- `templates` _list_ - Specify an Alertmanager template
+
+
+
+## AlertmanagerReceivers Objects
+
+```python
+class AlertmanagerReceivers(NamedTuple)
+```
+
+The class includes all necessary variables to generate an Alertmanager receivers object that is necessary to communicate and set up the Grafana Alertmanager receivers endpoint
+
+**Arguments**:
+
+- `name` _str_ - Specify the name of the receiver
+- `email_configs` _list_ - Specify the email configuration of the receiver's
+- `grafana_managed_receiver_configs` _list_ - Specify the Grafana managed receiver configuration of the receiver's
+- `opsgenie_configs` _list_ - Specify the ops genie configuration of the receiver's
+- `pagerduty_configs` _dict_ - Specify the pager duty configuration of the receiver's
+- `pushover_configs` _list_ - Specify the push over configuration of the receiver's
+- `slack_configs` _list_ - Specify the Slack configuration of the receiver's
+- `victorops_configs` _list_ - Specify the victor ops configuration of the receiver's
+- `webhook_configs` _list_ - Specify the webhook configuration of the receiver's
+- `wechat_configs` _list_ - Specify the wechaty configuration of the receiver's
+
+
+
+## RulerRule Objects
+
+```python
+class RulerRule(NamedTuple)
+```
+
+The class includes all necessary variables to generate a Ruler rule object that is necessary to communicate and set up a Grafana Ruler rule
+
+**Arguments**:
+
+- `alert` _str_ - Specify the name of the rule
+- `annotations` _dict_ - Specify the annotations of the rule
+- `expr` _str_ - Specify the expression of the rule
+- `grafana_alert` _dict_ - Specify the Grafana alert of the rule
+- `labels` _dict_ - Specify labels of the rule
+- `record` _str_ - Specify recode value of the rule
+- `for_id` _int_ - Specify the id of the rule if you update an existing rule (default 0)
+
diff --git a/docs/content/grafana_api/search.md b/docs/content/grafana_api/search.md
new file mode 100644
index 0000000..97ec771
--- /dev/null
+++ b/docs/content/grafana_api/search.md
@@ -0,0 +1,54 @@
+# Table of Contents
+
+* [grafana\_api.search](#grafana_api.search)
+ * [Search](#grafana_api.search.Search)
+ * [search](#grafana_api.search.Search.search)
+
+
+
+# grafana\_api.search
+
+
+
+## Search Objects
+
+```python
+class Search()
+```
+
+The class includes all necessary methods to access the Grafana search API endpoints
+
+**Arguments**:
+
+- `grafana_api_model` _APIModel_ - Inject a Grafana API model object that includes all necessary values and information
+
+
+**Attributes**:
+
+- `grafana_api_model` _APIModel_ - This is where we store the grafana_api_model
+
+
+
+#### search
+
+```python
+def search(search_query: str) -> list
+```
+
+The method includes a functionality to execute a custom query
+
+**Arguments**:
+
+- `search_query` _str_ - Specify the inserted query as string
+
+
+**Raises**:
+
+- `ValueError` - Missed specifying a necessary value
+- `Exception` - Unspecified error by executing the API call
+
+
+**Returns**:
+
+- `api_call` _list_ - Returns the list of query the results
+
diff --git a/docs/content/index.md b/docs/content/index.md
new file mode 100644
index 0000000..648f7e0
--- /dev/null
+++ b/docs/content/index.md
@@ -0,0 +1,56 @@
+# Grafana API SDK
+The repository includes an SDK for the Grafana API. It's possible to communicate with the Grafana API endpoints. Another feature of the SDK is the possibility to specify the used folder for the dashboard.
+
+## Supported Features
+
+The following list describes the currently supported features of the Grafana API functionality.
+
+- [ ] [Admin HTTP API](https://grafana.com/docs/grafana/latest/http_api/admin/)
+- [x] [Legacy Alerting HTTP API](https://grafana.com/docs/grafana/latest/http_api/alerting/)
+- [x] [Alerting HTTP API](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/pkg/services/ngalert/api/tooling/post.json)
+- [x] [Alerting Notification Channels HTTP API](https://grafana.com/docs/grafana/latest/http_api/alerting_notification_channels/)
+- [ ] [Annotations HTTP API](https://grafana.com/docs/grafana/latest/http_api/annotations/)
+- [ ] [Authentication HTTP API](https://grafana.com/docs/grafana/latest/http_api/auth/)
+- [x] [Data source HTTP API](https://grafana.com/docs/grafana/latest/http_api/data_source/)
+- [x] [Datasource Permissions HTTP API](https://grafana.com/docs/grafana/latest/http_api/datasource_permissions/)
+- [x] [Folder HTTP API](https://grafana.com/docs/grafana/v7.5/http_api/folder/)
+- [x] [Folder Permissions HTTP API](https://grafana.com/docs/grafana/v7.5/http_api/folder_permissions/)
+- [x] [Search HTTP API](https://grafana.com/docs/grafana/v7.5/http_api/folder_dashboard_search/)
+- [ ] [External Group Sync HTTP API](https://grafana.com/docs/grafana/latest/http_api/external_group_sync/)
+- [ ] [Fine-grained access control HTTP API](https://grafana.com/docs/grafana/latest/http_api/access_control/)
+- [ ] [HTTP Preferences API](https://grafana.com/docs/grafana/latest/http_api/preferences/)
+- [ ] [HTTP Snapshot API](https://grafana.com/docs/grafana/latest/http_api/snapshot/)
+- [ ] [Library Element HTTP API](https://grafana.com/docs/grafana/latest/http_api/library_element/)
+- [ ] [Licensing HTTP API](https://grafana.com/docs/grafana/latest/http_api/licensing/)
+- [ ] [Organization HTTP API](https://grafana.com/docs/grafana/latest/http_api/org/)
+- [ ] [Other HTTP API](https://grafana.com/docs/grafana/latest/http_api/other/)
+- [ ] [Playlist HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/)
+- [ ] [Reporting API](https://grafana.com/docs/grafana/latest/http_api/reporting/)
+- [ ] [Short URL HTTP API](https://grafana.com/docs/grafana/latest/http_api/short_url/)
+- [ ] [Team HTTP API](https://grafana.com/docs/grafana/latest/http_api/team/)
+- [ ] [User HTTP API](https://grafana.com/docs/grafana/latest/http_api/user/)
+
+## Installation
+
+`pip install grafana-api-sdk`
+
+## Example
+
+```python
+import json
+
+from grafana_api.model import APIModel
+from grafana_api.dashboard import Dashboard
+
+model: APIModel = APIModel(host="test", token="test")
+
+dashboard: Dashboard = Dashboard(model)
+
+with open("/tmp/test/test.json") as file:
+ json_dashboard = json.load(file)
+
+dashboard.create_or_update_dashboard(message="Create a new test dashboard", dashboard_json=json_dashboard, dashboard_path="test")
+```
+
+## Templating
+If you want to template your JSON document based on a predefined folder structure you can check out one of my other [project](https://github.com/ZPascal/grafana_dashboard_templater) and integrate the functionality inside your code.
\ No newline at end of file
diff --git a/docs/coverage.svg b/docs/coverage.svg
index e5db27c..6bfc8fa 100644
--- a/docs/coverage.svg
+++ b/docs/coverage.svg
@@ -15,7 +15,7 @@
coverage
coverage
- 100%
- 100%
+ 99%
+ 99%
diff --git a/docs/grafana_api_sdk.md b/docs/grafana_api_sdk.md
new file mode 100644
index 0000000..648f7e0
--- /dev/null
+++ b/docs/grafana_api_sdk.md
@@ -0,0 +1,56 @@
+# Grafana API SDK
+The repository includes an SDK for the Grafana API. It's possible to communicate with the Grafana API endpoints. Another feature of the SDK is the possibility to specify the used folder for the dashboard.
+
+## Supported Features
+
+The following list describes the currently supported features of the Grafana API functionality.
+
+- [ ] [Admin HTTP API](https://grafana.com/docs/grafana/latest/http_api/admin/)
+- [x] [Legacy Alerting HTTP API](https://grafana.com/docs/grafana/latest/http_api/alerting/)
+- [x] [Alerting HTTP API](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/pkg/services/ngalert/api/tooling/post.json)
+- [x] [Alerting Notification Channels HTTP API](https://grafana.com/docs/grafana/latest/http_api/alerting_notification_channels/)
+- [ ] [Annotations HTTP API](https://grafana.com/docs/grafana/latest/http_api/annotations/)
+- [ ] [Authentication HTTP API](https://grafana.com/docs/grafana/latest/http_api/auth/)
+- [x] [Data source HTTP API](https://grafana.com/docs/grafana/latest/http_api/data_source/)
+- [x] [Datasource Permissions HTTP API](https://grafana.com/docs/grafana/latest/http_api/datasource_permissions/)
+- [x] [Folder HTTP API](https://grafana.com/docs/grafana/v7.5/http_api/folder/)
+- [x] [Folder Permissions HTTP API](https://grafana.com/docs/grafana/v7.5/http_api/folder_permissions/)
+- [x] [Search HTTP API](https://grafana.com/docs/grafana/v7.5/http_api/folder_dashboard_search/)
+- [ ] [External Group Sync HTTP API](https://grafana.com/docs/grafana/latest/http_api/external_group_sync/)
+- [ ] [Fine-grained access control HTTP API](https://grafana.com/docs/grafana/latest/http_api/access_control/)
+- [ ] [HTTP Preferences API](https://grafana.com/docs/grafana/latest/http_api/preferences/)
+- [ ] [HTTP Snapshot API](https://grafana.com/docs/grafana/latest/http_api/snapshot/)
+- [ ] [Library Element HTTP API](https://grafana.com/docs/grafana/latest/http_api/library_element/)
+- [ ] [Licensing HTTP API](https://grafana.com/docs/grafana/latest/http_api/licensing/)
+- [ ] [Organization HTTP API](https://grafana.com/docs/grafana/latest/http_api/org/)
+- [ ] [Other HTTP API](https://grafana.com/docs/grafana/latest/http_api/other/)
+- [ ] [Playlist HTTP API](https://grafana.com/docs/grafana/latest/http_api/playlist/)
+- [ ] [Reporting API](https://grafana.com/docs/grafana/latest/http_api/reporting/)
+- [ ] [Short URL HTTP API](https://grafana.com/docs/grafana/latest/http_api/short_url/)
+- [ ] [Team HTTP API](https://grafana.com/docs/grafana/latest/http_api/team/)
+- [ ] [User HTTP API](https://grafana.com/docs/grafana/latest/http_api/user/)
+
+## Installation
+
+`pip install grafana-api-sdk`
+
+## Example
+
+```python
+import json
+
+from grafana_api.model import APIModel
+from grafana_api.dashboard import Dashboard
+
+model: APIModel = APIModel(host="test", token="test")
+
+dashboard: Dashboard = Dashboard(model)
+
+with open("/tmp/test/test.json") as file:
+ json_dashboard = json.load(file)
+
+dashboard.create_or_update_dashboard(message="Create a new test dashboard", dashboard_json=json_dashboard, dashboard_path="test")
+```
+
+## Templating
+If you want to template your JSON document based on a predefined folder structure you can check out one of my other [project](https://github.com/ZPascal/grafana_dashboard_templater) and integrate the functionality inside your code.
\ No newline at end of file
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
new file mode 100644
index 0000000..edd9b0d
--- /dev/null
+++ b/docs/mkdocs.yml
@@ -0,0 +1,18 @@
+docs_dir: content
+markdown_extensions:
+- pymdownx.tasklist
+nav:
+- Home: index.md
+- API SDK:
+ - Model: grafana_api/model.md
+ - Api: grafana_api/api.md
+ - Alerting: grafana_api/alerting.md
+ - Legacy Alerting: grafana_api/legacy-alerting.md
+ - Alerting Notifications: grafana_api/alerting-notifications.md
+ - Datasource: grafana_api/datasource.md
+ - Dashboard: grafana_api/dashboard.md
+ - Folder: grafana_api/folder.md
+ - Search: grafana_api/search.md
+repo_url: https://github.com/ZPascal/grafana_api_sdk
+site_name: Grafana API SDK
+theme: material
diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml
new file mode 100644
index 0000000..26d5219
--- /dev/null
+++ b/pydoc-markdown.yml
@@ -0,0 +1,39 @@
+loaders:
+ - type: python
+processors:
+ - type: filter
+ - type: smart
+ - type: crossref
+renderer:
+ type: mkdocs
+ pages:
+ - title: Home
+ name: index
+ source: docs/grafana_api_sdk.md
+ - title: API SDK
+ name: grafana_api
+ children:
+ - title: Model
+ contents: [ grafana_api.model.* ]
+ - title: Api
+ contents: [ grafana_api.api.* ]
+ - title: Alerting
+ contents: [ grafana_api.alerting.* ]
+ - title: Legacy Alerting
+ contents: [ grafana_api.legacy_alerting.* ]
+ - title: Alerting Notifications
+ contents: [ grafana_api.alerting_notifications.* ]
+ - title: Datasource
+ contents: [ grafana_api.datasource.* ]
+ - title: Dashboard
+ contents: [ grafana_api.dashboard.* ]
+ - title: Folder
+ contents: [ grafana_api.folder.* ]
+ - title: Search
+ contents: [ grafana_api.search.* ]
+ mkdocs_config:
+ site_name: Grafana API SDK
+ theme: material
+ repo_url: https://github.com/ZPascal/grafana_api_sdk
+ markdown_extensions:
+ - pymdownx.tasklist
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 663bd1f..b08fa6b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,4 @@
-requests
\ No newline at end of file
+requests
+pydoc-markdown
+mkdocs
+mkdocs-material
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 5f672a8..4561168 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@
setuptools.setup(
name="grafana-api-sdk",
- version="0.0.1",
+ version="0.0.2",
author="Pascal Zimmermann",
author_email="info@theiotstudio.com",
description="A Grafana API SDK",
diff --git a/src/grafana_api/alerting.py b/src/grafana_api/alerting.py
new file mode 100644
index 0000000..02381ce
--- /dev/null
+++ b/src/grafana_api/alerting.py
@@ -0,0 +1,1172 @@
+import datetime
+import json
+import logging
+
+from .model import (
+ APIModel,
+ APIEndpoints,
+ RequestsMethods,
+ Silence,
+ AlertmanagerConfig,
+)
+from .api import Api
+
+
+class Alerting:
+ """The class includes all necessary methods to access the Grafana alerting API endpoints
+
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
+ """
+
+ def __init__(self, grafana_api_model: APIModel):
+ self.grafana_api_model = grafana_api_model
+
+ def get_alertmanager_alerts(self, recipient: any = "grafana") -> list:
+ """The method includes a functionality to get the Alertmanager alerts specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns the list of Alertmanager alerts
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/alerts",
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("receivers") is None:
+ logging.error(f"Please, check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def create_or_update_alertmanager_alerts(
+ self, alerts: list, recipient: any = "grafana"
+ ):
+ """The method includes a functionality to create or update the Alertmanager alerts specified by the recipient and the alerts list
+
+ Args:
+ alerts (list): Specify a list of the alert objects
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) and alerts != list():
+ alerts_json_list: list = list()
+
+ for alert in alerts:
+ alert_json_dict: dict = dict(
+ {
+ "startsAt": alert.starts_at,
+ "endsAt": alert.ends_at,
+ "generatorURL": alert.generator_url,
+ "labels": alert.labels,
+ "annotations": alert.annotations,
+ }
+ )
+ alerts_json_list.append(alert_json_dict)
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/alerts/groups",
+ RequestsMethods.POST,
+ json.dumps(alerts_json_list),
+ )
+ .json()
+ )
+
+ if api_call != dict():
+ logging.error(f"Please, check the error: {api_call.get('message')}.")
+ raise Exception
+ else:
+ logging.info("You successfully created alerts.")
+ else:
+ logging.error("There is no recipient or alerts defined.")
+ raise ValueError
+
+ def get_alertmanager_group_alerts(self, recipient: any = "grafana") -> list:
+ """The method includes a functionality to get the Alertmanager group alerts specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns the list of Alertmanager group alerts
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/alerts",
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("alerts") is None:
+ logging.error(f"Please, check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def delete_alertmanager_silence_by_id(
+ self, silence_id: str, recipient: any = "grafana"
+ ):
+ """The method includes a functionality to delete the Alertmanager silence specified by the silence id and the recipient
+
+ Args:
+ silence_id (str): Specify the silence id of the alerts
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) and len(silence_id) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/silence/{silence_id}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call != dict():
+ logging.error(f"Please, check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a silence.")
+ else:
+ logging.error("There is no recipient or silence_id defined.")
+ raise ValueError
+
+ def get_alertmanager_silence_by_id(
+ self, silence_id: str, recipient: any = "grafana"
+ ) -> dict:
+ """The method includes a functionality to get the Alertmanager silence specified by the silence id and the recipient
+
+ Args:
+ silence_id (str): Specify the silence id of the alerts
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of Alertmanager silence alert
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) and len(silence_id) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/silence/{silence_id}",
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient or silence_id defined.")
+ raise ValueError
+
+ def get_alertmanager_silences(self, recipient: any = "grafana") -> list:
+ """The method includes a functionality to get all Alertmanager silences specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns the list of Alertmanager silence alerts
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/silences",
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def create_or_update_alertmanager_silence(
+ self, silence: Silence, recipient: any = "grafana"
+ ) -> dict:
+ """The method includes a functionality to create or update the Alertmanager silence specified by the silence object and the recipient
+
+ Args:
+ silence -> Specify the silence object
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of newly created silence alert
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) or silence is not None:
+ silence_json_dict: dict = dict(
+ {
+ "comment": silence.comment,
+ "createdBy": silence.created_by,
+ "endsAt": silence.ends_at,
+ "id": silence.id,
+ "matchers": silence.matchers,
+ "startsAt": silence.starts_at,
+ }
+ )
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/silences",
+ RequestsMethods.POST,
+ json.dumps(silence_json_dict),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient or silence defined.")
+ raise ValueError
+
+ def get_alertmanager_status(self, recipient: str = "grafana") -> dict:
+ """The method includes a functionality to get the Alertmanager status specified by the recipient
+
+ Args:
+ recipient (str): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of the Alertmanager status
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/api/v2/status",
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("config") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def delete_alertmanager_config(self, recipient: any = "grafana"):
+ """The method includes a functionality to delete the Alertmanager config specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/config/api/v1/alerts",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if (
+ api_call.get("message")
+ != "configuration deleted; the default is applied"
+ ):
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a alerting config.")
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def get_alertmanager_config(self, recipient: any = "grafana") -> dict:
+ """The method includes a functionality to get the Alertmanager config specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of the Alertmanager config
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/config/api/v1/alerts",
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("alertmanager_config") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def create_or_update_alertmanager_config(
+ self,
+ alertmanager_config: AlertmanagerConfig,
+ recipient: any = "grafana",
+ template_files: dict = None,
+ ):
+ """The method includes a functionality to create or update the Alertmanager config specified by the Alertmanager config object, recipient and template_files
+
+ Args:
+ alertmanager_config (AlertmanagerConfig): Specify the Alertmanager config object
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+ template_files(dict): Specify the optional template files (default None)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) and alertmanager_config is not None:
+ alertmanager_configuration_json_dict: dict = dict()
+
+ alertmanager_configuration_json_dict["alertmanager_config"] = dict(
+ {
+ "global": alertmanager_config.global_config,
+ "inhibit_rules": alertmanager_config.inhibit_rules,
+ "mute_time_intervals": alertmanager_config.mute_time_intervals,
+ "receivers": alertmanager_config.receivers,
+ "route": alertmanager_config.route,
+ "templates": alertmanager_config.templates,
+ }
+ )
+
+ if template_files is not None:
+ alertmanager_configuration_json_dict["template_files"] = template_files
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/config/api/v1/alerts",
+ RequestsMethods.POST,
+ json.dumps(alertmanager_configuration_json_dict),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("message") != "configuration created":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully created an Alertmanager alert config.")
+ else:
+ logging.error("There is no recipient or alertmanager_config defined.")
+ raise ValueError
+
+ def test_alertmanager_receivers(
+ self, alert: dict, receivers: list, recipient: any = "grafana"
+ ):
+ """The method includes a functionality to test the Alertmanager receivers specified by the alert dict, receivers object and the recipient
+
+ Args:
+ alert (dict): Specify the alert dict
+ receivers (list): Specify the list of AlertmanagerReceivers objects
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ )
+ and alert != dict()
+ and receivers is not None
+ ):
+ alertmanager_receivers_json_dict: dict = dict()
+ receivers_list: list = list()
+
+ alertmanager_receivers_json_dict["alert"] = alert
+
+ for receiver in receivers:
+ receivers_list.append(
+ dict(
+ {
+ "name": receiver.name,
+ "email_configs": receiver.email_configs,
+ "grafana_managed_receiver_configs": receiver.grafana_managed_receiver_configs,
+ "opsgenie_configs": receiver.opsgenie_configs,
+ "pagerduty_configs": receiver.pagerduty_configs,
+ "pushover_configs": receiver.pushover_configs,
+ "slack_configs": receiver.slack_configs,
+ "sns_configs": receiver.sns_configs,
+ "victorops_configs": receiver.victorops_configs,
+ "webhook_configs": receiver.webhook_configs,
+ "wechat_configs": receiver.wechat_configs,
+ }
+ )
+ )
+
+ alertmanager_receivers_json_dict["receivers"] = receivers_list
+
+ api_call: any = Api(self.grafana_api_model).call_the_api(
+ f"{APIEndpoints.ALERTS_ALERTMANAGER.value}/{recipient}/config/api/v1/receivers/test",
+ RequestsMethods.POST,
+ json.dumps(alertmanager_receivers_json_dict),
+ )
+
+ status_code: int = api_call.status_code
+ api_call_dict: dict = api_call.json()
+
+ alert_manager_status_dict: dict = dict(
+ {
+ 200: "You successfully tested Grafana managed receivers.",
+ 207: "You successfully tested Grafana managed receivers (Multi Status).",
+ 400: f"Validation error. Check the error: {api_call_dict.get('message')}.",
+ 403: "Permission denied. Please, check the access rights.",
+ 404: "Alert manager not found. Please, check the alert manager configuration.",
+ 408: f"Failure. Check the error: {api_call_dict.get('message')}.",
+ 409: "Alert manager not ready. Please, check the alert manager configuration.",
+ }
+ )
+
+ if 200 <= status_code <= 207:
+ logging.info(alert_manager_status_dict.get(status_code))
+ elif 400 <= status_code <= 409:
+ logging.error(alert_manager_status_dict.get(status_code))
+ raise Exception
+ else:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.error("There is no recipient, alert or receivers defined.")
+ raise ValueError
+
+ def get_prometheus_alerts(self, recipient: any = "grafana") -> dict:
+ """The method includes a functionality to get all prometheus alerts specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of the prometheus alerts
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_PROMETHEUS.value}/{recipient}/api/v1/alerts",
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("data") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def get_prometheus_rules(self, recipient: any = "grafana") -> dict:
+ """The method includes a functionality to get all prometheus rules specified by the recipient
+
+ Args:
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of the prometheus rules
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_PROMETHEUS.value}/{recipient}/api/v1/rules",
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("data") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def get_ruler_rules(self, recipient: str = "grafana") -> dict:
+ """The method includes a functionality to get all ruler rules specified by the recipient
+
+ Args:
+ recipient (str): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of the ruler rules
+ """
+
+ if (type(recipient) == int and recipient != 0) or (
+ type(recipient) == str and len(recipient) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_RULER.value}/{recipient}/api/v1/rules",
+ )
+ .json()
+ )
+
+ if api_call == dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient defined.")
+ raise ValueError
+
+ def delete_ruler_namespace(self, namespace: str, recipient: any = "grafana"):
+ """The method includes a functionality to delete a ruler namespace specified by the namespace name and the recipient
+
+ Args:
+ namespace (str): Specify the namespace name
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) and len(namespace) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_RULER.value}/{recipient}/api/v1/rules/{namespace}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call != dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a ruler namespace.")
+ else:
+ logging.error("There is no recipient or namespace defined.")
+ raise ValueError
+
+ def get_ruler_groups_by_namespace(
+ self, namespace: str, recipient: any = "grafana"
+ ) -> dict:
+ """The method includes a functionality to get all ruler groups specified by the namespace name and the recipient
+
+ Args:
+ namespace (str): Specify the namespace name
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of the ruler groups
+ """
+
+ if (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ ) and len(namespace) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_RULER.value}/{recipient}/api/v1/rules/{namespace}",
+ )
+ .json()
+ )
+
+ if api_call == dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient or namespace defined.")
+ raise ValueError
+
+ def create_or_update_ruler_group_by_namespace(
+ self,
+ namespace: str,
+ group_name: str,
+ rules: list,
+ recipient: any = "grafana",
+ interval: int = 0,
+ ):
+ """The method includes a functionality to create or update a ruler group specified by the namespace name, a ruler group name, a ruler rule object list, the recipient and an interval
+
+ Args:
+ namespace (str): Specify the namespace name
+ group_name (str): Specify the ruler group name
+ rules (list): Specify the ruler rule object list
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+ interval (int): Specify the interval of the ruler (default 0)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ )
+ and len(namespace) != 0
+ and len(group_name) != 0
+ and rules != list()
+ ):
+ rules_json_list: list = list()
+
+ for rule in rules:
+ rule_json_dict: dict = dict(
+ {
+ "alert": rule.alert,
+ "annotations": rule.annotations,
+ "expr": rule.expr,
+ "for": rule.for_id,
+ "grafana_alert": rule.grafana_alert,
+ "labels": rule.labels,
+ "record": rule.record,
+ }
+ )
+ rules_json_list.append(rule_json_dict)
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_RULER.value}/{recipient}/api/v1/rules/{namespace}",
+ RequestsMethods.POST,
+ json.dumps(
+ {
+ "interval": interval,
+ "name": group_name,
+ "rules": rules_json_list,
+ }
+ ),
+ )
+ .json()
+ )
+
+ if api_call != dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully created an ruler group.")
+ else:
+ logging.error("There is no recipient, namespace, name or rules defined.")
+ raise ValueError
+
+ def delete_ruler_group(
+ self, namespace: str, group_name: str, recipient: any = "grafana"
+ ):
+ """The method includes a functionality to delete a ruler group specified by the namespace name, a ruler group name and the recipient
+
+ Args:
+ namespace (str): Specify the namespace name
+ group_name (str): Specify the ruler group name
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if (
+ (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ )
+ and len(namespace) != 0
+ and len(group_name) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_RULER.value}/{recipient}/api/v1/rules/{namespace}/{group_name}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call != dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a ruler group.")
+ else:
+ logging.error("There is no recipient, namespace or group_name defined.")
+ raise ValueError
+
+ def get_ruler_group(
+ self, namespace: str, group_name: str, recipient: any = "grafana"
+ ) -> dict:
+ """The method includes a functionality to get a ruler group specified by the namespace name, a ruler group name and the recipient
+
+ Args:
+ namespace (str): Specify the namespace name
+ group_name (str): Specify the ruler group name
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dict of all ruler groups
+ """
+
+ if (
+ (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ )
+ and len(namespace) != 0
+ and len(group_name) != 0
+ ):
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_RULER.value}/{recipient}/api/v1/rules/{namespace}/{group_name}",
+ )
+ .json()
+ )
+
+ if api_call == dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no recipient, namespace or group_name defined.")
+ raise ValueError
+
+ def test_rule(self, data_query: list) -> dict:
+ """The method includes a functionality to test a rule specified by a list of datasource rule query objects
+
+ Args:
+ data_query (list): Specify a list of datasource rule query objects
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (str): Returns the result of the specified query
+ """
+
+ if data_query != list():
+ datasource_rule_query_objects_json: list = list()
+ datasource_rule_query_object_json: dict = dict()
+
+ for datasource_rule_query_object in data_query:
+ datasource_rule_query_object_json[
+ "datasourceUid"
+ ] = datasource_rule_query_object.datasource_uid
+ datasource_rule_query_object_json[
+ "model"
+ ] = datasource_rule_query_object.model
+ datasource_rule_query_object_json[
+ "queryType"
+ ] = datasource_rule_query_object.query_type
+ datasource_rule_query_object_json[
+ "refId"
+ ] = datasource_rule_query_object.ref_id
+ datasource_rule_query_object_json[
+ "relativeTimeRange"
+ ] = datasource_rule_query_object.relative_time_range
+ datasource_rule_query_objects_json.append(
+ datasource_rule_query_object_json
+ )
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ "/api/v1/eval",
+ RequestsMethods.POST,
+ json.dumps(
+ {
+ "data": datasource_rule_query_objects_json,
+ "now": str(datetime.datetime.now()),
+ }
+ ),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("message") is not None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no data_query defined.")
+ raise ValueError
+
+ def test_recipient_rule(
+ self, expr: str, condition: str, data_query: list, recipient: any = "grafana"
+ ) -> dict:
+ """The method includes a functionality to test a recipient role specified by the expr, the condition, a list of data queries and the recipient
+
+ Args:
+ expr (str): Specify a list of datasource rule query objects
+ condition (str): Specify the condition
+ data_query (list): Specify a list of datasource rule query objects
+ recipient (any): Specify the recipient datasource id of the alerts (default grafana)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the result of the specified recipient rule
+ """
+
+ if (
+ (
+ (type(recipient) == int and recipient != 0)
+ or (type(recipient) == str and len(recipient) != 0)
+ )
+ and len(expr) != 0
+ and len(condition) != 0
+ and data_query != list()
+ ):
+ datasource_rule_query_objects_json: list = list()
+ datasource_rule_query_object_json: dict = dict()
+
+ for datasource_rule_query_object in data_query:
+ datasource_rule_query_object_json[
+ "datasourceUid"
+ ] = datasource_rule_query_object.datasource_uid
+ datasource_rule_query_object_json[
+ "model"
+ ] = datasource_rule_query_object.model
+ datasource_rule_query_object_json[
+ "queryType"
+ ] = datasource_rule_query_object.query_type
+ datasource_rule_query_object_json[
+ "refId"
+ ] = datasource_rule_query_object.ref_id
+ datasource_rule_query_object_json[
+ "relativeTimeRange"
+ ] = datasource_rule_query_object.relative_time_range
+ datasource_rule_query_objects_json.append(
+ datasource_rule_query_object_json
+ )
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"/api/v1/rule/test/{recipient}",
+ RequestsMethods.POST,
+ json.dumps(
+ {
+ "expr": expr,
+ "grafana_condition": {
+ "condition": condition,
+ "data": datasource_rule_query_objects_json,
+ "now": str(datetime.datetime.now()),
+ },
+ }
+ ),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("message") is not None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error(
+ "There is no recipient, expr, condition or data_query defined."
+ )
+ raise ValueError
+
+ def delete_ngalert_organization_configuration(self):
+ """The method includes a functionality to delete the NGAlert organization admin configuration
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_NGALERT.value}/admin_config",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call != dict() and api_call.get("message") is not None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info(
+ "You successfully deleted the NGAlert organization configuration."
+ )
+
+ def get_ngalert_organization_configuration(self) -> dict:
+ """The method includes a functionality to get the NGAlert organization admin configuration
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the NGAlert organization configuration
+ """
+
+ api_call: any = Api(self.grafana_api_model).call_the_api(
+ f"{APIEndpoints.ALERTS_NGALERT.value}/admin_config",
+ )
+
+ status_code: int = api_call.status_code
+
+ alert_manager_status_dict: dict = dict(
+ {
+ 404: "There's no configuration available.",
+ 500: "Failure, an unexpected error occurred.",
+ }
+ )
+
+ if status_code == 200:
+ return api_call.json()
+ elif 404 <= status_code <= 500:
+ logging.error(alert_manager_status_dict.get(status_code))
+ raise Exception
+ else:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+
+ def create_or_update_ngalert_organization_configuration(
+ self, alert_managers: list, alertmanagers_choice: str = "all"
+ ):
+ """The method includes a functionality to create or update the NGAlert organization admin configuration
+
+ Args:
+ alert_managers (list): Specify the list of alert manager names
+ alertmanagers_choice (str): Specify the Alertmanagers choice (default all)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if alert_managers != list() and len(alertmanagers_choice) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_NGALERT.value}/admin_config",
+ RequestsMethods.POST,
+ json.dumps(
+ {
+ "Alertmanagers": alert_managers,
+ "alertmanagersChoice": alertmanagers_choice,
+ }
+ ),
+ )
+ .json()
+ )
+
+ if api_call != dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info(
+ "You successfully created an NGAlert organization configuration."
+ )
+ else:
+ logging.error(
+ "There is no recipient, expr, condition or data_query defined."
+ )
+ raise ValueError
+
+ def get_ngalert_alertmanagers_by_organization(self) -> dict:
+ """The method includes a functionality to get the discovered and dropped Alertmanagers of the user's organization and based on the specified configuration
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the NGAlert Alertmanagers
+ """
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERTS_NGALERT.value}/Alertmanagers",
+ )
+ .json()
+ )
+
+ if api_call == dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
diff --git a/src/grafana_api/alerting_notifications.py b/src/grafana_api/alerting_notifications.py
new file mode 100644
index 0000000..a312e87
--- /dev/null
+++ b/src/grafana_api/alerting_notifications.py
@@ -0,0 +1,345 @@
+import json
+import logging
+
+from .model import APIModel, APIEndpoints, RequestsMethods
+from .api import Api
+
+
+class AlertingNotifications:
+ """The class includes all necessary methods to access the Grafana alerting notifications API endpoints
+
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
+ """
+
+ def __init__(self, grafana_api_model: APIModel):
+ self.grafana_api_model = grafana_api_model
+
+ def get_all_notification_channels(self) -> list:
+ """The method includes a functionality to get all alerting notification channels
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns all notification channels
+ """
+
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ APIEndpoints.ALERT_NOTIFICATIONS.value,
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+
+ def get_all_notification_channels_lookup(self) -> list:
+ """The method includes a functionality to lookup and get reduced information of all alerting notification channels
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns all notification channels as reduced information
+ """
+
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/lookup",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+
+ def get_notification_channel_by_uid(self, uid: str) -> dict:
+ """The method includes a functionality to get an alerting notification channel specified by the uid
+
+ Args:
+ uid (str): Specify the uid of the notification channel
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the specified notification channel
+ """
+
+ if len(uid) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/uid/{uid}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no uid defined.")
+ raise ValueError
+
+ def get_notification_channel_by_id(self, id: int) -> dict:
+ """The method includes a functionality to get an alerting notification channel specified by the id
+
+ Args:
+ id (int): Specify the id of the notification channel
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the specified notification channel
+ """
+
+ if id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/{id}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no uid defined.")
+ raise ValueError
+
+ def create_notification_channel(self, notification_channel: dict) -> dict:
+ """The method includes a functionality to create an alerting notification channel specified by the notification channel dict
+
+ Args:
+ notification_channel (dict): Specify the channel of the notification
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the newly created notification channel
+ """
+
+ if notification_channel != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ APIEndpoints.ALERT_NOTIFICATIONS.value,
+ RequestsMethods.POST,
+ json.dumps(notification_channel),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no notification_channel defined.")
+ raise ValueError
+
+ def update_notification_channel_by_uid(
+ self, uid: str, notification_channel: dict
+ ) -> dict:
+ """The method includes a functionality to update an alerting notification channel specified by the notification channel dict and the uid
+
+ Args:
+ uid (str): Specify the uid of the notification channel
+ notification_channel (dict): Specify the channel of the notification
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the updated notification channel
+ """
+
+ if len(uid) != 0 and notification_channel != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/uid/{uid}",
+ RequestsMethods.PUT,
+ json.dumps(notification_channel),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no uid or notification_channel defined.")
+ raise ValueError
+
+ def update_notification_channel_by_id(
+ self, id: int, notification_channel: dict
+ ) -> dict:
+ """The method includes a functionality to update an alerting notification channel specified by the notification channel dict and the id
+
+ Args:
+ id (int): Specify the id of the notification channel
+ notification_channel (dict): Specify the channel of the notification
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the updated notification channel
+ """
+
+ if id != 0 and notification_channel != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/{id}",
+ RequestsMethods.PUT,
+ json.dumps(notification_channel),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no id or notification_channel defined.")
+ raise ValueError
+
+ def delete_notification_channel_by_uid(self, uid: str):
+ """The method includes a functionality to delete an alerting notification channel specified by the uid
+
+ Args:
+ uid (uid): Specify the uid of the notification channel
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if len(uid) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/uid/{uid}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Notification deleted":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully destroyed the notification channel.")
+ else:
+ logging.error("There is no uid defined.")
+ raise ValueError
+
+ def delete_notification_channel_by_id(self, id: int):
+ """The method includes a functionality to delete an alerting notification channel specified by the id
+
+ Args:
+ id (int): Specify the id of the notification channel
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/{id}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Notification deleted":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully destroyed the notification channel.")
+ else:
+ logging.error("There is no id defined.")
+ raise ValueError
+
+ def test_notification_channel(self, notification_channel: dict):
+ """The method includes a functionality to test an alerting notification channel specified by the notification_channel
+
+ Args:
+ notification_channel (dict): Specify the channel of the notification
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if notification_channel != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.ALERT_NOTIFICATIONS.value}/test",
+ RequestsMethods.POST,
+ json.dumps(notification_channel),
+ )
+ .json()
+ )
+
+ print(api_call)
+
+ if api_call.get("message") != "Test notification sent":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully tested the notification channel.")
+ else:
+ logging.error("There is no notification_channel defined.")
+ raise ValueError
diff --git a/src/grafana_api/api.py b/src/grafana_api/api.py
new file mode 100644
index 0000000..a948207
--- /dev/null
+++ b/src/grafana_api/api.py
@@ -0,0 +1,99 @@
+import logging
+import requests
+
+from .model import RequestsMethods, ERROR_MESSAGES, APIModel
+
+
+class Api:
+ """The class includes all necessary methods to make API calls to the Grafana API endpoints
+
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
+ """
+
+ def __init__(self, grafana_api_model: APIModel):
+ self.grafana_api_model = grafana_api_model
+
+ def call_the_api(
+ self,
+ api_call: str,
+ method: RequestsMethods = RequestsMethods.GET,
+ json_complete: str = None,
+ ) -> any:
+ """The method execute a defined API call against the Grafana endpoints
+
+ Args:
+ api_call (str): Specify the API call endpoint
+ method (RequestsMethods): Specify the used method (default GET)
+ json_complete (str): Specify the inserted JSON as string
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (any): Returns the value of the api call
+ """
+
+ api_url: str = f"{self.grafana_api_model.host}{api_call}"
+
+ headers: dict = {
+ "Authorization": f"Bearer {self.grafana_api_model.token}",
+ "Content-Type": "application/json",
+ }
+ try:
+ if method.value == RequestsMethods.GET.value:
+ return Api.__check_the_api_call_response(
+ requests.get(api_url, headers=headers)
+ )
+ elif method.value == RequestsMethods.PUT.value:
+ if json_complete is not None:
+ return Api.__check_the_api_call_response(
+ requests.put(api_url, data=json_complete, headers=headers)
+ )
+ else:
+ logging.error("Please define the json_complete.")
+ raise Exception
+ elif method.value == RequestsMethods.POST.value:
+ if json_complete is not None:
+ return Api.__check_the_api_call_response(
+ requests.post(api_url, data=json_complete, headers=headers)
+ )
+ else:
+ logging.error("Please define the json_complete.")
+ raise Exception
+ elif method.value == RequestsMethods.DELETE.value:
+ return Api.__check_the_api_call_response(
+ requests.delete(api_url, headers=headers)
+ )
+ else:
+ logging.error("Please define a valid method.")
+ raise Exception
+ except Exception as e:
+ raise e
+
+ @staticmethod
+ def __check_the_api_call_response(response: any = None) -> any:
+ """The method includes a functionality to check the output of API call method for errors
+
+ Args:
+ response (any): Specify the inserted response
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (any): Returns the value of the api call
+ """
+
+ if type(response.json()) == dict:
+ if (
+ "message" in response.json().keys()
+ and response.json()["message"] in ERROR_MESSAGES
+ ):
+ logging.error(response.json()["message"])
+ raise requests.exceptions.ConnectionError
+
+ return response
diff --git a/src/grafana_api/dashboard.py b/src/grafana_api/dashboard.py
index 2890d15..1661129 100644
--- a/src/grafana_api/dashboard.py
+++ b/src/grafana_api/dashboard.py
@@ -3,14 +3,17 @@
from .model import APIModel, APIEndpoints, RequestsMethods
from .folder import Folder
-from .utils import Utils
+from .api import Api
class Dashboard:
"""The class includes all necessary methods to access the Grafana dashboard API endpoints
- Keyword arguments:
- grafana_api_model -> Inject a Grafana API model object that includes all necessary values and information
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
"""
def __init__(self, grafana_api_model: APIModel):
@@ -25,11 +28,18 @@ def create_or_update_dashboard(
):
"""The method includes a functionality to create the specified dashboard
- Keyword arguments:
- dashboard_path -> Specify the dashboard path in which the dashboard is to be placed
- dashboard_json -> Specify the inserted dashboard as dict
- message -> Specify the message that should be injected as commit message inside the dashboard
- overwrite -> Should the already existing dashboard be overwritten
+ Args:
+ dashboard_path (str): Specify the dashboard path in which the dashboard is to be placed
+ dashboard_json (dict): Specify the inserted dashboard as dict
+ message (str): Specify the message that should be injected as commit message inside the dashboard
+ overwrite (bool): Should the already existing dashboard be overwritten (default False)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
"""
if len(dashboard_path) != 0 and dashboard_json != dict() and len(message) != 0:
@@ -44,10 +54,14 @@ def create_or_update_dashboard(
"overwrite": overwrite,
}
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/db",
- RequestsMethods.POST,
- json.dumps(dashboard_json_complete),
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DASHBOARDS.value}/db",
+ RequestsMethods.POST,
+ json.dumps(dashboard_json_complete),
+ )
+ .json()
)
if api_call.get("status") != "success":
@@ -56,7 +70,7 @@ def create_or_update_dashboard(
else:
logging.info("You successfully deployed the dashboard.")
else:
- logging.info(
+ logging.error(
"There is no dashboard_path or dashboard_json or message defined."
)
raise ValueError
@@ -66,8 +80,16 @@ def delete_dashboard_by_name_and_path(
):
"""The method includes a functionality to delete the specified dashboard inside the model
- dashboard_name -> Specify the dashboard name of the deleted dashboard
- dashboard_path -> Specify the dashboard path of the deleted dashboard
+ Args:
+ dashboard_name (str): Specify the dashboard name of the deleted dashboard
+ dashboard_path (str): Specify the dashboard path in which the dashboard is to be placed
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
"""
if len(dashboard_name) != 0 and len(dashboard_path) != 0:
@@ -76,9 +98,13 @@ def delete_dashboard_by_name_and_path(
)
if len(dashboard_uid) != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/uid/{dashboard_uid.get('uid')}",
- RequestsMethods.DELETE,
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DASHBOARDS.value}/uid/{dashboard_uid.get('uid')}",
+ RequestsMethods.DELETE,
+ )
+ .json()
)
if f"Dashboard {dashboard_name} deleted" != api_call.get("message"):
@@ -87,22 +113,31 @@ def delete_dashboard_by_name_and_path(
else:
logging.info("You successfully destroyed the dashboard.")
else:
- logging.info("Nothing to delete. There is no dashboard available.")
+ logging.error("Nothing to delete. There is no dashboard available.")
raise ValueError
else:
- logging.info("There is no dashboard_name or dashboard_path defined.")
+ logging.error("There is no dashboard_name or dashboard_path defined.")
raise ValueError
def get_dashboard_by_uid(self, uid: str) -> dict:
"""The method includes a functionality to get the dashboard from the specified uid
- Keyword arguments:
- uid -> Specify the uid of the dashboard
+ Args:
+ uid (str): Specify the uid of the dashboard
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dashboard
"""
if len(uid) != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/uid/{uid}"
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.DASHBOARDS.value}/uid/{uid}")
+ .json()
)
if api_call.get("dashboard") is None:
@@ -111,14 +146,23 @@ def get_dashboard_by_uid(self, uid: str) -> dict:
else:
return api_call
else:
- logging.info("There is no dashboard uid defined.")
+ logging.error("There is no dashboard uid defined.")
raise ValueError
def get_dashboard_home(self) -> dict:
- """The method includes a functionality to get the home dashboard"""
+ """The method includes a functionality to get the home dashboard
+
+ Raises:
+ Exception: Unspecified error by executing the API call
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/home"
+ Returns:
+ api_call (dict): Returns the home dashboard
+ """
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.DASHBOARDS.value}/home")
+ .json()
)
if api_call.get("dashboard") is None:
@@ -128,10 +172,19 @@ def get_dashboard_home(self) -> dict:
return api_call
def get_dashboard_tags(self) -> list:
- """The method includes a functionality to get the all tags of all dashboards"""
+ """The method includes a functionality to get the all tags of all dashboards
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns all dashboard tags
+ """
- api_call: list = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/tags"
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.DASHBOARDS.value}/tags")
+ .json()
)
if api_call == list() or api_call[0].get("term") is None:
@@ -145,8 +198,16 @@ def get_dashboard_uid_and_id_by_name_and_folder(
) -> dict:
"""The method includes a functionality to extract the dashboard uid specified inside the model
- dashboard_name -> Specify the dashboard name of the dashboard
- dashboard_path -> Specify the dashboard path of the dashboard
+ Args:
+ dashboard_name (str): Specify the dashboard name of the dashboard
+ dashboard_path (str): Specify the dashboard path of the dashboard
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the dashboard uid and the id
"""
if len(dashboard_name) != 0 and len(dashboard_path) != 0:
@@ -155,27 +216,52 @@ def get_dashboard_uid_and_id_by_name_and_folder(
).get_folder_id_by_dashboard_path(dashboard_path)
search_query: str = f"{APIEndpoints.SEARCH.value}?folderIds={folder_id}&query={dashboard_name}"
- dashboard_meta: list = Utils(self.grafana_api_model).call_the_api(
- search_query
+ dashboard_meta: list = (
+ Api(self.grafana_api_model).call_the_api(search_query).json()
)
- return dict(
- {"uid": dashboard_meta[0]["uid"], "id": dashboard_meta[0]["id"]}
- )
+ for dashboard_meta_object in dashboard_meta:
+ if dashboard_meta_object.get("title") is not None:
+ if dashboard_meta_object.get("title") == dashboard_name:
+ if (
+ dashboard_meta_object.get("uid") is not None
+ and dashboard_meta_object.get("id") is not None
+ ):
+ return dict(
+ {
+ "uid": dashboard_meta_object.get("uid"),
+ "id": dashboard_meta_object.get("id"),
+ }
+ )
+ else:
+ logging.error("There is no uid or id defined.")
+ raise ValueError
+ else:
+ logging.error("There is no title defined.")
+ raise ValueError
else:
- logging.info("There is no dashboard_name or dashboard_path defined.")
+ logging.error("There is no dashboard_name or dashboard_path defined.")
raise ValueError
def get_dashboard_permissions(self, id: int) -> list:
"""The method includes a functionality to extract the dashboard permissions based on the specified id
- Keyword arguments:
- id -> Specify the id of the dashboard
+ Args:
+ id (int): Specify the id of the dashboard
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns the dashboard permissions of a dashboard as list
"""
if id != 0:
- api_call: list = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/id/{id}/permissions"
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.DASHBOARDS.value}/id/{id}/permissions")
+ .json()
)
if api_call == list() or api_call[0].get("role") is None:
@@ -184,23 +270,33 @@ def get_dashboard_permissions(self, id: int) -> list:
else:
return api_call
else:
- logging.info("There is no dashboard uid defined.")
+ logging.error("There is no dashboard uid defined.")
raise ValueError
def update_dashboard_permissions(self, id: int, permission_json: dict):
- """The method includes a functionality to update the dashboard permissions based on the specified id
- and the permission json document
+ """The method includes a functionality to update the dashboard permissions based on the specified id and the permission json document
+
+ Args:
+ id (int): Specify the id of the dashboard
+ permission_json (dict): Specify the inserted permissions as dict
- Keyword arguments:
- id -> Specify the id of the dashboard
- permission_json -> Specify the inserted permissions as dict
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
"""
if id != 0 and len(permission_json) != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/id/{id}/permissions",
- RequestsMethods.POST,
- json.dumps(permission_json),
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DASHBOARDS.value}/id/{id}/permissions",
+ RequestsMethods.POST,
+ json.dumps(permission_json),
+ )
+ .json()
)
if api_call.get("message") != "Dashboard permissions updated":
@@ -209,19 +305,30 @@ def update_dashboard_permissions(self, id: int, permission_json: dict):
else:
logging.info("You successfully modified the dashboard permissions.")
else:
- logging.info("There is no dashboard uid or permission json defined.")
+ logging.error("There is no dashboard uid or permission json defined.")
raise ValueError
def get_dashboard_versions(self, id: int) -> list:
"""The method includes a functionality to extract the versions of a dashboard based on the specified id
- Keyword arguments:
- id -> Specify the id of the dashboard
+ Args:
+ id (int): Specify the id of the dashboard
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns all dashboard versions of a dashboard as list
"""
if id != 0:
- api_call: list = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/id/{id}/versions",
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DASHBOARDS.value}/id/{id}/versions",
+ )
+ .json()
)
if api_call == list() or api_call[0].get("id") is None:
@@ -230,21 +337,31 @@ def get_dashboard_versions(self, id: int) -> list:
else:
return api_call
else:
- logging.info("There is no dashboard uid defined.")
+ logging.error("There is no dashboard uid defined.")
raise ValueError
def get_dashboard_version(self, id: int, version_id: int) -> dict:
- """The method includes a functionality to extract a specified version of a dashboard based on the specified \
- dashboard id and a version_id of the dashboard
+ """The method includes a functionality to extract a specified version of a dashboard based on the specified dashboard id and a version_id of the dashboard
+
+ Args:
+ id (int): Specify the id of the dashboard
+ version_id (int): Specify the version_id of a dashboard
- Keyword arguments:
- id -> Specify the id of the dashboard
- version_id -> Specify the version_id of a dashboard
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns a dashboard version of a dashboard as dict
"""
if id != 0 and version_id != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/id/{id}/versions/{version_id}",
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DASHBOARDS.value}/id/{id}/versions/{version_id}",
+ )
+ .json()
)
if api_call == dict() or api_call.get("id") is None:
@@ -253,23 +370,33 @@ def get_dashboard_version(self, id: int, version_id: int) -> dict:
else:
return api_call
else:
- logging.info("There is no dashboard uid or version_id defined.")
+ logging.error("There is no dashboard uid or version_id defined.")
raise ValueError
def restore_dashboard_version(self, id: int, version: dict):
- """The method includes a functionality to restore a specified version of a dashboard based on the specified \
- dashboard uid and a version as dict of the dashboard
+ """The method includes a functionality to restore a specified version of a dashboard based on the specified dashboard uid and a version as dict of the dashboard
+
+ Args:
+ id (int): Specify the id of the dashboard
+ version (dict): Specify the version_id of a dashboard
- Keyword arguments:
- uid -> Specify the id of the dashboard
- version -> Specify the version_id of a dashboard
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
"""
if id != 0 and version != dict():
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.DASHBOARDS.value}/id/{id}/restore",
- RequestsMethods.POST,
- json.dumps(version),
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DASHBOARDS.value}/id/{id}/restore",
+ RequestsMethods.POST,
+ json.dumps(version),
+ )
+ .json()
)
if (
@@ -281,7 +408,7 @@ def restore_dashboard_version(self, id: int, version: dict):
else:
logging.info("You successfully restored the dashboard.")
else:
- logging.info("There is no dashboard uid or version_id defined.")
+ logging.error("There is no dashboard uid or version_id defined.")
raise ValueError
def calculate_dashboard_diff(
@@ -290,14 +417,19 @@ def calculate_dashboard_diff(
dashboard_id_and_version_new: dict,
diff_type: str = "json",
) -> str:
- """The method includes a functionality to calculate the diff of specified versions of a dashboard based on the \
- specified dashboard uid and the selected version of the base dashboard and the new dashboard and the diff \
- type (basic or json)
-
- Keyword arguments:
- dashboard_id_and_version_base -> Specify the version and id of the base dashboard
- dashboard_id_and_version_new -> Specify the version and id of the new dashboard
- diff_type -> Specify the diff type (basic or json the default is json)
+ """The method includes a functionality to calculate the diff of specified versions of a dashboard based on the specified dashboard uid and the selected version of the base dashboard and the new dashboard and the diff type (basic or json)
+
+ Args:
+ dashboard_id_and_version_base (dict): Specify the version and id of the base dashboard
+ dashboard_id_and_version_new (dict): Specify the version and id of the new dashboard
+ diff_type (str): Specify the diff type (basic or json) (default json)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (str): Returns the difference of the two specified dashboards
"""
possible_diff_types: list = list(["basic", "json"])
@@ -311,9 +443,7 @@ def calculate_dashboard_diff(
diff_object.update(dashboard_id_and_version_new)
diff_object.update({"diffType": diff_type.lower()})
- api_call: any = Utils(
- self.grafana_api_model
- ).call_the_api_non_json_output(
+ api_call: any = Api(self.grafana_api_model).call_the_api(
f"{APIEndpoints.DASHBOARDS.value}/calculate-diff",
RequestsMethods.POST,
json.dumps(diff_object),
@@ -325,12 +455,12 @@ def calculate_dashboard_diff(
else:
return api_call.text
else:
- logging.info(
+ logging.error(
"There is no dashboard_uid_and_version_base or dashboard_uid_and_version_new defined."
)
raise ValueError
else:
- logging.info(
+ logging.error(
f"The diff_type: {diff_type.lower()} is not valid. Please specify a valid value."
)
raise ValueError
diff --git a/src/grafana_api/datasource.py b/src/grafana_api/datasource.py
new file mode 100644
index 0000000..9444c90
--- /dev/null
+++ b/src/grafana_api/datasource.py
@@ -0,0 +1,630 @@
+import json
+import logging
+
+from .model import APIModel, APIEndpoints, RequestsMethods
+from .api import Api
+
+
+class Datasource:
+ """The class includes all necessary methods to access the Grafana datasource API endpoints. It's required that the API token got the corresponding datasource access rights. Please check the used methods docstring for the necessary access rights
+
+ HINT: Note Grafana Enterprise API need required permissions if fine-grained access control is enabled
+
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
+ """
+
+ def __init__(self, grafana_api_model: APIModel):
+ self.grafana_api_model = grafana_api_model
+
+ def get_all_datasources(self) -> list:
+ """The method includes a functionality to get all datasources
+
+ Required Permissions:
+ Action: datasources:read
+ Scope: datasources:*
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns the list of all datasources
+ """
+
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ APIEndpoints.DATASOURCES.value,
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+
+ def get_datasource_by_id(self, datasource_id: int) -> dict:
+ """The method includes a functionality to get the datasource specified by the datasource id
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+
+ Required Permissions:
+ Action: datasources:read
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns a datasource
+ """
+
+ if datasource_id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no datasource_id defined.")
+ raise ValueError
+
+ def get_datasource_by_uid(self, uid: str) -> dict:
+ """The method includes a functionality to get the datasource specified by the datasource uid
+
+ Args:
+ uid (str): Specify the uid of the datasource
+
+ Required Permissions:
+ Action: datasources:read
+ Scope: [datasources:*, datasources:uid:*, datasources:uid:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns a datasource
+ """
+
+ if len(uid) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/uid/{uid}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no uid defined.")
+ raise ValueError
+
+ def get_datasource_by_name(self, name: str) -> dict:
+ """The method includes a functionality to get the datasource specified by the datasource name
+
+ Args:
+ name (str): Specify the name of the datasource
+
+ Required Permissions:
+ Action: datasources:read
+ Scope: [datasources:*, datasources:name:*, datasources:name:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns a datasource
+ """
+
+ if len(name) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/name/{name}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no name defined.")
+ raise ValueError
+
+ def get_datasource_id_by_name(self, name: str) -> int:
+ """The method includes a functionality to get the datasource id specified by the datasource name
+
+ Args:
+ name (str): Specify the name of the datasource
+
+ Required Permissions:
+ Action: datasources:read
+ Scope: [datasources:*, datasources:name:*, datasources:name:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (int): Returns a datasource id
+ """
+
+ if len(name) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/id/{name}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call.get("id")
+ else:
+ logging.error("There is no name defined.")
+ raise ValueError
+
+ def create_datasource(self, data_source: dict):
+ """The method includes a functionality to create a datasource specified by the datasource as dict
+
+ Args:
+ data_source (dict): Specify the datasource as dict
+
+ Required Permissions:
+ Action: datasources:create
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if data_source != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ APIEndpoints.DATASOURCES.value,
+ RequestsMethods.POST,
+ json.dumps(data_source),
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Datasource added":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully created a datasource.")
+ else:
+ logging.error("There is no data_source defined.")
+ raise ValueError
+
+ def update_datasource(self, datasource_id: int, data_source: dict):
+ """The method includes a functionality to update a datasource specified by the datasource as dict and the datasource id
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+ data_source (dict): Specify the datasource as dict
+
+ Required Permissions:
+ Action: datasources:write
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if datasource_id != 0 and data_source != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}",
+ RequestsMethods.PUT,
+ json.dumps(data_source),
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Datasource updated":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully updated a datasource.")
+ else:
+ logging.error("There is no datasource_id or data_source defined.")
+ raise ValueError
+
+ def delete_datasource_by_id(self, datasource_id: int):
+ """The method includes a functionality to delete a datasource specified by the datasource id
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+
+ Required Permissions:
+ Action: datasources:delete
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if datasource_id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Data source deleted":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a datasource.")
+ else:
+ logging.error("There is no datasource_id defined.")
+ raise ValueError
+
+ def delete_datasource_by_uid(self, uid: str):
+ """The method includes a functionality to delete a datasource specified by the datasource uid
+
+ Args:
+ uid (str): Specify the uid of the datasource
+
+ Required Permissions:
+ Action: datasources:delete
+ Scope: [datasources:*, datasources:uid:*, datasources:uid:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if len(uid) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/uid/{uid}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Data source deleted":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a datasource.")
+ else:
+ logging.error("There is no uid defined.")
+ raise ValueError
+
+ def delete_datasource_by_name(self, name: str):
+ """The method includes a functionality to delete a datasource specified by the datasource name
+
+ Args:
+ name (str): Specify the name of the datasource
+
+ Required Permissions:
+ Action: datasources:delete
+ Scope: [datasources:*, datasources:name:*, datasources:name:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if len(name) != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/name/{name}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Data source deleted":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully deleted a datasource.")
+ else:
+ logging.error("There is no name defined.")
+ raise ValueError
+
+ def query_datasource_by_id(
+ self, time: str, to: str, datasource_queries: list
+ ) -> dict:
+ """The method includes a functionality to execute a queries inside the datasource itself specified by the datasource id
+
+ Args:
+ from (str): Specify the name of the absolute in epoch timestamps in milliseconds or relative using Grafana time units. For example, now-1h
+ to (str): Specify the name of the absolute in epoch timestamps in milliseconds or relative using Grafana time units. For example, now-1h
+ datasource_queries (list): Specify a list of execution queries based on the DatasourceQuery class
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the result of the specified query
+ """
+
+ if len(time) != 0 and len(to) != 0 and datasource_queries != list():
+ datasource_queries_json_list: list = list()
+
+ for datasource_query in datasource_queries:
+ datasource_query_json_dict: dict = dict(
+ {
+ "refId": datasource_query.ref_id,
+ "intervalMs": datasource_query.interval_ms,
+ "maxDataPoints": datasource_query.max_data_points,
+ "datasourceId": datasource_query.datasource_id,
+ "rawSql": datasource_query.raw_sql,
+ "format": datasource_query.output_format,
+ }
+ )
+ datasource_queries_json_list.append(datasource_query_json_dict)
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ APIEndpoints.DATASOURCE_QUERY.value,
+ RequestsMethods.POST,
+ json.dumps(datasource_queries_json_list),
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("results") == dict():
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call.get("results")
+ else:
+ logging.error("There is no time, to or datasource_queries defined.")
+ raise ValueError
+
+ def enable_datasource_permissions(self, datasource_id: int):
+ """The method includes a functionality to enable datasource permissions specified by the datasource id. The functionality is a Grafana ENTERPRISE feature
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+
+ Required Permissions:
+ Action: datasources.permissions:write
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if datasource_id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}/enable-permissions",
+ RequestsMethods.POST,
+ json.dumps({}),
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Datasource permissions enabled":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully enabled the datasource permissions.")
+ else:
+ logging.error("There is no datasource_id defined.")
+ raise ValueError
+
+ def disable_datasource_permissions(self, datasource_id: int):
+ """The method includes a functionality to disable datasource permissions specified by the datasource id. The functionality is a Grafana ENTERPRISE feature
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+
+ Required Permissions:
+ Action: datasources.permissions:write
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if datasource_id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}/disable-permissions",
+ RequestsMethods.POST,
+ json.dumps({}),
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Datasource permissions disabled":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully disabled the datasource permissions.")
+ else:
+ logging.error("There is no datasource_id defined.")
+ raise ValueError
+
+ def get_datasource_permissions(self, datasource_id: int) -> dict:
+ """The method includes a functionality to get the datasource permissions specified by the datasource id. The functionality is a Grafana ENTERPRISE feature
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+
+ Required Permissions:
+ Action: datasources.permissions:read
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns the datasource permissions
+ """
+
+ if datasource_id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}/permissions",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("datasourceId") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no datasource_id defined.")
+ raise ValueError
+
+ def add_datasource_permissions(
+ self, datasource_id: int, datasource_permission: dict
+ ):
+ """The method includes a functionality to add datasource permission specified by the datasource id and the datasource permission dict. The functionality is a Grafana ENTERPRISE feature
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+ datasource_permission (dict): Specify the permission of the datasource
+
+ Required Permissions:
+ Action: datasources.permissions:write
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if datasource_id != 0 and datasource_permission != dict():
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}/permissions",
+ RequestsMethods.POST,
+ json.dumps(datasource_permission),
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Datasource permission added":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully added a datasource permission.")
+ else:
+ logging.error("There is no datasource_id or datasource_permission defined.")
+ raise ValueError
+
+ def delete_datasource_permissions(self, datasource_id: int, permission_id: int):
+ """The method includes a functionality to delete datasource permission specified by the datasource id and the permission id. The functionality is a Grafana ENTERPRISE feature
+
+ Args:
+ datasource_id (int): Specify the id of the datasource
+ permission_id (id): Specify the permission id
+
+ Required Permissions:
+ Action: datasources.permissions:write
+ Scope: [datasources:*, datasources:id:*, datasources:id:]
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if datasource_id != 0 and permission_id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.DATASOURCES.value}/{datasource_id}/permissions/{permission_id}",
+ RequestsMethods.DELETE,
+ )
+ .json()
+ )
+
+ if api_call.get("message") != "Datasource permission removed":
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info("You successfully removed a datasource permission.")
+ else:
+ logging.error("There is no datasource_id or permission_id defined.")
+ raise ValueError
diff --git a/src/grafana_api/folder.py b/src/grafana_api/folder.py
index 904a264..deebdf4 100644
--- a/src/grafana_api/folder.py
+++ b/src/grafana_api/folder.py
@@ -1,25 +1,35 @@
import logging
import json
-from .utils import Utils
+from .api import Api
from .model import APIModel, APIEndpoints, RequestsMethods
class Folder:
"""The class includes all necessary methods to access the Grafana folder API endpoints
- Keyword arguments:
- grafana_api_model -> Inject a Grafana API model object that includes all necessary values and information
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
"""
def __init__(self, grafana_api_model: APIModel):
self.grafana_api_model = grafana_api_model
def get_folders(self) -> list:
- """The method includes a functionality to extract all folders inside the organization"""
+ """The method includes a functionality to extract all folders inside the organization
+
+ Raises:
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns all folders
+ """
- api_call: list = Utils(self.grafana_api_model).call_the_api(
- APIEndpoints.FOLDERS.value
+ api_call: list = (
+ Api(self.grafana_api_model).call_the_api(APIEndpoints.FOLDERS.value).json()
)
if api_call == list() or api_call[0].get("id") is None:
@@ -31,13 +41,22 @@ def get_folders(self) -> list:
def get_folder_by_uid(self, uid: str) -> dict:
"""The method includes a functionality to extract all folder information specified by the uid of the folder
- Keyword arguments:
- uid -> Specify the uid of the folder
+ Args:
+ uid (str): Specify the uid of the folder
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns a folder
"""
if len(uid) != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.FOLDERS.value}/{uid}"
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.FOLDERS.value}/{uid}")
+ .json()
)
if api_call == dict() or api_call.get("id") is None:
@@ -46,19 +65,30 @@ def get_folder_by_uid(self, uid: str) -> dict:
else:
return api_call
else:
- logging.info("There is no dashboard uid defined.")
+ logging.error("There is no dashboard uid defined.")
raise ValueError
def get_folder_by_id(self, id: int) -> dict:
"""The method includes a functionality to extract all folder information specified by the id of the folder
- Keyword arguments:
- id -> Specify the id of the folder
+ Args:
+ id (int): Specify the id of the folder
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns a folder
"""
if id != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.FOLDERS.value}/id/{id}",
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.FOLDERS.value}/id/{id}",
+ )
+ .json()
)
if api_call == dict() or api_call.get("id") is None:
@@ -67,16 +97,22 @@ def get_folder_by_id(self, id: int) -> dict:
else:
return api_call
else:
- logging.info("There is no folder id defined.")
+ logging.error("There is no folder id defined.")
raise ValueError
def create_folder(self, title: str, uid: str = None) -> dict:
- """The method includes a functionality to create a new folder inside the organization specified by the \
- defined title and the optional uid
+ """The method includes a functionality to create a new folder inside the organization specified by the defined title and the optional uid
+
+ Args:
+ title (str): Specify the title of the folder
+ uid (str): Specify the uid of the folder (default None)
- Keyword arguments:
- title -> Specify the title of the folder
- uid -> Specify the uid of the folder (the default value is None)
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns a newly created folder
"""
if len(title) != 0:
@@ -86,10 +122,14 @@ def create_folder(self, title: str, uid: str = None) -> dict:
if uid is not None and len(uid) != 0:
folder_information.update({"uid": uid})
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- APIEndpoints.FOLDERS.value,
- RequestsMethods.POST,
- json.dumps(folder_information),
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ APIEndpoints.FOLDERS.value,
+ RequestsMethods.POST,
+ json.dumps(folder_information),
+ )
+ .json()
)
if api_call == dict() or api_call.get("id") is None:
@@ -98,20 +138,26 @@ def create_folder(self, title: str, uid: str = None) -> dict:
else:
return api_call
else:
- logging.info("There is no folder uid or title defined.")
+ logging.error("There is no folder uid or title defined.")
raise ValueError
def update_folder(
self, title: str, uid: str = None, version: int = 0, overwrite: bool = False
) -> dict:
- """The method includes a functionality to update a folder information inside the organization specified \
- by the uid, the title, the version of the folder or if folder information be overwritten
-
- Keyword arguments:
- uid -> Specify the uid of the folder
- title -> Specify the title of the folder
- version -> Specify the version of the folder
- overwrite -> Should the already existing folder information be overwritten
+ """The method includes a functionality to update a folder information inside the organization specified by the uid, the title, the version of the folder or if folder information be overwritten
+
+ Args:
+ title (str): Specify the title of the folder
+ uid (str): Specify the uid of the folder
+ version (int): Specify the version of the folder (default 0)
+ overwrite (bool): Should the already existing folder information be overwritten (default False)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns an updated folder
"""
if overwrite is True:
@@ -128,10 +174,14 @@ def update_folder(
if version is not None:
folder_information.update({"version": version})
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.FOLDERS.value}/{uid}",
- RequestsMethods.PUT,
- json.dumps(folder_information),
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.FOLDERS.value}/{uid}",
+ RequestsMethods.PUT,
+ json.dumps(folder_information),
+ )
+ .json()
)
if api_call == dict() or api_call.get("id") is None:
@@ -140,21 +190,31 @@ def update_folder(
else:
return api_call
else:
- logging.info("There is no folder title or version defined.")
+ logging.error("There is no folder title or version defined.")
raise ValueError
def delete_folder(self, uid: str):
- """The method includes a functionality to delete a folder inside the organization specified by the \
- defined uid
+ """The method includes a functionality to delete a folder inside the organization specified by the defined uid
- Keyword arguments:
- uid -> Specify the uid of the folder
+ Args:
+ uid (str): Specify the uid of the folder
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
"""
if len(uid) != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.FOLDERS.value}/{uid}",
- RequestsMethods.DELETE,
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.FOLDERS.value}/{uid}",
+ RequestsMethods.DELETE,
+ )
+ .json()
)
if "Folder deleted" != api_call.get("message"):
@@ -163,21 +223,31 @@ def delete_folder(self, uid: str):
else:
logging.info("You successfully destroyed the folder.")
else:
- logging.info("There is no folder uid defined.")
+ logging.error("There is no folder uid defined.")
raise ValueError
def get_folder_permissions(self, uid: str) -> list:
- """The method includes a functionality to extract the folder permissions inside the organization specified by \
- the defined uid
+ """The method includes a functionality to extract the folder permissions inside the organization specified by the defined uid
+
+ Args:
+ uid (str): Specify the uid of the folder
- Keyword arguments:
- uid -> Specify the uid of the folder
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns a list of folder permissions
"""
if len(uid) != 0:
- api_call: list = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.FOLDERS.value}/{uid}/permissions",
- RequestsMethods.GET,
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.FOLDERS.value}/{uid}/permissions",
+ RequestsMethods.GET,
+ )
+ .json()
)
if api_call == list() or api_call[0].get("id") is None:
@@ -186,23 +256,33 @@ def get_folder_permissions(self, uid: str) -> list:
else:
return api_call
else:
- logging.info("There is no folder uid defined.")
+ logging.error("There is no folder uid defined.")
raise ValueError
def update_folder_permissions(self, uid: str, permission_json: dict):
- """The method includes a functionality to update the folder permissions based on the specified uid \
- and the permission json document
+ """The method includes a functionality to update the folder permissions based on the specified uid and the permission json document
+
+ Args:
+ uid (str): Specify the uid of the folder
+ permission_json (dict): Specify the inserted permissions as dict
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
- Keyword arguments:
- uid -> Specify the uid of the folder
- permission_json -> Specify the inserted permissions as dict
+ Returns:
+ None
"""
if len(uid) != 0 and len(permission_json) != 0:
- api_call: dict = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.FOLDERS.value}/{uid}/permissions",
- RequestsMethods.POST,
- json.dumps(permission_json),
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.FOLDERS.value}/{uid}/permissions",
+ RequestsMethods.POST,
+ json.dumps(permission_json),
+ )
+ .json()
)
if api_call.get("message") != "Folder permissions updated":
@@ -211,11 +291,25 @@ def update_folder_permissions(self, uid: str, permission_json: dict):
else:
logging.info("You successfully modified the folder permissions.")
else:
- logging.info("There is no folder uid or permission json defined.")
+ logging.error("There is no folder uid or permission json defined.")
raise ValueError
def get_folder_id_by_dashboard_path(self, dashboard_path: str) -> int:
- """The method includes a functionality to extract the folder id specified inside model dashboard path"""
+ """The method includes a functionality to extract the folder id specified inside model dashboard path
+
+ Args:
+ dashboard_path (str): Specify the dashboard path
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ folder_id (int): Returns the folder id
+ """
+
+ if dashboard_path.lower() == "general":
+ return 0
if len(dashboard_path) != 0:
folders: list = self.get_all_folder_ids_and_names()
@@ -233,14 +327,20 @@ def get_folder_id_by_dashboard_path(self, dashboard_path: str) -> int:
return folder_id
else:
- logging.info("There is no dashboard_path defined.")
+ logging.error("There is no dashboard_path defined.")
raise ValueError
def get_all_folder_ids_and_names(self) -> list:
- """The method extract all folder id and names inside the complete organisation"""
+ """The method extract all folder id and names inside the complete organisation
+
+ Returns:
+ folders (list): Returns a list of dicts with folder ids and the corresponding names
+ """
- folders_raw: list = Utils(self.grafana_api_model).call_the_api(
- f"{APIEndpoints.SEARCH.value}?folderIds=0"
+ folders_raw: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.SEARCH.value}?folderIds=0")
+ .json()
)
folders_raw_len: int = len(folders_raw)
folders: list = list()
diff --git a/src/grafana_api/legacy_alerting.py b/src/grafana_api/legacy_alerting.py
new file mode 100644
index 0000000..a73a0db
--- /dev/null
+++ b/src/grafana_api/legacy_alerting.py
@@ -0,0 +1,183 @@
+import json
+import logging
+
+from .model import APIModel, APIEndpoints, RequestsMethods
+from .api import Api
+
+
+class Alerting:
+ """The class includes all necessary methods to access the Grafana legacy alerting API endpoints
+
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
+ """
+
+ def __init__(self, grafana_api_model: APIModel):
+ self.grafana_api_model = grafana_api_model
+
+ def get_alerts(
+ self,
+ custom_querystring: str = None,
+ ) -> list:
+ """The method includes a functionality to get the legacy alerts
+
+ Args:
+ custom_querystring (str): Specify the custom querystring (default None)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns a list of all alerts
+ """
+
+ api_string: str = ""
+
+ if custom_querystring is not None and len(custom_querystring) != 0:
+ api_string = f"{APIEndpoints.LEGACY_ALERTS.value}/{custom_querystring}"
+ elif custom_querystring is None:
+ api_string = APIEndpoints.LEGACY_ALERTS.value
+
+ if len(api_string) != 0:
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ api_string,
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error(
+ "Please, check the functionality. An unexpected error occurred."
+ )
+ raise ValueError
+
+ def get_alerts_by_dashboard_ids(
+ self,
+ dashboard_ids: list,
+ ) -> list:
+ """The method includes a functionality to get legacy alerts specified by the dashboard ids
+
+ Args:
+ dashboard_ids (list): Specify the list of dashboard ids
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns a list of alerts
+ """
+
+ if dashboard_ids != list():
+ dashboard_ids_string: str = "?"
+ for i in range(0, len(dashboard_ids)):
+ dashboard_ids_string = (
+ f"{dashboard_ids_string}dashboardId={dashboard_ids[i]}"
+ )
+
+ if i < len(dashboard_ids) - 1:
+ dashboard_ids_string = f"{dashboard_ids_string}&"
+
+ api_call: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.LEGACY_ALERTS.value}/{dashboard_ids_string}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == list() or api_call[0].get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no dashboard_ids defined.")
+ raise ValueError
+
+ def get_alert_by_id(self, id: int) -> dict:
+ """The method includes a functionality to get the legacy alert specified by the alert id
+
+ Args:
+ id (int): Specify the id of the legacy alert
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (dict): Returns an alert
+ """
+
+ if id != 0:
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.LEGACY_ALERTS.value}/{id}",
+ RequestsMethods.GET,
+ )
+ .json()
+ )
+
+ if api_call == dict() or api_call.get("id") is None:
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ return api_call
+ else:
+ logging.error("There is no id defined.")
+ raise ValueError
+
+ def pause_alert_by_id(self, id: int, paused: bool = True):
+ """The method includes a functionality to pause/ unpause a legacy alert specified by the alert id
+
+ Args:
+ id (int): Specify the id of the legacy alert
+ paused (bool): Specify the pause/ unpause parameter (default True)
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ None
+ """
+
+ if id != 0:
+ json_complete: dict = {
+ "paused": paused,
+ }
+
+ api_call: dict = (
+ Api(self.grafana_api_model)
+ .call_the_api(
+ f"{APIEndpoints.LEGACY_ALERTS.value}/{id}/pause",
+ RequestsMethods.POST,
+ json.dumps(json_complete),
+ )
+ .json()
+ )
+
+ if api_call.get(
+ "message"
+ ) != "alert paused" or "alert unpause" in api_call.get("message"):
+ logging.error(f"Check the error: {api_call}.")
+ raise Exception
+ else:
+ logging.info(api_call.get("message"))
+ else:
+ logging.error("There is no id defined.")
+ raise ValueError
diff --git a/src/grafana_api/model.py b/src/grafana_api/model.py
index b6c9e35..39d9f1d 100644
--- a/src/grafana_api/model.py
+++ b/src/grafana_api/model.py
@@ -1,27 +1,29 @@
from enum import Enum
+from typing import NamedTuple
-""""""
+# The constant includes all necessary error messages that can occurs, if you establish a connection to the Grafana API.
ERROR_MESSAGES: list = ["invalid API key"]
class APIEndpoints(Enum):
- """The class includes all necessary methods to template the selected dashboard and return it as a dict
-
- Keyword arguments:
- dashboard_model -> Inject a dashboard object that includes all necessary values and information
- """
+ """The class includes all necessary API endpoint strings to connect the Grafana API"""
SEARCH = "/api/search"
DASHBOARDS = "/api/dashboards"
FOLDERS = "/api/folders"
+ LEGACY_ALERTS = "/api/alerts"
+ ALERT_NOTIFICATIONS = "/api/alert-notifications"
+ ALERTS_ALERTMANAGER = "/api/alertmanager"
+ ALERTS_PROMETHEUS = "/api/prometheus"
+ ALERTS_RULER = "/api/ruler"
+ ALERTS_TESTING = "/api/v1"
+ ALERTS_NGALERT = "/api/v1/ngalert"
+ DATASOURCES = "/api/datasources"
+ DATASOURCE_QUERY = "/api/tsdb/query"
class RequestsMethods(Enum):
- """The class includes all necessary methods to template the selected dashboard and return it as a dict
-
- Keyword arguments:
- dashboard_model -> Inject a dashboard object that includes all necessary values and information
- """
+ """The class includes all necessary methods to establish an HTTP/ HTTPS connection to the Grafana API endpoints"""
GET = "GET"
PUT = "PUT"
@@ -29,18 +31,160 @@ class RequestsMethods(Enum):
DELETE = "DELETE"
-class APIModel:
+class APIModel(NamedTuple):
"""The class includes all necessary variables to establish a connection to the Grafana API endpoints
- Keyword arguments:
- host -> Specify the host of the Grafana system
- token -> Specify the access token of the Grafana system
+ Args:
+ host (str): Specify the host of the Grafana system
+ token (str): Specify the access token of the Grafana system
+ """
+
+ host: str
+ token: str
+
+
+class DatasourceQuery(NamedTuple):
+ """The class includes all necessary variables to specify a query for the datasource search endpoint
+
+ Args:
+ datasource_id (int): Specify the id of the data source
+ raw_sql (str): Specify the raw SQL string to search inside the Grafana system
+ ref_id (str): Specify a reference id of the search command (default A)
+ interval_ms (int): Specify the time interval in milliseconds of output format (default 1000)
+ max_data_points (int): Specify maximum amount of data points that dashboard panel can render (default 100)
+ output_format (str): Specify the output format of the query (default time_series)
+ """
+
+ datasource_id: int
+ raw_sql: str
+ ref_id: str = "A"
+ interval_ms: int = 1000
+ max_data_points: int = 100
+ output_format: str = "time_series"
+
+
+class DatasourceRuleQuery(NamedTuple):
+ """The class includes all necessary variables to specify a query for the datasource rule search endpoint
+
+ Args:
+ datasource_uid (str): Specify the uid of the data source
+ model (dict): Specify the model of the search command
+ query_type (str): Specify the query time of the search command
+ ref_id (str): Specify a reference id of the search command
+ relative_time_range (dict): Specify the related time range of the search command
+ """
+
+ datasource_uid: str
+ model: dict
+ query_type: str
+ ref_id: str
+ relative_time_range: dict
+
+
+class Alert(NamedTuple):
+ """The class includes all necessary variables to generate an alert object that is necessary to communicate with the Grafana alert endpoint
+
+ Args:
+ starts_at (str): Specify the start date of the alert
+ ends_at (str): Specify end date of the alert
+ annotations (dict): Specify the annotations of the alert
+ generator_url (str): Specify the url of the generator endpoint
+ labels (dict): Specify labels of the alert
+ """
+
+ starts_at: str
+ ends_at: str
+ annotations: dict
+ generator_url: str
+ labels: dict
+
+
+class Silence(NamedTuple):
+ """The class includes all necessary variables to generate a silence object that is necessary to communicate with the Grafana silence endpoint
+
+ Args:
+ starts_at (str): Specify the start date of the silence
+ created_by (str): Specify the name of the silence creator
+ ends_at (str): Specify end date of the silence
+ comment (str): Specify a custom comment for the silence
+ id (str): Specify an id for the silence
+ matchers (dict): Specify matchers for the silence
+ """
+
+ starts_at: str
+ created_by: str
+ ends_at: str
+ comment: str
+ id: str
+ matchers: dict
+
+
+class AlertmanagerConfig(NamedTuple):
+ """The class includes all necessary variables to generate an Alertmanager config object that is necessary to communicate and set up the Grafana Alertmanager endpoint
+
+ Args:
+ global_config (dict): Specify the global config of the Alertmanager
+ inhibit_rules (list): Specify the inhibit rules of the Alertmanager
+ mute_time_intervals (list): Specify the mute time intervals of the Alertmanager
+ receivers (list): Specify the receivers of the Alertmanager
+ route (dict): Specify the route of the Alertmanager
+ templates (list): Specify an Alertmanager template
+ """
+
+ global_config: dict
+ inhibit_rules: list
+ mute_time_intervals: list
+ receivers: list
+ route: dict
+ templates: list
+
+
+class AlertmanagerReceivers(NamedTuple):
+ """The class includes all necessary variables to generate an Alertmanager receivers object that is necessary to communicate and set up the Grafana Alertmanager receivers endpoint
+
+ Args:
+ name (str): Specify the name of the receiver
+ email_configs (list): Specify the email configuration of the receiver's
+ grafana_managed_receiver_configs (list): Specify the Grafana managed receiver configuration of the receiver's
+ opsgenie_configs (list): Specify the ops genie configuration of the receiver's
+ pagerduty_configs (dict): Specify the pager duty configuration of the receiver's
+ pushover_configs (list): Specify the push over configuration of the receiver's
+ slack_configs (list): Specify the Slack configuration of the receiver's
+ victorops_configs (list): Specify the victor ops configuration of the receiver's
+ webhook_configs (list): Specify the webhook configuration of the receiver's
+ wechat_configs (list): Specify the wechaty configuration of the receiver's
+ """
+
+ name: str
+ email_configs: list
+ grafana_managed_receiver_configs: list
+ opsgenie_configs: list
+ pagerduty_configs: list
+ pushover_configs: list
+ slack_configs: list
+ sns_configs: list
+ victorops_configs: list
+ webhook_configs: list
+ wechat_configs: list
+
+
+class RulerRule(NamedTuple):
+ """The class includes all necessary variables to generate a Ruler rule object that is necessary to communicate and set up a Grafana Ruler rule
+
+ Args:
+ alert (str): Specify the name of the rule
+ annotations (dict): Specify the annotations of the rule
+ expr (str): Specify the expression of the rule
+ grafana_alert (dict): Specify the Grafana alert of the rule
+ labels (dict): Specify labels of the rule
+ record (str): Specify recode value of the rule
+ for_id (int): Specify the id of the rule if you update an existing rule (default 0)
"""
- def __init__(
- self,
- host: str = None,
- token: str = None,
- ):
- self.host = host
- self.token = token
+ alert: str
+ annotations: dict
+ expr: str
+ grafana_alert: dict
+ labels: dict
+ record: str
+ for_id: int = 0
diff --git a/src/grafana_api/search.py b/src/grafana_api/search.py
index b77711b..a8517c1 100644
--- a/src/grafana_api/search.py
+++ b/src/grafana_api/search.py
@@ -1,12 +1,17 @@
-from .utils import Utils
-from .model import APIModel
+import logging
+
+from .api import Api
+from .model import APIModel, APIEndpoints
class Search:
"""The class includes all necessary methods to access the Grafana search API endpoints
- Keyword arguments:
- grafana_api_model -> Inject a Grafana API model object that includes all necessary values and information
+ Args:
+ grafana_api_model (APIModel): Inject a Grafana API model object that includes all necessary values and information
+
+ Attributes:
+ grafana_api_model (APIModel): This is where we store the grafana_api_model
"""
def __init__(self, grafana_api_model: APIModel):
@@ -15,12 +20,27 @@ def __init__(self, grafana_api_model: APIModel):
def search(self, search_query: str) -> list:
"""The method includes a functionality to execute a custom query
- Keyword arguments:
- search_query -> Specify the inserted query as string
+ Args:
+ search_query (str): Specify the inserted query as string
+
+ Raises:
+ ValueError: Missed specifying a necessary value
+ Exception: Unspecified error by executing the API call
+
+ Returns:
+ api_call (list): Returns the list of query the results
"""
- result: list = Utils(self.grafana_api_model).call_the_api(search_query)
- if result == list():
- raise Exception
+ if len(search_query) != 0:
+ result: list = (
+ Api(self.grafana_api_model)
+ .call_the_api(f"{APIEndpoints.SEARCH.value}?{search_query}")
+ .json()
+ )
+ if result == list():
+ raise Exception
+ else:
+ return result
else:
- return result
+ logging.error("There is no search_query defined.")
+ raise ValueError
diff --git a/src/grafana_api/utils.py b/src/grafana_api/utils.py
deleted file mode 100644
index b63d42b..0000000
--- a/src/grafana_api/utils.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import logging
-import requests
-
-from .model import RequestsMethods, ERROR_MESSAGES, APIModel
-
-
-class Utils:
- """The class includes all necessary methods to make API calls to the Grafana API endpoints
-
- Keyword arguments:
- grafana_api_model -> Inject a Grafana API model object that includes all necessary values and information
- """
-
- def __init__(self, grafana_api_model: APIModel):
- self.grafana_api_model = grafana_api_model
-
- def call_the_api(
- self,
- api_call: str,
- method: RequestsMethods = RequestsMethods.GET,
- json_complete: str = None,
- ) -> any:
- """The method execute a defined API call against the Grafana endpoints
-
- Keyword arguments:
- api_call -> Specify the API call endpoint
- method -> Specify the used method
- json_complete -> Specify the inserted JSON as string
- """
-
- api_url: str = f"{self.grafana_api_model.host}{api_call}"
-
- headers: dict = {
- "Authorization": f"Bearer {self.grafana_api_model.token}",
- "Content-Type": "application/json",
- }
- try:
- if method.value == RequestsMethods.GET.value:
- return Utils.__check_the_api_call_response(
- requests.get(api_url, headers=headers).json()
- )
- elif method.value == RequestsMethods.PUT.value:
- if json_complete is not None:
- return Utils.__check_the_api_call_response(
- requests.put(
- api_url, data=json_complete, headers=headers
- ).json()
- )
- else:
- logging.error("Please define the json_complete.")
- raise Exception
- elif method.value == RequestsMethods.POST.value:
- if json_complete is not None:
- return Utils.__check_the_api_call_response(
- requests.post(
- api_url, data=json_complete, headers=headers
- ).json()
- )
- else:
- logging.error("Please define the json_complete.")
- raise Exception
- elif method.value == RequestsMethods.DELETE.value:
- return Utils.__check_the_api_call_response(
- requests.delete(api_url, headers=headers).json()
- )
- else:
- logging.error("Please define a valid method.")
- raise Exception
- except Exception as e:
- raise e
-
- def call_the_api_non_json_output(
- self,
- api_call: str,
- method: RequestsMethods = RequestsMethods.GET,
- json_complete: str = None,
- ) -> any:
- """The method execute a defined API call against the Grafana endpoints
-
- Keyword arguments:
- api_call -> Specify the API call endpoint
- method -> Specify the used method
- json_complete -> Specify the inserted JSON as string
- """
-
- api_url: str = f"{self.grafana_api_model.host}{api_call}"
-
- headers: dict = {
- "Authorization": f"Bearer {self.grafana_api_model.token}",
- "Content-Type": "application/json",
- }
- try:
- if method.value == RequestsMethods.GET.value:
- return Utils.__check_the_api_call_response(
- requests.get(api_url, headers=headers)
- )
- elif method.value == RequestsMethods.POST.value:
- if json_complete is not None:
- return Utils.__check_the_api_call_response(
- requests.post(api_url, data=json_complete, headers=headers)
- )
- else:
- logging.error("Please define the json_complete.")
- raise Exception
- elif method.value == RequestsMethods.DELETE.value:
- return Utils.__check_the_api_call_response(
- requests.delete(api_url, headers=headers)
- )
- else:
- logging.error("Please define a valid method.")
- raise Exception
- except Exception as e:
- raise e
-
- @staticmethod
- def __check_the_api_call_response(response: any = None) -> any:
- """The method includes a functionality to check the output of API call method for errors
-
- Keyword arguments:
- response -> Specify the inserted response
- """
-
- if type(response) == dict:
- if "message" in response.keys() and response["message"] in ERROR_MESSAGES:
- logging.error(response["message"])
- raise requests.exceptions.ConnectionError
-
- return response
diff --git a/tests/integrationtest/resources/dashboard.json b/tests/integrationtest/resources/dashboard.json
index f20876e..0925e53 100644
--- a/tests/integrationtest/resources/dashboard.json
+++ b/tests/integrationtest/resources/dashboard.json
@@ -1,30 +1,32 @@
{
- "id": null,
- "uid": "tests",
- "title": "Test",
- "tags": [],
- "style": "dark",
- "timezone": "browser",
- "editable": true,
- "hideControls": false,
- "graphTooltip": 1,
- "panels": [],
- "time": {
- "from": "now-6h",
- "to": "now"
- },
- "timepicker": {
- "time_options": [],
- "refresh_intervals": []
- },
- "templating": {
- "list": []
- },
- "annotations": {
- "list": []
- },
- "refresh": "5s",
- "schemaVersion": 17,
- "version": 0,
- "links": []
+ "dashboard": {
+ "id": null,
+ "uid": "tests",
+ "title": "Test",
+ "tags": [],
+ "style": "dark",
+ "timezone": "browser",
+ "editable": true,
+ "hideControls": false,
+ "graphTooltip": 1,
+ "panels": [],
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {
+ "time_options": [],
+ "refresh_intervals": []
+ },
+ "templating": {
+ "list": []
+ },
+ "annotations": {
+ "list": []
+ },
+ "refresh": "5s",
+ "schemaVersion": 17,
+ "version": 0,
+ "links": []
+ }
}
\ No newline at end of file
diff --git a/tests/integrationtest/resources/dashboard_expected_result.json b/tests/integrationtest/resources/dashboard_expected_result.json
index 007becc..384914d 100644
--- a/tests/integrationtest/resources/dashboard_expected_result.json
+++ b/tests/integrationtest/resources/dashboard_expected_result.json
@@ -4,13 +4,13 @@
"list": []
},
"editable": true,
- "graphTooltip": 1,
- "hideControls": false,
- "id": 104,
+ "fiscalYearStartMonth": 0,
+ "graphTooltip": 0,
+ "id": 152,
"links": [],
+ "liveNow": false,
"panels": [],
- "refresh": "5s",
- "schemaVersion": 17,
+ "schemaVersion": 34,
"style": "dark",
"tags": [],
"templating": {
@@ -20,36 +20,11 @@
"from": "now-6h",
"to": "now"
},
- "timepicker": {
- "refresh_intervals": [],
- "time_options": []
- },
- "timezone": "browser",
+ "timepicker": {},
+ "timezone": "",
"title": "Test 1",
- "uid": "tests1",
- "version": 1
- },
- "meta": {
- "canAdmin": true,
- "canEdit": true,
- "canSave": true,
- "canStar": true,
- "created": "2022-01-15T20:46:44+01:00",
- "createdBy": "Anonymous",
- "expires": "0001-01-01T00:00:00Z",
- "folderId": 72,
- "folderTitle": "Github Integrationtest",
- "folderUid": "6U_QdWJnz",
- "folderUrl": "/dashboards/f/6U_QdWJnz/github-integrationtest",
- "hasAcl": false,
- "isFolder": false,
- "provisioned": false,
- "provisionedExternalId": "",
- "slug": "test-1",
- "type": "db",
- "updated": "2022-01-15T20:46:44+01:00",
- "updatedBy": "Anonymous",
- "url": "/d/tests1/test-1",
- "version": 1
+ "uid": "test1",
+ "version": 3,
+ "weekStart": ""
}
}
\ No newline at end of file
diff --git a/tests/integrationtest/test_alerting.py b/tests/integrationtest/test_alerting.py
new file mode 100644
index 0000000..12ddc9a
--- /dev/null
+++ b/tests/integrationtest/test_alerting.py
@@ -0,0 +1,180 @@
+import os
+from unittest import TestCase
+
+from src.grafana_api.model import (
+ APIModel,
+ AlertmanagerConfig,
+ AlertmanagerReceivers,
+ DatasourceRuleQuery,
+)
+from src.grafana_api.alerting import Alerting
+
+
+class AlertingTest(TestCase):
+ model: APIModel = APIModel(
+ host=os.environ["GRAFANA_HOST"],
+ token=os.environ["GRAFANA_TOKEN"],
+ )
+ alerting: Alerting = Alerting(model)
+
+ def test_a_create_or_update_alertmanager_config(self):
+ alertmanager_config: AlertmanagerConfig = AlertmanagerConfig(
+ global_config=None,
+ inhibit_rules=None,
+ mute_time_intervals=None,
+ receivers=[
+ {
+ "name": "grafana-default-email-1",
+ "grafana_managed_receiver_configs": [
+ {
+ "uid": None,
+ "name": "email receiver 1",
+ "type": "email",
+ "disableResolveMessage": False,
+ "settings": {"addresses": ""},
+ "secureFields": {},
+ }
+ ],
+ }
+ ],
+ route={"receiver": "grafana-default-email-1"},
+ templates=None,
+ )
+ self.alerting.create_or_update_alertmanager_config(alertmanager_config)
+
+ def test_b_get_alertmanager_config(self):
+ self.assertEqual(
+ "grafana-default-email-1",
+ self.alerting.get_alertmanager_config()
+ .get("alertmanager_config")
+ .get("route")
+ .get("receiver"),
+ )
+
+ def test_c_delete_alertmanager_config(self):
+ self.alerting.delete_alertmanager_config()
+
+ result: dict = {
+ "template_files": None,
+ "alertmanager_config": {
+ "route": {"receiver": "grafana-default-email"},
+ "templates": None,
+ "receivers": [
+ {
+ "name": "grafana-default-email",
+ "grafana_managed_receiver_configs": [
+ {
+ "uid": "",
+ "name": "email receiver",
+ "type": "email",
+ "disableResolveMessage": False,
+ "settings": {"addresses": ""},
+ "secureFields": {},
+ }
+ ],
+ }
+ ],
+ },
+ }
+ self.assertEqual(result, self.alerting.get_alertmanager_config())
+
+ def test_test_alertmanager_receivers(self):
+ grafana_managed_receiver_configs: list = [
+ {
+ "uid": None,
+ "name": "email receiver",
+ "type": "email",
+ "disableResolveMessage": False,
+ "settings": {"addresses": "info@theiotstudio.com"},
+ "secureFields": {},
+ }
+ ]
+
+ alertmangager_receivers: AlertmanagerReceivers = AlertmanagerReceivers(
+ name="Test",
+ email_configs=None,
+ grafana_managed_receiver_configs=grafana_managed_receiver_configs,
+ opsgenie_configs=None,
+ pagerduty_configs=None,
+ pushover_configs=None,
+ slack_configs=None,
+ sns_configs=None,
+ victorops_configs=None,
+ webhook_configs=None,
+ wechat_configs=None,
+ )
+ self.assertEqual(
+ None,
+ self.alerting.test_alertmanager_receivers(
+ alert=dict(
+ {"annotations": {"test": "test"}, "labels": {"test": "test"}}
+ ),
+ receivers=list([alertmangager_receivers]),
+ ),
+ )
+
+ def test_get_prometheus_alerts(self):
+ result: dict = {
+ "status": "success",
+ "data": {
+ "alerts": [
+ {
+ "labels": {
+ "__alert_rule_namespace_uid__": "6U_QdWJnz",
+ "__alert_rule_uid__": "Z9GoLXx7z",
+ "alertname": "Test",
+ },
+ "annotations": {},
+ "state": "Normal",
+ "activeAt": "0001-01-01T00:53:28+00:53",
+ "value": "",
+ }
+ ]
+ },
+ }
+ self.assertEqual(result, self.alerting.get_prometheus_alerts())
+
+ def test_get_prometheus_rules(self):
+ self.assertEqual(
+ "Github Integrationtest",
+ self.alerting.get_prometheus_rules()
+ .get("data")
+ .get("groups")[0]
+ .get("file"),
+ )
+
+ def test_get_ruler_rules(self):
+ self.assertEqual(
+ "Test",
+ self.alerting.get_ruler_rules()
+ .get("Github Integrationtest")[0]
+ .get("name"),
+ )
+
+ def test_test_rule(self):
+ datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
+ datasource_uid="test",
+ model=dict(),
+ query_type="",
+ ref_id="test1",
+ relative_time_range=dict({"from": 20, "to": 90}),
+ )
+ data_queries: list = list([datasource_rule_query])
+
+ with self.assertRaises(Exception):
+ self.alerting.test_rule(data_queries)
+
+ def test_test_recipient_rule(self):
+ datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
+ datasource_uid="test",
+ model=dict(),
+ query_type="",
+ ref_id="test1",
+ relative_time_range=dict({"from": 20, "to": 90}),
+ )
+ data_queries: list = list([datasource_rule_query])
+
+ with self.assertRaises(Exception):
+ self.alerting.test_recipient_rule(
+ expr="test", condition="test", data_query=data_queries
+ )
diff --git a/tests/integrationtest/test_alerting_notifications.py b/tests/integrationtest/test_alerting_notifications.py
new file mode 100644
index 0000000..59d11b5
--- /dev/null
+++ b/tests/integrationtest/test_alerting_notifications.py
@@ -0,0 +1,250 @@
+import os
+from unittest import TestCase
+
+from src.grafana_api.model import APIModel
+from src.grafana_api.alerting_notifications import AlertingNotifications
+
+
+class AlertingNotificationsTest(TestCase):
+ model: APIModel = APIModel(
+ host=os.environ["GRAFANA_HOST"],
+ token=os.environ["GRAFANA_TOKEN"],
+ )
+ alerting_notifications: AlertingNotifications = AlertingNotifications(model)
+
+ def test_get_all_notification_channels(self):
+ self.alerting_notifications.delete_notification_channel_by_uid(
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-1"
+ ).get("uid")
+ )
+
+ all_notification_channels: list = list(
+ [
+ {
+ "created": "2022-03-02T10:04:24+01:00",
+ "disableResolveMessage": False,
+ "frequency": "",
+ "id": 1,
+ "isDefault": False,
+ "name": "new alert notification",
+ "secureFields": {},
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ "type": "email",
+ "uid": "new-alert-notification",
+ "updated": "2022-03-02T10:04:24+01:00",
+ }
+ ]
+ )
+
+ self.assertEqual(
+ all_notification_channels,
+ self.alerting_notifications.get_all_notification_channels(),
+ )
+
+ def test_get_all_notification_channels_lookup(self):
+ all_notification_channels: list = list(
+ [
+ {
+ "id": 1,
+ "isDefault": False,
+ "name": "new alert notification",
+ "type": "email",
+ "uid": "new-alert-notification",
+ }
+ ]
+ )
+
+ self.assertEqual(
+ all_notification_channels,
+ self.alerting_notifications.get_all_notification_channels_lookup(),
+ )
+
+ def test_get_notification_channel_by_uid(self):
+ notification_channel: dict = dict(
+ {
+ "created": "2022-03-02T10:04:24+01:00",
+ "disableResolveMessage": False,
+ "frequency": "",
+ "id": 1,
+ "isDefault": False,
+ "name": "new alert notification",
+ "secureFields": {},
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ "type": "email",
+ "uid": "new-alert-notification",
+ "updated": "2022-03-02T10:04:24+01:00",
+ }
+ )
+
+ self.assertEqual(
+ notification_channel,
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification"
+ ),
+ )
+
+ def test_get_notification_channel_by_id(self):
+ notification_channel: dict = dict(
+ {
+ "created": "2022-03-02T10:04:24+01:00",
+ "disableResolveMessage": False,
+ "frequency": "",
+ "id": 1,
+ "isDefault": False,
+ "name": "new alert notification",
+ "secureFields": {},
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ "type": "email",
+ "uid": "new-alert-notification",
+ "updated": "2022-03-02T10:04:24+01:00",
+ }
+ )
+
+ self.assertEqual(
+ notification_channel,
+ self.alerting_notifications.get_notification_channel_by_id(1),
+ )
+
+ def test_a_create_notification_channel(self):
+ notification_channel: dict = dict(
+ {
+ "uid": "new-alert-notification-1",
+ "name": "new alert notification-1",
+ "type": "email",
+ "isDefault": False,
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ }
+ )
+
+ self.alerting_notifications.create_notification_channel(notification_channel)
+
+ self.assertEqual(
+ "new-alert-notification-1",
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-1"
+ ).get("uid"),
+ )
+
+ def test_b_update_notification_channel_by_uid(self):
+ notification_channel: dict = dict(
+ {
+ "uid": "new-alert-notification-2",
+ "name": "new alert notification-2",
+ "type": "email",
+ "isDefault": False,
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ }
+ )
+
+ self.alerting_notifications.create_notification_channel(notification_channel)
+
+ notification_channel_update: dict = dict(
+ {
+ "uid": "new-alert-notification-2",
+ "name": "new-alert-notification-2.1",
+ "type": "email",
+ "isDefault": False,
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ }
+ )
+
+ self.alerting_notifications.update_notification_channel_by_uid(
+ "new-alert-notification-2", notification_channel_update
+ )
+
+ self.assertEqual(
+ "new-alert-notification-2.1",
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-2"
+ ).get("name"),
+ )
+
+ def test_c_update_notification_channel_by_id(self):
+ notification_channel: dict = dict(
+ {
+ "uid": "new-alert-notification-3",
+ "name": "new alert notification-3",
+ "type": "email",
+ "isDefault": False,
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ }
+ )
+
+ self.alerting_notifications.create_notification_channel(notification_channel)
+
+ notification_channel_update: dict = dict(
+ {
+ "id": self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-3"
+ ).get("id"),
+ "uid": "new-alert-notification-3",
+ "name": "new-alert-notification-3.1",
+ "type": "email",
+ "isDefault": False,
+ "sendReminder": False,
+ "settings": {"addresses": "test@test.com"},
+ }
+ )
+ self.alerting_notifications.update_notification_channel_by_id(
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-3"
+ ).get("id"),
+ notification_channel_update,
+ )
+
+ self.assertEqual(
+ "new-alert-notification-3.1",
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-3"
+ ).get("name"),
+ )
+
+ def test_d_delete_notification_channel_by_uid(self):
+ notification_channel_uid: str = (
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-2"
+ ).get("uid")
+ )
+
+ self.alerting_notifications.delete_notification_channel_by_uid(
+ notification_channel_uid
+ )
+
+ with self.assertRaises(Exception):
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-2"
+ )
+
+ def test_e_delete_notification_channel_by_id(self):
+ notification_channel_id: int = (
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-3"
+ ).get("id")
+ )
+
+ self.alerting_notifications.delete_notification_channel_by_id(
+ notification_channel_id
+ )
+
+ with self.assertRaises(Exception):
+ self.alerting_notifications.get_notification_channel_by_uid(
+ "new-alert-notification-3"
+ )
+
+ def test_test_notification_channel(self):
+ notification_channel: dict = dict(
+ {"type": "email", "settings": {"addresses": "info@theiotstudio.com"}}
+ )
+
+ self.assertEqual(
+ None,
+ self.alerting_notifications.test_notification_channel(notification_channel),
+ )
diff --git a/tests/integrationtest/test_dashboard.py b/tests/integrationtest/test_dashboard.py
index e59b991..27e3fdc 100644
--- a/tests/integrationtest/test_dashboard.py
+++ b/tests/integrationtest/test_dashboard.py
@@ -25,18 +25,24 @@ def test_a_dashboard_creation(self):
self.dashboard.create_or_update_dashboard(
message="Create a new test dashboard",
- dashboard_json=json_dashboard,
+ dashboard_json=json_dashboard.get("dashboard"),
dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"],
overwrite=True,
)
self.assertEqual(
- "tests", self.dashboard.get_dashboard_uid_and_id_by_name_and_folder(
+ "tests",
+ self.dashboard.get_dashboard_uid_and_id_by_name_and_folder(
dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"],
- dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"])["uid"]
+ dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"],
+ )["uid"],
+ )
+ self.assertEqual(
+ 72,
+ self.folder.get_folder_id_by_dashboard_path(
+ dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"]
+ ),
)
- self.assertEqual(72, self.folder.get_folder_id_by_dashboard_path(
- dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"]))
def test_b_get_dashboard(self):
with open(
@@ -44,18 +50,60 @@ def test_b_get_dashboard(self):
) as file:
json_dashboard = json.load(file)
- self.assertEqual(json_dashboard, self.dashboard.get_dashboard_by_uid("tests1"))
+ self.assertEqual(
+ json_dashboard.get("dashboard"),
+ self.dashboard.get_dashboard_by_uid("test1").get("dashboard"),
+ )
def test_c_dashboard_deletion(self):
- self.dashboard.delete_dashboard_by_name_and_path(dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"],
- dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"])
+ self.dashboard.delete_dashboard_by_name_and_path(
+ dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"],
+ dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"],
+ )
+
+ def test_d_dashboard_creation_general_folder(self):
+ with open(
+ f"{os.getcwd()}{os.sep}tests{os.sep}integrationtest{os.sep}resources{os.sep}dashboard.json"
+ ) as file:
+ json_dashboard = json.load(file)
+
+ self.dashboard.create_or_update_dashboard(
+ message="Create a new test dashboard",
+ dashboard_json=json_dashboard.get("dashboard"),
+ dashboard_path="General",
+ overwrite=True,
+ )
+
+ self.assertEqual(
+ "tests",
+ self.dashboard.get_dashboard_uid_and_id_by_name_and_folder(
+ dashboard_path="General",
+ dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"],
+ )["uid"],
+ )
+ self.assertEqual(
+ 0, self.folder.get_folder_id_by_dashboard_path(dashboard_path="General")
+ )
+
+ def test_e_dashboard_deletion_general_folder(self):
+ self.dashboard.delete_dashboard_by_name_and_path(
+ dashboard_path="General",
+ dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"],
+ )
def test_wrong_token(self):
- self.model.token = "test"
+ model: APIModel = APIModel(
+ host=os.environ["GRAFANA_HOST"],
+ token="test",
+ )
+
+ dashboard: Dashboard = Dashboard(model)
with self.assertRaises(requests.exceptions.ConnectionError):
- self.dashboard.delete_dashboard_by_name_and_path(dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"],
- dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"])
+ dashboard.delete_dashboard_by_name_and_path(
+ dashboard_path=os.environ["GRAFANA_DASHBOARD_PATH"],
+ dashboard_name=os.environ["GRAFANA_DASHBOARD_NAME"],
+ )
if __name__ == "__main__":
diff --git a/tests/integrationtest/test_datasource.py b/tests/integrationtest/test_datasource.py
new file mode 100644
index 0000000..04f4dbd
--- /dev/null
+++ b/tests/integrationtest/test_datasource.py
@@ -0,0 +1,93 @@
+import os
+from unittest import TestCase
+
+from src.grafana_api.model import APIModel
+from src.grafana_api.datasource import Datasource
+
+
+class DataSourceTest(TestCase):
+ model: APIModel = APIModel(
+ host=os.environ["GRAFANA_HOST"],
+ token=os.environ["GRAFANA_TOKEN"],
+ )
+ data_source: Datasource = Datasource(model)
+
+ def test_list_all_data_sources(self):
+ data_sources: list = self.data_source.get_all_datasources()
+
+ self.assertEqual(5, data_sources[0]["id"])
+
+ def test_get_datasource_by_id(self):
+ data_source: dict = self.data_source.get_datasource_by_id(5)
+
+ self.assertEqual("5yBH2Yxnk", data_source["uid"])
+
+ def test_get_datasource_by_uid(self):
+ data_source: dict = self.data_source.get_datasource_by_uid("5yBH2Yxnk")
+
+ self.assertEqual(5, data_source["id"])
+
+ def test_get_datasource_by_name(self):
+ data_source: dict = self.data_source.get_datasource_by_name("TestData DB")
+
+ self.assertEqual(5, data_source["id"])
+
+ def test_get_datasource_id_by_name(self):
+ self.assertEqual(5, self.data_source.get_datasource_id_by_name("TestData DB"))
+
+ def test_a_create_datasource(self):
+ data_source: dict = self.data_source.get_datasource_by_id(5)
+ data_source["id"] = None
+ data_source["uid"] = None
+ data_source["name"] = "TestData DB 1"
+
+ self.assertEqual(None, self.data_source.create_datasource(data_source))
+ self.assertEqual(
+ self.data_source.get_datasource_id_by_name("TestData DB 1"),
+ self.data_source.get_datasource_by_name("TestData DB 1")["id"],
+ )
+
+ def test_b_update_datasource(self):
+ data_source: dict = self.data_source.get_datasource_by_name("TestData DB 1")
+ data_source["name"] = "TestData DB 2"
+
+ self.assertEqual(
+ None,
+ self.data_source.update_datasource(
+ self.data_source.get_datasource_id_by_name("TestData DB 1"), data_source
+ ),
+ )
+ self.assertEqual(
+ self.data_source.get_datasource_id_by_name("TestData DB 2"),
+ self.data_source.get_datasource_by_name("TestData DB 2")["id"],
+ )
+
+ def test_c_delete_datasource_by_id(self):
+ id: int = self.data_source.get_datasource_id_by_name("TestData DB 2")
+
+ self.assertEqual(None, self.data_source.delete_datasource_by_id(id))
+
+ with self.assertRaises(Exception):
+ self.data_source.get_datasource_by_id(id)
+
+ def test_delete_datasource_by_uid(self):
+ self.test_a_create_datasource()
+ data_source: dict = self.data_source.get_datasource_by_name("TestData DB 1")
+
+ self.assertEqual(
+ None, self.data_source.delete_datasource_by_uid(data_source["uid"])
+ )
+
+ with self.assertRaises(Exception):
+ self.data_source.get_datasource_by_id(data_source["id"])
+
+ def test_delete_datasource_by_name(self):
+ self.test_a_create_datasource()
+ data_source: dict = self.data_source.get_datasource_by_name("TestData DB 1")
+
+ self.assertEqual(
+ None, self.data_source.delete_datasource_by_name("TestData DB 1")
+ )
+
+ with self.assertRaises(Exception):
+ self.data_source.get_datasource_by_id(data_source["id"])
diff --git a/tests/unittests/test_alerting.py b/tests/unittests/test_alerting.py
new file mode 100644
index 0000000..d4805de
--- /dev/null
+++ b/tests/unittests/test_alerting.py
@@ -0,0 +1,987 @@
+from unittest import TestCase
+from unittest.mock import MagicMock, Mock, patch
+
+from src.grafana_api.model import (
+ APIModel,
+ Alert,
+ Silence,
+ AlertmanagerConfig,
+ AlertmanagerReceivers,
+ RulerRule,
+ DatasourceRuleQuery,
+)
+from src.grafana_api.alerting import Alerting
+
+
+class AlertingTestCase(TestCase):
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_alerts(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([dict({"receivers": "test"})]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ list([dict({"receivers": "test"})]),
+ alerting.get_alertmanager_alerts(),
+ )
+
+ def test_get_alertmanager_alerts_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alertmanager_alerts("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_alerts_no_alerts_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([]))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alertmanager_alerts()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_alertmanager_alerts(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alert: Alert = Alert("test", "test", {"test": "test"}, "test", {"test": "test"})
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.create_or_update_alertmanager_alerts([alert]))
+
+ def test_create_or_update_alertmanager_alerts_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.create_or_update_alertmanager_alerts([])
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_alertmanager_alerts_no_alerts_created(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alert: Alert = Alert("test", "test", {"test": "test"}, "test", {"test": "test"})
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.create_or_update_alertmanager_alerts([alert])
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_group_alerts(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"alerts": "test"}]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ list([{"alerts": "test"}]),
+ alerting.get_alertmanager_group_alerts(),
+ )
+
+ def test_get_alertmanager_group_alerts_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alertmanager_group_alerts("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_group_alerts_no_group_alerts(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alertmanager_group_alerts()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_alertmanager_silence_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_alertmanager_silence_by_id("test"))
+
+ def test_delete_alertmanager_silence_by_id_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.delete_alertmanager_silence_by_id("", "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_alertmanager_silence_by_id_no_silence_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_alertmanager_silence_by_id("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_silence_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}),
+ alerting.get_alertmanager_silence_by_id("test"),
+ )
+
+ def test_get_alertmanager_silence_by_id_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alertmanager_silence_by_id("", "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_silence_by_id_no_silence_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alertmanager_silence_by_id("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_silences(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"id": "test"}]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(list([{"id": "test"}]), alerting.get_alertmanager_silences())
+
+ def test_get_alertmanager_silences_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alertmanager_silences("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_silences_no_silence_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"id": None}]))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alertmanager_silences()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_alertmanager_silence(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ silence: Silence = Silence(
+ "test", "test", "test", "test", "test", {"test": "test"}
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}),
+ alerting.create_or_update_alertmanager_silence(silence),
+ )
+
+ def test_create_or_update_alertmanager_silences_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.create_or_update_alertmanager_silence(None, "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_alertmanager_silence_no_silence_created(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ silence: Silence = Silence(
+ "test", "test", "test", "test", "test", {"test": "test"}
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.create_or_update_alertmanager_silence(silence)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_status(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"config": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(dict({"config": "test"}), alerting.get_alertmanager_status())
+
+ def test_get_alertmanager_status_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alertmanager_status("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_status_no_status(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"config": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alertmanager_status()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_alertmanager_config(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=dict(
+ {"message": "configuration deleted; the default is applied"}
+ )
+ )
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_alertmanager_config())
+
+ def test_delete_alertmanager_config_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.delete_alertmanager_config("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_alertmanager_config_deletion_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"config": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_alertmanager_config()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_config(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"alertmanager_config": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"alertmanager_config": "test"}),
+ alerting.get_alertmanager_config(),
+ )
+
+ def test_get_alertmanager_config_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alertmanager_config("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alertmanager_config_no_config(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"config": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alertmanager_config()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_alertmanager_config(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alertmanager_config: AlertmanagerConfig = AlertmanagerConfig(
+ {"test": "test"}, ["test"], ["test"], ["test"], {"test": "test"}, ["test"]
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "configuration created"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None,
+ alerting.create_or_update_alertmanager_config(
+ alertmanager_config, template_files={"test": "test"}
+ ),
+ )
+
+ def test_create_or_update_alertmanager_config_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.create_or_update_alertmanager_config(None)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_alertmanager_config_creation_not_possible(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alertmanager_config: AlertmanagerConfig = AlertmanagerConfig(
+ {"test": "test"}, ["test"], ["test"], ["test"], {"test": "test"}, ["test"]
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"alertmanager_config": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.create_or_update_alertmanager_config(alertmanager_config)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_alertmanager_receivers(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alertmanager_receivers: AlertmanagerReceivers = AlertmanagerReceivers(
+ "test",
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ )
+
+ call_the_api_mock.return_value.status_code = 200
+
+ self.assertEqual(
+ None,
+ alerting.test_alertmanager_receivers(
+ {"test": "test"}, list([alertmanager_receivers])
+ ),
+ )
+
+ def test_test_alertmanager_receivers_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.test_alertmanager_receivers(dict(), None, "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_alertmanager_receivers_test_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alertmanager_receivers: AlertmanagerReceivers = AlertmanagerReceivers(
+ "test",
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ )
+
+ call_the_api_mock.return_value.status_code = 600
+
+ with self.assertRaises(Exception):
+ alerting.test_alertmanager_receivers(
+ {"test": "test"}, alertmanager_receivers
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_alertmanager_receivers_test_not_found(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ alertmanager_receivers: AlertmanagerReceivers = AlertmanagerReceivers(
+ "test",
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ ["test"],
+ )
+
+ call_the_api_mock.return_value.status_code = 404
+
+ with self.assertRaises(Exception):
+ alerting.test_alertmanager_receivers(
+ {"test": "test"}, alertmanager_receivers
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_prometheus_alerts(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"data": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(dict({"data": "test"}), alerting.get_prometheus_alerts())
+
+ def test_get_prometheus_alerts_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_prometheus_alerts("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_prometheus_alerts_no_alerts_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"data": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_prometheus_alerts()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_prometheus_rules(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"data": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(dict({"data": "test"}), alerting.get_prometheus_rules())
+
+ def test_get_prometheus_rules_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_prometheus_rules("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_prometheus_rules_no_rules_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"data": None}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_prometheus_rules("grafana")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ruler_rules(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"data": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(dict({"data": "test"}), alerting.get_ruler_rules())
+
+ def test_get_ruler_rules_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_ruler_rules("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ruler_rules_no_rules_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_ruler_rules()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_ruler_namespace(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_ruler_namespace("test"))
+
+ def test_delete_ruler_namespace_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.delete_ruler_namespace("", "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_ruler_namespace_deletion_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_ruler_namespace("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ruler_groups_by_namespace(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"test": "test"}),
+ alerting.get_ruler_groups_by_namespace("test"),
+ )
+
+ def test_get_ruler_groups_by_namespace_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_ruler_groups_by_namespace("", "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ruler_groups_by_namespace_no_groups_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_ruler_groups_by_namespace("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_ruler_group_by_namespace(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ ruler_rule: RulerRule = RulerRule(
+ "test", {"test": "test"}, "test", {"test": "test"}, {"test": "test"}, "test"
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None,
+ alerting.create_or_update_ruler_group_by_namespace(
+ "test", "test", [ruler_rule]
+ ),
+ )
+
+ def test_create_or_update_ruler_group_by_namespace_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.create_or_update_ruler_group_by_namespace("", "", None, "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_ruler_group_by_namespace_creation_not_possible(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ ruler_rule: RulerRule = RulerRule(
+ "test", {"test": "test"}, "test", {"test": "test"}, {"test": "test"}, "test"
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.create_or_update_ruler_group_by_namespace(
+ "test", "test", [ruler_rule]
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_ruler_group(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_ruler_group("test", "test"))
+
+ def test_delete_ruler_group_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.delete_ruler_group("", "", "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_ruler_group_deletion_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_ruler_group("test", "test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ruler_group(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"test": "test"}), alerting.get_ruler_group("test", "test")
+ )
+
+ def test_get_ruler_group_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_ruler_group("", "", "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ruler_group_no_ruler_group_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_ruler_group("test", "test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_rule(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
+ "test", {"test": "test"}, "test", "test", {"test": "test"}
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(dict({"test": "test"}), alerting.test_rule([datasource_rule_query]))
+
+ def test_test_rule_no_data_query(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.test_rule(list())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_rule_test_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
+ "test", {"test": "test"}, "test", "test", {"test": "test"}
+ )
+
+ mock: Mock = Mock()
+ mock.text = Mock(return_value="")
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.test_rule([datasource_rule_query])
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_recipient_rule(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
+ "test", {"test": "test"}, "test", "test", {"test": "test"}
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"test": "test"}),
+ alerting.test_recipient_rule("test", "test", [datasource_rule_query]),
+ )
+
+ def test_test_recipient_rule_no_recipient(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.test_recipient_rule("", "", list(), "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_recipient_rule_test_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+ datasource_rule_query: DatasourceRuleQuery = DatasourceRuleQuery(
+ "test", {"test": "test"}, "test", "test", {"test": "test"}
+ )
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.test_recipient_rule("test", "test", [datasource_rule_query])
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_ngalert_organization_configuration(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_ngalert_organization_configuration())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_ngalert_organization_configuration_deletion_not_possible(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_ngalert_organization_configuration()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ngalert_organization_configuration(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ call_the_api_mock.return_value.status_code = 200
+ call_the_api_mock.return_value.json = Mock(return_value=dict({"test": "test"}))
+
+ self.assertEqual(
+ dict({"test": "test"}), alerting.get_ngalert_organization_configuration()
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ngalert_organization_configuration_no_configuration_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ call_the_api_mock.return_value.status_code = 404
+
+ with self.assertRaises(Exception):
+ alerting.get_ngalert_organization_configuration()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ngalert_organization_configuration_general_exception(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ call_the_api_mock.return_value.status_code = 600
+
+ with self.assertRaises(Exception):
+ alerting.get_ngalert_organization_configuration()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_ngalert_organization_configuration(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None,
+ alerting.create_or_update_ngalert_organization_configuration(["test"]),
+ )
+
+ def test_create_or_update_ngalert_organization_configuration_no_alert_managers(
+ self,
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.create_or_update_ngalert_organization_configuration(list(), "")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_or_update_ngalert_organization_configuration_no_configuration_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.create_or_update_ngalert_organization_configuration(["test"])
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ngalert_alertmanagers_by_organization(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"test": "test"}), alerting.get_ngalert_alertmanagers_by_organization()
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_ngalert_alertmanagers_by_organization_no_configuration_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_ngalert_alertmanagers_by_organization()
diff --git a/tests/unittests/test_alerting_notifications.py b/tests/unittests/test_alerting_notifications.py
new file mode 100644
index 0000000..9a59e76
--- /dev/null
+++ b/tests/unittests/test_alerting_notifications.py
@@ -0,0 +1,352 @@
+from unittest import TestCase
+from unittest.mock import MagicMock, Mock, patch
+
+from src.grafana_api.model import APIModel
+from src.grafana_api.alerting_notifications import AlertingNotifications
+
+
+class AlertingNotificationsTestCase(TestCase):
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_all_notification_channels(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([dict({"id": 1})]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ list([dict({"id": 1})]), alerting.get_all_notification_channels()
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_all_notification_channels_no_notification_channels_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_all_notification_channels()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_all_notification_channels_lookup(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([dict({"id": 1})]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ list([dict({"id": 1})]), alerting.get_all_notification_channels_lookup()
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_all_notification_channels_lookup_no_notification_channels_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_all_notification_channels_lookup()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_notification_channel_by_uid(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}), alerting.get_notification_channel_by_uid("test")
+ )
+
+ def test_get_notification_channel_by_uid_no_uid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_notification_channel_by_uid("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_notification_channel_by_uid_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_notification_channel_by_uid("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_notification_channel_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}), alerting.get_notification_channel_by_id(1)
+ )
+
+ def test_get_notification_channel_by_id_no_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_notification_channel_by_id(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_notification_channel_by_id_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_notification_channel_by_id(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_notification_channel(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}),
+ alerting.create_notification_channel(dict({"test": "test"})),
+ )
+
+ def test_create_notification_channel_no_notification_channel(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.create_notification_channel(dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_notification_channel_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.create_notification_channel(dict({"test": "test"}))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_update_notification_channel_by_uid(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}),
+ alerting.update_notification_channel_by_uid("test", dict({"test": "test"})),
+ )
+
+ def test_update_notification_channel_by_uid_no_uid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.update_notification_channel_by_uid("", dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_update_notification_channel_by_uid_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.update_notification_channel_by_uid("test", dict({"test": "test"}))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_update_notification_channel_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"id": "test"}),
+ alerting.update_notification_channel_by_id(1, dict({"test": "test"})),
+ )
+
+ def test_update_notification_channel_by_id_no_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.update_notification_channel_by_id(0, dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_update_notification_channel_by_id_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.update_notification_channel_by_id(1, dict({"test": "test"}))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_notification_channel_by_uid(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Notification deleted"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_notification_channel_by_uid("test"))
+
+ def test_delete_notification_channel_by_uid_no_uid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.delete_notification_channel_by_uid("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_notification_channel_by_uid_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_notification_channel_by_uid("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_notification_channel_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Notification deleted"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.delete_notification_channel_by_id(1))
+
+ def test_delete_notification_channel_by_id_no_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.delete_notification_channel_by_id(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_notification_channel_by_id_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.delete_notification_channel_by_id(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_notification_channel(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Test notification sent"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None, alerting.test_notification_channel(dict({"test": "test"}))
+ )
+
+ def test_test_notification_channel_no_notification_channel(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.test_notification_channel(dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_test_notification_channel_no_notification_channel_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: AlertingNotifications = AlertingNotifications(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.test_notification_channel(dict({"test": "test"}))
diff --git a/tests/unittests/test_api.py b/tests/unittests/test_api.py
new file mode 100644
index 0000000..e9497ab
--- /dev/null
+++ b/tests/unittests/test_api.py
@@ -0,0 +1,179 @@
+import requests
+
+from unittest import TestCase
+from unittest.mock import MagicMock, patch, Mock
+
+from requests.exceptions import MissingSchema
+
+from src.grafana_api.model import APIModel, RequestsMethods
+from src.grafana_api.api import Api
+
+
+class ApiTestCase(TestCase):
+ def test_call_the_api_non_method(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(Exception):
+ api.call_the_api(api_call=MagicMock(), method=None)
+
+ def test_call_the_api_non_valid_method(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(Exception):
+ api.call_the_api(api_call=MagicMock(), method=MagicMock())
+
+ @patch("requests.get")
+ def test_call_the_api_get_valid(self, get_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value={"status": "success"})
+
+ get_mock.return_value = mock
+
+ self.assertEqual(
+ "success",
+ api.call_the_api(api_call=MagicMock()).json()["status"],
+ )
+
+ def test_call_the_api_get_not_valid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(MissingSchema):
+ api.call_the_api(api_call=MagicMock(), method=RequestsMethods.GET)
+
+ @patch("requests.put")
+ def test_call_the_api_put_valid(self, put_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value={"status": "success"})
+
+ put_mock.return_value = mock
+
+ self.assertEqual(
+ "success",
+ api.call_the_api(
+ api_call=MagicMock(),
+ method=RequestsMethods.PUT,
+ json_complete=MagicMock(),
+ ).json()["status"],
+ )
+
+ def test_call_the_api_put_not_valid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(Exception):
+ api.call_the_api(api_call=MagicMock(), method=RequestsMethods.PUT)
+
+ @patch("requests.post")
+ def test_call_the_api_post_valid(self, post_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value={"status": "success"})
+
+ post_mock.return_value = mock
+
+ self.assertEqual(
+ "success",
+ api.call_the_api(
+ api_call=MagicMock(),
+ method=RequestsMethods.POST,
+ json_complete=MagicMock(),
+ ).json()["status"],
+ )
+
+ def test_call_the_api_post_not_valid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(MissingSchema):
+ api.call_the_api(
+ api_call=MagicMock(),
+ method=RequestsMethods.POST,
+ json_complete=MagicMock(),
+ )
+
+ def test_call_the_api_post_no_data(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(Exception):
+ api.call_the_api(api_call=MagicMock(), method=RequestsMethods.POST)
+
+ @patch("requests.delete")
+ def test_call_the_api_delete_valid(self, delete_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value={"message": "Deletion successful"})
+
+ delete_mock.return_value = mock
+
+ self.assertEqual(
+ "Deletion successful",
+ api.call_the_api(
+ api_call=MagicMock(), method=RequestsMethods.DELETE
+ ).json()["message"],
+ )
+
+ def test_call_the_api_delete_not_valid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ with self.assertRaises(Exception):
+ api.call_the_api(api_call=MagicMock(), method=RequestsMethods.DELETE)
+
+ def test_check_the_api_call_response(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"test": "test"}))
+
+ self.assertEqual(
+ dict({"test": "test"}),
+ api._Api__check_the_api_call_response(response=mock).json(),
+ )
+
+ def test_check_the_api_call_response_no_error_message(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "test"}))
+
+ self.assertEqual(
+ dict({"message": "test"}),
+ api._Api__check_the_api_call_response(response=mock).json(),
+ )
+
+ def test_check_the_api_call_response_no_json_response_value(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.text = Mock(return_value="test")
+
+ self.assertEqual(
+ "test", api._Api__check_the_api_call_response(response=mock).text()
+ )
+
+ def test_check_the_api_call_response_exception(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ api: Api = Api(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "invalid API key"}))
+
+ with self.assertRaises(requests.exceptions.ConnectionError):
+ api._Api__check_the_api_call_response(response=mock)
diff --git a/tests/unittests/test_dashboard.py b/tests/unittests/test_dashboard.py
index a6731a3..c8a999e 100644
--- a/tests/unittests/test_dashboard.py
+++ b/tests/unittests/test_dashboard.py
@@ -1,12 +1,12 @@
from unittest import TestCase
-from unittest.mock import MagicMock, patch
+from unittest.mock import MagicMock, Mock, patch
from src.grafana_api.model import APIModel
from src.grafana_api.dashboard import Dashboard
class DashboardTestCase(TestCase):
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
@patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
def test_create_or_update_dashboard(
self, folder_id_by_dashboard_path_mock, call_the_api_mock
@@ -15,7 +15,12 @@ def test_create_or_update_dashboard(
dashboard: Dashboard = Dashboard(grafana_api_model=model)
folder_id_by_dashboard_path_mock.return_value = 1
- call_the_api_mock.return_value = dict({"status": "success"})
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"status": "success"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
None,
dashboard.create_or_update_dashboard(
@@ -34,7 +39,7 @@ def test_create_or_update_dashboard_no_dashboard_path_defined(self):
dashboard_path="", dashboard_json=dict({"test": "test"}), message="test"
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
@patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
def test_create_or_update_dashboard_update_not_possible(
self, folder_id_by_dashboard_path_mock, call_the_api_mock
@@ -43,7 +48,12 @@ def test_create_or_update_dashboard_update_not_possible(
dashboard: Dashboard = Dashboard(grafana_api_model=model)
folder_id_by_dashboard_path_mock.return_value = 1
- call_the_api_mock.return_value = dict({"status": "error"})
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"status": "error"}))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.create_or_update_dashboard(
dashboard_path="test",
@@ -51,7 +61,7 @@ def test_create_or_update_dashboard_update_not_possible(
message="test",
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
@patch(
"src.grafana_api.dashboard.Dashboard.get_dashboard_uid_and_id_by_name_and_folder"
)
@@ -64,7 +74,12 @@ def test_delete_dashboard_by_name_and_path(
dashboard_uid_and_id_by_name_and_folder_mock.return_value = dict(
{"uid": "test", "id": 10}
)
- call_the_api_mock.return_value = dict({"message": "Dashboard test deleted"})
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Dashboard test deleted"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
None,
dashboard.delete_dashboard_by_name_and_path(
@@ -83,7 +98,7 @@ def test_delete_dashboard_by_name_and_path_no_dashboard_name(
dashboard_name="", dashboard_path="test"
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
@patch(
"src.grafana_api.dashboard.Dashboard.get_dashboard_uid_and_id_by_name_and_folder"
)
@@ -100,7 +115,24 @@ def test_delete_dashboard_by_name_and_path_deletion_list_empty(
dashboard_name="test", dashboard_path="test"
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
+ @patch(
+ "src.grafana_api.dashboard.Dashboard.get_dashboard_uid_and_id_by_name_and_folder"
+ )
+ def test_delete_dashboard_by_name_and_path_dashboard_uid_id_is_none(
+ self, dashboard_uid_and_id_by_name_and_folder_mock, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ dashboard: Dashboard = Dashboard(grafana_api_model=model)
+
+ dashboard_uid_and_id_by_name_and_folder_mock.return_value = None
+ call_the_api_mock.return_value = dict({"message": "error"})
+ with self.assertRaises(TypeError):
+ dashboard.delete_dashboard_by_name_and_path(
+ dashboard_name="test", dashboard_path="test"
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
@patch(
"src.grafana_api.dashboard.Dashboard.get_dashboard_uid_and_id_by_name_and_folder"
)
@@ -113,13 +145,18 @@ def test_delete_dashboard_by_name_and_path_deletion_not_possible(
dashboard_uid_and_id_by_name_and_folder_mock.return_value = dict(
{"uid": "test", "id": 10}
)
- call_the_api_mock.return_value = dict({"message": "error"})
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "error"}))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.delete_dashboard_by_name_and_path(
dashboard_name="test", dashboard_path="test"
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
@patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
def test_get_dashboard_uid_and_id_by_name_and_folder(
self, folder_id_by_dashboard_path_mock, call_the_api_mock
@@ -128,7 +165,14 @@ def test_get_dashboard_uid_and_id_by_name_and_folder(
dashboard: Dashboard = Dashboard(grafana_api_model=model)
folder_id_by_dashboard_path_mock.return_value = 1
- call_the_api_mock.return_value = [{"uid": "test", "id": 10}]
+
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=list([{"uid": "test", "title": "test", "id": 10}])
+ )
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
dict({"uid": "test", "id": 10}),
dashboard.get_dashboard_uid_and_id_by_name_and_folder(
@@ -136,7 +180,93 @@ def test_get_dashboard_uid_and_id_by_name_and_folder(
),
)
- def test_get_dashboard_uid_and_id_by_name_and_folder_bo_dashboard_name_defined(
+ @patch("src.grafana_api.api.Api.call_the_api")
+ @patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
+ def test_get_dashboard_uid_and_id_by_name_and_folder_no_id_inside_dashboard_meta_object(
+ self, folder_id_by_dashboard_path_mock, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ dashboard: Dashboard = Dashboard(grafana_api_model=model)
+
+ folder_id_by_dashboard_path_mock.return_value = 1
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"uid": "test", "title": "test"}]))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(ValueError):
+ dashboard.get_dashboard_uid_and_id_by_name_and_folder(
+ dashboard_name="test", dashboard_path="test"
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ @patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
+ def test_get_dashboard_uid_and_id_by_name_and_folder_no_title_inside_dashboard_meta_object(
+ self, folder_id_by_dashboard_path_mock, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ dashboard: Dashboard = Dashboard(grafana_api_model=model)
+
+ folder_id_by_dashboard_path_mock.return_value = 1
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"uid": "test", "id": 1}]))
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(ValueError):
+ dashboard.get_dashboard_uid_and_id_by_name_and_folder(
+ dashboard_name="test", dashboard_path="test"
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ @patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
+ def test_get_dashboard_uid_and_id_by_name_and_folder_no_matched_title_inside_dashboard_meta_object(
+ self, folder_id_by_dashboard_path_mock, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ dashboard: Dashboard = Dashboard(grafana_api_model=model)
+
+ folder_id_by_dashboard_path_mock.return_value = 1
+
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=list([{"uid": "test", "title": "test123", "id": 1}])
+ )
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None,
+ dashboard.get_dashboard_uid_and_id_by_name_and_folder(
+ dashboard_name="test", dashboard_path="test"
+ ),
+ )
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ @patch("src.grafana_api.folder.Folder.get_folder_id_by_dashboard_path")
+ def test_get_dashboard_uid_and_id_by_name_and_folder_empty_result(
+ self, folder_id_by_dashboard_path_mock, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ dashboard: Dashboard = Dashboard(grafana_api_model=model)
+
+ folder_id_by_dashboard_path_mock.return_value = 1
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None,
+ dashboard.get_dashboard_uid_and_id_by_name_and_folder(
+ dashboard_name="test", dashboard_path="test"
+ ),
+ )
+
+ def test_get_dashboard_uid_and_id_by_name_and_folder_no_dashboard_name_defined(
self,
):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
@@ -147,22 +277,30 @@ def test_get_dashboard_uid_and_id_by_name_and_folder_bo_dashboard_name_defined(
dashboard_name="", dashboard_path="test"
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_by_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"dashboard": "test"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"dashboard": "test"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
dict({"dashboard": "test"}), dashboard.get_dashboard_by_uid(uid="test")
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_by_uid_no_dashboard(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.get_dashboard_by_uid(uid="test")
@@ -173,59 +311,83 @@ def test_get_dashboard_by_uid_no_uid(self):
with self.assertRaises(ValueError):
dashboard.get_dashboard_by_uid(uid="")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_home(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"dashboard": "test"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"dashboard": "test"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(dict({"dashboard": "test"}), dashboard.get_dashboard_home())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_home_no_dashboard(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.get_dashboard_home()
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_tags(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = list([{"term": "test", "count": 4}])
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"term": "test", "count": 4}]))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
list([{"term": "test", "count": 4}]), dashboard.get_dashboard_tags()
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_tags_no_tags(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = list()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.get_dashboard_tags()
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_permissions(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = list([{"role": "test", "count": 4}])
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"role": "test", "count": 4}]))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
list([{"role": "test", "count": 4}]),
dashboard.get_dashboard_permissions(1),
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_permissions_empty_list(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = list()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.get_dashboard_permissions(1)
@@ -236,24 +398,32 @@ def test_get_dashboard_permissions_no_id(self):
with self.assertRaises(ValueError):
dashboard.get_dashboard_permissions(0)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_dashboard_permissions(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict(
- {"message": "Dashboard permissions updated"}
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=dict({"message": "Dashboard permissions updated"})
)
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
None, dashboard.update_dashboard_permissions(1, {"test": "test"})
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_dashboard_permissions_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"message": "Error"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Error"}))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.update_dashboard_permissions(1, {"test": "test"})
@@ -264,20 +434,28 @@ def test_update_dashboard_permissions_no_uid(self):
with self.assertRaises(ValueError):
dashboard.update_dashboard_permissions(0, MagicMock())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_versions(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = list([{"id": "test"}])
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"id": "test"}]))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(list([{"id": "test"}]), dashboard.get_dashboard_versions(1))
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_versions_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = list()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.get_dashboard_versions(1)
@@ -288,20 +466,28 @@ def test_get_dashboard_versions_no_uid(self):
with self.assertRaises(ValueError):
dashboard.get_dashboard_versions(0)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_version(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"id": "test"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(dict({"id": "test"}), dashboard.get_dashboard_version(1, 10))
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_dashboard_version_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.get_dashboard_version(1, MagicMock())
@@ -312,22 +498,30 @@ def test_get_dashboard_version_no_uid(self):
with self.assertRaises(ValueError):
dashboard.get_dashboard_version(0, MagicMock())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_restore_dashboard_version(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"status": "success"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"status": "success"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
None, dashboard.restore_dashboard_version(1, dict({"version": 1}))
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_restore_dashboard_version_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"status": "error"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"status": "error"}))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
dashboard.restore_dashboard_version(1, dict({"version": 1}))
@@ -338,7 +532,7 @@ def test_restore_dashboard_version_no_uid(self):
with self.assertRaises(ValueError):
dashboard.restore_dashboard_version(0, MagicMock())
- @patch("src.grafana_api.utils.Utils.call_the_api_non_json_output")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_calculate_dashboard_diff(self, call_the_api_non_json_output_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
dashboard: Dashboard = Dashboard(grafana_api_model=model)
@@ -353,7 +547,7 @@ def test_calculate_dashboard_diff(self, call_the_api_non_json_output_mock):
),
)
- @patch("src.grafana_api.utils.Utils.call_the_api_non_json_output")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_calculate_dashboard_diff_error_response(
self, call_the_api_non_json_output_mock
):
diff --git a/tests/unittests/test_datasource.py b/tests/unittests/test_datasource.py
new file mode 100644
index 0000000..3d9cd23
--- /dev/null
+++ b/tests/unittests/test_datasource.py
@@ -0,0 +1,539 @@
+from unittest import TestCase
+from unittest.mock import MagicMock, Mock, patch
+
+from src.grafana_api.model import APIModel, DatasourceQuery
+from src.grafana_api.datasource import Datasource
+
+
+class DatasourceTestCase(TestCase):
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_all_datasources(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"id": 1}]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual([{"id": 1}], datasource.get_all_datasources())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_all_datasources_no_datasources(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.get_all_datasources()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": 1}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual({"id": 1}, datasource.get_datasource_by_id(1))
+
+ def test_get_datasource_by_id_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.get_datasource_by_id(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_by_id_no_datasource_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.get_datasource_by_id(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_by_uid(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": 1}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual({"id": 1}, datasource.get_datasource_by_uid("test"))
+
+ def test_get_datasource_by_uid_no_uid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.get_datasource_by_uid("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_by_uid_no_datasource_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.get_datasource_by_uid("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_by_name(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": 1}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual({"id": 1}, datasource.get_datasource_by_name("test"))
+
+ def test_get_datasource_by_name_no_name(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.get_datasource_by_name("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_by_name_no_datasource_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.get_datasource_by_name("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_id_by_name(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": 1}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(1, datasource.get_datasource_id_by_name("test"))
+
+ def test_get_datasource_id_by_name_no_name(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.get_datasource_id_by_name("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_id_by_name_no_id_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.get_datasource_id_by_name("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_datasource(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Datasource added"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.create_datasource(dict({"test": "test"})))
+
+ def test_create_datasource_no_data_source(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.create_datasource(dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_create_datasource_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.create_datasource(dict({"test": "test"}))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_update_datasource(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Datasource updated"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.update_datasource(1, dict({"test": "test"})))
+
+ def test_update_datasource_no_data_source(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.update_datasource(1, dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_update_datasource_update_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.update_datasource(1, dict({"test": "test"}))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Data source deleted"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.delete_datasource_by_id(1))
+
+ def test_delete_datasource_by_id_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.delete_datasource_by_id(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_by_id_delete_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.delete_datasource_by_id(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_by_uid(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Data source deleted"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.delete_datasource_by_uid("test"))
+
+ def test_delete_datasource_by_uid_no_datasource_uid(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.delete_datasource_by_uid("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_by_uid_delete_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.delete_datasource_by_uid("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_by_name(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Data source deleted"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.delete_datasource_by_name("test"))
+
+ def test_delete_datasource_by_name_no_name(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.delete_datasource_by_name("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_by_name_delete_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.delete_datasource_by_name("test")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_query_datasource_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"results": dict({"test": "test"})}))
+
+ call_the_api_mock.return_value = mock
+
+ datasource_query: DatasourceQuery = DatasourceQuery(1, "test")
+ datasource_queries: list = list()
+ datasource_queries.append(datasource_query)
+
+ self.assertEqual(
+ dict({"test": "test"}),
+ datasource.query_datasource_by_id("1234", "1234", datasource_queries),
+ )
+
+ def test_query_datasource_by_id_no_time(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.query_datasource_by_id("", "", MagicMock())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_query_datasource_by_id_no_query_result(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ datasource_query: DatasourceQuery = DatasourceQuery(1, "test")
+ datasource_queries: list = list()
+ datasource_queries.append(datasource_query)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.query_datasource_by_id("1234", "1234", datasource_queries)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_enable_datasource_permissions(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=dict({"message": "Datasource permissions enabled"})
+ )
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.enable_datasource_permissions(1))
+
+ def test_enable_datasource_permissions_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.enable_datasource_permissions(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_enable_datasource_permissions_enable_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.enable_datasource_permissions(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_disable_datasource_permissions(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=dict({"message": "Datasource permissions disabled"})
+ )
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.disable_datasource_permissions(1))
+
+ def test_disable_datasource_permissions_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.disable_datasource_permissions(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_disable_datasource_permissions_disable_not_possible(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.disable_datasource_permissions(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_permissions(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"datasourceId": "Test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ dict({"datasourceId": "Test"}), datasource.get_datasource_permissions(1)
+ )
+
+ def test_get_datasource_permissions_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.get_datasource_permissions(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_datasource_permissions_no_datasource_permissions_available(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.get_datasource_permissions(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_add_datasource_permissions(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Datasource permission added"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ None, datasource.add_datasource_permissions(1, dict({"test": "test"}))
+ )
+
+ def test_add_datasource_permissions_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.add_datasource_permissions(0, dict())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_add_datasource_permissions_permission_add_not_possible(
+ self, call_the_api_mock
+ ):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.add_datasource_permissions(1, dict({"test": "test"}))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_permissions(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=dict({"message": "Datasource permission removed"})
+ )
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, datasource.delete_datasource_permissions(1, 1))
+
+ def test_delete_datasource_permissions_no_datasource_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ datasource.delete_datasource_permissions(0, 1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_delete_datasource_permissions_delete_not_possible(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ datasource: Datasource = Datasource(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ datasource.delete_datasource_permissions(1, 1)
diff --git a/tests/unittests/test_folder.py b/tests/unittests/test_folder.py
index 9f5efa5..95851e8 100644
--- a/tests/unittests/test_folder.py
+++ b/tests/unittests/test_folder.py
@@ -1,205 +1,289 @@
from unittest import TestCase
-from unittest.mock import MagicMock, patch
+from unittest.mock import MagicMock, Mock, patch
from src.grafana_api.model import APIModel
from src.grafana_api.folder import Folder
class FolderTestCase(TestCase):
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folders(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = list([{"title": None, "id": 12}])
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"title": None, "id": 12}]))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(list([{"title": None, "id": 12}]), folder.get_folders())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folders_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = list()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.get_folders()
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_by_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": None, "id": 12})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": None, "id": 12}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
dict({"title": None, "id": 12}), folder.get_folder_by_uid("xty13y")
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_by_uid_no_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(ValueError):
folder.get_folder_by_uid("")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_by_uid_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.get_folder_by_uid("xty13y")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_by_id(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": None, "id": 12})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": None, "id": 12}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(dict({"title": None, "id": 12}), folder.get_folder_by_id(12))
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_by_id_no_id(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(ValueError):
folder.get_folder_by_id(0)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_by_id_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.get_folder_by_id(10)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_create_folder(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": None, "id": 12})
- self.assertEqual(
- dict({"title": None, "id": 12}), folder.create_folder("test")
- )
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": None, "id": 12}))
+
+ call_the_api_mock.return_value = mock
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ self.assertEqual(dict({"title": None, "id": 12}), folder.create_folder("test"))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_create_folder_specified_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": None, "id": 12, "uid": "test"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": None, "id": 12, "uid": "test"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
- dict({"title": None, "id": 12, "uid": "test"}), folder.create_folder("test", "test")
+ dict({"title": None, "id": 12, "uid": "test"}),
+ folder.create_folder("test", "test"),
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_create_folder_no_title(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(ValueError):
folder.create_folder(MagicMock())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_create_folder_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.create_folder("test")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": "test1", "id": 12})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": "test1", "id": 12}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
- dict({"title": "test1", "id": 12}), folder.update_folder("test", "test1", 10)
+ dict({"title": "test1", "id": 12}),
+ folder.update_folder("test", "test1", 10),
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_no_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": "test", "id": 12})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": "test", "id": 12}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
dict({"title": "test", "id": 12}),
folder.update_folder("test", overwrite=True),
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_overwrite_true(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"title": "test", "id": 12})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"title": "test", "id": 12}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
dict({"title": "test", "id": 12}),
folder.update_folder("test", "test", overwrite=True),
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_no_title(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(ValueError):
folder.update_folder(MagicMock(), MagicMock())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.update_folder("test", "test", 10)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_delete_folder(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"message": "Folder deleted"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Folder deleted"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(None, folder.delete_folder("test"))
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_delete_folder_no_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(ValueError):
folder.delete_folder("")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_delete_folder_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"message": "error"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "error"}))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.delete_folder("test")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_permissions(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = list([{"id": "test"}])
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"id": "test"}]))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(list([{"id": "test"}]), folder.get_folder_permissions("test"))
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_permissions_no_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
@@ -208,26 +292,34 @@ def test_get_folder_permissions_no_uid(self, call_the_api_mock):
with self.assertRaises(ValueError):
folder.get_folder_permissions("")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_folder_permissions_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = list([{"test": "test"}])
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([{"test": "test"}]))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.get_folder_permissions("test")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_permissions(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"message": "Folder permissions updated"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "Folder permissions updated"}))
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
None, folder.update_folder_permissions("test", dict({"test": "test"}))
)
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_permissions_no_uid(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
@@ -236,12 +328,16 @@ def test_update_folder_permissions_no_uid(self, call_the_api_mock):
with self.assertRaises(ValueError):
folder.update_folder_permissions("", dict())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_update_folder_permissions_error_response(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = dict({"message": "test"})
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "test"}))
+
+ call_the_api_mock.return_value = mock
+
with self.assertRaises(Exception):
folder.update_folder_permissions("test", dict({"test": "test"}))
@@ -255,6 +351,14 @@ def test_get_folder_id_by_dashboard_path(self, all_folder_ids_and_names_mock):
12, folder.get_folder_id_by_dashboard_path(dashboard_path="test")
)
+ def test_get_folder_id_by_dashboard_path_general_path(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ folder: Folder = Folder(grafana_api_model=model)
+
+ self.assertEqual(
+ 0, folder.get_folder_id_by_dashboard_path(dashboard_path="General")
+ )
+
def test_get_folder_id_by_dashboard_path_no_dashboard_path_defined(self):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
@@ -275,14 +379,18 @@ def test_get_folder_id_by_dashboard_path_no_title_match(
with self.assertRaises(Exception):
folder.get_folder_id_by_dashboard_path(dashboard_path="test")
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_get_all_folder_ids_and_names(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
folder: Folder = Folder(grafana_api_model=model)
- call_the_api_mock.return_value = list(
- [{"title": "test", "id": 12, "test": "test"}]
+ mock: Mock = Mock()
+ mock.json = Mock(
+ return_value=list([{"title": "test", "id": 12, "test": "test"}])
)
+
+ call_the_api_mock.return_value = mock
+
self.assertEqual(
list([{"title": "test", "id": 12}]), folder.get_all_folder_ids_and_names()
)
diff --git a/tests/unittests/test_legacy_alerting.py b/tests/unittests/test_legacy_alerting.py
new file mode 100644
index 0000000..e52ca11
--- /dev/null
+++ b/tests/unittests/test_legacy_alerting.py
@@ -0,0 +1,150 @@
+from unittest import TestCase
+from unittest.mock import MagicMock, Mock, patch
+
+from src.grafana_api.model import APIModel
+from src.grafana_api.legacy_alerting import Alerting
+
+
+class LegacyAlertingTestCase(TestCase):
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alerts(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([dict({"id": "test"})]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(list([dict({"id": "test"})]), alerting.get_alerts())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alerts_custom_querystring(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([dict({"id": "test"})]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(list([dict({"id": "test"})]), alerting.get_alerts("test"))
+
+ def test_get_alerts_empty_api_string(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alerts("")
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alerts_no_alerts_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alerts()
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alerts_by_dashboard_ids(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list([dict({"id": "test"})]))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(
+ list([dict({"id": "test"})]),
+ alerting.get_alerts_by_dashboard_ids(list([1, 2])),
+ )
+
+ def test_get_alerts_by_dashboard_ids_no_dashboard_ids(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alerts_by_dashboard_ids(list())
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alerts_by_dashboard_ids_no_alerts_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alerts_by_dashboard_ids(list([1, 2]))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alert_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"id": "test"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(dict({"id": "test"}), alerting.get_alert_by_id(1))
+
+ def test_get_alert_by_id_no_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.get_alert_by_id(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_get_alert_by_id_no_alerts_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.get_alert_by_id(1)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_pause_alert_by_id(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict({"message": "alert paused"}))
+
+ call_the_api_mock.return_value = mock
+
+ self.assertEqual(None, alerting.pause_alert_by_id(1))
+
+ def test_pause_alert_by_id_no_id(self):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ with self.assertRaises(ValueError):
+ alerting.pause_alert_by_id(0)
+
+ @patch("src.grafana_api.api.Api.call_the_api")
+ def test_pause_alert_by_id_no_alerts_available(self, call_the_api_mock):
+ model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
+ alerting: Alerting = Alerting(grafana_api_model=model)
+
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=dict())
+
+ call_the_api_mock.return_value = mock
+
+ with self.assertRaises(Exception):
+ alerting.pause_alert_by_id(1)
diff --git a/tests/unittests/test_model.py b/tests/unittests/test_model.py
index 3807ab2..ebe38df 100644
--- a/tests/unittests/test_model.py
+++ b/tests/unittests/test_model.py
@@ -1,6 +1,11 @@
from unittest import TestCase
-from src.grafana_api.model import APIModel, RequestsMethods, APIEndpoints
+from src.grafana_api.model import (
+ APIModel,
+ RequestsMethods,
+ APIEndpoints,
+ DatasourceQuery,
+)
class APIEndpointsTestCase(TestCase):
@@ -22,3 +27,15 @@ def test_api_model_init(self):
self.assertEqual("test", model.host)
self.assertEqual("test", model.token)
+
+
+class DatasourceQueryTestCase(TestCase):
+ def test_datasource_query_init(self):
+ datasource_query = DatasourceQuery(datasource_id=1, raw_sql="TEST")
+
+ self.assertEqual(1, datasource_query.datasource_id)
+ self.assertEqual("TEST", datasource_query.raw_sql)
+ self.assertEqual("A", datasource_query.ref_id)
+ self.assertEqual(1000, datasource_query.interval_ms)
+ self.assertEqual(100, datasource_query.max_data_points)
+ self.assertEqual("time_series", datasource_query.output_format)
diff --git a/tests/unittests/test_search.py b/tests/unittests/test_search.py
index b9bf11e..bbbcebc 100644
--- a/tests/unittests/test_search.py
+++ b/tests/unittests/test_search.py
@@ -1,31 +1,37 @@
from unittest import TestCase
-from unittest.mock import MagicMock, patch
+from unittest.mock import MagicMock, Mock, patch
from src.grafana_api.model import APIModel
from src.grafana_api.search import Search
class SearchTestCase(TestCase):
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_search(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
search: Search = Search(grafana_api_model=model)
- call_the_api_mock.return_value = ["test"]
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list(["test"]))
- self.assertEqual(["test"], search.search(search_query=MagicMock()))
+ call_the_api_mock.return_value = mock
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ self.assertEqual(["test"], search.search(search_query="Test"))
+
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_search_invalid_empty_list(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
search: Search = Search(grafana_api_model=model)
- call_the_api_mock.return_value = list()
+ mock: Mock = Mock()
+ mock.json = Mock(return_value=list())
+
+ call_the_api_mock.return_value = mock
with self.assertRaises(Exception):
search.search(search_query=MagicMock())
- @patch("src.grafana_api.utils.Utils.call_the_api")
+ @patch("src.grafana_api.api.Api.call_the_api")
def test_search_invalid_output(self, call_the_api_mock):
model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
search: Search = Search(grafana_api_model=model)
diff --git a/tests/unittests/test_utils.py b/tests/unittests/test_utils.py
deleted file mode 100644
index 28a9b25..0000000
--- a/tests/unittests/test_utils.py
+++ /dev/null
@@ -1,237 +0,0 @@
-import requests
-
-from unittest import TestCase
-from unittest.mock import MagicMock, patch, Mock
-
-from requests.exceptions import MissingSchema
-
-from src.grafana_api.model import APIModel, RequestsMethods
-from src.grafana_api.utils import Utils
-
-
-class UtilsTestCase(TestCase):
- def test_call_the_api_non_method(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api(api_call=MagicMock(), method=None)
-
- def test_call_the_api_non_valid_method(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api(api_call=MagicMock(), method=MagicMock())
-
- @patch("requests.get")
- def test_call_the_api_get_valid(self, get_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- mock: Mock = Mock()
- mock.json = Mock(return_value={"status": "success"})
-
- get_mock.return_value = mock
-
- self.assertEqual(
- "success",
- utils.call_the_api(api_call=MagicMock())["status"],
- )
-
- def test_call_the_api_get_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(MissingSchema):
- utils.call_the_api(api_call=MagicMock(), method=RequestsMethods.GET)
-
- @patch("requests.put")
- def test_call_the_api_put_valid(self, put_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- mock: Mock = Mock()
- mock.json = Mock(return_value={"status": "success"})
-
- put_mock.return_value = mock
-
- self.assertEqual(
- "success",
- utils.call_the_api(
- api_call=MagicMock(),
- method=RequestsMethods.PUT,
- json_complete=MagicMock(),
- )["status"],
- )
-
- def test_call_the_api_put_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api(api_call=MagicMock(), method=RequestsMethods.PUT)
-
- @patch("requests.post")
- def test_call_the_api_post_valid(self, post_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- mock: Mock = Mock()
- mock.json = Mock(return_value={"status": "success"})
-
- post_mock.return_value = mock
-
- self.assertEqual(
- "success",
- utils.call_the_api(
- api_call=MagicMock(),
- method=RequestsMethods.POST,
- json_complete=MagicMock(),
- )["status"],
- )
-
- def test_call_the_api_post_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(MissingSchema):
- utils.call_the_api(
- api_call=MagicMock(),
- method=RequestsMethods.POST,
- json_complete=MagicMock(),
- )
-
- def test_call_the_api_post_no_data(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api(api_call=MagicMock(), method=RequestsMethods.POST)
-
- @patch("requests.delete")
- def test_call_the_api_delete_valid(self, delete_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- mock: Mock = Mock()
- mock.json = Mock(return_value={"message": "Deletion successful"})
-
- delete_mock.return_value = mock
-
- self.assertEqual(
- "Deletion successful",
- utils.call_the_api(api_call=MagicMock(), method=RequestsMethods.DELETE)[
- "message"
- ],
- )
-
- def test_call_the_api_delete_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api(api_call=MagicMock(), method=RequestsMethods.DELETE)
-
- def test_call_the_api_non_json_output_non_method(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api_non_json_output(api_call=MagicMock(), method=None)
-
- def test_call_the_api_non_json_output_non__valid_method(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api_non_json_output(api_call=MagicMock(), method=MagicMock())
-
- @patch("requests.get")
- def test_call_the_api_non_json_output_get_valid(self, get_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- get_mock.return_value.text = "success"
-
- self.assertEqual(
- "success",
- utils.call_the_api_non_json_output(api_call=MagicMock()).text,
- )
-
- def test_call_the_api_non_json_output_get_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(MissingSchema):
- utils.call_the_api_non_json_output(
- api_call=MagicMock(), method=RequestsMethods.GET
- )
-
- @patch("requests.post")
- def test_call_the_api_non_json_output_post_valid(self, post_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- post_mock.return_value.text = "success"
-
- self.assertEqual(
- "success",
- utils.call_the_api_non_json_output(
- api_call=MagicMock(),
- method=RequestsMethods.POST,
- json_complete=MagicMock(),
- ).text,
- )
-
- def test_call_the_api_non_json_output_post_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(MissingSchema):
- utils.call_the_api_non_json_output(
- api_call=MagicMock(),
- method=RequestsMethods.POST,
- json_complete=MagicMock(),
- )
-
- def test_call_the_api_non_json_output_post_no_data(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api_non_json_output(
- api_call=MagicMock(), method=RequestsMethods.POST
- )
-
- @patch("requests.delete")
- def test_call_the_api_non_json_output_delete_valid(self, delete_mock):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- delete_mock.return_value.text = "Deletion successful"
-
- self.assertEqual(
- "Deletion successful",
- utils.call_the_api_non_json_output(
- api_call=MagicMock(), method=RequestsMethods.DELETE
- ).text,
- )
-
- def test_call_the_api_non_json_output_delete_not_valid(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(Exception):
- utils.call_the_api_non_json_output(
- api_call=MagicMock(), method=RequestsMethods.DELETE
- )
-
- def test_check_the_api_call_response(self):
- model: APIModel = APIModel(host=MagicMock(), token=MagicMock())
- utils: Utils = Utils(grafana_api_model=model)
-
- with self.assertRaises(requests.exceptions.ConnectionError):
- utils._Utils__check_the_api_call_response(
- response=dict({"message": "invalid API key"})
- )