diff --git a/src/machinelearningservices/CHANGELOG.rst b/src/machinelearningservices/CHANGELOG.rst index 1fb194c0002..a9d384b386a 100644 --- a/src/machinelearningservices/CHANGELOG.rst +++ b/src/machinelearningservices/CHANGELOG.rst @@ -1,6 +1,10 @@ -## Azure Machine Learning CLI (v2) (unreleased) +## 2025-08-27 + +### Azure Machine Learning CLI (v2) v 2.39.0 - `az ml compute update` - Fix a bug compute update which caused Enable SSO property to reset. +- `az ml compute connect-ssh` + - Fix proxy endpoint path ## 2025-05-15 diff --git a/src/machinelearningservices/HISTORY.rst b/src/machinelearningservices/HISTORY.rst index 72821c13d93..be67d716394 100644 --- a/src/machinelearningservices/HISTORY.rst +++ b/src/machinelearningservices/HISTORY.rst @@ -3,6 +3,11 @@ Release History =============== +2.39.0 +++++++ +* Fix a bug compute update which caused Enable SSO property to reset. +* Fix proxy endpoint path + 2.38.0 ++++++ * Fix a bug compute update which caused Enable SSO property to reset. \ No newline at end of file diff --git a/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_command.py b/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_command.py index 58498d22c84..177491ad548 100644 --- a/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_command.py +++ b/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_command.py @@ -24,7 +24,8 @@ def get_ssh_command( services_dict: Dict[str, ServiceInstance], node_index: int, private_key_file_path: str, - ssh_args: Optional[Sequence[str]] = None + ssh_args: Optional[Sequence[str]] = None, + connector_args: Optional[Sequence[str]] = None ) -> Tuple[bool, str]: proxyEndpoint = _get_proxy_endpoint(services_dict, node_index).replace("", str(node_index)) connect_ssh_path = pathlib.Path(__file__).parent / "_ssh_connector.py" @@ -45,9 +46,10 @@ def get_ssh_command( identity_param = " -i {}".format(private_key_file_path) if private_key_file_path else "" # TODO: Find how to enable debug mode ssh_args_str = " ".join(ssh_args) if ssh_args else "" + connector_args_str = " ".join(connector_args) if connector_args else "" return ( connect_ssh_path_has_space, - f'{ssh_path} -v -o ProxyCommand="{sys.executable} {connect_ssh_path} {proxyEndpoint}" ' + f'{ssh_path} -v -o ProxyCommand="{sys.executable} {connect_ssh_path} {proxyEndpoint} {connector_args_str}" ' f"azureuser@{proxyEndpoint}{identity_param}{ssh_args_str}", ) diff --git a/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_connector.py b/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_connector.py index 7d2f39f8961..20611054143 100644 --- a/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_connector.py +++ b/src/machinelearningservices/azext_mlv2/manual/custom/_ssh_connector.py @@ -61,12 +61,17 @@ async def _connect_ssh(self): ) raise Exception(msg) # pylint: disable=broad-exception-raised proxy_endpoint = sys.argv[1] + + is_compute = len(sys.argv) > 2 and sys.argv[2] == "--is-compute" + uri = f"{proxy_endpoint}/nbip/v1.0/ws-tcp" + if is_compute: + uri += "/port/22" mgtScope = ["https://management.core.windows.net/.default"] aml_token = run_az_cli(["account", "get-access-token", "--scope", mgtScope[0]])["accessToken"] async with websockets.client.connect( - uri=f"{proxy_endpoint}/nbip/v1.0/ws-tcp", + uri=uri, extra_headers={"Authorization": f"Bearer {aml_token}"}, ) as websocket: diff --git a/src/machinelearningservices/azext_mlv2/manual/custom/compute.py b/src/machinelearningservices/azext_mlv2/manual/custom/compute.py index a5944007288..7d75b802412 100644 --- a/src/machinelearningservices/azext_mlv2/manual/custom/compute.py +++ b/src/machinelearningservices/azext_mlv2/manual/custom/compute.py @@ -274,12 +274,14 @@ def ml_compute_connect_ssh(cmd, resource_group_name, workspace_name, name, priva # create proxy endpoint for CI based on endpoint for jupyter # TODO: Improve with a call to get proxyendpoint from CI, requires API jupyter = [f["endpoint_uri"] for f in compute.services if f["display_name"] == "Jupyter"][0] - proxyEndpoint = jupyter.replace(name, f"{name}-22").replace("https://", "wss://").replace("/tree/", "") + proxyEndpoint = jupyter.replace("https://", "wss://").replace("/tree/", "") services_dict = { "ssh": ServiceInstance(type="SSH", status="Running", properties={"ProxyEndpoint": proxyEndpoint}) } - path_has_space, ssh_command = get_ssh_command(services_dict, 0, private_key_file_path) + path_has_space, ssh_command = get_ssh_command( + services_dict, 0, private_key_file_path, connector_args=["--is-compute"] + ) print(f"ssh_command: {ssh_command}") if path_has_space: module_logger.error(ssh_connector_file_path_space_message()) diff --git a/src/machinelearningservices/azext_mlv2/manual/requirements.txt b/src/machinelearningservices/azext_mlv2/manual/requirements.txt index 1fd972ed1e9..83eef209ca5 100644 --- a/src/machinelearningservices/azext_mlv2/manual/requirements.txt +++ b/src/machinelearningservices/azext_mlv2/manual/requirements.txt @@ -2,4 +2,4 @@ cryptography docker azure-mgmt-resourcegraph<9.0.0,>=2.0.0 azure-identity==1.17.1 -azure-ai-ml==1.28.1 \ No newline at end of file +azure-ai-ml==1.29.0 \ No newline at end of file diff --git a/src/machinelearningservices/setup.py b/src/machinelearningservices/setup.py index b53c622be57..46e07d728a3 100644 --- a/src/machinelearningservices/setup.py +++ b/src/machinelearningservices/setup.py @@ -10,7 +10,7 @@ from setuptools import setup, find_packages # HISTORY.rst entry. -VERSION = '2.38.1' +VERSION = '2.39.0' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers