Skip to content

Commit

Permalink
feat: Add purge image cli
Browse files Browse the repository at this point in the history
  • Loading branch information
jopemachine committed Feb 18, 2025
1 parent 7600200 commit cdf1e63
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/ai/backend/client/cli/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def list(ctx: CLIContext, customized: bool) -> None:
@click.argument("reference_or_id", type=str)
@click.option("--arch", type=str, default=None, help="Set an explicit architecture.")
def forget(reference_or_id, arch):
"""Forget image from server. This command will only work for image customized by user
"""Mark image as deleted from server. This command will only work for image customized by user
unless callee has superadmin privileges.
REFERENCE_OR_ID: Canonical string of image (<registry>/<project>/<name>:<tag>)"""
Expand Down
12 changes: 11 additions & 1 deletion src/ai/backend/manager/cli/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .image_impl import forget_image as forget_image_impl
from .image_impl import inspect_image as inspect_image_impl
from .image_impl import list_images as list_images_impl
from .image_impl import purge_image as purge_image_impl
from .image_impl import rescan_images as rescan_images_impl
from .image_impl import set_image_resource_limit as set_image_resource_limit_impl
from .image_impl import validate_image_alias as validate_image_alias_impl
Expand Down Expand Up @@ -51,10 +52,19 @@ def inspect(cli_ctx, canonical_or_alias, architecture) -> None:
@click.argument("architecture")
@click.pass_obj
def forget(cli_ctx, canonical_or_alias, architecture) -> None:
"""Forget (delete) a specific image."""
"""Forget (soft-delete) a specific image."""
asyncio.run(forget_image_impl(cli_ctx, canonical_or_alias, architecture))


@cli.command()
@click.argument("canonical_or_alias")
@click.argument("architecture")
@click.pass_obj
def purge(cli_ctx, canonical_or_alias, architecture) -> None:
"""Purge (hard-delete) a specific image."""
asyncio.run(purge_image_impl(cli_ctx, canonical_or_alias, architecture))


@cli.command()
@click.argument("canonical_or_alias")
@click.argument("slot_type")
Expand Down
24 changes: 23 additions & 1 deletion src/ai/backend/manager/cli/image_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from ai.backend.common.types import ImageAlias
from ai.backend.logging import BraceStyleAdapter

from ..models.image import ImageAliasRow, ImageIdentifier, ImageRow
from ..models.image import ImageAliasRow, ImageIdentifier, ImageRow, ImageStatus
from ..models.image import rescan_images as rescan_images_func
from ..models.utils import connect_database
from .context import CLIContext, redis_ctx
Expand Down Expand Up @@ -118,6 +118,28 @@ async def forget_image(cli_ctx, canonical_or_alias, architecture):
ImageAlias(canonical_or_alias),
],
)
image_row.status = ImageStatus.DELETED
await session.flush()
except UnknownImageReference:
log.exception("Image not found.")
except Exception:
log.exception("An error occurred.")


async def purge_image(cli_ctx, canonical_or_alias, architecture):
async with (
connect_database(cli_ctx.local_config) as db,
db.begin_session() as session,
):
try:
image_row = await ImageRow.resolve(
session,
[
ImageIdentifier(canonical_or_alias, architecture),
ImageAlias(canonical_or_alias),
],
load_only_active=False,
)
await session.delete(image_row)
except UnknownImageReference:
log.exception("Image not found.")
Expand Down

0 comments on commit cdf1e63

Please sign in to comment.