Compare commits

..

51 Commits

Author SHA1 Message Date
Drasko DRASKOVIC 9cacf5708b NOISSUE - Add info log-level for development (#427)
Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-10-24 17:13:29 +02:00
Aleksandar Novaković ad5c66fad2 NOISSUE - Refactor SDK and things service (#420)
* Refactor Mainflux go SDK

Add structures instead of string parameters. Add offset and limit
parameters to things and channels methods. Add better configuration
support.

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add new public errors with better error handling

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update SDK to use uint instread of string id

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update cli to use new SDK API

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Remove TLS termination from nginx configuration

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update SDK documentation and structures

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Refactor things service

Decouple HTTP layer from business logic. Remove ID number validation
check. Remove models from HTTP requests and responses.

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Reformat tests for things service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Increase test coverage for things service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-10-24 10:21:03 +01:00
Ivan Milošević d89e91143b Fix NATS install instruction (#423)
Signed-off-by: Ivan Milošević <iva@blokovi.com>
2018-10-21 22:47:53 +02:00
Sava R 96bcc4cff4 Update NATS docker image to newer version in docker-compose (#418)
Signed-off-by: Sava Radoš <srados@bitsfactory.com>
2018-10-15 11:05:14 +02:00
Drasko DRASKOVIC a8eb7ae039 MF-354 - Add Go SDK (#357)
* MF-354 - Add Go SDK

This PR adds Go SDK. It also refactors `cli` to use new SDK.

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Use http consts. Add doc.

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Insline const

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Add initial SDK tests

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix SDK to return values (not HTTP rsp)

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix CLI and test

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* fix typos, add header

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix doc

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix doc, add comment

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Inline error checks

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix typos

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Inline errs

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix typo

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Change fnc parameter name

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Rename getters to Go standard

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Use struct and interface

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Simplify sdk struct

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix README

Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-10-14 16:44:21 +02:00
Ivan Milošević 6eade2c1d0 NOISSUE - Add pull request template (#414)
* Add pull request template

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix formatting in docs

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix link for contributing guidelines

Signed-off-by: Ivan Milošević <iva@blokovi.com>
2018-10-04 10:04:58 +02:00
Dušan Borovčanin 148c1aca0a MF-404 - InfluxDB batch size and timeout zero values (#411)
* Add zero value check for batch size and timeout

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update InfluxDB writer tests

Test creation of InfluxDB writer with invalid (zero) batch size and timeout.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Fix config load

Loading batch size and timeout from env variables were missing in loadConfigs method.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-10-01 17:36:53 +02:00
Aleksandar Novaković 70517bd907 Update mqtt to mqtt communication to support full protocol (#408)
Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-09-30 19:00:21 +02:00
Ivan Milošević d5f0d7d225 MF-384 - Add test for Redis cache (#405)
* Add test

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add test

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add test

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add test

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add test

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-384 - Add test for Redis cache

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add copyright headers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix copyright header

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix test setup

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* handling errors and put test cases in maps instead of slices

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add test case if thing already exists

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix TestThingSave to use require instead of assert

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Add test case for removing non-existing thing from cache

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Use table of test cases for Remove and test Connect for every case

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Use table of test cases for Save

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Test cases in slice instead of map for testing Remove

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Make test-cases independent, use asserts instead of requires

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Use slice and map where appropriate

Signed-off-by: Ivan Milošević <iva@blokovi.com>
2018-09-30 02:03:00 +02:00
Michael Finley b20a846071 Fixing level_test.go (#406)
Signed-off-by: Michael Finley <Michael.Finley@target.com>
2018-09-26 20:22:26 +02:00
Michael Finley 6600d26ef1 MF-379 - Log Level Option (#402)
* Adding an option to select log level

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* making error default log level

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* removing go-kit/levels and expanding levels wrapper

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* refactoring test cases and using log.fatal

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* logger.new no longer accpets enum and now accepts string for level

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* level_test.go refactor to compare error

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* Updating the ws README

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* Adding log level for mqtt Adapter

Signed-off-by: Michael Finley <Michael.Finley@target.com>
2018-09-26 18:58:51 +02:00
Dušan Borovčanin 3de34062db NOISSUE - Influxdb batch add (#394)
* Add batch of streams

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Add env variables for batch point setup

Fix InfluxDB reader tests.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update Compose and Kubernetes config

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update env variables

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update docs

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Remove unused const

Refactor code and docs.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Handle NewBatchPoints error

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Reduce wait time in  batch save test

Fix typos.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update tests

Use single test with multiple cases to test single point save as well as
a batch of points.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Add an explanation for not resetting ticker

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-09-23 01:53:03 +02:00
Ivan Milošević 8e9d7b4fdb MF-389 - Add documentation for Writers and Readers (#398)
* MF-389 - Add documentation for Writers and Readers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-389 - Update readme files for readers and writers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-389 - Update mongodb-reader docker-compose.yml

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix links formatting in docs

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Updated reader and writer docs

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Fix formatting

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Update Grafana access

Signed-off-by: Ivan Milošević <iva@blokovi.com>
2018-09-20 15:32:50 +02:00
Dušan Borovčanin 5757380a63 NOISSUE - Dev dockers (#392)
* Add development Docker images build

Add Dockerfile.dev and target in the Makefile to provide much faster image
building for `development purposes`.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Build single service in dev mode

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update docs

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Fix Makefile

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Fix dev-guide

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-09-19 20:20:12 +02:00
Jovan Kostovski c944205080 dev guide spelling and formatting fixes (#393)
Signed-off-by: Jovan Kostovski <chombium@gmail.com>
2018-09-17 21:32:13 +02:00
Drasko DRASKOVIC d825174ccb NOISSUE - Separate docker-push into function (#386)
Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-09-13 15:40:40 +02:00
Aleksandar Novaković 6408b8a9d3 Fix NATS subscription bug in writers (#391)
Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-09-13 10:06:34 +02:00
Drasko DRASKOVIC 845b69a4ac Bump version to 0.5.1 (#385)
Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-09-04 23:32:04 +02:00
Aleksandar Novaković 0c77d84176 MF-382 - Improve performance by adding Redis cache for message auth (#383)
* Add redis caching for thing and channel connections

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix authorization caching flow

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update things documentation

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-09-04 22:19:43 +02:00
Sava R 970c1c86ca Fix topic to channel parsing (#381)
Signed-off-by: Sava Radoš <srados@bitsfactory.com>
2018-09-04 14:07:51 +02:00
Aleksandar Novaković 902630fb14 Fix type and name switching in connected things (#376)
Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-08-29 14:28:56 +02:00
Drasko DRASKOVIC 4ca443038d Update MAINTAINERS 2018-08-28 22:42:47 +02:00
Drasko DRASKOVIC 47c56cbac9 Update MAINTAINERS (#373)
Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-08-28 22:41:25 +02:00
Sava 0fd0e6a13f Initial user, device, channel provisioning script used to speed up testing on a fresh Mainflux installation. Accepts email, password, device name, channel name as arguments. (#369)
Signed-off-by: Sava Radoš <sava.rados@mainflux.com>
2018-08-27 20:51:17 +02:00
Jovan Kostovski 8a86593dc3 NOISSUE - Makefile test target, CREATE TABLE and dev guide enhancements (#359)
* Fixes #337

Signed-off-by: Jovan Kostovski <chombium@gmail.com>

* added create table if not exists

Signed-off-by: Jovan Kostovski <chombium@gmail.com>

* added test target in sync with Semaphore CI

Signed-off-by: Jovan Kostovski <chombium@gmail.com>

* added warning about the possible data loss

Signed-off-by: Jovan Kostovski <chombium@gmail.com>
2018-08-27 12:17:41 +02:00
Ivan Milošević effade00aa MF-325 - Add SPDX license and copyright headers (#362)
* MF-325 - Add SPDX license and copyright headers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-325 - Add SPDX license and copyright headers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-325 - Add SPDX license and copyright headers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-325 - Add SPDX license and copyright headers

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* MF-325 - Change mainflux version from 0.4.0 to 0.5.0

Signed-off-by: Ivan Milošević <iva@blokovi.com>
2018-08-26 13:15:48 +02:00
Sava 8edf6907bc Change project retrieval procedure from git clone to go get (#366)
Signed-off-by: Sava Radoš <sava.rados@mainflux.com>
2018-08-25 14:39:30 +02:00
Dušan Borovčanin 507bd2ee84 MF-311 - Implement basic InfluxDB reader (#365)
* Add InfluxDB reader

Summary:
- Add basic reader features
- Update Makefile

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Raise test coverage

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update README.md and docker composition

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Fix docker-compose.yml

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Remove exposed ports

Ports are already exposed by mapping, so no need to explicity expose them.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-08-25 12:48:03 +02:00
Sava 86f0d8e0d6 MF-363 - Add compiled .proto files (#364)
* Add compiled .proto files

Signed-off-by: Sava Radoš <sava.rados@mainflux.com>

* Remove proto as prerequisite for build services target

Signed-off-by: Sava Radoš <sava.rados@mainflux.com>
2018-08-24 15:33:40 +02:00
Aleksandar Novaković 6461761985 Add logging middleware to normalizer service (#360)
Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-08-21 10:15:50 +02:00
Paul RATHGEB ec03d877f0 Declare docker_mainflux-base-net as external and add it to all services (#361)
Signed-off-by: Paul RATHGEB <paul.rathgeb@skynet.be>
2018-08-20 22:00:45 +02:00
Ivan Milošević 4e137a3214 MF-343 - Thing Model: rename the Payload Field to Metadata (#358)
* Rename Payload field to Metadata

Rename Payload field of Thing to Metadata.

Signed-off-by: Ivan Milošević <iva@blokovi.com>

* Revert JSON payload rename in docs

Signed-off-by: Ivan Milošević <iva@blokovi.com>
2018-08-17 16:20:35 +02:00
Drasko DRASKOVIC af281da430 NOISSUE - Add insecure param to cli (#356)
Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-08-17 04:58:09 +02:00
Drasko DRASKOVIC 1683d17830 Add some make command info (#353)
Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-08-16 21:51:49 +02:00
Drasko DRASKOVIC 7e83b2d612 NOISSUE - Add system run script (#350)
* NOISSUE - Add system run script

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Add MQTT

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Add MQTT module install to Makefile. Fix warnings.

Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-08-16 19:52:43 +02:00
Drasko DRASKOVIC 312d30fd69 NOISSUE - Add Development Guide doc (#351)
* NOISSUE - Add Development Guide doc

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Add MQTT info

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix typos

Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-08-16 19:44:11 +02:00
Drasko DRASKOVIC 2c988c19b0 NOISSUE - Rename bashflux to cli and fix cert path (#349)
* NOISSUE - rename bashflux to cli and fix cert path

Signed-off-by: drasko <drasko.draskovic@gmail.com>

* Fix pkg name

Signed-off-by: drasko <drasko.draskovic@gmail.com>
2018-08-16 13:41:27 +02:00
Paul RATHGEB 455fedf075 Fix the influxdb hostname. Fix #346 (#348)
Signed-off-by: Paul RATHGEB <paul.rathgeb@skynet.be>
2018-08-16 04:06:25 +02:00
Aleksandar Novaković 58cdf2cddc MF-312 - Implement basic MongoDB reader (#344)
* Add mongodb reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add tests for mongodb reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add documentation for mongodb reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix test function name

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update comment in docker-compose for mongodb-reader service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-08-08 13:38:34 +02:00
Aleksandar Novaković 6d48446c16 MF-313 - Implement basic Cassandra reader (#331)
* Fix logger message in http service

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Inline query and error handling in cassandra writer

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix comments and import statement in writer interface

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add reader common interface and shared HTTP API

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add Cassandra reader implementation

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add tests for cassandra reader

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add swagger doc and readme for readers

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update make file

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add docker-compose configuration for cassandra reader

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add readme file to cassandra reader

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-08-06 17:06:55 +02:00
Ivan Milošević 29d146636a Change favicon on Dashflux (#341)
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
2018-08-01 23:11:40 +02:00
Marco Ferragina f3f14e803d Improved getting started docs (#339)
* Improved getting started docs

Better explaination of how to send messages to a channel using websockets.
Added a basic nodejs example

Signed-off-by: Marco Ferragina <marco.ferragina@gmail.com>

* Added leading slash

Signed-off-by: Marco Ferragina <marco.ferragina@gmail.com>

* added some comments to example code in docs

Signed-off-by: Marco Ferragina <marco.ferragina@gmail.com>
2018-07-25 11:12:31 +02:00
Manuel Imperiale b090aa3e02 MF-216 - Integrate Bashflux into monorepo (#308)
* MF-216 - Integrate Bashflux into monorepo

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename clients -> things

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix FormatResLog

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Initialize Channels commands in channels.go

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Mv bashflux to cmd/ repertory

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Mv API commands files to bashflux repertory

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Initialize Users commands in users.go

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Initialize Version command in version.go

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Initialize Messages command in messages.go

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm bashflux .gitignore and mv commands to root .gitignore

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename API commands vars

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix certificates paths

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm test logs

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Remove get channels cmd without arguments

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix connect and disconnect commands

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix messages endpoint

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm useless comments and dead code

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Use contentTypeSenml var

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename cmdCobra -> cmd

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm else statments

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename SetServerAddr function vars

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename conf parameters

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename main with proper name

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix Update channel comment

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix README

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm .DS_Store from .gitignore

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename hhtp_client.go -> http.go

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm DeleteAllChannels and DeleteAllThings funcs

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix BF users usage log

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Improve bashflux logs

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Share types in funcs

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Typo fix

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix BF version cmd

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Set certs paths via env variables

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix package

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm not direct dependencies from Gopkg.toml

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix README

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add def prefix to certificates paths

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* User thiings service for version cmd

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rename GetReqResp -> SendRequest

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix version help

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Return directly the pointer in NewVersionCmd

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Define endpoints names as consts and be consistent with naming

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Use Spintf for string concatenation

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* typo fix

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix README

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix version endpoint

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix serverAddr

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>
2018-07-11 13:53:37 +02:00
Dušan Borovčanin 0b954847fd MF-334 - Correct normalizer k8 port (#335)
* Fix k8s normalizer deployment port

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Remove targert port

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-07-02 14:53:16 +02:00
Dušan Borovčanin 44f5a7241f NOISSUE - Expose SenML subject from Normalizer service (#330)
* Expose SenML subject from Normalizer service

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Export shared NATS subjects

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-06-19 00:37:04 +02:00
Dušan Borovčanin b694f08ea2 Inteface implementation files match interface name (#329)
Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-06-18 10:51:30 +02:00
Dušan Borovčanin f1537528f9 NOISSUE - Raise test coverage (#324)
* Update WS tests

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use require in all writer tests

Refactor code.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Ignore Mainflux generated pb.go files

Ignore *.pb.go files generated by Mainflux, but don't ignore vendored generated code.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Return an exported ErrNotFound instead of the unexported one

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update mocks to match the actual behaviour

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Update mocks error message

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Add auth service unavailable error test

Since this error is caused by gRPC server returning codes.Internal,
this behaviour is simulated using specific token. When that token is
passed as an auth header, the mock gRPC client returns aforementioned error.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Use require package for postgres tests

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Remove redundant error checks in tests

Refactor tests.

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Rename error flag token

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-06-16 02:30:46 +02:00
Aleksandar Novaković 344eed7976 NOISSUE - Add exported metrics visualization for grafana (#326)
* Add exported metrics visualization in grafana

Add graphics for request count and request latency for users, things,
http adapter and ws adapter services.

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Rename grafana export file

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Move metrics configuration to metrics dir

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-06-15 17:08:49 +02:00
Aleksandar Novaković d8357b500c MF-328 - Add message persistence support for MQTT (#327)
* Add redis for message persistence

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add redis to docker composition

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix mqtt publish command in documentation

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update documentation with new environment variables

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-06-15 07:27:23 -07:00
Dušan Borovčanin 993398b8ab NOISSUE - Update Kubernetes setup (#322)
* Add InfluxDB writer services setup to k8s

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>

* Remove commented NginX config

Signed-off-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
2018-06-15 13:04:52 +02:00
Aleksandar Novaković 426f59d392 MF-235 - Add support for storing messages in Cassandra (#321)
* Add Cassandra writer implementation

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add cassandra service with version and metrics endpoints

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add test for cassandra writer

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Exclude api.go files from code coverage

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add readme file for cassandra writer

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add docker compose configuration for cassandra writer

Add README file. Add docker compose configuration.

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add gocql as project dependency

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix init script for cassandra in docker-compose

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add testifies require subpackage

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
2018-06-08 14:25:55 +02:00
665 changed files with 74912 additions and 3463 deletions
+15
View File
@@ -0,0 +1,15 @@
Pull request title should be `MF-XXX - description` or `NOISSUE - description` where XXX is ID of issue that this PR relate to.
Please review the [CONTRIBUTING.md](./CONTRIBUTING.md) file for detailed contributing guidelines.
### What does this do?
### Which issue(s) does this PR fix/relate to?
Put here `Resolves #XXX` to auto-close the issue that your PR fixes (if such)
### List any changes that modify/break current functionality
### Have you included tests for your changes?
### Did you document any new/modified functionality?
### Notes
+1 -1
View File
@@ -1,4 +1,4 @@
build
*.pb.go
site/
Generated
+125 -7
View File
@@ -34,6 +34,12 @@
packages = ["quantile"]
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
[[projects]]
branch = "master"
name = "github.com/buger/jsonparser"
packages = ["."]
revision = "2cac668e8456b4284edb0715e17e2af02d3ec993"
[[projects]]
name = "github.com/cenkalti/backoff"
packages = ["."]
@@ -76,6 +82,12 @@
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
version = "v0.3.3"
[[projects]]
name = "github.com/fatih/color"
packages = ["."]
revision = "5b77d2a35fb0ede96d138fc9a99f5c9b6aef11b4"
version = "v1.7.0"
[[projects]]
name = "github.com/go-kit/kit"
packages = [
@@ -96,6 +108,21 @@
revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5"
version = "v0.3.0"
[[projects]]
name = "github.com/go-redis/redis"
packages = [
".",
"internal",
"internal/consistenthash",
"internal/hashtag",
"internal/pool",
"internal/proto",
"internal/singleflight",
"internal/util"
]
revision = "f3bba01df2026fc865f7782948845db9cf44cf23"
version = "v6.14.1"
[[projects]]
name = "github.com/go-stack/stack"
packages = ["."]
@@ -108,6 +135,17 @@
revision = "fd0aebc74e908868b09ac140fb5a53cb363884c1"
version = "1.2"
[[projects]]
branch = "master"
name = "github.com/gocql/gocql"
packages = [
".",
"internal/lru",
"internal/murmur",
"internal/streams"
]
revision = "651d6b1f343c6e168e45d119dcfe8f71e5bafb32"
[[projects]]
name = "github.com/gogo/protobuf"
packages = ["proto"]
@@ -126,12 +164,35 @@
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/golang/snappy"
packages = ["."]
revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a"
[[projects]]
name = "github.com/gorilla/websocket"
packages = ["."]
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[[projects]]
name = "github.com/hailocab/go-hostpool"
packages = ["."]
revision = "e80d13ce29ede4452c43dea11e79b9bc8a15b478"
[[projects]]
branch = "master"
name = "github.com/hokaccha/go-prettyjson"
packages = ["."]
revision = "e6b9231a2b1cc5798b336fdbf99c16cd8ad1e0c9"
[[projects]]
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
name = "github.com/influxdata/influxdb"
packages = [
@@ -157,6 +218,18 @@
]
revision = "d34b9ff171c21ad295489235aec8b6626023cd04"
[[projects]]
name = "github.com/mattn/go-colorable"
packages = ["."]
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
version = "v0.0.9"
[[projects]]
name = "github.com/mattn/go-isatty"
packages = ["."]
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
@@ -171,28 +244,52 @@
"bson/decimal",
"bson/elements",
"bson/objectid",
"core/addr",
"bson/parser",
"bson/parser/ast",
"core/address",
"core/auth",
"core/auth/internal/gssapi",
"core/command",
"core/compressor",
"core/connection",
"core/connstring",
"core/description",
"core/dispatch",
"core/options",
"core/event",
"core/option",
"core/readconcern",
"core/readpref",
"core/result",
"core/session",
"core/tag",
"core/topology",
"core/uuid",
"core/version",
"core/wiremessage",
"core/writeconcern",
"internal",
"mongo"
"mongo",
"mongo/aggregateopt",
"mongo/changestreamopt",
"mongo/clientopt",
"mongo/collectionopt",
"mongo/countopt",
"mongo/dbopt",
"mongo/deleteopt",
"mongo/distinctopt",
"mongo/dropcollopt",
"mongo/findopt",
"mongo/indexopt",
"mongo/insertopt",
"mongo/listcollectionopt",
"mongo/listdbopt",
"mongo/mongoopt",
"mongo/replaceopt",
"mongo/runcmdopt",
"mongo/updateopt"
]
revision = "29a4d7d5b648e5b0b60e03e3bd71c11703f0c203"
version = "v0.0.5"
revision = "8df56f107cdd485351eb2523992c3364114b4b2e"
version = "v0.0.10"
[[projects]]
name = "github.com/nats-io/go-nats"
@@ -340,9 +437,24 @@
revision = "e9556a45379ef1da12e54847edb2fb3d7d566f36"
version = "0.3.0"
[[projects]]
name = "github.com/spf13/cobra"
packages = ["."]
revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
version = "v0.0.3"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1"
[[projects]]
name = "github.com/stretchr/testify"
packages = ["assert"]
packages = [
"assert",
"require"
]
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1"
@@ -456,6 +568,12 @@
revision = "c87af80f3cc5036b55b83d77171e156791085e2e"
version = "v1.7.1"
[[projects]]
name = "gopkg.in/inf.v0"
packages = ["."]
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
version = "v0.9.1"
[[projects]]
name = "gopkg.in/ory-am/dockertest.v3"
packages = ["."]
@@ -465,6 +583,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "6010ae4c4f91c30b3a63789cc280466ce56d50f387c1e4d11c49df1302f083da"
inputs-digest = "1f18adf44738d8f5c48b2f0576ab90c2f2c549f13a846b8f3c95aabaebe8efb4"
solver-name = "gps-cdcl"
solver-version = 1
+16
View File
@@ -10,6 +10,10 @@
name = "github.com/dgrijalva/jwt-go"
version = "3.2.0"
[[constraint]]
name = "github.com/fatih/color"
version = "1.7.0"
[[constraint]]
name = "github.com/go-kit/kit"
version = "0.6.0"
@@ -22,6 +26,10 @@
name = "github.com/golang/protobuf"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/hokaccha/go-prettyjson"
[[constraint]]
branch = "master"
name = "github.com/lib/pq"
@@ -42,6 +50,10 @@
name = "github.com/sony/gobreaker"
version = "0.3.0"
[[constraint]]
name = "github.com/spf13/cobra"
version = "0.0.3"
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"
@@ -70,6 +82,10 @@
name = "github.com/mongodb/mongo-go-driver"
version = "0.0.5"
[[constraint]]
branch = "master"
name = "github.com/gocql/gocql"
[prune]
go-tests = true
unused-packages = true
+14 -13
View File
@@ -7,7 +7,7 @@
[[drasko]]
Name = "Drasko DRASKOVIC"
Email = "drasko.draskovic@mainflux.com"
Email = "drasko@mainflux.com"
GitHub = "drasko"
# However, this role serves only in dead-lock events, or in a special and very rare cases
@@ -24,22 +24,23 @@
[maintainers]
[[aleksandar]]
Name = "Aleksandar NOVAKOVIC"
Email = "aleksandar@mainflux.com"
GitHub = "anovakovic01"
[[dusan]]
Name = "Dusan BOROVCANIN"
Email = "dusan@mainflux.com"
GitHub = "dusanb94"
[[manuel]]
Name = "Manuel IMPERIALE"
Email = "manuel.imperiale@gmail.com"
Email = "manuel@mainflux.com"
GitHub = "manuIO"
[[janko]]
Name = "Janko ISIDOROVIC"
Email = "janko.isidorovic@mainflux.com"
GitHub = "janko-isidorovic"
[[nikola]]
Name = "Nikola MARCETIC"
Email = "nikola.marcetic@mainflux.com"
Email = "nikola@mainflux.com"
GitHub = "nmarcetic"
[[dejan]]
Name = "Dejan MIJIC"
Email = "dejan.mijic@mainflux.com"
GitHub = "mijicd"
+37 -12
View File
@@ -1,6 +1,7 @@
BUILD_DIR = build
SERVICES = users things http normalizer ws influxdb mongodb
SERVICES = users things http normalizer ws influxdb-writer influxdb-reader mongodb-writer mongodb-reader cassandra-writer cassandra-reader cli
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
CGO_ENABLED ?= 0
GOOS ?= linux
@@ -9,23 +10,31 @@ define compile_service
endef
define make_docker
docker build --build-arg SVC_NAME=$(subst docker_,,$(1)) --tag=mainflux/$(subst docker_,,$(1)) -f docker/Dockerfile .
docker build --no-cache --build-arg SVC_NAME=$(subst docker_,,$(1)) --tag=mainflux/$(subst docker_,,$(1)) -f docker/Dockerfile .
endef
all: $(SERVICES)
define make_docker_dev
docker build --build-arg SVC_NAME=$(subst docker_dev_,,$(1)) --tag=mainflux/$(subst docker_dev_,,$(1)) -f docker/Dockerfile.dev ./build
endef
.PHONY: all $(SERVICES) dockers latest release
all: $(SERVICES) mqtt
.PHONY: all $(SERVICES) dockers dockers_dev latest release mqtt
clean:
rm -rf ${BUILD_DIR}
rm -rf mqtt/node_modules
install:
cp ${BUILD_DIR}/* $(GOBIN)
test:
GOCACHE=off go test -v -race -tags test $(shell go list ./... | grep -v 'vendor\|cmd')
proto:
protoc --go_out=plugins=grpc:. *.proto
$(SERVICES): proto
$(SERVICES):
$(call compile_service,$(@))
$(DOCKERS):
@@ -35,12 +44,24 @@ dockers: $(DOCKERS)
docker build --tag=mainflux/dashflux -f dashflux/docker/Dockerfile dashflux
docker build --tag=mainflux/mqtt -f mqtt/Dockerfile .
latest: dockers
$(DOCKERS_DEV):
$(call make_docker_dev,$(@))
dockers_dev: $(DOCKERS_DEV)
mqtt:
cd mqtt && npm install
define docker_push
for svc in $(SERVICES); do \
docker push mainflux/$$svc; \
docker push mainflux/$$svc:$(1); \
done
docker push mainflux/dashflux
docker push mainflux/mqtt
docker push mainflux/dashflux:$(1)
docker push mainflux/mqtt:$(1)
endef
latest: dockers
$(call docker_push,latest)
release:
$(eval version = $(shell git describe --abbrev=0 --tags))
@@ -48,9 +69,13 @@ release:
$(MAKE) dockers
for svc in $(SERVICES); do \
docker tag mainflux/$$svc mainflux/$$svc:$(version); \
docker push mainflux/$$svc:$(version); \
done
docker tag mainflux/dashflux mainflux/dashflux:$(version)
docker push mainflux/dashflux:$(version)
docker tag mainflux/mqtt mainflux/mqtt:$(version)
docker push mainflux/mqtt:$(version)
$(call docker_push,$(version))
rundev:
cd scripts && ./run.sh
run:
docker-compose -f docker/docker-compose.yml up
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package mainflux
// Response contains HTTP response specific methods.
+87
View File
@@ -0,0 +1,87 @@
# Mainflux CLI
## Build
From the project root:
```
make cli
```
## Usage
### Service
#### Get the service verison
```
mainflux-cli version
```
### User management
#### Create User
```
mainflux-cli users create john.doe@email.com password
```
#### Login User
```
mainflux-cli users token john.doe@email.com password
```
### System Provisioning
#### Provision Device
```
mainflux-cli things create '{"type":"device", "name":"nyDevice"}' <user_auth_token>
```
#### Provision Application
```
mainflux-cli things create '{"type":"app", "name":"nyDevice"}' <user_auth_token>
```
#### Retrieve All Things
```
mainflux-cli things get all --offset=1 --limit=5 <user_auth_token>
```
#### Retrieve Thing By ID
```
mainflux-cli things get <thing_id> --offset=1 --limit=5 <user_auth_token>
```
#### Remove Thing
```
mainflux-cli things delete <thing_id> <user_auth_token>
```
#### Provision Channel
```
mainflux-cli channels create '{"name":"nyChannel"}' <user_auth_token>
```
#### Retrieve All Channels
```
mainflux-cli channels get all --offset=1 --limit=5 <user_auth_token>
```
#### Retrievie Channel By ID
```
mainflux-cli channels get <channel_id> --offset=1 --limit=5 <user_auth_token>
```
#### Remove Channel
```
mainflux-cli channels delete <channel_id> <user_auth_token>
```
### Access control
#### Connect Thing to a Channel
```
mainflux-cli things connect <thing_id> <channel_id> <user_auth_token>
```
#### Disconnect Things from a Channel
```
mainflux-cli things disconnect <thing_id> <channel_id> <user_auth_token>
```
### Messaging
#### Send a message over HTTP
```
mainflux-cli msg send <channel_id> '[{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]' <thing_auth_token>
```
+133
View File
@@ -0,0 +1,133 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import (
"encoding/json"
mfxsdk "github.com/mainflux/mainflux/sdk/go"
"github.com/spf13/cobra"
)
var cmdChannels = []cobra.Command{
cobra.Command{
Use: "create",
Short: "create <JSON_channel> <user_auth_token>",
Long: `Creates new channel and generates it's UUID`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
var channel mfxsdk.Channel
if err := json.Unmarshal([]byte(args[0]), &channel); err != nil {
logError(err)
return
}
id, err := sdk.CreateChannel(channel, args[1])
if err != nil {
logError(err)
return
}
flush(id)
},
},
cobra.Command{
Use: "get",
Short: "get all/<channel_id> <user_auth_token>",
Long: `Gets list of all channels or gets channel by id`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
if args[0] == "all" {
l, err := sdk.Channels(args[1], uint64(Offset), uint64(Limit))
if err != nil {
logError(err)
return
}
flush(l)
return
}
c, err := sdk.Channel(args[0], args[1])
if err != nil {
logError(err)
return
}
flush(c)
},
},
cobra.Command{
Use: "update",
Short: "update <JSON_string> <user_auth_token>",
Long: `Updates channel record`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 3 {
logUsage(cmd.Short)
return
}
var channel mfxsdk.Channel
if err := json.Unmarshal([]byte(args[0]), &channel); err != nil {
logError(err)
return
}
if err := sdk.UpdateChannel(channel, args[1]); err != nil {
logError(err)
return
}
logOK()
},
},
cobra.Command{
Use: "delete",
Short: "delete <channel_id> <user_auth_token>",
Long: `Delete channel by ID`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
if err := sdk.DeleteChannel(args[0], args[1]); err != nil {
logError(err)
return
}
logOK()
},
},
}
// NewChannelsCmd returns channels command.
func NewChannelsCmd() *cobra.Command {
cmd := cobra.Command{
Use: "channels",
Short: "Manipulation with channels",
Long: `Manipulation with channels: create, delete or update channels`,
Run: func(cmd *cobra.Command, args []string) {
logUsage(cmd.Short)
},
}
for i := range cmdChannels {
cmd.AddCommand(&cmdChannels[i])
}
return &cmd
}
+48
View File
@@ -0,0 +1,48 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import "github.com/spf13/cobra"
const contentTypeSenml = "application/senml+json"
var cmdMessages = []cobra.Command{
cobra.Command{
Use: "send",
Short: "send <channel_id> <JSON_string> <thing_token>",
Long: `Sends message on the channel`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 3 {
logUsage(cmd.Short)
return
}
if err := sdk.SendMessage(args[0], args[1], args[2]); err != nil {
logError(err)
return
}
logOK()
},
},
}
// NewMessagesCmd returns messages command.
func NewMessagesCmd() *cobra.Command {
cmd := cobra.Command{
Use: "msg",
Short: "Send or retrieve messages",
Long: `Send or retrieve messages: control message flow on the channel`,
}
for i := range cmdMessages {
cmd.AddCommand(&cmdMessages[i])
}
return &cmd
}
+18
View File
@@ -0,0 +1,18 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import mfxsdk "github.com/mainflux/mainflux/sdk/go"
// Keep SDK handle in global var
var sdk mfxsdk.SDK
// SetSDK sets mainflux SDK instance.
func SetSDK(s mfxsdk.SDK) {
sdk = s
}
+170
View File
@@ -0,0 +1,170 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import (
"encoding/json"
mfxsdk "github.com/mainflux/mainflux/sdk/go"
"github.com/spf13/cobra"
)
const thingsEP = "things"
var cmdThings = []cobra.Command{
cobra.Command{
Use: "create",
Short: "create <JSON_thing> <user_auth_token>",
Long: `Create new thing, generate his UUID and store it`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
var thing mfxsdk.Thing
if err := json.Unmarshal([]byte(args[0]), &thing); err != nil {
logError(err)
return
}
id, err := sdk.CreateThing(thing, args[1])
if err != nil {
logError(err)
return
}
flush(id)
},
},
cobra.Command{
Use: "get",
Short: "get all/<thing_id> <user_auth_token>",
Long: `Get all things or thing by id`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
if args[0] == "all" {
l, err := sdk.Things(args[1], uint64(Offset), uint64(Limit))
if err != nil {
logError(err)
return
}
flush(l)
return
}
t, err := sdk.Thing(args[0], args[1])
if err != nil {
logError(err)
return
}
flush(t)
},
},
cobra.Command{
Use: "delete",
Short: "delete <thing_id> <user_auth_token>",
Long: `Removes thing from database`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
if err := sdk.DeleteThing(args[0], args[1]); err != nil {
logError(err)
return
}
logOK()
},
},
cobra.Command{
Use: "update",
Short: "update <JSON_string> <user_auth_token>",
Long: `Update thing record`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 3 {
logUsage(cmd.Short)
return
}
var thing mfxsdk.Thing
if err := json.Unmarshal([]byte(args[0]), &thing); err != nil {
logError(err)
return
}
if err := sdk.UpdateThing(thing, args[1]); err != nil {
logError(err)
return
}
logOK()
},
},
cobra.Command{
Use: "connect",
Short: "connect <thing_id> <channel_id> <user_auth_token>",
Long: `Connect thing to the channel`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 3 {
logUsage(cmd.Short)
return
}
if err := sdk.ConnectThing(args[0], args[1], args[2]); err != nil {
logError(err)
return
}
logOK()
},
},
cobra.Command{
Use: "disconnect",
Short: "disconnect <thing_id> <channel_id> <user_auth_token>",
Long: `Disconnect thing to the channel`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 3 {
logUsage(cmd.Short)
return
}
if err := sdk.DisconnectThing(args[0], args[1], args[2]); err != nil {
logError(err)
return
}
logOK()
},
},
}
// NewThingsCmd returns things command.
func NewThingsCmd() *cobra.Command {
cmd := cobra.Command{
Use: "things",
Short: "things <options>",
Long: `Things handling: create, delete or update things`,
Run: func(cmd *cobra.Command, args []string) {
logUsage(cmd.Short)
},
}
for i := range cmdThings {
cmd.AddCommand(&cmdThings[i])
}
return &cmd
}
+79
View File
@@ -0,0 +1,79 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import (
mfxsdk "github.com/mainflux/mainflux/sdk/go"
"github.com/spf13/cobra"
)
var cmdUsers = []cobra.Command{
cobra.Command{
Use: "create",
Short: "create <username> <password>",
Long: `Creates new user`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
user := mfxsdk.User{
Email: args[0],
Password: args[1],
}
if err := sdk.CreateUser(user); err != nil {
logError(err)
return
}
logOK()
},
},
cobra.Command{
Use: "token",
Short: "token <username> <password>",
Long: `Creates new token`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 2 {
logUsage(cmd.Short)
return
}
user := mfxsdk.User{
Email: args[0],
Password: args[1],
}
token, err := sdk.CreateToken(user)
if err != nil {
logError(err)
return
}
flush(token)
},
},
}
// NewUsersCmd returns users command.
func NewUsersCmd() *cobra.Command {
cmd := cobra.Command{
Use: "users",
Short: "users create/token <email> <password>",
Long: `Manages users in the system (create account or token)`,
Run: func(cmd *cobra.Command, args []string) {
logUsage(cmd.Short)
},
}
for i := range cmdUsers {
cmd.AddCommand(&cmdUsers[i])
}
return &cmd
}
+38
View File
@@ -0,0 +1,38 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import (
"fmt"
"github.com/davecgh/go-spew/spew"
"github.com/fatih/color"
)
var (
// Limit query parameter
Limit uint = 10
// Offset query parameter
Offset uint
)
func flush(i interface{}) {
fmt.Printf("%s", color.BlueString(spew.Sdump(i)))
}
func logUsage(u string) {
fmt.Printf(color.YellowString("Usage: %s\n"), u)
}
func logError(err error) {
fmt.Printf("%s\n", color.RedString(err.Error()))
}
func logOK() {
fmt.Printf("%s\n", color.GreenString("OK"))
}
+28
View File
@@ -0,0 +1,28 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package cli
import "github.com/spf13/cobra"
// NewVersionCmd returns version command.
func NewVersionCmd() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Get version of Mainflux Things Service",
Long: `Mainflux server health check`,
Run: func(cmd *cobra.Command, args []string) {
v, err := sdk.Version()
if err != nil {
logError(err)
return
}
flush(v)
},
}
}
+142
View File
@@ -0,0 +1,142 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/gocql/gocql"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/readers"
"github.com/mainflux/mainflux/readers/api"
"github.com/mainflux/mainflux/readers/cassandra"
thingsapi "github.com/mainflux/mainflux/things/api/grpc"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
)
const (
sep = ","
defLogLevel = "error"
defPort = "8180"
defCluster = "127.0.0.1"
defKeyspace = "mainflux"
defThingsURL = "localhost:8181"
envLogLevel = "MF_CASSANDRA_READER_LOG_LEVEL"
envPort = "MF_CASSANDRA_READER_PORT"
envCluster = "MF_CASSANDRA_READER_DB_CLUSTER"
envKeyspace = "MF_CASSANDRA_READER_DB_KEYSPACE"
envThingsURL = "MF_THINGS_URL"
)
type config struct {
logLevel string
port string
cluster string
keyspace string
thingsURL string
}
func main() {
cfg := loadConfig()
logger, err := logger.New(os.Stdout, cfg.logLevel)
if err != nil {
log.Fatalf(err.Error())
}
session := connectToCassandra(cfg.cluster, cfg.keyspace, logger)
defer session.Close()
conn := connectToThings(cfg.thingsURL, logger)
defer conn.Close()
tc := thingsapi.NewClient(conn)
repo := newService(session, logger)
errs := make(chan error, 2)
go startHTTPServer(repo, tc, cfg.port, errs, logger)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
err = <-errs
logger.Error(fmt.Sprintf("Cassandra reader service terminated: %s", err))
}
func loadConfig() config {
return config{
logLevel: mainflux.Env(envLogLevel, defLogLevel),
port: mainflux.Env(envPort, defPort),
cluster: mainflux.Env(envCluster, defCluster),
keyspace: mainflux.Env(envKeyspace, defKeyspace),
thingsURL: mainflux.Env(envThingsURL, defThingsURL),
}
}
func connectToCassandra(cluster, keyspace string, logger logger.Logger) *gocql.Session {
session, err := cassandra.Connect(strings.Split(cluster, sep), keyspace)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to Cassandra cluster: %s", err))
os.Exit(1)
}
return session
}
func connectToThings(url string, logger logger.Logger) *grpc.ClientConn {
conn, err := grpc.Dial(url, grpc.WithInsecure())
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to things service: %s", err))
os.Exit(1)
}
return conn
}
func newService(session *gocql.Session, logger logger.Logger) readers.MessageRepository {
repo := cassandra.New(session)
repo = api.LoggingMiddleware(repo, logger)
repo = api.MetricsMiddleware(
repo,
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "cassandra",
Subsystem: "message_reader",
Name: "request_count",
Help: "Number of requests received.",
}, []string{"method"}),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "cassandra",
Subsystem: "message_reader",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, []string{"method"}),
)
return repo
}
func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, port string, errs chan error, logger logger.Logger) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Cassandra reader service started, exposed port %s", port))
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, "cassandra-reader"))
}
+143
View File
@@ -0,0 +1,143 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/gocql/gocql"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/writers"
"github.com/mainflux/mainflux/writers/cassandra"
"github.com/nats-io/go-nats"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
queue = "cassandra-writer"
sep = ","
defNatsURL = nats.DefaultURL
defLogLevel = "error"
defPort = "8180"
defCluster = "127.0.0.1"
defKeyspace = "mainflux"
envNatsURL = "MF_NATS_URL"
envLogLevel = "MF_CASSANDRA_WRITER_LOG_LEVEL"
envPort = "MF_CASSANDRA_WRITER_PORT"
envCluster = "MF_CASSANDRA_WRITER_DB_CLUSTER"
envKeyspace = "MF_CASSANDRA_WRITER_DB_KEYSPACE"
)
type config struct {
natsURL string
logLevel string
port string
cluster string
keyspace string
}
func main() {
cfg := loadConfig()
logger, err := logger.New(os.Stdout, cfg.logLevel)
if err != nil {
log.Fatalf(err.Error())
}
nc := connectToNATS(cfg.natsURL, logger)
defer nc.Close()
session := connectToCassandra(cfg.cluster, cfg.keyspace, logger)
defer session.Close()
repo := newService(session, logger)
if err := writers.Start(nc, repo, queue, logger); err != nil {
logger.Error(fmt.Sprintf("Failed to create Cassandra writer: %s", err))
}
errs := make(chan error, 2)
go startHTTPServer(cfg.port, errs, logger)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
err = <-errs
logger.Error(fmt.Sprintf("Cassandra writer service terminated: %s", err))
}
func loadConfig() config {
return config{
natsURL: mainflux.Env(envNatsURL, defNatsURL),
logLevel: mainflux.Env(envLogLevel, defLogLevel),
port: mainflux.Env(envPort, defPort),
cluster: mainflux.Env(envCluster, defCluster),
keyspace: mainflux.Env(envKeyspace, defKeyspace),
}
}
func connectToNATS(url string, logger logger.Logger) *nats.Conn {
nc, err := nats.Connect(url)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to NATS: %s", err))
os.Exit(1)
}
return nc
}
func connectToCassandra(cluster, keyspace string, logger logger.Logger) *gocql.Session {
session, err := cassandra.Connect(strings.Split(cluster, sep), keyspace)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to Cassandra cluster: %s", err))
os.Exit(1)
}
return session
}
func newService(session *gocql.Session, logger logger.Logger) writers.MessageRepository {
repo := cassandra.New(session)
repo = writers.LoggingMiddleware(repo, logger)
repo = writers.MetricsMiddleware(
repo,
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "cassandra",
Subsystem: "message_writer",
Name: "request_count",
Help: "Number of requests received.",
}, []string{"method"}),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "cassandra",
Subsystem: "message_writer",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, []string{"method"}),
)
return repo
}
func startHTTPServer(port string, errs chan error, logger logger.Logger) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Cassandra writer service started, exposed port %s", port))
errs <- http.ListenAndServe(p, cassandra.MakeHandler())
}
+122
View File
@@ -0,0 +1,122 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"log"
"github.com/mainflux/mainflux/cli"
"github.com/mainflux/mainflux/sdk/go"
"github.com/spf13/cobra"
)
func main() {
msgContentType := string(sdk.CTJSONSenML)
sdkConf := sdk.Config{
BaseURL: "http://localhost",
UsersPrefix: "",
ThingsPrefix: "",
HTTPAdapterPrefix: "http",
MsgContentType: sdk.ContentType(msgContentType),
TLSVerification: false,
}
// Root
var rootCmd = &cobra.Command{
Use: "mainflux-cli",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
sdkConf.MsgContentType = sdk.ContentType(msgContentType)
s := sdk.NewSDK(sdkConf)
cli.SetSDK(s)
},
}
// API commands
versionCmd := cli.NewVersionCmd()
usersCmd := cli.NewUsersCmd()
thingsCmd := cli.NewThingsCmd()
channelsCmd := cli.NewChannelsCmd()
messagesCmd := cli.NewMessagesCmd()
// Root Commands
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(usersCmd)
rootCmd.AddCommand(thingsCmd)
rootCmd.AddCommand(channelsCmd)
rootCmd.AddCommand(messagesCmd)
// Root Flags
rootCmd.PersistentFlags().StringVarP(
&sdkConf.BaseURL,
"mainflux-url",
"m",
sdkConf.BaseURL,
"Mainflux host URL",
)
rootCmd.PersistentFlags().StringVarP(
&sdkConf.UsersPrefix,
"users-prefix",
"u",
sdkConf.UsersPrefix,
"Mainflux users service prefix",
)
rootCmd.PersistentFlags().StringVarP(
&sdkConf.ThingsPrefix,
"things-prefix",
"t",
sdkConf.ThingsPrefix,
"Mainflux things service prefix",
)
rootCmd.PersistentFlags().StringVarP(
&sdkConf.HTTPAdapterPrefix,
"http-prefix",
"a",
sdkConf.HTTPAdapterPrefix,
"Mainflux http adapter prefix",
)
rootCmd.PersistentFlags().StringVarP(
&msgContentType,
"content-type",
"c",
msgContentType,
"Mainflux message content type",
)
rootCmd.PersistentFlags().BoolVarP(
&sdkConf.TLSVerification,
"insecure",
"i",
sdkConf.TLSVerification,
"Do not check for TLS cert",
)
// Client and Channels Flags
rootCmd.PersistentFlags().UintVarP(
&cli.Limit,
"limit",
"l",
100,
"limit query parameter",
)
rootCmd.PersistentFlags().UintVarP(
&cli.Offset,
"offset",
"o",
0,
"offset query parameter",
)
if err := rootCmd.Execute(); err != nil {
log.Fatal(err)
}
}
+29 -8
View File
@@ -1,7 +1,15 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
@@ -12,7 +20,7 @@ import (
adapter "github.com/mainflux/mainflux/http"
"github.com/mainflux/mainflux/http/api"
"github.com/mainflux/mainflux/http/nats"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/logger"
thingsapi "github.com/mainflux/mainflux/things/api/grpc"
broker "github.com/nats-io/go-nats"
stdprometheus "github.com/prometheus/client_golang/prometheus"
@@ -21,9 +29,11 @@ import (
const (
defPort string = "8180"
defLogLevel string = "error"
defNatsURL string = broker.DefaultURL
defThingsURL string = "localhost:8181"
envPort string = "MF_HTTP_ADAPTER_PORT"
envLogLevel string = "MF_HTTP_ADAPTER_LOG_LEVEL"
envNatsURL string = "MF_NATS_URL"
envThingsURL string = "MF_THINGS_URL"
)
@@ -31,17 +41,18 @@ const (
type config struct {
ThingsURL string
NatsURL string
LogLevel string
Port string
}
func main() {
cfg := config{
ThingsURL: mainflux.Env(envThingsURL, defThingsURL),
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
Port: mainflux.Env(envPort, defPort),
}
logger := log.New(os.Stdout)
cfg := loadConfig()
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
nc, err := broker.Connect(cfg.NatsURL)
if err != nil {
@@ -52,7 +63,7 @@ func main() {
conn, err := grpc.Dial(cfg.ThingsURL, grpc.WithInsecure())
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to users service: %s", err))
logger.Error(fmt.Sprintf("Failed to connect to things service: %s", err))
os.Exit(1)
}
defer conn.Close()
@@ -95,3 +106,13 @@ func main() {
err = <-errs
logger.Error(fmt.Sprintf("HTTP adapter terminated: %s", err))
}
func loadConfig() config {
return config{
ThingsURL: mainflux.Env(envThingsURL, defThingsURL),
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
Port: mainflux.Env(envPort, defPort),
}
}
+148
View File
@@ -0,0 +1,148 @@
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
influxdata "github.com/influxdata/influxdb/client/v2"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/readers"
"github.com/mainflux/mainflux/readers/api"
"github.com/mainflux/mainflux/readers/influxdb"
thingsapi "github.com/mainflux/mainflux/things/api/grpc"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
)
const (
defThingsURL = "localhost:8181"
defLogLevel = "error"
defPort = "8180"
defDBName = "mainflux"
defDBHost = "localhost"
defDBPort = "8086"
defDBUser = "mainflux"
defDBPass = "mainflux"
envThingsURL = "MF_THINGS_URL"
envLogLevel = "MF_INFLUX_READER_LOG_LEVEL"
envPort = "MF_INFLUX_READER_PORT"
envDBName = "MF_INFLUX_READER_DB_NAME"
envDBHost = "MF_INFLUX_READER_DB_HOST"
envDBPort = "MF_INFLUX_READER_DB_PORT"
envDBUser = "MF_INFLUX_READER_DB_USER"
envDBPass = "MF_INFLUX_READER_DB_PASS"
)
type config struct {
ThingsURL string
LogLevel string
Port string
DBName string
DBHost string
DBPort string
DBUser string
DBPass string
}
func main() {
cfg, clientCfg := loadConfigs()
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
conn := connectToThings(cfg.ThingsURL, logger)
defer conn.Close()
tc := thingsapi.NewClient(conn)
client, err := influxdata.NewHTTPClient(clientCfg)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create InfluxDB client: %s", err))
os.Exit(1)
}
defer client.Close()
repo, err := influxdb.New(client, cfg.DBName)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create InfluxDB writer: %s", err))
os.Exit(1)
}
errs := make(chan error, 2)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
go startHTTPServer(repo, tc, cfg.Port, logger, errs)
err = <-errs
logger.Error(fmt.Sprintf("InfluxDB writer service terminated: %s", err))
}
func loadConfigs() (config, influxdata.HTTPConfig) {
cfg := config{
ThingsURL: mainflux.Env(envThingsURL, defThingsURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
Port: mainflux.Env(envPort, defPort),
DBName: mainflux.Env(envDBName, defDBName),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass),
}
clientCfg := influxdata.HTTPConfig{
Addr: fmt.Sprintf("http://%s:%s", cfg.DBHost, cfg.DBPort),
Username: cfg.DBUser,
Password: cfg.DBPass,
}
return cfg, clientCfg
}
func connectToThings(url string, logger logger.Logger) *grpc.ClientConn {
conn, err := grpc.Dial(url, grpc.WithInsecure())
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to things service: %s", err))
os.Exit(1)
}
return conn
}
func newService(client influxdata.Client, logger logger.Logger) readers.MessageRepository {
repo, _ := influxdb.New(client, "mainflux")
repo = api.LoggingMiddleware(repo, logger)
repo = api.MetricsMiddleware(
repo,
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "influxdb",
Subsystem: "message_reader",
Name: "request_count",
Help: "Number of requests received.",
}, []string{"method"}),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "influxdb",
Subsystem: "message_reader",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, []string{"method"}),
)
return repo
}
func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("InfluxDB reader service started, exposed port %s", port))
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, "influxdb-reader"))
}
+174
View File
@@ -0,0 +1,174 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"time"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
influxdata "github.com/influxdata/influxdb/client/v2"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/writers"
"github.com/mainflux/mainflux/writers/influxdb"
"github.com/nats-io/go-nats"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
queue = "influxdb-writer"
defNatsURL = nats.DefaultURL
defLogLevel = "error"
defPort = "8180"
defBatchSize = "5000"
defBatchTimeout = "5"
defDBName = "mainflux"
defDBHost = "localhost"
defDBPort = "8086"
defDBUser = "mainflux"
defDBPass = "mainflux"
envNatsURL = "MF_NATS_URL"
envLogLevel = "MF_INFLUX_WRITER_LOG_LEVEL"
envPort = "MF_INFLUX_WRITER_PORT"
envBatchSize = "MF_INFLUX_WRITER_BATCH_SIZE"
envBatchTimeout = "MF_INFLUX_WRITER_BATCH_TIMEOUT"
envDBName = "MF_INFLUX_WRITER_DB_NAME"
envDBHost = "MF_INFLUX_WRITER_DB_HOST"
envDBPort = "MF_INFLUX_WRITER_DB_PORT"
envDBUser = "MF_INFLUX_WRITER_DB_USER"
envDBPass = "MF_INFLUX_WRITER_DB_PASS"
)
type config struct {
NatsURL string
LogLevel string
Port string
BatchSize string
BatchTimeout string
DBName string
DBHost string
DBPort string
DBUser string
DBPass string
}
func main() {
cfg, clientCfg := loadConfigs()
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
nc, err := nats.Connect(cfg.NatsURL)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to NATS: %s", err))
os.Exit(1)
}
defer nc.Close()
client, err := influxdata.NewHTTPClient(clientCfg)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create InfluxDB client: %s", err))
os.Exit(1)
}
defer client.Close()
batchTimeout, err := strconv.Atoi(cfg.BatchTimeout)
if err != nil {
logger.Error(fmt.Sprintf("Invalid value for batch timeout: %s", err))
os.Exit(1)
}
batchSize, err := strconv.Atoi(cfg.BatchSize)
if err != nil {
logger.Error(fmt.Sprintf("Invalid value of batch size: %s", err))
os.Exit(1)
}
timeout := time.Duration(batchTimeout) * time.Second
repo, err := influxdb.New(client, cfg.DBName, batchSize, timeout)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create InfluxDB writer: %s", err))
os.Exit(1)
}
counter, latency := makeMetrics()
repo = writers.LoggingMiddleware(repo, logger)
repo = writers.MetricsMiddleware(repo, counter, latency)
if err := writers.Start(nc, repo, queue, logger); err != nil {
logger.Error(fmt.Sprintf("Failed to start message writer: %s", err))
os.Exit(1)
}
errs := make(chan error, 2)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
go startHTTPService(cfg.Port, logger, errs)
err = <-errs
logger.Error(fmt.Sprintf("InfluxDB writer service terminated: %s", err))
}
func loadConfigs() (config, influxdata.HTTPConfig) {
cfg := config{
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
Port: mainflux.Env(envPort, defPort),
BatchSize: mainflux.Env(envBatchSize, defBatchSize),
BatchTimeout: mainflux.Env(envBatchTimeout, defBatchTimeout),
DBName: mainflux.Env(envDBName, defDBName),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass),
}
clientCfg := influxdata.HTTPConfig{
Addr: fmt.Sprintf("http://%s:%s", cfg.DBHost, cfg.DBPort),
Username: cfg.DBUser,
Password: cfg.DBPass,
}
return cfg, clientCfg
}
func makeMetrics() (*kitprometheus.Counter, *kitprometheus.Summary) {
counter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "influxdb",
Subsystem: "message_writer",
Name: "request_count",
Help: "Number of database inserts.",
}, []string{"method"})
latency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "influxdb",
Subsystem: "message_writer",
Name: "request_latency_microseconds",
Help: "Total duration of inserts in microseconds.",
}, []string{"method"})
return counter, latency
}
func startHTTPService(port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("InfluxDB writer service started, exposed port %s", p))
errs <- http.ListenAndServe(p, influxdb.MakeHandler())
}
-139
View File
@@ -1,139 +0,0 @@
package main
import (
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
influxdata "github.com/influxdata/influxdb/client/v2"
"github.com/mainflux/mainflux"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/writers"
"github.com/mainflux/mainflux/writers/influxdb"
nats "github.com/nats-io/go-nats"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
name = "influxdb-writer"
senML = "out.senml"
prefix = "http://"
defNatsURL = nats.DefaultURL
defPort = "8180"
defPointName = "messages"
defDBName = "mainflux"
defDBHost = "localhost"
defDBPort = "8086"
defDBUser = "mainflux"
defDBPass = "mainflux"
envNatsURL = "MF_NATS_URL"
envPort = "MF_INFLUX_WRITER_PORT"
envDBName = "MF_INFLUX_WRITER_DB_NAME"
envDBHost = "MF_INFLUX_WRITER_DB_HOST"
envDBPort = "MF_INFLUX_WRITER_DB_PORT"
envDBUser = "MF_INFLUX_WRITER_DB_USER"
envDBPass = "MF_INFLUX_WRITER_DB_PASS"
)
type config struct {
NatsURL string
Port string
DBName string
DBHost string
DBPort string
DBUser string
DBPass string
}
func main() {
cfg, clientCfg := loadConfigs()
logger := log.New(os.Stdout)
nc, err := nats.Connect(cfg.NatsURL)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to NATS: %s", err))
os.Exit(1)
}
defer nc.Close()
client, err := influxdata.NewHTTPClient(clientCfg)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create InfluxDB client: %s", err))
os.Exit(1)
}
defer client.Close()
repo, err := influxdb.New(client, cfg.DBName)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create InfluxDB writer: %s", err))
os.Exit(1)
}
counter, latency := makeMetrics()
repo = writers.LoggingMiddleware(repo, logger)
repo = writers.MetricsMiddleware(repo, counter, latency)
if err := writers.Start(name, nc, logger, repo); err != nil {
logger.Error(fmt.Sprintf("Failed to start message writer: %s", err))
os.Exit(1)
}
errs := make(chan error, 2)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
go startHTTPService(cfg.Port, logger, errs)
err = <-errs
logger.Error(fmt.Sprintf("InfluxDB writer service terminated: %s", err))
}
func loadConfigs() (config, influxdata.HTTPConfig) {
cfg := config{
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
Port: mainflux.Env(envPort, defPort),
DBName: mainflux.Env(envDBName, defDBName),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass),
}
clientCfg := influxdata.HTTPConfig{
Addr: fmt.Sprintf("%s%s:%s", prefix, cfg.DBHost, cfg.DBPort),
Username: cfg.DBUser,
Password: cfg.DBPass,
}
return cfg, clientCfg
}
func makeMetrics() (*kitprometheus.Counter, *kitprometheus.Summary) {
counter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "influxdb",
Subsystem: "message_writer",
Name: "request_count",
Help: "Number of database inserts.",
}, []string{"method"})
latency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "influxdb",
Subsystem: "message_writer",
Name: "request_latency_microseconds",
Help: "Total duration of inserts in microseconds.",
}, []string{"method"})
return counter, latency
}
func startHTTPService(port string, logger log.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Influxdb writer service started, exposed port %s", p))
errs <- http.ListenAndServe(p, influxdb.MakeHandler())
}
+141
View File
@@ -0,0 +1,141 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/readers"
"github.com/mainflux/mainflux/readers/api"
"github.com/mainflux/mainflux/readers/mongodb"
thingsapi "github.com/mainflux/mainflux/things/api/grpc"
"github.com/mongodb/mongo-go-driver/mongo"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
)
const (
defThingsURL = "localhost:8181"
defLogLevel = "error"
defPort = "8180"
defDBName = "mainflux"
defDBHost = "localhost"
defDBPort = "27017"
envThingsURL = "MF_THINGS_URL"
envLogLevel = "MF_MONGO_READER_LOG_LEVEL"
envPort = "MF_MONGO_READER_PORT"
envDBName = "MF_MONGO_READER_DB_NAME"
envDBHost = "MF_MONGO_READER_DB_HOST"
envDBPort = "MF_MONGO_READER_DB_PORT"
)
type config struct {
thingsURL string
logLevel string
port string
dbName string
dbHost string
dbPort string
}
func main() {
cfg := loadConfigs()
logger, err := logger.New(os.Stdout, cfg.logLevel)
if err != nil {
log.Fatalf(err.Error())
}
conn := connectToThings(cfg.thingsURL, logger)
defer conn.Close()
tc := thingsapi.NewClient(conn)
db := connectToMongoDB(cfg.dbHost, cfg.dbPort, cfg.dbName, logger)
repo := newService(db, logger)
errs := make(chan error, 2)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
go startHTTPServer(repo, tc, cfg.port, logger, errs)
err = <-errs
logger.Error(fmt.Sprintf("MongoDB reader service terminated: %s", err))
}
func loadConfigs() config {
return config{
thingsURL: mainflux.Env(envThingsURL, defThingsURL),
logLevel: mainflux.Env(envLogLevel, defLogLevel),
port: mainflux.Env(envPort, defPort),
dbName: mainflux.Env(envDBName, defDBName),
dbHost: mainflux.Env(envDBHost, defDBHost),
dbPort: mainflux.Env(envDBPort, defDBPort),
}
}
func connectToMongoDB(host, port, name string, logger logger.Logger) *mongo.Database {
client, err := mongo.Connect(context.Background(), fmt.Sprintf("mongodb://%s:%s", host, port), nil)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to database: %s", err))
os.Exit(1)
}
return client.Database(name)
}
func connectToThings(url string, logger logger.Logger) *grpc.ClientConn {
conn, err := grpc.Dial(url, grpc.WithInsecure())
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to things service: %s", err))
os.Exit(1)
}
return conn
}
func newService(db *mongo.Database, logger logger.Logger) readers.MessageRepository {
repo := mongodb.New(db)
repo = api.LoggingMiddleware(repo, logger)
repo = api.MetricsMiddleware(
repo,
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "mongodb",
Subsystem: "message_reader",
Name: "request_count",
Help: "Number of requests received.",
}, []string{"method"}),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "mongodb",
Subsystem: "message_reader",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, []string{"method"}),
)
return repo
}
func startHTTPServer(repo readers.MessageRepository, tc mainflux.ThingsServiceClient, port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Mongo reader service started, exposed port %s", port))
errs <- http.ListenAndServe(p, api.MakeHandler(repo, tc, "cassandra-reader"))
}
@@ -1,8 +1,16 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
@@ -10,41 +18,47 @@ import (
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/mainflux/mainflux"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/writers"
mongodb "github.com/mainflux/mainflux/writers/mongodb"
"github.com/mainflux/mainflux/writers/mongodb"
"github.com/mongodb/mongo-go-driver/mongo"
nats "github.com/nats-io/go-nats"
"github.com/nats-io/go-nats"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
name = "mongodb-writer"
defNatsURL = nats.DefaultURL
defPort = "8180"
defDBName = "mainflux"
defDBHost = "localhost"
defDBPort = "27017"
queue = "mongodb-writer"
envNatsURL = "MF_NATS_URL"
envPort = "MF_MONGO_WRITER_PORT"
envDBName = "MF_MONGO_WRITER_DB_NAME"
envDBHost = "MF_MONGO_WRITER_DB_HOST"
envDBPort = "MF_MONGO_WRITER_DB_PORT"
defNatsURL = nats.DefaultURL
defLogLevel = "error"
defPort = "8180"
defDBName = "mainflux"
defDBHost = "localhost"
defDBPort = "27017"
envNatsURL = "MF_NATS_URL"
envLogLevel = "MF_MONGO_WRITER_LOG_LEVEL"
envPort = "MF_MONGO_WRITER_PORT"
envDBName = "MF_MONGO_WRITER_DB_NAME"
envDBHost = "MF_MONGO_WRITER_DB_HOST"
envDBPort = "MF_MONGO_WRITER_DB_PORT"
)
type config struct {
NatsURL string
Port string
DBName string
DBHost string
DBPort string
NatsURL string
LogLevel string
Port string
DBName string
DBHost string
DBPort string
}
func main() {
cfg := loadConfigs()
logger := log.New(os.Stdout)
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
nc, err := nats.Connect(cfg.NatsURL)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to NATS: %s", err))
@@ -59,16 +73,12 @@ func main() {
}
db := client.Database(cfg.DBName)
repo, err := mongodb.New(db)
if err != nil {
logger.Error(fmt.Sprintf("Failed to create MongoDB writer: %s", err))
os.Exit(1)
}
repo := mongodb.New(db)
counter, latency := makeMetrics()
repo = writers.LoggingMiddleware(repo, logger)
repo = writers.MetricsMiddleware(repo, counter, latency)
if err := writers.Start(name, nc, logger, repo); err != nil {
if err := writers.Start(nc, repo, queue, logger); err != nil {
logger.Error(fmt.Sprintf("Failed to start message writer: %s", err))
os.Exit(1)
}
@@ -88,11 +98,12 @@ func main() {
func loadConfigs() config {
return config{
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
Port: mainflux.Env(envPort, defPort),
DBName: mainflux.Env(envDBName, defDBName),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
Port: mainflux.Env(envPort, defPort),
DBName: mainflux.Env(envDBName, defDBName),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
}
}
@@ -114,7 +125,7 @@ func makeMetrics() (*kitprometheus.Counter, *kitprometheus.Summary) {
return counter, latency
}
func startHTTPService(port string, logger log.Logger, errs chan error) {
func startHTTPService(port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Mongodb writer service started, exposed port %s", p))
errs <- http.ListenAndServe(p, mongodb.MakeHandler())
+55 -31
View File
@@ -1,54 +1,84 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/mainflux/mainflux"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/normalizer"
nats "github.com/nats-io/go-nats"
"github.com/mainflux/mainflux/normalizer/api"
"github.com/mainflux/mainflux/normalizer/nats"
broker "github.com/nats-io/go-nats"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
stdprometheus "github.com/prometheus/client_golang/prometheus"
)
const (
defNatsURL string = nats.DefaultURL
defPort string = "8180"
envNatsURL string = "MF_NATS_URL"
envPort string = "MF_NORMALIZER_PORT"
defNatsURL string = broker.DefaultURL
defLogLevel string = "error"
defPort string = "8180"
envNatsURL string = "MF_NATS_URL"
envLogLevel string = "MF_NORMALIZER_LOG_LEVEL"
envPort string = "MF_NORMALIZER_PORT"
)
type config struct {
NatsURL string
Port string
NatsURL string
LogLevel string
Port string
}
func main() {
cfg := config{
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
Port: mainflux.Env(envPort, defPort),
cfg := loadConfig()
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
logger := log.New(os.Stdout)
nc, err := nats.Connect(cfg.NatsURL)
nc, err := broker.Connect(cfg.NatsURL)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to NATS: %s", err))
os.Exit(1)
}
defer nc.Close()
svc := normalizer.New()
svc = api.LoggingMiddleware(svc, logger)
svc = api.MetricsMiddleware(
svc,
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "normalizer",
Subsystem: "api",
Name: "request_count",
Help: "Number of requests received.",
}, []string{"method"}),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "normalizer",
Subsystem: "api",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, []string{"method"}),
)
errs := make(chan error, 2)
go func() {
p := fmt.Sprintf(":%s", cfg.Port)
logger.Info(fmt.Sprintf("Normalizer service started, exposed port %s", cfg.Port))
errs <- http.ListenAndServe(p, normalizer.MakeHandler())
errs <- http.ListenAndServe(p, api.MakeHandler())
}()
go func() {
@@ -57,22 +87,16 @@ func main() {
errs <- fmt.Errorf("%s", <-c)
}()
counter := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "normalizer",
Subsystem: "api",
Name: "request_count",
Help: "Number of requests received.",
}, []string{"method"})
latency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "normalizer",
Subsystem: "api",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, []string{"method"})
normalizer.Subscribe(nc, logger, counter, latency)
nats.Subscribe(svc, nc, logger)
err = <-errs
logger.Error(fmt.Sprintf("Normalizer service terminated: %s", err))
}
func loadConfig() config {
return config{
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
Port: mainflux.Env(envPort, defPort),
}
}
+90 -42
View File
@@ -1,22 +1,33 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"database/sql"
"fmt"
"log"
"net"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/go-redis/redis"
"github.com/mainflux/mainflux"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/things"
"github.com/mainflux/mainflux/things/api"
grpcapi "github.com/mainflux/mainflux/things/api/grpc"
httpapi "github.com/mainflux/mainflux/things/api/http"
"github.com/mainflux/mainflux/things/postgres"
rediscache "github.com/mainflux/mainflux/things/redis"
"github.com/mainflux/mainflux/things/uuid"
usersapi "github.com/mainflux/mainflux/users/api/grpc"
stdprometheus "github.com/prometheus/client_golang/prometheus"
@@ -24,39 +35,55 @@ import (
)
const (
defDBHost = "localhost"
defDBPort = "5432"
defDBUser = "mainflux"
defDBPass = "mainflux"
defDBName = "things"
defHTTPPort = "8180"
defGRPCPort = "8181"
defUsersURL = "localhost:8181"
envDBHost = "MF_THINGS_DB_HOST"
envDBPort = "MF_THINGS_DB_PORT"
envDBUser = "MF_THINGS_DB_USER"
envDBPass = "MF_THINGS_DB_PASS"
envDBName = "MF_THINGS_DB"
envHTTPPort = "MF_THINGS_HTTP_PORT"
envGRPCPort = "MF_THINGS_GRPC_PORT"
envUsersURL = "MF_USERS_URL"
defLogLevel = "error"
defDBHost = "localhost"
defDBPort = "5432"
defDBUser = "mainflux"
defDBPass = "mainflux"
defDBName = "things"
defCacheURL = "localhost:6379"
defCachePass = ""
defCacheDB = "0"
defHTTPPort = "8180"
defGRPCPort = "8181"
defUsersURL = "localhost:8181"
envLogLevel = "MF_THINGS_LOG_LEVEL"
envDBHost = "MF_THINGS_DB_HOST"
envDBPort = "MF_THINGS_DB_PORT"
envDBUser = "MF_THINGS_DB_USER"
envDBPass = "MF_THINGS_DB_PASS"
envDBName = "MF_THINGS_DB"
envCacheURL = "MF_THINGS_CACHE_URL"
envCachePass = "MF_THINGS_CACHE_PASS"
envCacheDB = "MF_THINGS_CACHE_DB"
envHTTPPort = "MF_THINGS_HTTP_PORT"
envGRPCPort = "MF_THINGS_GRPC_PORT"
envUsersURL = "MF_USERS_URL"
)
type config struct {
DBHost string
DBPort string
DBUser string
DBPass string
DBName string
HTTPPort string
GRPCPort string
UsersURL string
LogLevel string
DBHost string
DBPort string
DBUser string
DBPass string
DBName string
CacheURL string
CachePass string
CacheDB string
HTTPPort string
GRPCPort string
UsersURL string
}
func main() {
cfg := loadConfig()
logger := log.New(os.Stdout)
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
cache := connectToCache(cfg.CacheURL, cfg.CachePass, cfg.CacheDB, logger)
db := connectToDB(cfg, logger)
defer db.Close()
@@ -64,7 +91,7 @@ func main() {
conn := connectToUsersService(cfg.UsersURL, logger)
defer conn.Close()
svc := newService(conn, db, logger)
svc := newService(conn, db, cache, logger)
errs := make(chan error, 2)
go startHTTPServer(svc, cfg.HTTPPort, logger, errs)
@@ -76,24 +103,43 @@ func main() {
errs <- fmt.Errorf("%s", <-c)
}()
err := <-errs
err = <-errs
logger.Error(fmt.Sprintf("Things service terminated: %s", err))
}
func loadConfig() config {
return config{
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass),
DBName: mainflux.Env(envDBName, defDBName),
HTTPPort: mainflux.Env(envHTTPPort, defHTTPPort),
GRPCPort: mainflux.Env(envGRPCPort, defGRPCPort),
UsersURL: mainflux.Env(envUsersURL, defUsersURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass),
DBName: mainflux.Env(envDBName, defDBName),
CacheURL: mainflux.Env(envCacheURL, defCacheURL),
CachePass: mainflux.Env(envCachePass, defCachePass),
CacheDB: mainflux.Env(envCacheDB, defCacheDB),
HTTPPort: mainflux.Env(envHTTPPort, defHTTPPort),
GRPCPort: mainflux.Env(envGRPCPort, defGRPCPort),
UsersURL: mainflux.Env(envUsersURL, defUsersURL),
}
}
func connectToDB(cfg config, logger log.Logger) *sql.DB {
func connectToCache(cacheURL, cachePass string, cacheDB string, logger logger.Logger) *redis.Client {
db, err := strconv.Atoi(cacheDB)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to cache: %s", err))
os.Exit(1)
}
return redis.NewClient(&redis.Options{
Addr: cacheURL,
Password: cachePass,
DB: db,
})
}
func connectToDB(cfg config, logger logger.Logger) *sql.DB {
db, err := postgres.Connect(cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBUser, cfg.DBPass)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err))
@@ -102,7 +148,7 @@ func connectToDB(cfg config, logger log.Logger) *sql.DB {
return db
}
func connectToUsersService(usersAddr string, logger log.Logger) *grpc.ClientConn {
func connectToUsersService(usersAddr string, logger logger.Logger) *grpc.ClientConn {
conn, err := grpc.Dial(usersAddr, grpc.WithInsecure())
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to users service: %s", err))
@@ -111,13 +157,15 @@ func connectToUsersService(usersAddr string, logger log.Logger) *grpc.ClientConn
return conn
}
func newService(conn *grpc.ClientConn, db *sql.DB, logger log.Logger) things.Service {
func newService(conn *grpc.ClientConn, db *sql.DB, client *redis.Client, logger logger.Logger) things.Service {
users := usersapi.NewClient(conn)
thingsRepo := postgres.NewThingRepository(db, logger)
channelsRepo := postgres.NewChannelRepository(db, logger)
chanCache := rediscache.NewChannelCache(client)
thingCache := rediscache.NewThingCache(client)
idp := uuid.New()
svc := things.New(users, thingsRepo, channelsRepo, idp)
svc := things.New(users, thingsRepo, channelsRepo, chanCache, thingCache, idp)
svc = api.LoggingMiddleware(svc, logger)
svc = api.MetricsMiddleware(
svc,
@@ -137,13 +185,13 @@ func newService(conn *grpc.ClientConn, db *sql.DB, logger log.Logger) things.Ser
return svc
}
func startHTTPServer(svc things.Service, port string, logger log.Logger, errs chan error) {
func startHTTPServer(svc things.Service, port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Things service started, exposed port %s", port))
errs <- http.ListenAndServe(p, httpapi.MakeHandler(svc))
}
func startGRPCServer(svc things.Service, port string, logger log.Logger, errs chan error) {
func startGRPCServer(svc things.Service, port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
listener, err := net.Listen("tcp", p)
if err != nil {
+22 -8
View File
@@ -1,8 +1,16 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"database/sql"
"fmt"
"log"
"net"
"net/http"
"os"
@@ -11,7 +19,7 @@ import (
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/mainflux/mainflux"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/users"
"github.com/mainflux/mainflux/users/api"
grpcapi "github.com/mainflux/mainflux/users/api/grpc"
@@ -24,6 +32,7 @@ import (
)
const (
defLogLevel = "error"
defDBHost = "localhost"
defDBPort = "5432"
defDBUser = "mainflux"
@@ -32,6 +41,7 @@ const (
defHTTPPort = "8180"
defGRPCPort = "8181"
defSecret = "users"
envLogLevel = "MF_USERS_LOG_LEVEL"
envDBHost = "MF_USERS_DB_HOST"
envDBPort = "MF_USERS_DB_PORT"
envDBUser = "MF_USERS_DB_USER"
@@ -43,6 +53,7 @@ const (
)
type config struct {
LogLevel string
DBHost string
DBPort string
DBUser string
@@ -56,8 +67,10 @@ type config struct {
func main() {
cfg := loadConfig()
logger := log.New(os.Stdout)
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
db := connectToDB(cfg, logger)
defer db.Close()
@@ -73,12 +86,13 @@ func main() {
errs <- fmt.Errorf("%s", <-c)
}()
err := <-errs
err = <-errs
logger.Error(fmt.Sprintf("Users service terminated: %s", err))
}
func loadConfig() config {
return config{
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
DBHost: mainflux.Env(envDBHost, defDBHost),
DBPort: mainflux.Env(envDBPort, defDBPort),
DBUser: mainflux.Env(envDBUser, defDBUser),
@@ -90,7 +104,7 @@ func loadConfig() config {
}
}
func connectToDB(cfg config, logger log.Logger) *sql.DB {
func connectToDB(cfg config, logger logger.Logger) *sql.DB {
db, err := postgres.Connect(cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBUser, cfg.DBPass)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err))
@@ -99,7 +113,7 @@ func connectToDB(cfg config, logger log.Logger) *sql.DB {
return db
}
func newService(db *sql.DB, secret string, logger log.Logger) users.Service {
func newService(db *sql.DB, secret string, logger logger.Logger) users.Service {
repo := postgres.New(db)
hasher := bcrypt.New()
idp := jwt.New(secret)
@@ -124,13 +138,13 @@ func newService(db *sql.DB, secret string, logger log.Logger) users.Service {
return svc
}
func startHTTPServer(svc users.Service, port string, logger log.Logger, errs chan error) {
func startHTTPServer(svc users.Service, port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
logger.Info(fmt.Sprintf("Users HTTP service started, exposed port %s", port))
errs <- http.ListenAndServe(p, httpapi.MakeHandler(svc, logger))
}
func startGRPCServer(svc users.Service, port string, logger log.Logger, errs chan error) {
func startGRPCServer(svc users.Service, port string, logger logger.Logger, errs chan error) {
p := fmt.Sprintf(":%s", port)
listener, err := net.Listen("tcp", p)
if err != nil {
+25 -8
View File
@@ -1,7 +1,15 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
@@ -9,7 +17,7 @@ import (
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/mainflux/mainflux"
log "github.com/mainflux/mainflux/logger"
"github.com/mainflux/mainflux/logger"
thingsapi "github.com/mainflux/mainflux/things/api/grpc"
adapter "github.com/mainflux/mainflux/ws"
"github.com/mainflux/mainflux/ws/api"
@@ -21,9 +29,11 @@ import (
const (
defPort = "8180"
defLogLevel = "error"
defNatsURL = broker.DefaultURL
defThingsURL = "localhost:8181"
envPort = "MF_WS_ADAPTER_PORT"
envLogLevel = "MF_WS_ADAPTER_LOG_LEVEL"
envNatsURL = "MF_NATS_URL"
envThingsURL = "MF_THINGS_URL"
)
@@ -31,18 +41,17 @@ const (
type config struct {
ThingsURL string
NatsURL string
LogLevel string
Port string
}
func main() {
cfg := config{
ThingsURL: mainflux.Env(envThingsURL, defThingsURL),
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
Port: mainflux.Env(envPort, defPort),
cfg := loadConfig()
logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf(err.Error())
}
logger := log.New(os.Stdout)
nc, err := broker.Connect(cfg.NatsURL)
if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to NATS: %s", err))
@@ -94,3 +103,11 @@ func main() {
err = <-errs
logger.Error(fmt.Sprintf("WebSocket adapter terminated: %s", err))
}
func loadConfig() config {
return config{
NatsURL: mainflux.Env(envNatsURL, defNatsURL),
LogLevel: mainflux.Env(envLogLevel, defLogLevel),
Port: mainflux.Env(envPort, defPort),
}
}
+1 -1
View File
@@ -9,7 +9,7 @@
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
"favicon.png"
],
"index": "index.html",
"main": "main.ts",
+7
View File
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { Route, RouterModule } from '@angular/router';
+7
View File
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<div *mobxAutorun>
<div class="loading" *ngIf="uiStore.loading" fxLayoutAlign="center center">
<mat-progress-spinner [mode]="'indeterminate'"></mat-progress-spinner>
+7
View File
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
.loading {
position: absolute;
width: 100%;
+7
View File
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClientModule } from '@angular/common/http';
import { async, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
+7
View File
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import { reaction } from 'mobx';
+7
View File
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import './rxjs-extensions.ts';
import 'hammerjs';
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<div class="container" style="height: 80vh" fxLayoutAlign="center center">
<form fxLayout="column" [formGroup]="loginForm" (ngSubmit)="login()" fxFlex="30%" fxFlex.sm="70%" fxFlex.xs="90%">
<mat-card>
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
::ng-deep mat-card-content.loginCard {
height: 200px;
}
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<div class="container" style="height: 80vh" fxLayoutAlign="center center">
<form fxLayout="column" [formGroup]="signupForm" (ngSubmit)="signup()" fxFlex="30%" fxFlex.sm="70%" fxFlex.xs="90%">
<mat-card>
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
::ng-deep mat-card-content.loginCard {
height: 200px;
}
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<form [formGroup]="addChannelForm" (ngSubmit)="onAddChannel()">
<h1 *ngIf="!editMode" mat-dialog-title>Add channel</h1>
<h1 *ngIf="editMode" mat-dialog-title>Edit channel</h1>
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<div class="channelsContainer" fxLayout="row" fxLayoutWrap>
<ng-container [ngSwitch]="channelsStore.channels?.length > 0">
<ng-container *ngSwitchCase="true">
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
.addButton {
position: fixed;
bottom: 12px;
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<h1 mat-dialog-title>{{data.question}}</h1>
<div mat-dialog-actions fxLayoutAlign="end end">
<button mat-button mat-dialog-close>Cancel</button>
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material';
@@ -23,7 +23,7 @@
</mat-error>
</mat-form-field>
<mat-form-field>
<textarea formControlName="payload" matInput placeholder="Payload" matTextareaAutosize matAutosizeMinRows="2"
<textarea formControlName="metadata" matInput placeholder="Metadata" matTextareaAutosize matAutosizeMinRows="2"
matAutosizeMaxRows="5"></textarea>
</mat-form-field>
</div>
@@ -26,7 +26,7 @@ export class ThingDialogComponent implements OnInit {
id: null,
type: ['', [Validators.required]],
name: ['', [Validators.required, Validators.minLength(5)]],
payload: ['']
metadata: ['']
}
);
@@ -1,3 +1,10 @@
<!--
Copyright (c) 2018
Mainflux
SPDX-License-Identifier: Apache-2.0
-->
<div class="thingsContainer" fxLayout="row" fxLayoutWrap>
<ng-container [ngSwitch]="thingsStore.things?.length > 0">
<ng-container *ngSwitchCase="true">
@@ -17,9 +24,9 @@
<mat-header-cell fxFlex="10%" *matHeaderCellDef mat-sort-header>Type</mat-header-cell>
<mat-cell fxFlex="10%" *matCellDef="let row"> {{row.type}}</mat-cell>
</ng-container>
<ng-container matColumnDef="payload">
<mat-header-cell fxFlex="35%" *matHeaderCellDef mat-sort-header>Payload</mat-header-cell>
<mat-cell fxFlex="35%" *matCellDef="let row"> {{row.payload | json}}</mat-cell>
<ng-container matColumnDef="metadata">
<mat-header-cell fxFlex="35%" *matHeaderCellDef mat-sort-header>Metadata</mat-header-cell>
<mat-cell fxFlex="35%" *matCellDef="let row"> {{row.metadata | json}}</mat-cell>
</ng-container>
<!-- Actions -->
<ng-container matColumnDef="actions">
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
.addButton {
position: fixed;
bottom: 12px;
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material';
import { toJS } from 'mobx';
@@ -16,7 +23,7 @@ import { ChannelsStore } from '../../core/store/channels.store';
})
export class ThingsComponent implements OnInit {
things: Observable<Thing[]>;
displayedColumns = ['id', 'name', 'type', 'payload', 'actions'];
displayedColumns = ['id', 'name', 'type', 'metadata', 'actions'];
constructor(
private dialog: MatDialog,
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { NgModule } from '@angular/core';
import {
MatButtonModule,
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import '../../../rxjs-extensions';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClient, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
+1 -1
View File
@@ -8,7 +8,7 @@ export interface Thing {
id?: '';
type: string;
name: string;
payload: string;
metadata: string;
}
export interface User {
@@ -74,7 +74,7 @@ describe('ThingsStore', () => {
const newThing: Thing = {
name: 'new thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.addThing(newThing);
@@ -89,7 +89,7 @@ describe('ThingsStore', () => {
const newThing: Thing = {
name: 'new thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.addThing(newThing);
@@ -104,7 +104,7 @@ describe('ThingsStore', () => {
const newThing: Thing = {
name: 'new thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.addThing(newThing);
@@ -120,7 +120,7 @@ describe('ThingsStore', () => {
const newThing: Thing = {
name: 'new thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.addThing(newThing);
@@ -136,7 +136,7 @@ describe('ThingsStore', () => {
const editedThing: Thing = {
name: 'edited thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.editThing(editedThing);
@@ -151,7 +151,7 @@ describe('ThingsStore', () => {
const editedThing: Thing = {
name: 'edited thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.editThing(editedThing);
@@ -167,7 +167,7 @@ describe('ThingsStore', () => {
const editedThing: Thing = {
name: 'edited thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.editThing(editedThing);
@@ -182,7 +182,7 @@ describe('ThingsStore', () => {
const editedThing: Thing = {
name: 'edited thing',
type: 'app',
payload: '',
metadata: '',
};
thingsStore.editThing(editedThing);
@@ -198,7 +198,7 @@ describe('ThingsStore', () => {
const thingToBeDeleted: Thing = {
name: 'thingToBeDeleted',
type: 'app',
payload: ''
metadata: ''
};
thingsStore.deleteThing(thingToBeDeleted);
@@ -213,7 +213,7 @@ describe('ThingsStore', () => {
const thingToBeDeleted: Thing = {
name: 'thingToBeDeleted',
type: 'app',
payload: ''
metadata: ''
};
@@ -230,7 +230,7 @@ describe('ThingsStore', () => {
const thingToBeDeleted: Thing = {
name: 'thingToBeDeleted',
type: 'app',
payload: ''
metadata: ''
};
thingsStore.deleteThing(thingToBeDeleted);
@@ -245,7 +245,7 @@ describe('ThingsStore', () => {
const thingToBeDeleted: Thing = {
name: 'thingToBeDeleted',
type: 'app',
payload: ''
metadata: ''
};
thingsStore.deleteThing(thingToBeDeleted);
+7
View File
@@ -1,3 +1,10 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
import 'rxjs/add/observable/combineLatest';
import 'rxjs/add/observable/interval';
import 'rxjs/add/observable/of';
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+1 -1
View File
@@ -6,7 +6,7 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" type="image/x-icon" href="favicon.png">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
+7
View File
@@ -1 +1,8 @@
/*
* Copyright (c) 2018
* Mainflux
*
* SPDX-License-Identifier: Apache-2.0
*/
@import '~@angular/material/prebuilt-themes/indigo-pink.css';
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
// Package mainflux acts as an umbrella package containing multiple different
// microservices and defines all shared domain concepts.
package mainflux
+4
View File
@@ -0,0 +1,4 @@
FROM scratch
ARG SVC_NAME
COPY mainflux-$SVC_NAME /exe
ENTRYPOINT ["/exe"]
@@ -0,0 +1,28 @@
###
# This docker-compose file contains optional Cassandra and cassandra-reader. Since these are optional, this file is
# dependent of docker-compose file from <project_root>/docker. In order to run
# these optional service, execute command:
# docker-compose -f docker/docker-compose.yml -f docker/addons/cassandra-reader/docker-compose.yml up
# from project root.
###
version: "3"
networks:
docker_mainflux-base-net:
external: true
services:
cassandra-reader:
image: mainflux/cassandra-reader:latest
container_name: mainflux-cassandra-reader
restart: on-failure
environment:
MF_THINGS_URL: things:8183
MF_CASSANDRA_READER_PORT: 8903
MF_CASSANDRA_READER_DB_CLUSTER: mainflux-cassandra
MF_CASSANDRA_READER_DB_KEYSPACE: mainflux
ports:
- 8903:8903
networks:
- docker_mainflux-base-net
@@ -0,0 +1,39 @@
###
# This docker-compose file contains optional Cassandra and cassandra-writer. Since these are optional, this file is
# dependent of docker-compose file from <project_root>/docker. In order to run
# these optional service, execute command:
# docker-compose -f docker/docker-compose.yml -f docker/addons/cassandra-writer/docker-compose.yml up
# from project root.
###
version: "3"
networks:
docker_mainflux-base-net:
external: true
services:
cassandra:
image: cassandra:3.11.2
container_name: mainflux-cassandra
restart: on-failure
networks:
- docker_mainflux-base-net
cassandra-writer:
image: mainflux/cassandra-writer:latest
container_name: mainflux-cassandra-writer
depends_on:
- cassandra
expose:
- 8902
restart: on-failure
environment:
MF_NATS_URL: nats://nats:4222
MF_CASSANDRA_WRITER_PORT: 8902
MF_CASSANDRA_WRITER_DB_CLUSTER: mainflux-cassandra
MF_CASSANDRA_WRITER_DB_KEYSPACE: mainflux
ports:
- 8902:8902
networks:
- docker_mainflux-base-net
+3
View File
@@ -0,0 +1,3 @@
docker-compose -f docker/addons/cassandra-writer/docker-compose.yml up -d
sleep 20
docker exec mainflux-cassandra cqlsh -e "CREATE KEYSPACE IF NOT EXISTS mainflux WITH replication = {'class':'SimpleStrategy','replication_factor':'1'};"
@@ -0,0 +1,30 @@
###
# This docker-compose file contains optional InfluxDB-reader service for the Mainflux
# platform. Since this service is optional, this file is dependent on the docker-compose.yml
# file from <project_root>/docker/. In order to run InfluxDB-reader service, core services,
# as well as the network from the core composition, should be already running.
###
version: "3"
networks:
docker_mainflux-base-net:
external: true
services:
influxdb-reader:
image: mainflux/influxdb-reader:latest
container_name: mainflux-influxdb-reader
restart: on-failure
environment:
MF_THINGS_URL: things:8183
MF_INFLUX_READER_PORT: 8905
MF_INFLUX_READER_DB_NAME: mainflux
MF_INFLUX_READER_DB_HOST: mainflux-influxdb
MF_INFLUX_READER_DB_PORT: 8086
MF_INFLUX_READER_DB_USER: mainflux
MF_INFLUX_READER_DB_PASS: mainflux
ports:
- 8905:8905
networks:
- docker_mainflux-base-net
@@ -1,13 +1,16 @@
###
# This docker-compose file contains optional InfluxDB, InfluxDB-writer and Grafana services
# for Mainflux platform. Since these are optional, this file is dependent of docker-compose file
# from <project_root>/docker. In order to run these optional service, execute command:
# docker-compose -f docker/docker-compose.yml -f docker/addons/influxdb/docker-compose.yml up
# from project root.
# for the Mainflux platform. Since this services are optional, this file is dependent on the
# docker-compose.yml file from <project_root>/docker/. In order to run these services,
# core services, as well as the network from the core composition, should be already running.
###
version: "3"
networks:
docker_mainflux-base-net:
external: true
services:
influxdb:
@@ -18,26 +21,31 @@ services:
INFLUXDB_DB: mainflux
INFLUXDB_ADMIN_USER: mainflux
INFLUXDB_ADMIN_PASSWORD: mainflux
networks:
- docker_mainflux-base-net
influxdb-writer:
image: mainflux/influxdb:latest
image: mainflux/influxdb-writer:latest
container_name: mainflux-influxdb-writer
depends_on:
- influxdb
- nats
expose:
- 8900
restart: on-failure
environment:
MF_NATS_URL: nats://nats:4222
MF_INFLUX_WRITER_PORT: 8900
MF_INFLUX_WRITER_BATCH_SIZE: 5000
MF_INFLUX_WRITER_BATCH_TIMEOUT: 5
MF_INFLUX_WRITER_DB_NAME: mainflux
MF_INFLUX_WRITER_DB_HOST: influxdb
MF_INFLUX_WRITER_DB_HOST: mainflux-influxdb
MF_INFLUX_WRITER_DB_PORT: 8086
MF_INFLUX_WRITER_DB_USER: mainflux
MF_INFLUX_WRITER_DB_PASS: mainflux
ports:
- 8900:8900
networks:
- docker_mainflux-base-net
grafana:
image: grafana/grafana:5.1.3
@@ -47,3 +55,5 @@ services:
restart: on-failure
ports:
- 3001:3000
networks:
- docker_mainflux-base-net
@@ -0,0 +1,29 @@
###
# This docker-compose file contains optional MongoDB-reader service
# for Mainflux platform. Since these are optional, this file is dependent of docker-compose file
# from <project_root>/docker. In order to run these optional service, execute command:
# docker-compose -f docker/docker-compose.yml -f docker/addons/mongodb-reader/docker-compose.yml up
# from project root. MongoDB service is defined in docker/addons/mongodb-writer/docker-compose.yml.
###
version: "3"
networks:
docker_mainflux-base-net:
external: true
services:
mongodb-reader:
image: mainflux/mongodb-reader:latest
container_name: mainflux-mongodb-reader
restart: on-failure
environment:
MF_THINGS_URL: things:8183
MF_MONGO_READER_PORT: 8904
MF_MONGO_READER_DB_NAME: mainflux
MF_MONGO_READER_DB_HOST: mongodb
MF_MONGO_READER_DB_PORT: 27017
ports:
- 8904:8904
networks:
- docker_mainflux-base-net
@@ -2,15 +2,18 @@
# This docker-compose file contains optional MongoDB and MongoDB-writer services
# for Mainflux platform. Since these are optional, this file is dependent of docker-compose file
# from <project_root>/docker. In order to run these optional service, execute command:
# docker-compose -f docker/docker-compose.yml -f docker/addons/mongodb/docker-compose.yml up
# docker-compose -f docker/docker-compose.yml -f docker/addons/mongodb-writer/docker-compose.yml up
# from project root. MongoDB default port (27017) is exposed, so you can use various tools for database
# inspection and data visualization.
###
version: "3"
services:
networks:
docker_mainflux-base-net:
external: true
services:
mongodb:
image: mongo:3.6-jessie
container_name: mainflux-mongodb
@@ -21,15 +24,14 @@ services:
MONGO_INITDB_DATABASE: mainflux
ports:
- 27017:27017
networks:
- docker_mainflux-base-net
mongo-writer:
image: mainflux/mongodb:latest
mongodb-writer:
image: mainflux/mongodb-writer:latest
container_name: mainflux-mongodb-writer
depends_on:
- mongodb
- nats
expose:
- 8901
restart: on-failure
environment:
MF_NATS_URL: nats://nats:4222
@@ -39,3 +41,5 @@ services:
MF_MONGO_WRITER_DB_PORT: 27017
ports:
- 8901:8901
networks:
- docker_mainflux-base-net
+49 -1
View File
@@ -8,6 +8,10 @@
version: "3"
networks:
mainflux-base-net:
driver: bridge
services:
nginx:
image: nginx:1.13-alpine
@@ -22,11 +26,15 @@ services:
- 80:80
- 443:443
- 8883:8883
networks:
- mainflux-base-net
nats:
image: nats:1.0.2
image: nats:1.3.0
container_name: mainflux-nats
restart: on-failure
networks:
- mainflux-base-net
users-db:
image: postgres:10.2-alpine
@@ -36,6 +44,8 @@ services:
POSTGRES_USER: mainflux
POSTGRES_PASSWORD: mainflux
POSTGRES_DB: users
networks:
- mainflux-base-net
users:
image: mainflux/users:latest
@@ -57,6 +67,8 @@ services:
MF_USERS_SECRET: secret
ports:
- 8180:8180
networks:
- mainflux-base-net
things-db:
image: postgres:10.2-alpine
@@ -66,6 +78,15 @@ services:
POSTGRES_USER: mainflux
POSTGRES_PASSWORD: mainflux
POSTGRES_DB: things
networks:
- mainflux-base-net
things-cache:
image: redis:4.0.9-alpine
container_name: mainflux-things-cache
restart: on-failure
networks:
- mainflux-base-net
things:
image: mainflux/things:latest
@@ -83,22 +104,29 @@ services:
MF_THINGS_DB_USER: mainflux
MF_THINGS_DB_PASS: mainflux
MF_THINGS_DB: things
MF_THINGS_CACHE_URL: things-cache:6379
MF_THINGS_HTTP_PORT: 8182
MF_THINGS_GRPC_PORT: 8183
MF_USERS_URL: users:8181
MF_THINGS_SECRET: secret
ports:
- 8182:8182
networks:
- mainflux-base-net
normalizer:
image: mainflux/normalizer:latest
container_name: mainflux-normalizer
restart: on-failure
depends_on:
- nats
expose:
- 8184
environment:
MF_NATS_URL: nats://nats:4222
MF_NORMALIZER_PORT: 8184
networks:
- mainflux-base-net
dashflux:
image: mainflux/dashflux:latest
@@ -106,12 +134,15 @@ services:
restart: on-failure
ports:
- 3000:3000
networks:
- mainflux-base-net
ws-adapter:
image: mainflux/ws:latest
container_name: mainflux-ws
depends_on:
- things
- nats
expose:
- 8186
restart: on-failure
@@ -121,12 +152,15 @@ services:
MF_THINGS_URL: things:8183
ports:
- 8186:8186
networks:
- mainflux-base-net
http-adapter:
image: mainflux/http:latest
container_name: mainflux-http
depends_on:
- things
- nats
restart: on-failure
expose:
- 8185
@@ -136,18 +170,32 @@ services:
MF_THINGS_URL: things:8183
ports:
- 8185:8185
networks:
- mainflux-base-net
redis:
image: redis:4.0.9-alpine
container_name: mainflux-redis
restart: on-failure
networks:
- mainflux-base-net
mqtt-adapter:
image: mainflux/mqtt:latest
container_name: mainflux-mqtt
depends_on:
- things
- nats
- redis
restart: on-failure
environment:
MF_MQTT_ADAPTER_PORT: 1883
MF_MQTT_WS_PORT: 8880
MF_MQTT_REDIS_HOST: redis
MF_NATS_URL: nats://nats:4222
MF_THINGS_URL: things:8183
ports:
- 1883:1883
- 8880:8880
networks:
- mainflux-base-net
+1 -9
View File
@@ -58,18 +58,10 @@ http {
# Virtual Host Configs
##
# HTTP
# HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
access_log off;
error_log off;
return 301 https://$server_name$request_uri;
}
# HTTPS
server {
# SSL configuration
#
listen 443 ssl http2 default_server;
+203
View File
@@ -0,0 +1,203 @@
## Getting Mainflux
Mainflux can be fetched from the official [Mainflux GitHub repository](https://github.com/Mainflux/mainflux):
```
go get github.com/mainflux/mainflux
cd $GOPATH/src/github.com/mainflux/mainflux
```
## Building
### Prerequisites
Make sure that you have [Protocol Buffers](https://developers.google.com/protocol-buffers/) compiler (`protoc`) installed.
[Go Protobuf](https://github.com/golang/protobuf) installation instructions are [here](https://github.com/golang/protobuf#installation).
Go Protobuf uses C bindings, so you will need to install [C++ protobuf](https://github.com/google/protobuf) as a prerequisite.
### Build All Services
Use `GNU Make` tool to build all Mainflux services:
```
make
```
Build artefacts will be put in the `build` directory.
> N.B. All Mainflux services are built as a statically linked binaries. This way they can be portable (transferred to any platform just by placing them there and running them) as they contain all needed libraries and do not relay on shared system libraries. This helps creating [FROM scratch](https://hub.docker.com/_/scratch/) dockers.
### Build Individual Microservice
Individual microservices can be built with:
```
make <microservice_name>
```
For example:
```
make http
```
will build the HTTP Adapter microservice.
### Building Dockers
Dockers can be built with:
```
make dockers
```
or individually with:
```
make docker_<microservice_name>
```
For example:
```
make docker_http
```
> N.B. Mainflux creates `FROM scratch` docker containers which are compact and small in size.
> N.B. The `things-db` and `users-db` containers are built from a vanilla PostgreSQL docker image downloaded from docker hub which does not persist the data when these containers are rebuilt. Thus, __rebuilding of all docker containers with `make dockers` or rebuilding the `things-db` and `users-db` containers separately with `make docker_things-db` and `make docker_users-db` respectively, will cause data loss. All your users, things, channels and connections between them will be lost!__ As we use this setup only for development, we don't guarantee any permanent data persistence. If you need to retain the data between the container rebuilds you can attach volume to the `things-db` and `users-db` containers. Check the official docs on how to use volumes [here](https://docs.docker.com/storage/volumes/) and [here](https://docs.docker.com/compose/compose-file/#volumes).
#### Building Docker images for development
In order to speed up build process, you can use commands such as:
```bash
make dockers_dev
```
or individually with
```bash
make docker_dev_<microservice_name>
```
Commands `make dockers` and `make dockers_dev` are similar. The main difference is that building images in the development mode is done on the local machine, rather than an intermediate image, which makes building images much faster. Before running this command, corresponding binary needs to be built in order to make changes visible. This can be done using `make` or `make <service_name>` command. Commands `make dockers_dev` and `make docker_dev_<service_name>` should be used only for development to speed up the process of image building. **For deployment images, commands from section above should be used.**
### MQTT Microservice
The MQTT Microservice in Mainflux is special, as it is currently the only microservice written in NodeJS. It is not compiled, but node modules need to be downloaded in order to start the service:
```
cd mqtt
npm install
```
Note that there is a shorthand for doing these commands with `make` tool:
```
make mqtt
```
After that, the MQTT Adapter can be started from top directory (as it needs to find `*.proto` files) with:
```
node mqtt/mqtt.js
```
### Protobuf
Aforementioned `make` (which is an alias for `make all` target) is calling `protoc` command prior to compiling individual microservices.
To do this by hand, execute:
```
protoc --go_out=plugins=grpc:. *.proto
```
A shorthand to do this via `make` tool is:
```
make proto
```
> N.B. This must be done once at the beginning in order to generate protobuf Go structures needed for the build.
### Cross-compiling for ARM
Mainflux can be compiled for ARM platform and run on Raspberry Pi or other similar IoT gateways, by following the instructions [here](https://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5) or [here](https://www.alexruf.net/golang/arm/raspberrypi/2016/01/16/cross-compile-with-go-1-5-for-raspberry-pi.html) as well as information
found [here](https://github.com/golang/go/wiki/GoArm). The environment variables `GOARCH=arm` and `GOARM=7` must be set for the compilation.
Cross-compilation for ARM with Mainflux make:
```
GOOS=linux GOARCH=arm GOARM=7 make
```
## Running tests
To run all of the tests you can execute:
```
make test
```
Dockertest is used for the tests, so to run them, you will need the Docker daemon/service running.
## Installing
Installing Go binaries is simple: just move them from `build` to `$GOBIN` (do not fortget to add `$GOBIN` to your `$PATH`).
You can execute:
```
make install
```
which will do this copying of the binaries.
> N.B. Only Go binaries will be installed this way. The MQTT adapter is a NodeJS script and will stay in the `mqtt` dir.
## Deployment
### Prerequisites
Mainflux depends on several infrastructural services, notably [NATS](https://www.nats.io/) broker and [PostgreSQL](https://www.postgresql.org/) database.
#### NATS
Mainflux uses NATS as it's central message bus. For development purposes (when not run via Docker), it expects that NATS is installed on the local system.
To do this execute:
```
go get github.com/nats-io/gnatsd
```
This will install `gnatsd` binary that can be simply run by executing:
```
gnatsd
```
#### PostgreSQL
Mainflux uses PostgreSQL to store metadata (`users`, `things` and `channels` entities alongside with authorization tokens).
It expects that PostgreSQL DB is installed, set up and running on the local system.
Information how to set-up (prepare) PostgreSQL database can be found [here](https://support.rackspace.com/how-to/postgresql-creating-and-dropping-roles/),
and it is done by executing following commands:
```
# Create `users` and `things` databases
sudo -u postgres createdb users
sudo -u postgres createdb things
# Set-up Postgres roles
sudo su - postgres
psql -U postgres
postgres=# CREATE ROLE mainflux WITH LOGIN ENCRYPTED PASSWORD 'mainflux';
postgres=# ALTER USER mainflux WITH LOGIN ENCRYPTED PASSWORD 'mainflux';
```
### Mainflux Services
Running of the Mainflux microservices can be tricky, as there is a lot of them and each demand configuration in the form of environment variables.
The whole system (set of microservices) can be run with one command:
```
make run
```
which will properly configure and run all microservices.
Please assure that MQTT microservice has `node_modules` installed, as explained in _MQTT Microservice_ chapter.
> N.B. `make run` actually calls helper script `scripts/run.sh`, so you can inspect this script for the details.
+159 -2
View File
@@ -118,7 +118,7 @@ Content-Length: 1105
"id": "cb63f852-2d48-44f0-a0cf-e450496c6c92",
"type": "app",
"name": "myapp",
"key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1MjMzNTYzOTcsImlzcyI6Im1haW5mbHV4Iiwic3ViIjoiY2I2M2Y4NTItMmQ0OC00NGYwLWEwY2YtZTQ1MDQ5NmM2YzkyIn0.FE6DWB3yJmBb8uojpQJaKUEbD0Elrjx0HhJA28bVzkU"
"key": "cbf02d60-72f2-4180-9f82-2c957db929d1"
}
]
}
@@ -282,6 +282,32 @@ If you are not able to send custom headers in your handshake request, send it as
query parameter `authorization`. Then your path should look like this
`/channels/<channel_id>/messages?authorization=<thing_auth_key>`.
If you are using the docker environment prepend the url with `ws`. So for example
`/ws/channels/<channel_id>/messages?authorization=<thing_auth_key>`
#### Basic nodejs example
```javascript
const WebSocket = require('ws');
// do not verify self-signed certificates if you are using one
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
// cbf02d60-72f2-4180-9f82-2c957db929d1 is an example of a thing_auth_key
const ws = new WebSocket('wss://localhost/ws/channels/1/messages?authorization=cbf02d60-72f2-4180-9f82-2c957db929d1')
ws.on('open', () => {
ws.send('something')
})
ws.on('message', (data) => {
console.log(data)
})
ws.on('error', (e) => {
console.log(e)
})
```
### MQTT
To send and receive messages over MQTT you could use [Mosquitto tools](https://mosquitto.org),
@@ -290,7 +316,7 @@ or [Paho](https://www.eclipse.org/paho/) if you want to use MQTT over WebSocket.
To publish message over channel, thing should call following command:
```
mosquitto_pub -u <thing_id> -P <thing_key> -t channels/<channel_id>/messages -h localhost -m [{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]
mosquitto_pub -u <thing_id> -P <thing_key> -t channels/<channel_id>/messages -h localhost -m '[{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]'
```
To subscribe to channel, thing should call following command:
@@ -301,3 +327,134 @@ mosquitto_sub -u <thing_id> -P <thing_key> -t channels/<channel_id>/messages -h
If you are using TLS to secure MQTT connection, add `--cafile docker/ssl/certs/ca.crt`
to every command.
## Add-ons
The `<project_root>/docker` folder contains an `addons` directory. This directory is used for various services that are not core to the Mainflux platform but could be used for providing additional features.
In order to run these services, core services, as well as the network from the core composition, should be already running.
### Writers
Writers provide an implementation of various `message writers`. Message writers are services that consume normalized (in `SenML` format) Mainflux messages and store them in specific data store.
#### InfluxDB, InfluxDB-writer and Grafana
From the project root execute the following command:
```bash
docker-compose -f docker/addons/influxdb-writer/docker-compose.yml up -d
```
This will install and start:
- [InfluxDB](https://docs.influxdata.com/influxdb) - time series database
- InfluxDB writer - message repository implementation for InfluxDB
- [Grafana](https://grafana.com) - tool for database exploration and data visualization and analytics
Those new services will take some additional ports:
- 8086 by InfluxDB
- 8900 by InfluxDB writer service
- 3001 by Grafana
To access Grafana, navigate to `http://localhost:3001` and login with: `admin`, password: `admin`
#### Cassandra and Cassandra-writer
```bash
./docker/addons/cassandra-writer/init.sh
```
_Please note that Cassandra may not be suitable for your testing enviroment because it has high system requirements._
#### MongoDB and MongoDB-writer
```bash
docker-compose -f docker/addons/mongodb-writer/docker-compose.yml up -d
```
MongoDB default port (27017) is exposed, so you can use various tools for database inspection and data visualization.
### Readers
Readers provide an implementation of various `message readers`.
Message readers are services that consume normalized (in `SenML` format) Mainflux messages from data storage and opens HTTP API for message consumption.
Installing corresponding writer before reader is implied.
#### InfluxDB-reader
```bash
docker-compose -f docker/addons/influxdb-reader/docker-compose.yml up -d
```
Service exposes [HTTP API](https://github.com/mainflux/mainflux/blob/master/readers/swagger.yml) for fetching messages on port 8905
To read sent messages on channel with id `channel_id` you should send `GET` request to `/channels/<channel_id>/messages` with thing access token in `Authorization` header. That thing must be connected to channel with `channel_id`
```
curl -s -S -i -H "Authorization: <thing_token>" http://localhost:8905/channels/<channel_id>/messages
```
Response should look like this:
```
HTTP/1.1 200 OK
Content-Type: application/json
Date: Tue, 18 Sep 2018 18:56:19 GMT
Content-Length: 228
{
"messages": [
{
"Channel": 1,
"Publisher": 2,
"Protocol": "mqtt",
"Name": "name:voltage",
"Unit": "V",
"Value": 5.6,
"Time": 48.56
},
{
"Channel": 1,
"Publisher": 2,
"Protocol": "mqtt",
"Name": "name:temperature",
"Unit": "C",
"Value": 24.3,
"Time": 48.56
}
]
}
```
Note that you will receive only those messages that were sent by authorization token's owner.
You can specify `offset` and `limit` parameters in order to fetch specific group of messages. In that case, your request should look like:
```
curl -s -S -i -H "Authorization: <thing_token>" http://localhost:8905/channels/<channel_id>/messages?offset=0&limit=5
```
If you don't provide them, default values will be used instead: 0 for `offset`, and 10 for `limit`.
#### Cassandra-reader
```bash
docker-compose -f docker/addons/cassandra-reader/docker-compose.yml up -d
```
Service exposes [HTTP API](https://github.com/mainflux/mainflux/blob/master/readers/swagger.yml) for fetching messages on port 8903
Aside from port, reading request is same as for other readers:
```
curl -s -S -i -H "Authorization: <thing_token>" http://localhost:8903/channels/<channel_id>/messages
```
#### MongoDB-reader
```bash
docker-compose -f docker/addons/mongodb-reader/docker-compose.yml up -d
```
Service exposes [HTTP API](https://github.com/mainflux/mainflux/blob/master/readers/swagger.yml) for fetching messages on port 8904
Aside from port, reading request is same as for other readers:
```
curl -s -S -i -H "Authorization: <thing_token>" http://localhost:8904/channels/<channel_id>/messages
```
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package mainflux
import "os"
+8 -6
View File
@@ -8,11 +8,12 @@ The service is configured using the environment variables presented in the
following table. Note that any unset variables will be replaced with their
default values.
| Variable | Description | Default |
|----------------------|---------------------|-----------------------|
| MF_HTTP_ADAPTER_PORT | Service HTTP port | 8180 |
| MF_NATS_URL | NATS instance URL | nats://localhost:4222 |
| MF_THINGS_URL | Things service URL | localhost:8181 |
| Variable | Description | Default |
|-----------------------------|--------------------------------|-----------------------|
| MF_HTTP_ADAPTER_LOG_LEVEL | Log level for the HTTP Adapter | error |
| MF_HTTP_ADAPTER_PORT | Service HTTP port | 8180 |
| MF_NATS_URL | NATS instance URL | nats://localhost:4222 |
| MF_THINGS_URL | Things service URL | localhost:8181 |
## Deployment
@@ -30,6 +31,7 @@ services:
environment:
MF_THINGS_URL: [Things service URL]
MF_NATS_URL: [NATS instance URL]
MF_HTTP_ADAPTER_LOG_LEVEL: [HTTP Adapter Log Level]
MF_HTTP_ADAPTER_PORT: [Service HTTP port]
```
@@ -48,7 +50,7 @@ make http
make install
# set the environment variables and run the service
MF_THINGS_URL=[Things service URL] MF_NATS_URL=[NATS instance URL] MF_HTTP_ADAPTER_PORT=[Service HTTP port] $GOBIN/mainflux-http
MF_THINGS_URL=[Things service URL] MF_NATS_URL=[NATS instance URL] MF_HTTP_ADAPTER_LOG_LEVEL=[HTTP Adapter Log Level] MF_HTTP_ADAPTER_PORT=[Service HTTP port] $GOBIN/mainflux-http
```
## Usage
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
// Package http contains the domain concept definitions needed to support
// Mainflux http adapter service functionality.
package http
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
// Package api contains API-related concerns: endpoint definitions, middlewares
// and all resource representations.
package api
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package api
import (
+31 -8
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package api_test
import (
@@ -5,6 +12,7 @@ import (
"io"
"net/http"
"net/http/httptest"
"strconv"
"strings"
"testing"
@@ -49,59 +57,74 @@ func (tr testRequest) make() (*http.Response, error) {
}
func TestPublish(t *testing.T) {
id := uint64(1)
chanID := "1"
invalidID := "wrong"
contentType := "application/senml+json"
token := "auth_token"
invalidToken := "invalid_token"
msg := `[{"n":"current","t":-1,"v":1.6}]`
id, _ := strconv.ParseUint(chanID, 10, 64)
thingsClient := mocks.NewThingsClient(map[string]uint64{token: id})
pub := newService()
ts := newHTTPServer(pub, thingsClient)
defer ts.Close()
cases := map[string]struct {
chanID uint64
chanID string
msg string
contentType string
auth string
status int
}{
"publish message": {
chanID: id,
chanID: chanID,
msg: msg,
contentType: contentType,
auth: token,
status: http.StatusAccepted,
},
"publish message without authorization token": {
chanID: id,
chanID: chanID,
msg: msg,
contentType: contentType,
auth: "",
status: http.StatusForbidden,
},
"publish message with invalid authorization token": {
chanID: id,
chanID: chanID,
msg: msg,
contentType: contentType,
auth: invalidToken,
status: http.StatusForbidden,
},
"publish message without content type": {
chanID: id,
chanID: chanID,
msg: msg,
contentType: "",
auth: token,
status: http.StatusAccepted,
},
"publish message to wrong channel": {
chanID: invalidID,
msg: msg,
contentType: contentType,
auth: token,
status: http.StatusNotFound,
},
"publish message unable to authorize": {
chanID: chanID,
msg: msg,
contentType: contentType,
auth: mocks.ServiceErrToken,
status: http.StatusServiceUnavailable,
},
}
for desc, tc := range cases {
req := testRequest{
client: ts.Client(),
method: http.MethodPost,
url: fmt.Sprintf("%s/channels/%d/messages", ts.URL, tc.chanID),
url: fmt.Sprintf("%s/channels/%s/messages", ts.URL, tc.chanID),
contentType: tc.contentType,
token: tc.auth,
body: strings.NewReader(tc.msg),
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
// +build !test
package api
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
// +build !test
package api
+10 -4
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package api
import (
@@ -21,13 +28,12 @@ const protocol = "http"
var (
errMalformedData = errors.New("malformed SenML data")
errNotFound = errors.New("non-existent entity")
auth mainflux.ThingsServiceClient
)
// MakeHandler returns a HTTP handler for API endpoints.
func MakeHandler(svc mainflux.MessagePublisher, cc mainflux.ThingsServiceClient) http.Handler {
auth = cc
func MakeHandler(svc mainflux.MessagePublisher, tc mainflux.ThingsServiceClient) http.Handler {
auth = tc
opts := []kithttp.ServerOption{
kithttp.ServerErrorEncoder(encodeError),
@@ -118,7 +124,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
switch err {
case errMalformedData:
w.WriteHeader(http.StatusBadRequest)
case errNotFound:
case things.ErrNotFound:
w.WriteHeader(http.StatusNotFound)
case things.ErrUnauthorizedAccess:
w.WriteHeader(http.StatusForbidden)
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package mocks
import "github.com/mainflux/mainflux"
+21 -1
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
package mocks
import (
@@ -6,10 +13,15 @@ import (
"github.com/mainflux/mainflux"
"github.com/mainflux/mainflux/things"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var _ mainflux.ThingsServiceClient = (*thingsClient)(nil)
// ServiceErrToken is used to simulate internal server error.
const ServiceErrToken = "unavailable"
type thingsClient struct {
things map[string]uint64
}
@@ -21,13 +33,21 @@ func NewThingsClient(data map[string]uint64) mainflux.ThingsServiceClient {
func (tc thingsClient) CanAccess(ctx context.Context, req *mainflux.AccessReq, opts ...grpc.CallOption) (*mainflux.ThingID, error) {
key := req.GetToken()
// Since there is no appropriate way to simulate internal server error,
// we had to use this obscure approach. ErrorToken simulates gRPC
// call which returns internal server error.
if key == ServiceErrToken {
return nil, status.Error(codes.Internal, "internal server error")
}
if key == "" {
return nil, things.ErrUnauthorizedAccess
}
id, ok := tc.things[key]
if !ok {
return nil, things.ErrUnauthorizedAccess
return nil, status.Error(codes.PermissionDenied, "invalid credentials provided")
}
return &mainflux.ThingID{Value: id}, nil
+7
View File
@@ -1,3 +1,10 @@
//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//
// Package nats contains NATS message publisher implementation.
package nats
+381
View File
@@ -0,0 +1,381 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: internal.proto
package mainflux
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type AccessReq struct {
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
ChanID uint64 `protobuf:"varint,2,opt,name=chanID,proto3" json:"chanID,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AccessReq) Reset() { *m = AccessReq{} }
func (m *AccessReq) String() string { return proto.CompactTextString(m) }
func (*AccessReq) ProtoMessage() {}
func (*AccessReq) Descriptor() ([]byte, []int) {
return fileDescriptor_internal_50ed0f35f4250621, []int{0}
}
func (m *AccessReq) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AccessReq.Unmarshal(m, b)
}
func (m *AccessReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AccessReq.Marshal(b, m, deterministic)
}
func (dst *AccessReq) XXX_Merge(src proto.Message) {
xxx_messageInfo_AccessReq.Merge(dst, src)
}
func (m *AccessReq) XXX_Size() int {
return xxx_messageInfo_AccessReq.Size(m)
}
func (m *AccessReq) XXX_DiscardUnknown() {
xxx_messageInfo_AccessReq.DiscardUnknown(m)
}
var xxx_messageInfo_AccessReq proto.InternalMessageInfo
func (m *AccessReq) GetToken() string {
if m != nil {
return m.Token
}
return ""
}
func (m *AccessReq) GetChanID() uint64 {
if m != nil {
return m.ChanID
}
return 0
}
type ThingID struct {
Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ThingID) Reset() { *m = ThingID{} }
func (m *ThingID) String() string { return proto.CompactTextString(m) }
func (*ThingID) ProtoMessage() {}
func (*ThingID) Descriptor() ([]byte, []int) {
return fileDescriptor_internal_50ed0f35f4250621, []int{1}
}
func (m *ThingID) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ThingID.Unmarshal(m, b)
}
func (m *ThingID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ThingID.Marshal(b, m, deterministic)
}
func (dst *ThingID) XXX_Merge(src proto.Message) {
xxx_messageInfo_ThingID.Merge(dst, src)
}
func (m *ThingID) XXX_Size() int {
return xxx_messageInfo_ThingID.Size(m)
}
func (m *ThingID) XXX_DiscardUnknown() {
xxx_messageInfo_ThingID.DiscardUnknown(m)
}
var xxx_messageInfo_ThingID proto.InternalMessageInfo
func (m *ThingID) GetValue() uint64 {
if m != nil {
return m.Value
}
return 0
}
type Token struct {
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Token) Reset() { *m = Token{} }
func (m *Token) String() string { return proto.CompactTextString(m) }
func (*Token) ProtoMessage() {}
func (*Token) Descriptor() ([]byte, []int) {
return fileDescriptor_internal_50ed0f35f4250621, []int{2}
}
func (m *Token) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Token.Unmarshal(m, b)
}
func (m *Token) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Token.Marshal(b, m, deterministic)
}
func (dst *Token) XXX_Merge(src proto.Message) {
xxx_messageInfo_Token.Merge(dst, src)
}
func (m *Token) XXX_Size() int {
return xxx_messageInfo_Token.Size(m)
}
func (m *Token) XXX_DiscardUnknown() {
xxx_messageInfo_Token.DiscardUnknown(m)
}
var xxx_messageInfo_Token proto.InternalMessageInfo
func (m *Token) GetValue() string {
if m != nil {
return m.Value
}
return ""
}
type UserID struct {
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *UserID) Reset() { *m = UserID{} }
func (m *UserID) String() string { return proto.CompactTextString(m) }
func (*UserID) ProtoMessage() {}
func (*UserID) Descriptor() ([]byte, []int) {
return fileDescriptor_internal_50ed0f35f4250621, []int{3}
}
func (m *UserID) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UserID.Unmarshal(m, b)
}
func (m *UserID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UserID.Marshal(b, m, deterministic)
}
func (dst *UserID) XXX_Merge(src proto.Message) {
xxx_messageInfo_UserID.Merge(dst, src)
}
func (m *UserID) XXX_Size() int {
return xxx_messageInfo_UserID.Size(m)
}
func (m *UserID) XXX_DiscardUnknown() {
xxx_messageInfo_UserID.DiscardUnknown(m)
}
var xxx_messageInfo_UserID proto.InternalMessageInfo
func (m *UserID) GetValue() string {
if m != nil {
return m.Value
}
return ""
}
func init() {
proto.RegisterType((*AccessReq)(nil), "mainflux.AccessReq")
proto.RegisterType((*ThingID)(nil), "mainflux.ThingID")
proto.RegisterType((*Token)(nil), "mainflux.Token")
proto.RegisterType((*UserID)(nil), "mainflux.UserID")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// ThingsServiceClient is the client API for ThingsService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ThingsServiceClient interface {
CanAccess(ctx context.Context, in *AccessReq, opts ...grpc.CallOption) (*ThingID, error)
Identify(ctx context.Context, in *Token, opts ...grpc.CallOption) (*ThingID, error)
}
type thingsServiceClient struct {
cc *grpc.ClientConn
}
func NewThingsServiceClient(cc *grpc.ClientConn) ThingsServiceClient {
return &thingsServiceClient{cc}
}
func (c *thingsServiceClient) CanAccess(ctx context.Context, in *AccessReq, opts ...grpc.CallOption) (*ThingID, error) {
out := new(ThingID)
err := c.cc.Invoke(ctx, "/mainflux.ThingsService/CanAccess", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *thingsServiceClient) Identify(ctx context.Context, in *Token, opts ...grpc.CallOption) (*ThingID, error) {
out := new(ThingID)
err := c.cc.Invoke(ctx, "/mainflux.ThingsService/Identify", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ThingsServiceServer is the server API for ThingsService service.
type ThingsServiceServer interface {
CanAccess(context.Context, *AccessReq) (*ThingID, error)
Identify(context.Context, *Token) (*ThingID, error)
}
func RegisterThingsServiceServer(s *grpc.Server, srv ThingsServiceServer) {
s.RegisterService(&_ThingsService_serviceDesc, srv)
}
func _ThingsService_CanAccess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AccessReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ThingsServiceServer).CanAccess(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mainflux.ThingsService/CanAccess",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ThingsServiceServer).CanAccess(ctx, req.(*AccessReq))
}
return interceptor(ctx, in, info, handler)
}
func _ThingsService_Identify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Token)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ThingsServiceServer).Identify(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mainflux.ThingsService/Identify",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ThingsServiceServer).Identify(ctx, req.(*Token))
}
return interceptor(ctx, in, info, handler)
}
var _ThingsService_serviceDesc = grpc.ServiceDesc{
ServiceName: "mainflux.ThingsService",
HandlerType: (*ThingsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CanAccess",
Handler: _ThingsService_CanAccess_Handler,
},
{
MethodName: "Identify",
Handler: _ThingsService_Identify_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "internal.proto",
}
// UsersServiceClient is the client API for UsersService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type UsersServiceClient interface {
Identify(ctx context.Context, in *Token, opts ...grpc.CallOption) (*UserID, error)
}
type usersServiceClient struct {
cc *grpc.ClientConn
}
func NewUsersServiceClient(cc *grpc.ClientConn) UsersServiceClient {
return &usersServiceClient{cc}
}
func (c *usersServiceClient) Identify(ctx context.Context, in *Token, opts ...grpc.CallOption) (*UserID, error) {
out := new(UserID)
err := c.cc.Invoke(ctx, "/mainflux.UsersService/Identify", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// UsersServiceServer is the server API for UsersService service.
type UsersServiceServer interface {
Identify(context.Context, *Token) (*UserID, error)
}
func RegisterUsersServiceServer(s *grpc.Server, srv UsersServiceServer) {
s.RegisterService(&_UsersService_serviceDesc, srv)
}
func _UsersService_Identify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Token)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UsersServiceServer).Identify(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mainflux.UsersService/Identify",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UsersServiceServer).Identify(ctx, req.(*Token))
}
return interceptor(ctx, in, info, handler)
}
var _UsersService_serviceDesc = grpc.ServiceDesc{
ServiceName: "mainflux.UsersService",
HandlerType: (*UsersServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Identify",
Handler: _UsersService_Identify_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "internal.proto",
}
func init() { proto.RegisterFile("internal.proto", fileDescriptor_internal_50ed0f35f4250621) }
var fileDescriptor_internal_50ed0f35f4250621 = []byte{
// 231 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xcc, 0x2b, 0x49,
0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xc8, 0x4d, 0xcc, 0xcc,
0x4b, 0xcb, 0x29, 0xad, 0x50, 0xb2, 0xe4, 0xe2, 0x74, 0x4c, 0x4e, 0x4e, 0x2d, 0x2e, 0x0e, 0x4a,
0x2d, 0x14, 0x12, 0xe1, 0x62, 0x2d, 0xc9, 0xcf, 0x4e, 0xcd, 0x93, 0x60, 0x54, 0x60, 0xd4, 0xe0,
0x0c, 0x82, 0x70, 0x84, 0xc4, 0xb8, 0xd8, 0x92, 0x33, 0x12, 0xf3, 0x3c, 0x5d, 0x24, 0x98, 0x14,
0x18, 0x35, 0x58, 0x82, 0xa0, 0x3c, 0x25, 0x79, 0x2e, 0xf6, 0x90, 0x8c, 0xcc, 0xbc, 0x74, 0x4f,
0x17, 0x90, 0xc6, 0xb2, 0xc4, 0x9c, 0xd2, 0x54, 0xb0, 0x46, 0x96, 0x20, 0x08, 0x47, 0x49, 0x96,
0x8b, 0x35, 0x04, 0x6c, 0x02, 0x8a, 0x34, 0x27, 0x4c, 0x5a, 0x8e, 0x8b, 0x2d, 0xb4, 0x38, 0xb5,
0x08, 0x5d, 0x3b, 0x4c, 0xde, 0xa8, 0x82, 0x8b, 0x17, 0x6c, 0x7e, 0x71, 0x70, 0x6a, 0x51, 0x59,
0x66, 0x72, 0xaa, 0x90, 0x29, 0x17, 0xa7, 0x73, 0x62, 0x1e, 0xc4, 0xb9, 0x42, 0xc2, 0x7a, 0x30,
0x3f, 0xe8, 0xc1, 0x3d, 0x20, 0x25, 0x88, 0x10, 0x84, 0x3a, 0x4d, 0x89, 0x41, 0xc8, 0x80, 0x8b,
0xc3, 0x33, 0x25, 0x35, 0xaf, 0x24, 0x33, 0xad, 0x52, 0x88, 0x1f, 0x49, 0x01, 0xc8, 0x69, 0x58,
0x75, 0x18, 0xd9, 0x73, 0xf1, 0x80, 0x5c, 0x06, 0xb7, 0x58, 0x1f, 0x9f, 0x09, 0x02, 0x08, 0x01,
0x88, 0x77, 0x94, 0x18, 0x92, 0xd8, 0xc0, 0xc1, 0x6c, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x2f,
0xbc, 0xec, 0x14, 0x78, 0x01, 0x00, 0x00,
}

Some files were not shown because too many files have changed in this diff Show More