Skip to content

feat(snap): add snap aliases module#571

Open
james-garner-canonical wants to merge 2 commits into
canonical:mainfrom
james-garner-canonical:26-06+feat+snap-aliases-module
Open

feat(snap): add snap aliases module#571
james-garner-canonical wants to merge 2 commits into
canonical:mainfrom
james-garner-canonical:26-06+feat+snap-aliases-module

Conversation

@james-garner-canonical

Copy link
Copy Markdown
Collaborator

This PR adds the snap library functionality using the /v2/aliases endpoint, mirroring the snap CLI commands snap alias and snap unalias.

@james-garner-canonical james-garner-canonical marked this pull request as ready for review July 1, 2026 05:49
@james-garner-canonical james-garner-canonical requested a review from a team as a code owner July 1, 2026 05:49
if typing.TYPE_CHECKING:
from collections.abc import Mapping

_SNAP = 'lxd'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know there's an issue for having dedicated test snaps, but in the meantime, isn't lxd rather large to be using?


def _alias_exists() -> bool:
info = _list_aliases().get(_SNAP, {}).get(_ALIAS)
return info is not None and info.get('command') == f'{_SNAP}.{_APP}'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess strictly speaking this is the definition of it existing and working. I wonder if a functional test ought to check the higher level "I can run the command" rather than only "snap db has the value". But maybe that falls out of testing "snap library" and into testing snapd.

ensure_installed(_SNAP)
_cleanup_alias()
_snapd_aliases.alias(_SNAP, _APP, _ALIAS)
_snapd_aliases.alias(_SNAP, _APP, _ALIAS) # Second call — no error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To really test idempotency this should check it exists after both calls. Otherwise it maybe just worked the second time and failed the first.

ensure_installed(_SNAP)
_cleanup_alias()
_snapd_aliases.alias(_SNAP, _APP, _ALIAS)
_snapd_aliases.alias(_SNAP, 'lxd', _ALIAS) # Different app, same snap — no error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be testing that the alias exists (both times) not just that there is no error.

alias_name: The alias to remove.

Raises:
ChangeError: if the unalias change fails after starting.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically correct, but maybe more friendly as

Suggested change
ChangeError: if the unalias change fails after starting.
ChangeError: if the alias removal fails after starting.


Raises:
ChangeError: if the unalias change fails after starting.
APIError: if the alias does not exist (e.g. was never created, or the snap it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
APIError: if the alias does not exist (e.g. was never created, or the snap it
APIError: if the alias does not exist (for example, was never created, or the snap it

logger = logging.getLogger(__name__)


def alias(snap: str, app: str, alias_name: str) -> None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about dropping "alias"? It's there in the function name and pretty implied.

Suggested change
def alias(snap: str, app: str, alias_name: str) -> None:
def alias(snap: str, app: str, name: str) -> None:

Or, simplifying in a different way, but maybe more explicit even though it keeps the duplication:

Suggested change
def alias(snap: str, app: str, alias_name: str) -> None:
def alias(snap: str, app: str, alias: str) -> None:

(Maybe linters don't like the shadow there, but it's not like this is recursive or ever would be.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants