Giter VIP home page Giter VIP logo

cachet-client's Introduction

pypi travis Documentation Status

cachet-client

A python 3.6+ API client for the open source status page system Cachet.

The goal of this package is to create a user friendly interface to the Cachet API.

  • Resources are returned as objects clearly separating read only properties from the ones we can change. The raw json response is always available in an attrs property
  • Active use of type hints throughout the entire codebase making code completion a breeze
  • Proper pagination under the hood. Method listing resources will return generators. You can configure the start page and page size that fits the situation. Each new page leads to a new http request.
  • Client is using a single session regardless of resource type making more complex work a lot faster (connection reuse)
  • A very extensive set of tests/unit tests.
  • Easy to extend and test
  • Documentation

Please don't hesitate opening an issue about anything related to this package.

Install

pip install cachet-client

Example

import cachetclient
from cachetclient.v1 import enums

client = cachetclient.Client(
    endpoint='https://status.test/api/v1',
    api_token='secrettoken',
)

Check if api is responding

if client.ping():
    print("Cachet is up and running!")

Create and delete a subscriber

sub = client.subscribers.create(email='[email protected]', verify=True)
sub.delete()

List all subscribers paginated (generator). Each new page is fetched from the server under the hood.

for sub in client.subscribers.list(page=1, per_page=100):
    print(sub.id, sub.email)

Create a component issue

issue = client.incidents.create(
    name="Something blew up!",
    message="We are looking into it",
    status=enums.INCIDENT_INVESTIGATING,
    # Optional for component issues
    component_id=mycomponent.id,
    component_status=enums.COMPONENT_STATUS_MAJOR_OUTAGE,
)

.. and most other features supported by the Cachet API

Local Development

Local setup:

python -m virtualenv .venv
. .venv/bin/activate
pip install -e .

Tests

This project has a fairly extensive test setup.

  • Unit tests are located in tests/ including a fake implementation of the Cachet API.
  • A simpler test script under extras/live_run.py that needs a running test instance of Cachet.

Running unit tests

pip install -r tests/requirements.txt
tox

# Optionally
tox -e pep8  # for pep8 run only
tox -e py36  # tests only


# Running tests with pytest also works, but this works poorly in combination with environment variables for the live test script (tox separates environments)
pytest tests/

Testing with real Cachet service

Do not run this script against a system in production. This is only for a test service. Cachet can easily be set up locally with docker: https://github.com/CachetHQ/Docker

Optionally we can run cachet from source: https://github.com/CachetHQ/Docker

A local setup is also located in the root or the repo (docker-compose.yaml).

You need to set the following environment variables.

CACHET_ENDPOINT
CACHET_API_TOKEN

Running tests:

python extras/live_run.py
...
=================================================
Number of tests   : 10
Successful        : 10
Failure           : 0
Percentage passed : 100.0%
=================================================

Building Docs

pip install -r docs/requirements.txt
python setup.py build_sphinx

Contributing

Do not hesitate opening issues or submit completed or partial pull requests. Contributors of all experience levels are welcome.


This project is sponsored by zetta.io

zetta.io

cachet-client's People

Contributors

ccampo133 avatar einarf avatar neutron-ah avatar zipy124 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cachet-client's Issues

Possible breaking features due to 2.3/2.4 differences

There seems to be some differences i 2.3 and 2.4 api for some features. These are minor, but causes unexpected 400 errors in some cases.

Started setting up 2.3 and 2.4 with docker so we can quickly test both versions. The mocked api should probably also mimic these differences or at least only accept what both cachet versions allow.

Cannot create component tags with list/set

Hi,

According to the documentation, component tag is a type of Set. However, it doesn't work as expected.

