diff --git a/cratedb_toolkit/cluster/croud.py b/cratedb_toolkit/cluster/croud.py index 6fc81881..ddcc71b1 100644 --- a/cratedb_toolkit/cluster/croud.py +++ b/cratedb_toolkit/cluster/croud.py @@ -1,4 +1,5 @@ import json +import os import typing as t from pathlib import Path @@ -11,7 +12,25 @@ class CloudManager: A wrapper around the CrateDB Cloud API through the `croud` package, providing common methods. """ - def get_cluster_list(self): + def list_subscriptions(self): + """ + Get list of clusters + + croud clusters list --format=json + """ + from croud.__main__ import command_tree + from croud.subscriptions.commands import subscriptions_list + + call = CroudCall( + fun=subscriptions_list, + specs=command_tree["subscriptions"]["commands"]["list"]["extra_args"], + arguments=[], + ) + + wr = CroudWrapper(call=call) + return wr.invoke() + + def list_clusters(self): """ Get list of clusters @@ -66,7 +85,7 @@ def create_project(self, name: str): wr = CroudWrapper(call=call) return wr.invoke() - def deploy_cluster(self, name: str, project_id: str): + def deploy_cluster(self, name: str, project_id: str, subscription_id: str = None): """ Deploy cluster. @@ -85,11 +104,32 @@ def deploy_cluster(self, name: str, project_id: str): from croud.__main__ import command_tree from croud.clusters.commands import clusters_deploy + # TODO: Refactor elsewhere. + subscription_id = subscription_id or os.environ.get("CRATEDB_CLOUD_SUBSCRIPTION_ID") + + # Automatically use subscription, if there is only a single one. Otherwise, croak. + if subscription_id is None: + subscriptions = self.list_subscriptions() + if not subscriptions: + raise ValueError("Not selecting a subscription automatically, because there are none.") + if len(subscriptions) > 1: + subscriptions_text = json.dumps(subscriptions, indent=2) + raise ValueError( + "Not selecting a subscription automatically, because there is more than one in your " # noqa: S608 + "account. Please select one from this list by choosing the relevant UUID from the " + f"`id` attribute, and supply it to the `CRATEDB_CLOUD_SUBSCRIPTION_ID` environment " + f"variable:\n{subscriptions_text}" + ) + subscription_id = subscriptions[0]["id"] + + if subscription_id is None: + raise ValueError("Failed to obtain a subscription identifier") + call = CroudCall( fun=clusters_deploy, specs=command_tree["clusters"]["commands"]["deploy"]["extra_args"], arguments=[ - "--subscription-id=ba8592d2-b85b-4b21-b1c1-fbb99bc3c419", + f"--subscription-id={subscription_id}", f"--project-id={project_id}", "--tier=default", "--product-name=crfree", diff --git a/cratedb_toolkit/cluster/util.py b/cratedb_toolkit/cluster/util.py index b9c2f3d1..08ba912f 100644 --- a/cratedb_toolkit/cluster/util.py +++ b/cratedb_toolkit/cluster/util.py @@ -14,17 +14,18 @@ def get_cluster_info(cluster_id: str) -> ClusterInformation: def get_cluster_by_name(cluster_name: str) -> ClusterInformation: cm = CloudManager() - cluster_list = cm.get_cluster_list() + cluster_list = cm.list_clusters() for cluster in cluster_list: if cluster["name"] == cluster_name: return ClusterInformation(cloud=cluster) raise CroudException(f"Cluster not found: {cluster_name}") -def deploy_cluster(cluster_name: str) -> ClusterInformation: +def deploy_cluster(cluster_name: str, subscription_id: str = None) -> ClusterInformation: cm = CloudManager() + # TODO: Only create new project when needed. Otherwise, use existing project. project = cm.create_project(name=cluster_name) project_id = project["id"] logger.info(f"Created project: {project_id}") - cluster_info = cm.deploy_cluster(name=cluster_name, project_id=project_id) + cluster_info = cm.deploy_cluster(name=cluster_name, project_id=project_id, subscription_id=subscription_id) return cluster_info diff --git a/examples/cloud_cluster.py b/examples/cloud_cluster.py index 435c8ca8..ef87650a 100644 --- a/examples/cloud_cluster.py +++ b/examples/cloud_cluster.py @@ -18,6 +18,10 @@ # Log in to CrateDB Cloud. croud login --idp azuread + # Optional: If your account uses multiple subscriptions, you will need + # to select a specific one for invoking the cluster deployment operation. + export CRATEDB_CLOUD_SUBSCRIPTION_ID=f33a2f55-17d1-4f21-8130-b6595d7c52db + # Initialize a cluster instance. python examples/cloud_cluster.py --cluster-name Hotzenplotz