Skip to content

[maintenance] black-formatted packages/services and new common.Makefile #1342

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
merged 34 commits into from
Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
595807b
Removed pprint in log
Mar 4, 2020
26f9462
Added extension to bash scripts
Mar 4, 2020
cf58cac
code-climate bash
Mar 4, 2020
ce0e9ac
Changed extension to bash of some of the scripts
Mar 4, 2020
cd567bc
Hints on unhandled exception in socket task
Mar 5, 2020
7f57742
Formatted postgres-database
Mar 6, 2020
b868511
Autoformats servicelib
Mar 6, 2020
343934e
Adds autoformat recipe in Makefiles
Mar 6, 2020
bab5d4f
Formats storage
Mar 6, 2020
081c8a7
Formatted webserver
Mar 6, 2020
e79dc05
Add base makefile
Mar 6, 2020
fc8ae5b
register *Makefile pattern
Mar 6, 2020
4f653ab
Including common.Makefile in service makefiles
Mar 6, 2020
cf4611e
More modifications on Makefiles
Mar 6, 2020
b985942
Merge branch 'master' into maintenance/march4
Mar 6, 2020
d0c1301
Fixes pip3
Mar 6, 2020
2bd8e75
Minor fix to clean
Mar 6, 2020
4959c31
Minor
Mar 6, 2020
c597b78
Fixes hard-coded dev password
Mar 6, 2020
6e84848
Using password generator for get_random_string
Mar 6, 2020
96100bf
Fixes linter error after formatting
Mar 6, 2020
9b10e77
Updates ignores
Mar 6, 2020
f07dbf2
common.Makefile: Added extra variables and fixed help
Mar 6, 2020
3c05464
Minor pylint
Mar 6, 2020
c55ec1a
codeclimate fix: deeply nested control flow
Mar 6, 2020
8b672f4
Fixed CC: deeply nested control flow statements
Mar 6, 2020
9f3ff1d
Fixed CC: Try, Except and Pass
Mar 6, 2020
56908bd
Fixes CC assert
Mar 6, 2020
225da49
Merge branch 'master' into maintenance/march4
Mar 6, 2020
6d8eaf7
Merge branch 'master' into maintenance/march4
pcrespov Mar 9, 2020
8481e7d
Merge branch 'master' into maintenance/march4
Mar 9, 2020
cd3b3af
Merge branch 'maintenance/march4' of github.com:pcrespov/osparc-simco…
Mar 9, 2020
3b0fb09
Merge branch 'master' into maintenance/march4
Mar 9, 2020
14cd212
Adds shell to all services
Mar 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode-template/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"python.testing.pyTestEnabled": true,
"autoDocstring.docstringFormat": "sphinx",
"shellcheck.executablePath": "${workspaceFolder}/scripts/shellcheck",
"shellcheck.executablePath": "${workspaceFolder}/scripts/shellcheck.bash",
"shellcheck.run": "onSave",
"shellcheck.enableQuickFix": true
}
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,9 @@ openapi-specs: ## bundles and validates openapi specifications and schemas of AL
.PHONY: code-analysis
code-analysis: .codeclimate.yml ## runs code-climate analysis
# Validates $<
./scripts/code-climate.sh validate-config
./scripts/code-climate.bash validate-config
# Running analysis
./scripts/code-climate.sh analyze
./scripts/code-climate.bash analyze


.PHONY: info info-images info-swarm info-tools
Expand Down
2 changes: 1 addition & 1 deletion scripts/check_requirements.sh → scripts/check_requirements.bash
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

# lists all python packages used throughout all the repository that are not tied to a specific version

find . \( -name "requirements.txt" -o -name "common.txt" -o -name "devel.txt" -o -name "prod.txt" \) | xargs -I % grep -v "\-r " % | sort |uniq | awk '$0 !~ /==/'
find . \( -name "requirements.txt" -o -name "common.txt" -o -name "devel.txt" -o -name "prod.txt" \) | xargs -I % grep -v "\-r " % | sort |uniq | awk '$0 !~ /==/'
3 changes: 2 additions & 1 deletion scripts/code-climate.sh → scripts/code-climate.bash
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ docker run \
codeclimate/codeclimate "$@"


