Inital Commit
This commit is contained in:
commit
0203e73cd1
4
.flake8
Normal file
4
.flake8
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[flake8]
|
||||||
|
ignore = E203, W503, E501
|
||||||
|
max-line-length = 120
|
||||||
|
exclude = .git,__pycache__,__init__.py,.mypy_cache,.pytest_cache
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*.pyc
|
||||||
|
*/__pycache__/
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
poetry.lock
|
29
.pre-commit-config.yaml
Normal file
29
.pre-commit-config.yaml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 23.3.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 6.0.0
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
args: ['--config=brewman/.flake8']
|
||||||
|
|
||||||
|
- repo: https://github.com/timothycrosley/isort
|
||||||
|
rev: 5.12.0
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
additional_dependencies: [toml]
|
||||||
|
exclude: ^.*/?setup\.py$
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.3.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: debug-statements
|
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python: FastAPI",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "gru",
|
||||||
|
"args": [],
|
||||||
|
"justMyCode": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"python.defaultInterpreterPath": "/home/tanshu/.cache/pypoetry/virtualenvs/gru-uwCeNnAP-py3.11/bin/python",
|
||||||
|
"files.exclude": {
|
||||||
|
"**/__pycache__": true,
|
||||||
|
"**/.mypy_cache": true,
|
||||||
|
".idea": true,
|
||||||
|
"**/node_modules": true,
|
||||||
|
},
|
||||||
|
"search.exclude": {
|
||||||
|
"**/__pycache__": true,
|
||||||
|
"**/.mypy_cache": true,
|
||||||
|
".idea": true,
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/package-lock.json": true,
|
||||||
|
}
|
||||||
|
}
|
4
CHANGES.md
Normal file
4
CHANGES.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
0.0
|
||||||
|
---
|
||||||
|
|
||||||
|
- Initial version
|
21
README.md
Normal file
21
README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
## Prettier - to format typescript files
|
||||||
|
```npx prettier --write src/app/```
|
||||||
|
|
||||||
|
## Eslint - to lint typescript files
|
||||||
|
```shell script
|
||||||
|
eslint src/app/
|
||||||
|
```
|
||||||
|
Optional to fix the errors as well
|
||||||
|
```
|
||||||
|
eslint src/app/ --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### Poerty remove environment
|
||||||
|
```sh
|
||||||
|
rm -rf `poetry env info -p`
|
||||||
|
```
|
||||||
|
|
||||||
|
### Poerty install
|
||||||
|
```sh
|
||||||
|
poetry install
|
||||||
|
```
|
31
deploy.sh
Executable file
31
deploy.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P )
|
||||||
|
cd "$parent_path" || exit
|
||||||
|
|
||||||
|
#./lint.sh
|
||||||
|
|
||||||
|
# if [ 1 -eq "$#" ]
|
||||||
|
# then
|
||||||
|
# ./version_bump.sh "$1"
|
||||||
|
# else
|
||||||
|
# ./version_bump.sh
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# Download the package.json for caching
|
||||||
|
curl --silent 'https://git.tanshu.com/tanshu/gru/raw/tag/latest/pyproject.toml' \
|
||||||
|
| sed 's/version = \"[0-9\.]*\"/version = "0.0.0"/g' \
|
||||||
|
> "$parent_path/docker/app/pyproject.toml"
|
||||||
|
|
||||||
|
|
||||||
|
cd "$parent_path/docker/app" || exit
|
||||||
|
docker build --tag gru:latest .
|
||||||
|
if [ 1 -eq "$#" ]
|
||||||
|
then
|
||||||
|
docker tag gru:latest "$1"
|
||||||
|
else
|
||||||
|
echo "No version bump"
|
||||||
|
fi
|
||||||
|
cd "$parent_path/docker" || exit
|
||||||
|
docker save gru:latest | bzip2 | pv | ssh beacon 'bunzip2 | sudo docker load'
|
||||||
|
ansible-playbook --limit=beacon playbook.yml
|
2
docker/.gitignore
vendored
Normal file
2
docker/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
app/package.json
|
||||||
|
app/pyproject.toml
|
23
docker/app/Dockerfile
Normal file
23
docker/app/Dockerfile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
FROM python:3.11
|
||||||
|
LABEL maintainer="Amritanshu <docker@tanshu.com>"
|
||||||
|
|
||||||
|
ADD https://git.tanshu.com/api/v1/repos/tanshu/gru/tags /tags.json
|
||||||
|
RUN git clone --single-branch --depth 1 --branch latest https://git.tanshu.com/tanshu/gru.git /app
|
||||||
|
|
||||||
|
# Install Poetry
|
||||||
|
RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | POETRY_HOME=/opt/poetry python && \
|
||||||
|
cd /usr/local/bin && \
|
||||||
|
ln -s /opt/poetry/bin/poetry && \
|
||||||
|
poetry config virtualenvs.create false
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Allow installing dev dependencies to run tests
|
||||||
|
ARG INSTALL_DEV=false
|
||||||
|
RUN bash -c "if [ $INSTALL_DEV == 'true' ] ; then poetry install --no-root ; else poetry install --no-root --only main ; fi"
|
||||||
|
|
||||||
|
ENV PYTHONPATH=/app
|
||||||
|
EXPOSE 80
|
||||||
|
VOLUME /data
|
||||||
|
|
||||||
|
CMD ["poetry", "run", "python", "-m", "gru"]
|
3
docker/files/.env
Normal file
3
docker/files/.env
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=80
|
||||||
|
FILE_PATH=/data/readings.csv
|
13
docker/files/nginx.conf.j2
Normal file
13
docker/files/nginx.conf.j2
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
server {
|
||||||
|
|
||||||
|
listen 80;
|
||||||
|
server_name {{ http_host }};
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_set_header Host $host:$server_port;
|
||||||
|
proxy_set_header X-Scheme $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
proxy_pass http://localhost:{{ host_port }};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
75
docker/playbook.yml
Executable file
75
docker/playbook.yml
Executable file
@ -0,0 +1,75 @@
|
|||||||
|
#################################################
|
||||||
|
# DO Community Playbooks: Docker
|
||||||
|
#################################################
|
||||||
|
---
|
||||||
|
- hosts: gru
|
||||||
|
become: true
|
||||||
|
vars_files:
|
||||||
|
- "vars/gru.yml"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Copy dockerfile
|
||||||
|
synchronize:
|
||||||
|
src: app
|
||||||
|
dest: "/tmp/{{ host_directory }}"
|
||||||
|
|
||||||
|
- name: Build gru image
|
||||||
|
docker_image:
|
||||||
|
name: brewman:latest
|
||||||
|
build:
|
||||||
|
path: "/tmp/{{ host_directory }}/"
|
||||||
|
dockerfile: "/tmp/{{ host_directory }}/Dockerfile"
|
||||||
|
pull: yes
|
||||||
|
state: present
|
||||||
|
source: build
|
||||||
|
|
||||||
|
- name: Ensure Host Directory exists
|
||||||
|
file:
|
||||||
|
path: "/var/lib/{{ host_directory }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Upload the .env file
|
||||||
|
template:
|
||||||
|
src: "{{ env_file }}"
|
||||||
|
dest: "/var/lib/{{ host_directory }}/.env"
|
||||||
|
|
||||||
|
- name: Create gru container
|
||||||
|
docker_container:
|
||||||
|
name: "{{ host_directory }}"
|
||||||
|
image: gru:latest
|
||||||
|
state: started
|
||||||
|
restart_policy: "unless-stopped"
|
||||||
|
env_file: "/var/lib/{{ host_directory }}/.env"
|
||||||
|
published_ports:
|
||||||
|
- "127.0.0.1:{{ host_port }}:80"
|
||||||
|
volumes:
|
||||||
|
- "/var/lib/{{ host_directory }}:/data"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Check if Nginx conf file exists
|
||||||
|
stat: path="/etc/nginx/sites-available/{{ http_conf }}"
|
||||||
|
register: status
|
||||||
|
|
||||||
|
- name: No need to reload Nginx
|
||||||
|
debug: msg= {{ "No need to reload Nginx as sites-available entries have already been created" }}
|
||||||
|
|
||||||
|
- name: Set Nginx conf file
|
||||||
|
when: status.stat.exists == false
|
||||||
|
template:
|
||||||
|
src: "files/nginx.conf.j2"
|
||||||
|
dest: "/etc/nginx/sites-available/{{ http_conf }}"
|
||||||
|
|
||||||
|
- name: Enable new site
|
||||||
|
when: status.stat.exists == false
|
||||||
|
file:
|
||||||
|
src: "/etc/nginx/sites-available/{{ http_conf }}"
|
||||||
|
dest: "/etc/nginx/sites-enabled/{{ http_conf }}"
|
||||||
|
state: link
|
||||||
|
notify: Reload Nginx
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Reload Nginx
|
||||||
|
service:
|
||||||
|
name: nginx
|
||||||
|
state: reloaded
|
||||||
|
|
6
docker/vars/gru.yml
Normal file
6
docker/vars/gru.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
http_host: "sensors.tanshu.com"
|
||||||
|
http_conf: "sensors.tanshu.com.conf"
|
||||||
|
host_port: "8745"
|
||||||
|
host_directory: "sensors"
|
||||||
|
env_file: "files/.env"
|
0
gru/__init__.py
Normal file
0
gru/__init__.py
Normal file
4
gru/__main__.py
Normal file
4
gru/__main__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from gru.main import init
|
||||||
|
|
||||||
|
|
||||||
|
init()
|
19
gru/config.py
Normal file
19
gru/config.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from pydantic import BaseSettings
|
||||||
|
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
# openssl rand -hex 32
|
||||||
|
FILE_PATH: str = "/data/readings.csv"
|
||||||
|
HOST: str = "0.0.0.0"
|
||||||
|
PORT: int = 80
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
case_sensitive = True
|
||||||
|
env_file = ".env"
|
||||||
|
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
settings = Settings()
|
33
gru/main.py
Normal file
33
gru/main.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from typing import Annotated
|
||||||
|
import csv
|
||||||
|
import uvicorn
|
||||||
|
import datetime
|
||||||
|
from fastapi import FastAPI, Form
|
||||||
|
|
||||||
|
from .core.config import settings
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
class Reading(BaseModel):
|
||||||
|
temperature: float
|
||||||
|
humidity: float
|
||||||
|
age: int
|
||||||
|
|
||||||
|
@app.post("/upload", response_model=Reading)
|
||||||
|
def add_reading(temp: Annotated[float, Form()], humidity: Annotated[float, Form()], age: Annotated[int, Form()], device: Annotated[str, Form()]):
|
||||||
|
current_datetime = datetime.datetime.now()
|
||||||
|
deducted_datetime = current_datetime - datetime.timedelta(milliseconds=age)
|
||||||
|
append_to_csv(settings.FILE_PATH, temp, humidity, deducted_datetime)
|
||||||
|
return Reading(temperature=temp,humidity=humidity,age=age)
|
||||||
|
|
||||||
|
|
||||||
|
def append_to_csv(filename, temperature, humidity, datetime_var):
|
||||||
|
with open(filename, 'a', newline='') as csvfile:
|
||||||
|
writer = csv.writer(csvfile)
|
||||||
|
writer.writerow([temperature, humidity, datetime_var])
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
uvicorn.run(app, host=settings.HOST, port=settings.PORT)
|
10
lint.sh
Executable file
10
lint.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eEu -o pipefail
|
||||||
|
shopt -s extdebug
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P )
|
||||||
|
cd "$parent_path" || exit
|
||||||
|
isort gru
|
||||||
|
black gru
|
||||||
|
flake8 gru
|
77
pyproject.toml
Normal file
77
pyproject.toml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
[tool.poetry]
|
||||||
|
name = "gru"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "Sensor manager."
|
||||||
|
authors = ["tanshu <git@tanshu.com>"]
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.11"
|
||||||
|
uvicorn = {extras = ["standard"], version = "^0.22.0"}
|
||||||
|
fastapi = "^0.99.1"
|
||||||
|
python-jose = {extras = ["cryptography"], version = "^3.3.0"}
|
||||||
|
passlib = {extras = ["bcrypt"], version = "^1.7.4"}
|
||||||
|
python-multipart = "^0.0.6"
|
||||||
|
itsdangerous = "^2.1.2"
|
||||||
|
python-dotenv = "^1.0.0"
|
||||||
|
openpyxl = "^3.1.2"
|
||||||
|
|
||||||
|
[tool.poetry.dev-dependencies]
|
||||||
|
flake8 = "^6.0.0"
|
||||||
|
black = "^23.3.0"
|
||||||
|
ruff = "^0.0.277"
|
||||||
|
pre-commit = "^3.3.3"
|
||||||
|
mypy = "^1.4.1"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
# --strict
|
||||||
|
disallow_any_generics = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
no_implicit_optional = true
|
||||||
|
warn_redundant_casts = true
|
||||||
|
warn_unused_ignores = true
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unused_configs = true
|
||||||
|
strict_equality = true
|
||||||
|
plugins = ["sqlalchemy.ext.mypy.plugin"]
|
||||||
|
# --strict end
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
||||||
|
atomic = true
|
||||||
|
include_trailing_comma = true
|
||||||
|
lines_after_imports = 2
|
||||||
|
lines_between_types = 1
|
||||||
|
use_parentheses = true
|
||||||
|
src_paths = ["poetry", "tests"]
|
||||||
|
skip_glob = ["*/setup.py"]
|
||||||
|
filter_files = true
|
||||||
|
known_first_party = "poetry"
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
||||||
|
include = '\.pyi?$'
|
||||||
|
exclude = '''
|
||||||
|
/(
|
||||||
|
\.eggs
|
||||||
|
| \.git
|
||||||
|
| \.hg
|
||||||
|
| \.mypy_cache
|
||||||
|
| \.tox
|
||||||
|
| \.venv
|
||||||
|
| _build
|
||||||
|
| buck-out
|
||||||
|
| build
|
||||||
|
| dist
|
||||||
|
| tests/.*/setup.py
|
||||||
|
)/
|
||||||
|
'''
|
Loading…
Reference in New Issue
Block a user