diff --git a/.github/actions/python-build/action.yml b/.github/actions/python-build/action.yml new file mode 100644 index 0000000..9bfdfd6 --- /dev/null +++ b/.github/actions/python-build/action.yml @@ -0,0 +1,7 @@ +runs: + using: "composite" + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' \ No newline at end of file diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml new file mode 100644 index 0000000..5245bc3 --- /dev/null +++ b/.github/workflows/build-and-push.yml @@ -0,0 +1,101 @@ +name: moira-build-and-push +on: + workflow_run: + workflows: + - moira-test + types: + - completed + branches: + - 'main' + push: + tags: + - '*' +jobs: + build: + runs-on: ubuntu-latest + env: + BUILD_DEPENDENCIES: "build~=0.10.0" + steps: + - uses: actions/checkout@v4 + - name: python-build + uses: ./.github/actions/python-build + - name: install-dependencies + run: python3 -m pip install $BUILD_DEPENDENCIES $PUSH_DEPENDENCIES + - name: build + run: | + ls . + python -m build + - name: store-dist + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + publish-to-pypi: + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/moira + permissions: + id-token: write + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + check-release-exists: + needs: + - publish-to-pypi + runs-on: ubuntu-latest + outputs: + release-exists: ${{ steps.check-release.outputs.release-exists }} + steps: + - uses: actions/checkout@v4 + - name: Release Existence Action + id: check-release + uses: insightsengineering/release-existence-action@v1.0.0 + with: + release-tag: ${{github.ref_name}} + github-release: + name: >- + Sign the Python 🐍 distribution 📦 with Sigstore + and upload them to GitHub Release + needs: + - check-release-exists + runs-on: ubuntu-latest + permissions: + contents: write # IMPORTANT: mandatory for making GitHub Releases + id-token: write # IMPORTANT: mandatory for sigstore + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@v2.1.1 + with: + inputs: >- + ./dist/*.tar.gz + ./dist/*.whl + - name: Create GitHub Release + if: ${{ needs.check-release-exists.outputs.release-exists == 'false' }} + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release create + '${{ github.ref_name }}' + --repo '${{ github.repository }}' + --notes "" + - name: Upload artifact signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release upload + '${{ github.ref_name }}' dist/** + --repo '${{ github.repository }}' + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1435987..c0e4286 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,19 +1,52 @@ -name: Python test - -on: - push - +name: moira-test +on: [push] +env: + TEST_DEPENDENCIES: "tox~=4.15.1" jobs: - run-tests: - runs-on: ubuntu-22.04 + check-project-files: + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up Python "3.9" - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - - name: Install dependencies - run: make deps - - name: Test - run: make test \ No newline at end of file + - name: variables + run: | + PROJECT_FILES=(README.md pyproject.toml) + ERROR=0 + - name: test + run: | + for file in ${PROJECT_FILES[*]}; do + if ! [ -f $file ]; then + echo "$file not found in project" + ERROR=1 + fi + done + exit $ERROR + lint: + runs-on: ubuntu-latest + strategy: + matrix: + linters: [pyproject, lint, format, mypy] + steps: + - uses: actions/checkout@v4 + - name: python-build + uses: ./.github/actions/python-build + - name: install-dependencies + run: | + python3 -m pip install --upgrade pip + pip install $TEST_DEPENDENCIES + - name: test + run: tox -e "${{ matrix.linters }}" + test: + runs-on: ubuntu-latest + strategy: + matrix: + minor_versions: [10, 11, 12, 13, 14] + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.${{ matrix.minor_versions }}' + - name: install-dependencies + run: | + python3 -m pip install --upgrade pip + pip install $TEST_DEPENDENCIES + - name: test + run: tox -e "py3${{ matrix.minor_versions }}" diff --git a/.gitignore b/.gitignore index 7909c32..0b03a90 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -8,7 +9,6 @@ __pycache__/ # Distribution / packaging .Python -env/ build/ develop-eggs/ dist/ @@ -20,9 +20,12 @@ lib64/ parts/ sdist/ var/ +wheels/ +share/python-wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -37,13 +40,17 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml -*,cover +*.cover +*.py,cover .hypothesis/ +.pytest_cache/ +cover/ # Translations *.mo @@ -52,6 +59,8 @@ coverage.xml # Django stuff: *.log local_settings.py +db.sqlite3 +db.sqlite3-journal # Flask stuff: instance/ @@ -64,29 +73,106 @@ instance/ docs/_build/ # PyBuilder +.pybuilder/ target/ -# IPython Notebook +# Jupyter Notebook .ipynb_checkpoints -# pyenv -.python-version +# IPython +profile_default/ +ipython_config.py -# celery beat schedule file +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff celerybeat-schedule +celerybeat.pid -# dotenv -.env +# SageMath parsed files +*.sage.py -# virtualenv +# Environments +.env +.venv +env/ venv/ ENV/ +env.bak/ +venv.bak/ # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -# IDE -.idea +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ + +# VS Code +.vscode/ +.devcontainer/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +# tox envname junit/coverage reports +/.reports diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 696955a..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,154 +0,0 @@ -# 5.1.1 - -extra_message field in contact support - -# 5.1.0 - -System tags api support - -# 5.0.0 - -‼️ The add method creates a new contact if the passed name does not match an existing one - -# 4.3.2 - -The PATCH method should be used to update a team - -# 4.3.1 - -Fix package issues - -# 4.3.0 - -Add support for Team APIs - -# 4.2.1 - -Add support for name field in contacts - -# 4.2.0 - -Add support for multiple clusters in trigger creation - -Now you can use `cluster_id` field in api to set non-default cluster for remote triggers. List of available clusters can be seen in api at `https://your-moira-url/api/config` - -# 4.1.0 - -Add support for prometheus trigger creation. - -Now you can use `trigger_source` field in api that overrides `is_remote` field - -# 4.0.2 - -Fix typo - -# 4.0.1 - -Small refactor to satisfy users that use Python < 3.6 - -# 4.0.0 - -Make validation for Python-client like validation in Web Moira. It is need to make valiation right and unified for all Moira client sides. - -[Use new validation for creating/updating triggers](https://github.com/moira-alert/python-moira-client/commit/3edb4c720d4b80ae8a4bd6117cb2b9cf0c5bec16) - -[Return response object instead of string ID](https://github.com/moira-alert/python-moira-client/commit/5f2bccdd11d6ef6a2a548b9c7072037ebf0445c0) - -# 3.0.0 - -‼️ Remove underscore-prefixed fields that contained scheduling time settings: - -- `_start_hour` -- `_start_minute` -- `_end_hour` -- `_end_minute` -- `_timezone_offset` -- `disabled_days` - -Because they were duplicates of data from sched field. - -Please use sched field for scheduling settings instead. - -# 2.6.1 - -- Fix missed disabled_days -- Push only tags create - -# 2.6.0 -- Add "/setMaintenance" methods #8 -- Set login equal to auth_user by default if last one is specified #9 -- Add "/config" methods #10 -- Add support for changing moira notification state #16 - -# 2.5.1 -- Added ability to subscribe for all triggers without specifying tags (moira-alert/moira#236). - -# 2.4 - -- Python Moira client is now MIT licensed -- Changed default timezone offset to UTC -- Added dictionary attribute with plotting settings to subscription and
- corresponding methods enable_plotting(theme) and disable_plotting() -- Added boolean attribute mute_new_metrics to trigger -- Optimized tag stats methods (stats, fetch_assigned_triggers, fetch_assigned_triggers_by_tags)
-to return trigger id's instead of triggers to speed up method execution time - -# 2.3.5 -- Fixed url to update existing subscription - -# 2.3.4 - -- Added health methods (get_notifier_state, disable_notifications, enable_notifications) to potect
- end user from false NODATA notifications.
- See more details: https://moira.readthedocs.io/en/latest/user_guide/selfstate.html -- Added event.delete_all() and notification.delete_all() to remove unexpectedly generated
- trigger events and notifications in cases when Moira Notifier is managed to stop sending notifications. -- Added subscription.test(subscription_id) to trigger test notification -- Added boolean attributes to subscription (ignore_warnings, ignore_recoverings).
- Corresponding tags "ERROR", "DEGRADATION" and "HIGH DEGRADATION" are deprecated -- Added boolean "is_remote" attribute to trigger to provide ability to use external Graphite storage
- instead of Redis -- Added string "trigger_type" attribute to trigger. Options are: rising, falling, expression
- Single thresholds (only warn_value or only error_value) may be used if "trigger_type" value
- is defined. - -# 2.1.1 -- Allow passing warn_value and error_value for trigger as None when expression is used -- Fixed case with subscription's schedule with no days selected - -# 2.0 -- Added custom headers support -- Added trigger creation by custom id -- Removed tags extra data addition feature -- Changed ttl type from string to int -- Optimized fetch_by_id for large production solutions - -# 0.4 -- Added fetch_assigned_triggers_by_tags method for Tag entity -- Fixed trigger existence check. Check equals by casting to sets -- Fixed trigger delete logic - -# 0.3.3 -- Fixed contact creation. Explore only current user's contacts - -# 0.3.2 -- Added basic authorization - -# 0.3.1 -- Trigger update on save -- Subscription is_exist method added -- Contact idempotent creation - -# 0.3 -- Store id in Trigger after save of existent trigger -- Add get_id Contact method - -# 0.2 -- TriggerManager is_exist function added -- TriggerManager get_non_existent function added - -# 0.1.1 -- Trigger exist check added - -# 0.1 -- base functionality (support for models: contact, event, notification, pattern, subscription, tag, trigger) diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 1dc2e32..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Moira - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index ebd679e..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include *.txt -include *.md diff --git a/Makefile b/Makefile deleted file mode 100644 index 7f07945..0000000 --- a/Makefile +++ /dev/null @@ -1,24 +0,0 @@ - -PYTHON=python -PYTHONPATH=./ -SOURCE_DIR=./ -TESTS_DIR=./tests - -all: help - -help: - @echo "install - install python package" - @echo "test - run tests" - @echo "test-deps - install test dependencies" - -install: - $(PYTHON) setup.py install - -test: - $(PYTHON) -m unittest discover $(TESTS_DIR) -v - -deps: - pip install -r ./requirements.txt - -test-deps: - pip install -r ./test-requirements.txt diff --git a/README.md b/README.md index e3573b4..9d15767 100644 --- a/README.md +++ b/README.md @@ -1,285 +1,27 @@ -[![Build Status](https://travis-ci.org/moira-alert/python-moira-client.svg?branch=master)](https://travis-ci.org/moira-alert/python-moira-client) +# moira + +Client for [Moira](https://moira.readthedocs.io). -# Moira Client +> :warning: The library is the result of automatic generation. -If you're new here, better check out our main [README](https://github.com/moira-alert/moira/blob/master/README.md). +## asyncio support + +Yes -Python client for Moira. - -# Installation - -``` -pip install moira-python-client -``` - -# Getting started - -Initialize Moira client: -``` -from moira_client import Moira - -moira = Moira('http://localhost:8888/api/') -``` - -## Triggers - -### Create new trigger -``` -from moira_client.models.trigger import STATE_ERROR - -trigger = moira.trigger.create( - id='service_trigger_name', - name='Trigger name', - tags=['service'], - targets=['prefix.service.*.postfix'], - warn_value=300, - error_value=600, - desc='my trigger', - ttl_state=STATE_ERROR -) - -trigger.disable_day('Tue') -trigger.save() -print(trigger.id) -``` - -> **Note:** id parameter is not required but highly recommended for large production solutions
-> (e.q. fetch_by_id will work faster than is_exist). -> If parameter is not specified, random trigger guid will be generated. - -### Update triggers -Turn off all triggers for Monday. -``` -triggers = moira.trigger.fetch_all() -for trigger in triggers: - trigger.disable_day('Mon') - trigger.update() -``` - -### Delete trigger -``` -trigger = moira.trigger.fetch_by_id('bb1a8514-128b-406e-bec3-25e94153ab30') -moira.trigger.delete(trigger.id) -``` - -### Check whether trigger exists or not (manually) -``` -trigger = moira.trigger.create( - name='service', - targets=['service.rps'], - tags=['ops'] -) - -if not moira.trigger.is_exist(trigger): - trigger.save() -``` - -### Get non existent triggers -``` -trigger1 = moira.trigger.create( - name='service', - targets=['service.rps'], - tags=['ops'] -) - -trigger2 = moira.trigger.create( - name='site', - targets=['site.rps'], - tags=['ops'] -) - -triggers = [trigger1, trigger2] - -non_existent_triggers = moira.trigger.get_non_existent(triggers) -``` - -## Subscription - -### Create subscription -``` -subscription = moira.subscription.create( - contacts=['79ac9de2-a3b3-4f94-b3ea-74f6f4094fd2'], - tags=['tag'] -) -subscription.save() -``` - -### Delete subscription -Delete all subscriptions -``` -subscriptions = moira.subscription.fetch_all() -for subscription in subscriptions: - moira.subscription.delete(subscription.id) -``` - -## Contact - -### Get all contacts -``` -contacts = moira.contact.fetch_all() -for contact in contacts: - print(contact.id) -``` - -### Get contact id by type and value -``` -contact_id = moira.contact.get_id(type='slack', value='#err') -print(contact_id) -``` - -## Team - -### Get all teams -```python -teams = moira.team.get_all() -``` - -### Create a new team -```python -from moira_client.models.team import TeamModel - -team = TeamModel( - description="Team that holds all members of infrastructure division", - name="Infrastructure Team", -) - -saved_team = moira.team.create(team) -``` - -### Delete a team -```python -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" - -deleted_team = moira.team.delete(team_id) -``` - -### Get a team by ID -```python -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" - -team = moira.team.get(team_id) +## Installation +```bash +pip install moira ``` -### Update existing team +## Usage example ```python -from moira_client.models.team import TeamModel - -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" -team = TeamModel( - description="Team that holds all members of infrastructure division", - name="Infrastructure Team", -) - -updated_team = moira.team.update(team_id, team) -``` - -### Team Settings - -#### Get team settings -```python -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" - -settings = moira.team.settings.get(team_id) -``` - -### Team User - -#### Get users of a team - -```python -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" - -users = moira.team.user.get(team_id) -``` - -#### Add users to a team - -```python -from moira_client.models.team.user import TeamMembers - -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" -users_to_add = TeamMembers(usernames=["anonymous", ]) +from moira.clients import MoiraClient -users = moira.team.user.add(team_id, users_to_add) -``` - -#### Set users of a team - -```python -from moira_client.models.team.user import TeamMembers - -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" -users_to_set = TeamMembers(usernames=["anonymous", ]) - -users = moira.team.user.set(team_id, users_to_set) -``` - -#### Delete a user from a team - -```python -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" -team_user_id = "anonymous" - -users = moira.team.user.delete(team_id, team_user_id) -``` - -### Team Subscription - -#### Create a new team subscription - -```python -from moira_client.models.subscription import SubscriptionModel - -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" -subscription_to_create = SubscriptionModel( - any_tags=False, - contacts=[ - "acd2db98-1659-4a2f-b227-52d71f6e3ba1" - ], - enabled=True, - ignore_recoverings=False, - ignore_warnings=False, - plotting={ - "enabled": True, - "theme": "dark" - }, - sched={ - "days": [ - { - "enabled": True, - "name": "Mon" - } - ], - "endOffset": 1439, - "startOffset": 0, - "tzOffset": -60 - }, - tags=[ - "server", - "cpu" - ], - throttling=False, - user="", -) - -subscription = moira.team.subscription.create(team_id, subscription_to_create) -``` - -### Team Contact - -#### Create a new team contact - -```python -from moira_client.models.contact import Contact - -team_id = "d5d98eb3-ee18-4f75-9364-244f67e23b54" -contact_to_create = Contact( - name="Mail Alerts", - team_id=team_id, - type="mail", - user="", - value="devops@example.com", -) - -contact = moira.team.contact.create(team_id, contact_to_create) -``` +moira = MoiraClient(base_url="https://moira-api.example.com") +result = moira.get_web_config() +``` \ No newline at end of file diff --git a/VERSION.txt b/VERSION.txt deleted file mode 100644 index 91ff572..0000000 --- a/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -5.2.0 diff --git a/moira_client/__init__.py b/moira_client/__init__.py deleted file mode 100644 index da872c7..0000000 --- a/moira_client/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from moira_client.moira import Moira -from requests import HTTPError \ No newline at end of file diff --git a/moira_client/client.py b/moira_client/client.py deleted file mode 100644 index 8ae894f..0000000 --- a/moira_client/client.py +++ /dev/null @@ -1,178 +0,0 @@ -from requests.auth import HTTPBasicAuth -import requests - - -class ResponseStructureError(Exception): - def __init__(self, msg, content): - """ - - :param msg: str error message - :param content: dict response content - """ - self.msg = msg - self.content = content - - -class InvalidJSONError(Exception): - def __init__(self, content): - """ - - :param content: bytes response content - """ - self.content = content - -class MoiraApiError(Exception): - def __init__(self, body): - """ - - :param body: response body - """ - self.body = body - - -class Client: - def __init__(self, api_url, auth_custom=None, auth_user=None, auth_pass=None, login=None): - """ - - :param api_url: str Moira API URL - :param auth_custom: dict auth custom headers - :param auth_user: str auth user - :param auth_pass: str auth password - :param login: str auth login - """ - if not api_url.endswith('/'): - self.api_url = api_url + '/' - else: - self.api_url = api_url - - if not login and auth_user: - login = auth_user - - self.auth = None - self.headers = { - 'X-Webauth-User': login, - 'Content-Type': 'application/json', - 'User-Agent': 'Python Moira Client' - } - - if auth_user and auth_pass: - self.auth = HTTPBasicAuth(auth_user, auth_pass) - - if auth_custom: - self.headers.update(auth_custom) - - def get(self, path='', **kwargs): - """ - - :param path: str api path - :param kwargs: additional parameters for request - :return: dict response - - :raises: MoiraApiError - :raises: InvalidJSONError - """ - r = requests.get(self._path_join(path), headers=self.headers, auth=self.auth, **kwargs) - - try: - r.raise_for_status() - except requests.exceptions.HTTPError as err: - raise MoiraApiError(r.content) - - try: - return r.json() - except ValueError: - raise InvalidJSONError(r.content) - - def delete(self, path='', **kwargs): - """ - - :param path: str api path - :param kwargs: additional parameters for request - :return: dict response - - :raises: MoiraApiError - :raises: InvalidJSONError - """ - r = requests.delete(self._path_join(path), headers=self.headers, auth=self.auth, **kwargs) - - try: - r.raise_for_status() - except requests.exceptions.HTTPError as err: - raise MoiraApiError(r.content) - - try: - return r.json() - except ValueError: - raise InvalidJSONError(r.content) - - def put(self, path='', **kwargs): - """ - - :param path: str api path - :param kwargs: additional parameters for request - :return: dict response - - :raises: MoiraApiError - :raises: InvalidJSONError - """ - r = requests.put(self._path_join(path), headers=self.headers, auth=self.auth, **kwargs) - - try: - r.raise_for_status() - except requests.exceptions.HTTPError as err: - raise MoiraApiError(r.content) - - try: - return r.json() - except ValueError: - raise InvalidJSONError(r.content) - - def patch(self, path='', **kwargs): - """ - - :param path: str api path - :param kwargs: additional parameters for request - :return: dict response - - :raises: MoiraApiError - :raises: InvalidJSONError - """ - r = requests.patch(self._path_join(path), headers=self.headers, auth=self.auth, **kwargs) - - try: - r.raise_for_status() - except requests.exceptions.HTTPError as err: - raise MoiraApiError(r.content) - - try: - return r.json() - except ValueError: - raise InvalidJSONError(r.content) - - def post(self, path='', **kwargs): - """ - - :param path: str api path - :param kwargs: additional parameters for request - :return: dict response - - :raises: MoiraApiError - :raises: InvalidJSONError - """ - r = requests.post(self._path_join(path), headers=self.headers, auth=self.auth, **kwargs) - - try: - r.raise_for_status() - except requests.exceptions.HTTPError as err: - raise MoiraApiError(r.content) - - try: - return r.json() - except ValueError: - raise InvalidJSONError(r.content) - - def _path_join(self, *args): - path = self.api_url - for part in args: - path += part - return path diff --git a/moira_client/models/__init__.py b/moira_client/models/__init__.py deleted file mode 100644 index 44eed60..0000000 --- a/moira_client/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .trigger import Trigger -from .contact import Contact -from .pattern import Pattern -from .subscription import Subscription diff --git a/moira_client/models/base.py b/moira_client/models/base.py deleted file mode 100644 index e715a2f..0000000 --- a/moira_client/models/base.py +++ /dev/null @@ -1,17 +0,0 @@ - -class Base: - @property - def id(self): - return self._id - - def __repr__(self): - return '({} {})'.format(self.__class__.__name__, self.id) - - def __unicode__(self): - return u'({} {})'.format(self.__class__.__name__, self.id) - - def __eq__(self, other): - return self.id == other.id - - def __ne__(self, other): - return self.id != other.id diff --git a/moira_client/models/config.py b/moira_client/models/config.py deleted file mode 100644 index 044e683..0000000 --- a/moira_client/models/config.py +++ /dev/null @@ -1,60 +0,0 @@ -from ..client import ResponseStructureError - - -class WebContact: - def __init__(self, _type, label, validation=None, placeholder=None, _help=None): - self.type = _type - self.label = label - self.validation = validation - self.placeholder = placeholder - self.help = _help - - -class Config: - def __init__(self, remote_allowed, contacts, support_email=None): - self.remoteAllowed = remote_allowed - self.contacts = contacts - self.supportEmail = support_email - - -class ConfigManager: - def __init__(self, client): - self._client = client - - def fetch(self): - """ - Returns config, see https://moira.readthedocs.io/en/latest/installation/configuration.html - - :return: config - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - - if 'contacts' not in result: - raise ResponseStructureError("'contacts' field doesn't exist in response", result) - if 'remoteAllowed' not in result: - raise ResponseStructureError("'remoteAllowed' field doesn't exist in response", result) - - contacts = [] - for contact in result['contacts']: - if self._validate_contact(contact): - _help = contact['help'] if 'help' in contact else None - validation = contact['validation'] if 'validation' in contact else None - placeholder = contact['placeholder'] if 'placeholder' in contact else None - contacts.append(WebContact(_type=contact['type'], label=contact['label'], validation=validation, - placeholder=placeholder, _help=_help)) - support = result['supportEmail'] if 'supportEmail' in result else None - return Config(remote_allowed=result['remoteAllowed'], contacts=contacts, support_email=support) - - def _validate_contact(self, contact): - if 'type' not in contact: - return False - if 'label' not in contact: - return False - return True - - def _full_path(self, path=''): - if path: - return 'config/{}'.format(path) - return 'config' diff --git a/moira_client/models/contact.py b/moira_client/models/contact.py deleted file mode 100644 index 05bbcc4..0000000 --- a/moira_client/models/contact.py +++ /dev/null @@ -1,175 +0,0 @@ -from ..client import InvalidJSONError -from ..client import ResponseStructureError -from .base import Base - -CONTACT_EMAIL = 'mail' -CONTACT_PUSHOVER = 'pushover' -CONTACT_SLACK = 'slack' -CONTACT_TELEGRAM = 'telegram' -CONTACT_TWILIO_SMS = 'twilio sms' -CONTACT_TWILIO_VOICE = 'twilio voice' - - -class Contact(Base): - def __init__(self, value='', type='', **kwargs): - """ - - :param value: str contact value - :param contact_type: str contact type (one of CONTACT_* constants) - :param kwargs: additional parameters - """ - self.type = type - self.value = value - self.user = kwargs.get('user', None) - self.name = kwargs.get('name', None) - self._id = kwargs.get('id', None) - self.team_id = kwargs.get('team_id', None) - self.extra_message = kwargs.get('extra_message', None) - - -class ContactManager: - def __init__(self, client): - self._client = client - - def add(self, value, contact_type, name=None): - """ - Add new contact - - :param value: str contact value - :param contact_type: str contact type (one of CONTACT_* constants) - :param name: str contact name - :return: Contact - - :raises: ResponseStructureError - """ - - contacts = self.fetch_by_current_user() - for contact in contacts: - if contact.value == value and contact.type == contact_type: - if name is not None and contact.name == name: - return contact - - data = { - 'value': value, - 'type': contact_type - } - if name: - data['name'] = name - - result = self._client.put(self._full_path(), json=data) - if 'id' not in result: - raise ResponseStructureError('No id in response', result) - - return Contact(id=result['id'], **data) - - def fetch_all(self): - """ - Returns all existing contacts - - :return: list of Contact - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - if 'list' not in result: - raise ResponseStructureError("list doesn't exist in response", result) - - contacts = [] - - for contact in result['list']: - contacts.append(Contact(**contact)) - - return contacts - - def fetch_by_current_user(self): - """ - Returns all contacts by current user - - :return: list of Contact - - :raises: ResponseStructurteError - """ - result = self._client.get('user/settings') - if 'contacts' not in result: - raise ResponseStructureError("'contacts' field doesn't exist in response", result) - - contacts = [] - - for contact in result['contacts']: - contacts.append(Contact(**contact)) - - return contacts - - def get_id(self, type, value): - """ - Returns contact id by type and value - Returns None if contact doesn't exist - - :param type: str contact type - :param value: str contact value - :return: str contact id - """ - for contact in self.fetch_all(): - if contact.type == type and contact.value == value: - return contact.id - - def delete(self, contact_id): - """ - Delete contact by contact id - If contact id doesn't exist returns True - - :param contact_id: str contact id - :return: True if ok, False otherwise - - :raises: ResponseStructureError - """ - try: - self._client.delete(self._full_path(contact_id)) - return False - except InvalidJSONError as e: - if e.content == b'': # successfully if response is blank - return True - else: - return False - - def update(self, contact): - """ - Updates an existing notification contact - - :param contact: Contact - :return: True if ok, False otherwise - """ - data = { - 'type': contact.type, - 'value': contact.value, - } - if contact.name: - data['name'] = contact.name - - try: - self._client.put(self._full_path(contact.id), json=data) - return True - except InvalidJSONError: - return False - - def test(self, contact_id): - """ - Push a test notification to verify that the contact is properly set up. - - :param contact_id: str contact id - :return: True if ok, False otherwise - """ - - try: - self._client.post(self._full_path('{id}/test'.format(id=contact_id))) - return False - except InvalidJSONError as e: - if len(e.content) == 0: # successfully if response is blank - return True - else: - return False - - def _full_path(self, path=''): - if path: - return 'contact/{}'.format(path) - return 'contact' diff --git a/moira_client/models/event.py b/moira_client/models/event.py deleted file mode 100644 index 7c6492f..0000000 --- a/moira_client/models/event.py +++ /dev/null @@ -1,51 +0,0 @@ -from ..client import InvalidJSONError -from ..client import ResponseStructureError - - -MAX_FETCH_LIMIT = 1000 - - -class EventManager: - def __init__(self, client): - self._client = client - - def fetch_by_trigger(self, trigger, limit=MAX_FETCH_LIMIT): - """ - Get all events by trigger - :param trigger: Trigger trigger - :param limit: int limit - :return: list of dicts - - :raises: ValueError - :raises: ResponseStructureError - """ - if not trigger.id: - raise ValueError('Trigger id is None') - params = { - 'p': 0, - 'size': limit - } - result = self._client.get(self._full_path(trigger.id), params=params) - if 'list' not in result: - raise ResponseStructureError("list doesn't exist in response", result) - - return result['list'] - - def delete_all(self): - """ - Remove all events - - :return: True on success, False otherwise - """ - try: - result = self._client.delete(self._full_path("all")) - return False - except InvalidJSONError as e: - if e.content == b'': # successfully if response is blank - return True - return False - - def _full_path(self, path=''): - if path: - return 'event/{}'.format(path) - return 'event' diff --git a/moira_client/models/health.py b/moira_client/models/health.py deleted file mode 100644 index 61bf691..0000000 --- a/moira_client/models/health.py +++ /dev/null @@ -1,62 +0,0 @@ -from ..client import ResponseStructureError - - -STATE_ENABLED = 'OK' -STATE_DISABLED = 'ERROR' - - -class HealthManager: - def __init__(self, client): - self._client = client - - def get_notifier_state(self): - """ - Returns current Moira Notifier state - :return: str - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path("notifier")) - if 'state' not in result: - raise ResponseStructureError("state doesn't exist in response", result) - - return result['state'] - - def disable_notifications(self): - """ - Manage Moira Notifier to stop sending notifications - Returns current Moira Notifier state - :return: str - - :raises: ResponseStructureError - """ - data = { - 'state': STATE_DISABLED - } - result = self._client.put(self._full_path("notifier"), json=data) - if 'state' not in result: - raise ResponseStructureError("state doesn't exist in response", result) - - return result['state'] - - def enable_notifications(self): - """ - Manage Moira Notifier to start sending notifications - Returns current Moira Notifier state - :return: str - - :raises: ResponseStructureError - """ - data = { - 'state': STATE_ENABLED - } - result = self._client.put(self._full_path("notifier"), json=data) - if 'state' not in result: - raise ResponseStructureError("state doesn't exist in response", result) - - return result['state'] - - def _full_path(self, path=''): - if path: - return 'health/{}'.format(path) - return 'health' diff --git a/moira_client/models/notification.py b/moira_client/models/notification.py deleted file mode 100644 index e9113ba..0000000 --- a/moira_client/models/notification.py +++ /dev/null @@ -1,75 +0,0 @@ -from ..client import InvalidJSONError -from ..client import ResponseStructureError - - -class NotificationManager: - def __init__(self, client): - self._client = client - - def fetch_all(self): - """ - Returns all notifications - :return: list of dict - - :raises: ResponseStructureError - """ - result = self.fetch(start=0, end=-1) - return result - - def fetch(self, start, end): - """ - Gets a paginated list of notifications - :return: list of dict - - :param start - :param end - - :raises: ResponseStructureError - """ - params = { - 'start': start, - 'end': end - } - result = self._client.get(self._full_path(), params=params) - if 'list' not in result: - raise ResponseStructureError("list doesn't exist in response", result) - - return result['list'] - - def delete_all(self): - """ - Remove all notifications - - :return: True on success, False otherwise - """ - try: - result = self._client.delete(self._full_path("all")) - return False - except InvalidJSONError as e: - if e.content == b'': # successfully if response is blank - return True - return False - - def delete(self, notification_id): - """ - Remove notification by id - - :param notification_id: str notification id - - :return: True on success, False otherwise - """ - - params = { - 'id': notification_id, - } - try: - result = self._client.delete(self._full_path(), params=params) - if 'result' in result and result['result'] == 0: - return True - except InvalidJSONError as e: - return False - - def _full_path(self, path=''): - if path: - return 'notification/{}'.format(path) - return 'notification' diff --git a/moira_client/models/pattern.py b/moira_client/models/pattern.py deleted file mode 100644 index 8174ec2..0000000 --- a/moira_client/models/pattern.py +++ /dev/null @@ -1,56 +0,0 @@ -from collections import namedtuple - -from ..client import InvalidJSONError -from ..client import ResponseStructureError -from .trigger import Trigger - - -Pattern = namedtuple('Pattern', ['metrics', 'pattern', 'triggers']) - - -class PatternManager: - """ - A Graphite pattern is a single dot-separated metric name, possibly containing one or more wildcards. - """ - def __init__(self, client): - self._client = client - - def fetch_all(self): - """ - Returns all existing patterns in all triggers - - :return: list of Pattern - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - if 'list' in result: - patterns = [] - for pattern in result['list']: - if 'triggers' in pattern: - pattern['triggers'] = [Trigger(self._client, **trigger) for trigger in pattern['triggers']] - patterns.append(Pattern(**pattern)) - return patterns - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def delete(self, pattern): - """ - Delete pattern - Returns True even if pattern doesn't exist - - :param pattern: str pattern - :return: True if deleted, False otherwise - - :raises: ResponseStructureError - """ - try: - self._client.delete(self._full_path(pattern)) - return False - except InvalidJSONError: - return True - - def _full_path(self, path=''): - if path: - return 'pattern/{}'.format(path) - return 'pattern' diff --git a/moira_client/models/subscription.py b/moira_client/models/subscription.py deleted file mode 100644 index 73d121d..0000000 --- a/moira_client/models/subscription.py +++ /dev/null @@ -1,324 +0,0 @@ -from ..client import InvalidJSONError -from ..client import ResponseStructureError -from .base import Base - -class SubscriptionModel(Base): - def __init__(self, tags, contacts=None, enabled=None, throttling=None, sched=None, - ignore_warnings=False, ignore_recoverings=False, plotting=None, any_tags=False, **kwargs): - """ - :param tags: list of str tags - :param contacts: list of contact id's - :param enabled: bool is enabled - :param throttling: bool throttling - :param sched: dict schedule - :param ignore_warnings: bool ignore warnings - :param ignore_recoverings: bool ignore recoverings - :param plotting: dict plotting settings - :param any_tags: bool any tags - :param kwargs: additional parameters - """ - self._id = kwargs.get('id', None) - self.tags = tags if not any_tags else [] - if not contacts: - contacts = [] - self.contacts = contacts - self.enabled = enabled - self.any_tags = any_tags - self.throttling = throttling - - self.sched = sched - - self.ignore_warnings = ignore_warnings - self.ignore_recoverings = ignore_recoverings - - if not plotting: - plotting = {'enabled': False, 'theme': 'light'} - self.plotting = plotting - self.team_id = kwargs.get('team_id', None) - - def disable_day(self, day): - """ - Disable day - - :param day: str one of DAYS_OF_WEEK - :return: None - """ - self.disabled_days.add(day) - - def enable_day(self, day): - """ - Enable day - - :param day: str one of DAYS_OF_WEEK - :return: None - """ - self.disabled_days.remove(day) - - def add_tag(self, tag): - """ - Add tag to subscription - - :param tag: str tag name - :return: None - """ - self.tags.append(tag) - - def add_contact(self, contact_id): - """ - Add contact - - :param contact_id: str contact id - :return: None - """ - self.contacts.append(contact_id) - - def enable_plotting(self, theme='light'): - """ - Enable plotting - - :param theme: str plotting theme - :return: None - """ - self.plotting = { - 'enabled': True, - 'theme': theme - } - - def disable_plotting(self): - """ - Disable plotting - - :return: None - """ - self.plotting = { - 'enabled': False, - 'theme': 'light' - } - - def set_start_hour(self, hour): - """ - Set start hour - - :param hour: int hour - - :return: None - """ - self._start_hour = hour - - def set_start_minute(self, minute): - """ - Set start minute - - :param minute: int minute - - :return: None - """ - self._start_minute = minute - - def set_end_hour(self, hour): - """ - Set end hour - - :param hour: int hour - - :return: None - """ - self._end_hour = hour - - def set_end_minute(self, minute): - """ - Set end minute - - :param minute: int minute - - :return: None - """ - self._end_minute = minute - - -class Subscription(SubscriptionModel): - def __init__(self, client, tags, contacts=None, enabled=None, throttling=None, sched=None, - ignore_warnings=False, ignore_recoverings=False, plotting=None, any_tags=False, **kwargs): - """ - :param client: api client - :param tags: list of str tags - :param contacts: list of contact id's - :param enabled: bool is enabled - :param throttling: bool throttling - :param sched: dict schedule - :param ignore_warnings: bool ignore warnings - :param ignore_recoverings: bool ignore recoverings - :param plotting: dict plotting settings - :param any_tags: bool any tags - :param kwargs: additional parameters - """ - self._client = client - - super().__init__( - tags=tags, - contacts=contacts, - enabled=enabled, - throttling=throttling, - sched=sched, - ignore_warnings=ignore_warnings, - ignore_recoverings=ignore_recoverings, - plotting=plotting, - any_tags=any_tags, - **kwargs, - ) - - def _send_request(self, subscription_id=None): - data = { - 'contacts': self.contacts, - 'tags': self.tags, - 'enabled': self.enabled, - 'any_tags': self.any_tags, - 'throttling': self.throttling, - 'sched': self.sched, - 'ignore_warnings': self.ignore_warnings, - 'ignore_recoverings': self.ignore_recoverings, - 'plotting': self.plotting, - 'team_id': self.team_id, - } - - if subscription_id: - data['id'] = subscription_id - - if subscription_id: - result = self._client.put('subscription/{id}'.format(id=subscription_id), json=data) - else: - result = self._client.put('subscription', json=data) - if 'id' not in result: - raise ResponseStructureError("id doesn't exist in response", result) - - self._id = result['id'] - return self._id - - def save(self): - """ - Save subscription - - :return: subscription id - """ - if self._id: - return self.update() - self._send_request() - - def update(self): - """ - Update subscription - - :return: subscription id - """ - if not self._id: - return self.save() - self._send_request(self._id) - - -class SubscriptionManager: - def __init__(self, client): - self._client = client - - def fetch_all(self): - """ - Returns all existing subscriptions - - :return: list of Subscription - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - if 'list' in result: - subscriptions = [] - for subscription in result['list']: - subscriptions.append(Subscription(self._client, **subscription)) - return subscriptions - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def is_exist(self, **kwargs): - """ - Check whether subscription exists or not by any attributes - - :param kwargs: attributes - :return: bool - - :raises: ValueError - """ - for subscription in self.fetch_all(): - equal = True - for attr, value in kwargs.items(): - try: - if getattr(subscription, attr) != value: - equal = False - break - except Exception: - raise ValueError('Wrong attribute "{}"'.format(attr)) - if equal: - return True - return False - - def create(self, tags, contacts=None, enabled=True, throttling=True, sched=None, - ignore_warnings=False, ignore_recoverings=False, plotting=None, any_tags=False, **kwargs): - """ - Create new subscription. - - :param tags: list of str tags - :param contacts: list of contact id's - :param enabled: bool is enabled - :param throttling: bool throttling - :param sched: dict schedule - :param ignore_warnings: bool ignore warnings - :param ignore_recoverings: bool ignore recoverings - :param kwargs: additional parameters - :param plotting: dict plotting settings - :param any_tags: bool any tags - :return: Subscription - """ - - return Subscription( - self._client, - tags, - contacts, - enabled, - throttling, - sched, - ignore_warnings, - ignore_recoverings, - plotting, - any_tags, - **kwargs - ) - - def delete(self, subscription_id): - """ - Remove subscription by given id - - :return: True on success, False otherwise - """ - try: - self._client.delete(self._full_path(subscription_id)) - return False - except InvalidJSONError as e: - if e.content == b'': # successfully if response is blank - return True - return False - - def test(self, subscription_id): - """ - Send test notification to subscription contact - - :return: True on success, False otherwise - """ - try: - self._client.put(self._full_path('{id}/test'.format(id=subscription_id))) - return False - except InvalidJSONError as e: - if e.content == b'': # successfully if response is blank - return True - return False - - def _full_path(self, path=''): - if path: - return 'subscription/{}'.format(path) - return 'subscription' diff --git a/moira_client/models/system_tag.py b/moira_client/models/system_tag.py deleted file mode 100644 index 80c5b9e..0000000 --- a/moira_client/models/system_tag.py +++ /dev/null @@ -1,25 +0,0 @@ -from moira_client.client import ResponseStructureError - - -class SystemTagManager: - def __init__(self, client) -> None: - self._client = client - - def fetch_all(self): - """ - Returns all existing system tags - - :return: list of str - - :raises: ResponseStructureError - """ - - result = self._client.get(self._full_path()) - if 'list' not in result: - raise ResponseStructureError("list doesn't exist in response", result) - - return result['list'] - - def _full_path(self) -> str: - return 'system-tag' - diff --git a/moira_client/models/tag.py b/moira_client/models/tag.py deleted file mode 100644 index 135189f..0000000 --- a/moira_client/models/tag.py +++ /dev/null @@ -1,137 +0,0 @@ -from collections import namedtuple - -from requests.exceptions import HTTPError - -from ..client import InvalidJSONError -from ..client import ResponseStructureError -from .subscription import Subscription - - -TagStats = namedtuple('TagStats', ['name', 'subscriptions', 'triggers']) - - -class TagManager: - def __init__(self, client): - self._client = client - - def fetch_all(self): - """ - Returns all existing tags - - :return: list of str - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - if 'list' not in result: - raise ResponseStructureError("list doesn't exist in response", result) - - return result['list'] - - def delete(self, tag): - """ - Delete tag. - In case if tag doesn't exist returns True. - Returns False if tag is assigned to at least 1 trigger. - - :param tag: str tag name - :return: True if deleted, False otherwise - """ - try: - self._client.delete(self._full_path(tag)) - except (InvalidJSONError, HTTPError): - return False - - return True - - def stats(self): - """ - Returns stats by all triggers - - :return: list of TagStats - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path('stats')) - if 'list' in result: - for stat in result['list']: - if 'subscriptions' in stat: - stat['subscriptions'] = [ - Subscription(self._client, **subscription) for subscription in stat['subscriptions'] - ] - return [TagStats(**stat) for stat in result['list']] - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def fetch_assigned_triggers(self, tag): - """ - Returns triggers assigned to tag - - :param tag: str tag name - :return: list of trigger id's - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path('stats')) - if 'list' in result: - trigger_ids = set() - for stat in result['list']: - if 'triggers' in stat and 'name' in stat: - if stat['name'] == tag: - for trigger_id in stat['triggers']: - trigger_ids.add(trigger_id) - return list(trigger_ids) - return list(trigger_ids) - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def fetch_assigned_triggers_by_tags(self, tags): - """ - Returns triggers assigned to at least one tag of tags - - :param tags: Iterable of tags - :return: list of trigger id's - - :raises: ResponseStructureError - """ - - tags = set(tags) - result = self._client.get(self._full_path('stats')) - if 'list' in result: - trigger_ids = set() - for stat in result['list']: - if 'triggers' in stat and 'name' in stat: - if stat['name'] in tags: - for trigger_id in stat['triggers']: - trigger_ids.add(trigger_id) - - return list(trigger_ids) - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def fetch_assigned_subscriptions(self, tag): - """ - Returns subscriptions assigned to tag - - :param tag: str tag name - :return: list of str subscription_id - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path('stats')) - if 'list' in result: - trigger_ids = set() - for stat in result['list']: - if 'subscriptions' in stat and 'name' in stat: - if stat['name'] == tag: - return [ - Subscription(self._client, **subscription) for subscription in stat['subscriptions'] - ] - return list(trigger_ids) - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def _full_path(self, path=''): - if path: - return 'tag/{}'.format(path) - return 'tag' diff --git a/moira_client/models/team/__init__.py b/moira_client/models/team/__init__.py deleted file mode 100644 index eab2cff..0000000 --- a/moira_client/models/team/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from ._managers import TeamManager -from ._models import TeamModel - - -__all__ = [ - "TeamManager", - "TeamModel", -] diff --git a/moira_client/models/team/_managers.py b/moira_client/models/team/_managers.py deleted file mode 100644 index 122df81..0000000 --- a/moira_client/models/team/_managers.py +++ /dev/null @@ -1,96 +0,0 @@ -from typing import Optional - -from ._models import TeamModel, UserTeams, SaveTeamResponse -from .contact import TeamContactManager -from .settings import TeamSettingsManager -from .subscription import TeamSubscriptionManager -from .user import TeamUserManager -from ...client import Client - - -class TeamManager: - def __init__(self, client: Client) -> None: - self._client = client - self._user = None # type: Optional[TeamUserManager] - self._settings = None # type: Optional[TeamSettingsManager] - self._subscription = None # type: Optional[TeamSubscriptionManager] - self._contact = None # type: Optional[TeamContactManager] - - def get_all(self) -> UserTeams: - """Get all teams""" - response = self._client.get(self._full_path()) - - return UserTeams(teams=[TeamModel(**team) for team in response["teams"]]) - - def create(self, team: TeamModel) -> SaveTeamResponse: - """Create a new team""" - payload = { - "name": team.name, - "description": team.description, - } - - response = self._client.post(self._full_path(), json=payload) - - return SaveTeamResponse(**response) - - def delete(self, team_id: str) -> SaveTeamResponse: - """Delete a team""" - response = self._client.delete(self._full_path(team_id)) - - return SaveTeamResponse(**response) - - def get(self, team_id: str) -> TeamModel: - """Get a team by ID""" - response = self._client.get(self._full_path(team_id)) - - return TeamModel(**response) - - def update(self, team_id: str, team: TeamModel) -> SaveTeamResponse: - """Update existing team""" - payload = { - "name": team.name, - "description": team.description, - } - - response = self._client.patch(self._full_path(team_id), json=payload) - - return SaveTeamResponse(**response) - - @property - def user(self) -> TeamUserManager: - """Get team user manager""" - if self._user is None: - self._user = TeamUserManager(self._client) - - return self._user - - @property - def settings(self) -> TeamSettingsManager: - """Get team settings manager""" - if self._settings is None: - self._settings = TeamSettingsManager(self._client) - - return self._settings - - @property - def subscription(self) -> TeamSubscriptionManager: - """Get team subscription manager""" - if self._subscription is None: - self._subscription = TeamSubscriptionManager(self._client) - - return self._subscription - - @property - def contact(self) -> TeamContactManager: - """Get team contact manager""" - if self._contact is None: - self._contact = TeamContactManager(self._client) - - return self._contact - - @staticmethod - def _full_path(team_id: Optional[str] = None) -> str: - if team_id is None: - return "teams" - - return "teams/{team_id}".format(team_id=team_id) diff --git a/moira_client/models/team/_models.py b/moira_client/models/team/_models.py deleted file mode 100644 index ad4c82c..0000000 --- a/moira_client/models/team/_models.py +++ /dev/null @@ -1,19 +0,0 @@ -from ..base import Base -from typing import List - - -class TeamModel(Base): - def __init__(self, description: str, name: str, **kwargs): - self.description = description - self.name = name - self._id = kwargs.get("id", None) - - -class UserTeams: - def __init__(self, teams: List[TeamModel]): - self.teams = teams - - -class SaveTeamResponse(Base): - def __init__(self, **kwargs): - self._id = kwargs.get("id") diff --git a/moira_client/models/team/contact/__init__.py b/moira_client/models/team/contact/__init__.py deleted file mode 100644 index 9f380fd..0000000 --- a/moira_client/models/team/contact/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from ._managers import TeamContactManager - -__all__ = [ - "TeamContactManager", -] diff --git a/moira_client/models/team/contact/_managers.py b/moira_client/models/team/contact/_managers.py deleted file mode 100644 index 78a0308..0000000 --- a/moira_client/models/team/contact/_managers.py +++ /dev/null @@ -1,25 +0,0 @@ -from ...contact import Contact -from ....client import Client - - -class TeamContactManager: - def __init__(self, client: Client) -> None: - self._client = client - - def create(self, team_id: str, contact: Contact) -> Contact: - """Create a new team contact""" - payload = { - "team_id": team_id, - "name": contact.name, - "type": contact.type, - "value": contact.value, - "extra_message": contact.extra_message, - } - - response = self._client.post(self._full_path(team_id), json=payload) - - return Contact(**response) - - @staticmethod - def _full_path(team_id: str) -> str: - return "teams/{team_id}/contacts".format(team_id=team_id) diff --git a/moira_client/models/team/settings/__init__.py b/moira_client/models/team/settings/__init__.py deleted file mode 100644 index 4488e84..0000000 --- a/moira_client/models/team/settings/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from ._managers import TeamSettingsManager -from ._models import TeamSettings - -__all__ = [ - "TeamSettings", - "TeamSettingsManager", -] diff --git a/moira_client/models/team/settings/_managers.py b/moira_client/models/team/settings/_managers.py deleted file mode 100644 index e9843aa..0000000 --- a/moira_client/models/team/settings/_managers.py +++ /dev/null @@ -1,23 +0,0 @@ -from ._models import TeamSettings -from ...contact import Contact -from ...subscription import Subscription -from ....client import Client - - -class TeamSettingsManager: - def __init__(self, client: Client) -> None: - self._client = client - - def get(self, team_id: str) -> TeamSettings: - """Get team settings""" - response = self._client.get(self._full_path(team_id)) - - return TeamSettings( - contacts=[Contact(**contact) for contact in response["contacts"]], - subscriptions=[Subscription(self._client, **subscription) for subscription in response["subscriptions"]], - team_id=response["team_id"], - ) - - @staticmethod - def _full_path(team_id: str) -> str: - return "teams/{team_id}/settings".format(team_id=team_id) diff --git a/moira_client/models/team/settings/_models.py b/moira_client/models/team/settings/_models.py deleted file mode 100644 index 57dd898..0000000 --- a/moira_client/models/team/settings/_models.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import List - -from ...contact import Contact -from ...subscription import Subscription - - -class TeamSettings: - def __init__(self, contacts: List[Contact], subscriptions: List[Subscription], team_id: str) -> None: - self.contacts = contacts - self.subscriptions = subscriptions - self.team_id = team_id diff --git a/moira_client/models/team/subscription/__init__.py b/moira_client/models/team/subscription/__init__.py deleted file mode 100644 index b398aa1..0000000 --- a/moira_client/models/team/subscription/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from ._managers import TeamSubscriptionManager - -__all__ = [ - "TeamSubscriptionManager", -] diff --git a/moira_client/models/team/subscription/_managers.py b/moira_client/models/team/subscription/_managers.py deleted file mode 100644 index a3a8eff..0000000 --- a/moira_client/models/team/subscription/_managers.py +++ /dev/null @@ -1,30 +0,0 @@ -from ...subscription import SubscriptionModel, Subscription -from ....client import Client - - -class TeamSubscriptionManager: - def __init__(self, client: Client) -> None: - self._client = client - - def create(self, team_id: str, subscription: SubscriptionModel) -> Subscription: - """Create a new team subscription""" - payload = { - "team_id": team_id, - "contacts": subscription.contacts, - "tags": subscription.tags, - "enabled": subscription.enabled, - "any_tags": subscription.any_tags, - "throttling": subscription.throttling, - "sched": subscription.sched, - "ignore_warnings": subscription.ignore_warnings, - "ignore_recoverings": subscription.ignore_recoverings, - "plotting": subscription.plotting, - } - - response = self._client.post(self._full_path(team_id), json=payload) - - return Subscription(self._client, **response) - - @staticmethod - def _full_path(team_id: str) -> str: - return "teams/{team_id}/subscriptions".format(team_id=team_id) diff --git a/moira_client/models/team/user/__init__.py b/moira_client/models/team/user/__init__.py deleted file mode 100644 index fd89c8e..0000000 --- a/moira_client/models/team/user/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from ._managers import TeamUserManager -from ._models import TeamMembers - -__all__ = [ - "TeamMembers", - "TeamUserManager", -] diff --git a/moira_client/models/team/user/_managers.py b/moira_client/models/team/user/_managers.py deleted file mode 100644 index 3fc5133..0000000 --- a/moira_client/models/team/user/_managers.py +++ /dev/null @@ -1,43 +0,0 @@ -from ._models import TeamMembers -from ....client import Client -from typing import Optional - - -class TeamUserManager: - def __init__(self, client: Client) -> None: - self._client = client - - def get(self, team_id: str) -> TeamMembers: - """Get users of a team""" - response = self._client.get(self._full_path(team_id)) - - return TeamMembers(**response) - - def add(self, team_id: str, members: TeamMembers) -> TeamMembers: - """Add users to a team""" - payload = {"usernames": members.usernames} - - response = self._client.post(self._full_path(team_id), json=payload) - - return TeamMembers(**response) - - def set(self, team_id: str, members: TeamMembers) -> TeamMembers: - """Set users of a team""" - payload = {"usernames": members.usernames} - - response = self._client.put(self._full_path(team_id), json=payload) - - return TeamMembers(**response) - - def delete(self, team_id: str, team_user_id: str) -> TeamMembers: - """Delete a user from a team""" - response = self._client.delete(self._full_path(team_id, team_user_id)) - - return TeamMembers(**response) - - @staticmethod - def _full_path(team_id: str, team_user_id: Optional[str] = None) -> str: - if team_user_id is None: - return "teams/{team_id}/users".format(team_id=team_id) - - return "teams/{team_id}/users/{team_user_id}".format(team_id=team_id, team_user_id=team_user_id) diff --git a/moira_client/models/team/user/_models.py b/moira_client/models/team/user/_models.py deleted file mode 100644 index be7baaa..0000000 --- a/moira_client/models/team/user/_models.py +++ /dev/null @@ -1,6 +0,0 @@ -from typing import List - - -class TeamMembers: - def __init__(self, usernames: List[str]) -> None: - self.usernames = usernames diff --git a/moira_client/models/trigger.py b/moira_client/models/trigger.py deleted file mode 100644 index 9ab3fe0..0000000 --- a/moira_client/models/trigger.py +++ /dev/null @@ -1,594 +0,0 @@ -from ..client import ResponseStructureError -from ..client import InvalidJSONError -from .base import Base - -STATE_OK = 'OK' -STATE_WARN = 'WARN' -STATE_ERROR = 'ERROR' -STATE_NODATA = 'NODATA' -STATE_EXCEPTION = 'EXCEPTION' - -RISING_TRIGGER = 'rising' -FALLING_TRIGGER = 'falling' -EXPRESSION_TRIGGER = 'expression' - -GRAPHITE_LOCAL = 'graphite_local' -GRAPHITE_REMOTE = 'graphite_remote' -PROMETHEUS_REMOTE = 'prometheus_remote' - -class Trigger(Base): - QUERY_PARAM_VALIDATE_FLAG = 'validate' - - def __init__( - self, - client, - name, - tags, - targets, - team_id=None, - warn_value=None, - error_value=None, - desc='', - ttl=600, - ttl_state=STATE_NODATA, - sched=None, - expression='', - trigger_type=None, - is_remote=False, - mute_new_metrics=False, - alone_metrics=None, - trigger_source=None, - cluster_id=None, - **kwargs): - """ - - :param client: api client - :param team_id: str team id of a team that owns this trigger. - :param name: str trigger name - :param tags: list of str tags for trigger - :param targets: list of str targets - :param warn_value: float warning value (if T1 <= warn_value) - :param error_value: float error value (if T1 <= error_value) - :param desc: str trigger description - :param ttl: int set ttl_state if has no value for ttl seconds - :param ttl_state: str state after ttl seconds without data (one of STATE_* constants) - :param sched: dict schedule for trigger - :param expression: str c-like expression - :param trigger_type: str trigger type - :param is_remote: bool use remote storage - :param mute_new_metrics: bool mute new metrics - :param alone_metrics: dict with targets of alone metrics - :param kwargs: additional parameters - :param trigger_source: str specify trigger source, overrides is_remote - :param cluster_id: str specify cluster id - """ - self._client = client - - self._id = kwargs.get('id', None) - self.team_id = team_id - self.name = name - self.tags = tags - self.targets = targets - self.warn_value = warn_value - self.error_value = error_value - self.desc = desc - self.ttl = ttl - self.ttl_state = ttl_state - self.sched = sched - self.expression = expression - self.trigger_type = self.resolve_type(trigger_type) - - self.is_remote = is_remote - self.trigger_source = trigger_source - self.cluster_id = cluster_id - self.mute_new_metrics = mute_new_metrics - self.alone_metrics = alone_metrics - - def resolve_type(self, trigger_type): - """ - Resolve type of a trigger - :return: str - """ - if trigger_type in (RISING_TRIGGER, FALLING_TRIGGER, EXPRESSION_TRIGGER): - return trigger_type - if self.expression != '': - return EXPRESSION_TRIGGER - if self.warn_value is not None and self.error_value is not None: - if self.warn_value > self.error_value: - return FALLING_TRIGGER - if self.warn_value < self.error_value: - return RISING_TRIGGER - - def add_target(self, target): - """ - Add pattern name - - :param target: str target pattern - :return: None - """ - self.targets.append(target) - - def add_tag(self, tag): - """ - Add tag to trigger - - :param tag: str tag name - :return: None - """ - self.tags.append(tag) - - def disable_day(self, day): - """ - Disable day - - :param day: str one of DAYS_OF_WEEK - :return: None - """ - self.disabled_days.add(day) - - def enable_day(self, day): - """ - Enable day - - :param day: str one of DAYS_OF_WEEK - :return: None - """ - self.disabled_days.remove(day) - - @property - def id(self): - return self._id - - def _send_request(self, trigger_id=None): - data = { - 'name': self.name, - 'team_id': self.team_id, - 'tags': self.tags, - 'targets': self.targets, - 'warn_value': self.warn_value, - 'error_value': self.error_value, - 'desc': self.desc, - 'ttl': self.ttl, - 'ttl_state': self.ttl_state, - 'sched': self.sched, - 'expression': self.expression, - 'is_remote': self.is_remote, - 'trigger_type': self.trigger_type, - 'mute_new_metrics': self.mute_new_metrics, - 'alone_metrics': self.alone_metrics, - } - - if self.trigger_source: - data['trigger_source'] = self.trigger_source - if self.cluster_id: - data['cluster_id'] = self.cluster_id - - if trigger_id: - data['id'] = trigger_id - api_response = TriggerManager(self._client).fetch_by_id(trigger_id) - - if trigger_id and api_response: - res = self._client.put('trigger/{}?{}'.format(trigger_id, self.QUERY_PARAM_VALIDATE_FLAG), json=data) - else: - res = self._client.put('trigger?{}'.format(self.QUERY_PARAM_VALIDATE_FLAG), json=data) - - if 'id' not in res: - raise ResponseStructureError('id not in response', res) - - self._id = res['id'] - return res - - def save(self): - """ - Save trigger - - :return: response object - """ - if self._id: - return self.update() - trigger = self.check_exists() - - if trigger: - self._id = trigger.id - return self.update() - - return self._send_request() - - def update(self): - """ - Update trigger - - :return: response object - """ - return self._send_request(self._id) - - def set_start_hour(self, hour): - """ - Set start hour - - :param hour: int hour - :return: None - """ - self._start_hour = int(hour) - - def set_start_minute(self, minute): - """ - Set start minute - - :param minute: int minute - :return: None - """ - self._start_minute = int(minute) - - def set_end_hour(self, hour): - """ - Set end hour - - :param hour: int hour - :return: None - """ - self._end_hour = int(hour) - - def set_end_minute(self, minute): - """ - Set end minute - - :param minute: int minute - :return: None - """ - self._end_minute = int(minute) - - def check_exists(self): - """ - Check if current trigger exists - - :return: trigger id if exists, None otherwise - """ - trigger_manager = TriggerManager(self._client) - for trigger in trigger_manager.fetch_all(): - if self.name == trigger.name and \ - set(self.targets) == set(trigger.targets) and \ - set(self.tags) == set(trigger.tags): - return trigger - - def get_metrics(self, start, end): - """ - Get metrics associated with certain trigger - - :param start: The start period of metrics to get. Example : -1hour - :param end: The end period of metrics to get. Example : now - - :return: Metrics for trigger - """ - try: - params = { - 'from': start, - 'to': end, - } - result = self._client.get('trigger/{id}/metrics'.format(id=self.id), params=params) - return result - except InvalidJSONError: - return [] - - def delete_metric(self, metric_name): - """ - Deletes metric from last check and all trigger pattern metrics - - :param metric_name: str name of the target metric, example: DevOps.my_server.hdd.freespace_mbytes - - :return: True if success, False otherwise - """ - try: - params = { - 'name': metric_name, - } - self._client.delete('trigger/{id}/metrics'.format(id=self.id), params=params) - return True - except InvalidJSONError: - return False - - def delete_nodata_metrics(self): - """ - Deletes all metrics from last data which are in NODATA state. - It also deletes all trigger patterns of those metrics. - - :return: True if success, False otherwise - """ - try: - self._client.delete('trigger/{id}/metrics/nodata'.format(id=self.id)) - return True - except InvalidJSONError: - return False - - -class TriggerManager: - def __init__(self, client): - self._client = client - - @property - def trigger_client(self): - return self._client - - def fetch_all(self): - """ - Returns all existing triggers - - :return: list of Trigger - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - if 'list' in result: - triggers = [] - for trigger in result['list']: - triggers.append(Trigger(self._client, **trigger)) - return triggers - else: - raise ResponseStructureError("list doesn't exist in response", result) - - def fetch_by_id(self, trigger_id): - """ - Returns Trigger by trigger id - - :param trigger_id: str trigger id - :return: Trigger - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path('{id}/state'.format(id=trigger_id))) - if 'state' in result: - trigger = self._client.get(self._full_path(trigger_id)) - return Trigger(self._client, **trigger) - elif not 'trigger_id' in result: - raise ResponseStructureError("invalid api response", result) - - def search(self, only_problems, page, text, team_id=''): - """ - Search triggers - - :param only_problems: Restricts the result to errors only. Example: false - :param page: Defines the number of the displayed page. E.g, page=2 would display the 2nd page. Example: 1 - :param text: Query to perform a search for. Example: cpu - :param team_id: str team id of a team that owns this trigger. - - :return: matching triggers list - - :raises: ResponseStructureError - """ - params = { - 'onlyProblems': only_problems, - 'page': page, - 'text': text, - 'teamID': team_id, - } - result = self._client.get(self._full_path('search'), params=params) - if 'list' not in result: - raise ResponseStructureError("list doesn't exist in response", result) - - return result['list'] - - def delete(self, trigger_id): - """ - Delete trigger by trigger id - - :param trigger_id: str trigger id - :return: True if deleted, False otherwise - """ - try: - self._client.delete(self._full_path(trigger_id)) - return False - except InvalidJSONError: - return True - - def get_throttling(self, trigger_id): - """ - Get a trigger with its throttling i.e its next allowed message time - - :param trigger_id: str trigger id - :return: trigger throttle value or None - """ - try: - result = self._client.get(self._full_path('{id}/throttling'.format(id=trigger_id))) - if 'throttling' in result: - return result['throttling'] - return None - except InvalidJSONError: - return None - - def reset_throttling(self, trigger_id): - """ - Resets throttling by trigger id - - :param trigger_id: str trigger id - :return: True if reset, False otherwise - """ - try: - self._client.delete(self._full_path('{id}/throttling'.format(id=trigger_id))) - return True - except InvalidJSONError: - return False - - def get_state(self, trigger_id): - """ - Get state of trigger by trigger id - - :param trigger_id: str trigger id - :return: state of trigger - """ - return self._client.get(self._full_path('{id}/state'.format(id=trigger_id))) - - def get_metrics(self, trigger_id, _from, to): - """ - Get metrics associated with certain trigger - - :param trigger_id: str trigger id - :param _from: The start period of metrics to get. Example : -1hour - :param to: The end period of metrics to get. Example : now - - :return: Metrics for trigger - """ - try: - params = { - 'from': _from, - 'to': to, - } - result = self._client.get(self._full_path('{id}/metrics'.format(id=trigger_id)), params=params) - return result - except InvalidJSONError: - return [] - - def remove_metric(self, trigger_id, metric): - """ - Remove metric by trigger id - - :param trigger_id: str trigger id - :param metric: str metric name - :return: True if removed, False otherwise - """ - try: - params = { - 'name': metric - } - self._client.delete(self._full_path('{id}/metrics'.format(id=trigger_id)), params=params) - return True - except InvalidJSONError: - return False - - def remove_nodata_metrics(self, trigger_id): - """ - Remove metric by trigger id - - :param trigger_id: str trigger id - :return: True if removed, False otherwise - """ - try: - self._client.delete(self._full_path('{id}/metrics/nodata'.format(id=trigger_id))) - return True - except InvalidJSONError: - return False - - def is_exist(self, trigger): - """ - Check whether trigger exists or not - - :param trigger: Trigger trigger to check - :return: bool - """ - for moira_trigger in self.fetch_all(): - if trigger.name == moira_trigger.name and \ - set(trigger.targets) == set(moira_trigger.targets) and \ - set(trigger.tags) == set(moira_trigger.tags): - return True - return False - - def get_non_existent(self, triggers): - """ - Returns triggers which are not exist yet - - :param triggers: list of Trigger - :return: list of Trigger - """ - moira_triggers = self.fetch_all() - non_existent = [] - for trigger in triggers: - exist = False - for moira_trigger in moira_triggers: - if trigger.name == moira_trigger.name and \ - set(trigger.targets) == set(moira_trigger.targets) and \ - set(trigger.tags) == set(moira_trigger.tags): - exist = True - break - if not exist: - non_existent.append(trigger) - - return non_existent - - def set_maintenance(self, trigger_id, end_time, metrics=None): - """ - Set maintenance trigger id or metric name - - :param trigger_id: str trigger id - :param metrics: "metric name" - "end-time" map, end-time like param end_time - :param end_time: unix time to end the scheduled maintenance - :return: True if success, False otherwise - """ - try: - data = { - 'trigger': end_time, - } - if metrics is not None: - data['metrics'] = metrics - self._client.put(self._full_path('{id}/setMaintenance'.format(id=trigger_id)), json=data) - return True - except InvalidJSONError: - return False - - def create( - self, - name, - tags, - targets, - team_id=None, - warn_value=None, - error_value=None, - desc='', - ttl=600, - ttl_state=STATE_NODATA, - sched=None, - expression='', - trigger_type=None, - is_remote=False, - mute_new_metrics=False, - alone_metrics=None, - trigger_source=None, - cluster_id=None, - **kwargs - ): - """ - Creates new trigger. To save it call save() method of Trigger. - :param name: str trigger name - :param team_id: str team id of a team that owns this trigger. - :param tags: list of str tags for trigger - :param targets: list of str targets - :param warn_value: float warning value (if T1 <= warn_value) - :param error_value: float error value (if T1 <= error_value) - :param desc: str trigger description - :param ttl: int set ttl_state if has no value for ttl seconds - :param ttl_state: str state after ttl seconds without data (one of STATE_* constants) - :param sched: dict schedule for trigger - :param expression: str c-like expression - :param trigger_type: str trigger type - :param is_remote: bool use remote storage - :param mute_new_metrics: bool mute new metrics - :param alone_metrics: dict with targets of alone metrics - :param kwargs: additional trigger params - :param trigger_source: str specify trigger source, overrides is_remote - :param cluster_id: str specify cluster id - :return: Trigger - """ - return Trigger( - client=self._client, - team_id=team_id, - name=name, - tags=tags, - targets=targets, - warn_value=warn_value, - error_value=error_value, - desc=desc, - ttl=ttl, - ttl_state=ttl_state, - sched=sched, - expression=expression, - trigger_type=trigger_type, - is_remote=is_remote, - mute_new_metrics=mute_new_metrics, - alone_metrics=alone_metrics, - trigger_source=trigger_source, - cluster_id=cluster_id, - **kwargs - ) - - def _full_path(self, path=''): - if path: - return 'trigger/{}'.format(path) - return 'trigger' diff --git a/moira_client/models/user.py b/moira_client/models/user.py deleted file mode 100644 index 5b1c2fe..0000000 --- a/moira_client/models/user.py +++ /dev/null @@ -1,59 +0,0 @@ -from ..client import ResponseStructureError -from .contact import Contact -from .subscription import Subscription - - -class UserSettings: - def __init__(self, login, contacts, subscriptions): - self.login = login - self.contacts = contacts - self.subscriptions = subscriptions - - -class UserManager: - def __init__(self, client): - self._client = client - - def get_username(self): - """ - Gets the username of the authenticated user if it is available. - - :return: login - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path()) - if 'login' not in result: - raise ResponseStructureError("'login' field doesn't exist in response", result) - return result['login'] - - def get_user_settings(self): - """ - Get the user's contacts and subscriptions. - - :return: user settings - - :raises: ResponseStructureError - """ - result = self._client.get(self._full_path('settings')) - required = ['login', 'contacts', 'subscriptions'] - for field in required: - if field not in result: - raise ResponseStructureError("'{}' field doesn't exist in response".format(field), result) - - contacts = [] - for contact in result['contacts']: - contacts.append(Contact(**contact)) - result['contacts'] = contacts - - subscriptions = [] - for subscription in result['subscriptions']: - subscriptions.append(Subscription(self._client, **subscription)) - result['subscriptions'] = subscriptions - - return UserSettings(**result) - - def _full_path(self, path=''): - if path: - return 'user/{}'.format(path) - return 'user' diff --git a/moira_client/moira.py b/moira_client/moira.py deleted file mode 100644 index ade6498..0000000 --- a/moira_client/moira.py +++ /dev/null @@ -1,171 +0,0 @@ -from .client import Client -from .models.contact import ContactManager -from .models.event import EventManager -from .models.notification import NotificationManager -from .models.pattern import PatternManager -from .models.subscription import SubscriptionManager -from .models.tag import TagManager -from .models.system_tag import SystemTagManager -from .models.trigger import TriggerManager -from .models.health import HealthManager -from .models.config import ConfigManager -from .models.user import UserManager -from .models.team import TeamManager - - -class Moira: - def __init__(self, api_url, auth_custom=None, - auth_user=None, auth_pass=None, login=None): - """ - :param api_url: str API URL - :param auth_custom: dict auth custom headers - :param auth_user: str auth user - :param auth_pass: str auth password - :param login: str auth login - """ - self._client = Client(api_url, auth_custom, - auth_user, auth_pass, login) - - self._trigger = None - self._tag = None - self._system_tag = None - self._event = None - self._notification = None - self._contact = None - self._pattern = None - self._subscription = None - self._health = None - self._config = None - self._user = None - self._team = None - - @property - def trigger(self): - """ - Get trigger manager - - :return: TriggerManager - """ - if not self._trigger: - self._trigger = TriggerManager(self._client) - return self._trigger - - @property - def system_tag(self): - """ - Get system tag manager - - :return: SystemTagManager - """ - if not self._system_tag: - self._system_tag = SystemTagManager(self._client) - return self._system_tag - - @property - def tag(self): - """ - Get tag manager - - :return: TagManager - """ - if not self._tag: - self._tag = TagManager(self._client) - return self._tag - - @property - def event(self): - """ - Get event manager - - :return: EventManager - """ - if not self._event: - self._event = EventManager(self._client) - return self._event - - @property - def notification(self): - """ - Get notification manager - - :return: NotificationManager - """ - if not self._notification: - self._notification = NotificationManager(self._client) - return self._notification - - @property - def contact(self): - """ - Get contact manager - - :return: ContactManager - """ - if not self._contact: - self._contact = ContactManager(self._client) - return self._contact - - @property - def pattern(self): - """ - Get pattern manager - - :return: PatternManager - """ - if not self._pattern: - self._pattern = PatternManager(self._client) - return self._pattern - - @property - def subscription(self): - """ - Get subscription manager - - :return: SubscriptionManager - """ - if not self._subscription: - self._subscription = SubscriptionManager(self._client) - return self._subscription - - @property - def health(self): - """ - Get health manager - - :return: HealthManager - """ - if not self._health: - self._health = HealthManager(self._client) - return self._health - - @property - def config(self): - """ - Get config manager - - :return: ConfigManager - """ - if not self._config: - self._config = ConfigManager(self._client) - return self._config - - @property - def user(self): - """ - Get user manager - - :return: UserManager - - """ - if not self._user: - self._user = UserManager(self._client) - return self._user - - @property - def team(self) -> TeamManager: - """Get team manager - """ - if not self._team: - self._team = TeamManager(self._client) - - return self._team diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e1f305a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,98 @@ +[build-system] +requires = ["setuptools~=80.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "python-moira-client" +authors = [{name="Kontur", email = "python@skbkontur.ru"}] +description = "Client for Moira" +readme = "README.md" +requires-python = ">=3.10, <3.15" +dependencies = ["http_toolkit~=1.0", "pydantic~=2.0"] +dynamic = ["version"] # The version is imported from the module attribute specified in section [tool.setuptools.dynamic] + +[project.optional-dependencies] +test = ["pytest~=8.4", "pytest-cov~=7.0", "pytest-asyncio~=1.2", "pytest_httpx>=0.22.0, <0.31.0", "polyfactory~=3.2"] + +[project.urls] +homepage = "https://github.com/moira-alert/python-moira-client" + +[tool.pytest.ini_options] +addopts = "-ra -q --cov-report term-missing --cov moira" + +[tool.ruff] +line-length = 119 +output-format = "grouped" +show-fixes = true +target-version = "py310" +exclude = [".svn", "CVS", ".bzr", ".hg",".git", "__pycache__", ".tox", ".eggs", "*.egg", ".venv", "env", "venv", "build"] + +[tool.ruff.lint] +select = ["W", "E", "F", "I", "N", "DJ", "T20", "Q"] + +[tool.ruff.lint.isort] +combine-as-imports = true + +[tool.ruff.lint.mccabe] +max-complexity = 6 + +[tool.mypy] +ignore_missing_imports = true +explicit_package_bases = true +install_types = true +non_interactive = true +exclude = ["env", "venv", "build"] + +[tool.setuptools.dynamic] +version = {attr = "moira._version.__version__"} + +[tool.coverage.run] +omit = ["**/_version.py"] + +[tool.tox] +requires = ["tox~=4.53"] +env_list = [ + "pyproject", + "lint", + "format", + "mypy", + {prefix = "py3", start = 10, stop = 14}, + {prefix = "pypy3", start = 10, stop = 11}, +] + +[tool.tox.env_run_base.set_env] +PIP_INDEX_URL = "{env:PIP_INDEX_URL:https://pypi.kontur.host/}" +UV_DEFAULT_INDEX = "{env:UV_DEFAULT_INDEX:https://pypi.kontur.host/}" +PYTHONUTF8 = "1" + +[tool.tox.env_run_base] +extras = ["test"] +allowlist_externals = ["coverage"] +commands = [ + ["pytest", "--junitxml=.reports/{envname}_junit.xml", "{posargs}"] +] +commands_post = [ + { replace = "if", condition = "not (factor.lint or factor.pyproject or factor.format or factor.mypy)", then = [ + ["coverage", "xml", "-o", ".reports/{envname}_coverage.xml"] + ], extend = true }, +] + +[tool.tox.env.pyproject] +skip_install = true +deps = ["validate-pyproject[all]~=0.24.0"] +commands = [["validate-pyproject", "pyproject.toml"]] + +[tool.tox.env.mypy] +skip_install = true +deps = ["mypy~=1.18"] +commands = [["mypy", "--junit-xml", ".reports/{env:TOX_ENV_NAME}_junit.xml", "."]] + +[tool.tox.env.lint] +skip_install = true +deps = ["ruff~=0.14.0"] +commands = [["ruff", "check", ".", "--output-format=full"]] + +[tool.tox.env.format] +skip_install = true +deps = ["ruff~=0.14.0"] +commands = [["ruff", "format", "--diff", "."]] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 2379e6b..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests>=2.4.3 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b88034e..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -description-file = README.md diff --git a/setup.py b/setup.py deleted file mode 100644 index 903a5f1..0000000 --- a/setup.py +++ /dev/null @@ -1,53 +0,0 @@ -from distutils.core import setup - -with open('requirements.txt') as f: - required = f.read().splitlines() - -with open("VERSION.txt", "r") as file: - version = file.readline() - -setup( - name='moira-python-client', - version=version, - description='Client for Moira - Alerting system based on Graphite data', - keywords='moira monitoring client metrics alerting', - long_description=""" - Moira is a real-time alerting tool, based on Graphite data. - moira-client is a python client for Moira API. - Key features: - - create, update, delete, manage triggers - - create, delete, update subscriptions - - manage tags, patterns, notifications, events, contacts - """, - author = 'Alexander Lukyanchenko', - author_email = 'al.lukyanchenko@gmail.com', - packages=[ - 'moira_client', - 'moira_client.models', - 'moira_client.models.team', - 'moira_client.models.team.contact', - 'moira_client.models.team.settings', - 'moira_client.models.team.subscription', - 'moira_client.models.team.user', - ], - classifiers=[ - 'Development Status :: 4 - Beta', - - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - - 'Operating System :: OS Independent', - 'Intended Audience :: Developers', - - 'Topic :: Software Development :: Libraries', - 'Topic :: Utilities', - 'Topic :: System :: Monitoring', - - "License :: OSI Approved :: MIT License" - ], - url='https://github.com/moira-alert/python-moira-client', - install_requires=required -) diff --git a/tests/models/__init__.py b/src/moira/__init__.py similarity index 100% rename from tests/models/__init__.py rename to src/moira/__init__.py diff --git a/src/moira/_error_handler.py b/src/moira/_error_handler.py new file mode 100644 index 0000000..f1f08c7 --- /dev/null +++ b/src/moira/_error_handler.py @@ -0,0 +1,21 @@ +from contextlib import contextmanager +from typing import Type + +from httptoolkit.errors import HttpError + +from moira.exceptions import MoiraApiError, MoiraServerError + + +class ErrorHandler: + def __init__(self, error_class: Type[MoiraApiError]): + self._error_class = error_class + + @contextmanager + def handle(self): + try: + yield + except HttpError as error: + response = error.response + if 400 <= response.status_code < 500: + raise self._error_class(response=response) from error + raise MoiraServerError(response.reason) from error diff --git a/src/moira/_version.py b/src/moira/_version.py new file mode 100644 index 0000000..3d4dd23 --- /dev/null +++ b/src/moira/_version.py @@ -0,0 +1,3 @@ +from os import environ + +__version__ = environ.get("CI_COMMIT_TAG") or "0.dev0" diff --git a/src/moira/clients/__init__.py b/src/moira/clients/__init__.py new file mode 100644 index 0000000..aeeeb09 --- /dev/null +++ b/src/moira/clients/__init__.py @@ -0,0 +1,7 @@ +from ._async import MoiraClientAsync +from ._sync import MoiraClient + +__all__ = [ + "MoiraClient", + "MoiraClientAsync", +] diff --git a/src/moira/clients/_async.py b/src/moira/clients/_async.py new file mode 100644 index 0000000..00ad5c5 --- /dev/null +++ b/src/moira/clients/_async.py @@ -0,0 +1,749 @@ +from typing import Any, Type + +from httptoolkit import AsyncService, Header +from httptoolkit.transport import AsyncHttpxTransport, BaseAsyncTransport +from pydantic import BaseModel + +from moira._error_handler import ErrorHandler +from moira.exceptions import MoiraApiError +from moira.models.requests import ( + AddTeamUsersPathParams, + CreateNewTeamContactPathParams, + CreateNewTeamSubscriptionPathParams, + CreateTriggerQueryParams, + DeleteNotificationQueryParams, + DeleteNotificationsFilteredQueryParams, + DeletePagerQueryParams, + DeletePatternPathParams, + DeleteTeamPathParams, + DeleteTeamUserPathParams, + DeleteTriggerMetricPathParams, + DeleteTriggerMetricQueryParams, + DeleteTriggerNodataMetricsPathParams, + DeleteTriggerThrottlingPathParams, + GetAllHeavyTriggersQueryParams, + GetAllTeamsQueryParams, + GetContactByIdPathParams, + GetContactEventsByIdPathParams, + GetContactEventsByIdQueryParams, + GetContactsNoisinessQueryParams, + GetEventsListPathParams, + GetEventsListQueryParams, + GetNotificationsQueryParams, + GetSubscriptionPathParams, + GetTeamPathParams, + GetTeamSettingsPathParams, + GetTeamUsersPathParams, + GetTriggerDumpPathParams, + GetTriggerMetricsPathParams, + GetTriggerMetricsQueryParams, + GetTriggerPathParams, + GetTriggerQueryParams, + GetTriggersNoisinessQueryParams, + GetTriggerStatePathParams, + GetTriggerThrottlingPathParams, + RemoveContactPathParams, + RemoveSubscriptionPathParams, + RemoveTagPathParams, + RemoveTriggerPathParams, + RenderTriggerMetricsPathParams, + RenderTriggerMetricsQueryParams, + SearchTriggersQueryParams, + SendTestContactNotificationPathParams, + SendTestNotificationPathParams, + SetTeamUsersPathParams, + SetTriggerMaintenancePathParams, + UpdateContactPathParams, + UpdateSubscriptionPathParams, + UpdateTeamPathParams, + UpdateTriggerPathParams, + UpdateTriggerQueryParams, +) +from moira.models.responses import ( + ApiWebConfig, + DtoContact, + DtoContactEventItemList, + DtoContactList, + DtoContactNoisinessList, + DtoEventsList, + DtoMessageResponse, + DtoNotificationDeleteResponse, + DtoNotificationsList, + DtoNotifierState, + DtoNotifierStatesForSources, + DtoPatternList, + DtoSaveTeamResponse, + DtoSaveTriggerResponse, + DtoSubscription, + DtoSubscriptionList, + DtoTagsData, + DtoTagsStatistics, + DtoTeamMembers, + DtoTeamModel, + DtoTeamSettings, + DtoTeamsList, + DtoThrottlingResponse, + DtoTrigger, + DtoTriggerCheck, + DtoTriggerCheckResponse, + DtoTriggerDump, + DtoTriggerMaintenance, + DtoTriggerNoisinessList, + DtoTriggersList, + DtoTriggersSearchResultDeleteResponse, + DtoUser, + DtoUserSettings, + DtoUserTeams, +) + + +class MoiraClientAsync(AsyncService): + def __init__( + self, + headers: tuple[Header, ...] = (), + error_class: Type[MoiraApiError] = MoiraApiError, + transport: BaseAsyncTransport = None, + *args, + **kwargs, + ) -> None: + super().__init__(transport=transport or AsyncHttpxTransport(*args, **kwargs), headers=headers) + self._error_handler = ErrorHandler(error_class) + + @staticmethod + def convert_headers(headers: BaseModel | None = None) -> tuple[Header, ...]: + if headers is None: + return () + + return tuple( + Header(name=name, value=value, is_sensitive=False) for name, value in headers.model_dump().items() + ) + + async def get_web_config( + self, + ) -> ApiWebConfig: + path = "/config" + with self._error_handler.handle(): + response = await self.get(path) + return ApiWebConfig.model_validate(response.json()) + + async def get_all_contacts( + self, + ) -> DtoContactList: + path = "/contact" + with self._error_handler.handle(): + response = await self.get(path) + return DtoContactList.model_validate(response.json()) + + async def get_contact_by_id( + self, + path_params: GetContactByIdPathParams, + ) -> DtoContact: + path = "/contact/{contactID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoContact.model_validate(response.json()) + + async def get_contact_events_by_id( + self, + path_params: GetContactEventsByIdPathParams, + query_params: GetContactEventsByIdQueryParams, + ) -> DtoContactEventItemList: + path = "/contact/{contactID}/events".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoContactEventItemList.model_validate(response.json()) + + async def get_contacts_noisiness( + self, + query_params: GetContactsNoisinessQueryParams, + ) -> DtoContactNoisinessList: + path = "/contact/noisiness" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoContactNoisinessList.model_validate(response.json()) + + async def get_events_list( + self, + path_params: GetEventsListPathParams, + query_params: GetEventsListQueryParams, + ) -> DtoEventsList: + path = "/event/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoEventsList.model_validate(response.json()) + + async def get_notifier_state_for_sources( + self, + ) -> DtoNotifierStatesForSources: + path = "/health/notifier" + with self._error_handler.handle(): + response = await self.get(path) + return DtoNotifierStatesForSources.model_validate(response.json()) + + async def get_system_subscription( + self, + ) -> DtoSubscriptionList: + path = "/health/system-subscriptions" + with self._error_handler.handle(): + response = await self.get(path) + return DtoSubscriptionList.model_validate(response.json()) + + async def get_notifications( + self, + query_params: GetNotificationsQueryParams, + ) -> DtoNotificationsList: + path = "/notification" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoNotificationsList.model_validate(response.json()) + + async def get_all_patterns( + self, + ) -> DtoPatternList: + path = "/pattern" + with self._error_handler.handle(): + response = await self.get(path) + return DtoPatternList.model_validate(response.json()) + + async def get_user_subscriptions( + self, + ) -> DtoSubscriptionList: + path = "/subscription" + with self._error_handler.handle(): + response = await self.get(path) + return DtoSubscriptionList.model_validate(response.json()) + + async def get_subscription( + self, + path_params: GetSubscriptionPathParams, + ) -> DtoSubscription: + path = "/subscription/{subscriptionID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoSubscription.model_validate(response.json()) + + async def get_all_system_tags( + self, + ) -> DtoTagsData: + path = "/system-tag" + with self._error_handler.handle(): + response = await self.get(path) + return DtoTagsData.model_validate(response.json()) + + async def get_all_tags( + self, + ) -> DtoTagsData: + path = "/tag" + with self._error_handler.handle(): + response = await self.get(path) + return DtoTagsData.model_validate(response.json()) + + async def get_all_tags_and_subscriptions( + self, + ) -> DtoTagsStatistics: + path = "/tag/stats" + with self._error_handler.handle(): + response = await self.get(path) + return DtoTagsStatistics.model_validate(response.json()) + + async def get_all_teams_for_user( + self, + ) -> DtoUserTeams: + path = "/teams" + with self._error_handler.handle(): + response = await self.get(path) + return DtoUserTeams.model_validate(response.json()) + + async def get_team( + self, + path_params: GetTeamPathParams, + ) -> DtoTeamModel: + path = "/teams/{teamID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoTeamModel.model_validate(response.json()) + + async def get_team_settings( + self, + path_params: GetTeamSettingsPathParams, + ) -> DtoTeamSettings: + path = "/teams/{teamID}/settings".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoTeamSettings.model_validate(response.json()) + + async def get_team_users( + self, + path_params: GetTeamUsersPathParams, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoTeamMembers.model_validate(response.json()) + + async def get_all_teams( + self, + query_params: GetAllTeamsQueryParams, + ) -> DtoTeamsList: + path = "/teams/all" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoTeamsList.model_validate(response.json()) + + async def get_all_triggers( + self, + ) -> DtoTriggersList: + path = "/trigger" + with self._error_handler.handle(): + response = await self.get(path) + return DtoTriggersList.model_validate(response.json()) + + async def get_trigger( + self, + path_params: GetTriggerPathParams, + query_params: GetTriggerQueryParams, + ) -> DtoTrigger: + path = "/trigger/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoTrigger.model_validate(response.json()) + + async def get_trigger_dump( + self, + path_params: GetTriggerDumpPathParams, + ) -> DtoTriggerDump: + path = "/trigger/{triggerID}/dump".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoTriggerDump.model_validate(response.json()) + + async def get_trigger_metrics( + self, + path_params: GetTriggerMetricsPathParams, + query_params: GetTriggerMetricsQueryParams, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/metrics".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return response.json() + + async def render_trigger_metrics( + self, + path_params: RenderTriggerMetricsPathParams, + query_params: RenderTriggerMetricsQueryParams, + ) -> bytes: + path = "/trigger/{triggerID}/render".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return response.content + + async def get_trigger_state( + self, + path_params: GetTriggerStatePathParams, + ) -> DtoTriggerCheck: + path = "/trigger/{triggerID}/state".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoTriggerCheck.model_validate(response.json()) + + async def get_trigger_throttling( + self, + path_params: GetTriggerThrottlingPathParams, + ) -> DtoThrottlingResponse: + path = "/trigger/{triggerID}/throttling".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.get(path) + return DtoThrottlingResponse.model_validate(response.json()) + + async def get_all_heavy_triggers( + self, + query_params: GetAllHeavyTriggersQueryParams, + ) -> DtoTriggersList: + path = "/trigger/heavy" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoTriggersList.model_validate(response.json()) + + async def get_triggers_noisiness( + self, + query_params: GetTriggersNoisinessQueryParams, + ) -> DtoTriggerNoisinessList: + path = "/trigger/noisiness" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoTriggerNoisinessList.model_validate(response.json()) + + async def search_triggers( + self, + query_params: SearchTriggersQueryParams, + ) -> DtoTriggersList: + path = "/trigger/search" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.get(path, params=params) + return DtoTriggersList.model_validate(response.json()) + + async def get_unused_triggers( + self, + ) -> DtoTriggersList: + path = "/trigger/unused" + with self._error_handler.handle(): + response = await self.get(path) + return DtoTriggersList.model_validate(response.json()) + + async def get_user_name( + self, + ) -> DtoUser: + path = "/user" + with self._error_handler.handle(): + response = await self.get(path) + return DtoUser.model_validate(response.json()) + + async def get_user_settings( + self, + ) -> DtoUserSettings: + path = "/user/settings" + with self._error_handler.handle(): + response = await self.get(path) + return DtoUserSettings.model_validate(response.json()) + + async def send_test_contact_notification( + self, + path_params: SendTestContactNotificationPathParams, + body: dict[Any, Any], + ) -> dict[Any, Any]: + path = "/contact/{contactID}/test".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body + with self._error_handler.handle(): + response = await self.post(path, json=json) + return response.json() + + async def create_tags( + self, + body: DtoTagsData, + ) -> str: + path = "/tag" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.post(path, json=json) + return response.text + + async def create_team( + self, + body: DtoTeamModel, + ) -> DtoSaveTeamResponse: + path = "/teams" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.post(path, json=json) + return DtoSaveTeamResponse.model_validate(response.json()) + + async def create_new_team_contact( + self, + path_params: CreateNewTeamContactPathParams, + body: DtoContact, + ) -> DtoContact: + path = "/teams/{teamID}/contacts".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.post(path, json=json) + return DtoContact.model_validate(response.json()) + + async def create_new_team_subscription( + self, + path_params: CreateNewTeamSubscriptionPathParams, + body: DtoSubscription, + ) -> DtoSubscription: + path = "/teams/{teamID}/subscriptions".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.post(path, json=json) + return DtoSubscription.model_validate(response.json()) + + async def add_team_users( + self, + path_params: AddTeamUsersPathParams, + body: DtoTeamMembers, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.post(path, json=json) + return DtoTeamMembers.model_validate(response.json()) + + async def update_team( + self, + path_params: UpdateTeamPathParams, + body: DtoTeamModel, + ) -> DtoSaveTeamResponse: + path = "/teams/{teamID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.patch(path, json=json) + return DtoSaveTeamResponse.model_validate(response.json()) + + async def create_new_contact( + self, + body: DtoContact, + ) -> DtoContact: + path = "/contact" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return DtoContact.model_validate(response.json()) + + async def update_contact( + self, + path_params: UpdateContactPathParams, + body: DtoContact, + ) -> DtoContact: + path = "/contact/{contactID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return DtoContact.model_validate(response.json()) + + async def set_notifier_state( + self, + ) -> DtoNotifierState: + path = "/health/notifier" + with self._error_handler.handle(): + response = await self.put(path) + return DtoNotifierState.model_validate(response.json()) + + async def create_subscription( + self, + body: DtoSubscription, + ) -> DtoSubscription: + path = "/subscription" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return DtoSubscription.model_validate(response.json()) + + async def update_subscription( + self, + path_params: UpdateSubscriptionPathParams, + body: DtoSubscription, + ) -> DtoSubscription: + path = "/subscription/{subscriptionID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return DtoSubscription.model_validate(response.json()) + + async def send_test_notification( + self, + path_params: SendTestNotificationPathParams, + ) -> dict[Any, Any]: + path = "/subscription/{subscriptionID}/test".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.put(path) + return response.json() + + async def set_team_users( + self, + path_params: SetTeamUsersPathParams, + body: DtoTeamMembers, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return DtoTeamMembers.model_validate(response.json()) + + async def create_trigger( + self, + query_params: CreateTriggerQueryParams, + body: DtoTrigger, + ) -> DtoSaveTriggerResponse: + path = "/trigger" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json, params=params) + return DtoSaveTriggerResponse.model_validate(response.json()) + + async def update_trigger( + self, + path_params: UpdateTriggerPathParams, + query_params: UpdateTriggerQueryParams, + body: DtoTrigger, + ) -> DtoSaveTriggerResponse: + path = "/trigger/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json, params=params) + return DtoSaveTriggerResponse.model_validate(response.json()) + + async def set_trigger_maintenance( + self, + path_params: SetTriggerMaintenancePathParams, + body: DtoTriggerMaintenance, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/setMaintenance".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return response.json() + + async def trigger_check( + self, + body: DtoTrigger, + ) -> DtoTriggerCheckResponse: + path = "/trigger/check" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = await self.put(path, json=json) + return DtoTriggerCheckResponse.model_validate(response.json()) + + async def remove_contact( + self, + path_params: RemoveContactPathParams, + body: dict[Any, Any], + ) -> dict[Any, Any]: + path = "/contact/{contactID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body + with self._error_handler.handle(): + response = await self.delete(path, json=json) + return response.json() + + async def delete_all_events( + self, + ) -> dict[Any, Any]: + path = "/event/all" + with self._error_handler.handle(): + response = await self.delete(path) + return response.json() + + async def delete_notification( + self, + query_params: DeleteNotificationQueryParams, + ) -> DtoNotificationDeleteResponse: + path = "/notification" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.delete(path, params=params) + return DtoNotificationDeleteResponse.model_validate(response.json()) + + async def delete_all_notifications( + self, + ) -> DtoNotificationsList: + path = "/notification/all" + with self._error_handler.handle(): + response = await self.delete(path) + return DtoNotificationsList.model_validate(response.json()) + + async def delete_notifications_filtered( + self, + query_params: DeleteNotificationsFilteredQueryParams, + ) -> DtoNotificationsList: + path = "/notification/filtered" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.delete(path, params=params) + return DtoNotificationsList.model_validate(response.json()) + + async def delete_pattern( + self, + path_params: DeletePatternPathParams, + ) -> dict[Any, Any]: + path = "/pattern/{pattern}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.delete(path) + return response.json() + + async def remove_subscription( + self, + path_params: RemoveSubscriptionPathParams, + ) -> dict[Any, Any]: + path = "/subscription/{subscriptionID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.delete(path) + return response.json() + + async def remove_tag( + self, + path_params: RemoveTagPathParams, + ) -> DtoMessageResponse: + path = "/tag/{tag}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.delete(path) + return DtoMessageResponse.model_validate(response.json()) + + async def delete_team( + self, + path_params: DeleteTeamPathParams, + ) -> DtoSaveTeamResponse: + path = "/teams/{teamID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.delete(path) + return DtoSaveTeamResponse.model_validate(response.json()) + + async def delete_team_user( + self, + path_params: DeleteTeamUserPathParams, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users/{teamUserID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.delete(path) + return DtoTeamMembers.model_validate(response.json()) + + async def remove_trigger( + self, + path_params: RemoveTriggerPathParams, + ) -> None: + path = "/trigger/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + await self.delete(path) + return None + + async def delete_trigger_metric( + self, + path_params: DeleteTriggerMetricPathParams, + query_params: DeleteTriggerMetricQueryParams, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/metrics".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.delete(path, params=params) + return response.json() + + async def delete_trigger_nodata_metrics( + self, + path_params: DeleteTriggerNodataMetricsPathParams, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/metrics/nodata".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = await self.delete(path) + return response.json() + + async def delete_trigger_throttling( + self, + path_params: DeleteTriggerThrottlingPathParams, + ) -> None: + path = "/trigger/{triggerID}/throttling".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + await self.delete(path) + return None + + async def delete_pager( + self, + query_params: DeletePagerQueryParams, + ) -> DtoTriggersSearchResultDeleteResponse: + path = "/trigger/search/pager" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = await self.delete(path, params=params) + return DtoTriggersSearchResultDeleteResponse.model_validate(response.json()) diff --git a/src/moira/clients/_sync.py b/src/moira/clients/_sync.py new file mode 100644 index 0000000..0aaaa45 --- /dev/null +++ b/src/moira/clients/_sync.py @@ -0,0 +1,749 @@ +from typing import Any, Type + +from httptoolkit import Header, Service +from httptoolkit.transport import BaseTransport, HttpxTransport +from pydantic import BaseModel + +from moira._error_handler import ErrorHandler +from moira.exceptions import MoiraApiError +from moira.models.requests import ( + AddTeamUsersPathParams, + CreateNewTeamContactPathParams, + CreateNewTeamSubscriptionPathParams, + CreateTriggerQueryParams, + DeleteNotificationQueryParams, + DeleteNotificationsFilteredQueryParams, + DeletePagerQueryParams, + DeletePatternPathParams, + DeleteTeamPathParams, + DeleteTeamUserPathParams, + DeleteTriggerMetricPathParams, + DeleteTriggerMetricQueryParams, + DeleteTriggerNodataMetricsPathParams, + DeleteTriggerThrottlingPathParams, + GetAllHeavyTriggersQueryParams, + GetAllTeamsQueryParams, + GetContactByIdPathParams, + GetContactEventsByIdPathParams, + GetContactEventsByIdQueryParams, + GetContactsNoisinessQueryParams, + GetEventsListPathParams, + GetEventsListQueryParams, + GetNotificationsQueryParams, + GetSubscriptionPathParams, + GetTeamPathParams, + GetTeamSettingsPathParams, + GetTeamUsersPathParams, + GetTriggerDumpPathParams, + GetTriggerMetricsPathParams, + GetTriggerMetricsQueryParams, + GetTriggerPathParams, + GetTriggerQueryParams, + GetTriggersNoisinessQueryParams, + GetTriggerStatePathParams, + GetTriggerThrottlingPathParams, + RemoveContactPathParams, + RemoveSubscriptionPathParams, + RemoveTagPathParams, + RemoveTriggerPathParams, + RenderTriggerMetricsPathParams, + RenderTriggerMetricsQueryParams, + SearchTriggersQueryParams, + SendTestContactNotificationPathParams, + SendTestNotificationPathParams, + SetTeamUsersPathParams, + SetTriggerMaintenancePathParams, + UpdateContactPathParams, + UpdateSubscriptionPathParams, + UpdateTeamPathParams, + UpdateTriggerPathParams, + UpdateTriggerQueryParams, +) +from moira.models.responses import ( + ApiWebConfig, + DtoContact, + DtoContactEventItemList, + DtoContactList, + DtoContactNoisinessList, + DtoEventsList, + DtoMessageResponse, + DtoNotificationDeleteResponse, + DtoNotificationsList, + DtoNotifierState, + DtoNotifierStatesForSources, + DtoPatternList, + DtoSaveTeamResponse, + DtoSaveTriggerResponse, + DtoSubscription, + DtoSubscriptionList, + DtoTagsData, + DtoTagsStatistics, + DtoTeamMembers, + DtoTeamModel, + DtoTeamSettings, + DtoTeamsList, + DtoThrottlingResponse, + DtoTrigger, + DtoTriggerCheck, + DtoTriggerCheckResponse, + DtoTriggerDump, + DtoTriggerMaintenance, + DtoTriggerNoisinessList, + DtoTriggersList, + DtoTriggersSearchResultDeleteResponse, + DtoUser, + DtoUserSettings, + DtoUserTeams, +) + + +class MoiraClient(Service): + def __init__( + self, + headers: tuple[Header, ...] = (), + error_class: Type[MoiraApiError] = MoiraApiError, + transport: BaseTransport = None, + *args, + **kwargs, + ) -> None: + super().__init__(transport=transport or HttpxTransport(*args, **kwargs), headers=headers) + self._error_handler = ErrorHandler(error_class) + + @staticmethod + def convert_headers(headers: BaseModel | None = None) -> tuple[Header, ...]: + if headers is None: + return () + + return tuple( + Header(name=name, value=value, is_sensitive=False) for name, value in headers.model_dump().items() + ) + + def get_web_config( + self, + ) -> ApiWebConfig: + path = "/config" + with self._error_handler.handle(): + response = self.get(path) + return ApiWebConfig.model_validate(response.json()) + + def get_all_contacts( + self, + ) -> DtoContactList: + path = "/contact" + with self._error_handler.handle(): + response = self.get(path) + return DtoContactList.model_validate(response.json()) + + def get_contact_by_id( + self, + path_params: GetContactByIdPathParams, + ) -> DtoContact: + path = "/contact/{contactID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoContact.model_validate(response.json()) + + def get_contact_events_by_id( + self, + path_params: GetContactEventsByIdPathParams, + query_params: GetContactEventsByIdQueryParams, + ) -> DtoContactEventItemList: + path = "/contact/{contactID}/events".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoContactEventItemList.model_validate(response.json()) + + def get_contacts_noisiness( + self, + query_params: GetContactsNoisinessQueryParams, + ) -> DtoContactNoisinessList: + path = "/contact/noisiness" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoContactNoisinessList.model_validate(response.json()) + + def get_events_list( + self, + path_params: GetEventsListPathParams, + query_params: GetEventsListQueryParams, + ) -> DtoEventsList: + path = "/event/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoEventsList.model_validate(response.json()) + + def get_notifier_state_for_sources( + self, + ) -> DtoNotifierStatesForSources: + path = "/health/notifier" + with self._error_handler.handle(): + response = self.get(path) + return DtoNotifierStatesForSources.model_validate(response.json()) + + def get_system_subscription( + self, + ) -> DtoSubscriptionList: + path = "/health/system-subscriptions" + with self._error_handler.handle(): + response = self.get(path) + return DtoSubscriptionList.model_validate(response.json()) + + def get_notifications( + self, + query_params: GetNotificationsQueryParams, + ) -> DtoNotificationsList: + path = "/notification" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoNotificationsList.model_validate(response.json()) + + def get_all_patterns( + self, + ) -> DtoPatternList: + path = "/pattern" + with self._error_handler.handle(): + response = self.get(path) + return DtoPatternList.model_validate(response.json()) + + def get_user_subscriptions( + self, + ) -> DtoSubscriptionList: + path = "/subscription" + with self._error_handler.handle(): + response = self.get(path) + return DtoSubscriptionList.model_validate(response.json()) + + def get_subscription( + self, + path_params: GetSubscriptionPathParams, + ) -> DtoSubscription: + path = "/subscription/{subscriptionID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoSubscription.model_validate(response.json()) + + def get_all_system_tags( + self, + ) -> DtoTagsData: + path = "/system-tag" + with self._error_handler.handle(): + response = self.get(path) + return DtoTagsData.model_validate(response.json()) + + def get_all_tags( + self, + ) -> DtoTagsData: + path = "/tag" + with self._error_handler.handle(): + response = self.get(path) + return DtoTagsData.model_validate(response.json()) + + def get_all_tags_and_subscriptions( + self, + ) -> DtoTagsStatistics: + path = "/tag/stats" + with self._error_handler.handle(): + response = self.get(path) + return DtoTagsStatistics.model_validate(response.json()) + + def get_all_teams_for_user( + self, + ) -> DtoUserTeams: + path = "/teams" + with self._error_handler.handle(): + response = self.get(path) + return DtoUserTeams.model_validate(response.json()) + + def get_team( + self, + path_params: GetTeamPathParams, + ) -> DtoTeamModel: + path = "/teams/{teamID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoTeamModel.model_validate(response.json()) + + def get_team_settings( + self, + path_params: GetTeamSettingsPathParams, + ) -> DtoTeamSettings: + path = "/teams/{teamID}/settings".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoTeamSettings.model_validate(response.json()) + + def get_team_users( + self, + path_params: GetTeamUsersPathParams, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoTeamMembers.model_validate(response.json()) + + def get_all_teams( + self, + query_params: GetAllTeamsQueryParams, + ) -> DtoTeamsList: + path = "/teams/all" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoTeamsList.model_validate(response.json()) + + def get_all_triggers( + self, + ) -> DtoTriggersList: + path = "/trigger" + with self._error_handler.handle(): + response = self.get(path) + return DtoTriggersList.model_validate(response.json()) + + def get_trigger( + self, + path_params: GetTriggerPathParams, + query_params: GetTriggerQueryParams, + ) -> DtoTrigger: + path = "/trigger/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoTrigger.model_validate(response.json()) + + def get_trigger_dump( + self, + path_params: GetTriggerDumpPathParams, + ) -> DtoTriggerDump: + path = "/trigger/{triggerID}/dump".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoTriggerDump.model_validate(response.json()) + + def get_trigger_metrics( + self, + path_params: GetTriggerMetricsPathParams, + query_params: GetTriggerMetricsQueryParams, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/metrics".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return response.json() + + def render_trigger_metrics( + self, + path_params: RenderTriggerMetricsPathParams, + query_params: RenderTriggerMetricsQueryParams, + ) -> bytes: + path = "/trigger/{triggerID}/render".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return response.content + + def get_trigger_state( + self, + path_params: GetTriggerStatePathParams, + ) -> DtoTriggerCheck: + path = "/trigger/{triggerID}/state".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoTriggerCheck.model_validate(response.json()) + + def get_trigger_throttling( + self, + path_params: GetTriggerThrottlingPathParams, + ) -> DtoThrottlingResponse: + path = "/trigger/{triggerID}/throttling".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.get(path) + return DtoThrottlingResponse.model_validate(response.json()) + + def get_all_heavy_triggers( + self, + query_params: GetAllHeavyTriggersQueryParams, + ) -> DtoTriggersList: + path = "/trigger/heavy" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoTriggersList.model_validate(response.json()) + + def get_triggers_noisiness( + self, + query_params: GetTriggersNoisinessQueryParams, + ) -> DtoTriggerNoisinessList: + path = "/trigger/noisiness" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoTriggerNoisinessList.model_validate(response.json()) + + def search_triggers( + self, + query_params: SearchTriggersQueryParams, + ) -> DtoTriggersList: + path = "/trigger/search" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.get(path, params=params) + return DtoTriggersList.model_validate(response.json()) + + def get_unused_triggers( + self, + ) -> DtoTriggersList: + path = "/trigger/unused" + with self._error_handler.handle(): + response = self.get(path) + return DtoTriggersList.model_validate(response.json()) + + def get_user_name( + self, + ) -> DtoUser: + path = "/user" + with self._error_handler.handle(): + response = self.get(path) + return DtoUser.model_validate(response.json()) + + def get_user_settings( + self, + ) -> DtoUserSettings: + path = "/user/settings" + with self._error_handler.handle(): + response = self.get(path) + return DtoUserSettings.model_validate(response.json()) + + def send_test_contact_notification( + self, + path_params: SendTestContactNotificationPathParams, + body: dict[Any, Any], + ) -> dict[Any, Any]: + path = "/contact/{contactID}/test".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body + with self._error_handler.handle(): + response = self.post(path, json=json) + return response.json() + + def create_tags( + self, + body: DtoTagsData, + ) -> str: + path = "/tag" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.post(path, json=json) + return response.text + + def create_team( + self, + body: DtoTeamModel, + ) -> DtoSaveTeamResponse: + path = "/teams" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.post(path, json=json) + return DtoSaveTeamResponse.model_validate(response.json()) + + def create_new_team_contact( + self, + path_params: CreateNewTeamContactPathParams, + body: DtoContact, + ) -> DtoContact: + path = "/teams/{teamID}/contacts".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.post(path, json=json) + return DtoContact.model_validate(response.json()) + + def create_new_team_subscription( + self, + path_params: CreateNewTeamSubscriptionPathParams, + body: DtoSubscription, + ) -> DtoSubscription: + path = "/teams/{teamID}/subscriptions".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.post(path, json=json) + return DtoSubscription.model_validate(response.json()) + + def add_team_users( + self, + path_params: AddTeamUsersPathParams, + body: DtoTeamMembers, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.post(path, json=json) + return DtoTeamMembers.model_validate(response.json()) + + def update_team( + self, + path_params: UpdateTeamPathParams, + body: DtoTeamModel, + ) -> DtoSaveTeamResponse: + path = "/teams/{teamID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.patch(path, json=json) + return DtoSaveTeamResponse.model_validate(response.json()) + + def create_new_contact( + self, + body: DtoContact, + ) -> DtoContact: + path = "/contact" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return DtoContact.model_validate(response.json()) + + def update_contact( + self, + path_params: UpdateContactPathParams, + body: DtoContact, + ) -> DtoContact: + path = "/contact/{contactID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return DtoContact.model_validate(response.json()) + + def set_notifier_state( + self, + ) -> DtoNotifierState: + path = "/health/notifier" + with self._error_handler.handle(): + response = self.put(path) + return DtoNotifierState.model_validate(response.json()) + + def create_subscription( + self, + body: DtoSubscription, + ) -> DtoSubscription: + path = "/subscription" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return DtoSubscription.model_validate(response.json()) + + def update_subscription( + self, + path_params: UpdateSubscriptionPathParams, + body: DtoSubscription, + ) -> DtoSubscription: + path = "/subscription/{subscriptionID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return DtoSubscription.model_validate(response.json()) + + def send_test_notification( + self, + path_params: SendTestNotificationPathParams, + ) -> dict[Any, Any]: + path = "/subscription/{subscriptionID}/test".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.put(path) + return response.json() + + def set_team_users( + self, + path_params: SetTeamUsersPathParams, + body: DtoTeamMembers, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return DtoTeamMembers.model_validate(response.json()) + + def create_trigger( + self, + query_params: CreateTriggerQueryParams, + body: DtoTrigger, + ) -> DtoSaveTriggerResponse: + path = "/trigger" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json, params=params) + return DtoSaveTriggerResponse.model_validate(response.json()) + + def update_trigger( + self, + path_params: UpdateTriggerPathParams, + query_params: UpdateTriggerQueryParams, + body: DtoTrigger, + ) -> DtoSaveTriggerResponse: + path = "/trigger/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json, params=params) + return DtoSaveTriggerResponse.model_validate(response.json()) + + def set_trigger_maintenance( + self, + path_params: SetTriggerMaintenancePathParams, + body: DtoTriggerMaintenance, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/setMaintenance".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return response.json() + + def trigger_check( + self, + body: DtoTrigger, + ) -> DtoTriggerCheckResponse: + path = "/trigger/check" + json = body.model_dump(by_alias=True, mode="json") + with self._error_handler.handle(): + response = self.put(path, json=json) + return DtoTriggerCheckResponse.model_validate(response.json()) + + def remove_contact( + self, + path_params: RemoveContactPathParams, + body: dict[Any, Any], + ) -> dict[Any, Any]: + path = "/contact/{contactID}".format(**path_params.model_dump(by_alias=True, mode="json")) + json = body + with self._error_handler.handle(): + response = self.delete(path, json=json) + return response.json() + + def delete_all_events( + self, + ) -> dict[Any, Any]: + path = "/event/all" + with self._error_handler.handle(): + response = self.delete(path) + return response.json() + + def delete_notification( + self, + query_params: DeleteNotificationQueryParams, + ) -> DtoNotificationDeleteResponse: + path = "/notification" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.delete(path, params=params) + return DtoNotificationDeleteResponse.model_validate(response.json()) + + def delete_all_notifications( + self, + ) -> DtoNotificationsList: + path = "/notification/all" + with self._error_handler.handle(): + response = self.delete(path) + return DtoNotificationsList.model_validate(response.json()) + + def delete_notifications_filtered( + self, + query_params: DeleteNotificationsFilteredQueryParams, + ) -> DtoNotificationsList: + path = "/notification/filtered" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.delete(path, params=params) + return DtoNotificationsList.model_validate(response.json()) + + def delete_pattern( + self, + path_params: DeletePatternPathParams, + ) -> dict[Any, Any]: + path = "/pattern/{pattern}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.delete(path) + return response.json() + + def remove_subscription( + self, + path_params: RemoveSubscriptionPathParams, + ) -> dict[Any, Any]: + path = "/subscription/{subscriptionID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.delete(path) + return response.json() + + def remove_tag( + self, + path_params: RemoveTagPathParams, + ) -> DtoMessageResponse: + path = "/tag/{tag}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.delete(path) + return DtoMessageResponse.model_validate(response.json()) + + def delete_team( + self, + path_params: DeleteTeamPathParams, + ) -> DtoSaveTeamResponse: + path = "/teams/{teamID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.delete(path) + return DtoSaveTeamResponse.model_validate(response.json()) + + def delete_team_user( + self, + path_params: DeleteTeamUserPathParams, + ) -> DtoTeamMembers: + path = "/teams/{teamID}/users/{teamUserID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.delete(path) + return DtoTeamMembers.model_validate(response.json()) + + def remove_trigger( + self, + path_params: RemoveTriggerPathParams, + ) -> None: + path = "/trigger/{triggerID}".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + self.delete(path) + return None + + def delete_trigger_metric( + self, + path_params: DeleteTriggerMetricPathParams, + query_params: DeleteTriggerMetricQueryParams, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/metrics".format(**path_params.model_dump(by_alias=True, mode="json")) + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.delete(path, params=params) + return response.json() + + def delete_trigger_nodata_metrics( + self, + path_params: DeleteTriggerNodataMetricsPathParams, + ) -> dict[Any, Any]: + path = "/trigger/{triggerID}/metrics/nodata".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + response = self.delete(path) + return response.json() + + def delete_trigger_throttling( + self, + path_params: DeleteTriggerThrottlingPathParams, + ) -> None: + path = "/trigger/{triggerID}/throttling".format(**path_params.model_dump(by_alias=True, mode="json")) + with self._error_handler.handle(): + self.delete(path) + return None + + def delete_pager( + self, + query_params: DeletePagerQueryParams, + ) -> DtoTriggersSearchResultDeleteResponse: + path = "/trigger/search/pager" + params = query_params.model_dump(by_alias=True, mode="json", exclude_none=True) + with self._error_handler.handle(): + response = self.delete(path, params=params) + return DtoTriggersSearchResultDeleteResponse.model_validate(response.json()) diff --git a/src/moira/exceptions.py b/src/moira/exceptions.py new file mode 100644 index 0000000..4c6e61e --- /dev/null +++ b/src/moira/exceptions.py @@ -0,0 +1,20 @@ +from httptoolkit.response import Response + +__all__ = [ + "MoiraError", + "MoiraApiError", + "MoiraServerError", +] + + +class MoiraError(Exception): + """Base exception""" + + +class MoiraApiError(MoiraError): + def __init__(self, response: Response): + super(MoiraApiError, self).__init__(response.reason) + + +class MoiraServerError(MoiraError): + """""" diff --git a/tests/models/team/__init__.py b/src/moira/models/__init__.py similarity index 100% rename from tests/models/team/__init__.py rename to src/moira/models/__init__.py diff --git a/src/moira/models/enums.py b/src/moira/models/enums.py new file mode 100644 index 0000000..4d21ee8 --- /dev/null +++ b/src/moira/models/enums.py @@ -0,0 +1,3 @@ +from __future__ import annotations + +__all__ = [] diff --git a/src/moira/models/requests.py b/src/moira/models/requests.py new file mode 100644 index 0000000..7f26c95 --- /dev/null +++ b/src/moira/models/requests.py @@ -0,0 +1,307 @@ +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field +from pydantic.experimental.missing_sentinel import MISSING + +__all__ = [ + "GetContactByIdPathParams", + "GetContactEventsByIdPathParams", + "GetContactEventsByIdQueryParams", + "GetContactsNoisinessQueryParams", + "GetEventsListPathParams", + "GetEventsListQueryParams", + "GetNotificationsQueryParams", + "GetSubscriptionPathParams", + "GetTeamPathParams", + "GetTeamSettingsPathParams", + "GetTeamUsersPathParams", + "GetAllTeamsQueryParams", + "GetTriggerPathParams", + "GetTriggerQueryParams", + "GetTriggerDumpPathParams", + "GetTriggerMetricsPathParams", + "GetTriggerMetricsQueryParams", + "RenderTriggerMetricsPathParams", + "RenderTriggerMetricsQueryParams", + "GetTriggerStatePathParams", + "GetTriggerThrottlingPathParams", + "GetAllHeavyTriggersQueryParams", + "GetTriggersNoisinessQueryParams", + "SearchTriggersQueryParams", + "SendTestContactNotificationPathParams", + "CreateNewTeamContactPathParams", + "CreateNewTeamSubscriptionPathParams", + "AddTeamUsersPathParams", + "UpdateContactPathParams", + "UpdateSubscriptionPathParams", + "SendTestNotificationPathParams", + "SetTeamUsersPathParams", + "CreateTriggerQueryParams", + "UpdateTriggerPathParams", + "UpdateTriggerQueryParams", + "SetTriggerMaintenancePathParams", + "UpdateTeamPathParams", + "RemoveContactPathParams", + "DeleteNotificationQueryParams", + "DeleteNotificationsFilteredQueryParams", + "DeletePatternPathParams", + "RemoveSubscriptionPathParams", + "RemoveTagPathParams", + "DeleteTeamPathParams", + "DeleteTeamUserPathParams", + "RemoveTriggerPathParams", + "DeleteTriggerMetricPathParams", + "DeleteTriggerMetricQueryParams", + "DeleteTriggerNodataMetricsPathParams", + "DeleteTriggerThrottlingPathParams", + "DeletePagerQueryParams", +] + + +class BaseConfig: + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + ) + + +class GetContactByIdPathParams(BaseModel, BaseConfig): + contact_id: str = Field(alias="contactID") + + +class GetContactEventsByIdPathParams(BaseModel, BaseConfig): + contact_id: str = Field(alias="contactID") + + +class GetContactEventsByIdQueryParams(BaseModel, BaseConfig): + from_: str | MISSING = Field(MISSING, alias="from") + to: str | MISSING = Field(MISSING, alias="to") + size: int | MISSING = Field(MISSING, alias="size") + p: int | MISSING = Field(MISSING, alias="p") + + +class GetContactsNoisinessQueryParams(BaseModel, BaseConfig): + size: int | MISSING = Field(MISSING, alias="size") + p: int | MISSING = Field(MISSING, alias="p") + from_: str | MISSING = Field(MISSING, alias="from") + to: str | MISSING = Field(MISSING, alias="to") + sort: str | MISSING = Field(MISSING, alias="sort") + + +class GetEventsListPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class GetEventsListQueryParams(BaseModel, BaseConfig): + size: int | MISSING = Field(MISSING, alias="size") + p: int | MISSING = Field(MISSING, alias="p") + from_: str | MISSING = Field(MISSING, alias="from") + to: str | MISSING = Field(MISSING, alias="to") + metric: str | MISSING = Field(MISSING, alias="metric") + states: list[str] | MISSING = Field(MISSING, alias="states") + + +class GetNotificationsQueryParams(BaseModel, BaseConfig): + start: int | MISSING = Field(MISSING, alias="start") + end: int | MISSING = Field(MISSING, alias="end") + + +class GetSubscriptionPathParams(BaseModel, BaseConfig): + subscription_id: str = Field(alias="subscriptionID") + + +class GetTeamPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class GetTeamSettingsPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class GetTeamUsersPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class GetAllTeamsQueryParams(BaseModel, BaseConfig): + size: int | MISSING = Field(MISSING, alias="size") + p: int | MISSING = Field(MISSING, alias="p") + search_text: str | MISSING = Field(MISSING, alias="searchText") + sort: str | MISSING = Field(MISSING, alias="sort") + + +class GetTriggerPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class GetTriggerQueryParams(BaseModel, BaseConfig): + populated: bool | MISSING = Field(MISSING, alias="populated") + + +class GetTriggerDumpPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class GetTriggerMetricsPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class GetTriggerMetricsQueryParams(BaseModel, BaseConfig): + from_: str | MISSING = Field(MISSING, alias="from") + to: str | MISSING = Field(MISSING, alias="to") + + +class RenderTriggerMetricsPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class RenderTriggerMetricsQueryParams(BaseModel, BaseConfig): + target: str | MISSING = Field(MISSING, alias="target") + from_: str | MISSING = Field(MISSING, alias="from") + to: str | MISSING = Field(MISSING, alias="to") + timezone: str | MISSING = Field(MISSING, alias="timezone") + theme: str | MISSING = Field(MISSING, alias="theme") + realtime: bool | MISSING = Field(MISSING, alias="realtime") + + +class GetTriggerStatePathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class GetTriggerThrottlingPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class GetAllHeavyTriggersQueryParams(BaseModel, BaseConfig): + from_: int | MISSING = Field(MISSING, alias="from") + + +class GetTriggersNoisinessQueryParams(BaseModel, BaseConfig): + size: int | MISSING = Field(MISSING, alias="size") + p: int | MISSING = Field(MISSING, alias="p") + from_: str | MISSING = Field(MISSING, alias="from") + to: str | MISSING = Field(MISSING, alias="to") + sort: str | MISSING = Field(MISSING, alias="sort") + + +class SearchTriggersQueryParams(BaseModel, BaseConfig): + only_problems: bool | MISSING = Field(MISSING, alias="onlyProblems") + text: str | MISSING = Field(MISSING, alias="text") + p: int | MISSING = Field(MISSING, alias="p") + size: int | MISSING = Field(MISSING, alias="size") + tags: list[str] | MISSING = Field(MISSING, alias="tags") + create_pager: bool | MISSING = Field(MISSING, alias="createPager") + pager_id: str | MISSING = Field(MISSING, alias="pagerID") + created_by: str | MISSING = Field(MISSING, alias="createdBy") + team_id: str | MISSING = Field(MISSING, alias="teamID") + + +class SendTestContactNotificationPathParams(BaseModel, BaseConfig): + contact_id: str = Field(alias="contactID") + + +class CreateNewTeamContactPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class CreateNewTeamSubscriptionPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class AddTeamUsersPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class UpdateContactPathParams(BaseModel, BaseConfig): + contact_id: str = Field(alias="contactID") + + +class UpdateSubscriptionPathParams(BaseModel, BaseConfig): + subscription_id: str = Field(alias="subscriptionID") + + +class SendTestNotificationPathParams(BaseModel, BaseConfig): + subscription_id: str = Field(alias="subscriptionID") + + +class SetTeamUsersPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class CreateTriggerQueryParams(BaseModel, BaseConfig): + validate: bool | MISSING = Field(MISSING, alias="validate") + + +class UpdateTriggerPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class UpdateTriggerQueryParams(BaseModel, BaseConfig): + validate: bool | MISSING = Field(MISSING, alias="validate") + + +class SetTriggerMaintenancePathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class UpdateTeamPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class RemoveContactPathParams(BaseModel, BaseConfig): + contact_id: str = Field(alias="contactID") + + +class DeleteNotificationQueryParams(BaseModel, BaseConfig): + id: str = Field(alias="id") + + +class DeleteNotificationsFilteredQueryParams(BaseModel, BaseConfig): + start: int = Field(alias="start") + end: int = Field(alias="end") + ignored_tags: list[str] | MISSING = Field(MISSING, alias="ignoredTags") + cluster_keys: list[str] | MISSING = Field(MISSING, alias="clusterKeys") + + +class DeletePatternPathParams(BaseModel, BaseConfig): + pattern: str = Field(alias="pattern") + + +class RemoveSubscriptionPathParams(BaseModel, BaseConfig): + subscription_id: str = Field(alias="subscriptionID") + + +class RemoveTagPathParams(BaseModel, BaseConfig): + tag: str = Field(alias="tag") + + +class DeleteTeamPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + + +class DeleteTeamUserPathParams(BaseModel, BaseConfig): + team_id: str = Field(alias="teamID") + team_user_id: str = Field(alias="teamUserID") + + +class RemoveTriggerPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class DeleteTriggerMetricPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class DeleteTriggerMetricQueryParams(BaseModel, BaseConfig): + name: str | MISSING = Field(MISSING, alias="name") + + +class DeleteTriggerNodataMetricsPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class DeleteTriggerThrottlingPathParams(BaseModel, BaseConfig): + trigger_id: str = Field(alias="triggerID") + + +class DeletePagerQueryParams(BaseModel, BaseConfig): + pager_id: str | MISSING = Field(MISSING, alias="pagerID") diff --git a/src/moira/models/responses.py b/src/moira/models/responses.py new file mode 100644 index 0000000..0068be3 --- /dev/null +++ b/src/moira/models/responses.py @@ -0,0 +1,819 @@ +from __future__ import annotations + +from typing import Any, Literal + +from pydantic import BaseModel, ConfigDict, Field +from pydantic.experimental.missing_sentinel import MISSING + +__all__ = [ + "MoiraTriggerData", + "MoiraScheduleDataDay", + "MoiraScheduleData", + "MoiraCheckData", + "MoiraTriggerCheck", + "MoiraTrigger", + "MoiraPlottingData", + "MoiraSubscriptionData", + "MoiraEventInfo", + "MoiraNotificationEvent", + "MoiraContactData", + "MoiraScheduledNotification", + "MoiraMetricValue", + "MoiraMaintenanceInfo", + "MoiraMetricState", + "DtoTeamModel", + "DtoUserTeams", + "DtoSubscription", + "DtoContactWithScore", + "DtoUserSettings", + "DtoUser", + "DtoTriggersSearchResultDeleteResponse", + "DtoTriggersList", + "DtoTriggerNoisiness", + "DtoTriggerNoisinessList", + "DtoTriggerModel", + "DtoTriggerMaintenance", + "DtoPatternMetrics", + "DtoTriggerDump", + "DtoProblemOfTarget", + "DtoTreeOfProblems", + "DtoTriggerCheckResponse", + "DtoTriggerCheck", + "DtoTrigger", + "DtoThrottlingResponse", + "DtoTeamsList", + "DtoContactScore", + "DtoTeamContactWithScore", + "DtoTeamSettings", + "DtoTeamMembers", + "DtoTeamContact", + "DtoTagStatistics", + "DtoTagsStatistics", + "DtoTagsData", + "DtoSubscriptionList", + "DtoSaveTriggerResponse", + "DtoSaveTeamResponse", + "DtoPatternData", + "DtoPatternList", + "DtoNotifierStateForSource", + "DtoNotifierStatesForSources", + "DtoNotifierState", + "DtoNotificationsList", + "DtoNotificationDeleteResponse", + "DtoMessageResponse", + "DtoEventsList", + "DtoContactNoisiness", + "DtoContactNoisinessList", + "DtoContactList", + "DtoContactEventItem", + "DtoContactEventItemList", + "DtoContact", + "ApiWebContact", + "ApiSentry", + "ApiMetricSourceCluster", + "ApiFeatureFlags", + "ApiWebConfig", + "ApiErrorResponse", +] + + +class BaseConfig: + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + ) + + +class SetTriggerMaintenanceResponse200(BaseModel, BaseConfig): ... + + +class DeleteTriggerNodataMetricsResponse200(BaseModel, BaseConfig): ... + + +class DeleteTriggerMetricResponse200(BaseModel, BaseConfig): ... + + +class SendTestNotificationResponse200(BaseModel, BaseConfig): ... + + +class RemoveSubscriptionResponse200(BaseModel, BaseConfig): ... + + +class DeletePatternResponse200(BaseModel, BaseConfig): ... + + +class DeleteAllEventsResponse200(BaseModel, BaseConfig): ... + + +class SendTestContactNotificationRequestBody(BaseModel, BaseConfig): ... + + +class SendTestContactNotificationResponse200(BaseModel, BaseConfig): ... + + +class RemoveContactRequestBody(BaseModel, BaseConfig): ... + + +class RemoveContactResponse200(BaseModel, BaseConfig): ... + + +class MoiraTriggerData(BaseModel, BaseConfig): + notifier_trigger_tags: list[str] = Field(..., alias="__notifier_trigger_tags") + desc: str + error_value: float + id: str + is_remote: bool + name: str + targets: list[str] + warn_value: float + cluster_id: str | MISSING = Field(MISSING) + trigger_source: str | MISSING = Field(MISSING) + + +class MoiraScheduleDataDay(BaseModel, BaseConfig): + enabled: bool + name: Literal["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] | MISSING = Field(MISSING) + + +class MoiraScheduleData(BaseModel, BaseConfig): + """ + Determines when Moira should monitor trigger + """ + + days: list[MoiraScheduleDataDay] + end_offset: int = Field(..., alias="endOffset") + start_offset: int = Field(..., alias="startOffset") + tz_offset: int = Field(..., alias="tzOffset") + + +class MoiraCheckData(BaseModel, BaseConfig): + last_successful_check_timestamp: int = Field( + ..., + description=( + "LastSuccessfulCheckTimestamp - time of the last check of the trigger, during which there were no errors" + ), + ) + maintenance_info: MoiraMaintenanceInfo + metrics: dict + metrics_to_target_relation: dict = Field( + ..., + description=( + "MetricsToTargetRelation is a map that holds relation between metric names that was alone during last" + ' check and targets that fetched this metric {"t1": "metric.name.1", "t2": "metric.name.2"}' + ), + ) + score: int + state: str + event_timestamp: int | MISSING = Field(MISSING) + maintenance: int | MISSING = Field(MISSING) + msg: str | MISSING = Field(MISSING) + suppressed: bool | MISSING = Field(MISSING) + suppressed_state: str | MISSING = Field(MISSING) + timestamp: int | MISSING = Field( + MISSING, + description=( + "Timestamp - time, which means when the checker last checked this trigger, this value stops updating if" + " the trigger does not receive metrics" + ), + ) + + +class MoiraTriggerCheck(BaseModel, BaseConfig): + alone_metrics: dict + created_at: int + created_by: str + error_value: float + highlights: dict + id: str + last_check: MoiraCheckData + mute_new_metrics: bool + name: str + patterns: list[str] + tags: list[str] + targets: list[str] + throttling: int + trigger_type: str + updated_at: int + updated_by: str + warn_value: float + cluster_id: str | MISSING = Field(MISSING) + desc: str | MISSING = Field(MISSING) + expression: str | MISSING = Field(MISSING) + python_expression: str | MISSING = Field(MISSING) + sched: MoiraScheduleData | MISSING = Field(MISSING, description="Determines when Moira should monitor trigger") + team_id: str | MISSING = Field(MISSING) + trigger_source: str | MISSING = Field(MISSING) + ttl: int | MISSING = Field(MISSING) + ttl_state: str | MISSING = Field(MISSING) + + +class MoiraTrigger(BaseModel, BaseConfig): + alone_metrics: dict + created_at: int + created_by: str + error_value: float + id: str + mute_new_metrics: bool + name: str + patterns: list[str] + tags: list[str] + targets: list[str] + trigger_type: str + updated_at: int + updated_by: str + warn_value: float + cluster_id: str | MISSING = Field(MISSING) + desc: str | MISSING = Field(MISSING) + expression: str | MISSING = Field(MISSING) + python_expression: str | MISSING = Field(MISSING) + sched: MoiraScheduleData | MISSING = Field(MISSING, description="Determines when Moira should monitor trigger") + team_id: str | MISSING = Field(MISSING) + trigger_source: str | MISSING = Field(MISSING) + ttl: int | MISSING = Field(MISSING) + ttl_state: str | MISSING = Field(MISSING) + + +class MoiraPlottingData(BaseModel, BaseConfig): + enabled: bool + theme: str + + +class MoiraSubscriptionData(BaseModel, BaseConfig): + any_tags: bool + contacts: list[str] + enabled: bool + id: str + plotting: MoiraPlottingData + sched: MoiraScheduleData = Field(..., description="Determines when Moira should monitor trigger") + tags: list[str] + team_id: str + throttling: bool + user: str + ignore_recoverings: bool | MISSING = Field(MISSING) + ignore_warnings: bool | MISSING = Field(MISSING) + + +class MoiraEventInfo(BaseModel, BaseConfig): + interval: int | MISSING = Field(MISSING) + maintenance: MoiraMaintenanceInfo | MISSING = Field(MISSING) + + +class MoiraNotificationEvent(BaseModel, BaseConfig): + event_message: MoiraEventInfo + metric: str + old_state: str + state: str + timestamp: int + trigger_id: str + contact_id: str | MISSING = Field(MISSING) + msg: str | MISSING = Field(MISSING) + sub_id: str | MISSING = Field(MISSING) + trigger_event: bool | MISSING = Field(MISSING) + value: float | MISSING = Field(MISSING) + values: dict | MISSING = Field(MISSING) + + +class MoiraContactData(BaseModel, BaseConfig): + id: str + team: str + type: str + user: str + value: str + extra_message: str | MISSING = Field(MISSING) + name: str | MISSING = Field(MISSING) + + +class MoiraScheduledNotification(BaseModel, BaseConfig): + contact: MoiraContactData + event: MoiraNotificationEvent + plotting: MoiraPlottingData + send_fail: int + throttled: bool + timestamp: int + trigger: MoiraTriggerData + created_at: int | MISSING = Field(MISSING) + + +class MoiraMetricValue(BaseModel, BaseConfig): + ts: int + value: float + step: int | MISSING = Field(MISSING) + + +class MoiraMaintenanceInfo(BaseModel, BaseConfig): + remove_time: int + remove_user: str + setup_time: int + setup_user: str + + +class MoiraMetricState(BaseModel, BaseConfig): + event_timestamp: int + maintenance_info: MoiraMaintenanceInfo + state: str + suppressed: bool + timestamp: int + deleted_but_kept: bool | MISSING = Field( + MISSING, + description=( + "DeletedButKept controls whether the metric is shown to the user if the trigger has ttlState = Del and the" + " metric is in Maintenance. The metric remains in the database" + ), + ) + maintenance: int | MISSING = Field(MISSING) + suppressed_state: str | MISSING = Field(MISSING) + value: float | MISSING = Field(MISSING) + values: dict | MISSING = Field(MISSING) + + +class DtoTeamModel(BaseModel, BaseConfig): + id: str + name: str + description: str | MISSING = Field(MISSING) + + +class DtoUserTeams(BaseModel, BaseConfig): + teams: list[DtoTeamModel] + + +class DtoSubscription(BaseModel, BaseConfig): + any_tags: bool + contacts: list[str] + enabled: bool + id: str + plotting: MoiraPlottingData + sched: MoiraScheduleData = Field(..., description="Determines when Moira should monitor trigger") + tags: list[str] + team_id: str + throttling: bool + user: str + ignore_recoverings: bool | MISSING = Field(MISSING) + ignore_warnings: bool | MISSING = Field(MISSING) + + +class DtoContactWithScore(BaseModel, BaseConfig): + id: str + type: str + value: str + extra_message: str | MISSING = Field(MISSING) + name: str | MISSING = Field(MISSING) + score: DtoContactScore | MISSING = Field(MISSING) + team_id: str | MISSING = Field(MISSING) + user: str | MISSING = Field(MISSING) + + +class DtoUserSettings(BaseModel, BaseConfig): + contacts: list[DtoContactWithScore] + login: str + subscriptions: list[DtoSubscription] + auth_enabled: bool | MISSING = Field(MISSING) + role: str | MISSING = Field(MISSING) + + +class DtoUser(BaseModel, BaseConfig): + login: str + auth_enabled: bool | MISSING = Field(MISSING) + role: str | MISSING = Field(MISSING) + + +class DtoTriggersSearchResultDeleteResponse(BaseModel, BaseConfig): + pager_id: str + + +class DtoTriggersList(BaseModel, BaseConfig): + list: list[MoiraTriggerCheck] + page: int | MISSING = Field(MISSING) + pager: str | MISSING = Field(MISSING) + size: int | MISSING = Field(MISSING) + total: int | MISSING = Field(MISSING) + + +class DtoTriggerNoisiness(BaseModel, BaseConfig): + alone_metrics: dict = Field(..., description="A list of targets that have only alone metrics") + cluster_id: str = Field(..., description="Shows the exact cluster from where the metrics are fetched") + created_at: str = Field(..., description="Datetime when the trigger was created") + created_by: str = Field(..., description="Username who created trigger") + error_value: float = Field(..., description="ERROR threshold") + events_count: int = Field(..., description="EventsCount for the trigger.") + expression: str = Field(..., description="Used if you need more complex logic than provided by WARN/ERROR values") + id: str = Field(..., description="Trigger unique ID") + is_remote: bool = Field( + ..., + description=( + "Shows if trigger is remote (graphite-backend) based or stored inside Moira-Redis DB Deprecated: Use" + " TriggerSource field instead" + ), + ) + mute_new_metrics: bool = Field(..., description="If true, first event NODATA → OK will be omitted") + name: str = Field(..., description="Trigger name") + patterns: list[str] = Field(..., description="Graphite patterns for trigger") + tags: list[str] = Field(..., description="Set of tags to manipulate subscriptions") + targets: list[str] = Field(..., description="Graphite-like targets: t1, t2, ...") + throttling: int + trigger_source: str = Field(..., description="Shows the type of source from where the metrics are fetched") + trigger_type: str = Field(..., description="Could be: rising, falling, expression") + updated_at: str = Field(..., description="Datetime when the trigger was updated") + updated_by: str = Field(..., description="Username who updated trigger") + warn_value: float = Field(..., description="WARN threshold") + desc: str | MISSING = Field(MISSING, description="Description string") + sched: MoiraScheduleData | MISSING = Field(MISSING, description="Determines when Moira should monitor trigger") + team_id: str | MISSING = Field(MISSING, description="ID of a Team that owns this trigger") + ttl: int | MISSING = Field( + MISSING, + description=( + "When there are no metrics for trigger, Moira will switch metric to TTLState state after TTL seconds" + ), + ) + ttl_state: str | MISSING = Field( + MISSING, + description=( + "When there are no metrics for trigger, Moira will switch metric to TTLState state after TTL seconds" + ), + ) + + +class DtoTriggerNoisinessList(BaseModel, BaseConfig): + list: list[DtoTriggerNoisiness] = Field(..., description="List of entities.") + page: int = Field(..., description="Page number.") + size: int = Field(..., description="Size is the amount of entities per Page.") + total: int = Field(..., description="Total amount of entities in the database.") + + +class DtoTriggerModel(BaseModel, BaseConfig): + alone_metrics: dict = Field(..., description="A list of targets that have only alone metrics") + cluster_id: str = Field(..., description="Shows the exact cluster from where the metrics are fetched") + created_at: str = Field(..., description="Datetime when the trigger was created") + created_by: str = Field(..., description="Username who created trigger") + error_value: float = Field(..., description="ERROR threshold") + expression: str = Field(..., description="Used if you need more complex logic than provided by WARN/ERROR values") + id: str = Field(..., description="Trigger unique ID") + is_remote: bool = Field( + ..., + description=( + "Shows if trigger is remote (graphite-backend) based or stored inside Moira-Redis DB Deprecated: Use" + " TriggerSource field instead" + ), + ) + mute_new_metrics: bool = Field(..., description="If true, first event NODATA → OK will be omitted") + name: str = Field(..., description="Trigger name") + patterns: list[str] = Field(..., description="Graphite patterns for trigger") + tags: list[str] = Field(..., description="Set of tags to manipulate subscriptions") + targets: list[str] = Field(..., description="Graphite-like targets: t1, t2, ...") + trigger_source: str = Field(..., description="Shows the type of source from where the metrics are fetched") + trigger_type: str = Field(..., description="Could be: rising, falling, expression") + updated_at: str = Field(..., description="Datetime when the trigger was updated") + updated_by: str = Field(..., description="Username who updated trigger") + warn_value: float = Field(..., description="WARN threshold") + desc: str | MISSING = Field(MISSING, description="Description string") + sched: MoiraScheduleData | MISSING = Field(MISSING, description="Determines when Moira should monitor trigger") + team_id: str | MISSING = Field(MISSING, description="ID of a Team that owns this trigger") + ttl: int | MISSING = Field( + MISSING, + description=( + "When there are no metrics for trigger, Moira will switch metric to TTLState state after TTL seconds" + ), + ) + ttl_state: str | MISSING = Field( + MISSING, + description=( + "When there are no metrics for trigger, Moira will switch metric to TTLState state after TTL seconds" + ), + ) + + +class DtoTriggerMetrics(BaseModel, BaseConfig): ... + + +class DtoMetricsMaintenance(BaseModel, BaseConfig): ... + + +class DtoTriggerMaintenance(BaseModel, BaseConfig): + metrics: dict[Any, Any] + trigger: int | MISSING = Field(MISSING) + + +class DtoPatternMetrics(BaseModel, BaseConfig): + metrics: dict + pattern: str + retention: dict + + +class DtoTriggerDump(BaseModel, BaseConfig): + created: str + last_check: MoiraCheckData + metrics: list[DtoPatternMetrics] + trigger: MoiraTrigger + + +class DtoProblemOfTarget(BaseModel, BaseConfig): + argument: str + position: int + description: str | MISSING = Field(MISSING) + problems: list[DtoProblemOfTarget] | MISSING = Field(MISSING) + type: str | MISSING = Field(MISSING) + + +class DtoTreeOfProblems(BaseModel, BaseConfig): + syntax_ok: bool + tree_of_problems: DtoProblemOfTarget | MISSING = Field(MISSING) + + +class DtoTriggerCheckResponse(BaseModel, BaseConfig): + targets: list[DtoTreeOfProblems] | MISSING = Field(MISSING, description="Graphite-like targets: t1, t2, ...") + + +class DtoTriggerCheck(BaseModel, BaseConfig): + last_successful_check_timestamp: int = Field( + ..., + description=( + "LastSuccessfulCheckTimestamp - time of the last check of the trigger, during which there were no errors" + ), + ) + maintenance_info: MoiraMaintenanceInfo + metrics: dict + metrics_to_target_relation: dict = Field( + ..., + description=( + "MetricsToTargetRelation is a map that holds relation between metric names that was alone during last" + ' check and targets that fetched this metric {"t1": "metric.name.1", "t2": "metric.name.2"}' + ), + ) + score: int + state: str + trigger_id: str + event_timestamp: int | MISSING = Field(MISSING) + maintenance: int | MISSING = Field(MISSING) + msg: str | MISSING = Field(MISSING) + suppressed: bool | MISSING = Field(MISSING) + suppressed_state: str | MISSING = Field(MISSING) + timestamp: int | MISSING = Field( + MISSING, + description=( + "Timestamp - time, which means when the checker last checked this trigger, this value stops updating if" + " the trigger does not receive metrics" + ), + ) + + +class DtoTrigger(BaseModel, BaseConfig): + alone_metrics: dict = Field(..., description="A list of targets that have only alone metrics") + cluster_id: str = Field(..., description="Shows the exact cluster from where the metrics are fetched") + created_at: str = Field(..., description="Datetime when the trigger was created") + created_by: str = Field(..., description="Username who created trigger") + error_value: float = Field(..., description="ERROR threshold") + expression: str = Field(..., description="Used if you need more complex logic than provided by WARN/ERROR values") + id: str = Field(..., description="Trigger unique ID") + is_remote: bool = Field( + ..., + description=( + "Shows if trigger is remote (graphite-backend) based or stored inside Moira-Redis DB Deprecated: Use" + " TriggerSource field instead" + ), + ) + mute_new_metrics: bool = Field(..., description="If true, first event NODATA → OK will be omitted") + name: str = Field(..., description="Trigger name") + patterns: list[str] = Field(..., description="Graphite patterns for trigger") + tags: list[str] = Field(..., description="Set of tags to manipulate subscriptions") + targets: list[str] = Field(..., description="Graphite-like targets: t1, t2, ...") + throttling: int + trigger_source: str = Field(..., description="Shows the type of source from where the metrics are fetched") + trigger_type: str = Field(..., description="Could be: rising, falling, expression") + updated_at: str = Field(..., description="Datetime when the trigger was updated") + updated_by: str = Field(..., description="Username who updated trigger") + warn_value: float = Field(..., description="WARN threshold") + desc: str | MISSING = Field(MISSING, description="Description string") + sched: MoiraScheduleData | MISSING = Field(MISSING, description="Determines when Moira should monitor trigger") + team_id: str | MISSING = Field(MISSING, description="ID of a Team that owns this trigger") + ttl: int | MISSING = Field( + MISSING, + description=( + "When there are no metrics for trigger, Moira will switch metric to TTLState state after TTL seconds" + ), + ) + ttl_state: str | MISSING = Field( + MISSING, + description=( + "When there are no metrics for trigger, Moira will switch metric to TTLState state after TTL seconds" + ), + ) + + +class DtoThrottlingResponse(BaseModel, BaseConfig): + throttling: int + + +class DtoTeamsList(BaseModel, BaseConfig): + list: list[DtoTeamModel] + page: int + size: int + total: int + + +class DtoContactScore(BaseModel, BaseConfig): + last_err: str | MISSING = Field(MISSING, description="LastErrMessage is the last error message encountered.") + last_err_timestamp: int | MISSING = Field( + MISSING, description="LastErrTimestamp is the timestamp of the last error." + ) + score_percent: int | MISSING = Field( + MISSING, description="ScorePercent is the percentage score of successful transactions." + ) + status: str | MISSING = Field(MISSING, description="Status is the current status of the contact.") + + +class DtoTeamContactWithScore(BaseModel, BaseConfig): + id: str + type: str + value: str + extra_message: str | MISSING = Field(MISSING) + name: str | MISSING = Field(MISSING) + score: DtoContactScore | MISSING = Field(MISSING) + team: str | MISSING = Field(MISSING, description="This field is deprecated") + team_id: str | MISSING = Field(MISSING) + user: str | MISSING = Field(MISSING) + + +class DtoTeamSettings(BaseModel, BaseConfig): + contacts: list[DtoTeamContactWithScore] + subscriptions: list[MoiraSubscriptionData] + team_id: str + + +class DtoTeamMembers(BaseModel, BaseConfig): + usernames: list[str] + + +class DtoTeamContact(BaseModel, BaseConfig): + id: str + type: str + value: str + extra_message: str | MISSING = Field(MISSING) + name: str | MISSING = Field(MISSING) + team: str | MISSING = Field(MISSING, description="This field is deprecated") + team_id: str | MISSING = Field(MISSING) + user: str | MISSING = Field(MISSING) + + +class DtoTagStatistics(BaseModel, BaseConfig): + name: str + subscriptions: list[MoiraSubscriptionData] + triggers: list[str] + + +class DtoTagsStatistics(BaseModel, BaseConfig): + list: list[DtoTagStatistics] + + +class DtoTagsData(BaseModel, BaseConfig): + list: list[str] + + +class DtoSubscriptionList(BaseModel, BaseConfig): + list: list[MoiraSubscriptionData] + + +class DtoSaveTriggerResponse(BaseModel, BaseConfig): + id: str + message: str + check_result: DtoTriggerCheckResponse | MISSING = Field(MISSING, alias="checkResult") + + +class DtoSaveTeamResponse(BaseModel, BaseConfig): + id: str + + +class DtoPatternData(BaseModel, BaseConfig): + metrics: list[str] + pattern: str + triggers: list[DtoTriggerModel] + + +class DtoPatternList(BaseModel, BaseConfig): + list: list[DtoPatternData] + + +class DtoNotifierStateForSource(BaseModel, BaseConfig): + actor: str + cluster_id: str + state: str + trigger_source: str + message: str | MISSING = Field(MISSING) + + +class DtoNotifierStatesForSources(BaseModel, BaseConfig): + sources: list[DtoNotifierStateForSource] + + +class DtoNotifierState(BaseModel, BaseConfig): + actor: str + state: str + message: str | MISSING = Field(MISSING) + + +class DtoNotificationsList(BaseModel, BaseConfig): + list: list[MoiraScheduledNotification] + total: int + + +class DtoNotificationDeleteResponse(BaseModel, BaseConfig): + result: int + + +class DtoMessageResponse(BaseModel, BaseConfig): + message: str + + +class DtoEventsList(BaseModel, BaseConfig): + list: list[MoiraNotificationEvent] + page: int + size: int + total: int + + +class DtoContactNoisiness(BaseModel, BaseConfig): + events_count: int = Field(..., description="EventsCount for the contact.") + id: str + type: str + value: str + extra_message: str | MISSING = Field(MISSING) + name: str | MISSING = Field(MISSING) + team_id: str | MISSING = Field(MISSING) + user: str | MISSING = Field(MISSING) + + +class DtoContactNoisinessList(BaseModel, BaseConfig): + list: list[DtoContactNoisiness] = Field(..., description="List of entities.") + page: int = Field(..., description="Page number.") + size: int = Field(..., description="Size is the amount of entities per Page.") + total: int = Field(..., description="Total amount of entities in the database.") + + +class DtoContactList(BaseModel, BaseConfig): + list: list[DtoTeamContact] + + +class DtoContactEventItem(BaseModel, BaseConfig): + metric: str + old_state: str + state: str + timestamp: int + trigger_id: str + + +class DtoContactEventItemList(BaseModel, BaseConfig): + list: list[DtoContactEventItem] + page: int + size: int + total: int + + +class DtoContact(BaseModel, BaseConfig): + id: str + type: str + value: str + extra_message: str | MISSING = Field(MISSING) + name: str | MISSING = Field(MISSING) + team_id: str | MISSING = Field(MISSING) + user: str | MISSING = Field(MISSING) + + +class ApiWebContact(BaseModel, BaseConfig): + label: str + type: str + help: str | MISSING = Field(MISSING) + logo_uri: str | MISSING = Field(MISSING) + placeholder: str | MISSING = Field(MISSING) + validation: str | MISSING = Field(MISSING) + + +class ApiSentry(BaseModel, BaseConfig): + dsn: str | MISSING = Field(MISSING) + platform: str | MISSING = Field(MISSING) + + +class ApiMetricSourceCluster(BaseModel, BaseConfig): + cluster_id: str + cluster_name: str + metrics_ttl: int + trigger_source: str + + +class ApiFeatureFlags(BaseModel, BaseConfig): + celebration_mode: str = Field(..., alias="celebrationMode") + is_plotting_available: bool = Field(..., alias="isPlottingAvailable") + is_plotting_default_on: bool = Field(..., alias="isPlottingDefaultOn") + is_readonly_enabled: bool = Field(..., alias="isReadonlyEnabled") + is_subscription_to_all_tags_available: bool = Field(..., alias="isSubscriptionToAllTagsAvailable") + + +class ApiWebConfig(BaseModel, BaseConfig): + contacts: list[ApiWebContact] + feature_flags: ApiFeatureFlags = Field(..., alias="featureFlags") + metric_source_clusters: list[ApiMetricSourceCluster] + remote_allowed: bool = Field(..., alias="remoteAllowed") + sentry: ApiSentry + support_email: str | MISSING = Field(MISSING, alias="supportEmail") + + +class ApiErrorResponse(BaseModel, BaseConfig): + status: str = Field(..., description="user-level status message") + error: str | MISSING = Field(MISSING, description="application-level error message, for debugging") diff --git a/tests/models/team/contact/__init__.py b/src/moira/py.typed similarity index 100% rename from tests/models/team/contact/__init__.py rename to src/moira/py.typed diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 6eb6461..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1 +0,0 @@ -mock==2.0.0 \ No newline at end of file diff --git a/tests/models/team/settings/__init__.py b/tests/client_tests/__init__.py similarity index 100% rename from tests/models/team/settings/__init__.py rename to tests/client_tests/__init__.py diff --git a/tests/client_tests/test_async_client.py b/tests/client_tests/test_async_client.py new file mode 100644 index 0000000..5709116 --- /dev/null +++ b/tests/client_tests/test_async_client.py @@ -0,0 +1,1504 @@ +from typing import Any +from urllib.parse import urlencode + +import pytest +from httptoolkit.response import Response +from polyfactory.factories.pydantic_factory import ModelFactory +from pydantic import RootModel +from pydantic_core import to_jsonable_python +from pytest_httpx import HTTPXMock + +from moira.clients import MoiraClientAsync +from moira.exceptions import MoiraApiError +from moira.models.requests import ( + AddTeamUsersPathParams, + CreateNewTeamContactPathParams, + CreateNewTeamSubscriptionPathParams, + CreateTriggerQueryParams, + DeleteNotificationQueryParams, + DeleteNotificationsFilteredQueryParams, + DeletePagerQueryParams, + DeletePatternPathParams, + DeleteTeamPathParams, + DeleteTeamUserPathParams, + DeleteTriggerMetricPathParams, + DeleteTriggerMetricQueryParams, + DeleteTriggerNodataMetricsPathParams, + DeleteTriggerThrottlingPathParams, + GetAllHeavyTriggersQueryParams, + GetAllTeamsQueryParams, + GetContactByIdPathParams, + GetContactEventsByIdPathParams, + GetContactEventsByIdQueryParams, + GetContactsNoisinessQueryParams, + GetEventsListPathParams, + GetEventsListQueryParams, + GetNotificationsQueryParams, + GetSubscriptionPathParams, + GetTeamPathParams, + GetTeamSettingsPathParams, + GetTeamUsersPathParams, + GetTriggerDumpPathParams, + GetTriggerMetricsPathParams, + GetTriggerMetricsQueryParams, + GetTriggerPathParams, + GetTriggerQueryParams, + GetTriggersNoisinessQueryParams, + GetTriggerStatePathParams, + GetTriggerThrottlingPathParams, + RemoveContactPathParams, + RemoveSubscriptionPathParams, + RemoveTagPathParams, + RemoveTriggerPathParams, + RenderTriggerMetricsPathParams, + RenderTriggerMetricsQueryParams, + SearchTriggersQueryParams, + SendTestContactNotificationPathParams, + SendTestNotificationPathParams, + SetTeamUsersPathParams, + SetTriggerMaintenancePathParams, + UpdateContactPathParams, + UpdateSubscriptionPathParams, + UpdateTeamPathParams, + UpdateTriggerPathParams, + UpdateTriggerQueryParams, +) +from moira.models.responses import ( + ApiWebConfig, + DtoContact, + DtoContactEventItemList, + DtoContactList, + DtoContactNoisinessList, + DtoEventsList, + DtoMessageResponse, + DtoNotificationDeleteResponse, + DtoNotificationsList, + DtoNotifierState, + DtoNotifierStatesForSources, + DtoPatternList, + DtoSaveTeamResponse, + DtoSaveTriggerResponse, + DtoSubscription, + DtoSubscriptionList, + DtoTagsData, + DtoTagsStatistics, + DtoTeamMembers, + DtoTeamModel, + DtoTeamSettings, + DtoTeamsList, + DtoThrottlingResponse, + DtoTrigger, + DtoTriggerCheck, + DtoTriggerCheckResponse, + DtoTriggerDump, + DtoTriggerMaintenance, + DtoTriggerNoisinessList, + DtoTriggersList, + DtoTriggersSearchResultDeleteResponse, + DtoUser, + DtoUserSettings, + DtoUserTeams, +) + + +class CustomError(MoiraApiError): + def __init__(self, response: Response): + reason = response.reason + " My own error" + super(MoiraApiError, self).__init__(reason) + + +@pytest.fixture +def async_client() -> MoiraClientAsync: + return MoiraClientAsync(base_url="https://moira-api.example.com") + + +@pytest.fixture +def async_client_with_custom_error() -> MoiraClientAsync: + return MoiraClientAsync(base_url="https://moira-api.example.com", error_class=CustomError) + + +@pytest.mark.asyncio +async def test_async_get_web_config(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = ApiWebConfig + api_web_config_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = api_web_config_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/config") + result = await async_client.get_web_config() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_contacts(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoContactList + dto_contact_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/contact") + result = await async_client.get_all_contacts() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_contact_by_id(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetContactByIdPathParams + get_contact_by_id_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_contact_by_id_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/contact/{contactID}".format(**path_params_json), + ) + result = await async_client.get_contact_by_id( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_contact_events_by_id(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetContactEventsByIdPathParams + get_contact_events_by_id_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = get_contact_events_by_id_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetContactEventsByIdQueryParams + get_contact_events_by_id_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_contact_events_by_id_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoContactEventItemList + dto_contact_event_item_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_event_item_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/contact/{contactID}/events?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_contact_events_by_id( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_contacts_noisiness(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = GetContactsNoisinessQueryParams + get_contacts_noisiness_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_contacts_noisiness_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoContactNoisinessList + dto_contact_noisiness_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_noisiness_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/contact/noisiness?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_contacts_noisiness( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_events_list(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetEventsListPathParams + get_events_list_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_events_list_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetEventsListQueryParams + get_events_list_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = get_events_list_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoEventsList + dto_events_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_events_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/event/{triggerID}?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_events_list( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_notifier_state_for_sources(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoNotifierStatesForSources + dto_notifier_states_for_sources_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifier_states_for_sources_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/health/notifier") + result = await async_client.get_notifier_state_for_sources() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_system_subscription(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoSubscriptionList + dto_subscription_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", json=result_json, url="https://moira-api.example.com/health/system-subscriptions" + ) + result = await async_client.get_system_subscription() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_notifications(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = GetNotificationsQueryParams + get_notifications_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_notifications_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoNotificationsList + dto_notifications_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifications_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/notification?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_notifications( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_patterns(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoPatternList + dto_pattern_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_pattern_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/pattern") + result = await async_client.get_all_patterns() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_user_subscriptions(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoSubscriptionList + dto_subscription_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/subscription") + result = await async_client.get_user_subscriptions() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_subscription(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetSubscriptionPathParams + get_subscription_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/subscription/{subscriptionID}".format(**path_params_json), + ) + result = await async_client.get_subscription( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_system_tags(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoTagsData + dto_tags_data_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_tags_data_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/system-tag") + result = await async_client.get_all_system_tags() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_tags(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoTagsData + dto_tags_data_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_tags_data_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/tag") + result = await async_client.get_all_tags() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_tags_and_subscriptions(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoTagsStatistics + dto_tags_statistics_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_tags_statistics_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/tag/stats") + result = await async_client.get_all_tags_and_subscriptions() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_teams_for_user(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoUserTeams + dto_user_teams_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_user_teams_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/teams") + result = await async_client.get_all_teams_for_user() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_team(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTeamPathParams + get_team_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_team_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamModel + dto_team_model_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_model_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}".format(**path_params_json), + ) + result = await async_client.get_team( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_team_settings(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTeamSettingsPathParams + get_team_settings_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_team_settings_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamSettings + dto_team_settings_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_settings_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}/settings".format(**path_params_json), + ) + result = await async_client.get_team_settings( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_team_users(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTeamUsersPathParams + get_team_users_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_team_users_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}/users".format(**path_params_json), + ) + result = await async_client.get_team_users( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_teams(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = GetAllTeamsQueryParams + get_all_teams_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = get_all_teams_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTeamsList + dto_teams_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_teams_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/all?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_all_teams( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_triggers(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/trigger") + result = await async_client.get_all_triggers() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_trigger(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerPathParams + get_trigger_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_trigger_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetTriggerQueryParams + get_trigger_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = get_trigger_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_trigger( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_trigger_dump(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerDumpPathParams + get_trigger_dump_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_trigger_dump_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTriggerDump + dto_trigger_dump_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_dump_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/dump".format(**path_params_json), + ) + result = await async_client.get_trigger_dump( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_trigger_metrics(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerMetricsPathParams + get_trigger_metrics_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = get_trigger_metrics_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetTriggerMetricsQueryParams + get_trigger_metrics_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_trigger_metrics_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/metrics?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_trigger_metrics( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_render_trigger_metrics(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = RenderTriggerMetricsPathParams + render_trigger_metrics_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = render_trigger_metrics_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = RenderTriggerMetricsQueryParams + render_trigger_metrics_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = render_trigger_metrics_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + + class RespBytes(RootModel[bytes]): ... + + resp_bytes_factory = ModelFactory.create_factory(model=RespBytes, __use_defaults__=True) + result_obj = resp_bytes_factory.build().root + httpx_mock.add_response( + method="get", + content=result_obj, + url="https://moira-api.example.com/trigger/{triggerID}/render?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.render_trigger_metrics( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_trigger_state(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerStatePathParams + get_trigger_state_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_trigger_state_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTriggerCheck + dto_trigger_check_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_check_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/state".format(**path_params_json), + ) + result = await async_client.get_trigger_state( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_trigger_throttling(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerThrottlingPathParams + get_trigger_throttling_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = get_trigger_throttling_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoThrottlingResponse + dto_throttling_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_throttling_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/throttling".format(**path_params_json), + ) + result = await async_client.get_trigger_throttling( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_all_heavy_triggers(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = GetAllHeavyTriggersQueryParams + get_all_heavy_triggers_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_all_heavy_triggers_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/heavy?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_all_heavy_triggers( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_triggers_noisiness(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = GetTriggersNoisinessQueryParams + get_triggers_noisiness_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_triggers_noisiness_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggerNoisinessList + dto_trigger_noisiness_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_noisiness_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/noisiness?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.get_triggers_noisiness( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_search_triggers(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = SearchTriggersQueryParams + search_triggers_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = search_triggers_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/search?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.search_triggers( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_unused_triggers(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/trigger/unused") + result = await async_client.get_unused_triggers() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_user_name(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoUser + dto_user_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_user_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/user") + result = await async_client.get_user_name() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_user_settings(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoUserSettings + dto_user_settings_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_user_settings_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/user/settings") + result = await async_client.get_user_settings() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_send_test_contact_notification(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_obj: dict[Any, Any] = {} + body_json = to_jsonable_python(body_obj) + path_params_model = SendTestContactNotificationPathParams + send_test_contact_notification_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = send_test_contact_notification_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/contact/{contactID}/test".format(**path_params_json), + ) + result = await async_client.send_test_contact_notification( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_tags(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTagsData + dto_tags_data_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_tags_data_factory.build() + body_json = to_jsonable_python(body_obj) + + class RespStr(RootModel[str]): ... + + resp_str_factory = ModelFactory.create_factory(model=RespStr, __use_defaults__=True) + result_obj = resp_str_factory.build().root + httpx_mock.add_response( + method="post", text=str(result_obj), match_json=body_json, url="https://moira-api.example.com/tag" + ) + result = await async_client.create_tags( + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_team(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamModel + dto_team_model_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_model_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoSaveTeamResponse + dto_save_team_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_team_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", json=result_json, match_json=body_json, url="https://moira-api.example.com/teams" + ) + result = await async_client.create_team( + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_new_team_contact(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_contact_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = CreateNewTeamContactPathParams + create_new_team_contact_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = create_new_team_contact_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/contacts".format(**path_params_json), + ) + result = await async_client.create_new_team_contact( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_new_team_subscription(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_subscription_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = CreateNewTeamSubscriptionPathParams + create_new_team_subscription_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = create_new_team_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/subscriptions".format(**path_params_json), + ) + result = await async_client.create_new_team_subscription( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_add_team_users(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_members_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = AddTeamUsersPathParams + add_team_users_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = add_team_users_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/users".format(**path_params_json), + ) + result = await async_client.add_team_users( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_update_team(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamModel + dto_team_model_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_model_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateTeamPathParams + update_team_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = update_team_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSaveTeamResponse + dto_save_team_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_team_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="patch", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}".format(**path_params_json), + ) + result = await async_client.update_team( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_new_contact(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_contact_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", json=result_json, match_json=body_json, url="https://moira-api.example.com/contact" + ) + result = await async_client.create_new_contact( + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_update_contact(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_contact_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateContactPathParams + update_contact_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = update_contact_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/contact/{contactID}".format(**path_params_json), + ) + result = await async_client.update_contact( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_set_notifier_state(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoNotifierState + dto_notifier_state_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifier_state_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="put", json=result_json, url="https://moira-api.example.com/health/notifier") + result = await async_client.set_notifier_state() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_subscription(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_subscription_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", json=result_json, match_json=body_json, url="https://moira-api.example.com/subscription" + ) + result = await async_client.create_subscription( + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_update_subscription(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_subscription_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateSubscriptionPathParams + update_subscription_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = update_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/subscription/{subscriptionID}".format(**path_params_json), + ) + result = await async_client.update_subscription( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_send_test_notification(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = SendTestNotificationPathParams + send_test_notification_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = send_test_notification_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + url="https://moira-api.example.com/subscription/{subscriptionID}/test".format(**path_params_json), + ) + result = await async_client.send_test_notification( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_set_team_users(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_members_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = SetTeamUsersPathParams + set_team_users_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = set_team_users_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/users".format(**path_params_json), + ) + result = await async_client.set_team_users( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_create_trigger(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_factory.build() + body_json = to_jsonable_python(body_obj) + query_params_model = CreateTriggerQueryParams + create_trigger_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = create_trigger_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoSaveTriggerResponse + dto_save_trigger_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_trigger_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/trigger?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.create_trigger( + query_params=query_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_update_trigger(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateTriggerPathParams + update_trigger_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = update_trigger_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = UpdateTriggerQueryParams + update_trigger_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = update_trigger_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoSaveTriggerResponse + dto_save_trigger_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_trigger_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/trigger/{triggerID}?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.update_trigger( + path_params=path_params_obj, + query_params=query_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_set_trigger_maintenance(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTriggerMaintenance + dto_trigger_maintenance_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_maintenance_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = SetTriggerMaintenancePathParams + set_trigger_maintenance_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = set_trigger_maintenance_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/trigger/{triggerID}/setMaintenance".format(**path_params_json), + ) + result = await async_client.set_trigger_maintenance( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_trigger_check(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoTriggerCheckResponse + dto_trigger_check_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_check_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", json=result_json, match_json=body_json, url="https://moira-api.example.com/trigger/check" + ) + result = await async_client.trigger_check( + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_remove_contact(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + body_obj: dict[Any, Any] = {} + body_json = to_jsonable_python(body_obj) + path_params_model = RemoveContactPathParams + remove_contact_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = remove_contact_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/contact/{contactID}".format(**path_params_json), + ) + result = await async_client.remove_contact( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_all_events(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="delete", json=result_json, url="https://moira-api.example.com/event/all") + result = await async_client.delete_all_events() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_notification(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = DeleteNotificationQueryParams + delete_notification_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = delete_notification_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoNotificationDeleteResponse + dto_notification_delete_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notification_delete_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/notification?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.delete_notification( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_all_notifications(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + response_model = DtoNotificationsList + dto_notifications_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifications_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="delete", json=result_json, url="https://moira-api.example.com/notification/all") + result = await async_client.delete_all_notifications() + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_notifications_filtered(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = DeleteNotificationsFilteredQueryParams + delete_notifications_filtered_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = delete_notifications_filtered_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoNotificationsList + dto_notifications_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifications_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/notification/filtered?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.delete_notifications_filtered( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_pattern(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = DeletePatternPathParams + delete_pattern_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = delete_pattern_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/pattern/{pattern}".format(**path_params_json), + ) + result = await async_client.delete_pattern( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_remove_subscription(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = RemoveSubscriptionPathParams + remove_subscription_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = remove_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/subscription/{subscriptionID}".format(**path_params_json), + ) + result = await async_client.remove_subscription( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_remove_tag(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = RemoveTagPathParams + remove_tag_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = remove_tag_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoMessageResponse + dto_message_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_message_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/tag/{tag}".format(**path_params_json), + ) + result = await async_client.remove_tag( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_team(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTeamPathParams + delete_team_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = delete_team_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSaveTeamResponse + dto_save_team_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_team_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}".format(**path_params_json), + ) + result = await async_client.delete_team( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_team_user(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTeamUserPathParams + delete_team_user_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = delete_team_user_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}/users/{teamUserID}".format(**path_params_json), + ) + result = await async_client.delete_team_user( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_remove_trigger(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = RemoveTriggerPathParams + remove_trigger_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = remove_trigger_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj = None + httpx_mock.add_response( + method="delete", + content=b"", + url="https://moira-api.example.com/trigger/{triggerID}".format(**path_params_json), + ) + result = await async_client.remove_trigger( + path_params=path_params_obj, + ) # type: ignore[func-returns-value] + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_trigger_metric(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTriggerMetricPathParams + delete_trigger_metric_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = delete_trigger_metric_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = DeleteTriggerMetricQueryParams + delete_trigger_metric_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = delete_trigger_metric_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/metrics?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.delete_trigger_metric( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_trigger_nodata_metrics(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTriggerNodataMetricsPathParams + delete_trigger_nodata_metrics_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = delete_trigger_nodata_metrics_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/metrics/nodata".format(**path_params_json), + ) + result = await async_client.delete_trigger_nodata_metrics( + path_params=path_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_trigger_throttling(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTriggerThrottlingPathParams + delete_trigger_throttling_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = delete_trigger_throttling_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj = None + httpx_mock.add_response( + method="delete", + content=b"", + url="https://moira-api.example.com/trigger/{triggerID}/throttling".format(**path_params_json), + ) + result = await async_client.delete_trigger_throttling( + path_params=path_params_obj, + ) # type: ignore[func-returns-value] + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_delete_pager(async_client: MoiraClientAsync, httpx_mock: HTTPXMock) -> None: + query_params_model = DeletePagerQueryParams + delete_pager_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = delete_pager_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggersSearchResultDeleteResponse + dto_triggers_search_result_delete_response_factory = ModelFactory.create_factory( + model=response_model, __use_defaults__=True + ) + result_obj = dto_triggers_search_result_delete_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/trigger/search/pager?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = await async_client.delete_pager( + query_params=query_params_obj, + ) + assert result == result_obj + + +@pytest.mark.asyncio +async def test_async_get_web_config_custom_error( + async_client_with_custom_error: MoiraClientAsync, httpx_mock: HTTPXMock +) -> None: + response_model = ApiWebConfig + api_web_config_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = api_web_config_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", json=result_json, status_code=404, url="https://moira-api.example.com/config" + ) + with pytest.raises(CustomError) as error: + await async_client_with_custom_error.get_web_config() + assert "My own error" in str(error.value) diff --git a/tests/client_tests/test_serialization.py b/tests/client_tests/test_serialization.py new file mode 100644 index 0000000..71b841c --- /dev/null +++ b/tests/client_tests/test_serialization.py @@ -0,0 +1,154 @@ +import pytest +from pydantic import BaseModel, ConfigDict, Field, ValidationError +from pydantic.experimental.missing_sentinel import MISSING + + +class BaseConfig: + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + ) + + +class NullableRequiredDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str | None = Field("default_string_value") + + +class NotNullableRequiredDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str = Field("default_string_value") + + +class NullableRequiredNoDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str | None + + +class NotNullableRequiredNoDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str + + +class NullableNotRequiredDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str | MISSING | None = Field("default_string_value") + + +class NotNullableNotRequiredDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str | MISSING = Field("default_string_value") + + +class NullableNotRequiredNoDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str | MISSING | None = Field(default=MISSING) + + +class NotNullableNotRequiredNoDefaultValueCaseModel(BaseModel, BaseConfig): + prop_schema: str | MISSING = Field(default=MISSING) + + +class TestNullableRequiredDefaultValueCaseModel: + def test_default(self) -> None: + model_object = NullableRequiredDefaultValueCaseModel() # type: ignore[call-arg] + assert model_object.model_dump() == {"prop_schema": "default_string_value"} + + def test_custom(self) -> None: + model_object = NullableRequiredDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + model_object = NullableRequiredDefaultValueCaseModel(prop_schema=None) + assert model_object.model_dump() == {"prop_schema": None} + + +class TestNotNullableRequiredDefaultValueCaseModel: + def test_default(self) -> None: + model_object = NotNullableRequiredDefaultValueCaseModel() # type: ignore[call-arg] + assert model_object.model_dump() == {"prop_schema": "default_string_value"} + + def test_custom(self) -> None: + model_object = NotNullableRequiredDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + with pytest.raises(ValidationError): + NotNullableRequiredDefaultValueCaseModel(prop_schema=None) # type: ignore[arg-type] + + +class TestNullableRequiredNoDefaultValueCaseModel: + def test_no_value(self) -> None: + with pytest.raises(ValidationError): + NullableRequiredNoDefaultValueCaseModel() # type: ignore[call-arg] + + def test_custom(self) -> None: + model_object = NullableRequiredNoDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + model_object = NullableRequiredNoDefaultValueCaseModel(prop_schema=None) + assert model_object.model_dump() == {"prop_schema": None} + + +class TestNotNullableRequiredNoDefaultValueCaseModel: + def test_no_value(self) -> None: + with pytest.raises(ValidationError): + NotNullableRequiredNoDefaultValueCaseModel() # type: ignore[call-arg] + + def test_custom(self) -> None: + model_object = NotNullableRequiredNoDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + with pytest.raises(ValidationError): + NotNullableRequiredNoDefaultValueCaseModel(prop_schema=None) # type: ignore[arg-type] + + +class TestNullableNotRequiredDefaultValueCaseModel: + def test_default(self) -> None: + model_object = NullableNotRequiredDefaultValueCaseModel() # type: ignore[call-arg] + assert model_object.model_dump() == {"prop_schema": "default_string_value"} + + def test_custom(self) -> None: + model_object = NullableNotRequiredDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + model_object = NullableNotRequiredDefaultValueCaseModel(prop_schema=None) + assert model_object.model_dump() == {"prop_schema": None} + + +class TestNotNullableNotRequiredDefaultValueCaseModel: + def test_default(self) -> None: + model_object = NotNullableNotRequiredDefaultValueCaseModel() # type: ignore[call-arg] + assert model_object.model_dump() == {"prop_schema": "default_string_value"} + + def test_custom(self) -> None: + model_object = NotNullableNotRequiredDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + with pytest.raises(ValidationError): + NotNullableNotRequiredDefaultValueCaseModel(prop_schema=None) + + +class TestNullableNotRequiredNoDefaultValueCaseModel: + def test_no_value(self) -> None: + model_object = NullableNotRequiredNoDefaultValueCaseModel() + assert model_object.model_dump() == {} + + def test_custom(self) -> None: + model_object = NullableNotRequiredNoDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + model_object = NullableNotRequiredNoDefaultValueCaseModel(prop_schema=None) + assert model_object.model_dump() == {"prop_schema": None} + + +class TestNotNullableNotRequiredNoDefaultValueCaseModel: + def test_no_value(self) -> None: + model_object = NotNullableNotRequiredNoDefaultValueCaseModel() + assert model_object.model_dump() == {} + + def test_custom(self) -> None: + model_object = NotNullableNotRequiredNoDefaultValueCaseModel(prop_schema="my_string") + assert model_object.model_dump() == {"prop_schema": "my_string"} + + def test_null(self) -> None: + with pytest.raises(ValidationError): + NotNullableNotRequiredNoDefaultValueCaseModel(prop_schema=None) diff --git a/tests/client_tests/test_sync_client.py b/tests/client_tests/test_sync_client.py new file mode 100644 index 0000000..3e3d566 --- /dev/null +++ b/tests/client_tests/test_sync_client.py @@ -0,0 +1,1435 @@ +from typing import Any +from urllib.parse import urlencode + +import pytest +from httptoolkit.response import Response +from polyfactory.factories.pydantic_factory import ModelFactory +from pydantic import RootModel +from pydantic_core import to_jsonable_python +from pytest_httpx import HTTPXMock + +from moira.clients import MoiraClient +from moira.exceptions import MoiraApiError +from moira.models.requests import ( + AddTeamUsersPathParams, + CreateNewTeamContactPathParams, + CreateNewTeamSubscriptionPathParams, + CreateTriggerQueryParams, + DeleteNotificationQueryParams, + DeleteNotificationsFilteredQueryParams, + DeletePagerQueryParams, + DeletePatternPathParams, + DeleteTeamPathParams, + DeleteTeamUserPathParams, + DeleteTriggerMetricPathParams, + DeleteTriggerMetricQueryParams, + DeleteTriggerNodataMetricsPathParams, + DeleteTriggerThrottlingPathParams, + GetAllHeavyTriggersQueryParams, + GetAllTeamsQueryParams, + GetContactByIdPathParams, + GetContactEventsByIdPathParams, + GetContactEventsByIdQueryParams, + GetContactsNoisinessQueryParams, + GetEventsListPathParams, + GetEventsListQueryParams, + GetNotificationsQueryParams, + GetSubscriptionPathParams, + GetTeamPathParams, + GetTeamSettingsPathParams, + GetTeamUsersPathParams, + GetTriggerDumpPathParams, + GetTriggerMetricsPathParams, + GetTriggerMetricsQueryParams, + GetTriggerPathParams, + GetTriggerQueryParams, + GetTriggersNoisinessQueryParams, + GetTriggerStatePathParams, + GetTriggerThrottlingPathParams, + RemoveContactPathParams, + RemoveSubscriptionPathParams, + RemoveTagPathParams, + RemoveTriggerPathParams, + RenderTriggerMetricsPathParams, + RenderTriggerMetricsQueryParams, + SearchTriggersQueryParams, + SendTestContactNotificationPathParams, + SendTestNotificationPathParams, + SetTeamUsersPathParams, + SetTriggerMaintenancePathParams, + UpdateContactPathParams, + UpdateSubscriptionPathParams, + UpdateTeamPathParams, + UpdateTriggerPathParams, + UpdateTriggerQueryParams, +) +from moira.models.responses import ( + ApiWebConfig, + DtoContact, + DtoContactEventItemList, + DtoContactList, + DtoContactNoisinessList, + DtoEventsList, + DtoMessageResponse, + DtoNotificationDeleteResponse, + DtoNotificationsList, + DtoNotifierState, + DtoNotifierStatesForSources, + DtoPatternList, + DtoSaveTeamResponse, + DtoSaveTriggerResponse, + DtoSubscription, + DtoSubscriptionList, + DtoTagsData, + DtoTagsStatistics, + DtoTeamMembers, + DtoTeamModel, + DtoTeamSettings, + DtoTeamsList, + DtoThrottlingResponse, + DtoTrigger, + DtoTriggerCheck, + DtoTriggerCheckResponse, + DtoTriggerDump, + DtoTriggerMaintenance, + DtoTriggerNoisinessList, + DtoTriggersList, + DtoTriggersSearchResultDeleteResponse, + DtoUser, + DtoUserSettings, + DtoUserTeams, +) + + +class CustomError(MoiraApiError): + def __init__(self, response: Response): + reason = response.reason + " My own error" + super(MoiraApiError, self).__init__(reason) + + +@pytest.fixture +def client() -> MoiraClient: + return MoiraClient(base_url="https://moira-api.example.com") + + +@pytest.fixture +def client_with_custom_error() -> MoiraClient: + return MoiraClient(base_url="https://moira-api.example.com", error_class=CustomError) + + +def test_get_web_config(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = ApiWebConfig + api_web_config_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = api_web_config_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/config") + result = client.get_web_config() + assert result == result_obj + + +def test_get_all_contacts(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoContactList + dto_contact_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/contact") + result = client.get_all_contacts() + assert result == result_obj + + +def test_get_contact_by_id(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetContactByIdPathParams + get_contact_by_id_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_contact_by_id_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/contact/{contactID}".format(**path_params_json), + ) + result = client.get_contact_by_id( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_contact_events_by_id(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetContactEventsByIdPathParams + get_contact_events_by_id_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = get_contact_events_by_id_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetContactEventsByIdQueryParams + get_contact_events_by_id_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_contact_events_by_id_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoContactEventItemList + dto_contact_event_item_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_event_item_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/contact/{contactID}/events?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_contact_events_by_id( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_contacts_noisiness(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = GetContactsNoisinessQueryParams + get_contacts_noisiness_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_contacts_noisiness_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoContactNoisinessList + dto_contact_noisiness_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_noisiness_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/contact/noisiness?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_contacts_noisiness( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_events_list(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetEventsListPathParams + get_events_list_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_events_list_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetEventsListQueryParams + get_events_list_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = get_events_list_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoEventsList + dto_events_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_events_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/event/{triggerID}?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_events_list( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_notifier_state_for_sources(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoNotifierStatesForSources + dto_notifier_states_for_sources_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifier_states_for_sources_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/health/notifier") + result = client.get_notifier_state_for_sources() + assert result == result_obj + + +def test_get_system_subscription(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoSubscriptionList + dto_subscription_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", json=result_json, url="https://moira-api.example.com/health/system-subscriptions" + ) + result = client.get_system_subscription() + assert result == result_obj + + +def test_get_notifications(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = GetNotificationsQueryParams + get_notifications_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_notifications_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoNotificationsList + dto_notifications_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifications_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/notification?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_notifications( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_all_patterns(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoPatternList + dto_pattern_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_pattern_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/pattern") + result = client.get_all_patterns() + assert result == result_obj + + +def test_get_user_subscriptions(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoSubscriptionList + dto_subscription_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/subscription") + result = client.get_user_subscriptions() + assert result == result_obj + + +def test_get_subscription(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetSubscriptionPathParams + get_subscription_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/subscription/{subscriptionID}".format(**path_params_json), + ) + result = client.get_subscription( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_all_system_tags(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoTagsData + dto_tags_data_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_tags_data_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/system-tag") + result = client.get_all_system_tags() + assert result == result_obj + + +def test_get_all_tags(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoTagsData + dto_tags_data_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_tags_data_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/tag") + result = client.get_all_tags() + assert result == result_obj + + +def test_get_all_tags_and_subscriptions(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoTagsStatistics + dto_tags_statistics_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_tags_statistics_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/tag/stats") + result = client.get_all_tags_and_subscriptions() + assert result == result_obj + + +def test_get_all_teams_for_user(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoUserTeams + dto_user_teams_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_user_teams_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/teams") + result = client.get_all_teams_for_user() + assert result == result_obj + + +def test_get_team(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTeamPathParams + get_team_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_team_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamModel + dto_team_model_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_model_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}".format(**path_params_json), + ) + result = client.get_team( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_team_settings(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTeamSettingsPathParams + get_team_settings_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_team_settings_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamSettings + dto_team_settings_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_settings_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}/settings".format(**path_params_json), + ) + result = client.get_team_settings( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_team_users(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTeamUsersPathParams + get_team_users_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_team_users_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}/users".format(**path_params_json), + ) + result = client.get_team_users( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_all_teams(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = GetAllTeamsQueryParams + get_all_teams_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = get_all_teams_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTeamsList + dto_teams_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_teams_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/teams/all?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_all_teams( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_all_triggers(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/trigger") + result = client.get_all_triggers() + assert result == result_obj + + +def test_get_trigger(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerPathParams + get_trigger_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_trigger_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetTriggerQueryParams + get_trigger_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = get_trigger_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_trigger( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_trigger_dump(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerDumpPathParams + get_trigger_dump_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_trigger_dump_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTriggerDump + dto_trigger_dump_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_dump_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/dump".format(**path_params_json), + ) + result = client.get_trigger_dump( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_trigger_metrics(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerMetricsPathParams + get_trigger_metrics_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = get_trigger_metrics_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = GetTriggerMetricsQueryParams + get_trigger_metrics_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_trigger_metrics_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/metrics?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_trigger_metrics( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_render_trigger_metrics(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = RenderTriggerMetricsPathParams + render_trigger_metrics_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = render_trigger_metrics_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = RenderTriggerMetricsQueryParams + render_trigger_metrics_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = render_trigger_metrics_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + + class RespBytes(RootModel[bytes]): ... + + resp_bytes_factory = ModelFactory.create_factory(model=RespBytes, __use_defaults__=True) + result_obj = resp_bytes_factory.build().root + httpx_mock.add_response( + method="get", + content=result_obj, + url="https://moira-api.example.com/trigger/{triggerID}/render?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.render_trigger_metrics( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_trigger_state(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerStatePathParams + get_trigger_state_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = get_trigger_state_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTriggerCheck + dto_trigger_check_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_check_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/state".format(**path_params_json), + ) + result = client.get_trigger_state( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_trigger_throttling(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = GetTriggerThrottlingPathParams + get_trigger_throttling_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = get_trigger_throttling_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoThrottlingResponse + dto_throttling_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_throttling_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/throttling".format(**path_params_json), + ) + result = client.get_trigger_throttling( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_get_all_heavy_triggers(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = GetAllHeavyTriggersQueryParams + get_all_heavy_triggers_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_all_heavy_triggers_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/heavy?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_all_heavy_triggers( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_triggers_noisiness(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = GetTriggersNoisinessQueryParams + get_triggers_noisiness_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = get_triggers_noisiness_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggerNoisinessList + dto_trigger_noisiness_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_noisiness_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/noisiness?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.get_triggers_noisiness( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_search_triggers(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = SearchTriggersQueryParams + search_triggers_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = search_triggers_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", + json=result_json, + url="https://moira-api.example.com/trigger/search?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.search_triggers( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_unused_triggers(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoTriggersList + dto_triggers_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_triggers_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/trigger/unused") + result = client.get_unused_triggers() + assert result == result_obj + + +def test_get_user_name(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoUser + dto_user_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_user_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/user") + result = client.get_user_name() + assert result == result_obj + + +def test_get_user_settings(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoUserSettings + dto_user_settings_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_user_settings_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="get", json=result_json, url="https://moira-api.example.com/user/settings") + result = client.get_user_settings() + assert result == result_obj + + +def test_send_test_contact_notification(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_obj: dict[Any, Any] = {} + body_json = to_jsonable_python(body_obj) + path_params_model = SendTestContactNotificationPathParams + send_test_contact_notification_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = send_test_contact_notification_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/contact/{contactID}/test".format(**path_params_json), + ) + result = client.send_test_contact_notification( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_create_tags(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTagsData + dto_tags_data_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_tags_data_factory.build() + body_json = to_jsonable_python(body_obj) + + class RespStr(RootModel[str]): ... + + resp_str_factory = ModelFactory.create_factory(model=RespStr, __use_defaults__=True) + result_obj = resp_str_factory.build().root + httpx_mock.add_response( + method="post", text=str(result_obj), match_json=body_json, url="https://moira-api.example.com/tag" + ) + result = client.create_tags( + body=body_obj, + ) + assert result == result_obj + + +def test_create_team(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamModel + dto_team_model_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_model_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoSaveTeamResponse + dto_save_team_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_team_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", json=result_json, match_json=body_json, url="https://moira-api.example.com/teams" + ) + result = client.create_team( + body=body_obj, + ) + assert result == result_obj + + +def test_create_new_team_contact(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_contact_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = CreateNewTeamContactPathParams + create_new_team_contact_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = create_new_team_contact_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/contacts".format(**path_params_json), + ) + result = client.create_new_team_contact( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_create_new_team_subscription(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_subscription_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = CreateNewTeamSubscriptionPathParams + create_new_team_subscription_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = create_new_team_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/subscriptions".format(**path_params_json), + ) + result = client.create_new_team_subscription( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_add_team_users(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_members_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = AddTeamUsersPathParams + add_team_users_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = add_team_users_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="post", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/users".format(**path_params_json), + ) + result = client.add_team_users( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_update_team(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamModel + dto_team_model_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_model_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateTeamPathParams + update_team_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = update_team_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSaveTeamResponse + dto_save_team_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_team_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="patch", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}".format(**path_params_json), + ) + result = client.update_team( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_create_new_contact(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_contact_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", json=result_json, match_json=body_json, url="https://moira-api.example.com/contact" + ) + result = client.create_new_contact( + body=body_obj, + ) + assert result == result_obj + + +def test_update_contact(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_contact_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateContactPathParams + update_contact_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = update_contact_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoContact + dto_contact_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_contact_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/contact/{contactID}".format(**path_params_json), + ) + result = client.update_contact( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_set_notifier_state(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoNotifierState + dto_notifier_state_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifier_state_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="put", json=result_json, url="https://moira-api.example.com/health/notifier") + result = client.set_notifier_state() + assert result == result_obj + + +def test_create_subscription(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_subscription_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", json=result_json, match_json=body_json, url="https://moira-api.example.com/subscription" + ) + result = client.create_subscription( + body=body_obj, + ) + assert result == result_obj + + +def test_update_subscription(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_subscription_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateSubscriptionPathParams + update_subscription_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = update_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSubscription + dto_subscription_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_subscription_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/subscription/{subscriptionID}".format(**path_params_json), + ) + result = client.update_subscription( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_send_test_notification(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = SendTestNotificationPathParams + send_test_notification_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = send_test_notification_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + url="https://moira-api.example.com/subscription/{subscriptionID}/test".format(**path_params_json), + ) + result = client.send_test_notification( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_set_team_users(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_team_members_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = SetTeamUsersPathParams + set_team_users_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = set_team_users_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/teams/{teamID}/users".format(**path_params_json), + ) + result = client.set_team_users( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_create_trigger(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_factory.build() + body_json = to_jsonable_python(body_obj) + query_params_model = CreateTriggerQueryParams + create_trigger_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = create_trigger_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoSaveTriggerResponse + dto_save_trigger_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_trigger_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/trigger?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.create_trigger( + query_params=query_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_update_trigger(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = UpdateTriggerPathParams + update_trigger_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = update_trigger_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = UpdateTriggerQueryParams + update_trigger_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = update_trigger_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoSaveTriggerResponse + dto_save_trigger_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_trigger_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/trigger/{triggerID}?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.update_trigger( + path_params=path_params_obj, + query_params=query_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_set_trigger_maintenance(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTriggerMaintenance + dto_trigger_maintenance_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_maintenance_factory.build() + body_json = to_jsonable_python(body_obj) + path_params_model = SetTriggerMaintenancePathParams + set_trigger_maintenance_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = set_trigger_maintenance_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/trigger/{triggerID}/setMaintenance".format(**path_params_json), + ) + result = client.set_trigger_maintenance( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_trigger_check(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_model = DtoTrigger + dto_trigger_factory = ModelFactory.create_factory(model=body_model, __use_defaults__=True) + body_obj = dto_trigger_factory.build() + body_json = to_jsonable_python(body_obj) + response_model = DtoTriggerCheckResponse + dto_trigger_check_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_trigger_check_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="put", json=result_json, match_json=body_json, url="https://moira-api.example.com/trigger/check" + ) + result = client.trigger_check( + body=body_obj, + ) + assert result == result_obj + + +def test_remove_contact(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + body_obj: dict[Any, Any] = {} + body_json = to_jsonable_python(body_obj) + path_params_model = RemoveContactPathParams + remove_contact_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = remove_contact_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + match_json=body_json, + url="https://moira-api.example.com/contact/{contactID}".format(**path_params_json), + ) + result = client.remove_contact( + path_params=path_params_obj, + body=body_obj, + ) + assert result == result_obj + + +def test_delete_all_events(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="delete", json=result_json, url="https://moira-api.example.com/event/all") + result = client.delete_all_events() + assert result == result_obj + + +def test_delete_notification(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = DeleteNotificationQueryParams + delete_notification_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = delete_notification_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoNotificationDeleteResponse + dto_notification_delete_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notification_delete_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/notification?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.delete_notification( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_delete_all_notifications(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = DtoNotificationsList + dto_notifications_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifications_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response(method="delete", json=result_json, url="https://moira-api.example.com/notification/all") + result = client.delete_all_notifications() + assert result == result_obj + + +def test_delete_notifications_filtered(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = DeleteNotificationsFilteredQueryParams + delete_notifications_filtered_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = delete_notifications_filtered_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoNotificationsList + dto_notifications_list_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_notifications_list_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/notification/filtered?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.delete_notifications_filtered( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_delete_pattern(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = DeletePatternPathParams + delete_pattern_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = delete_pattern_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/pattern/{pattern}".format(**path_params_json), + ) + result = client.delete_pattern( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_remove_subscription(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = RemoveSubscriptionPathParams + remove_subscription_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = remove_subscription_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/subscription/{subscriptionID}".format(**path_params_json), + ) + result = client.remove_subscription( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_remove_tag(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = RemoveTagPathParams + remove_tag_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = remove_tag_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoMessageResponse + dto_message_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_message_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/tag/{tag}".format(**path_params_json), + ) + result = client.remove_tag( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_delete_team(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTeamPathParams + delete_team_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = delete_team_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoSaveTeamResponse + dto_save_team_response_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_save_team_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}".format(**path_params_json), + ) + result = client.delete_team( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_delete_team_user(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTeamUserPathParams + delete_team_user_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = delete_team_user_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + response_model = DtoTeamMembers + dto_team_members_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = dto_team_members_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/teams/{teamID}/users/{teamUserID}".format(**path_params_json), + ) + result = client.delete_team_user( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_remove_trigger(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = RemoveTriggerPathParams + remove_trigger_path_params_factory = ModelFactory.create_factory(model=path_params_model, __use_defaults__=True) + path_params_obj = remove_trigger_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj = None + httpx_mock.add_response( + method="delete", + content=b"", + url="https://moira-api.example.com/trigger/{triggerID}".format(**path_params_json), + ) + result = client.remove_trigger( + path_params=path_params_obj, + ) # type: ignore[func-returns-value] + assert result == result_obj + + +def test_delete_trigger_metric(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTriggerMetricPathParams + delete_trigger_metric_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = delete_trigger_metric_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + query_params_model = DeleteTriggerMetricQueryParams + delete_trigger_metric_query_params_factory = ModelFactory.create_factory( + model=query_params_model, __use_defaults__=True + ) + query_params_obj = delete_trigger_metric_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/metrics?{query_params}".format( + **path_params_json, query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.delete_trigger_metric( + path_params=path_params_obj, + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_delete_trigger_nodata_metrics(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTriggerNodataMetricsPathParams + delete_trigger_nodata_metrics_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = delete_trigger_nodata_metrics_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj: dict[Any, Any] = {} + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/trigger/{triggerID}/metrics/nodata".format(**path_params_json), + ) + result = client.delete_trigger_nodata_metrics( + path_params=path_params_obj, + ) + assert result == result_obj + + +def test_delete_trigger_throttling(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + path_params_model = DeleteTriggerThrottlingPathParams + delete_trigger_throttling_path_params_factory = ModelFactory.create_factory( + model=path_params_model, __use_defaults__=True + ) + path_params_obj = delete_trigger_throttling_path_params_factory.build() + path_params_json = to_jsonable_python(path_params_obj) + result_obj = None + httpx_mock.add_response( + method="delete", + content=b"", + url="https://moira-api.example.com/trigger/{triggerID}/throttling".format(**path_params_json), + ) + result = client.delete_trigger_throttling( + path_params=path_params_obj, + ) # type: ignore[func-returns-value] + assert result == result_obj + + +def test_delete_pager(client: MoiraClient, httpx_mock: HTTPXMock) -> None: + query_params_model = DeletePagerQueryParams + delete_pager_query_params_factory = ModelFactory.create_factory(model=query_params_model, __use_defaults__=True) + query_params_obj = delete_pager_query_params_factory.build() + query_params_json = to_jsonable_python(query_params_obj) + response_model = DtoTriggersSearchResultDeleteResponse + dto_triggers_search_result_delete_response_factory = ModelFactory.create_factory( + model=response_model, __use_defaults__=True + ) + result_obj = dto_triggers_search_result_delete_response_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="delete", + json=result_json, + url="https://moira-api.example.com/trigger/search/pager?{query_params}".format( + query_params=urlencode(query_params_json, doseq=False) + ), + ) + result = client.delete_pager( + query_params=query_params_obj, + ) + assert result == result_obj + + +def test_get_web_config_custom_error(client_with_custom_error: MoiraClient, httpx_mock: HTTPXMock) -> None: + response_model = ApiWebConfig + api_web_config_factory = ModelFactory.create_factory(model=response_model, __use_defaults__=True) + result_obj = api_web_config_factory.build() + result_json = to_jsonable_python(result_obj) + httpx_mock.add_response( + method="get", json=result_json, status_code=404, url="https://moira-api.example.com/config" + ) + with pytest.raises(CustomError) as error: + client_with_custom_error.get_web_config() + assert "My own error" in str(error.value) diff --git a/tests/models/team/_mock.py b/tests/models/team/_mock.py deleted file mode 100644 index ff50876..0000000 --- a/tests/models/team/_mock.py +++ /dev/null @@ -1,11 +0,0 @@ -try: - from unittest.mock import patch, Mock - -except ImportError: - from mock import patch, Mock - - -__all__ = [ - "patch", - "Mock", -] diff --git a/tests/models/team/contact/test_managers.py b/tests/models/team/contact/test_managers.py deleted file mode 100644 index d12099f..0000000 --- a/tests/models/team/contact/test_managers.py +++ /dev/null @@ -1,64 +0,0 @@ -from moira_client.client import Client -from moira_client.models.contact import Contact -from moira_client.models.team.contact import TeamContactManager -from .._mock import patch, Mock -from ...test_model import ModelTest - - -class TestTeamContactManager(ModelTest): - def __init__(self, *args, **kwargs) -> None: - self._client = Client(self.api_url) - self._manager = TeamContactManager(self._client) - super().__init__(*args, **kwargs) - - @property - def _request_data(self) -> dict: - return { - "name": "Mail Alerts", - "team_id": "string", - "type": "mail", - "value": "devops@example.com", - "extra_message": "string", - } - - @property - def _response_data(self) -> dict: - return { - "id": "1dd38765-c5be-418d-81fa-7a5f879c2315", - "name": "Mail Alerts", - "team_id": "string", - "type": "mail", - "user": "", - "value": "devops@example.com", - "extra_message": "string", - } - - @property - def _contact(self) -> Contact: - return Contact(**self._request_data) - - def _assert_is_resource_request(self, request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams/{team_id}/contacts".format(team_id=self._contact.team_id) - - def _assert_is_request_data_sent(self, request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 1 - assert kwargs["json"] == self._request_data - - def test_create(self) -> None: - with patch.object(self._client, "post", return_value=self._response_data) as request: - response = self._manager.create(self._contact.team_id, self._contact) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_request_data_sent(request) - - assert response.id == self._response_data["id"] - assert response.name == self._response_data["name"] - assert response.team_id == self._response_data["team_id"] - assert response.type == self._response_data["type"] - assert response.user == self._response_data["user"] - assert response.value == self._response_data["value"] - assert response.extra_message == self._response_data["extra_message"] diff --git a/tests/models/team/settings/test_managers.py b/tests/models/team/settings/test_managers.py deleted file mode 100644 index 93339a4..0000000 --- a/tests/models/team/settings/test_managers.py +++ /dev/null @@ -1,115 +0,0 @@ -from moira_client.client import Client -from moira_client.models.team.settings import TeamSettingsManager -from .._mock import patch, Mock -from ...test_model import ModelTest - - -class TestTeamSettingsManager(ModelTest): - def __init__(self, *args, **kwargs) -> None: - self._client = Client(self.api_url) - self._manager = TeamSettingsManager(self._client) - super().__init__(*args, **kwargs) - - @property - def _response_data_contact(self) -> dict: - return { - "id": "1dd38765-c5be-418d-81fa-7a5f879c2315", - "name": "Mail Alerts", - "team_id": "string", - "type": "mail", - "user": "", - "value": "devops@example.com", - } - - @property - def _response_data_subscription(self) -> dict: - return { - "any_tags": False, - "contacts": [ - "acd2db98-1659-4a2f-b227-52d71f6e3ba1", - ], - "enabled": True, - "id": "292516ed-4924-4154-a62c-ebe312431fce", - "ignore_recoverings": False, - "ignore_warnings": False, - "plotting": { - "enabled": True, - "theme": "dark", - }, - "sched": { - "days": [ - { - "enabled": True, - "name": "Mon", - } - ], - "endOffset": 1439, - "startOffset": 0, - "tzOffset": -60, - }, - "tags": [ - "server", - "cpu", - ], - "team_id": "324516ed-4924-4154-a62c-eb124234fce", - "throttling": False, - "user": "", - } - - @property - def _team_id(self) -> str: - return "d5d98eb3-ee18-4f75-9364-244f67e23b54" - - @property - def _response_data(self) -> dict: - return { - "contacts": [ - self._response_data_contact, - ], - "subscriptions": [ - self._response_data_subscription, - ], - "team_id": self._team_id, - } - - def _assert_is_resource_request(self, request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams/{team_id}/settings".format(team_id=self._team_id) - - @staticmethod - def _assert_is_no_data_sent(request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 0 - - def test_get_all(self) -> None: - with patch.object(self._client, "get", return_value=self._response_data) as request: - response = self._manager.get(self._team_id) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_no_data_sent(request) - - assert response.team_id == self._team_id - - assert len(response.contacts) == 1 - - assert response.contacts[0].id == self._response_data_contact["id"] - assert response.contacts[0].name == self._response_data_contact["name"] - assert response.contacts[0].team_id == self._response_data_contact["team_id"] - assert response.contacts[0].type == self._response_data_contact["type"] - assert response.contacts[0].user == self._response_data_contact["user"] - assert response.contacts[0].value == self._response_data_contact["value"] - - assert len(response.subscriptions) == 1 - - assert response.subscriptions[0].team_id == self._response_data_subscription["team_id"] - assert response.subscriptions[0].contacts == self._response_data_subscription["contacts"] - assert response.subscriptions[0].tags == self._response_data_subscription["tags"] - assert response.subscriptions[0].enabled == self._response_data_subscription["enabled"] - assert response.subscriptions[0].any_tags == self._response_data_subscription["any_tags"] - assert response.subscriptions[0].throttling == self._response_data_subscription["throttling"] - assert response.subscriptions[0].sched == self._response_data_subscription["sched"] - assert response.subscriptions[0].ignore_warnings == self._response_data_subscription["ignore_warnings"] - assert response.subscriptions[0].ignore_recoverings == self._response_data_subscription["ignore_recoverings"] - assert response.subscriptions[0].plotting == self._response_data_subscription["plotting"] diff --git a/tests/models/team/subscription/__init__.py b/tests/models/team/subscription/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/models/team/subscription/test_managers.py b/tests/models/team/subscription/test_managers.py deleted file mode 100644 index e3e8ea8..0000000 --- a/tests/models/team/subscription/test_managers.py +++ /dev/null @@ -1,87 +0,0 @@ -from moira_client.client import Client -from moira_client.models.subscription import SubscriptionModel -from moira_client.models.team.subscription import TeamSubscriptionManager -from .._mock import patch, Mock -from ...test_model import ModelTest - - -class TestTeamSubscriptionManager(ModelTest): - def __init__(self, *args, **kwargs) -> None: - self._client = Client(self.api_url) - self._manager = TeamSubscriptionManager(self._client) - super().__init__(*args, **kwargs) - - @property - def _request_data(self) -> dict: - return { - "team_id": "324516ed-4924-4154-a62c-eb124234fce", - "contacts": [ - "acd2db98-1659-4a2f-b227-52d71f6e3ba1", - ], - "tags": [ - "server", - "cpu", - ], - "enabled": True, - "any_tags": False, - "throttling": False, - "sched": { - "days": [ - { - "enabled": True, - "name": "Mon", - }, - ], - "endOffset": 1439, - "startOffset": 0, - "tzOffset": -60, - }, - "ignore_warnings": False, - "ignore_recoverings": False, - "plotting": { - "enabled": True, - "theme": "dark", - }, - } - - @property - def _response_data(self) -> dict: - return { - "id": "292516ed-4924-4154-a62c-ebe312431fce", - **self._request_data, - } - - @property - def _subscription(self) -> SubscriptionModel: - return SubscriptionModel(**self._request_data) - - def _assert_is_resource_request(self, request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams/{team_id}/subscriptions".format( - team_id=self._subscription.team_id, - ) - - def _assert_is_request_data_sent(self, request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 1 - assert kwargs["json"] == self._request_data - - def test_create(self) -> None: - with patch.object(self._client, "post", return_value=self._response_data) as request: - response = self._manager.create(self._subscription.team_id, self._subscription) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_request_data_sent(request) - - assert response.team_id == self._response_data["team_id"] - assert response.contacts == self._response_data["contacts"] - assert response.tags == self._response_data["tags"] - assert response.enabled == self._response_data["enabled"] - assert response.any_tags == self._response_data["any_tags"] - assert response.throttling == self._response_data["throttling"] - assert response.sched == self._response_data["sched"] - assert response.ignore_warnings == self._response_data["ignore_warnings"] - assert response.ignore_recoverings == self._response_data["ignore_recoverings"] - assert response.plotting == self._response_data["plotting"] diff --git a/tests/models/team/subscription/test_models.py b/tests/models/team/subscription/test_models.py deleted file mode 100644 index e4c84fe..0000000 --- a/tests/models/team/subscription/test_models.py +++ /dev/null @@ -1,83 +0,0 @@ -from moira_client.client import Client -from moira_client.models.subscription import Subscription -from .._mock import patch, Mock -from ...test_model import ModelTest - - -class TestSubscription(ModelTest): - def __init__(self, *args, **kwargs) -> None: - self._client = Client(self.api_url) - super().__init__(*args, **kwargs) - - @property - def _request_data(self) -> dict: - return { - "team_id": "324516ed-4924-4154-a62c-eb124234fce", - "contacts": [ - "acd2db98-1659-4a2f-b227-52d71f6e3ba1", - ], - "tags": [ - "server", - "cpu", - ], - "enabled": True, - "any_tags": False, - "throttling": False, - "sched": { - "days": [ - { - "enabled": True, - "name": "Mon", - }, - ], - "endOffset": 1439, - "startOffset": 0, - "tzOffset": -60, - }, - "ignore_warnings": False, - "ignore_recoverings": False, - "plotting": { - "enabled": True, - "theme": "dark", - }, - } - - @property - def _response_data(self) -> dict: - return { - "id": "292516ed-4924-4154-a62c-ebe312431fce", - **self._request_data, - } - - @staticmethod - def _assert_is_resource_request(request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "subscription" - - def _assert_is_request_data_sent(self, request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 1 - assert kwargs["json"] == self._request_data - - def test_save(self) -> None: - subscription = Subscription(self._client, **self._request_data) - - with patch.object(self._client, "put", return_value=self._response_data) as request: - subscription.save() - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_request_data_sent(request) - - assert subscription.id == self._response_data["id"] - assert subscription.team_id == self._response_data["team_id"] - assert subscription.contacts == self._response_data["contacts"] - assert subscription.tags == self._response_data["tags"] - assert subscription.enabled == self._response_data["enabled"] - assert subscription.any_tags == self._response_data["any_tags"] - assert subscription.throttling == self._response_data["throttling"] - assert subscription.sched == self._response_data["sched"] - assert subscription.ignore_warnings == self._response_data["ignore_warnings"] - assert subscription.ignore_recoverings == self._response_data["ignore_recoverings"] - assert subscription.plotting == self._response_data["plotting"] diff --git a/tests/models/team/test_managers.py b/tests/models/team/test_managers.py deleted file mode 100644 index 0ca037a..0000000 --- a/tests/models/team/test_managers.py +++ /dev/null @@ -1,121 +0,0 @@ -from moira_client.client import Client -from moira_client.models.team import TeamManager, TeamModel -from ._mock import patch, Mock -from ..test_model import ModelTest - - -class TestTeamManager(ModelTest): - def __init__(self, *args, **kwargs) -> None: - self._client = Client(self.api_url) - self._manager = TeamManager(self._client) - super().__init__(*args, **kwargs) - - @property - def _request_data(self) -> dict: - return { - "name": "Infrastructure Team", - "description": "Team that holds all members of infrastructure division", - } - - @property - def _single_response_data(self) -> dict: - return { - "id": "d5d98eb3-ee18-4f75-9364-244f67e23b54", - } - - @property - def _response_data(self) -> dict: - return { - **self._single_response_data, - **self._request_data, - } - - @property - def _team(self) -> TeamModel: - return TeamModel( - id="d5d98eb3-ee18-4f75-9364-244f67e23b54", - name="Infrastructure Team", - description="Team that holds all members of infrastructure division", - ) - - @staticmethod - def _assert_is_resource_request(request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams" - - def _assert_is_object_request(self, request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams/{team_id}".format(team_id=self._team.id) - - def _assert_is_request_data_sent(self, request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 1 - assert kwargs["json"] == self._request_data - - @staticmethod - def _assert_is_no_data_sent(request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 0 - - def test_get_all(self) -> None: - return_value = { - "teams": [ - self._response_data, - ], - } - - with patch.object(self._client, "get", return_value=return_value) as request: - response = self._manager.get_all() - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_no_data_sent(request) - - assert len(response.teams) == 1 - assert response.teams[0].id == self._response_data["id"] - assert response.teams[0].name == self._response_data["name"] - assert response.teams[0].description == self._response_data["description"] - - def test_create(self): - with patch.object(self._client, "post", return_value=self._single_response_data) as request: - response = self._manager.create(self._team) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_request_data_sent(request) - - assert response.id == self._single_response_data["id"] - - def test_delete(self): - with patch.object(self._client, "delete", return_value=self._single_response_data) as request: - response = self._manager.delete(self._team.id) - - assert len(request.mock_calls) == 1 - self._assert_is_object_request(request) - self._assert_is_no_data_sent(request) - - assert response.id == self._single_response_data["id"] - - def test_get(self): - with patch.object(self._client, "get", return_value=self._response_data) as request: - response = self._manager.get(self._team.id) - - assert len(request.mock_calls) == 1 - self._assert_is_object_request(request) - self._assert_is_no_data_sent(request) - - assert response.id == self._response_data["id"] - assert response.name == self._response_data["name"] - assert response.description == self._response_data["description"] - - def test_update(self): - with patch.object(self._client, "patch", return_value=self._single_response_data) as request: - response = self._manager.update(self._team.id, self._team) - - assert len(request.mock_calls) == 1 - self._assert_is_object_request(request) - self._assert_is_request_data_sent(request) - - assert response.id == self._single_response_data["id"] diff --git a/tests/models/team/user/__init__.py b/tests/models/team/user/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/models/team/user/test_managers.py b/tests/models/team/user/test_managers.py deleted file mode 100644 index c9e37dd..0000000 --- a/tests/models/team/user/test_managers.py +++ /dev/null @@ -1,88 +0,0 @@ -from moira_client.client import Client -from moira_client.models.team.user import TeamUserManager, TeamMembers -from .._mock import patch, Mock -from ...test_model import ModelTest - - -class TestTeamUserManager(ModelTest): - def __init__(self, *args, **kwargs) -> None: - self._client = Client(self.api_url) - self._manager = TeamUserManager(self._client) - super().__init__(*args, **kwargs) - - @property - def _request_data(self) -> dict: - return { - "usernames": ["anonymous"], - } - - @property - def _response_data(self) -> dict: - return self._request_data - - @property - def _users(self) -> TeamMembers: - return TeamMembers(**self._request_data) - - @property - def _team_id(self) -> str: - return "d5d98eb3-ee18-4f75-9364-244f67e23b54" - - def _assert_is_resource_request(self, request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams/{team_id}/users".format(team_id=self._team_id) - - def _assert_is_object_request(self, request: Mock) -> None: - args = request.call_args[0] - assert len(args) == 1 - assert args[0] == "teams/{team_id}/users/{team_user_id}".format( - team_id=self._team_id, - team_user_id=self._users.usernames[0], - ) - - def _assert_is_request_data_sent(self, request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 1 - assert kwargs["json"] == self._request_data - - @staticmethod - def _assert_is_no_data_sent(request: Mock) -> None: - kwargs = request.call_args[1] - assert len(kwargs) == 0 - - def _assert_response(self, response) -> None: - assert len(response.usernames) == 1 - assert response.usernames[0] == self._response_data["usernames"][0] - - def test_get(self) -> None: - with patch.object(self._client, "get", return_value=self._response_data) as request: - self._assert_response(self._manager.get(self._team_id)) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_no_data_sent(request) - - def test_add(self) -> None: - with patch.object(self._client, "post", return_value=self._response_data) as request: - self._assert_response(self._manager.add(self._team_id, self._users)) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_request_data_sent(request) - - def test_set(self) -> None: - with patch.object(self._client, "put", return_value=self._response_data) as request: - self._assert_response(self._manager.set(self._team_id, self._users)) - - assert len(request.mock_calls) == 1 - self._assert_is_resource_request(request) - self._assert_is_request_data_sent(request) - - def test_delete(self) -> None: - with patch.object(self._client, "delete", return_value=self._response_data) as request: - self._assert_response(self._manager.delete(self._team_id, self._users.usernames[0])) - - assert len(request.mock_calls) == 1 - self._assert_is_object_request(request) - self._assert_is_no_data_sent(request) diff --git a/tests/models/test_config.py b/tests/models/test_config.py deleted file mode 100644 index 4edf6b5..0000000 --- a/tests/models/test_config.py +++ /dev/null @@ -1,51 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import ResponseStructureError -from .test_model import ModelTest -from moira_client.models.config import ConfigManager - - -class ConfigTest(ModelTest): - - def test_fetch(self): - client = Client(self.api_url) - config_manager = ConfigManager(client) - - with patch.object(client, 'get', return_value={'remoteAllowed': True, 'contacts': []}) as get_mock: - res = config_manager.fetch() - - self.assertTrue(get_mock.called) - - def test_fetch_with_contacts(self): - client = Client(self.api_url) - config_manager = ConfigManager(client) - - with patch.object(client, 'get', return_value={'remoteAllowed': True, - 'contacts': [{'label': 'Telegram', 'type': 'telegram'}]} - ) as get_mock: - res = config_manager.fetch() - self.assertTrue(res.remoteAllowed) - - self.assertEqual(res.contacts[0].type, 'telegram') - self.assertEqual(res.contacts[0].label, 'Telegram') - self.assertTrue(get_mock.called) - - def test_fetch_fail_without_required_fields(self): - client = Client(self.api_url) - config_manager = ConfigManager(client) - - with patch.object(client, 'get', return_value={'remoteAllowed': True}) as get_mock: - with self.assertRaises(ResponseStructureError): - config_manager.fetch() - self.assertTrue(get_mock.called) - - with patch.object(client, 'get', return_value={'contacts': True}) as get_mock: - with self.assertRaises(ResponseStructureError): - config_manager.fetch() - self.assertTrue(get_mock.called) diff --git a/tests/models/test_contact.py b/tests/models/test_contact.py deleted file mode 100644 index bfe7af6..0000000 --- a/tests/models/test_contact.py +++ /dev/null @@ -1,135 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import InvalidJSONError -from moira_client.client import ResponseStructureError -from moira_client.models.contact import CONTACT_SLACK -from moira_client.models.contact import Contact -from moira_client.models.contact import ContactManager -from .test_model import ModelTest - - -class ContactTest(ModelTest): - - def test_add(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - - contact_value = '#channel' - contact_id = 1 - contact_type = CONTACT_SLACK - existing_contact = { - 'value': contact_value, - 'type': contact_type, - } - - with patch.object(client, 'put', return_value={'id': contact_id}) as put_mock, \ - patch.object(client, 'get', return_value={'contacts': [existing_contact]}) as get_mock: - res_contact = contact_manager.add(contact_value, contact_type) - - self.assertTrue(put_mock.called) - self.assertTrue(get_mock.called) - - expected_request_data = { - 'value': contact_value, - 'type': contact_type - } - - expected_contact = Contact(id=contact_id, **expected_request_data) - - self.assertEqual(expected_contact, res_contact) - - put_mock.assert_called_with('contact', json=expected_request_data) - - def test_add_bad_response(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - - contact_value = '#channel' - contact_type = CONTACT_SLACK - existing_contact = { - 'value': contact_value, - 'type': contact_type, - } - - with patch.object(client, 'put', return_value={}) as put_mock, \ - patch.object(client, 'get', return_value={'contacts': [existing_contact]}) as get_mock: - with self.assertRaises(ResponseStructureError): - contact_manager.add(contact_value, contact_type) - - self.assertTrue(put_mock.called) - self.assertTrue(get_mock.called) - expected_request_data = { - 'value': contact_value, - 'type': contact_type - } - put_mock.assert_called_with('contact', json=expected_request_data) - - def test_add_contact_exist(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - contact_value, contact_type, contact_name = '#channel', CONTACT_SLACK, 'name' - existing_contact = { - 'value': contact_value, - 'type': contact_type, - 'name': contact_name, - } - - with patch.object(client, 'put', return_value={}) as put_mock, \ - patch.object(client, 'get', return_value={'contacts': [existing_contact]}) as get_mock: - contact_manager.add(contact_value, contact_type, contact_name) - - self.assertTrue(get_mock.called) - self.assertFalse(put_mock.called) - - def test_fetch_all(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - contact_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('contact') - - def test_fetch_all_bad_response(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - contact_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('contact') - - def test_delete(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - - contact_id = '1' - - with patch.object(client, 'delete', new=Mock(side_effect=InvalidJSONError(b''))) as delete_mock: - res = contact_manager.delete(contact_id) - - self.assertTrue(delete_mock.called) - self.assertTrue(res) - delete_mock.assert_called_with('contact/' + contact_id) - - def test_delete_fail(self): - client = Client(self.api_url) - contact_manager = ContactManager(client) - - contact_id = '1' - - with patch.object(client, 'delete') as delete_mock: - res = contact_manager.delete(contact_id) - - self.assertTrue(delete_mock.called) - self.assertFalse(res) - delete_mock.assert_called_with('contact/' + contact_id) diff --git a/tests/models/test_event.py b/tests/models/test_event.py deleted file mode 100644 index 3825869..0000000 --- a/tests/models/test_event.py +++ /dev/null @@ -1,53 +0,0 @@ -try: - from unittest.mock import patch -except ImportError: - from mock import patch - -from moira_client.client import Client -from moira_client.client import ResponseStructureError -from moira_client.models.event import EventManager -from moira_client.models.event import MAX_FETCH_LIMIT -from moira_client.models.trigger import Trigger -from .test_model import ModelTest - - -class EventTest(ModelTest): - - def test_fetch_by_trigger(self): - client = Client(self.api_url) - contact_manager = EventManager(client) - - trigger_id = '1' - trigger = Trigger(client, 'Name', ['tag'], ['target'], 0, 1, id=trigger_id) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - contact_manager.fetch_by_trigger(trigger) - - self.assertTrue(get_mock.called) - - expected_request_data = { - 'p': 0, - 'size': MAX_FETCH_LIMIT - } - - get_mock.assert_called_with('event/' + trigger_id, params=expected_request_data) - - def test_fetch_by_trigger_bad_response(self): - client = Client(self.api_url) - contact_manager = EventManager(client) - - trigger_id = '1' - trigger = Trigger(client, 'Name', ['tag'], ['target'], 0, 1, id=trigger_id) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - contact_manager.fetch_by_trigger(trigger) - - self.assertTrue(get_mock.called) - - expected_request_data = { - 'p': 0, - 'size': MAX_FETCH_LIMIT - } - - get_mock.assert_called_with('event/' + trigger_id, params=expected_request_data) diff --git a/tests/models/test_health.py b/tests/models/test_health.py deleted file mode 100644 index 3b1f1a5..0000000 --- a/tests/models/test_health.py +++ /dev/null @@ -1,85 +0,0 @@ -try: - from unittest.mock import patch -except ImportError: - from mock import patch - -from moira_client.client import Client -from moira_client.client import ResponseStructureError -from moira_client.models.health import HealthManager -from .test_model import ModelTest - - -class HealthTest(ModelTest): - - def test_get_notifier_state(self): - client = Client(self.api_url) - health_manager = HealthManager(client) - - with patch.object(client, 'get', return_value={'state': 'OK'}) as get_mock: - health_manager.get_notifier_state() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('health/notifier') - - def test_get_notifier_state_bad_response(self): - client = Client(self.api_url) - health_manager = HealthManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - health_manager.get_notifier_state() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('health/notifier') - - def test_disable_notifications(self): - client = Client(self.api_url) - health_manager = HealthManager(client) - - with patch.object(client, 'put', return_value={'state': 'ERROR'}) as put_mock: - res = health_manager.disable_notifications() - - data = {'state': 'ERROR'} - - self.assertTrue(put_mock.called) - self.assertTrue(res) - put_mock.assert_called_with('health/notifier', json=data) - - def test_disable_notifications_bad_response(self): - client = Client(self.api_url) - health_manager = HealthManager(client) - - with patch.object(client, 'put') as put_mock: - with self.assertRaises(ResponseStructureError): - health_manager.disable_notifications() - - data = {'state': 'ERROR'} - - self.assertTrue(put_mock.called) - put_mock.assert_called_with('health/notifier', json=data) - - def test_enable_notifications(self): - client = Client(self.api_url) - health_manager = HealthManager(client) - - with patch.object(client, 'put', return_value={'state': 'OK'}) as put_mock: - res = health_manager.enable_notifications() - - data = {'state': 'OK'} - - self.assertTrue(put_mock.called) - self.assertTrue(res) - put_mock.assert_called_with('health/notifier', json=data) - - def test_enable_notifications_bad_response(self): - client = Client(self.api_url) - health_manager = HealthManager(client) - - with patch.object(client, 'put') as put_mock: - with self.assertRaises(ResponseStructureError): - health_manager.enable_notifications() - - data = {'state': 'OK'} - - self.assertTrue(put_mock.called) - put_mock.assert_called_with('health/notifier', json=data) diff --git a/tests/models/test_model.py b/tests/models/test_model.py deleted file mode 100644 index 6d7da8f..0000000 --- a/tests/models/test_model.py +++ /dev/null @@ -1,9 +0,0 @@ -import unittest - - -class ModelTest(unittest.TestCase): - TEST_API_URL = 'http://test/url' - - @property - def api_url(self): - return self.TEST_API_URL diff --git a/tests/models/test_notification.py b/tests/models/test_notification.py deleted file mode 100644 index 112537a..0000000 --- a/tests/models/test_notification.py +++ /dev/null @@ -1,62 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import InvalidJSONError -from moira_client.client import ResponseStructureError -from moira_client.models.notification import NotificationManager -from .test_model import ModelTest - - -class NotificationTest(ModelTest): - - def test_fetch_all(self): - client = Client(self.api_url) - contact_manager = NotificationManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - contact_manager.fetch_all() - - params = {'end': -1, 'start': 0} - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('notification', params=params) - - def test_fetch_all_bad_response(self): - client = Client(self.api_url) - contact_manager = NotificationManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - contact_manager.fetch_all() - - params = {'end': -1, 'start': 0} - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('notification', params=params) - - def test_delete_all(self): - client = Client(self.api_url) - notification_manager = NotificationManager(client) - - with patch.object(client, 'delete', new=Mock(side_effect=InvalidJSONError(b''))) as delete_mock: - res = notification_manager.delete_all() - - self.assertTrue(delete_mock.called) - self.assertTrue(res) - delete_mock.assert_called_with('notification/all') - - def test_delete_all_bad_response(self): - client = Client(self.api_url) - notification_manager = NotificationManager(client) - - with patch.object(client, 'delete') as delete_mock: - res = notification_manager.delete_all() - - self.assertTrue(delete_mock.called) - self.assertFalse(res) - delete_mock.assert_called_with('notification/all') diff --git a/tests/models/test_pattern.py b/tests/models/test_pattern.py deleted file mode 100644 index f05ceac..0000000 --- a/tests/models/test_pattern.py +++ /dev/null @@ -1,62 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import InvalidJSONError -from moira_client.client import ResponseStructureError -from moira_client.models.pattern import PatternManager -from .test_model import ModelTest - - -class PatternTest(ModelTest): - - def test_fetch_all(self): - client = Client(self.api_url) - pattern_manager = PatternManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - pattern_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('pattern') - - def test_fetch_all_bad_response(self): - client = Client(self.api_url) - pattern_manager = PatternManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - pattern_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('pattern') - - def test_delete(self): - client = Client(self.api_url) - pattern_manager = PatternManager(client) - - pattern_id = '1' - - with patch.object(client, 'delete', new=Mock(side_effect=InvalidJSONError(b''))) as delete_mock: - res = pattern_manager.delete(pattern_id) - - self.assertTrue(delete_mock.called) - self.assertTrue(res) - delete_mock.assert_called_with('pattern/' + pattern_id) - - def test_delete_fail(self): - client = Client(self.api_url) - pattern_manager = PatternManager(client) - - pattern_id = '1' - - with patch.object(client, 'delete') as delete_mock: - res = pattern_manager.delete(pattern_id) - - self.assertTrue(delete_mock.called) - self.assertFalse(res) - delete_mock.assert_called_with('pattern/' + pattern_id) diff --git a/tests/models/test_subscription.py b/tests/models/test_subscription.py deleted file mode 100644 index 07801b0..0000000 --- a/tests/models/test_subscription.py +++ /dev/null @@ -1,114 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import InvalidJSONError -from moira_client.client import ResponseStructureError -from moira_client.models.subscription import SubscriptionManager -from .test_model import ModelTest - - -class SubscriptionTest(ModelTest): - - def test_create(self): - client = Client(self.api_url) - manager = SubscriptionManager(client) - - tags = ['server', 'cpu'] - contacts = ['acd2db98-1659-4a2f-b227-52d71f6e3ba1'] - s = manager.create(tags, contacts) - - with patch.object(client, 'put', return_value={"id": "e5cd5d73-d893-42b5-98b5-f9bd6c7bc501"}) as put_mock: - s.save() - - self.assertTrue(put_mock.called) - args_ = put_mock.call_args[1] - body_json = args_['json'] - # check required fields - self.assertEqual(tags, body_json['tags']) - self.assertEqual(contacts, body_json['contacts']) - # check default values - self.assertEqual(True, body_json['enabled']) - self.assertEqual(True, body_json['throttling']) - self.assertTrue('sched' in body_json) - self.assertEqual(False, body_json['ignore_warnings']) - self.assertEqual(False, body_json['ignore_recoverings']) - self.assertTrue('plotting' in body_json) - self.assertEqual(False, body_json['any_tags']) - - def test_fetch_all(self): - client = Client(self.api_url) - subscription_manager = SubscriptionManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - subscription_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('subscription') - - def test_fetch_all_bad_response(self): - client = Client(self.api_url) - subscription_manager = SubscriptionManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - subscription_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('subscription') - - def test_delete(self): - client = Client(self.api_url) - subscription_manager = SubscriptionManager(client) - - subscription_id = '1' - - with patch.object(client, 'delete', new=Mock(side_effect=InvalidJSONError(b''))) as delete_mock: - res = subscription_manager.delete(subscription_id) - - self.assertTrue(delete_mock.called) - self.assertTrue(res) - delete_mock.assert_called_with('subscription/' + subscription_id) - - def test_delete_fail(self): - client = Client(self.api_url) - subscription_manager = SubscriptionManager(client) - - subscription_id = '1' - - with patch.object(client, 'delete') as delete_mock: - res = subscription_manager.delete(subscription_id) - - self.assertTrue(delete_mock.called) - self.assertFalse(res) - delete_mock.assert_called_with('subscription/' + subscription_id) - - def test_test(self): - client = Client(self.api_url) - subscription_manager = SubscriptionManager(client) - - subscription_id = '1' - - with patch.object(client, 'put', new=Mock(side_effect=InvalidJSONError(b''))) as put_mock: - res = subscription_manager.test(subscription_id) - - self.assertTrue(put_mock.called) - self.assertTrue(res) - put_mock.assert_called_with('subscription/' + subscription_id + '/test') - - def test_test_fail(self): - client = Client(self.api_url) - subscription_manager = SubscriptionManager(client) - - subscription_id = '1' - - with patch.object(client, 'put') as put_mock: - res = subscription_manager.test(subscription_id) - - self.assertTrue(put_mock.called) - self.assertFalse(res) - put_mock.assert_called_with('subscription/' + subscription_id + '/test') diff --git a/tests/models/test_system_tag.py b/tests/models/test_system_tag.py deleted file mode 100644 index f24e94c..0000000 --- a/tests/models/test_system_tag.py +++ /dev/null @@ -1,22 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch -from moira_client.client import Client -from moira_client.models.system_tag import SystemTagManager -from .test_model import ModelTest - - -class SystemTagTest(ModelTest): - - def test_fetch_all(self): - client = Client(self.api_url) - system_tag_manager = SystemTagManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - system_tag_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('system-tag') diff --git a/tests/models/test_tag.py b/tests/models/test_tag.py deleted file mode 100644 index 5effb8b..0000000 --- a/tests/models/test_tag.py +++ /dev/null @@ -1,193 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import InvalidJSONError -from moira_client.client import ResponseStructureError -from moira_client.models.tag import TagManager -from .test_model import ModelTest - - -class TagTest(ModelTest): - - def test_fetch_all(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - tag_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('tag') - - def test_fetch_all_bad_response(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - tag_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('tag') - - def test_delete(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - - tag = 'tag' - - with patch.object(client, 'delete') as delete_mock: - res = tag_manager.delete(tag) - - self.assertTrue(delete_mock.called) - self.assertTrue(res) - delete_mock.assert_called_with('tag/' + tag) - - def test_delete_fail(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - - tag = 'tag' - - with patch.object(client, 'delete', new=Mock(side_effect=InvalidJSONError(b''))) as delete_mock: - res = tag_manager.delete(tag) - - self.assertTrue(delete_mock.called) - self.assertFalse(res) - delete_mock.assert_called_with('tag/' + tag) - - def test_stats(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - tag_name = 'tag_name' - subscription_id = '3c01399e-1d40-46dd-934f-318e8255fd3e' - return_value = { - 'list': [ - { - 'name': tag_name, - 'subscriptions': [ - { - 'tags': ['test'], - 'contacts': ['3c01399e-1d40-46dd-934f-318e8255fd3e'], - 'enabled': True, - 'id': subscription_id, - 'days': [ - {'name': 'Mon', 'enabled': True}, - {'name': 'Tue', 'enabled': True}, - {'name': 'Wed', 'enabled': True}, - {'name': 'Thu', 'enabled': True}, - {'name': 'Fri', 'enabled': True}, - {'name': 'Sat', 'enabled': True}, - {'name': 'Sun', 'enabled': True} - ], - 'endOffset': 1439, - 'startOffset': 0, - 'tzOffset': 0 - } - ], - 'triggers': [] - } - ] - } - - with patch.object(client, 'get', return_value=return_value) as get_mock: - stats = tag_manager.stats() - - self.assertTrue(get_mock.called) - self.assertEqual(1, len(stats)) - self.assertEqual(tag_name, stats[0].name) - self.assertEqual(1, len(stats[0].subscriptions)) - self.assertEqual(subscription_id, stats[0].subscriptions[0].id) - - - def test_fetch_assigned_triggers(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - - tag_name = 'tag_name' - subscription_id = '3c01399e-1d40-46dd-934f-318e8255fd3e' - trigger_id = '123' - return_value = { - 'list': [ - { - 'name': tag_name, - 'subscriptions': [ - { - 'tags': ['test'], - 'contacts': ['1'], - 'enabled': True, - 'id': subscription_id, - 'days': [ - {'name': 'Mon', 'enabled': True}, - {'name': 'Tue', 'enabled': True}, - {'name': 'Wed', 'enabled': True}, - {'name': 'Thu', 'enabled': True}, - {'name': 'Fri', 'enabled': True}, - {'name': 'Sat', 'enabled': True}, - {'name': 'Sun', 'enabled': True} - ], - 'endOffset': 1439, - 'startOffset': 0, - 'tzOffset': 0 - } - ], - 'triggers': [trigger_id] - } - ] - } - - with patch.object(client, 'get', return_value=return_value) as get_mock: - triggerIds = tag_manager.fetch_assigned_triggers(tag_name) - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('tag/stats') - self.assertEqual(1, len(triggerIds)) - - def test_fetch_assigned_subscriptions(self): - client = Client(self.api_url) - tag_manager = TagManager(client) - - tag_name = 'tag_name' - subscription_id = '3c01399e-1d40-46dd-934f-318e8255fd3e' - trigger_id = '123' - return_value = { - 'list': [ - { - 'name': tag_name, - 'subscriptions': [ - { - 'tags': ['test'], - 'contacts': ['1'], - 'enabled': True, - 'id': subscription_id, - 'days': [ - {'name': 'Mon', 'enabled': True}, - {'name': 'Tue', 'enabled': True}, - {'name': 'Wed', 'enabled': True}, - {'name': 'Thu', 'enabled': True}, - {'name': 'Fri', 'enabled': True}, - {'name': 'Sat', 'enabled': True}, - {'name': 'Sun', 'enabled': True} - ], - 'endOffset': 1439, - 'startOffset': 0, - 'tzOffset': 0 - } - ], - 'triggers': [trigger_id] - } - ] - } - - with patch.object(client, 'get', return_value=return_value) as get_mock: - subscriptions = tag_manager.fetch_assigned_subscriptions(tag_name) - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('tag/stats') - self.assertEqual(1, len(subscriptions)) - self.assertEqual(subscription_id, subscriptions[0].id) diff --git a/tests/models/test_trigger.py b/tests/models/test_trigger.py deleted file mode 100644 index f146153..0000000 --- a/tests/models/test_trigger.py +++ /dev/null @@ -1,201 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.client import InvalidJSONError -from moira_client.client import ResponseStructureError -from moira_client.models.trigger import TriggerManager -from .test_model import ModelTest - - -class TriggerTest(ModelTest): - QUERY_PARAM_VALIDATE_FLAG = 'validate' - - def test_fetch_all(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - trigger_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('trigger') - - def test_fetch_all_bad_response(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - with patch.object(client, 'get', return_value={}) as get_mock: - with self.assertRaises(ResponseStructureError): - trigger_manager.fetch_all() - - self.assertTrue(get_mock.called) - get_mock.assert_called_with('trigger') - - def test_delete_fail(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - - with patch.object(client, 'delete') as delete_mock: - res = trigger_manager.delete(trigger_id) - - self.assertTrue(delete_mock.called) - self.assertFalse(res) - delete_mock.assert_called_with('trigger/' + trigger_id) - - def test_delete(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - - with patch.object(client, 'delete', new=Mock(side_effect=InvalidJSONError(b''))) as delete_mock: - res = trigger_manager.delete(trigger_id) - - self.assertTrue(delete_mock.called) - self.assertTrue(res) - delete_mock.assert_called_with('trigger/' + trigger_id) - - def test_setMaintenance(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - end_timestamp = 1612260000 - - with patch.object(client, 'put') as put_mock: - res = trigger_manager.set_maintenance(trigger_id, end_timestamp) - - self.assertTrue(put_mock.called) - self.assertTrue(res) - expected_request_data = { - 'trigger': end_timestamp, - } - put_mock.assert_called_with('trigger/' + trigger_id + '/setMaintenance', json=expected_request_data) - - def test_setMaintenance_with_metrics(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - end_timestamp = 1612260000 - metrics = { - 'metric': end_timestamp, - 'metric2': 1612260555, - } - - with patch.object(client, 'put') as put_mock: - res = trigger_manager.set_maintenance(trigger_id, end_timestamp, metrics) - - self.assertTrue(put_mock.called) - self.assertTrue(res) - expected_request_data = { - 'trigger': end_timestamp, - 'metrics': metrics, - } - put_mock.assert_called_with('trigger/' + trigger_id + '/setMaintenance', json=expected_request_data) - - def test_fetch_by_id(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - - state = { - 'state': 'OK', - 'trigger_id': trigger_id - } - - trigger = { - 'id': trigger_id, - 'name': 'trigger_name', - 'tags': ['tag'], - 'targets': ['pattern'], - 'warn_value': 0, - 'error_value': 1 - } - - with patch.object(client, 'get', side_effect=[state, trigger]) as get_mock: - trigger = trigger_manager.fetch_by_id(trigger_id) - - self.assertTrue(get_mock.called) - self.assertEqual(trigger_id, trigger.id) - - def test_save_new_trigger(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger = trigger_manager.create('Name', ['tag'], ['target']) - - with patch.object(client, 'get', return_value={'list': []}) as get_mock: - trigger_id = '1' - - with patch.object(client, 'put', return_value={'id': trigger_id}) as put_mock: - result = trigger.save() - - self.assertTrue(get_mock.called) - self.assertTrue(put_mock.called) - self.assertEqual(put_mock.call_args[0][0], 'trigger?{}'.format(self.QUERY_PARAM_VALIDATE_FLAG)) - self.assertEqual(result['id'], trigger_id) - - def test_save_existing_trigger(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - - state = { - 'state': 'OK', - 'trigger_id': trigger_id - } - trigger = { - 'name': 'Name', - 'tags': ['tag'], - 'targets': ['target'], - } - trigger_from_response = { - 'id': trigger_id, - **trigger - } - - with patch.object(client, 'get', side_effect=[{'list': [trigger_from_response]}, state, trigger_from_response]) as get_mock: - trigger_dto = trigger_manager.create(**trigger) - with patch.object(client, 'put', return_value={'id': trigger_id}) as put_mock: - result = trigger_dto.save() - - self.assertTrue(get_mock.called) - self.assertTrue(put_mock.called) - self.assertEqual(put_mock.call_args[0][0], 'trigger/{}?{}'.format(trigger_id, self.QUERY_PARAM_VALIDATE_FLAG)) - self.assertEqual(result['id'], trigger_id) - - def test_save_trigger_with_id(self): - client = Client(self.api_url) - trigger_manager = TriggerManager(client) - - trigger_id = '1' - state = { - 'state': 'OK', - 'trigger_id': trigger_id - } - trigger = { - 'id': trigger_id, - 'name': 'Name', - 'tags': ['tag'], - 'targets': ['target'], - } - - with patch.object(client, 'get', side_effect=[state, trigger]) as get_mock: - trigger_dto = trigger_manager.create(**trigger) - with patch.object(client, 'put', return_value={'id': trigger_id}) as put_mock: - result = trigger_dto.save() - - self.assertTrue(get_mock.called) - self.assertTrue(put_mock.called) - self.assertEqual(put_mock.call_args[0][0], 'trigger/{}?{}'.format(trigger_id, self.QUERY_PARAM_VALIDATE_FLAG)) - self.assertEqual(result['id'], trigger_id) diff --git a/tests/models/test_user.py b/tests/models/test_user.py deleted file mode 100644 index 7cc89a6..0000000 --- a/tests/models/test_user.py +++ /dev/null @@ -1,83 +0,0 @@ -try: - from unittest.mock import Mock - from unittest.mock import patch -except ImportError: - from mock import Mock - from mock import patch - -from moira_client.client import Client -from moira_client.models.user import UserManager - -from .test_model import ModelTest - - -class UserTest(ModelTest): - - def test_get_settings(self): - client = Client(self.api_url) - user_manager = UserManager(client) - - with patch.object(client, 'get', return_value={'login': 'aaa', 'contacts': [], 'subscriptions': []} - ) as get_mock: - res_settings = user_manager.get_user_settings() - - self.assertEqual(res_settings.login, 'aaa') - - self.assertTrue(get_mock.called) - - def test_response_example_from_docs(self): - client = Client(self.api_url) - user_manager = UserManager(client) - - response = { - "login": "john", - "contacts": [ - { - "id": "1dd38765-c5be-418d-81fa-7a5f879c2315", - "user": "", - "type": "mail", - "value": "devops@example.com" - } - ], - "subscriptions": [ - { - "contacts": [ - "acd2db98-1659-4a2f-b227-52d71f6e3ba1" - ], - "tags": [ - "server", - "cpu" - ], - "sched": { - "days": [ - { - "enabled": True, - "name": "Mon" - } - ], - "tzOffset": -60, - "startOffset": 0, - "endOffset": 1439 - }, - "plotting": { - "enabled": True, - "theme": "dark" - }, - "id": "292516ed-4924-4154-a62c-ebe312431fce", - "enabled": True, - "any_tags": False, - "ignore_warnings": False, - "ignore_recoverings": False, - "throttling": False, - "user": "" - } - ] - } - - with patch.object(client, 'get', return_value=response) as get_mock: - res_settings = user_manager.get_user_settings() - - self.assertEqual(res_settings.login, 'john') - self.assertEqual(res_settings.contacts[0].id, '1dd38765-c5be-418d-81fa-7a5f879c2315') - - self.assertTrue(get_mock.called) \ No newline at end of file diff --git a/tests/test_client.py b/tests/test_client.py deleted file mode 100644 index 3396a43..0000000 --- a/tests/test_client.py +++ /dev/null @@ -1,148 +0,0 @@ -import unittest -try: - from unittest.mock import patch -except ImportError: - from mock import patch - -import requests -from moira_client.client import Client -from moira_client.client import InvalidJSONError - -TEST_API_URL = 'http://test/api/url' -TEST_HEADERS = { - 'X-Webauth-User': 'login', - 'Content-Type': 'application/json', - 'User-Agent': 'Python Moira Client' - } - - -class FakeResponse: - - @property - def content(self): - return 'not json' - - def raise_for_status(self): - pass - - def json(self): - raise ValueError('invalid json') - - -class ClientTest(unittest.TestCase): - - def test_get(self): - - def get(url, params, **kwargs): - pass - - with patch.object(requests, 'get', side_effects=get) as mock_get: - test_path = 'test_path' - - client = Client(TEST_API_URL, TEST_HEADERS) - client.get(test_path) - - self.assertTrue(mock_get.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_get.assert_called_with(expected_url_call, headers=TEST_HEADERS, auth=None) - - def test_put(self): - - def put(url, data, **kwargs): - pass - - with patch.object(requests, 'put', side_effects=put) as mock_put: - test_path = 'test_path' - test_data = {'test': 'test'} - - client = Client(TEST_API_URL, TEST_HEADERS) - client.put(test_path, data=test_data) - - self.assertTrue(mock_put.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_put.assert_called_with(expected_url_call, data=test_data, headers=TEST_HEADERS, auth=None) - - def test_post(self): - def post(url, data, **kwargs): - pass - - with patch.object(requests, 'post', side_effects=post) as mock_post: - test_path = 'test_path' - test_data = {'test': 'test'} - - client = Client(TEST_API_URL, TEST_HEADERS) - client.post(test_path, data=test_data) - - self.assertTrue(mock_post.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_post.assert_called_with(expected_url_call, data=test_data, headers=TEST_HEADERS, auth=None) - - def test_delete(self): - - def delete(url, **kwargs): - pass - - with patch.object(requests, 'delete', side_effects=delete) as mock_delete: - test_path = 'test_path' - - client = Client(TEST_API_URL, TEST_HEADERS) - client.delete(test_path) - - self.assertTrue(mock_delete.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_delete.assert_called_with(expected_url_call, headers=TEST_HEADERS, auth=None) - - def test_get_invalid_response(self): - - def get(url, params, **kwargs): - return FakeResponse() - - response = FakeResponse() - - with patch.object(requests, 'get', side_effects=get, return_value=response) as mock_get: - test_path = 'test_path' - - client = Client(TEST_API_URL, TEST_HEADERS) - with self.assertRaises(InvalidJSONError): - client.get(test_path) - - self.assertTrue(mock_get.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_get.assert_called_with(expected_url_call, headers=TEST_HEADERS, auth=None) - - def test_put_invalid_response(self): - test_data = {'test': 'test'} - - def put(url, data, **kwargs): - return FakeResponse() - - response = FakeResponse() - - with patch.object(requests, 'put', side_effects=put, return_value=response) as mock_put: - test_path = 'test_path' - - client = Client(TEST_API_URL, TEST_HEADERS) - with self.assertRaises(InvalidJSONError): - client.put(test_path, data=test_data) - - self.assertTrue(mock_put.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_put.assert_called_with(expected_url_call, data=test_data, headers=TEST_HEADERS, auth=None) - - def test_delete_invalid_response(self): - - def delete(url, **kwargs): - return FakeResponse() - - response = FakeResponse() - - with patch.object(requests, 'delete', side_effects=delete, return_value=response) as mock_delete: - test_path = 'test_path' - - client = Client(TEST_API_URL, TEST_HEADERS) - with self.assertRaises(InvalidJSONError): - client.delete(test_path) - - self.assertTrue(mock_delete.called) - expected_url_call = TEST_API_URL + '/' + test_path - mock_delete.assert_called_with(expected_url_call, headers=TEST_HEADERS, auth=None)