>>> cli.components.create(name="test1", status=1, tags=set(["tag1", "tag2"]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/v1/components.py", line 188, in create
    'tags': tags,
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/base.py", line 136, in _create
    response = self._http.post(path, data=data)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/httpclient.py", line 37, in post
    return self.request('POST', path, data=data)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/httpclient.py", line 53, in request
    timeout=self.timeout,
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/requests/sessions.py", line 516, in request
    prep = self.prepare_request(req)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/requests/sessions.py", line 459, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/requests/models.py", line 317, in prepare
    self.prepare_body(data, files, json)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/requests/models.py", line 467, in prepare_body
    body = complexjson.dumps(json)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/simplejson/__init__.py", line 395, in dumps
    return _default_encoder.encode(obj)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/simplejson/encoder.py", line 296, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/simplejson/encoder.py", line 378, in iterencode
    return _iterencode(o, 0)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/simplejson/encoder.py", line 273, in default
    o.__class__.__name__)
TypeError: Object of type set is not JSON serializable
>>> cli.components.create(name="test1", status=1, tags=["tag1", "tag2"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/v1/components.py", line 188, in create
    'tags': tags,
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/base.py", line 136, in _create
    response = self._http.post(path, data=data)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/httpclient.py", line 37, in post
    return self.request('POST', path, data=data)
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/cachetclient/httpclient.py", line 60, in request
    response.raise_for_status()
  File "/home/user/devel/.tox/py36/lib/python3.6/site-packages/requests/models.py", line 941, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://swarm.imagine-sw.com:8400/status/api/v1/components
>>>

Properly test package with 2.4-dev

There seems to be some compatibility issues between 2.3 and 2.4 related to what fields can be left empty in post requests. We need to get a local 2.4-dev instance up and running locally in docker.

Component tag is not case-sensitive

Hi,

I created a component with tags, it seems all tags are converted to lowercase. Can we support case-sensitive tag?

>>> cli.components.create(name="test1", status=1, tags="TAG1,Tag2,tag3")
{'order': 0, 'group_id': 0, 'description': '', 'link': '', 'enabled': True, 'meta': None, 'name': 'test1', 'status': 1, 'updated_at': '2020-07-19 14:31:57', 'created_at': '2020-07-19 14:31:57', 'id': 3574, 'status_name': 'Operational', 'tags': {'tag1': 'TAG1', 'tag2': 'Tag2', 'tag3': 'tag3'}}
>>> cli.components.get(3574)
{'id': 3574, 'name': 'test1', 'description': '', 'link': '', 'status': 1, 'order': 0, 'group_id': 0, 'created_at': '2020-07-19 14:31:57', 'updated_at': '2020-07-19 14:31:57', 'deleted_at': None, 'enabled': True, 'meta': None, 'status_name': 'Operational', 'tags': {'tag1': 'TAG1', 'tag2': 'Tag2', 'tag3': 'tag3'}}
>>> cli.components.get(3574).tags
{'tag3', 'tag2', 'tag1'}
>>> cli.components.get(3574).has_tag("TAG1")
False
>>> cli.components.get(3574).has_tag("tag1")
True
>>>

Thanks.

Inconsistent use of Manager._build_data_dict

This method is mostly used in update methods were None fields are weeded out. We should use this consistently as it's not easy to know if the server will accept None values as a new entry. There are currently no good reason for updating a resource field to None anyway.

Support "visible" property of component groups

Cachet allows you to set a "visible" flag (bit value, 1 or 0) for component groups, indicating whether the group is visible to the public or not. The functionality is equivalent to the existing "visible" functionality for incident. For component groups however, the feature currently appears to be undocumented, but it definitely is supported by the API.

I'm opening this issue with the hopes of the client allowing this visible flag to be set for component groups during creation and update, and retrieved during any gets.

Add simple doc tests

We should add a simple doc tests checking if all class members are documented etc.

Properly enforce mandatory and optional parameters

We want to use named parameters the vast majority of methods, but currently we don't properly check for mandatory parameters everywhere.

  • Use decorator for mandatory param check
  • Use keyword arguments in most places

Metrics / Points

We currently only have a skeleton manager and resource for these. Implement, test and document.

Add params argument to list methods

Right now we don't have support for extra parameters related to searching or sorting. Instead of users having to to go _post and _get methods in the base class we should expost this directly.

def list(self, ...., params: Dict = None);
    ....
subscribers = client.subsribers.list(..., params={"param1": "value1, "param2": "value2"}

This is a "low level" fix for #6, but there are room for both.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.