Skip to content

Commit

Permalink
Chore/setup update api v2 (#138)
Browse files Browse the repository at this point in the history
* chore: update Dockerfile and requirements, cleanup settings

* chore: add /env template

* fix: fix error TypeError 'bool' object is not callable

* chore: add Now api endpoint, cleanup router

* chore: update v1 route to only push sensors data, add statistics view

* update: fix push-sensors-url

* update: update NodesView

* update: update NodesView

* Update README docker setup

* update: modify NodeView permissions

* chore: update views docstrings

* chore: modify data stats url

* chore: add .dockerignore file

---------

Co-authored-by: Xavier Frankline <[email protected]>
  • Loading branch information
thepsalmist and thepsalmist authored Nov 14, 2024
1 parent d8d6aba commit 607b559
Show file tree
Hide file tree
Showing 12 changed files with 268 additions and 82 deletions.
77 changes: 77 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Git
.git
.gitignore

# Docker
docker-compose.yml
.docker

# Byte-compiled / optimized / DLL files
__pycache__/
*/__pycache__/
*/*/__pycache__/
*/*/*/__pycache__/
*.py[cod]
*/*.py[cod]
*/*/*.py[cod]
*/*/*/*.py[cod]

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Virtual environment
.env/
.venv/
venv/

# PyCharm
.idea

# Python mode for VIM
.ropeproject
*/.ropeproject
*/*/.ropeproject
*/*/*/.ropeproject

# Vim swap files
*.swp
*/*.swp
*/*/*.swp
*/*/*/*.swp
6 changes: 6 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SENSORSAFRICA_DATABASE_URL=""
SENSORSAFRICA_DEBUG=""
SENSORSAFRICA_FLOWER_ADMIN_PASSWORD=""
SENSORSAFRICA_FLOWER_ADMIN_USERNAME=""
SENSORSAFRICA_RABBITMQ_URL=""
SENSORSAFRICA_SENTRY_DSN=""
23 changes: 10 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,21 @@ FROM python:3.6.3

ENV PYTHONUNBUFFERED 1

# Create root directory for our project in the container
RUN mkdir /src

# Create application subdirectories
# Create application root directory
WORKDIR /src

RUN mkdir media static logs
VOLUME [ "/src/logs" ]

# Copy the current directory contents into the container at sensorsafrica
ADD . /src/

# Upgrade pip and setuptools
RUN pip install -q -U pip setuptools
# Upgrade pip and setuptools with trusted hosts
RUN python -m pip install --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org --upgrade pip setuptools

# Install feinstaub from opendata-stuttgart
RUN pip install -q git+https://github.com/opendata-stuttgart/feinstaub-api
# Copy the current directory contents into the container at sensorsafrica
COPY . /src/

# Install sensors.AFRICA-api and its dependencies
RUN pip install -q -U .
# Install dependencies
RUN pip install -q git+https://github.com/opendata-stuttgart/feinstaub-api && \
pip install -q .

# Expose port server
EXPOSE 8000
Expand All @@ -31,3 +27,4 @@ COPY ./contrib/entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
CMD [ "/start.sh" ]

8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ API to save and access data from deployed sensors in cities all around Africa.

## Documentation

The API is documented [here.](https://github.com/CodeForAfricaLabs/sensors.AFRICA-api/wiki/API-Documentation)
The API is documented [here.](https://github.com/CodeForAfricaLabs/sensors.AFRICA-api/wiki/API-Documentation)

## Development

Expand All @@ -29,11 +29,17 @@ GRANT ALL PRIVILEGES ON DATABASE sensorsafrica TO sensorsafrica;

- Migrate the database; `python manage.py migrate`
- Run the server; `python manage.py runserver`
- Create super user for admin login; `python manage.py createsuperuser`

username: `<username>`
email: blank
password: `<password>`

### Docker

Using docker compose:

- Create a `.env` file using `.env.template` . ***docker-compose has some default values for these variables***
- Build the project; `docker-compose build` or `make build`
- Run the project; `docker-compose up -d` or `make up`

Expand Down
30 changes: 17 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ version: '3.3'

services:
rabbitmq:
image: rabbitmq:3.5.1
image: rabbitmq:3.12.7-management
ports:
- 4369:4369
- 5672:5672
- 25672:25672
- 15672:15672
- "5672:5672"
# GUI port
- "15672:15672"
environment:
- RABBITMQ_USERNAME=sensorsafrica
- RABBITMQ_PASSWORD=sensorsafrica
- RABBITMQ_DEFAULT_USER=sensorsafrica
- RABBITMQ_DEFAULT_PASS=sensorsafrica
healthcheck:
test: [ "CMD-SHELL", "rabbitmq-diagnostics -q ping" ]
interval: 10s
timeout: 5s
retries: 2

postgres:
image: postgres:13.7
ports:
Expand All @@ -25,12 +30,11 @@ services:
build:
context: .
environment:
SENSORSAFRICA_DATABASE_URL: postgres://sensorsafrica:sensorsafrica@postgres:5432/sensorsafrica
SENSORSAFRICA_READ_DATABASE_URLS: postgres://sensorsafrica:sensorsafrica@postgres:5432/sensorsafrica
SENSORSAFRICA_RABBITMQ_URL: amqp://sensorsafrica:sensorsafrica@rabbitmq//
SENSORSAFRICA_FLOWER_ADMIN_USERNAME: admin
SENSORSAFRICA_FLOWER_ADMIN_PASSWORD: password
DOKKU_APP_NAME: sensorsafrica
SENSORSAFRICA_DATABASE_URL: ${SENSORSAFRICA_DATABASE_URL:-postgres://sensorsafrica:sensorsafrica@postgres:5432/sensorsafrica}
SENSORSAFRICA_RABBITMQ_URL: ${SENSORSAFRICA_RABBITMQ_URL:-amqp://sensorsafrica:sensorsafrica@rabbitmq/}
SENSORSAFRICA_FLOWER_ADMIN_USERNAME: ${SENSORSAFRICA_FLOWER_ADMIN_USERNAME:-admin}
SENSORSAFRICA_FLOWER_ADMIN_PASSWORD: ${SENSORSAFRICA_FLOWER_ADMIN_PASSWORD:-password}
DOKKU_APP_NAME: ${DOKKU_APP_NAME:-sensorsafrica}
depends_on:
- postgres
- rabbitmq
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ckanapi==4.1

celery-slack==0.3.0

urllib3<1.25,>=1.21.1 #requests 2.21.0
urllib3<2

django-cors-headers==3.0.2

Expand Down
6 changes: 5 additions & 1 deletion sensorsafrica/api/v1/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from rest_framework import routers

router = routers.DefaultRouter()
router.register(r"push-sensor-data", PostSensorDataView)
router.register(r"node", NodeView)
router.register(r"sensor", SensorView)
router.register(r"data", VerboseSensorDataView)
Expand All @@ -31,3 +30,8 @@
router.register(r"filter", FilterView, basename="filter")

api_urls = router.urls

push_sensor_data_router = routers.DefaultRouter()
push_sensor_data_router.register(r"push-sensor-data", PostSensorDataView)

push_sensor_data_urls = push_sensor_data_router.urls
4 changes: 2 additions & 2 deletions sensorsafrica/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class NodeView(
filter_class = NodeFilter

def get_queryset(self):
if self.request.user.is_authenticated():
if self.request.user.is_authenticated:
if self.request.user.groups.filter(name="show_me_everything").exists():
return Node.objects.all()

Expand Down Expand Up @@ -92,7 +92,7 @@ class PostSensorDataView(mixins.CreateModelMixin,
permission_classes = tuple()
serializer_class = LastNotifySensorDataSerializer
queryset = SensorData.objects.all()


class VerboseSensorDataView(SensorDataView):
filter_class = SensorFilter
Expand Down
42 changes: 14 additions & 28 deletions sensorsafrica/api/v2/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,28 @@
from .views import (
CitiesView,
NodesView,
NowView,
SensorDataStatsView,
SensorDataView,
SensorLocationsView,
SensorTypesView,
SensorsView,
StatisticsView,
meta_data,
)

stat_data_router = routers.DefaultRouter()
stat_data_router.register(r"", SensorDataStatsView)

data_router = routers.DefaultRouter()
data_router.register(r"", SensorDataView)

cities_router = routers.DefaultRouter()
cities_router.register(r"", CitiesView, basename="cities")

nodes_router = routers.DefaultRouter()
nodes_router.register(r"", NodesView, basename="map")

sensors_router = routers.DefaultRouter()
sensors_router.register(r"", SensorsView, basename="sensors")

sensor_locations_router = routers.DefaultRouter()
sensor_locations_router.register(r"", SensorLocationsView, basename="locations")

sensor_types_router = routers.DefaultRouter()
sensor_types_router.register(r"", SensorTypesView, basename="sensor_types")
router = routers.DefaultRouter()
router.register(r"data", SensorDataView, basename="sensor-data")
router.register(r"data/stats/(?P<sensor_type>[air]+)", SensorDataStatsView, basename="sensor-data-stats")
router.register(r"cities", CitiesView, basename="cities")
router.register(r"nodes", NodesView, basename="nodes")
router.register(r"now", NowView, basename="now")
router.register(r"locations", SensorLocationsView, basename="sensor-locations")
router.register(r"sensors", SensorsView, basename="sensors")
router.register(r"sensor-types", SensorTypesView, basename="sensor-types")
router.register(r"statistics", StatisticsView, basename="statistics")

api_urls = [
url(r"data/(?P<sensor_type>[air]+)/", include(stat_data_router.urls)),
url(r"data/", include(data_router.urls)),
url(r"cities/", include(cities_router.urls)),
url(r"nodes/", include(nodes_router.urls)),
url(r"locations/", include(sensor_locations_router.urls)),
url(r"sensors/", include(sensors_router.urls)),
url(r"sensor-types/", include(sensor_types_router.urls)),
url(r"meta/", meta_data),
url(r"^", include(router.urls)),
url(r"^meta/", meta_data),
]
Loading

0 comments on commit 607b559

Please sign in to comment.