Skip to content

Commit 4397cc8

Browse files
authored
Merge branch 'master' into enh/hide-some-tabs
2 parents bdeaeb6 + a98b2fb commit 4397cc8

File tree

26 files changed

+502
-264
lines changed

26 files changed

+502
-264
lines changed

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/webserver/functions/functions_rpc_interface.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from typing import Literal
23

34
from models_library.api_schemas_webserver import WEBSERVER_RPC_NAMESPACE
45
from models_library.api_schemas_webserver.functions import (
@@ -18,6 +19,7 @@
1819
)
1920
from models_library.functions import (
2021
FunctionClass,
22+
FunctionGroupAccessRights,
2123
FunctionJobStatus,
2224
FunctionOutputs,
2325
FunctionUserAccessRights,
@@ -418,6 +420,7 @@ async def update_function_job_status(
418420
product_name: ProductName,
419421
function_job_id: FunctionJobID,
420422
job_status: FunctionJobStatus,
423+
check_write_permissions: bool = True,
421424
) -> FunctionJobStatus:
422425
result = await rabbitmq_rpc_client.request(
423426
WEBSERVER_RPC_NAMESPACE,
@@ -426,6 +429,7 @@ async def update_function_job_status(
426429
job_status=job_status,
427430
user_id=user_id,
428431
product_name=product_name,
432+
check_write_permissions=check_write_permissions,
429433
)
430434
return TypeAdapter(FunctionJobStatus).validate_python(result)
431435

@@ -438,6 +442,7 @@ async def update_function_job_outputs(
438442
product_name: ProductName,
439443
function_job_id: FunctionJobID,
440444
outputs: FunctionOutputs,
445+
check_write_permissions: bool = True,
441446
) -> FunctionOutputs:
442447
result = await rabbitmq_rpc_client.request(
443448
WEBSERVER_RPC_NAMESPACE,
@@ -446,6 +451,7 @@ async def update_function_job_outputs(
446451
outputs=outputs,
447452
user_id=user_id,
448453
product_name=product_name,
454+
check_write_permissions=check_write_permissions,
449455
)
450456
return TypeAdapter(FunctionOutputs).validate_python(result)
451457

@@ -578,3 +584,37 @@ async def get_functions_user_api_access_rights(
578584
product_name=product_name,
579585
)
580586
return TypeAdapter(FunctionUserApiAccessRights).validate_python(result)
587+
588+
589+
@log_decorator(_logger, level=logging.DEBUG)
590+
async def set_group_permissions(
591+
rabbitmq_rpc_client: RabbitMQRPCClient,
592+
*,
593+
user_id: UserID,
594+
product_name: ProductName,
595+
object_type: Literal["function", "function_job", "function_job_collection"],
596+
object_ids: list[FunctionID | FunctionJobID | FunctionJobCollectionID],
597+
permission_group_id: int,
598+
read: bool | None = None,
599+
write: bool | None = None,
600+
execute: bool | None = None,
601+
) -> list[
602+
tuple[
603+
FunctionID | FunctionJobID | FunctionJobCollectionID, FunctionGroupAccessRights
604+
]
605+
]:
606+
result = await rabbitmq_rpc_client.request(
607+
WEBSERVER_RPC_NAMESPACE,
608+
TypeAdapter(RPCMethodName).validate_python("set_group_permissions"),
609+
user_id=user_id,
610+
product_name=product_name,
611+
object_type=object_type,
612+
object_ids=object_ids,
613+
permission_group_id=permission_group_id,
614+
read=read,
615+
write=write,
616+
execute=execute,
617+
)
618+
return TypeAdapter(
619+
list[tuple[FunctionID | FunctionJobID, FunctionGroupAccessRights]]
620+
).validate_python(result)

services/api-server/src/simcore_service_api_server/_service_function_jobs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ async def inspect_function_job(
203203
user_id=self.user_id,
204204
product_name=self.product_name,
205205
job_status=new_job_status,
206+
check_write_permissions=False,
206207
)
207208

208209
async def create_function_job_inputs( # pylint: disable=no-self-use
@@ -529,4 +530,5 @@ async def function_job_outputs(
529530
user_id=user_id,
530531
product_name=product_name,
531532
outputs=new_outputs,
533+
check_write_permissions=False,
532534
)

services/api-server/src/simcore_service_api_server/services_rpc/wb_api_server.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,13 +587,15 @@ async def update_function_job_status(
587587
user_id: UserID,
588588
product_name: ProductName,
589589
job_status: FunctionJobStatus,
590+
check_write_permissions: bool = True,
590591
) -> FunctionJobStatus:
591592
return await functions_rpc_interface.update_function_job_status(
592593
self._client,
593594
function_job_id=function_job_id,
594595
user_id=user_id,
595596
product_name=product_name,
596597
job_status=job_status,
598+
check_write_permissions=check_write_permissions,
597599
)
598600

599601
async def update_function_job_outputs(
@@ -603,13 +605,15 @@ async def update_function_job_outputs(
603605
user_id: UserID,
604606
product_name: ProductName,
605607
outputs: FunctionOutputs,
608+
check_write_permissions: bool = True,
606609
) -> FunctionOutputs:
607610
return await functions_rpc_interface.update_function_job_outputs(
608611
self._client,
609612
function_job_id=function_job_id,
610613
user_id=user_id,
611614
product_name=product_name,
612615
outputs=outputs,
616+
check_write_permissions=check_write_permissions,
613617
)
614618

615619
async def find_cached_function_jobs(

services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_api/_core.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from models_library.services_enums import ServiceState
1919
from models_library.services_metadata_runtime import to_simcore_runtime_docker_label_key
2020
from servicelib.utils import logged_gather
21+
from settings_library.docker_registry import RegistrySettings
2122
from starlette import status
2223
from tenacity import TryAgain, retry
2324
from tenacity.asyncio import AsyncRetrying
@@ -99,6 +100,7 @@ def _to_snake_case(string: str) -> str:
99100

100101
async def create_service_and_get_id(
101102
create_service_data: AioDockerServiceSpec | dict[str, Any],
103+
registry_settings: RegistrySettings | None,
102104
) -> ServiceId:
103105
# NOTE: ideally the argument should always be AioDockerServiceSpec
104106
# but for that we need get_dynamic_proxy_spec to return that type
@@ -107,6 +109,13 @@ async def create_service_and_get_id(
107109
create_service_data, by_alias=True, exclude_unset=True
108110
)
109111
kwargs = {_to_snake_case(k): v for k, v in kwargs.items()}
112+
if registry_settings:
113+
kwargs["auth"] = {
114+
"username": registry_settings.REGISTRY_USER,
115+
"password": registry_settings.REGISTRY_PW.get_secret_value(),
116+
"serveraddress": registry_settings.resolved_registry_url,
117+
}
118+
kwargs["registry"] = registry_settings.resolved_registry_url
110119

111120
logging.debug("Creating service with\n%s", json_dumps(kwargs, indent=1))
112121
service_start_result = await client.services.create(**kwargs)

services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/scheduler/_core/_event_create_sidecars.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
DynamicSidecarSettings,
3131
PlacementSettings,
3232
)
33+
from .....core.settings import AppSettings
3334
from .....models.dynamic_services_scheduler import NetworkId, SchedulerData
3435
from .....utils.db import get_repository
3536
from .....utils.dict_utils import nested_update
@@ -93,32 +94,35 @@ async def _create_proxy_service(
9394
swarm_network_id: NetworkId,
9495
swarm_network_name: str,
9596
):
97+
app_settings: AppSettings = app.state.settings
9698
proxy_settings: DynamicSidecarProxySettings = (
9799
app.state.settings.DYNAMIC_SERVICES.DYNAMIC_SIDECAR_PROXY_SETTINGS
98100
)
99101
scheduler_data.proxy_admin_api_port = (
100102
proxy_settings.DYNAMIC_SIDECAR_CADDY_ADMIN_API_PORT
101103
)
102-
103104
dynamic_services_settings: DynamicServicesSettings = (
104105
app.state.settings.DYNAMIC_SERVICES
105106
)
106107

107-
dynamic_sidecar_proxy_create_service_params: dict[
108-
str, Any
109-
] = get_dynamic_proxy_spec(
110-
scheduler_data=scheduler_data,
111-
dynamic_services_settings=dynamic_services_settings,
112-
dynamic_sidecar_network_id=dynamic_sidecar_network_id,
113-
swarm_network_id=swarm_network_id,
114-
swarm_network_name=swarm_network_name,
108+
dynamic_sidecar_proxy_create_service_params: dict[str, Any] = (
109+
get_dynamic_proxy_spec(
110+
scheduler_data=scheduler_data,
111+
dynamic_services_settings=dynamic_services_settings,
112+
dynamic_sidecar_network_id=dynamic_sidecar_network_id,
113+
swarm_network_id=swarm_network_id,
114+
swarm_network_name=swarm_network_name,
115+
)
115116
)
116117
_logger.debug(
117118
"dynamic-sidecar-proxy create_service_params %s",
118119
json_dumps(dynamic_sidecar_proxy_create_service_params),
119120
)
120121

121-
await create_service_and_get_id(dynamic_sidecar_proxy_create_service_params)
122+
await create_service_and_get_id(
123+
dynamic_sidecar_proxy_create_service_params,
124+
app_settings.DIRECTOR_V2_DOCKER_HUB_REGISTRY,
125+
)
122126

123127

124128
class CreateSidecars(DynamicSchedulerEvent):
@@ -156,6 +160,7 @@ async def action(cls, app: FastAPI, scheduler_data: SchedulerData) -> None:
156160
rabbitmq_client: RabbitMQClient = app.state.rabbitmq_client
157161
await rabbitmq_client.publish(message.channel_name, message)
158162

163+
app_settings: AppSettings = app.state.settings
159164
dynamic_sidecar_settings: DynamicSidecarSettings = (
160165
app.state.settings.DYNAMIC_SERVICES.DYNAMIC_SIDECAR
161166
)
@@ -244,18 +249,20 @@ async def action(cls, app: FastAPI, scheduler_data: SchedulerData) -> None:
244249

245250
# WARNING: do NOT log, this structure has secrets in the open
246251
# If you want to log, please use an obfuscator
247-
dynamic_sidecar_service_spec_base: AioDockerServiceSpec = await get_dynamic_sidecar_spec(
248-
scheduler_data=scheduler_data,
249-
dynamic_sidecar_settings=dynamic_sidecar_settings,
250-
dynamic_services_scheduler_settings=dynamic_services_scheduler_settings,
251-
swarm_network_id=swarm_network_id,
252-
settings=settings,
253-
app_settings=app.state.settings,
254-
hardware_info=scheduler_data.hardware_info,
255-
has_quota_support=dynamic_services_scheduler_settings.DYNAMIC_SIDECAR_ENABLE_VOLUME_LIMITS,
256-
metrics_collection_allowed=metrics_collection_allowed,
257-
user_extra_properties=user_extra_properties,
258-
rpc_client=rpc_client,
252+
dynamic_sidecar_service_spec_base: AioDockerServiceSpec = (
253+
await get_dynamic_sidecar_spec(
254+
scheduler_data=scheduler_data,
255+
dynamic_sidecar_settings=dynamic_sidecar_settings,
256+
dynamic_services_scheduler_settings=dynamic_services_scheduler_settings,
257+
swarm_network_id=swarm_network_id,
258+
settings=settings,
259+
app_settings=app.state.settings,
260+
hardware_info=scheduler_data.hardware_info,
261+
has_quota_support=dynamic_services_scheduler_settings.DYNAMIC_SIDECAR_ENABLE_VOLUME_LIMITS,
262+
metrics_collection_allowed=metrics_collection_allowed,
263+
user_extra_properties=user_extra_properties,
264+
rpc_client=rpc_client,
265+
)
259266
)
260267

261268
user_specific_service_spec = (
@@ -278,7 +285,8 @@ async def action(cls, app: FastAPI, scheduler_data: SchedulerData) -> None:
278285
)
279286
await rabbitmq_client.publish(rabbit_message.channel_name, rabbit_message)
280287
dynamic_sidecar_id = await create_service_and_get_id(
281-
dynamic_sidecar_service_final_spec
288+
dynamic_sidecar_service_final_spec,
289+
app_settings.DIRECTOR_V2_DOCKER_HUB_REGISTRY,
282290
)
283291
# constrain service to the same node
284292
scheduler_data.dynamic_sidecar.docker_node_id = (

services/director-v2/tests/unit/with_dbs/test_modules_dynamic_sidecar_docker_api.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ async def test_create_service(
453453
cleanup_test_service_name: None,
454454
docker_swarm: None,
455455
):
456-
service_id = await docker_api.create_service_and_get_id(service_spec)
456+
service_id = await docker_api.create_service_and_get_id(service_spec, None)
457457
assert service_id
458458

459459

@@ -465,7 +465,7 @@ async def test_services_to_observe_exist(
465465
docker_swarm: None,
466466
):
467467
service_id = await docker_api.create_service_and_get_id(
468-
dynamic_sidecar_service_spec
468+
dynamic_sidecar_service_spec, None
469469
)
470470
assert service_id
471471

@@ -484,7 +484,7 @@ async def test_dynamic_sidecar_in_running_state_and_node_id_is_recovered(
484484
docker_swarm: None,
485485
):
486486
service_id = await docker_api.create_service_and_get_id(
487-
dynamic_sidecar_service_spec
487+
dynamic_sidecar_service_spec, None
488488
)
489489
assert service_id
490490

@@ -511,7 +511,7 @@ async def test_dynamic_sidecar_get_dynamic_sidecar_sate_fail_to_schedule(
511511
}
512512

513513
service_id = await docker_api.create_service_and_get_id(
514-
dynamic_sidecar_service_spec
514+
dynamic_sidecar_service_spec, None
515515
)
516516
assert service_id
517517

@@ -539,7 +539,9 @@ async def test_is_dynamic_sidecar_stack_missing(
539539

540540
# start 2 fake services to emulate the dynamic-sidecar stack
541541
for dynamic_sidecar_stack in dynamic_sidecar_stack_specs:
542-
service_id = await docker_api.create_service_and_get_id(dynamic_sidecar_stack)
542+
service_id = await docker_api.create_service_and_get_id(
543+
dynamic_sidecar_stack, None
544+
)
543545
assert service_id
544546

545547
services_are_missing = await docker_api.is_dynamic_sidecar_stack_missing(
@@ -562,7 +564,9 @@ async def test_are_sidecar_and_proxy_services_present(
562564

563565
# start 2 fake services to emulate the dynamic-sidecar stack
564566
for dynamic_sidecar_stack in dynamic_sidecar_stack_specs:
565-
service_id = await docker_api.create_service_and_get_id(dynamic_sidecar_stack)
567+
service_id = await docker_api.create_service_and_get_id(
568+
dynamic_sidecar_stack, None
569+
)
566570
assert service_id
567571

568572
services_are_missing = await docker_api.are_sidecar_and_proxy_services_present(
@@ -605,7 +609,9 @@ async def _count_services_in_stack(
605609

606610
# start 2 fake services to emulate the dynamic-sidecar stack
607611
for dynamic_sidecar_stack in dynamic_sidecar_stack_specs:
608-
service_id = await docker_api.create_service_and_get_id(dynamic_sidecar_stack)
612+
service_id = await docker_api.create_service_and_get_id(
613+
dynamic_sidecar_stack, None
614+
)
609615
assert service_id
610616

611617
assert (
@@ -667,7 +673,9 @@ async def test_is_sidecar_running(
667673

668674
# start 2 fake services to emulate the dynamic-sidecar stack
669675
for dynamic_sidecar_stack in dynamic_sidecar_stack_specs:
670-
service_id = await docker_api.create_service_and_get_id(dynamic_sidecar_stack)
676+
service_id = await docker_api.create_service_and_get_id(
677+
dynamic_sidecar_stack, None
678+
)
671679
assert service_id
672680

673681
async for attempt in AsyncRetrying(

services/static-webserver/client/source/class/osparc/data/model/Node.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ qx.Class.define("osparc.data.model.Node", {
196196
},
197197

198198
events: {
199-
"updateStudyDocument": "qx.event.type.Event",
200199
"projectDocumentChanged": "qx.event.type.Data",
201200
"reloadModel": "qx.event.type.Event",
202201
"retrieveInputs": "qx.event.type.Data",
@@ -490,6 +489,7 @@ qx.Class.define("osparc.data.model.Node", {
490489
this.populateNodeUIData(nodeData);
491490
// new place to store the position and marker
492491
this.populateNodeUIData(nodeUiData);
492+
this.listenToChanges();
493493
})
494494
.catch(err => {
495495
console.log(err);

0 commit comments

Comments
 (0)