import shutil from unittest import mock from unittest.mock import MagicMock from click.testing import CliRunner from lightning_cloud.openapi import ( Externalv1LightningappInstance, Externalv1Lightningwork, V1ClusterStatus, V1GetClusterResponse, V1LightningappInstanceSpec, ) from lightning.app.cli.lightning_cli import ssh @mock.patch("lightning_cloud.login.Auth.authenticate", MagicMock()) @mock.patch("inquirer.prompt") @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_apps") @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_components") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_app") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_cluster") @mock.patch("os.execv") def test_ssh_no_arguments( os_execv: mock.MagicMock, get_cluster: mock.MagicMock, get_app: mock.MagicMock, list_components: mock.MagicMock, list_apps: mock.MagicMock, list_prompt: mock.MagicMock, ): app_instance = Externalv1LightningappInstance( id="test1234", name="test", spec=V1LightningappInstanceSpec(cluster_id="clusterA"), ) list_apps.return_value = [app_instance] list_components.return_value = [Externalv1Lightningwork(id="work1234", name="root.server")] get_app.return_value = app_instance get_cluster.return_value = V1GetClusterResponse(status=V1ClusterStatus(ssh_gateway_endpoint="ssh.lightning.ai")) list_prompt.side_effect = [{"app_name": "test"}, {"component_name": "root.server"}] runner = CliRunner() runner.invoke(ssh, []) ssh_path = shutil.which("ssh") os_execv.assert_called_once_with(ssh_path, ["-tt", "lightningwork-work1234@ssh.lightning.ai"]) @mock.patch("lightning_cloud.login.Auth.authenticate", MagicMock()) @mock.patch("inquirer.prompt") @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_apps") @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_components") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_app") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_cluster") @mock.patch("os.execv") def test_ssh_app_preselected( os_execv: mock.MagicMock, get_cluster: mock.MagicMock, get_app: mock.MagicMock, list_components: mock.MagicMock, list_apps: mock.MagicMock, list_prompt: mock.MagicMock, ): app_instance = Externalv1LightningappInstance( id="test1234", name="test", spec=V1LightningappInstanceSpec(cluster_id="clusterA"), ) list_apps.return_value = [app_instance] list_components.return_value = [Externalv1Lightningwork(id="work1234", name="root.server")] get_app.return_value = app_instance get_cluster.return_value = V1GetClusterResponse(status=V1ClusterStatus(ssh_gateway_endpoint="ssh.lightning.ai")) list_prompt.return_value = {"component_name": "root.server"} runner = CliRunner() runner.invoke(ssh, ["--app-name", "test"]) ssh_path = shutil.which("ssh") os_execv.assert_called_once_with(ssh_path, ["-tt", "lightningwork-work1234@ssh.lightning.ai"]) @mock.patch("lightning_cloud.login.Auth.authenticate", MagicMock()) @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_apps") @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_components") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_app") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_cluster") @mock.patch("os.execv") def test_ssh_app_and_component_preselected( os_execv: mock.MagicMock, get_cluster: mock.MagicMock, get_app: mock.MagicMock, list_components: mock.MagicMock, list_apps: mock.MagicMock, ): app_instance = Externalv1LightningappInstance( id="test1234", name="test", spec=V1LightningappInstanceSpec(cluster_id="clusterA"), ) list_apps.return_value = [app_instance] list_components.return_value = [Externalv1Lightningwork(id="work1234", name="root.server")] get_app.return_value = app_instance get_cluster.return_value = V1GetClusterResponse(status=V1ClusterStatus(ssh_gateway_endpoint="ssh.lightning.ai")) runner = CliRunner() runner.invoke(ssh, ["--app-name", "test", "--component-name", "root.server"]) ssh_path = shutil.which("ssh") os_execv.assert_called_once_with(ssh_path, ["-tt", "lightningwork-work1234@ssh.lightning.ai"]) @mock.patch("lightning_cloud.login.Auth.authenticate", MagicMock()) @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_apps") @mock.patch("click.ClickException") def test_ssh_unknown_app( click_exception: mock.MagicMock, list_apps: mock.MagicMock, ): app_instance = Externalv1LightningappInstance( id="test1234", name="test-different-name", spec=V1LightningappInstanceSpec(cluster_id="clusterA"), ) list_apps.return_value = [app_instance] runner = CliRunner() runner.invoke(ssh, ["--app-name", "unknown-app-name"]) click_exception.assert_called_once() @mock.patch("lightning_cloud.login.Auth.authenticate", MagicMock()) @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_apps") @mock.patch("lightning.app.cli.cmd_apps._AppManager.list_components") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_app") @mock.patch("lightning.app.cli.cmd_apps._AppManager.get_cluster") @mock.patch("click.ClickException") def test_ssh_unknown_component( click_exception: mock.MagicMock, get_cluster: mock.MagicMock, get_app: mock.MagicMock, list_components: mock.MagicMock, list_apps: mock.MagicMock, ): app_instance = Externalv1LightningappInstance( id="test1234", name="test", spec=V1LightningappInstanceSpec(cluster_id="clusterA"), ) list_apps.return_value = [app_instance] list_components.return_value = [Externalv1Lightningwork(id="work1234", name="root.server")] get_app.return_value = app_instance get_cluster.return_value = V1GetClusterResponse(status=V1ClusterStatus(ssh_gateway_endpoint="ssh.lightning.ai")) runner = CliRunner() runner.invoke(ssh, ["--app-name", "test", "--component-name", "rot.server"]) click_exception.assert_called_once()