Skip to content

Commit

Permalink
Merge pull request #46 from spectriclabs/feat-pydantic-params
Browse files Browse the repository at this point in the history
Update dependancies and clear CVE's
  • Loading branch information
desean1625 authored Dec 20, 2023
2 parents becfc4f + e8957eb commit caa1168
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 18 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ COPY elastic_datashader /build/elastic_datashader
WORKDIR /build/elastic_datashader
RUN poetry build

FROM python:3.11 AS deployment
FROM python:3.11-slim AS deployment
LABEL maintainer="[email protected]"
RUN useradd -d /home/datashader datashader && \
mkdir -p /home/datashader /opt/elastic_datashader/tms-cache && \
Expand All @@ -23,8 +23,8 @@ COPY --from=builder /build/dist/*.whl /home/datashader/tmp/
ENV PATH="$PATH:/home/datashader/.local/bin"
RUN pip install --upgrade pip && \
pip install --no-cache-dir /home/datashader/tmp/*.whl && \
pip install gunicorn==20.1.0 && \
pip install uvicorn==0.22.0
pip install gunicorn==21.2.0 && \
pip install uvicorn==0.24.0

COPY deployment/logging_config.yml /opt/elastic_datashader/
COPY deployment/gunicorn_config.py /opt/elastic_datashader/
Expand Down
15 changes: 14 additions & 1 deletion elastic_datashader/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from asyncio import create_task

from fastapi import FastAPI

from fastapi.middleware.cors import CORSMiddleware
import urllib3

from .cache import background_cache_cleanup
Expand Down Expand Up @@ -30,6 +30,19 @@
app.include_router(legend.router)
app.include_router(tms.router)




origins = ["*"]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

@app.on_event("startup")
async def app_startup():
create_task(background_cache_cleanup())
18 changes: 17 additions & 1 deletion elastic_datashader/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@
from .logger import logger
from .timeutil import quantize_time_range, convert_kibana_time

from pydantic import BaseModel, Field

class SearchParams(BaseModel):
geopoint_field: str
params: dict
cmap: str = Field(default="bym")
resolution:str = Field(default="finest")
span_range:str = Field(default="auto", alias='span')
spread:str = Field(default="auto") # Point Size
timeOverlap:bool = Field(default=False)
timeOverlapSize:str = Field(default="auto")
timestamp_field:str = Field(default="@timestamp")
search_nautical_miles: int = Field(default=50)
geofield_type: str = Field(default='geo_point')
bucket_max: float = Field(default=100, ge=0, le=100)
bucket_min: float = Field(default=0, ge=0, le=1)

def create_default_params() -> Dict[str, Any]:
return {
Expand Down Expand Up @@ -287,7 +303,7 @@ def extract_parameters(headers: Dict[Any, Any], query_params: Dict[Any, Any]) ->
params["highlight"] = query_params.get("highlight")
params["spread"] = normalize_spread(query_params.get("spread"))
params["resolution"] = query_params.get("resolution", params["resolution"])
params["use_centroid"] = query_params.get("use_centroid", default=params["use_centroid"])
params["use_centroid"] = query_params.get("use_centroid", params["use_centroid"])
params["cmap"] = get_cmap(query_params.get("cmap", None), category_field)
params["span_range"] = query_params.get("span", "auto")
params["geopoint_field"] = query_params.get("geopoint_field", params["geopoint_field"])
Expand Down
30 changes: 24 additions & 6 deletions elastic_datashader/routers/tms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from typing import Optional
import time
import uuid
import json
from elasticsearch import Elasticsearch
from elasticsearch.exceptions import NotFoundError
from elasticsearch_dsl import Document
from fastapi import APIRouter, BackgroundTasks, HTTPException, Request, Response
from fastapi.responses import RedirectResponse
from fastapi.responses import RedirectResponse, JSONResponse
from starlette.datastructures import URL

from ..cache import (
Expand All @@ -26,7 +27,7 @@
from ..drawing import generate_x_tile
from ..elastic import get_es_headers, get_search_base
from ..logger import logger
from ..parameters import extract_parameters, merge_generated_parameters
from ..parameters import extract_parameters, merge_generated_parameters, SearchParams
from ..tilegen import (
TILE_HEIGHT_PX,
TILE_WIDTH_PX,
Expand Down Expand Up @@ -148,8 +149,8 @@ def cached_response(es, idx, x, y, z, params, parameter_hash) -> Optional[Respon

try:
es.update( # pylint: disable=E1123
".datashader_tiles",
tile_id(idx, x, y, z, parameter_hash),
index=".datashader_tiles",
id=tile_id(idx, x, y, z, parameter_hash),
body={"script" : {"source": "ctx._source.cache_hits++"}},
retry_on_conflict=5,
)
Expand Down Expand Up @@ -281,7 +282,7 @@ def generate_tile_to_cache(idx: str, x: int, y: int, z: int, params, parameter_h
logger.debug("Releasing cache placeholder %s", rendering_tile_name(idx, x, y, z, parameter_hash))
release_cache_placeholder(config.cache_path, rendering_tile_name(idx, x, y, z, parameter_hash))

async def fetch_or_render_tile(already_waited: int, idx: str, x: int, y: int, z: int, request: Request, background_tasks: BackgroundTasks):
async def fetch_or_render_tile(already_waited: int, idx: str, x: int, y: int, z: int, request: Request, background_tasks: BackgroundTasks,post_params={}):
check_proxy_key(request.headers.get('tms-proxy-key'))

es = Elasticsearch(
Expand All @@ -292,7 +293,9 @@ async def fetch_or_render_tile(already_waited: int, idx: str, x: int, y: int, z:

# Get hash and parameters
try:
parameter_hash, params = extract_parameters(request.headers, request.query_params)
print(request.query_params)
print(post_params)
parameter_hash, params = extract_parameters(request.headers, {**request.query_params,**post_params})
# try to build the dsl object bad filters cause exceptions that are then retried.
# underlying elasticsearch_dsl doesn't support the elasticsearch 8 api yet so this causes requests to thrash
# If the filters are bad or elasticsearch_dsl cannot build the request will never be completed so serve X tile
Expand Down Expand Up @@ -344,3 +347,18 @@ async def get_tms(idx: str, x: int, y: int, z: int, request: Request, background
@router.get("/{already_waited}/{idx}/{z}/{x}/{y}.png")
async def get_tms_after_wait(already_waited: int, idx: str, x: int, y: int, z: int, request: Request, background_tasks: BackgroundTasks):
return await fetch_or_render_tile(already_waited, idx, x, y, z, request, background_tasks)


@router.post("/{idx}/{z}/{x}/{y}.png")
async def post_tile(already_waited: int,idx: str, x: int, y: int, z: int, request: Request,params: SearchParams, background_tasks: BackgroundTasks):
params = params.dict()
params["params"] = json.dumps(params["params"])
response = await fetch_or_render_tile(0, idx, x, y, z, request, background_tasks,post_params=params)
if isinstance(response,RedirectResponse):
print(response.headers)
return JSONResponse(status_code=200, content={"retry-after":response.headers['retry-after']})
return response




4 changes: 2 additions & 2 deletions elastic_datashader/tilegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ def generate_tile(idx, x, y, z, headers, params, tile_width_px=256, tile_height_

# Create base search
base_s = get_search_base(config.elastic_hosts, headers, params, idx)
base_s = base_s[0:0]
#base_s = base_s[0:0]
# Now find out how many documents
count_s = copy.copy(base_s)[0:0] # slice of array sets from/size since we are aggregating the data we don't need the hits
count_s = count_s.filter("geo_bounding_box", **{geopoint_field: bb_dict})
Expand Down Expand Up @@ -1023,7 +1023,7 @@ def generate_tile(idx, x, y, z, headers, params, tile_width_px=256, tile_height_
geotile_precision = min(max(current_zoom, current_zoom + agg_zooms), MAXIMUM_PERCISION)

tile_s = copy.copy(base_s)
tile_s = tile_s.params(size=0, track_total_hits=False)
tile_s = tile_s.params(track_total_hits=False)
tile_s = tile_s.filter(
"geo_bounding_box", **{geopoint_field: bb_dict}
)
Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ elastic_datashader = "elastic_datashader.cli:main"

[tool.poetry.dependencies]
python = ">=3.10,<4"
elasticsearch = "7.17.4"
elasticsearch-dsl = "7.4.0"
datashader = "0.15.2"
elasticsearch = "8.11.1"
elasticsearch-dsl = "8.11.0"
datashader = "0.16.0"
pandas = "^1.5.3"
colorcet = "^3.0.1"
mercantile = "1.2.1"
Expand All @@ -32,11 +32,11 @@ Pillow = "*"
pynumeral = "*"
arrow = "*"
python-datemath = "*"
numba = "0.57.0"
numba = "0.57.1"
numpy = "^1.23"
PyYAML = "*"
humanize = "*"
uvicorn = {extras = ["standard"], version = "^0.18.2", optional = true}
uvicorn = {extras = ["standard"], version = "0.24.0", optional = true}
fastapi = "^0.96"
georgio = "2023.156.924"
jinja2 = "3.1.2"
Expand Down

0 comments on commit caa1168

Please sign in to comment.