From 7c9e9df87ba920e82e951b9a19d33d67b22b7c73 Mon Sep 17 00:00:00 2001 From: Patrick Tesh Date: Thu, 19 Jan 2023 11:41:24 +0000 Subject: [PATCH 1/3] Add format option to server list command --- faculty_cli/cli.py | 54 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/faculty_cli/cli.py b/faculty_cli/cli.py index f6d7dcf..aafed79 100644 --- a/faculty_cli/cli.py +++ b/faculty_cli/cli.py @@ -509,12 +509,28 @@ def server(): "-v", "--verbose", is_flag=True, - help="Print extra information about servers.", + help="", ) -def list_servers(project, all, verbose): +@click.option( + "-f", + "--format", + type=click.Choice(["list", "table", "ssh-config"], case_sensitive=False), + help="Output format.", +) +def list_servers(project, all, verbose, format): """List your Faculty servers. If you do not specify a project, all servers will be listed.""" + if verbose: + if format is None: + # Retain legacy behaviour for verbose flag. + format = "table" + else: + raise click.exceptions.BadOptionUsage( + "format", + "You can't specify the `--verbose` flag and also pass the `--format` option", + ) + status_filter = None if all else ServerStatus.RUNNING if not project: projects = {project.id: project.name for project in _list_projects()} @@ -558,16 +574,36 @@ def list_servers(project, all, verbose): server.created_at.strftime("%Y-%m-%d %H:%M"), ) ) - if not found_servers and verbose: + + if not found_servers: click.echo("No servers.") - elif project and verbose: - servers = [server[1:] for server in found_servers] - click.echo(tabulate(servers, headers[1:], tablefmt="plain")) - elif project or not verbose: + return + + if format == "table": + if project: + found_servers = [server[1:] for server in found_servers] + headers = headers[1:] + click.echo(tabulate(found_servers, headers, tablefmt="plain")) + + elif format == "ssh-config": + config_entries = [] + for server in found_servers: + server_name = server[1] + project_name = project if project else server[0] + ssh_details = _get_ssh_details(project_name, server_name) + host = f"{server_name}-{project_name.lower().replace(' ', '_')}" + config_entries.append( + f"""Host {host} + HostName {ssh_details.hostname} + User {ssh_details.username} + Port {ssh_details.port}""" + ) + + click.echo("\n".join(config_entries)) + + else: for server in found_servers: click.echo(server[1]) - elif not project and verbose: - click.echo(tabulate(found_servers, headers, tablefmt="plain")) @server.command(name="open") From a9cbd3b44a0295a68019acca5c185dd8210db0bd Mon Sep 17 00:00:00 2001 From: Patrick Tesh Date: Thu, 19 Jan 2023 11:41:36 +0000 Subject: [PATCH 2/3] add test cases for new server list format option --- test/fixtures.py | 6 ++++++ test/test_servers.py | 50 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/test/fixtures.py b/test/fixtures.py index bc0c14d..713d49f 100644 --- a/test/fixtures.py +++ b/test/fixtures.py @@ -22,6 +22,7 @@ SharedServerResources, Server, Service, + SSHDetails, ) from faculty.config import Profile @@ -71,3 +72,8 @@ status=ServerStatus.RUNNING, services=[SERVICE], ) + + +SSH_DETAILS = SSHDetails( + hostname="test-server", port=1234, username="faculty", key="not-a-real-key" +) diff --git a/test/test_servers.py b/test/test_servers.py index df68f02..0822c1f 100644 --- a/test/test_servers.py +++ b/test/test_servers.py @@ -23,6 +23,7 @@ DEDICATED_SERVER, DEDICATED_RESOURCE, SHARED_RESOURCE, + SSH_DETAILS, ) @@ -54,7 +55,7 @@ def test_list_all_servers_no_servers( mocker.patch("faculty_cli.cli._list_user_servers", return_value=[]) result = runner.invoke(cli, ["server", "list"]) assert result.exit_code == 0 - assert result.output == "" + assert result.output == "No servers.\n" def test_list_all_servers( @@ -180,6 +181,53 @@ def test_list_servers_verbose( ) +def test_list_all_servers_ssh_config( + mocker, + mock_update_check, + mock_check_credentials, + mock_profile, + mock_user_id, +): + runner = CliRunner() + mocker.patch("faculty_cli.cli._list_projects", return_value=[PROJECT]) + mocker.patch( + "faculty_cli.cli._list_user_servers", return_value=[DEDICATED_SERVER] + ) + mocker.patch("faculty_cli.cli._get_ssh_details", return_value=SSH_DETAILS) + result = runner.invoke( + cli, + ["server", "list", "--format", "ssh-config"], + ) + assert result.exit_code == 0 + assert ( + result.output + == f"Host test-server-test-project\n HostName test-server\n User faculty\n Port 1234\n" + ) + + +def test_list_all_servers_verbose_error( + mocker, + mock_update_check, + mock_check_credentials, + mock_profile, + mock_user_id, +): + runner = CliRunner() + result = runner.invoke( + cli, + ["server", "list", "--verbose", "--format", "ssh-config"], + ) + assert result.exit_code == 2 + assert ( + result.output + == """Usage: cli server list [OPTIONS] PROJECT +Try 'cli server list --help' for help. + +Error: You can't specify the `--verbose` flag and also pass the `--format` option +""" + ) + + def test_server_spec_dedicated(): machine_type, cpus, memory_gb = _server_spec(DEDICATED_SERVER) assert machine_type == DEDICATED_RESOURCE.node_type From 8da75988284c2641e4d4b1638a5c4458a8664628 Mon Sep 17 00:00:00 2001 From: Patrick Tesh Date: Mon, 30 Jan 2023 13:27:13 +0000 Subject: [PATCH 3/3] Fix flake8 errors --- faculty_cli/cli.py | 3 ++- test/test_servers.py | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/faculty_cli/cli.py b/faculty_cli/cli.py index aafed79..a33b885 100644 --- a/faculty_cli/cli.py +++ b/faculty_cli/cli.py @@ -528,7 +528,8 @@ def list_servers(project, all, verbose, format): else: raise click.exceptions.BadOptionUsage( "format", - "You can't specify the `--verbose` flag and also pass the `--format` option", + "You can't specify the `--verbose` flag and also pass the " + "`--format` option", ) status_filter = None if all else ServerStatus.RUNNING diff --git a/test/test_servers.py b/test/test_servers.py index 0822c1f..d48bec1 100644 --- a/test/test_servers.py +++ b/test/test_servers.py @@ -199,9 +199,9 @@ def test_list_all_servers_ssh_config( ["server", "list", "--format", "ssh-config"], ) assert result.exit_code == 0 - assert ( - result.output - == f"Host test-server-test-project\n HostName test-server\n User faculty\n Port 1234\n" + assert result.output == ( + "Host test-server-test-project\n HostName test-server\n User " + "faculty\n Port 1234\n" ) @@ -217,14 +217,14 @@ def test_list_all_servers_verbose_error( cli, ["server", "list", "--verbose", "--format", "ssh-config"], ) - assert result.exit_code == 2 - assert ( - result.output - == """Usage: cli server list [OPTIONS] PROJECT -Try 'cli server list --help' for help. -Error: You can't specify the `--verbose` flag and also pass the `--format` option -""" + assert result.exit_code == 2 + assert result.output == ( + "Usage: cli server list [OPTIONS] PROJECT\n" + "Try 'cli server list --help' for help.\n" + "\n" + "Error: You can't specify the `--verbose` flag " + "and also pass the `--format` option\n" )