未验证 提交 ff30b776 编写于 作者: N Nikita Manovich 提交者: GitHub

Fix serverless functions on Mac (#29)

* Fix serverless functions on Mac. Use host.docker.internal as an alias for localhost.
* Updated the CHANGELOG.md
* Fix unit tests for the lambda manager.
上级 c266a942
......@@ -4,7 +4,7 @@
/share/
/static/
/db.sqlite3
/.env
/.*env*
/keys
/logs
/profiles
......
......@@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- TDB
- Bumped nuclio version to 1.8.14 (<https://github.com/cvat-ai/cvat/pull/29>)
### Deprecated
- TDB
......
......@@ -2,7 +2,7 @@ version: '3.3'
services:
nuclio:
container_name: nuclio
image: quay.io/nuclio/dashboard:1.5.16-amd64
image: quay.io/nuclio/dashboard:1.8.14-amd64
restart: always
networks:
- cvat
......
......@@ -75,66 +75,65 @@ class LambdaTestCase(APITestCase):
def setUp(self):
self.client = APIClient()
patcher = mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', side_effect = self.__get_response_data_from_lambda_gateway_http)
self.addCleanup(patcher.stop)
patcher.start()
http_patcher = mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', side_effect = self.__get_data_from_lambda_manager_http)
self.addCleanup(http_patcher.stop)
http_patcher.start()
invoke_patcher = mock.patch('cvat.apps.lambda_manager.views.LambdaGateway.invoke', side_effect = self.__invoke_function)
self.addCleanup(invoke_patcher.stop)
invoke_patcher.start()
images_main_task = self._generate_task_images(3)
images_assigneed_to_user_task = self._generate_task_images(3)
self.main_task = self._create_task(tasks["main"], images_main_task)
self.assigneed_to_user_task = self._create_task(tasks["assigneed_to_user"], images_assigneed_to_user_task)
def __get_response_data_from_lambda_gateway_http(self, *args, **kwargs):
def __get_data_from_lambda_manager_http(self, **kwargs):
url = kwargs["url"]
# POST query for get annotations
if url == "/api/function_invocations":
data = []
id_function = kwargs["headers"]["x-nuclio-function-name"]
type_function = functions["positive"][id_function]["metadata"]["annotations"]["type"]
if type_function == "reid":
if id_function == id_function_reid_response_data:
data = [0, 1]
else:
data = []
elif type_function == "tracker":
data = {
"shape": [12.34, 34.0, 35.01, 41.99],
"state": {"key": "value"},
}
elif type_function == "interactor":
data = [
[8, 12],
[34, 56],
[77, 77],
]
elif type_function == "detector":
data = [
{'confidence': '0.9959098', 'label': 'car', 'points': [3, 3, 15, 15], 'type': 'rectangle'},
{'confidence': '0.89535173', 'label': 'car', 'points': [20, 25, 30, 35], 'type': 'rectangle'},
{'confidence': '0.59464583', 'label': 'car', 'points': [12.17, 45.0, 69.80, 18.99], 'type': 'polygon'},
]
return data
# GET query for get all functions
elif url == "/api/functions":
if url == "/api/functions":
return functions["positive"]
# GET query for get function
else:
id_function = url.split("/")[-1]
if id_function in functions["positive"]:
# raise 500 Internal_Server error
if id_function in [id_function_state_building, id_function_state_error]:
func_id = url.split("/")[-1]
if func_id in functions["positive"]:
if func_id in [id_function_state_building, id_function_state_error]:
r = requests.RequestException()
r.response = HttpResponseServerError()
raise r
# return values
return functions["positive"][id_function]
# raise 404 Not Found error
raise r # raise 500 Internal_Server error
return functions["positive"][func_id]
else:
r = requests.HTTPError()
r.response = HttpResponseNotFound()
raise r
raise r # raise 404 Not Found error
def __invoke_function(self, func, payload):
data = []
func_id = func.id
type_function = functions["positive"][func_id]["metadata"]["annotations"]["type"]
if type_function == "reid":
if func_id == id_function_reid_response_data:
data = [0, 1]
else:
data = []
elif type_function == "tracker":
data = {
"shape": [12.34, 34.0, 35.01, 41.99],
"state": {"key": "value"},
}
elif type_function == "interactor":
data = [
[8, 12],
[34, 56],
[77, 77],
]
elif type_function == "detector":
data = [
{'confidence': '0.9959098', 'label': 'car', 'points': [3, 3, 15, 15], 'type': 'rectangle'},
{'confidence': '0.89535173', 'label': 'car', 'points': [20, 25, 30, 35], 'type': 'rectangle'},
{'confidence': '0.59464583', 'label': 'car', 'points': [12.17, 45.0, 69.80, 18.99], 'type': 'polygon'},
]
return data
@classmethod
def _create_db_users(cls):
......
......@@ -11,6 +11,7 @@ from copy import deepcopy
import django_rq
import requests
import rq
import os
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from rest_framework import status, viewsets
......@@ -75,17 +76,18 @@ class LambdaGateway:
return response
def invoke(self, func, payload):
# NOTE: it is overhead to invoke a function using nuclio
# dashboard REST API. Better to call host.docker.internal:<port>
# Look at https://github.com/docker/for-linux/issues/264.
# host.docker.internal isn't supported by docker on Linux.
# There are many workarounds but let's try to use the
# simple solution.
return self._http(method="post", url='/api/function_invocations',
data=payload, headers={
'x-nuclio-function-name': func.id,
'x-nuclio-path': '/'
})
# Note: call the function directly without the nuclio dashboard
# host.docker.internal for Linux will work only with Docker 20.10+
NUCLIO_TIMEOUT = settings.NUCLIO['DEFAULT_TIMEOUT']
if os.path.exists('/.dockerenv'): # inside a docker container
url = f'http://host.docker.internal:{func.port}'
else:
url = f'http://localhost:{func.port}'
reply = requests.post(url, timeout=NUCLIO_TIMEOUT, json=payload)
reply.raise_for_status()
response = reply.json()
return response
class LambdaFunction:
def __init__(self, gateway, data):
......
......@@ -52,6 +52,8 @@ services:
- cvat_logs:/home/django/logs
networks:
- cvat
extra_hosts:
- "host.docker.internal:host-gateway"
cvat_ui:
container_name: cvat_ui
......
......@@ -29,7 +29,7 @@ description: 'Information about the installation of components needed for semi-a
```
- You have to install `nuctl` command line tool to build and deploy serverless
functions. Download [version 1.5.16](https://github.com/nuclio/nuclio/releases/tag/1.5.16).
functions. Download [version 1.8.14](https://github.com/nuclio/nuclio/releases/tag/1.8.14).
It is important that the version you download matches the version in
[docker-compose.serverless.yml](https://github.com/openvinotoolkit/cvat/blob/develop/components/serverless/docker-compose.serverless.yml).
For example, using wget.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册