From 833ec4243ce9117c5b801884cc9e8b09347fc5eb Mon Sep 17 00:00:00 2001 From: Marcus Young Date: Thu, 13 Feb 2020 20:07:15 -0600 Subject: [PATCH] Move influxdb to influx lib --- README.md | 7 ++--- poetry.lock | 52 ++++++++++++++++++++++++++++++++++++-- pyproject.toml | 1 + requirements.txt | 3 +++ setup.py | 1 + tests/test_common.py | 14 ++++++++++ tests/test_influxdb.py | 39 ++++++++++++++++++---------- tests/test_tilty.py | 2 +- tilty/common.py | 11 ++++++++ tilty/emitters/influxdb.py | 32 +++++++++++++---------- tilty/tilty.py | 9 ++++--- 11 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 tests/test_common.py create mode 100644 tilty/common.py diff --git a/README.md b/README.md index 8cb0323..3e5d4a1 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,11 @@ payload_template = {"color": "{{ color }}", "gravity": {{ gravity }}, "temp": {{ method = GET [influxdb] -url = http://grafana.corp.com +url = influxdb.corp.com +port = 80 database = tilty -gravity_payload_template = gravity,color={{ color }} value={{ gravity }} {{timestamp}} -temperature_payload_template = temperature,scale=fahrenheit,color={{ color }} value={{ temp }} {{timestamp}} +gravity_payload_template = {"measurement": "gravity", "tags": {"color": "{{ color }}"}, "fields": {"value": {{ gravity }}}} +temperature_payload_template = {"measurement": "temperature", "tags": {"color": "{{ color }}"}, "fields": {"value": {{ temp }}}} EOF $ tilty ``` diff --git a/poetry.lock b/poetry.lock index d6e5507..51f9044 100644 --- a/poetry.lock +++ b/poetry.lock @@ -136,6 +136,23 @@ zipp = ">=0.5" docs = ["sphinx", "rst.linker"] testing = ["packaging", "importlib-resources"] +[[package]] +category = "main" +description = "InfluxDB client" +name = "influxdb" +optional = false +python-versions = "*" +version = "5.2.3" + +[package.dependencies] +python-dateutil = ">=2.6.0" +pytz = "*" +requests = ">=2.17.0" +six = ">=1.10.0" + +[package.extras] +test = ["nose", "nose-cov", "mock", "requests-mock"] + [[package]] category = "dev" description = "A Python utility / library to sort Python imports." @@ -321,6 +338,25 @@ pytest = ">=3.6" [package.extras] testing = ["fields", "hunter", "process-tests (2.0.2)", "six", "virtualenv"] +[[package]] +category = "main" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "main" +description = "World timezone definitions, modern and historical" +name = "pytz" +optional = false +python-versions = "*" +version = "2019.3" + [[package]] category = "main" description = "Python HTTP for Humans." @@ -340,7 +376,7 @@ security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] -category = "dev" +category = "main" description = "Python 2 and 3 compatibility utilities" name = "six" optional = false @@ -448,7 +484,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pathlib2", "contextlib2", "unittest2"] [metadata] -content-hash = "b8de88fcd77dd71a746d3725e695889c62a2f93eec73bc63a142f7e0430ef44b" +content-hash = "aaaaaee62ecd567cb981bd6029700fd8189fc7da649f363cbd32793f686a74ad" python-versions = ">=3.6,<3.8" [metadata.files] @@ -533,6 +569,10 @@ importlib-metadata = [ {file = "importlib_metadata-1.3.0-py2.py3-none-any.whl", hash = "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f"}, {file = "importlib_metadata-1.3.0.tar.gz", hash = "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45"}, ] +influxdb = [ + {file = "influxdb-5.2.3-py2.py3-none-any.whl", hash = "sha256:270ec1ec9cf1927a38cf5ec808e76f364482977577eb8c335f6aed5fcdc4cb25"}, + {file = "influxdb-5.2.3.tar.gz", hash = "sha256:30276c7e04bf7659424c733b239ba2f0804d7a1f3c59ec5dd3f88c56176c8d36"}, +] isort = [ {file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"}, {file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"}, @@ -651,6 +691,14 @@ pytest-cov = [ {file = "pytest-cov-2.8.1.tar.gz", hash = "sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b"}, {file = "pytest_cov-2.8.1-py2.py3-none-any.whl", hash = "sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"}, ] +python-dateutil = [ + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, +] +pytz = [ + {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, + {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, +] requests = [ {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, diff --git a/pyproject.toml b/pyproject.toml index 5afd2d1..c35a39a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ click = "^7.0" pybluez = "^0.22.0" requests = "^2.22" jinja2 = "^2.11.1" +influxdb = "^5.2.3" [tool.poetry.dev-dependencies] flake8 = "^3.7" diff --git a/requirements.txt b/requirements.txt index 2cf8fc3..959afef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ filelock==3.0.12 flake8==3.7.9 idna==2.8 importlib-metadata==1.3.0 +influxdb==5.2.3 isort==4.3.21 Jinja2==2.11.1 lazy-object-proxy==1.4.3 @@ -25,6 +26,8 @@ pylint==2.4.4 pyparsing==2.4.5 pytest==5.3.2 pytest-cov==2.8.1 +python-dateutil==2.8.1 +pytz==2019.3 requests==2.22.0 six==1.13.0 toml==0.10.0 diff --git a/setup.py b/setup.py index a99645d..9475117 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ packages=find_packages(exclude=['tests*']), install_requires=[ 'Click', + 'influxdb', 'Jinja2', 'pybluez', 'requests', diff --git a/tests/test_common.py b/tests/test_common.py new file mode 100644 index 0000000..2221ef9 --- /dev/null +++ b/tests/test_common.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +from tilty import common + + +def test_safe_get_key_no_fallback(): + assert common.safe_get_key({}, 'foo') is None + + +def test_safe_get_key_fallback(): + assert common.safe_get_key({}, 'foo', 'wut') == 'wut' + + +def test_safe_get_key_valid(): + assert common.safe_get_key({'foo': 'asdf'}, 'foo', 'wut') == 'asdf' diff --git a/tests/test_influxdb.py b/tests/test_influxdb.py index 9309660..1c867bf 100644 --- a/tests/test_influxdb.py +++ b/tests/test_influxdb.py @@ -4,26 +4,37 @@ from tilty.emitters import influxdb -@mock.patch('tilty.emitters.influxdb.requests') +@mock.patch('tilty.emitters.influxdb.InfluxDBClient') def test_influxdb( - mock_requests, + mock_influx_client, ): config = { 'url': 'http://www.google.com', 'database': 'foo', - 'temperature_payload': 'temperature,color=Black value=85 1422568543702900257', # noqa - 'gravity_payload': 'gravity,color=Black value=1.045 1422568543702900257', # noqa + 'gravity_payload': '{"measurement": "gravity", "tags": {"color": "Black"}, "fields": {"value": 1.054}}', # noqa + 'temperature_payload': '{"measurement": "temperature", "tags": {"color": "Black", "scale": "fahrenheight"}, "fields": {"value": 32}}', # noqa } influxdb.InfluxDB(config=config).emit() - assert mock_requests.mock_calls == [ - mock.call.post( - data='temperature,color=Black value=85 1422568543702900257', - params=('db', 'mydb'), - url='http://www.google.com' + assert mock_influx_client.mock_calls == [ + mock.call( + 'http://www.google.com', + 80, + None, + None, + 'foo' ), - mock.call.post( - data='gravity,color=Black value=1.045 1422568543702900257', - params=('db', 'mydb'), - url='http://www.google.com' - ) + mock.call().write_points([ + { + 'measurement': 'temperature', + 'tags': {'color': 'Black', 'scale': 'fahrenheight'}, + 'fields': {'value': 32} + } + ]), + mock.call().write_points([ + { + 'measurement': 'gravity', + 'tags': {'color': 'Black'}, + 'fields': {'value': 1.054} + } + ]) ] diff --git a/tests/test_tilty.py b/tests/test_tilty.py index 537ebe5..15e0d7a 100644 --- a/tests/test_tilty.py +++ b/tests/test_tilty.py @@ -50,7 +50,7 @@ def test_scan_for_tilt_data_parse_influxdb( 'url': 'http://www.google.com', 'database': 'foo', 'temperature_payload': 'temperature,scale=fahrenheit,color=black value=32 155558888', # noqa - 'gravity_payload': 'temperature,scale=fahrenheit,color=black value=32 155558888' # noqa + 'gravity_payload': 'gravity,color=black value=1 155558888' } ), mock.call().emit() diff --git a/tilty/common.py b/tilty/common.py new file mode 100644 index 0000000..94810c1 --- /dev/null +++ b/tilty/common.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +""" Common methods """ + + +def safe_get_key(config, key, fallback=None): + """ Class to safely pull key from config or a fallback value """ + try: + return config[key] + except KeyError: + pass + return fallback diff --git a/tilty/emitters/influxdb.py b/tilty/emitters/influxdb.py index 3aa96a8..cdde1f8 100644 --- a/tilty/emitters/influxdb.py +++ b/tilty/emitters/influxdb.py @@ -1,6 +1,13 @@ # -*- coding: utf-8 -*- """ InfluxDB emitter """ -import requests +import json +import logging + +from influxdb import InfluxDBClient + +from tilty.common import safe_get_key + +LOGGER = logging.getLogger() class InfluxDB: # pylint: disable=too-few-public-methods @@ -11,23 +18,22 @@ def __init__(self, config): Args: config: (dict) represents the configuration for the emitter """ - self.url = config['url'] - self.database = config['database'] self.temperature_payload = config['temperature_payload'] self.gravity_payload = config['gravity_payload'] + self.client = InfluxDBClient( + config['url'], + safe_get_key(config, 'port', 80), + safe_get_key(config, 'user'), + safe_get_key(config, 'password'), + config['database'] + ) def emit(self, **kwargs): # pylint: disable=no-self-use,unused-argument """ Initializer Args: """ - requests.post( - url=self.url, - params=(('db', 'mydb')), - data=self.temperature_payload, - ) - requests.post( - url=self.url, - params=(('db', 'mydb')), - data=self.gravity_payload, - ) + LOGGER.info('[influxdb] posting temperature data') + self.client.write_points([json.loads(self.temperature_payload)]) + LOGGER.info('[influxdb] posting gravity data') + self.client.write_points([json.loads(self.gravity_payload)]) diff --git a/tilty/tilty.py b/tilty/tilty.py index 6caa127..c7dd67a 100644 --- a/tilty/tilty.py +++ b/tilty/tilty.py @@ -39,12 +39,13 @@ def emit(config, tilt_data): # # [influxdb] - # url = http://www.foo.com + # url = www.foo.com + # port = 80 # database = tilty - # gravity_payload_template = 'gravity,color={{ color }} value={{ gravity }} {{timestamp}} # noqa - # temperature_payload_template = 'temperature,scale=fahrenheit,.... + # gravity_payload_template = {"measurement": "gravity", "tags": {"color": "{{ color }}"}, "fields": {"value": {{ gravity }}}} # noqa # pylint: disable=line-too-long + # temperature_payload_template = {"measurement": "temperature", "tags": {"color": "{{ color }}"}, "fields": {"value": {{ temp }}}} # noqa # pylint: disable=line-too-long if config.has_section('influxdb'): - _gravity_template = Template(config['influxdb']['gravity_payload_template']) # noqa + _gravity_template = Template(config['influxdb']['gravity_payload_template']) # noqa _temperature_template = Template(config['influxdb']['temperature_payload_template']) # noqa _config = { 'url': config['influxdb']['url'],