418 lines
14 KiB
Python
418 lines
14 KiB
Python
#!/usr/bin/env python
|
|
"""The BigQuery delete CLI command."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
from typing import Optional
|
|
|
|
from absl import app
|
|
from absl import flags
|
|
|
|
import bq_flags
|
|
from clients import client_connection
|
|
from clients import client_data_transfer
|
|
from clients import client_dataset
|
|
from clients import client_job
|
|
from clients import client_model
|
|
from clients import client_reservation
|
|
from clients import client_routine
|
|
from clients import client_row_access_policy
|
|
from clients import client_table
|
|
from clients import utils as bq_client_utils
|
|
from frontend import bigquery_command
|
|
from frontend import bq_cached_client
|
|
from frontend import utils as frontend_utils
|
|
from frontend import utils_flags
|
|
from frontend import utils_id as frontend_id_utils
|
|
from utils import bq_error
|
|
from utils import bq_id_utils
|
|
|
|
# These aren't relevant for user-facing docstrings:
|
|
# pylint: disable=g-doc-return-or-yield
|
|
# pylint: disable=g-doc-args
|
|
|
|
|
|
class Delete(bigquery_command.BigqueryCmd):
|
|
"""The Delete CLI command."""
|
|
|
|
usage = """rm [-f] [-r] [(-d|-t)] <identifier>"""
|
|
|
|
def __init__(self, name: str, fv: flags.FlagValues):
|
|
super(Delete, self).__init__(name, fv)
|
|
flags.DEFINE_boolean(
|
|
'dataset',
|
|
False,
|
|
'Remove dataset described by this identifier.',
|
|
short_name='d',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'table',
|
|
False,
|
|
'Remove table described by this identifier.',
|
|
short_name='t',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'job',
|
|
False,
|
|
'Remove job described by this identifier.',
|
|
short_name='j',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'transfer_config',
|
|
False,
|
|
'Remove transfer configuration described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'force',
|
|
None,
|
|
"Ignore existing tables and datasets, don't prompt.",
|
|
short_name='f',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'recursive',
|
|
False,
|
|
'Remove dataset and any tables it may contain.',
|
|
short_name='r',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'reservation',
|
|
False,
|
|
'Deletes the reservation described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'capacity_commitment',
|
|
False,
|
|
'Deletes the capacity commitment described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'reservation_assignment',
|
|
False,
|
|
'Delete a reservation assignment.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'reservation_group',
|
|
False,
|
|
'Delete a reservation group described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'model',
|
|
False,
|
|
'Remove model with this model ID.',
|
|
short_name='m',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'routine', False, 'Remove routine with this routine ID.', flag_values=fv
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'connection', False, 'Delete a connection.', flag_values=fv
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'migration_workflow',
|
|
False,
|
|
'Delete a migration workflow.',
|
|
flag_values=fv,
|
|
)
|
|
self._ProcessCommandRc(fv)
|
|
|
|
def RunWithArgs(self, identifier: str) -> Optional[int]:
|
|
"""Delete the resource described by the identifier.
|
|
|
|
Always requires an identifier, unlike the show and ls commands.
|
|
By default, also requires confirmation before deleting. Supports
|
|
the -d -t flags to signify that the identifier is a dataset
|
|
or table.
|
|
* With -f, don't ask for confirmation before deleting.
|
|
* With -r, remove all tables in the named dataset.
|
|
|
|
Examples:
|
|
bq rm ds.table
|
|
bq rm -m ds.model
|
|
bq rm --routine ds.routine
|
|
bq rm -r -f old_dataset
|
|
bq rm --transfer_config=projects/p/locations/l/transferConfigs/c
|
|
bq rm --connection --project_id=proj --location=us con
|
|
bq rm --capacity_commitment proj:US.capacity_commitment_id
|
|
bq rm --reservation --project_id=proj --location=us reservation_name
|
|
bq rm --reservation_assignment --project_id=proj --location=us
|
|
assignment_name
|
|
bq rm --reservation_group --project_id=proj --location=us
|
|
reservation_group_name
|
|
"""
|
|
|
|
client = bq_cached_client.Client.Get()
|
|
|
|
# pylint: disable=g-doc-exception
|
|
if frontend_utils.ValidateAtMostOneSelected(
|
|
self.d,
|
|
self.t,
|
|
self.j,
|
|
self.routine,
|
|
self.transfer_config,
|
|
self.reservation,
|
|
self.reservation_assignment,
|
|
self.capacity_commitment,
|
|
self.reservation_group,
|
|
self.connection,
|
|
):
|
|
raise app.UsageError('Cannot specify more than one resource type.')
|
|
if not identifier:
|
|
raise app.UsageError('Must provide an identifier for rm.')
|
|
|
|
if self.t:
|
|
reference = bq_client_utils.GetTableReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
elif self.m:
|
|
reference = bq_client_utils.GetModelReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
elif self.routine:
|
|
reference = bq_client_utils.GetRoutineReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
elif self.d:
|
|
reference = bq_client_utils.GetDatasetReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
elif self.j:
|
|
reference = bq_client_utils.GetJobReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
elif self.transfer_config:
|
|
formatted_identifier = frontend_id_utils.FormatDataTransferIdentifiers(
|
|
client, identifier
|
|
)
|
|
reference = bq_id_utils.ApiClientHelper.TransferConfigReference(
|
|
transferConfigName=formatted_identifier
|
|
)
|
|
elif self.reservation:
|
|
try:
|
|
reference = bq_client_utils.GetReservationReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
client_reservation.DeleteReservation(
|
|
client=client.GetReservationApiClient(),
|
|
reference=reference,
|
|
)
|
|
print("Reservation '%s' successfully deleted." % identifier)
|
|
except BaseException as e:
|
|
raise bq_error.BigqueryError(
|
|
"Failed to delete reservation '%s': %s" % (identifier, e)
|
|
)
|
|
elif self.reservation_assignment:
|
|
try:
|
|
reference = bq_client_utils.GetReservationAssignmentReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
client_reservation.DeleteReservationAssignment(
|
|
client=client.GetReservationApiClient(), reference=reference
|
|
)
|
|
print("Reservation assignment '%s' successfully deleted." % identifier)
|
|
except BaseException as e:
|
|
raise bq_error.BigqueryError(
|
|
"Failed to delete reservation assignment '%s': %s" % (identifier, e)
|
|
)
|
|
elif self.capacity_commitment:
|
|
try:
|
|
reference = bq_client_utils.GetCapacityCommitmentReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
client_reservation.DeleteCapacityCommitment(
|
|
client=client.GetReservationApiClient(),
|
|
reference=reference,
|
|
force=self.force,
|
|
)
|
|
print("Capacity commitment '%s' successfully deleted." % identifier)
|
|
except BaseException as e:
|
|
raise bq_error.BigqueryError(
|
|
"Failed to delete capacity commitment '%s': %s" % (identifier, e)
|
|
)
|
|
elif self.reservation_group:
|
|
try:
|
|
utils_flags.fail_if_not_using_alpha_feature(
|
|
bq_flags.AlphaFeatures.RESERVATION_GROUPS
|
|
)
|
|
reference = bq_client_utils.GetReservationGroupReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
client_reservation.DeleteReservationGroup(
|
|
reservation_group_client=client.GetReservationApiClient(),
|
|
reference=reference,
|
|
)
|
|
# TODO(b/392704450): Refactor the print and error handling for
|
|
# reservation resources.
|
|
print("Reservation group '%s' successfully deleted." % identifier)
|
|
except BaseException as e:
|
|
raise bq_error.BigqueryError(
|
|
"Failed to delete reservation group '%s': %s" % (identifier, e)
|
|
)
|
|
elif self.connection:
|
|
reference = bq_client_utils.GetConnectionReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
client_connection.DeleteConnection(
|
|
client=client.GetConnectionV1ApiClient(), reference=reference
|
|
)
|
|
elif self.migration_workflow:
|
|
reference = identifier
|
|
else:
|
|
reference = bq_client_utils.GetReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
bq_id_utils.typecheck(
|
|
reference,
|
|
(
|
|
bq_id_utils.ApiClientHelper.DatasetReference,
|
|
bq_id_utils.ApiClientHelper.TableReference,
|
|
),
|
|
'Invalid identifier "%s" for rm.' % (identifier,),
|
|
is_usage_error=True,
|
|
)
|
|
|
|
if (
|
|
isinstance(reference, bq_id_utils.ApiClientHelper.TableReference)
|
|
and self.r
|
|
):
|
|
raise app.UsageError('Cannot specify -r with %r' % (reference,))
|
|
|
|
if (
|
|
isinstance(reference, bq_id_utils.ApiClientHelper.ModelReference)
|
|
and self.r
|
|
):
|
|
raise app.UsageError('Cannot specify -r with %r' % (reference,))
|
|
|
|
if (
|
|
isinstance(reference, bq_id_utils.ApiClientHelper.RoutineReference)
|
|
and self.r
|
|
):
|
|
raise app.UsageError('Cannot specify -r with %r' % (reference,))
|
|
|
|
if self.migration_workflow and self.r:
|
|
raise app.UsageError('Cannot specify -r with %r' % (reference,))
|
|
|
|
if not self.force:
|
|
if (
|
|
(
|
|
isinstance(
|
|
reference, bq_id_utils.ApiClientHelper.DatasetReference
|
|
)
|
|
and client_dataset.DatasetExists(
|
|
apiclient=client.apiclient, reference=reference
|
|
)
|
|
)
|
|
or (
|
|
isinstance(reference, bq_id_utils.ApiClientHelper.TableReference)
|
|
and client_table.table_exists(
|
|
apiclient=client.apiclient, reference=reference
|
|
)
|
|
)
|
|
or (
|
|
isinstance(reference, bq_id_utils.ApiClientHelper.JobReference)
|
|
and client_job.JobExists(client, reference)
|
|
)
|
|
or (
|
|
isinstance(reference, bq_id_utils.ApiClientHelper.ModelReference)
|
|
and client_model.model_exists(
|
|
model_client=client.GetModelsApiClient(), reference=reference
|
|
)
|
|
)
|
|
or (
|
|
isinstance(
|
|
reference, bq_id_utils.ApiClientHelper.RoutineReference
|
|
)
|
|
and client_routine.RoutineExists(
|
|
routines_api_client=client.GetRoutinesApiClient(),
|
|
reference=reference,
|
|
)
|
|
)
|
|
or (
|
|
isinstance(
|
|
reference, bq_id_utils.ApiClientHelper.TransferConfigReference
|
|
)
|
|
and client_data_transfer.transfer_exists(
|
|
client.GetTransferV1ApiClient(), reference
|
|
)
|
|
)
|
|
or self.migration_workflow
|
|
):
|
|
if 'y' != frontend_utils.PromptYN(
|
|
'rm: remove %r? (y/N) ' % (reference,)
|
|
):
|
|
print('NOT deleting %r, exiting.' % (reference,))
|
|
return 0
|
|
|
|
if isinstance(reference, bq_id_utils.ApiClientHelper.DatasetReference):
|
|
# Prompt for confirmation has already occurred.
|
|
self.PossiblyDelegateToGcloudAndExit(
|
|
resource='datasets',
|
|
bq_command='rm',
|
|
identifier=identifier,
|
|
command_flags_for_this_resource={'recursive': self.recursive},
|
|
)
|
|
client_dataset.DeleteDataset(
|
|
client.apiclient,
|
|
reference,
|
|
ignore_not_found=self.force,
|
|
delete_contents=self.recursive,
|
|
)
|
|
elif isinstance(reference, bq_id_utils.ApiClientHelper.TableReference):
|
|
client_table.delete_table(
|
|
apiclient=client.apiclient,
|
|
reference=reference,
|
|
ignore_not_found=self.force,
|
|
)
|
|
elif isinstance(reference, bq_id_utils.ApiClientHelper.JobReference):
|
|
client_job.DeleteJob(client, reference, ignore_not_found=self.force)
|
|
elif isinstance(reference, bq_id_utils.ApiClientHelper.ModelReference):
|
|
client_model.delete_model(
|
|
model_client=client.GetModelsApiClient(),
|
|
reference=reference,
|
|
ignore_not_found=self.force,
|
|
)
|
|
elif isinstance(reference, bq_id_utils.ApiClientHelper.RoutineReference):
|
|
client_routine.DeleteRoutine(
|
|
routines_api_client=client.GetRoutinesApiClient(),
|
|
reference=reference,
|
|
ignore_not_found=self.force,
|
|
)
|
|
elif isinstance(
|
|
reference, bq_id_utils.ApiClientHelper.TransferConfigReference
|
|
):
|
|
client_data_transfer.delete_transfer_config(
|
|
client.GetTransferV1ApiClient(),
|
|
reference,
|
|
ignore_not_found=self.force,
|
|
)
|
|
elif self.migration_workflow:
|
|
# Prompt for confirmation has already occurred.
|
|
self.DelegateToGcloudAndExit(
|
|
'migration_workflows',
|
|
'rm',
|
|
identifier,
|
|
)
|