Skip to content

Commit

Permalink
Merge branch 'main' into perf/cli-load
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Nov 2, 2024
2 parents c4aa540 + 0c43363 commit 31a0cc1
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 37 deletions.
2 changes: 1 addition & 1 deletion docs/userguides/managing.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ logging in to the Platform using [`silverback login`][silverback-login].

A Workspace is an area for one or more people to co-manage a set of clusters together. You can manage workspaces from the Silverback CLI using [`silverback cluster workspaces`][silverback-cluster-workspaces].

Using the Silverback CLI you can [list workspaces][silverback-cluster-workspaces-list], [make new ones][silverback-cluster-workspaces-new], [view their configuration information][silverback-cluster-workspaces-info], [update their metadata][silverback-cluster-workspaces-update], as well as [delete them][silverback-cluster-workspaces-delete] workspaces.
Using the Silverback CLI you can [list workspaces][silverback-cluster-workspaces-list], [make new ones][silverback-cluster-workspaces-new], [view their configuration information][silverback-cluster-workspaces-info], [update their metadata][silverback-cluster-workspaces-update], as well as [delete them][silverback-cluster-workspaces-delete].

## Managing a Cluster

Expand Down
62 changes: 29 additions & 33 deletions silverback/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,39 +228,38 @@ def workspace_info(platform: "PlatformClient", workspace: str):
"-n",
"--name",
"workspace_name",
required=True,
help="Name for new workspace",
)
@click.option(
"-s",
"--slug",
"workspace_slug",
required=True,
help="Slug for new workspace",
)
@platform_client
def new_workspace(
platform: "PlatformClient",
workspace_name: str,
workspace_slug: str,
workspace_name: str | None,
workspace_slug: str | None,
):
"""Create a new workspace"""

if workspace_name:
click.echo(f"name: {workspace_name}")
click.echo(f"slug: {workspace_slug or workspace_name.lower().replace(' ', '-')}")

elif workspace_slug:
click.echo(f"slug: {workspace_slug}")
workspace_name = workspace_name or workspace_slug
workspace_slug = workspace_slug or (
workspace_name.lower().replace(" ", "-") if workspace_name else None
)

else:
if not workspace_name:
raise click.UsageError("Must provide a name or a slug/name combo")

platform.create_workspace(
workspace = platform.create_workspace(
workspace_name=workspace_name,
workspace_slug=workspace_slug,
)
click.echo(f"{click.style('SUCCESS', fg='green')}: Created '{workspace_name}'")
click.echo(
f"{click.style('SUCCESS', fg='green')}: "
f"Created '{workspace.name}' (slug: '{workspace.slug}')"
)


@workspaces.command(name="update", section="Platform Commands (https://silverback.apeworx.io)")
Expand Down Expand Up @@ -330,8 +329,9 @@ def list_clusters(platform: "PlatformClient", workspace: str):
if not (workspace_client := platform.workspaces.get(workspace)):
raise click.BadOptionUsage("workspace", f"Unknown workspace '{workspace}'")

if cluster_names := list(workspace_client.clusters):
click.echo(yaml.safe_dump(cluster_names))
if clusters := workspace_client.clusters.values():
cluster_info = [f"- {cluster.name} ({cluster.status})" for cluster in clusters]
click.echo("\n".join(cluster_info))

else:
click.secho("No clusters for this account", bold=True, fg="red")
Expand Down Expand Up @@ -363,14 +363,12 @@ def new_cluster(
if not (workspace_client := platform.workspaces.get(workspace)):
raise click.BadOptionUsage("workspace", f"Unknown workspace '{workspace}'")

if cluster_name:
click.echo(f"name: {cluster_name}")
click.echo(f"slug: {cluster_slug or cluster_name.lower().replace(' ', '-')}")

elif cluster_slug:
click.echo(f"slug: {cluster_slug}")
cluster_name = cluster_name or cluster_slug
cluster_slug = cluster_slug or (
cluster_name.lower().replace(" ", "-") if cluster_name else None
)

else:
if not cluster_name:
raise click.UsageError("Must provide a name or a slug/name combo")

from silverback.cluster.types import ResourceStatus
Expand All @@ -379,7 +377,9 @@ def new_cluster(
cluster_name=cluster_name,
cluster_slug=cluster_slug,
)
click.echo(f"{click.style('SUCCESS', fg='green')}: Created '{cluster.name}'")
click.echo(
f"{click.style('SUCCESS', fg='green')}: Created '{cluster.name}' (slug: '{cluster.slug}')"
)

if cluster.status == ResourceStatus.CREATED:
click.echo(
Expand Down Expand Up @@ -658,7 +658,7 @@ def fund_payment_stream(
)

elif cluster.status != ResourceStatus.RUNNING:
raise click.UsageError(f"Cannot fund '{cluster_info.name}': cluster is not running.")
raise click.UsageError(f"Cannot fund '{cluster.name}': cluster is not running.")

elif not (stream := workspace_client.get_payment_stream(cluster, network.chain_id)):
raise click.UsageError("Cluster is not funded via ApePay Stream")
Expand Down Expand Up @@ -728,9 +728,6 @@ def cancel_payment_stream(
f"Unknown cluster in workspace '{workspace_name}': '{cluster_name}'"
)

elif cluster.status != ResourceStatus.RUNNING:
raise click.UsageError(f"Cannot fund '{cluster_info.name}': cluster is not running.")

elif not (stream := workspace_client.get_payment_stream(cluster, network.chain_id)):
raise click.UsageError("Cluster is not funded via ApePay Stream")

Expand All @@ -749,12 +746,11 @@ def cluster_info(cluster: "ClusterClient"):

# NOTE: This actually doesn't query the cluster's routes, which are protected
click.echo(f"Cluster Version: v{cluster.version}")

if config := cluster.state.configuration:
click.echo(yaml.safe_dump(config.settings_display_dict()))

else:
click.secho("No Cluster Configuration detected", fg="yellow", bold=True)
# TODO: Add way to fetch config and display it (this doesn't work)
# if config := cluster.state.configuration:
# click.echo(yaml.safe_dump(config.settings_display_dict()))
# else:
# click.secho("No Cluster Configuration detected", fg="yellow", bold=True)


@cluster.command(name="health")
Expand Down
7 changes: 4 additions & 3 deletions silverback/cluster/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from apepay import Stream, StreamManager
from pydantic import computed_field

from silverback.exceptions import ClientError
from silverback.version import version

from .types import (
Expand Down Expand Up @@ -54,7 +55,7 @@ def render_error(error: dict):
else:
message = response.text

raise RuntimeError(message)
raise ClientError(message)

response.raise_for_status()

Expand Down Expand Up @@ -480,8 +481,8 @@ def workspaces(self) -> dict[str, Workspace]:

def create_workspace(
self,
workspace_slug: str = "",
workspace_name: str = "",
workspace_slug: str | None = None,
workspace_name: str | None = None,
) -> Workspace:
response = self.post(
"/workspaces",
Expand Down
6 changes: 6 additions & 0 deletions silverback/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Any

import click
from ape.exceptions import ApeException

from .types import TaskType
Expand Down Expand Up @@ -41,6 +42,11 @@ def __init__(self, *exceptions: Exception | str):
super().__init__("Startup failure(s) detected. See logs for details.")


# NOTE: Subclass `click.UsageError` here so bad requests in CLI don't show stack trace
class ClientError(SilverbackException, click.UsageError):
"""Exception for client errors in the HTTP request."""


class NoTasksAvailableError(SilverbackException):
def __init__(self):
super().__init__("No tasks to execute")
Expand Down

0 comments on commit 31a0cc1

Please sign in to comment.