-
Notifications
You must be signed in to change notification settings - Fork 299
Add bloom checking endpoints #1243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from 6 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
4d81312
Add bloom checking endpoints
tomchop 63e8f01
Tweak test
tomchop f7578bc
Remove bloom from logging
tomchop 95e8fb5
Ensure endpoint config is set
tomchop cc39933
Adjust tests
tomchop 48c27ae
Sort imports
tomchop 8a090a7
Formatting
tomchop File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import requests | ||
from fastapi import APIRouter, Depends, HTTPException, Request | ||
from pydantic import BaseModel, ConfigDict | ||
|
||
from core.config.config import yeti_config | ||
|
||
|
||
class BloomSearchRequest(BaseModel): | ||
model_config = ConfigDict(extra="forbid") | ||
values: list[str] | ||
|
||
|
||
class BloomHit(BaseModel): | ||
value: str | ||
hits: list[str] | ||
|
||
|
||
# API endpoints | ||
router = APIRouter() | ||
|
||
BLOOMCHECK_ENDPOINT = yeti_config.get("bloom", "bloomcheck_endpoint") | ||
|
||
def check_bloomcheck_endpoint(): | ||
"""Ensure BLOOMCHECK_ENDPOINT is set.""" | ||
if not BLOOMCHECK_ENDPOINT: | ||
raise HTTPException( | ||
status_code=503, | ||
detail="bloomcheck endpoint not set in config", | ||
) | ||
return BLOOMCHECK_ENDPOINT | ||
|
||
@router.post("/search") | ||
def search( | ||
httpreq: Request, | ||
request: BloomSearchRequest, | ||
bloomcheck_endpoint: str = Depends(check_bloomcheck_endpoint), | ||
) -> list[BloomHit]: | ||
"""Checks the bloomcheck microservice for hits.""" | ||
try: | ||
response = requests.post( | ||
f"{bloomcheck_endpoint}/check", | ||
json={"values": request.values, "filters": []}, | ||
) | ||
except requests.ConnectionError as e: | ||
raise HTTPException( | ||
status_code=503, | ||
detail=f"Error connecting to bloomcheck: {e}", | ||
) | ||
if response.status_code != 200: | ||
raise HTTPException( | ||
status_code=response.status_code, | ||
detail=f"Error fetching bloomcheck: {response.text}", | ||
) | ||
|
||
data = response.json() | ||
if not data: | ||
return [] | ||
return [BloomHit(**hit) for hit in data] | ||
|
||
|
||
@router.post("/search/raw") | ||
async def search_raw( | ||
httpreq: Request, bloomcheck_endpoint: str = Depends(check_bloomcheck_endpoint) | ||
) -> list[BloomHit]: | ||
"""Checks the bloomcheck microservice for hits.""" | ||
values = await httpreq.body() | ||
try: | ||
response = requests.post( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this call synchronous? The fastapi method is async though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. body is async(), so we have to |
||
f"{bloomcheck_endpoint}/check/raw", | ||
data=values, | ||
) | ||
except requests.ConnectionError as e: | ||
raise HTTPException( | ||
status_code=503, | ||
detail=f"Error connecting to bloomcheck: {e}", | ||
) | ||
if response.status_code != 200: | ||
raise HTTPException( | ||
status_code=response.status_code, | ||
detail=f"Error fetching bloomcheck: {response.text}", | ||
) | ||
|
||
data = response.json() | ||
if not data: | ||
return [] | ||
return [BloomHit(**hit) for hit in data] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import unittest | ||
from unittest import mock | ||
|
||
import requests | ||
from fastapi.testclient import TestClient | ||
|
||
from core.schemas.user import UserSensitive | ||
from core.web import webapp | ||
|
||
client = TestClient(webapp.app) | ||
|
||
|
||
class IndicatorTest(unittest.TestCase): | ||
def setUp(self) -> None: | ||
user = UserSensitive(username="test", password="test", enabled=True).save() | ||
apikey = user.create_api_key("default") | ||
token_data = client.post( | ||
"/api/v2/auth/api-token", headers={"x-yeti-apikey": apikey} | ||
).json() | ||
client.headers = {"Authorization": "Bearer " + token_data["access_token"]} | ||
|
||
@mock.patch("core.web.apiv2.bloom.requests.post") | ||
def testConnectionError(self, mock_post) -> None: | ||
mock_post.side_effect = requests.ConnectionError("Connection error") | ||
|
||
response = client.post( | ||
"/api/v2/bloom/search", | ||
json={ | ||
"values": ["test"], | ||
}, | ||
) | ||
data = response.json() | ||
self.assertEqual(response.status_code, 503, data) | ||
self.assertIn("Error connecting to bloomcheck", data["detail"]) | ||
|
||
@mock.patch("core.web.apiv2.bloom.requests.post") | ||
def testBloomCall(self, mock_post) -> None: | ||
mock_response = mock.Mock() | ||
mock_response.status_code = 200 | ||
mock_response.json.return_value = [{"value": "test", "hits": ["fltr"]}] | ||
mock_post.return_value = mock_response | ||
|
||
response = client.post( | ||
"/api/v2/bloom/search", | ||
json={ | ||
"values": ["test"], | ||
}, | ||
) | ||
|
||
data = response.json() | ||
self.assertEqual(response.status_code, 200, data) | ||
self.assertEqual(len(data), 1) | ||
self.assertEqual(data[0]["value"], "test") | ||
|
||
mock_post.assert_called_once_with( | ||
"http://bloomcheck:8100/check", | ||
json={"values": ["test"], "filters": []}, | ||
) | ||
|
||
@mock.patch("core.web.apiv2.bloom.requests.post") | ||
def testBloomCallRaw(self, mock_post) -> None: | ||
mock_response = mock.Mock() | ||
mock_response.status_code = 200 | ||
mock_response.json.return_value = [{"value": "test", "hits": ["fltr"]}] | ||
mock_post.return_value = mock_response | ||
test_body = b"test1\ntest2\ntest3\n" | ||
response = client.post("/api/v2/bloom/search/raw", data=test_body) | ||
|
||
data = response.json() | ||
self.assertEqual(response.status_code, 200, data) | ||
self.assertEqual(len(data), 1) | ||
self.assertEqual(data[0]["value"], "test") | ||
|
||
mock_post.assert_called_once_with( | ||
"http://bloomcheck:8100/check/raw", | ||
data=b"test1\ntest2\ntest3\n", | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit weird to me but if i understand it correctly, the Yeti API server makes an http call to the bloom service (which is separate), to get the status hit/no hit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right! How can I make it less weird?