Skip to content

Commit fb1cd83

Browse files
Merge branch 'master' into add-notifications-service
2 parents 77197a8 + e873406 commit fb1cd83

File tree

28 files changed

+663
-175
lines changed

28 files changed

+663
-175
lines changed

packages/pytest-simcore/src/pytest_simcore/helpers/playwright.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,29 @@ def __call__(self, message: str) -> bool:
302302
return False
303303

304304

305+
@dataclass
306+
class SocketIOWaitNodeForOutputs:
307+
logger: logging.Logger
308+
expected_number_of_outputs: int
309+
node_id: str
310+
311+
def __call__(self, message: str) -> bool:
312+
if message.startswith(SOCKETIO_MESSAGE_PREFIX):
313+
decoded_message = decode_socketio_42_message(message)
314+
if decoded_message.name == _OSparcMessages.NODE_UPDATED:
315+
assert "data" in decoded_message.obj
316+
assert "node_id" in decoded_message.obj
317+
if decoded_message.obj["node_id"] == self.node_id:
318+
assert "outputs" in decoded_message.obj["data"]
319+
320+
return (
321+
len(decoded_message.obj["data"]["outputs"])
322+
== self.expected_number_of_outputs
323+
)
324+
325+
return False
326+
327+
305328
@dataclass
306329
class SocketIOOsparcMessagePrinter:
307330
include_logger_messages: bool = False

services/agent/src/simcore_service_agent/services/backup.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import asyncio
2+
import json
23
import logging
3-
import os
4+
import socket
45
import tempfile
56
from asyncio.streams import StreamReader
67
from datetime import timedelta
@@ -9,6 +10,7 @@
910
from typing import Final
1011
from uuid import uuid4
1112