if [ -z "$@" ];then
if test -z "$@"
then
echo "----"
echo "Listing other engines (in dockers)"
docker images codeclimate/*
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

for path_to_req_test in $(find ../ -type f -name '_test.txt')
do
rm --verbose $path_to_req_test
make --directory $(dirname -- $path_to_req_test)
rm --verbose "$path_to_req_test"
make --directory "$(dirname -- "$path_to_req_test")"
done
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"""
import logging
from asyncio import ensure_future, gather
from pprint import pprint
from pprint import pformat
from typing import Dict, Optional
from uuid import uuid4

Expand All @@ -20,26 +20,31 @@

from ..computation_api import delete_pipeline_db
from ..director import director_api
from ..storage_api import \
copy_data_folders_from_project # mocked in unit-tests
from ..storage_api import (delete_data_folders_of_project,
delete_data_folders_of_project_node)
from ..storage_api import copy_data_folders_from_project # mocked in unit-tests
from ..storage_api import (
delete_data_folders_of_project,
delete_data_folders_of_project_node,
)
from .config import CONFIG_SECTION_NAME
from .projects_db import APP_PROJECT_DBAPI
from .projects_exceptions import NodeNotFoundError, ProjectNotFoundError
from .projects_utils import clone_project_document

log = logging.getLogger(__name__)


def _is_node_dynamic(node_key: str) -> bool:
return "/dynamic/" in node_key


def validate_project(app: web.Application, project: Dict):
project_schema = app[APP_JSONSCHEMA_SPECS_KEY][CONFIG_SECTION_NAME]
validate_instance(project, project_schema) # TODO: handl
validate_instance(project, project_schema) # TODO: handl


async def get_project_for_user(app: web.Application, project_uuid, user_id, *, include_templates=False) -> Dict:
async def get_project_for_user(
app: web.Application, project_uuid:str, user_id:int, *, include_templates: bool=False
) -> Dict:
""" Returns a project accessible to user

:raises web.HTTPNotFound: if no match found
Expand All @@ -66,7 +71,9 @@ async def get_project_for_user(app: web.Application, project_uuid, user_id, *, i
raise web.HTTPNotFound(reason="Project not found")


async def clone_project(request: web.Request, project: Dict, user_id, forced_copy_project_id: str ="") -> Dict:
async def clone_project(
request: web.Request, project: Dict, user_id: int, forced_copy_project_id: str=""
) -> Dict:
"""Clones both document and data folders of a project

- document
Expand All @@ -87,54 +94,86 @@ async def clone_project(request: web.Request, project: Dict, user_id, forced_cop
"""
cloned_project, nodes_map = clone_project_document(project, forced_copy_project_id)

updated_project = await copy_data_folders_from_project(request.app,
project, cloned_project, nodes_map, user_id)
updated_project = await copy_data_folders_from_project(
request.app, project, cloned_project, nodes_map, user_id
)

return updated_project

async def start_project_interactive_services(request: web.Request, project: Dict, user_id: str) -> None:

async def start_project_interactive_services(
request: web.Request, project: Dict, user_id: str
) -> None:
# first get the services if they already exist
log.debug("getting running interactive services of project %s for user %s", project["uuid"], user_id)
running_services = await director_api.get_running_interactive_services(request.app, user_id, project["uuid"])
log.debug(
"getting running interactive services of project %s for user %s",
project["uuid"],
user_id,
)
running_services = await director_api.get_running_interactive_services(
request.app, user_id, project["uuid"]
)
running_service_uuids = [x["service_uuid"] for x in running_services]
# now start them if needed
project_needed_services = {service_uuid:service for service_uuid, service in project["workbench"].items() \
if _is_node_dynamic(service["key"]) and \
service_uuid not in running_service_uuids}

start_service_tasks = [director_api.start_service(request.app,
user_id=user_id,
project_id=project["uuid"],
service_key=service["key"],
service_version=service["version"],
service_uuid=service_uuid) for service_uuid, service in project_needed_services.items()]
project_needed_services = {
service_uuid: service
for service_uuid, service in project["workbench"].items()
if _is_node_dynamic(service["key"])
and service_uuid not in running_service_uuids
}

start_service_tasks = [
director_api.start_service(
request.app,
user_id=user_id,
project_id=project["uuid"],
service_key=service["key"],
service_version=service["version"],
service_uuid=service_uuid,
)
for service_uuid, service in project_needed_services.items()
]
await gather(*start_service_tasks)


async def delete_project(request: web.Request, project_uuid: str, user_id: str) -> None:
async def delete_project(request: web.Request, project_uuid: str, user_id: int) -> None:
await delete_project_from_db(request, project_uuid, user_id)

async def remove_services_and_data():
await remove_project_interactive_services(user_id, project_uuid, request.app)
await delete_project_data(request, project_uuid, user_id)

ensure_future(remove_services_and_data())


@observe(event="SIGNAL_PROJECT_CLOSE")
async def remove_project_interactive_services(user_id: Optional[str], project_uuid: Optional[str], app: web.Application) -> None:
async def remove_project_interactive_services(
user_id: Optional[int], project_uuid: Optional[str], app: web.Application
) -> None:
if not user_id and not project_uuid:
raise ValueError("Expected either user or project")

list_of_services = await director_api.get_running_interactive_services(app,
project_id=project_uuid,
user_id=user_id)
stop_tasks = [director_api.stop_service(app, service["service_uuid"]) for service in list_of_services]
list_of_services = await director_api.get_running_interactive_services(
app, project_id=project_uuid, user_id=user_id
)
stop_tasks = [
director_api.stop_service(app, service["service_uuid"])
for service in list_of_services
]
if stop_tasks:
await gather(*stop_tasks)

async def delete_project_data(request: web.Request, project_uuid: str, user_id: str) -> None:

async def delete_project_data(
request: web.Request, project_uuid: str, user_id: int
) -> None:
# requests storage to delete all project's stored data
await delete_data_folders_of_project(request.app, project_uuid, user_id)

async def delete_project_from_db(request: web.Request, project_uuid: str, user_id: str) -> None:

async def delete_project_from_db(
request: web.Request, project_uuid: str, user_id: int
) -> None:
db = request.config_dict[APP_PROJECT_DBAPI]
try:
await delete_pipeline_db(request.app, project_uuid)
Expand All @@ -146,58 +185,104 @@ async def delete_project_from_db(request: web.Request, project_uuid: str, user_i
# requests storage to delete all project's stored data
await delete_data_folders_of_project(request.app, project_uuid, user_id)

async def add_project_node(request: web.Request, project_uuid: str, user_id: str, service_key: str, service_version: str, service_id: Optional[str]) -> str: # pylint: disable=too-many-arguments
log.debug("starting node %s:%s in project %s for user %s", service_key, service_version, project_uuid, user_id)

async def add_project_node(
request: web.Request,
project_uuid: str,
user_id: int,
service_key: str,
service_version: str,
service_id: Optional[str],
) -> str: # pylint: disable=too-many-arguments
log.debug(
"starting node %s:%s in project %s for user %s",
service_key,
service_version,
project_uuid,
user_id,
)
node_uuid = service_id if service_id else str(uuid4())
if _is_node_dynamic(service_key):
await director_api.start_service(request.app, user_id, project_uuid, service_key, service_version, node_uuid)
await director_api.start_service(
request.app, user_id, project_uuid, service_key, service_version, node_uuid
)
return node_uuid

async def get_project_node(request: web.Request, project_uuid: str, user_id:str, node_id: str):
log.debug("getting node %s in project %s for user %s", node_id, project_uuid, user_id)

list_of_interactive_services = await director_api.get_running_interactive_services(request.app,
project_id=project_uuid,
user_id=user_id)
async def get_project_node(
request: web.Request, project_uuid: str, user_id: int, node_id: str
):
log.debug(
"getting node %s in project %s for user %s", node_id, project_uuid, user_id
)

list_of_interactive_services = await director_api.get_running_interactive_services(
request.app, project_id=project_uuid, user_id=user_id
)
# get the project if it is running
for service in list_of_interactive_services:
if service["service_uuid"] == node_id:
return service
# the service is not running, it's a computational service maybe
# TODO: find out if computational service is running if not throw a 404 since it's not around
return {
"service_uuid": node_id,
"service_state": "idle"
}
return {"service_uuid": node_id, "service_state": "idle"}

async def delete_project_node(request: web.Request, project_uuid: str, user_id: str, node_uuid: str) -> None:
log.debug("deleting node %s in project %s for user %s", node_uuid, project_uuid, user_id)

list_of_services = await director_api.get_running_interactive_services(request.app,
project_id=project_uuid,
user_id=user_id)
async def delete_project_node(
request: web.Request, project_uuid: str, user_id: int, node_uuid: str
) -> None:
log.debug(
"deleting node %s in project %s for user %s", node_uuid, project_uuid, user_id
)

list_of_services = await director_api.get_running_interactive_services(
request.app, project_id=project_uuid, user_id=user_id
)
# stop the service if it is running
for service in list_of_services:
if service["service_uuid"] == node_uuid:
await director_api.stop_service(request.app, node_uuid)
break
# remove its data if any
await delete_data_folders_of_project_node(request.app, project_uuid, node_uuid, user_id)


async def update_project_node_progress(app: web.Application, user_id: str, project_id: str, node_id: str, progress: float) -> Optional[Dict]:
log.debug("updating node %s progress in project %s for user %s with %s", node_id, project_id, user_id, progress)
await delete_data_folders_of_project_node(
request.app, project_uuid, node_uuid, user_id
)


async def update_project_node_progress(
app: web.Application, user_id: int, project_id: str, node_id: str, progress: float
) -> Optional[Dict]:
log.debug(
"updating node %s progress in project %s for user %s with %s",
node_id,
project_id,
user_id,
progress,
)
project = await get_project_for_user(app, project_id, user_id)
if not node_id in project["workbench"]:
raise NodeNotFoundError(project_id, node_id)

project["workbench"][node_id]["progress"] = int(100.0 * float(progress) + .5)
project["workbench"][node_id]["progress"] = int(100.0 * float(progress) + 0.5)
db = app[APP_PROJECT_DBAPI]
await db.update_user_project(project, user_id, project_id)
return project["workbench"][node_id]

async def update_project_node_outputs(app: web.Application, user_id: str, project_id: str, node_id: str, data: Optional[Dict]) -> Optional[Dict]:
log.debug("updating node %s outputs in project %s for user %s with %s", node_id, project_id, user_id, pprint(data))

async def update_project_node_outputs(
app: web.Application,
user_id: int,
project_id: str,
node_id: str,
data: Optional[Dict],
) -> Optional[Dict]:
log.debug(
"updating node %s outputs in project %s for user %s with %s",
node_id,
project_id,
user_id,
pformat(data),
)
project = await get_project_for_user(app, project_id, user_id)
if not node_id in project["workbench"]:
raise NodeNotFoundError(project_id, node_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,10 @@ async def find_users_of_resource(self, key: str, value: str) -> List[str]:
@contextmanager
def managed_resource(user_id: str, client_session_id: str, app: web.Application) -> WebsocketRegistry:
registry = WebsocketRegistry(user_id, client_session_id, app)
yield registry
try:
yield registry
except Exception:
log.exception("Error in web-socket for user:%s, session:%s", user_id, client_session_id)
raise

# TODO: PC->SAN?? exception handling? e.g. remove resource from registry?
Loading