Path: blob/main/singlestoredb/fusion/handlers/workspace.py
801 views
#!/usr/bin/env python31import json2from typing import Any3from typing import Dict4from typing import Optional56from .. import result7from ..handler import SQLHandler8from ..result import FusionSQLResult9from .utils import dt_isoformat10from .utils import get_workspace11from .utils import get_workspace_group12from .utils import get_workspace_manager131415class UseWorkspaceHandler(SQLHandler):16"""17USE WORKSPACE workspace [ in_group ] [ with_database ];1819# Workspace20workspace = { workspace_id | workspace_name | current_workspace }2122# ID of workspace23workspace_id = ID '<workspace-id>'2425# Name of workspace26workspace_name = '<workspace-name>'2728# Current workspace29current_workspace = @@CURRENT3031# Workspace group specification32in_group = IN GROUP { group_id | group_name }3334# ID of workspace group35group_id = ID '<group-id>'3637# Name of workspace group38group_name = '<group-name>'3940# Name of database41with_database = WITH DATABASE 'database-name'4243Description44-----------45Change the workspace and database in the notebook.4647Arguments48---------49* ``<workspace-id>``: The ID of the workspace to use.50* ``<workspace-name>``: The name of the workspace to use.51* ``<group-id>``: The ID of the workspace group to search in.52* ``<group-name>``: The name of the workspace group to search in.5354Remarks55-------56* If you want to specify a database in the current workspace,57the workspace name can be specified as ``@@CURRENT``.58* Use the ``IN GROUP`` clause to specify the ID or name of the workspace59group where the workspace should be found. If not specified, the current60workspace group will be used.61* Specify the ``WITH DATABASE`` clause to select a default62database for the session.63* This command only works in a notebook session in the64Managed Service.6566Example67-------68The following command sets the workspace to ``examplews`` and69select 'dbname' as the default database::7071USE WORKSPACE 'examplews' WITH DATABASE 'dbname';7273The following command sets the workspace to ``examplews`` from a specific74workspace group::7576USE WORKSPACE 'examplews' IN GROUP 'my-workspace-group';7778"""79def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:80from singlestoredb.notebook import portal8182# Handle current workspace case83if params['workspace'].get('current_workspace'):84if params.get('with_database'):85portal.default_database = params['with_database']86return None8788# Get workspace name or ID89workspace_name = params['workspace'].get('workspace_name')90workspace_id = params['workspace'].get('workspace_id')9192# If IN GROUP is specified, look up workspace in that group93if params.get('in_group'):94workspace_group = get_workspace_group(params)9596if workspace_name:97workspace = workspace_group.workspaces[workspace_name]98elif workspace_id:99# Find workspace by ID in the specified group100workspace = next(101(w for w in workspace_group.workspaces if w.id == workspace_id),102None,103)104if workspace is None:105raise KeyError(f'no workspace found with ID: {workspace_id}')106107workspace_id = workspace.id108109try:110# Set workspace and database111if params.get('with_database'):112if params.get('in_group'):113# Use 3-element tuple: (workspace_group_id, workspace_name_or_id,114# database)115portal.connection = ( # type: ignore[assignment]116workspace_group.id,117workspace_name or workspace_id,118params['with_database'],119)120else:121# Use 2-element tuple: (workspace_name_or_id, database)122portal.connection = (123workspace_name or workspace_id,124params['with_database'],125)126else:127if params.get('in_group'):128# Use 2-element tuple: (workspace_group_id, workspace_name_or_id)129portal.workspace = ( # type: ignore[assignment]130workspace_group.id,131workspace_name or workspace_id,132)133else:134# Use string: workspace_name_or_id135portal.workspace = workspace_name or workspace_id136137except RuntimeError as exc:138if 'timeout' not in str(exc):139raise140141return None142143144UseWorkspaceHandler.register(overwrite=True)145146147class ShowRegionsHandler(SQLHandler):148"""149SHOW REGIONS [ <like> ]150[ <order-by> ]151[ <limit> ];152153Description154-----------155Returns a list of all the valid regions for the user.156157Arguments158---------159* ``<pattern>``: A pattern similar to SQL LIKE clause.160Uses ``%`` as the wildcard character.161162Remarks163-------164* Use the ``LIKE`` clause to specify a pattern and return only the165regions that match the specified pattern.166* The ``LIMIT`` clause limits the number of results to the167specified number.168* Use the ``ORDER BY`` clause to sort the results by the specified169key. By default, the results are sorted in the ascending order.170171Example172-------173The following command returns a list of all the regions in the US174and sorts the results in ascending order by their ``Name``::175176SHOW REGIONS LIKE 'US%' ORDER BY Name;177178"""179180def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:181manager = get_workspace_manager()182183res = FusionSQLResult()184res.add_field('Name', result.STRING)185res.add_field('ID', result.STRING)186res.add_field('Provider', result.STRING)187188res.set_rows([(x.name, x.id, x.provider) for x in manager.regions])189190if params['like']:191res = res.like(Name=params['like'])192193return res.order_by(**params['order_by']).limit(params['limit'])194195196ShowRegionsHandler.register(overwrite=True)197198199class ShowWorkspaceGroupsHandler(SQLHandler):200"""201SHOW WORKSPACE GROUPS [ <like> ]202[ <extended> ] [ <order-by> ]203[ <limit> ];204205Description206-----------207Displays information on workspace groups.208209Arguments210---------211* ``<pattern>``: A pattern similar to SQL LIKE clause.212Uses ``%`` as the wildcard character.213214Remarks215-------216* Use the ``LIKE`` clause to specify a pattern and return only the217workspace groups that match the specified pattern.218* The ``LIMIT`` clause limits the number of results to the219specified number.220* Use the ``ORDER BY`` clause to sort the results by the specified221key. By default, the results are sorted in the ascending order.222* To return more information about the workspace groups, use the223``EXTENDED`` clause.224225Example226-------227The following command displays a list of workspace groups with names228that match the specified pattern::229230SHOW WORKSPACE GROUPS LIKE 'Marketing%' EXTENDED ORDER BY Name;231232See Also233--------234* ``SHOW WORKSPACES``235236"""237238def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:239manager = get_workspace_manager()240241res = FusionSQLResult()242res.add_field('Name', result.STRING)243res.add_field('ID', result.STRING)244res.add_field('Region', result.STRING)245res.add_field('FirewallRanges', result.JSON)246247if params['extended']:248res.add_field('CreatedAt', result.DATETIME)249res.add_field('TerminatedAt', result.DATETIME)250251def fields(x: Any) -> Any:252return (253x.name, x.id, x.region.name,254json.dumps(x.firewall_ranges),255dt_isoformat(x.created_at),256dt_isoformat(x.terminated_at),257)258else:259def fields(x: Any) -> Any:260return (x.name, x.id, x.region.name, json.dumps(x.firewall_ranges))261262res.set_rows([fields(x) for x in manager.workspace_groups])263264if params['like']:265res = res.like(Name=params['like'])266267return res.order_by(**params['order_by']).limit(params['limit'])268269270ShowWorkspaceGroupsHandler.register(overwrite=True)271272273class ShowWorkspacesHandler(SQLHandler):274"""275SHOW WORKSPACES [ in_group ]276[ <like> ] [ <extended> ]277[ <order-by> ] [ <limit> ];278279# Workspace group280in_group = IN GROUP { group_id | group_name }281282# ID of group283group_id = ID '<group-id>'284285# Name of group286group_name = '<group-name>'287288Description289-----------290Displays information on workspaces in a workspace group.291292Arguments293---------294* ``<group_id>``: The ID of the workspace group that contains295the workspace.296* ``<group_name>``: The name of the workspace group that297contains the workspace.298* ``<pattern>``: A pattern similar to SQL LIKE clause.299Uses ``%`` as the wildcard character.300301Remarks302-------303* The ``IN GROUP`` clause specifies the ID or the name of the304workspace group that contains the workspace.305* Use the ``LIKE`` clause to specify a pattern and return only306the workspaces that match the specified pattern.307* The ``LIMIT`` clause limits the number of results to the308specified number.309* Use the ``ORDER BY`` clause to sort the results by the310specified key. By default, the results are sorted in the311ascending order.312* To return more information about the workspaces, use the313``EXTENDED`` clause.314315Example316-------317The following command displays information on all the workspaces318in a workspace group named **wsg1** and sorts the results by319workspace name in the ascending order::320321SHOW WORKSPACES IN GROUP 'wsg1' EXTENDED ORDER BY Name;322323See Also324--------325* ``SHOW WORKSPACE GROUPS``326327"""328329def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:330res = FusionSQLResult()331res.add_field('Name', result.STRING)332res.add_field('ID', result.STRING)333res.add_field('Size', result.STRING)334res.add_field('State', result.STRING)335336workspace_group = get_workspace_group(params)337338if params['extended']:339res.add_field('Endpoint', result.STRING)340res.add_field('CreatedAt', result.DATETIME)341res.add_field('TerminatedAt', result.DATETIME)342343def fields(x: Any) -> Any:344return (345x.name, x.id, x.size, x.state,346x.endpoint, dt_isoformat(x.created_at),347dt_isoformat(x.terminated_at),348)349else:350def fields(x: Any) -> Any:351return (x.name, x.id, x.size, x.state)352353res.set_rows([fields(x) for x in workspace_group.workspaces])354355if params['like']:356res = res.like(Name=params['like'])357358return res.order_by(**params['order_by']).limit(params['limit'])359360361ShowWorkspacesHandler.register(overwrite=True)362363364class CreateWorkspaceGroupHandler(SQLHandler):365"""366CREATE WORKSPACE GROUP [ if_not_exists ] group_name367IN REGION { region_id | region_name }368[ with_password ]369[ expires_at ]370[ with_firewall_ranges ]371[ with_backup_bucket_kms_key_id ]372[ with_data_bucket_kms_key_id ]373[ with_smart_dr ]374[ allow_all_traffic ]375[ with_update_window ]376;377378# Only create workspace group if it doesn't exist already379if_not_exists = IF NOT EXISTS380381# Name of the workspace group382group_name = '<group-name>'383384# ID of region to create workspace group in385region_id = ID '<region-id>'386387# Name of region to create workspace group in388region_name = '<region-name>'389390# Admin password391with_password = WITH PASSWORD '<password>'392393# Datetime or interval for expiration date/time of workspace group394expires_at = EXPIRES AT '<iso-datetime-or-interval>'395396# Incoming IP ranges397with_firewall_ranges = WITH FIREWALL RANGES '<ip-range>',...398399# Backup bucket key400with_backup_bucket_kms_key_id = WITH BACKUP BUCKET KMS KEY ID '<key-id>'401402# Data bucket key403with_data_bucket_kms_key_id = WITH DATA BUCKET KMS KEY ID '<key-id>'404405# Smart DR406with_smart_dr = WITH SMART DR407408# Allow all incoming traffic409allow_all_traffic = ALLOW ALL TRAFFIC410411# Update window412with_update_window = WITH UPDATE WINDOW '<day>:<hour>'413414Description415-----------416Creates a workspace group.417418Arguments419---------420* ``<group-name>``: The name of the workspace group.421* ``<region_id>`` or ``<region_name>``: The ID or the name of the region422in which the new workspace group is created.423* ``<password>``: The admin password of the workspace group.424The password must contain:425- At least 8 characters426- At least one uppercase character427- At least one lowercase character428- At least one number or special character429* ``<expiry_time>``: The timestamp of when the workspace group terminates.430Expiration time can be specified as a timestamp or duration.431* ``<ip_range>``: A list of allowed IP addresses or CIDR ranges.432* ``<backup_key_id>``: The KMS key ID associated with the backup bucket.433* ``<data_key_id>``: The KMS key ID associated with the data bucket.434* ``<day>:<hour>``: The day of the week (0-6) and the hour of the day435(0-23) when the engine updates are applied to the workspace group.436437Remarks438-------439* Specify the ``IF NOT EXISTS`` clause to create a new workspace group only440if a workspace group with the specified name does not exist.441* If the ``WITH BACKUP BUCKET KMS KEY ID '<backup_key_id>'`` clause is442specified, Customer-Managed Encryption Keys (CMEK) encryption is enabled443for the data bucket of the workspace group.444* If the ``WITH DATA BUCKET KMS KEY ID '<data_key_id>'`` clause is specified,445CMEK encryption for the data bucket and Amazon Elastic Block Store (EBS)446volumes of the workspace group is enabled.447* To enable Smart Disaster Recovery (SmartDR) for the workspace group, specify448the WITH SMART DR clause. Refer to Smart Disaster Recovery (DR):449SmartDR for more information.450* To allow incoming traffic from any IP address, use the ``ALLOW ALL TRAFFIC``451clause.452453Examples454--------455The following command creates a workspace group named wsg1 in the456US East 2 (Ohio) region::457458CREATE WORKSPACE GROUP 'wsg1' IN REGION 'US East 2 (Ohio)';459460The following command specifies additional workspace group configuration461options::462463CREATE WORKSPACE GROUP 'wsg1'464IN REGION ID '93b61160-0000-1000-9000-977b8e2e3ee5'465WITH FIREWALL RANGES '0.0.0.0/0';466467See Also468--------469* ``SHOW WORKSPACE GROUPS``470471"""472473def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:474manager = get_workspace_manager()475476# Only create if one doesn't exist477if params['if_not_exists']:478try:479get_workspace_group(params)480return None481except (ValueError, KeyError):482pass483484# Get region ID485if params['region_name']:486regs = [x for x in manager.regions if x.name == params['region_name']]487if not regs:488raise KeyError(f'no region found with name "{params["region_name"]}"')489if len(regs) > 1:490raise ValueError(491f'multiple regions found with the name "{params["region_name"]}"',492)493region_id = regs[0].id494else:495region_id = params['region_id']496497with_update_window = None498if params['with_update_window']:499day, hour = params['with_update_window'].split(':', 1)500with_update_window = dict(day=int(day), hour=int(hour))501502manager.create_workspace_group(503params['group_name'],504region=region_id,505admin_password=params['with_password'],506expires_at=params['expires_at'],507firewall_ranges=params['with_firewall_ranges'],508backup_bucket_kms_key_id=params['with_backup_bucket_kms_key_id'],509data_bucket_kms_key_id=params['with_data_bucket_kms_key_id'],510smart_dr=params['with_smart_dr'],511allow_all_traffic=params['allow_all_traffic'],512update_window=with_update_window,513)514515return None516517518CreateWorkspaceGroupHandler.register(overwrite=True)519520521class CreateWorkspaceHandler(SQLHandler):522"""523CREATE WORKSPACE [ if_not_exists ] workspace_name524[ in_group ]525WITH SIZE size526[ auto_suspend ]527[ enable_kai ]528[ with_cache_config ]529[ wait_on_active ];530531# Create workspace in workspace group532in_group = IN GROUP { group_id | group_name }533534# Only run command if workspace doesn't already exist535if_not_exists = IF NOT EXISTS536537# Name of the workspace538workspace_name = '<workspace-name>'539540# ID of the group to create workspace in541group_id = ID '<group-id>'542543# Name of the group to create workspace in544group_name = '<group-name>'545546# Runtime size547size = '<size>'548549# Auto-suspend550auto_suspend = AUTO SUSPEND AFTER suspend_after_value suspend_after_units suspend_type551suspend_after_value = <integer>552suspend_after_units = { SECONDS | MINUTES | HOURS | DAYS }553suspend_type = WITH TYPE { IDLE | SCHEDULED | DISABLED }554555# Enable Kai556enable_kai = ENABLE KAI557558# Cache config559with_cache_config = WITH CACHE CONFIG <integer>560561# Wait for workspace to be active before continuing562wait_on_active = WAIT ON ACTIVE563564Description565-----------566Creates a new workspace. Refer to567`Creating and Using Workspaces <https://docs.singlestore.com/cloud/getting-started-with-singlestore-helios/about-workspaces/creating-and-using-workspaces/>`_568for more information.569570Arguments571---------572* ``<workspace_name>``: The name of the workspace.573* ``<group_id>`` or ``<group_name>``: The ID or name of the workspace group574in which the workspace is created.575* ``<workspace_size>``: The size of the workspace in workspace size notation,576for example "S-1".577* ``<suspend_time>``: The time (in given units) after which the workspace is578suspended, according to the specified auto-suspend type.579* ``<multiplier>``: The multiplier for the persistent cache associated with580the workspace.581582Remarks583-------584* Use the ``IF NOT EXISTS`` clause to create a new workspace only if a workspace585with the specified name does not exist.586* If the ``WITH CACHE CONFIG <multiplier>`` clause is specified, the cache587configuration multiplier is enabled for the workspace. It can have the588following values: 1, 2, or 4.589* The ``WAIT ON ACTIVE`` clause indicates that the execution is paused until this590workspace is in ACTIVE state.591* Specify the ``ENABLE KAI`` clause to enable SingleStore Kai and the MongoDB®592API for the workspace.593594Example595-------596The following command creates a workspace named **examplews** in a workspace597group named **wsg1**::598599CREATE WORKSPACE 'examplews' IN GROUP 'wsgroup1'600WITH SIZE 'S-00' WAIT ON ACTIVE;601602See Also603--------604* ``CREATE WORKSPACE GROUP``605606""" # noqa: E501607608def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:609workspace_group = get_workspace_group(params)610611# Only create if one doesn't exist612if params['if_not_exists']:613try:614workspace_group.workspaces[params['workspace_name']]615return None616except KeyError:617pass618619auto_suspend = None620if params['auto_suspend']:621mult = dict(622SECONDS=1,623MINUTES=60,624HOURS=60*60,625DAYS=60*60*24,626)627val = params['auto_suspend'][0]['suspend_after_value']628val = val * mult[params['auto_suspend'][1]['suspend_after_units'].upper()]629auto_suspend = dict(630suspend_after_seconds=val,631suspend_type=params['auto_suspend'][2]['suspend_type'].upper(),632)633634workspace_group.create_workspace(635params['workspace_name'],636size=params['size'],637auto_suspend=auto_suspend,638enable_kai=params['enable_kai'],639cache_config=params['with_cache_config'],640wait_on_active=params['wait_on_active'],641)642643return None644645646CreateWorkspaceHandler.register(overwrite=True)647648649class SuspendWorkspaceHandler(SQLHandler):650"""651SUSPEND WORKSPACE workspace652[ in_group ]653[ wait_on_suspended ];654655# Workspace656workspace = { workspace_id | workspace_name }657658# ID of workspace659workspace_id = ID '<workspace-id>'660661# Name of workspace662workspace_name = '<workspace-name>'663664# Workspace group665in_group = IN GROUP { group_id | group_name }666667# ID of workspace group668group_id = ID '<group-id>'669670# Name of workspace group671group_name = '<group-name>'672673# Wait for workspace to be suspended before continuing674wait_on_suspended = WAIT ON SUSPENDED675676Description677-----------678Suspends a workspace.679680Refer to `Manage Workspaces <https://docs.singlestore.com/cloud/user-and-workspace-administration/manage-organizations/manage-workspaces/>`_681for more information.682683Arguments684---------685* ``<workspace-id>``: The ID of the workspace to suspend.686* ``<workspace-name>``: The name of the workspace to suspend.687* ``<group-id>``: The ID of the workspace group that contains688the workspace.689* ``<group-name>``: The name of the workspace group that690contains the workspace.691692Remarks693-------694* Use the ``WAIT ON SUSPENDED`` clause to pause query execution695until the workspace is in the ``SUSPENDED`` state.696697Example698-------699The following example suspends a workspace named examplews in700a workspace group named **wsg1**::701702SUSPEND WORKSPACE 'examplews' IN GROUP 'wsg1';703704See Also705--------706* ``RESUME WORKSPACE``707708""" # noqa: E501709710def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:711ws = get_workspace(params)712ws.suspend(wait_on_suspended=params['wait_on_suspended'])713return None714715716SuspendWorkspaceHandler.register(overwrite=True)717718719class ResumeWorkspaceHandler(SQLHandler):720"""721RESUME WORKSPACE workspace722[ in_group ]723[ disable_auto_suspend ]724[ wait_on_resumed ];725726# Workspace727workspace = { workspace_id | workspace_name }728729# ID of workspace730workspace_id = ID '<workspace-id>'731732# Name of workspace733workspace_name = '<workspace-name>'734735# Workspace group736in_group = IN GROUP { group_id | group_name }737738# ID of workspace group739group_id = ID '<group-id>'740741# Name of workspace group742group_name = '<group-name>'743744# Disable auto-suspend745disable_auto_suspend = DISABLE AUTO SUSPEND746747# Wait for workspace to be resumed before continuing748wait_on_resumed = WAIT ON RESUMED749750Description751-----------752Resumes a workspace.753754Refer to `Manage Workspaces <https://docs.singlestore.com/cloud/user-and-workspace-administration/manage-organizations/manage-workspaces/>`_755for more information.756757Arguments758---------759* ``<workspace-id>``: The ID of the workspace to resume.760* ``<workspace-name>``: The name of the workspace to resume.761* ``<group_id>``: The ID of the workspace group that contains762the workspace.763* ``<group_name>``: The name of the workspace group that764contains the workspace.765766Remarks767-------768* Use the ``IN GROUP`` clause to specify the ID or name of the769workspace group that contains the workspace to resume.770* Use the ``WAIT ON RESUMED`` clause to pause query execution771until the workspace is in the ``RESUMED`` state.772* Specify the ``DISABLE AUTO SUSPEND`` clause to disable773auto-suspend for the resumed workspace.774775Example776-------777The following example resumes a workspace with the specified ID778in a workspace group named **wsg1**::779780RESUME WORKSPACE ID '93b61160-0000-1000-9000-977b8e2e3ee5'781IN GROUP 'wsg1';782783""" # noqa: E501784785def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:786ws = get_workspace(params)787ws.resume(788wait_on_resumed=params['wait_on_resumed'],789disable_auto_suspend=params['disable_auto_suspend'],790)791return None792793794ResumeWorkspaceHandler.register(overwrite=True)795796797class DropWorkspaceGroupHandler(SQLHandler):798"""799DROP WORKSPACE GROUP [ if_exists ]800group801[ wait_on_terminated ]802[ force ];803804# Only run command if the workspace group exists805if_exists = IF EXISTS806807# Workspace group808group = { group_id | group_name }809810# ID of the workspace group to delete811group_id = ID '<group-id>'812813# Name of the workspace group to delete814group_name = '<group-name>'815816# Wait for termination to complete before continuing817wait_on_terminated = WAIT ON TERMINATED818819# Should the workspace group be terminated even if it has workspaces?820force = FORCE821822Description823-----------824Deletes the specified workspace group.825826Arguments827---------828* ``<group_id>``: The ID of the workspace group to delete.829* ``<group_name>``: The name of the workspace group to delete.830831Remarks832-------833* Specify the ``IF EXISTS`` clause to attempt the delete operation834only if a workspace group with the specified ID or name exists.835* Use the ``WAIT ON TERMINATED`` clause to pause query execution until836the workspace group is in the ``TERMINATED`` state.837* If the ``FORCE`` clause is specified, the workspace group is838terminated even if it contains workspaces.839840Example841-------842The following command deletes a workspace group named **wsg1** even843if it contains workspaces::844845DROP WORKSPACE GROUP 'wsg1' FORCE;846847See Also848--------849* ``DROP WORKSPACE``850851"""852853def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:854try:855workspace_group = get_workspace_group(params)856if workspace_group.terminated_at is not None:857raise KeyError('workspace group is alread terminated')858workspace_group.terminate(859wait_on_terminated=params['wait_on_terminated'],860force=params['force'],861)862863except KeyError:864if not params['if_exists']:865raise866867return None868869870DropWorkspaceGroupHandler.register(overwrite=True)871872873class DropWorkspaceHandler(SQLHandler):874"""875DROP WORKSPACE [ if_exists ]876workspace877[ in_group ]878[ wait_on_terminated ];879880# Only drop workspace if it exists881if_exists = IF EXISTS882883# Workspace884workspace = { workspace_id | workspace_name }885886# ID of workspace887workspace_id = ID '<workspace-id>'888889# Name of workspace890workspace_name = '<workspace-name>'891892# Workspace group893in_group = IN GROUP { group_id | group_name }894895# ID of workspace group896group_id = ID '<group-id>'897898# Name of workspace group899group_name = '<group-name>'900901# Wait for workspace to be terminated before continuing902wait_on_terminated = WAIT ON TERMINATED903904Description905-----------906Deletes a workspace.907908Arguments909---------910* ``<workspace-id>``: The ID of the workspace to delete.911* ``<workspace-name>``: The name of the workspace to delete.912* ``<group_id>``: The ID of the workspace group that contains913the workspace.914* ``<group_name>``: The name of the workspace group that915contains the workspace.916917Remarks918-------919* Specify the ``IF EXISTS`` clause to attempt the delete operation920only if a workspace with the specified ID or name exists.921* Use the ``IN GROUP`` clause to specify the ID or name of the workspace922group that contains the workspace to delete.923* Use the ``WAIT ON TERMINATED`` clause to pause query execution until924the workspace is in the ``TERMINATED`` state.925* All databases attached to the workspace are detached when the926workspace is deleted (terminated).927928Example929-------930The following example deletes a workspace named **examplews** in931a workspace group **wsg1**::932933DROP WORKSPACE IF EXISTS 'examplews' IN GROUP 'wsg1';934935See Also936--------937* ``DROP WORKSPACE GROUP``938939"""940941def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:942try:943ws = get_workspace(params)944if ws.terminated_at is not None:945raise KeyError('workspace is already terminated')946ws.terminate(wait_on_terminated=params['wait_on_terminated'])947948except KeyError:949if not params['if_exists']:950raise951952return None953954955DropWorkspaceHandler.register(overwrite=True)956957958