13+
import httpx
1214
from fastapi import FastAPI
1315
from servicelib.container_utils import run_command_in_container
1416
from settings_library.utils_r_clone import resolve_provider
@@ -112,8 +114,28 @@ def _log_expected_operation(
112114
_logger.log(log_level, formatted_message)
113115

114116

117+
def _get_self_container_ip() -> str:
118+
return socket.gethostbyname(socket.gethostname())
119+
120+
121+
async def _get_self_container() -> str:
122+
ip = _get_self_container_ip()
123+
124+
async with httpx.AsyncClient(
125+
transport=httpx.AsyncHTTPTransport(uds="/var/run/docker.sock")
126+
) as client:
127+
response = await client.get("http://localhost/containers/json")
128+
for entry in response.json():
129+
if ip in json.dumps(entry):
130+
container_id: str = entry["Id"]
131+
return container_id
132+
133+
msg = "Could not determine self container ID"
134+
raise RuntimeError(msg)
135+
136+
115137
async def _ensure_permissions_on_source_dir(source_dir: Path) -> None:
116-
self_container = os.environ["HOSTNAME"]
138+
self_container = await _get_self_container()
117139
await run_command_in_container(
118140
self_container,
119141
command=f"chmod -R o+rX '{source_dir}'",

services/agent/tests/unit/test_services_backup.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from models_library.projects_nodes_io import NodeID
1616
from models_library.services_types import ServiceRunID
1717
from pydantic import NonNegativeInt
18+
from pytest_mock import MockerFixture
19+
from servicelib.container_utils import run_command_in_container
1820
from simcore_service_agent.core.settings import ApplicationSettings
1921
from simcore_service_agent.services.backup import backup_volume
2022
from simcore_service_agent.services.docker_utils import get_volume_details
@@ -42,7 +44,7 @@ def volume_content(tmpdir: Path) -> Path:
4244
@pytest.fixture
4345
async def mock_container_with_data(
4446
volume_content: Path, monkeypatch: pytest.MonkeyPatch
45-
) -> AsyncIterable[None]:
47+
) -> AsyncIterable[str]:
4648
async with aiodocker.Docker() as client:
4749
container = await client.containers.run(
4850
config={
@@ -56,7 +58,7 @@ async def mock_container_with_data(
5658
container_name = container_inspect["Name"][1:]
5759
monkeypatch.setenv("HOSTNAME", container_name)
5860

59-
yield None
61+
yield container_inspect["Id"]
6062

6163
await container.delete(force=True)
6264

@@ -68,8 +70,24 @@ def downlaoded_from_s3(tmpdir: Path) -> Path:
6870
return path
6971

7072

73+
@pytest.fixture
74+
async def mock__get_self_container_ip(
75+
mock_container_with_data: str,
76+
mocker: MockerFixture,
77+
) -> None:
78+
container_ip = await run_command_in_container(
79+
mock_container_with_data, command="hostname -i"
80+
)
81+
82+
mocker.patch(
83+
"simcore_service_agent.services.backup._get_self_container_ip",
84+
return_value=container_ip.strip(),
85+
)
86+
87+
7188
async def test_backup_volume(
72-
mock_container_with_data: None,
89+
mock_container_with_data: str,
90+
mock__get_self_container_ip: None,
7391
volume_content: Path,
7492
project_id: ProjectID,
7593
swarm_stack_name: str,

services/static-webserver/client/source/class/osparc/dashboard/GridButtonItem.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ qx.Class.define("osparc.dashboard.GridButtonItem", {
250250
_applyOwner: function(value, old) {
251251
const label = this.getChildControl("subtitle-text");
252252
if (osparc.utils.Resources.isFunction(this.getResourceData())) {
253-
const canIWrite = Boolean(this.getResourceData()["accessRights"]["write"]);
253+
// Functions don't have 'owner'
254+
const canIWrite = osparc.data.model.Function.canIWrite(this.getResourceData()["accessRights"]);
254255
label.setValue(canIWrite ? "My Function" : "Read Only");
255256
} else {
256257
const user = this.__createOwner(value);
@@ -262,20 +263,15 @@ qx.Class.define("osparc.dashboard.GridButtonItem", {
262263
_applyAccessRights: function(value) {
263264
if (value && Object.keys(value).length) {
264265
const shareIcon = this.getChildControl("subtitle-icon");
265-
if (this.isResourceType("function")) {
266-
// in case of functions, the access rights are actually myAccessRights
267-
osparc.dashboard.CardBase.populateMyAccessRightsIcon(shareIcon, value);
268-
} else {
269-
shareIcon.addListener("tap", e => {
270-
e.stopPropagation();
271-
this.openAccessRights();
272-
}, this);
273-
shareIcon.addListener("pointerdown", e => e.stopPropagation());
274-
osparc.dashboard.CardBase.populateShareIcon(shareIcon, value);
266+
shareIcon.addListener("tap", e => {
267+
e.stopPropagation();
268+
this.openAccessRights();
269+
}, this);
270+
shareIcon.addListener("pointerdown", e => e.stopPropagation());
271+
osparc.dashboard.CardBase.populateShareIcon(shareIcon, value);
275272

276-
if (this.isResourceType("study")) {
277-
this._setStudyPermissions(value);
278-
}
273+
if (this.isResourceType("study")) {
274+
this._setStudyPermissions(value);
279275
}
280276
}
281277
},

services/static-webserver/client/source/class/osparc/dashboard/ListButtonItem.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ qx.Class.define("osparc.dashboard.ListButtonItem", {
244244
_applyOwner: function(value, old) {
245245
const label = this.getChildControl("owner");
246246
if (osparc.utils.Resources.isFunction(this.getResourceData())) {
247-
const canIWrite = Boolean(this.getResourceData()["accessRights"]["write"]);
247+
// Functions don't have 'owner'
248+
const canIWrite = osparc.data.model.Function.canIWrite(this.getResourceData()["accessRights"]);
248249
label.setValue(canIWrite ? "My Function" : "Read Only");
249250
} else {
250251
const user = this.__createOwner(value);
@@ -257,20 +258,15 @@ qx.Class.define("osparc.dashboard.ListButtonItem", {
257258
_applyAccessRights: function(value) {
258259
if (value && Object.keys(value).length) {
259260
const shareIcon = this.getChildControl("shared-icon");
260-
if (this.isResourceType("function")) {
261-
// in case of functions, the access rights are actually myAccessRights
262-
osparc.dashboard.CardBase.populateMyAccessRightsIcon(shareIcon, value);
263-
} else {
264-
shareIcon.addListener("tap", e => {
265-
e.stopPropagation();
266-
this.openAccessRights();
267-
}, this);
268-
shareIcon.addListener("pointerdown", e => e.stopPropagation());
269-
osparc.dashboard.CardBase.populateShareIcon(shareIcon, value);
261+
shareIcon.addListener("tap", e => {
262+
e.stopPropagation();
263+
this.openAccessRights();
264+
}, this);
265+
shareIcon.addListener("pointerdown", e => e.stopPropagation());
266+
osparc.dashboard.CardBase.populateShareIcon(shareIcon, value);
270267

271-
if (this.isResourceType("study")) {
272-
this._setStudyPermissions(value);
273-
}
268+
if (this.isResourceType("study")) {
269+
this._setStudyPermissions(value);
274270
}
275271
}
276272
},

services/static-webserver/client/source/class/osparc/dashboard/ResourceContainerManager.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ qx.Class.define("osparc.dashboard.ResourceContainerManager", {
163163
text = this.tr("No Public Projects found");
164164
break;
165165
case osparc.dashboard.StudyBrowser.CONTEXT.FUNCTIONS:
166+
case osparc.dashboard.StudyBrowser.CONTEXT.SEARCH_FUNCTIONS:
166167
text = this.tr("No Functions found");
167168
break;
168169
}

services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
409409
return;
410410
} else if (osparc.utils.Resources.isFunction(this.__resourceData)) {
411411
this.__addInfoPage();
412+
this.__addPermissionsPage();
412413
if (this.__resourceModel.getFunctionClass() === osparc.data.model.Function.FUNCTION_CLASS.PROJECT) {
413414
this.__addPreviewPage();
414415
}
@@ -641,6 +642,12 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
641642
const updatedData = e.getData();
642643
this.__fireUpdateEvent(resourceData, updatedData);
643644
}, this);
645+
} else if (osparc.utils.Resources.isFunction(resourceData)) {
646+
collaboratorsView = new osparc.share.CollaboratorsFunction(resourceData);
647+
collaboratorsView.addListener("updateAccessRights", e => {
648+
const updatedData = e.getData();
649+
this.__fireUpdateEvent(resourceData, updatedData);
650+
}, this);
644651
} else {
645652
collaboratorsView = new osparc.share.CollaboratorsStudy(resourceData);
646653
if (osparc.utils.Resources.isStudy(resourceData)) {

0 commit comments

Comments
 (0)