Skip to content
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

check global config for hub url and #507

Merged
merged 6 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ $ towncrier create <PR-number>.<break|feat|fix>.md --content "Short description"

<!-- towncrier release notes start -->

## cylc-uiserver-1.4.1
### 🚀 Enhancements

[#507](https://github.com/cylc/cylc-uiserver/pull/507) - Added functionality for routing to a multiuser deploymnet when running cylc gui command.


markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
## cylc-uiserver-1.4.0 (Released 2023-09-12)

### 🚀 Enhancements
Expand Down
35 changes: 34 additions & 1 deletion cylc/uiserver/scripts/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
from requests.exceptions import RequestException
import requests
import sys
from textwrap import dedent
from typing import Optional
import webbrowser
from getpass import getuser


from cylc.flow.id_cli import parse_id_async
Expand All @@ -40,6 +42,8 @@
WorkflowFilesError
)

from cylc.flow.cfgspec.glbl_cfg import glbl_cfg

from cylc.uiserver import init_log
from cylc.uiserver.app import (
CylcUIServer,
Expand All @@ -51,8 +55,32 @@

def main(*argv):
init_log()
GLOBAL_CONFIG = glbl_cfg().get(['hub', 'url'])
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
jp_server_opts, new_gui, workflow_id = parse_args_opts()
if '--help' in sys.argv and GLOBAL_CONFIG:
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
print(
dedent('''
cylc gui [WORKFLOW]

Open the Cylc GUI in a new web browser tab.

If WORKFLOW is specified, the GUI will open on this workflow.

This command has been configured to use a centrally configured
Jupyter Hub instance rather than start a standalone server.
To see the configuration options for the server run
"cylc gui --help-all", these options can be configured in the
Jupyter configuration files using "c.Spawner.cmd", see the Cylc
and Jupyter Hub documentation for more details.
'''))
return
if '--help' not in sys.argv:
oliver-sanders marked this conversation as resolved.
Show resolved Hide resolved
if GLOBAL_CONFIG:
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
print(f"Running on {GLOBAL_CONFIG} as specified in global config.")
oliver-sanders marked this conversation as resolved.
Show resolved Hide resolved
webbrowser.open(
update_url(GLOBAL_CONFIG, workflow_id), autoraise=True
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
)
return
# get existing jpserver-<pid>-open.html files
# check if the server is available for use
# prompt for user whether to clean files for un-usable uiservers
Expand Down Expand Up @@ -190,6 +218,7 @@ def get_arg_parser():
def update_url(url, workflow_id):
""" Update the url to open at the correct workflow in the gui.
"""
GLOBAL_CONFIG = glbl_cfg().get(['hub', 'url'])
oliver-sanders marked this conversation as resolved.
Show resolved Hide resolved
if not url:
return
split_url = url.split('/workspace/')
Expand All @@ -212,4 +241,8 @@ def update_url(url, workflow_id):
return url.replace(old_workflow, workflow_id)
else:
# current url points to dashboard, update to point to workflow
return f"{url}/workspace/{workflow_id}"
if GLOBAL_CONFIG:
oliver-sanders marked this conversation as resolved.
Show resolved Hide resolved
return (f"{url}/user/{getuser()}/{CylcUIServer.name}"
f"/#/workspace/{workflow_id}")
else:
return f"{url}/workspace/{workflow_id}"
51 changes: 51 additions & 0 deletions cylc/uiserver/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
from cylc.uiserver.data_store_mgr import DataStoreMgr
from cylc.uiserver.workflows_mgr import WorkflowsManager

from cylc.flow.cfgspec.globalcfg import SPEC
from cylc.flow.parsec.config import ParsecConfig
from cylc.flow.parsec.validate import cylc_config_validate

class AsyncClientFixture(WorkflowRuntimeClient):
pattern = zmq.REQ
Expand Down Expand Up @@ -360,3 +363,51 @@ def workflow_run_dir(request):
yield flow_name, log_dir
if not request.session.testsfailed:
rmtree(run_dir)

@pytest.fixture
def mock_glbl_cfg(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
wxtim marked this conversation as resolved.
Show resolved Hide resolved
"""A Pytest fixture for fiddling global config values.

* Hacks the specified `glbl_cfg` object.
* Can be called multiple times within a test function.

Args:
pypath (str):
The python-like path to the global configuation object you want
to fiddle.
E.G. if you want to hack the `glbl_cfg` in
`cylc.flow.scheduler` you would provide
`cylc.flow.scheduler.glbl_cfg`
global_config (str):
The globlal configuration as a multi-line string.

Example:
Change the value of `UTC mode` in the global config as seen from
`the scheduler` module.

def test_something(mock_glbl_cfg):
mock_glbl_cfg(
'cylc.flow.scheduler.glbl_cfg',
'''
[scheduler]
UTC mode = True
'''
)

"""
# TODO: modify Parsec so we can use StringIO rather than a temp file.
def _mock_glbl_cfg(pypath: str, global_config: str) -> None:
nonlocal tmp_path, monkeypatch
global_config_path = tmp_path / 'global.cylc'
global_config_path.write_text(global_config)
glbl_cfg = ParsecConfig(SPEC, validator=cylc_config_validate)
glbl_cfg.loadcfg(global_config_path)

def _inner(cached=False):
nonlocal glbl_cfg
return glbl_cfg

monkeypatch.setattr(pypath, _inner)

yield _mock_glbl_cfg
rmtree(tmp_path)
31 changes: 27 additions & 4 deletions cylc/uiserver/tests/test_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import pytest
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
from random import randint
import requests
from shutil import rmtree
from time import sleep

from cylc.uiserver.scripts.gui import (
Expand All @@ -29,48 +28,72 @@
update_url
)

from cylc.flow.cfgspec.glbl_cfg import glbl_cfg
GLOBAL_CONFIG = glbl_cfg().get(['hub', 'url'])


markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
@pytest.mark.parametrize(
'existing_content,workflow_id,expected_updated_content',
'existing_content,workflow_id,expected_updated_content,hub_url',
[
pytest.param(
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#',
None,
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#',
'',
id='existing_no_workflow_new_no_workflow'
),
pytest.param(
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#',
'some/workflow',
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#/workspace/some/workflow',
'',
id='existing_no_workflow_new_workflow'
),
pytest.param(
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#',
'some/hub/workflow',
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#/user/mdawson/cylc/#/workspace/some/hub/workflow',
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
'localhost:8000',
id='existing_no_workflow_new_workflow_hub'
),
pytest.param(
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#/workspace/some/workflow',
'another/flow',
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#/workspace/another/flow',
'',
id='existing_workflow_new_workflow'
),
pytest.param(
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#/workspace/some/workflow',
None,
'http://localhost:8892/cylc/?token=1234567890some_big_long_token1234567890#',
'',
id='existing_workflow_no_new_workflow'
),
pytest.param(
'',
'another/flow',
None,
'',
id='no_url_no_change'
),
]
)

def test_update_html_file_updates_gui_file(
existing_content,
workflow_id,
expected_updated_content):
expected_updated_content,
hub_url,
mock_glbl_cfg):
"""Tests url is updated correctly"""

mock_glbl_cfg('cylc.uiserver.scripts.gui.glbl_cfg',
f'''[hub]
url = {hub_url}
''')
updated_file_content = update_url(existing_content, workflow_id)
print('updated_file_content')
print(updated_file_content)
markgrahamdawson marked this conversation as resolved.
Show resolved Hide resolved
assert updated_file_content == expected_updated_content


Expand Down
Loading