diff --git a/sdk/python/feast/cli/projects.py b/sdk/python/feast/cli/projects.py index ea8d5b573a6..a4ae3216cb8 100644 --- a/sdk/python/feast/cli/projects.py +++ b/sdk/python/feast/cli/projects.py @@ -3,16 +3,15 @@ from feast import utils from feast.cli.cli_options import tagsOption -from feast.errors import FeastObjectNotFoundException +from feast.errors import FeastObjectNotFoundException, ProjectNotFoundException from feast.repo_operations import create_feature_store @click.group(name="projects") def projects_cmd(): """ - Access projects + Access and manage projects """ - pass @projects_cmd.command("describe") @@ -27,8 +26,8 @@ def project_describe(ctx: click.Context, name: str): try: project = store.get_project(name) except FeastObjectNotFoundException as e: - print(e) - exit(1) + print(str(e)) + raise SystemExit(1) print( yaml.dump( @@ -58,7 +57,7 @@ def project_current(ctx: click.Context): ) -@projects_cmd.command(name="list") +@projects_cmd.command("list") @tagsOption @click.pass_context def project_list(ctx: click.Context, tags: list[str]): @@ -75,6 +74,43 @@ def project_list(ctx: click.Context, tags: list[str]): print( tabulate( - table, headers=["NAME", "DESCRIPTION", "TAGS", "OWNER"], tablefmt="plain" + table, + headers=["NAME", "DESCRIPTION", "TAGS", "OWNER"], + tablefmt="plain", ) ) + + +@projects_cmd.command("delete") +@click.argument("name", type=click.STRING) +@click.option( + "--yes", + "-y", + is_flag=True, + help="Skip confirmation prompt and delete immediately.", +) +@click.pass_context +def project_delete(ctx: click.Context, name: str, yes: bool): + """ + Delete a project and all its resources from the registry. + + This removes the project entry from the registry. Individual objects + (feature views, entities, data sources) that belong to the project + are also purged when commit=True (the default). + """ + store = create_feature_store(ctx) + + if not yes: + click.confirm( + f"Are you sure you want to delete project '{name}'? " + "This will remove all associated resources from the registry.", + abort=True, + ) + + try: + store.registry.delete_project(name, commit=True) + except (FeastObjectNotFoundException, ProjectNotFoundException) as e: + print(str(e)) + raise SystemExit(1) + + print(f"Project '{name}' deleted successfully.")