Skip to content
Draft
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
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,57 @@ All notable changes to orca are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.0] — unreleased

### Removed (breaking)

- **Every ADR-0008 deprecated alias is gone.** The 314 hyphenated
legacy command names that 2.0.x → 2.3.x kept registering as
``deprecated=True`` aliases (each printing a yellow warning to
stderr before forwarding to the new path) are now removed
outright. Scripts that still call e.g. ``orca server attach-volume``,
``orca placement resource-provider-list``, or
``orca profile to-openrc`` must switch to the openstackclient
forms (``orca server volume add``, ``orca placement resource-provider list``,
``orca profile export openrc``). See ADR-0008 for the full mapping;
``orca doctor --list-deprecated`` on 2.3.x prints the table.
- **``orca_cli/core/aliases``** (private module) is dropped. Its
three exports (``add_command_with_alias``,
``count_deprecated_aliases``, ``list_deprecated_aliases``) had no
external consumers — the module existed solely to power the
alias-and-deprecate migration, which is now complete.
- **``orca doctor``** loses ``--list-deprecated`` and the
``ADR-0008: deprecated aliases`` row in its output. Both became
meaningless once the aliases were dropped.
- **Python 3.9 is no longer supported.** Already announced in 2.3.0
(``build!:`` commit), formally cuts in 3.0.0. Minimum is 3.10.
- **Two ratchet tests removed:** ``tests/test_naming_convention.py``
and ``tests/test_aliases.py``. The naming-convention check has no
legacy-name whitelist left to ratchet against; the alias-count
sanity check no longer applies.

### Migration guide

For ~95 % of legacy invocations the rule is mechanical:
``orca <top> <leaf-name-with-hyphen>`` becomes
``orca <top> <leaf> <name>`` (e.g. ``server list-volumes`` →
``server volume list``). A handful of compound-verb leaves keep
their hyphen by design — ``server confirm-resize``,
``server port-forward``, ``volume upload-to-image``,
``zone reverse-lookup``, ``image share-and-accept``,
``floating-ip bulk-release`` (full list in
``docs/adr/0008-command-naming-convention.md`` — *Permanent
exceptions*).

To audit a script before upgrading, run on 2.3.x:

```
orca doctor --list-deprecated
```

The table shows the legacy invocation alongside its 3.0.0
replacement.

## [2.3.0] — 2026-04-28

### Added
Expand Down
10 changes: 0 additions & 10 deletions orca_cli/commands/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.context import OrcaContext
from orca_cli.core.exceptions import OrcaCLIError
from orca_cli.core.output import console, output_options, print_detail, print_list
Expand Down Expand Up @@ -117,10 +116,6 @@ def aggregate_host_remove(ctx, aggregate_id, host):
console.print(f"[green]Host '{host}' removed from aggregate {aggregate_id}.[/green]")


add_command_with_alias(aggregate, aggregate_host_add,
legacy_name="add-host", primary_path="aggregate host add")
add_command_with_alias(aggregate, aggregate_host_remove,
legacy_name="remove-host", primary_path="aggregate host remove")


@aggregate.command("set")
Expand Down Expand Up @@ -194,8 +189,3 @@ def aggregate_image_cache(ctx, aggregate_id, image_ids):
svc = ComputeService(ctx.find_object(OrcaContext).ensure_client())
svc.cache_aggregate_images(aggregate_id, [{"id": iid} for iid in image_ids])
console.print(f"[green]Image caching requested on aggregate {aggregate_id}.[/green]")


add_command_with_alias(aggregate, aggregate_image_cache,
legacy_name="cache-image",
primary_path="aggregate image cache")
9 changes: 0 additions & 9 deletions orca_cli/commands/alarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.context import OrcaContext
from orca_cli.core.output import console, output_options, print_detail, print_list
from orca_cli.core.validators import validate_id
Expand Down Expand Up @@ -281,10 +280,6 @@ def alarm_state_set(ctx, alarm_id, state):
console.print(f"Alarm [bold]{alarm_id}[/bold] state set to [bold]{state}[/bold].")


add_command_with_alias(alarm, alarm_state_get,
legacy_name="state-get", primary_path="alarm state get")
add_command_with_alias(alarm, alarm_state_set,
legacy_name="state-set", primary_path="alarm state set")


# ══════════════════════════════════════════════════════════════════════════════
Expand Down Expand Up @@ -353,7 +348,3 @@ def alarm_quota_set(ctx, project_id, alarm_quota_value):
}
AlarmService(client).update_quota(body)
console.print(f"Quota for project [bold]{project_id}[/bold] set to [bold]{alarm_quota_value}[/bold] alarms.")


