commit
9e584d1114
3 changed files with 93 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||||
|
FROM python:3.10 |
||||
|
RUN pip install fastapi uvicorn |
||||
|
WORKDIR /app |
||||
|
COPY server.py /app/ |
||||
|
ENTRYPOINT ["python3", "server.py"] |
@ -0,0 +1,11 @@ |
|||||
|
services: |
||||
|
node_exporter_relay: |
||||
|
build: ./ |
||||
|
environment: |
||||
|
- NEC_HOST=0.0.0.0 |
||||
|
- NEC_PORT=9100 |
||||
|
- DEAD_AFTER=60 |
||||
|
ports: |
||||
|
- 9100:9100 |
||||
|
env_file: |
||||
|
- .env |
@ -0,0 +1,77 @@ |
|||||
|
from fastapi import FastAPI |
||||
|
from fastapi import Request |
||||
|
from fastapi.responses import Response |
||||
|
from fastapi import BackgroundTasks |
||||
|
import uvicorn |
||||
|
import os |
||||
|
from time import time |
||||
|
import asyncio |
||||
|
|
||||
|
class Collector: |
||||
|
app = FastAPI() |
||||
|
secrets = [] |
||||
|
hosts = [] |
||||
|
store = {} |
||||
|
def __init__(self) -> None: |
||||
|
self.secrets = os.getenv("KEYS", "secret").split(",") |
||||
|
self.hosts = os.getenv("HOSTS", "srv").split(",") |
||||
|
self.dead_after = int(os.getenv("DEAD_AFTER", "60")) |
||||
|
self.build_routes() |
||||
|
|
||||
|
def check_headers(self, request: Request): |
||||
|
if not request.headers.get("Secret", ""): |
||||
|
print("secret empty") |
||||
|
return Response(status_code=400) |
||||
|
if not request.headers.get("Host", ""): |
||||
|
print("host empty") |
||||
|
return Response(status_code=400) |
||||
|
|
||||
|
if not request.headers.get("Secret", "") in self.secrets: |
||||
|
return Response(status_code=400) |
||||
|
|
||||
|
if not request.headers.get("Host", "").split(":")[0] in self.hosts: |
||||
|
print(request.headers.get("Host", "")) |
||||
|
print(request.headers) |
||||
|
return Response(status_code=400) |
||||
|
|
||||
|
return None |
||||
|
|
||||
|
async def deadline(self, host): |
||||
|
await asyncio.sleep(self.dead_after) |
||||
|
if host in self.store: |
||||
|
if time()+1 - self.store[host]['timestamp'] > self.dead_after: |
||||
|
print(f"{host} is dead") |
||||
|
del self.store[host] |
||||
|
|
||||
|
|
||||
|
def build_routes(self): |
||||
|
@self.app.get("/metrics") |
||||
|
async def get(request: Request): |
||||
|
response: Response = self.check_headers(request) |
||||
|
if response: |
||||
|
return response |
||||
|
|
||||
|
if request.headers.get("Host", "").split(":")[0] in self.store and self.store[request.headers.get("Host", "").split(":")[0]]['data']: |
||||
|
return Response(content=self.store[request.headers.get("Host", "").split(":")[0]]['data'], status_code=200) |
||||
|
else: |
||||
|
return Response(status_code=404) |
||||
|
|
||||
|
@self.app.post("/metrics") |
||||
|
async def post(request: Request, background_tasks: BackgroundTasks): |
||||
|
response: Response = self.check_headers(request) |
||||
|
if response: |
||||
|
return response |
||||
|
|
||||
|
host = request.headers.get("Host", "").split(":")[0] |
||||
|
|
||||
|
self.store[host] = { |
||||
|
"data":await request.body(), |
||||
|
"timestamp": time() |
||||
|
} |
||||
|
|
||||
|
background_tasks.add_task(self.deadline, host) |
||||
|
return Response(status_code=200) |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
collector = Collector() |
||||
|
uvicorn.run(collector.app, host = os.getenv("NEC_HOST", "0.0.0.0"), port = int(os.getenv("NEC_PORT", "9100"))) |
Loading…
Reference in new issue