Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/added-20260403-104100.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: added
body: adds purge flag to rm command (permanent delete)
time: 2026-04-03T10:41:00.7101911+03:00
custom:
Author: v-alexmoraru
AuthorLink: https://github.com/v-alexmoraru
10 changes: 9 additions & 1 deletion docs/commands/fs/rm.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,24 @@ Delete a workspace, item, or file.
**Usage:**

```
fab rm <path> [-f]
fab rm <path> [-f] [--purge]
```

**Parameters:**

- `<path>`: Path to delete.
- `-f, --force`: Force deletion without confirmation. Optional.
- `--purge`: Permanently delete items (when applicable). Cannot be recovered. Ignored for workspace force deletion. Optional.

**Example:**

```
# Soft delete
fab rm ws1.Workspace/nb1.Notebook

# Force delete without confirmation
fab rm ws1.Workspace/nb1.Notebook --force

# Purge delete (permanent removal)
fab rm ws1.Workspace/nb1.Notebook --purge --force
```
29 changes: 23 additions & 6 deletions src/fabric_cli/client/fab_api_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,29 @@ def delete_resource(
verbose: bool = True,
operation: Optional[str] = "delete",
) -> bool:
purge = bool(getattr(args, 'purge', False))

if not bypass_confirmation:
if utils_ui.prompt_confirm():
return _do_delete_resource(args, operation=operation)
if purge:
resource_name = getattr(args, 'name', 'resource')
confirm_message = f"'{resource_name}' will be deleted forever. Are you sure you want to proceed?"
else:
confirm_message = "Are you sure?"

if utils_ui.prompt_confirm(confirm_message):
if purge and verbose:
utils_ui.print_warning("! Executing purge delete")
return _do_delete_resource(args, verbose=verbose, operation=operation)
else:
if verbose:
utils_ui.print_warning(f"Resource {operation} cancelled")
return False
else:
if verbose:
utils_ui.print_warning(f"Executing force {operation}...")
if purge:
utils_ui.print_warning("! Executing force purge delete")
else:
utils_ui.print_warning(f"Executing force {operation}...")
return _do_delete_resource(args, verbose=verbose, operation=operation)


Expand Down Expand Up @@ -125,7 +138,8 @@ def get_api_version(resource_uri: str) -> Any:
return rt["apiVersions"][0]

raise FabricCLIError(
ErrorMessages.Client.resource_type_not_found_in_provider(args.resource_type, args.provider_namespace),
ErrorMessages.Client.resource_type_not_found_in_provider(
args.resource_type, args.provider_namespace),
status_code=constant.ERROR_NOT_SUPPORTED,
)

Expand All @@ -136,7 +150,8 @@ def _do_delete_resource(
) -> bool:
if verbose:
if operation is not None:
utils_ui.print_grey(f"{_to_gerund_capitalized(operation)} '{args.name}'...")
utils_ui.print_grey(
f"{_to_gerund_capitalized(operation)} '{args.name}'...")
response = fabric_api.do_request(args)

return _validate_success_and_print_on_verbose(
Expand Down Expand Up @@ -187,6 +202,7 @@ def _do_unassign_resource(
args, "unassigned", response.status_code, verbose
)


def _to_gerund_capitalized(operation: str) -> str:
if operation.endswith("e") and not operation.endswith("ee"):
result = f"{operation[:-1]}ing"
Expand All @@ -200,7 +216,8 @@ def _validate_success_and_print_on_verbose(
) -> bool:
if status_code in [200, 201]:
if verbose:
utils_ui.print_output_format(args, message=f"'{args.name}' {action}")
utils_ui.print_output_format(
args, message=f"'{args.name}' {action}")
return True
if status_code == 202:
if verbose:
Expand Down
3 changes: 3 additions & 0 deletions src/fabric_cli/commands/fs/rm/fab_fs_rm_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from fabric_cli.client import fab_api_item as item_api
from fabric_cli.core.hiearchy.fab_hiearchy import Item
from fabric_cli.utils import fab_mem_store as utils_mem_store
from fabric_cli.utils import fab_util as utils


def exec(item: Item, args: Namespace, force_delete: bool) -> None:
Expand All @@ -14,6 +15,8 @@ def exec(item: Item, args: Namespace, force_delete: bool) -> None:
args.name = item.name
args.item_type = item.type.value

utils.setup_delete_request_params(args)

if item_api.delete_item(args, force_delete):
# Remove from mem_store
utils_mem_store.delete_item_from_cache(item)
23 changes: 16 additions & 7 deletions src/fabric_cli/commands/fs/rm/fab_fs_rm_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

def bulk(tenant: Tenant, args: Namespace, force_delete: bool) -> None:
workspaces: list[Workspace] = utils_mem_store.get_workspaces(tenant)
sorted_workspaces: list[Workspace] = sorted(workspaces, key=lambda ws: ws.name)
sorted_workspaces: list[Workspace] = sorted(
workspaces, key=lambda ws: ws.name)

names = [workspace.name for workspace in sorted_workspaces]
selected_workspaces = utils_ui.prompt_select_items("Select workspaces:", names)
selected_workspaces = utils_ui.prompt_select_items(
"Select workspaces:", names)
if selected_workspaces:
for workspace_str in selected_workspaces:
utils_ui.print_grey(workspace_str)
Expand Down Expand Up @@ -51,7 +53,8 @@ def bulk(tenant: Tenant, args: Namespace, force_delete: bool) -> None:
utils_mem_store.delete_workspace_from_cache(workspace)

utils_ui.print("")
utils_ui.print_output_format(args, message=f"{deleted_workspaces} workspaces deleted successfully")
utils_ui.print_output_format(
args, message=f"{deleted_workspaces} workspaces deleted successfully")


def single(workspace: Workspace, args: Namespace, force_delete: bool) -> None:
Expand All @@ -77,7 +80,8 @@ def single(workspace: Workspace, args: Namespace, force_delete: bool) -> None:
pass

if force_delete:
utils_ui.print_grey(f"This will delete {len(ws_items)} underlying items")
utils_ui.print_grey(
f"This will delete {len(ws_items)} underlying items")

if workspace_api.delete_workspace(args, force_delete):
# Remove from mem_store
Expand All @@ -94,7 +98,8 @@ def single(workspace: Workspace, args: Namespace, force_delete: bool) -> None:
sorted_items = item_utils.sort_ws_elems_by_config(supported_items)

names = [item.name for item in sorted_items]
selected_items = utils_ui.prompt_select_items("Select items:", names)
selected_items = utils_ui.prompt_select_items(
"Select items:", names)
if selected_items:
for item_str in selected_items:
utils_ui.print_grey(item_str)
Expand All @@ -113,18 +118,22 @@ def single(workspace: Workspace, args: Namespace, force_delete: bool) -> None:
args.name = item.name
args.item_type = str(item.item_type)

utils.setup_delete_request_params(args)

# Reset args for subsequent calls
args.uri = None
args.method = None

if item_api.delete_item(
args, bypass_confirmation=True, verbose=False
):
utils_ui.print_output_format(args, message=f"'{args.name}' deleted")
utils_ui.print_output_format(
args, message=f"'{args.name}' deleted")
deleted_items = deleted_items + 1

# Remove from mem_store
utils_mem_store.delete_item_from_cache(item)

utils_ui.print("")
utils_ui.print_output_format(args, message=f"{deleted_items} items deleted successfully")
utils_ui.print_output_format(
args, message=f"{deleted_items} items deleted successfully")
Loading
Loading