add_command_with_alias(alarm, alarm_quota_set,
legacy_name="quota-set", primary_path="alarm quota set")
7 changes: 0 additions & 7 deletions orca_cli/commands/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.config import (
_find_clouds_yaml,
_load_clouds_yaml,
Expand Down Expand Up @@ -315,9 +314,3 @@ def auth_token_revoke(ctx: click.Context, token: str) -> None:
client = ctx.find_object(OrcaContext).ensure_client()
IdentityService(client).revoke_token(token)
console.print("[green]Token revoked.[/green]")


add_command_with_alias(auth, auth_token_debug,
legacy_name="token-debug", primary_path="auth token debug")
add_command_with_alias(auth, auth_token_revoke,
legacy_name="token-revoke", primary_path="auth token revoke")
64 changes: 0 additions & 64 deletions orca_cli/commands/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.context import OrcaContext
from orca_cli.core.output import console, output_options, print_detail, print_list
from orca_cli.services.backup import BackupService
Expand Down Expand Up @@ -594,72 +593,9 @@ def action_delete(ctx: click.Context, action_id: str, yes: bool) -> None:
# ══════════════════════════════════════════════════════════════════════════

# Action aliases
add_command_with_alias(backup, action_list,
legacy_name="action-list",
primary_path="backup action list")
add_command_with_alias(backup, action_show,
legacy_name="action-show",
primary_path="backup action show")
add_command_with_alias(backup, action_create,
legacy_name="action-create",
primary_path="backup action create")
add_command_with_alias(backup, action_delete,
legacy_name="action-delete",
primary_path="backup action delete")

# Client aliases
add_command_with_alias(backup, client_list,
legacy_name="client-list",
primary_path="backup client list")
add_command_with_alias(backup, client_show,
legacy_name="client-show",
primary_path="backup client show")
add_command_with_alias(backup, client_register,
legacy_name="client-register",
primary_path="backup client register")
add_command_with_alias(backup, client_delete,
legacy_name="client-delete",
primary_path="backup client delete")

# Job aliases
add_command_with_alias(backup, job_list,
legacy_name="job-list",
primary_path="backup job list")
add_command_with_alias(backup, job_show,
legacy_name="job-show",
primary_path="backup job show")
add_command_with_alias(backup, job_create,
legacy_name="job-create",
primary_path="backup job create")
add_command_with_alias(backup, job_start,
legacy_name="job-start",
primary_path="backup job start")
add_command_with_alias(backup, job_stop,
legacy_name="job-stop",
primary_path="backup job stop")
add_command_with_alias(backup, job_delete,
legacy_name="job-delete",
primary_path="backup job delete")

# Session aliases
add_command_with_alias(backup, session_list,
legacy_name="session-list",
primary_path="backup session list")
add_command_with_alias(backup, session_show,
legacy_name="session-show",
primary_path="backup session show")
add_command_with_alias(backup, session_create,
legacy_name="session-create",
primary_path="backup session create")
add_command_with_alias(backup, session_add_job,
legacy_name="session-add-job",
primary_path="backup session add-job")
add_command_with_alias(backup, session_remove_job,
legacy_name="session-remove-job",
primary_path="backup session remove-job")
add_command_with_alias(backup, session_start,
legacy_name="session-start",
primary_path="backup session start")
add_command_with_alias(backup, session_delete,
legacy_name="session-delete",
primary_path="backup session delete")
28 changes: 0 additions & 28 deletions orca_cli/commands/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.context import OrcaContext
from orca_cli.core.output import console, output_options, print_detail, print_list
from orca_cli.services.container_infra import ContainerInfraService
Expand Down Expand Up @@ -449,32 +448,5 @@ def nodegroup_delete(ctx: click.Context, cluster_id: str, nodegroup_id: str,
# ══════════════════════════════════════════════════════════════════════════

# Nodegroup aliases
add_command_with_alias(cluster, nodegroup_list,
legacy_name="nodegroup-list",
primary_path="cluster nodegroup list")
add_command_with_alias(cluster, nodegroup_show,
legacy_name="nodegroup-show",
primary_path="cluster nodegroup show")
add_command_with_alias(cluster, nodegroup_create,
legacy_name="nodegroup-create",
primary_path="cluster nodegroup create")
add_command_with_alias(cluster, nodegroup_update,
legacy_name="nodegroup-update",
primary_path="cluster nodegroup update")
add_command_with_alias(cluster, nodegroup_delete,
legacy_name="nodegroup-delete",
primary_path="cluster nodegroup delete")

# Template aliases
add_command_with_alias(cluster, template_list,
legacy_name="template-list",
primary_path="cluster template list")
add_command_with_alias(cluster, template_show,
legacy_name="template-show",
primary_path="cluster template show")
add_command_with_alias(cluster, template_create,
legacy_name="template-create",
primary_path="cluster template create")
add_command_with_alias(cluster, template_delete,
legacy_name="template-delete",
primary_path="cluster template delete")
46 changes: 1 addition & 45 deletions orca_cli/commands/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@
@click.option("--cidr", default=None,
help="CIDR for auto-created security group rules (--fix). "
"Defaults to interactive prompt when a TTY is detected, otherwise 0.0.0.0/0.")
@click.option("--list-deprecated", "list_deprecated", is_flag=True,
help="List every ADR-0008 deprecated alias in the CLI tree and exit "
"(offline — no authentication required).")
@click.pass_context
def doctor(ctx: click.Context, fix: bool, cidr: str | None, list_deprecated: bool) -> None: # noqa: C901
def doctor(ctx: click.Context, fix: bool, cidr: str | None) -> None: # noqa: C901
"""Run a pre-deployment health check on your OpenStack environment.

Verifies authentication, quota headroom, default security group rules,
Expand All @@ -44,27 +41,6 @@ def doctor(ctx: click.Context, fix: bool, cidr: str | None, list_deprecated: boo
Red ≥ 90% — critical, next deploy may fail
"""

# Offline branch: list deprecated aliases and exit before authenticating.
if list_deprecated:
from rich.table import Table

from orca_cli.core.aliases import list_deprecated_aliases
from orca_cli.main import cli as _cli_root

rows = sorted(list_deprecated_aliases(_cli_root))
if not rows:
console.print("[bold green]No deprecated aliases — CLI tree is clean.[/bold green]")
return

table = Table(title=f"ADR-0008 deprecated aliases ({len(rows)} total)")
table.add_column("Legacy invocation", style="yellow")
table.add_column("Replacement", style="green")
for legacy, replacement in rows:
table.add_row(f"orca {legacy}", f"orca {replacement}")
console.print(table)
console.print("\n[dim]These aliases will be removed in v3.0.0. See ADR-0008.[/dim]")
return

orca_ctx = ctx.find_object(OrcaContext)
client = orca_ctx.ensure_client()
compute = ComputeService(client)
Expand Down Expand Up @@ -196,26 +172,6 @@ def _quota(check: str, used: int, total: int, unit: str = "") -> None:
else:
_info("Network quotas", "Skipped — Neutron unreachable")

# ── 6.5. ADR-0008 deprecated-alias inventory (offline, no API) ──────────
# Surface how many hyphenated-form aliases still live in the CLI tree —
# they are scheduled for removal in v3.0.0 (see ADR-0008 / Deprecation
# horizon). Helps users audit their own scripts before the breaking
# major bump.
try:
from orca_cli.core.aliases import count_deprecated_aliases
from orca_cli.main import cli as _cli_root
n_deprecated = count_deprecated_aliases(_cli_root)
if n_deprecated:
_info(
"ADR-0008: deprecated aliases",
f"{n_deprecated} alias(es) kept for backwards-compat — will be "
"removed in v3.0.0. Run 'orca doctor --list-deprecated' to enumerate.",
)
else:
_ok("ADR-0008: deprecated aliases", "None — tree is clean")
except Exception as exc: # pragma: no cover — best-effort, never crash doctor
_info("ADR-0008: deprecated aliases", f"Could not introspect tree — {exc}")

# ── 6. Default security group SSH/ICMP (skip if Neutron is down) ───────
if svc_up.get("Neutron (network)", False):
try:
Expand Down
9 changes: 0 additions & 9 deletions orca_cli/commands/endpoint_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.context import OrcaContext
from orca_cli.core.output import console, output_options, print_detail, print_list
from orca_cli.core.validators import validate_id
Expand Down Expand Up @@ -162,11 +161,3 @@ def eg_project_remove(ctx, endpoint_group_id, project_id, yes):
console.print(
f"Project [bold]{project_id}[/bold] removed from endpoint group [bold]{endpoint_group_id}[/bold]."
)


add_command_with_alias(endpoint_group, eg_project_add,
legacy_name="add-project",
primary_path="endpoint-group project add")
add_command_with_alias(endpoint_group, eg_project_remove,
legacy_name="remove-project",
primary_path="endpoint-group project remove")
9 changes: 0 additions & 9 deletions orca_cli/commands/flavor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.completions import complete_flavors
from orca_cli.core.context import OrcaContext
from orca_cli.core.exceptions import OrcaCLIError
Expand Down Expand Up @@ -246,11 +245,3 @@ def flavor_access_remove(ctx: click.Context, flavor_id: str, project_id: str, ye
click.confirm(f"Remove project {project_id} from flavor {flavor_id}?", abort=True)
svc.remove_flavor_access(flavor_id, project_id)
console.print(f"[green]Project {project_id} access to flavor {flavor_id} revoked.[/green]")


add_command_with_alias(flavor, flavor_access_list,
legacy_name="access-list", primary_path="flavor access list")
add_command_with_alias(flavor, flavor_access_add,
legacy_name="access-add", primary_path="flavor access add")
add_command_with_alias(flavor, flavor_access_remove,
legacy_name="access-remove", primary_path="flavor access remove")
9 changes: 0 additions & 9 deletions orca_cli/commands/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import click

from orca_cli.core.aliases import add_command_with_alias
from orca_cli.core.context import OrcaContext
from orca_cli.core.output import console, output_options, print_detail, print_list
from orca_cli.services.identity import IdentityService
Expand Down Expand Up @@ -164,11 +163,3 @@ def group_member_list(ctx, group_id, output_format, columns, fit_width, max_widt
fit_width=fit_width, max_width=max_width, noindent=noindent,
empty_msg="No users in this group.",
)


add_command_with_alias(group, group_user_add,
legacy_name="add-user", primary_path="group user add")
add_command_with_alias(group, group_user_remove,
legacy_name="remove-user", primary_path="group user remove")
add_command_with_alias(group, group_member_list,
legacy_name="member-list", primary_path="group member list")
Loading
Loading