mirror of
https://github.com/projecthorus/sondehub-infra.git
synced 2025-01-29 15:13:53 +00:00
add reverse predit endpoint
This commit is contained in:
parent
e75988050e
commit
e33d46f1cb
50
predictor.tf
50
predictor.tf
@ -114,6 +114,14 @@ resource "aws_apigatewayv2_route" "predictions" {
|
|||||||
target = "integrations/${aws_apigatewayv2_integration.predictions.id}"
|
target = "integrations/${aws_apigatewayv2_integration.predictions.id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "aws_apigatewayv2_route" "reverse_predictions" {
|
||||||
|
api_id = aws_apigatewayv2_api.main.id
|
||||||
|
api_key_required = false
|
||||||
|
authorization_type = "NONE"
|
||||||
|
route_key = "GET /predictions/reverse"
|
||||||
|
target = "integrations/${aws_apigatewayv2_integration.reverse_predictions.id}"
|
||||||
|
}
|
||||||
|
|
||||||
resource "aws_apigatewayv2_integration" "predictions" {
|
resource "aws_apigatewayv2_integration" "predictions" {
|
||||||
api_id = aws_apigatewayv2_api.main.id
|
api_id = aws_apigatewayv2_api.main.id
|
||||||
connection_type = "INTERNET"
|
connection_type = "INTERNET"
|
||||||
@ -124,12 +132,28 @@ resource "aws_apigatewayv2_integration" "predictions" {
|
|||||||
payload_format_version = "2.0"
|
payload_format_version = "2.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "aws_apigatewayv2_integration" "reverse_predictions" {
|
||||||
|
api_id = aws_apigatewayv2_api.main.id
|
||||||
|
connection_type = "INTERNET"
|
||||||
|
integration_method = "POST"
|
||||||
|
integration_type = "AWS_PROXY"
|
||||||
|
integration_uri = aws_lambda_function.reverse_predictions.arn
|
||||||
|
timeout_milliseconds = 30000
|
||||||
|
payload_format_version = "2.0"
|
||||||
|
}
|
||||||
|
|
||||||
data "archive_file" "predictions" {
|
data "archive_file" "predictions" {
|
||||||
type = "zip"
|
type = "zip"
|
||||||
source_file = "predict/lambda_function.py"
|
source_file = "predict/lambda_function.py"
|
||||||
output_path = "${path.module}/build/predictions.zip"
|
output_path = "${path.module}/build/predictions.zip"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data "archive_file" "reverse_predictions" {
|
||||||
|
type = "zip"
|
||||||
|
source_file = "reverse-predict/lambda_function.py"
|
||||||
|
output_path = "${path.module}/build/reverse-predict.zip"
|
||||||
|
}
|
||||||
|
|
||||||
resource "aws_lambda_function" "predictions" {
|
resource "aws_lambda_function" "predictions" {
|
||||||
function_name = "predictions"
|
function_name = "predictions"
|
||||||
handler = "lambda_function.predict"
|
handler = "lambda_function.predict"
|
||||||
@ -153,3 +177,29 @@ resource "aws_lambda_permission" "predictions" {
|
|||||||
principal = "apigateway.amazonaws.com"
|
principal = "apigateway.amazonaws.com"
|
||||||
source_arn = "arn:aws:execute-api:us-east-1:${data.aws_caller_identity.current.account_id}:${aws_apigatewayv2_api.main.id}/*/*/predictions"
|
source_arn = "arn:aws:execute-api:us-east-1:${data.aws_caller_identity.current.account_id}:${aws_apigatewayv2_api.main.id}/*/*/predictions"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
resource "aws_lambda_function" "reverse_predictions" {
|
||||||
|
function_name = "reverse-predictions"
|
||||||
|
handler = "lambda_function.predict"
|
||||||
|
filename = "${path.module}/build/reverse-predict.zip"
|
||||||
|
source_code_hash = data.archive_file.reverse_predictions.output_base64sha256
|
||||||
|
publish = true
|
||||||
|
memory_size = 128
|
||||||
|
role = aws_iam_role.basic_lambda_role.arn
|
||||||
|
runtime = "python3.9"
|
||||||
|
timeout = 30
|
||||||
|
architectures = ["arm64"]
|
||||||
|
environment {
|
||||||
|
variables = {
|
||||||
|
"ES" = "es.${local.domain_name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "aws_lambda_permission" "reverse_predictions" {
|
||||||
|
action = "lambda:InvokeFunction"
|
||||||
|
function_name = aws_lambda_function.reverse_predictions.arn
|
||||||
|
principal = "apigateway.amazonaws.com"
|
||||||
|
source_arn = "arn:aws:execute-api:us-east-1:${data.aws_caller_identity.current.account_id}:${aws_apigatewayv2_api.main.id}/*/*/predictions/reverse"
|
||||||
|
}
|
||||||
|
|
||||||
|
162
reverse-predict/lambda_function.py
Normal file
162
reverse-predict/lambda_function.py
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import boto3
|
||||||
|
import botocore.credentials
|
||||||
|
from botocore.awsrequest import AWSRequest
|
||||||
|
from botocore.endpoint import URLLib3Session
|
||||||
|
from botocore.auth import SigV4Auth
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
import http.client
|
||||||
|
import math
|
||||||
|
import logging
|
||||||
|
import gzip
|
||||||
|
from io import BytesIO
|
||||||
|
import base64
|
||||||
|
|
||||||
|
HOST = os.getenv("ES")
|
||||||
|
|
||||||
|
|
||||||
|
def predict(event, context):
|
||||||
|
path = "reverse-prediction-*/_search"
|
||||||
|
payload = {
|
||||||
|
"aggs": {
|
||||||
|
"2": {
|
||||||
|
"terms": {
|
||||||
|
"field": "serial.keyword",
|
||||||
|
"order": {
|
||||||
|
"_key": "desc"
|
||||||
|
},
|
||||||
|
"size": 1000
|
||||||
|
},
|
||||||
|
"aggs": {
|
||||||
|
"1": {
|
||||||
|
"top_hits": {
|
||||||
|
"_source": True,
|
||||||
|
"size": 1,
|
||||||
|
"sort": [
|
||||||
|
{
|
||||||
|
"datetime": {
|
||||||
|
"order": "desc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": 0,
|
||||||
|
"stored_fields": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"script_fields": {},
|
||||||
|
"docvalue_fields": [
|
||||||
|
{
|
||||||
|
"field": "datetime",
|
||||||
|
"format": "date_time"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_source": {
|
||||||
|
"excludes": []
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"bool": {
|
||||||
|
"must": [],
|
||||||
|
"filter": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"datetime": {
|
||||||
|
"gte": "now-6h",
|
||||||
|
"lte": "now",
|
||||||
|
"format": "strict_date_optional_time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"should": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"must_not": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if "queryStringParameters" in event:
|
||||||
|
if "vehicles" in event["queryStringParameters"] and event["queryStringParameters"]["vehicles"] != "RS_*;*chase" and event["queryStringParameters"]["vehicles"] != "":
|
||||||
|
for serial in event["queryStringParameters"]["vehicles"].split(","):
|
||||||
|
payload["query"]["bool"]["should"].append(
|
||||||
|
{
|
||||||
|
"match_phrase": {
|
||||||
|
"serial.keyword": serial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# for single sonde allow longer predictions
|
||||||
|
payload['query']['bool']['filter'].pop(0)
|
||||||
|
logging.debug("Start ES Request")
|
||||||
|
results = es_request(payload, path, "GET")
|
||||||
|
logging.debug("Finished ES Request")
|
||||||
|
output = {x['1']['hits']['hits'][0]['_source']['serial']: x['1']['hits']['hits'][0]['_source'] for x in results['aggregations']['2']['buckets']}
|
||||||
|
|
||||||
|
compressed = BytesIO()
|
||||||
|
with gzip.GzipFile(fileobj=compressed, mode='w') as f:
|
||||||
|
json_response = json.dumps(output)
|
||||||
|
f.write(json_response.encode('utf-8'))
|
||||||
|
|
||||||
|
gzippedResponse = compressed.getvalue()
|
||||||
|
return {
|
||||||
|
"body": base64.b64encode(gzippedResponse).decode(),
|
||||||
|
"isBase64Encoded": True,
|
||||||
|
"statusCode": 200,
|
||||||
|
"headers": {
|
||||||
|
"Content-Encoding": "gzip",
|
||||||
|
"content-type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def es_request(payload, path, method):
|
||||||
|
# get aws creds
|
||||||
|
session = boto3.Session()
|
||||||
|
|
||||||
|
params = json.dumps(payload)
|
||||||
|
|
||||||
|
compressed = BytesIO()
|
||||||
|
with gzip.GzipFile(fileobj=compressed, mode='w') as f:
|
||||||
|
f.write(params.encode('utf-8'))
|
||||||
|
params = compressed.getvalue()
|
||||||
|
|
||||||
|
headers = {"Host": HOST, "Content-Type": "application/json",
|
||||||
|
"Content-Encoding": "gzip"}
|
||||||
|
request = AWSRequest(
|
||||||
|
method=method, url=f"https://{HOST}/{path}", data=params, headers=headers
|
||||||
|
)
|
||||||
|
SigV4Auth(boto3.Session().get_credentials(),
|
||||||
|
"es", "us-east-1").add_auth(request)
|
||||||
|
|
||||||
|
session = URLLib3Session()
|
||||||
|
r = session.send(request.prepare())
|
||||||
|
return json.loads(r.text)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# print(get_sondes({"queryStringParameters":{"lat":"-28.22717","lon":"153.82996","distance":"50000"}}, {}))
|
||||||
|
# mode: 6hours
|
||||||
|
# type: positions
|
||||||
|
# format: json
|
||||||
|
# max_positions: 0
|
||||||
|
# position_id: 0
|
||||||
|
# vehicles: RS_*;*chase
|
||||||
|
print(predict(
|
||||||
|
{"queryStringParameters": {
|
||||||
|
"vehicles": ""
|
||||||
|
}}, {}
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
# get list of sondes, serial, lat,lon, alt
|
||||||
|
# and current rate
|
||||||
|
# for each one, request http://predict.cusf.co.uk/api/v1/?launch_latitude=-37.8136&launch_longitude=144.9631&launch_datetime=2021-02-22T00:15:18.513413Z&launch_altitude=30000&ascent_rate=5&burst_altitude=30000.1&descent_rate=5
|
||||||
|
# have to set the burst alt slightly higher than the launch
|
81
vpc.tf
Normal file
81
vpc.tf
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
resource "aws_vpc" "main" {
|
||||||
|
cidr_block = "172.31.0.0/16"
|
||||||
|
assign_generated_ipv6_cidr_block = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_egress_only_internet_gateway" "main" {
|
||||||
|
vpc_id = aws_vpc.main.id
|
||||||
|
}
|
||||||
|
|
||||||
|
locals {
|
||||||
|
private_subnets = {
|
||||||
|
"us-east-1a"= "172.31.128.0/24",
|
||||||
|
"us-east-1b"= "172.31.131.0/24",
|
||||||
|
"us-east-1c"= "172.31.130.0/24",
|
||||||
|
"us-east-1d"= "172.31.133.0/24",
|
||||||
|
"us-east-1e"= "172.31.129.0/24",
|
||||||
|
"us-east-1f"= "172.31.132.0/24"
|
||||||
|
}
|
||||||
|
public_subnets = {
|
||||||
|
"us-east-1a"= "172.31.80.0/20",
|
||||||
|
"us-east-1b"= "172.31.16.0/20",
|
||||||
|
"us-east-1c"= "172.31.32.0/20",
|
||||||
|
"us-east-1d"= "172.31.0.0/20",
|
||||||
|
"us-east-1e"= "172.31.48.0/20",
|
||||||
|
"us-east-1f"= "172.31.64.0/20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "aws_subnet" "private" {
|
||||||
|
for_each = local.private_subnets
|
||||||
|
|
||||||
|
map_public_ip_on_launch = false
|
||||||
|
vpc_id = aws_vpc.main.id
|
||||||
|
cidr_block = each.value
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${each.key} - private"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_subnet" "public" {
|
||||||
|
for_each = local.public_subnets
|
||||||
|
|
||||||
|
map_public_ip_on_launch = false
|
||||||
|
vpc_id = aws_vpc.main.id
|
||||||
|
cidr_block = each.value
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${each.key} - public"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route_table" "main" {
|
||||||
|
vpc_id = aws_vpc.main.id
|
||||||
|
}
|
||||||
|
resource "aws_route_table_association" "public" {
|
||||||
|
for_each = local.public_subnets
|
||||||
|
subnet_id = aws_subnet.public[each.key].id
|
||||||
|
route_table_id = aws_route_table.main.id
|
||||||
|
}
|
||||||
|
resource "aws_route_table_association" "private" {
|
||||||
|
for_each = local.private_subnets
|
||||||
|
subnet_id = aws_subnet.private[each.key].id
|
||||||
|
route_table_id = aws_route_table.main.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_internet_gateway" "gw" {
|
||||||
|
vpc_id = aws_vpc.main.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route" "main6" {
|
||||||
|
route_table_id = aws_route_table.main.id
|
||||||
|
destination_ipv6_cidr_block = "::/0"
|
||||||
|
egress_only_gateway_id = aws_egress_only_internet_gateway.main.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route" "main" {
|
||||||
|
route_table_id = aws_route_table.main.id
|
||||||
|
destination_cidr_block = "0.0.0.0/0"
|
||||||
|
gateway_id = aws_internet_gateway.gw.id
|
||||||
|
}
|
@ -62,4 +62,10 @@ resource "aws_apigatewayv2_integration" "sign_socket" {
|
|||||||
|
|
||||||
|
|
||||||
# TODO subnet for reader
|
# TODO subnet for reader
|
||||||
# padding interfaces
|
# ecr
|
||||||
|
# padding interfaces
|
||||||
|
# service, reader, writer
|
||||||
|
# task definition
|
||||||
|
# s3 config bucket
|
||||||
|
# iam roles
|
||||||
|
# reader autoscaling
|
||||||
|
Loading…
x
Reference in New Issue
Block a user