434 lines
14 KiB
Python
434 lines
14 KiB
Python
#!/usr/bin/env python
|
|
"""The show command for the BQ CLI."""
|
|
|
|
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_deprecated
|
|
from clients import client_reservation
|
|
from clients import client_row_access_policy
|
|
from clients import utils as bq_client_utils
|
|
from frontend import bigquery_command
|
|
from frontend import bq_cached_client
|
|
from frontend import utils as bq_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
|
|
|
|
|
|
ApiClientHelper = bq_id_utils.ApiClientHelper
|
|
DatasetReference = bq_id_utils.ApiClientHelper.DatasetReference
|
|
TransferConfigReference = bq_id_utils.ApiClientHelper.TransferConfigReference
|
|
TransferRunReference = bq_id_utils.ApiClientHelper.TransferRunReference
|
|
EncryptionServiceAccount = bq_id_utils.ApiClientHelper.EncryptionServiceAccount
|
|
|
|
|
|
class Show(bigquery_command.BigqueryCmd):
|
|
"""The BQ CLI command to display a resource to the user."""
|
|
|
|
usage = """show [<identifier>]"""
|
|
|
|
def __init__(self, name: str, fv: flags.FlagValues) -> None:
|
|
super(Show, self).__init__(name, fv)
|
|
flags.DEFINE_boolean(
|
|
'job',
|
|
False,
|
|
'If true, interpret this identifier as a job id.',
|
|
short_name='j',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'dataset',
|
|
False,
|
|
'Show dataset with this name.',
|
|
short_name='d',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'view',
|
|
False,
|
|
'Show view specific details instead of general table details.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'materialized_view',
|
|
False,
|
|
'Show materialized view specific details instead of general table '
|
|
'details.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'table_replica',
|
|
False,
|
|
'Show table replica specific details instead of general table details.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'schema',
|
|
False,
|
|
'Show only the schema instead of general table details.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'encryption_service_account',
|
|
False,
|
|
'Show the service account for a user if it exists, or create one '
|
|
'if it does not exist.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'transfer_config',
|
|
False,
|
|
'Show transfer configuration for configuration resource name.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'transfer_run',
|
|
False,
|
|
'Show information about the particular transfer run.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'model',
|
|
False,
|
|
'Show details of model with this model ID.',
|
|
short_name='m',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'routine',
|
|
False,
|
|
'Show the details of a particular routine.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'reservation',
|
|
None,
|
|
'Shows details for the reservation described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'capacity_commitment',
|
|
None,
|
|
'Shows details for the capacity commitment described by this '
|
|
'identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'reservation_assignment',
|
|
None,
|
|
'Looks up reservation assignments for a specified '
|
|
'project/folder/organization. Explicit reservation assignments will be '
|
|
'returned if exist. Otherwise implicit reservation assignments from '
|
|
'parents will be returned. '
|
|
'Used in conjunction with --job_type, --assignee_type and '
|
|
'--assignee_id.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'reservation_group',
|
|
None,
|
|
'Shows details for the reservation group described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_enum(
|
|
'job_type',
|
|
None,
|
|
[
|
|
'QUERY',
|
|
'PIPELINE',
|
|
'ML_EXTERNAL',
|
|
'BACKGROUND',
|
|
'SPARK',
|
|
'CONTINUOUS',
|
|
'BACKGROUND_CHANGE_DATA_CAPTURE',
|
|
'BACKGROUND_COLUMN_METADATA_INDEX',
|
|
'BACKGROUND_SEARCH_INDEX_REFRESH',
|
|
],
|
|
(
|
|
'Type of jobs to search reservation assignment for. Options'
|
|
' include:'
|
|
'\n QUERY'
|
|
'\n PIPELINE'
|
|
'\n ML_EXTERNAL'
|
|
'\n BACKGROUND'
|
|
'\n SPARK'
|
|
'\n CONTINUOUS'
|
|
'\n BACKGROUND_CHANGE_DATA_CAPTURE'
|
|
'\n BACKGROUND_COLUMN_METADATA_INDEX'
|
|
'\n BACKGROUND_SEARCH_INDEX_REFRESH'
|
|
'\n Used in conjunction with --reservation_assignment.'
|
|
),
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_enum(
|
|
'assignee_type',
|
|
None,
|
|
['PROJECT', 'FOLDER', 'ORGANIZATION'],
|
|
'Type of assignees for the reservation assignment. Options include:'
|
|
'\n PROJECT'
|
|
'\n FOLDER'
|
|
'\n ORGANIZATION'
|
|
'\n Used in conjunction with --reservation_assignment.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_string(
|
|
'assignee_id',
|
|
None,
|
|
'Project/folder/organization ID, to which the reservation is assigned. '
|
|
'Used in conjunction with --reservation_assignment.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'connection',
|
|
None,
|
|
'Shows details for the connection described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_enum(
|
|
'dataset_view',
|
|
None,
|
|
['METADATA', 'ACL', 'FULL'],
|
|
'Specifies the view that determines which dataset information is '
|
|
'returned. By default, metadata and ACL information are returned. '
|
|
'Options include:'
|
|
'\n METADATA'
|
|
'\n ACL'
|
|
'\n FULL'
|
|
'\n If not set, defaults as FULL',
|
|
flag_values=fv,
|
|
)
|
|
flags.DEFINE_boolean(
|
|
'migration_workflow',
|
|
None,
|
|
'Show details of migration workflow described by this identifier.',
|
|
flag_values=fv,
|
|
)
|
|
self._ProcessCommandRc(fv)
|
|
|
|
def RunWithArgs(self, identifier: str = '') -> Optional[int]:
|
|
"""Show all information about an object.
|
|
|
|
Examples:
|
|
bq show -j <job_id>
|
|
bq show dataset
|
|
bq show [--schema] dataset.table
|
|
bq show [--view] dataset.view
|
|
bq show [--materialized_view] dataset.materialized_view
|
|
bq show -m ds.model
|
|
bq show --routine ds.routine
|
|
bq show --transfer_config projects/p/locations/l/transferConfigs/c
|
|
bq show --transfer_run projects/p/locations/l/transferConfigs/c/runs/r
|
|
bq show --encryption_service_account
|
|
bq show --connection --project_id=project --location=us connection
|
|
bq show --capacity_commitment project:US.capacity_commitment_id
|
|
bq show --reservation --location=US --project_id=project reservation_name
|
|
bq show --reservation_assignment --project_id=project --location=US
|
|
--assignee_type=PROJECT --assignee_id=myproject --job_type=QUERY
|
|
bq show --reservation_assignment --project_id=project --location=US
|
|
--assignee_type=FOLDER --assignee_id=123 --job_type=QUERY
|
|
bq show --reservation_assignment --project_id=project --location=US
|
|
--assignee_type=ORGANIZATION --assignee_id=456 --job_type=QUERY
|
|
bq show --reservation_group --location=US --project_id=project
|
|
reservation_group_name
|
|
bq show --migration_workflow projects/p/locations/l/workflows/workflow_id
|
|
|
|
Arguments:
|
|
identifier: the identifier of the resource to show.
|
|
"""
|
|
# pylint: disable=g-doc-exception
|
|
client = bq_cached_client.Client.Get()
|
|
custom_format = 'show'
|
|
object_info = None
|
|
print_reference = True
|
|
if self.j:
|
|
reference = bq_client_utils.GetJobReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
elif self.d:
|
|
self.PossiblyDelegateToGcloudAndExit('datasets', 'show', identifier)
|
|
reference = bq_client_utils.GetDatasetReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
object_info = client_dataset.GetDataset(
|
|
apiclient=client.apiclient,
|
|
reference=reference,
|
|
dataset_view=self.dataset_view,
|
|
)
|
|
elif self.view:
|
|
reference = bq_client_utils.GetTableReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
custom_format = 'view'
|
|
elif self.materialized_view:
|
|
reference = bq_client_utils.GetTableReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
custom_format = 'materialized_view'
|
|
elif self.table_replica:
|
|
reference = bq_client_utils.GetTableReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
custom_format = 'table_replica'
|
|
elif self.schema:
|
|
if bq_flags.FORMAT.value not in [None, 'prettyjson', 'json']:
|
|
raise app.UsageError(
|
|
'Table schema output format must be json or prettyjson.'
|
|
)
|
|
reference = bq_client_utils.GetTableReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
custom_format = 'schema'
|
|
elif self.transfer_config:
|
|
formatted_identifier = frontend_id_utils.FormatDataTransferIdentifiers(
|
|
client, identifier
|
|
)
|
|
reference = TransferConfigReference(
|
|
transferConfigName=formatted_identifier
|
|
)
|
|
object_info = client_data_transfer.get_transfer_config(
|
|
client.GetTransferV1ApiClient(), formatted_identifier
|
|
)
|
|
elif self.transfer_run:
|
|
formatted_identifier = frontend_id_utils.FormatDataTransferIdentifiers(
|
|
client, identifier
|
|
)
|
|
reference = TransferRunReference(transferRunName=formatted_identifier)
|
|
object_info = client_data_transfer.get_transfer_run(
|
|
client.GetTransferV1ApiClient(), formatted_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.reservation:
|
|
reference = bq_client_utils.GetReservationReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
object_info = client_reservation.GetReservation(
|
|
client=client.GetReservationApiClient(), reference=reference
|
|
)
|
|
elif self.reservation_assignment:
|
|
search_all_projects = True
|
|
if search_all_projects:
|
|
object_info = client_reservation.SearchAllReservationAssignments(
|
|
client=client.GetReservationApiClient(),
|
|
location=bq_flags.LOCATION.value,
|
|
job_type=self.job_type,
|
|
assignee_type=self.assignee_type,
|
|
assignee_id=self.assignee_id,
|
|
)
|
|
# Here we just need any object of ReservationAssignmentReference type, but
|
|
# the value of the object doesn't matter here.
|
|
# PrintObjectInfo() will use the type and object_info to format the
|
|
# output.
|
|
reference = ApiClientHelper.ReservationAssignmentReference.Create(
|
|
projectId=' ',
|
|
location=' ',
|
|
reservationId=' ',
|
|
reservationAssignmentId=' ',
|
|
)
|
|
print_reference = False
|
|
elif self.capacity_commitment:
|
|
reference = bq_client_utils.GetCapacityCommitmentReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
object_info = client_reservation.GetCapacityCommitment(
|
|
client=client.GetReservationApiClient(),
|
|
reference=reference,
|
|
)
|
|
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,
|
|
)
|
|
object_info = client_reservation.GetReservationGroup(
|
|
reservation_group_client=client.GetReservationApiClient(),
|
|
reference=reference,
|
|
)
|
|
except BaseException as e:
|
|
raise bq_error.BigqueryError(
|
|
"Failed to get reservation group '%s': %s" % (identifier, e)
|
|
)
|
|
elif self.encryption_service_account:
|
|
object_info = (
|
|
client.apiclient.projects()
|
|
.getServiceAccount(
|
|
projectId=bq_client_utils.GetProjectReference(
|
|
id_fallbacks=client
|
|
).projectId
|
|
)
|
|
.execute()
|
|
)
|
|
email = object_info['email']
|
|
object_info = {'ServiceAccountID': email}
|
|
reference = EncryptionServiceAccount(serviceAccount='serviceAccount')
|
|
elif self.connection:
|
|
reference = bq_client_utils.GetConnectionReference(
|
|
id_fallbacks=client,
|
|
identifier=identifier,
|
|
default_location=bq_flags.LOCATION.value,
|
|
)
|
|
object_info = client_connection.GetConnection(
|
|
client=client.GetConnectionV1ApiClient(), reference=reference
|
|
)
|
|
elif self.migration_workflow:
|
|
reference = None
|
|
self.DelegateToGcloudAndExit(
|
|
'migration_workflows',
|
|
'show',
|
|
identifier,
|
|
)
|
|
|
|
else:
|
|
reference = bq_client_utils.GetReference(
|
|
id_fallbacks=client, identifier=identifier
|
|
)
|
|
if reference is None:
|
|
raise app.UsageError('Must provide an identifier for show.')
|
|
|
|
if isinstance(reference, DatasetReference) and not object_info:
|
|
self.PossiblyDelegateToGcloudAndExit('datasets', 'show', identifier)
|
|
object_info = client_dataset.GetDataset(
|
|
apiclient=client.apiclient,
|
|
reference=reference,
|
|
dataset_view=self.dataset_view,
|
|
)
|
|
pass
|
|
|
|
if object_info is None:
|
|
object_info = client_deprecated.get_object_info(
|
|
apiclient=client.apiclient,
|
|
get_routines_api_client=client.GetRoutinesApiClient,
|
|
get_models_api_client=client.GetModelsApiClient,
|
|
reference=reference,
|
|
)
|
|
bq_frontend_utils.PrintObjectInfo(
|
|
object_info,
|
|
reference,
|
|
custom_format=custom_format,
|
|
print_reference=print_reference,
|
|
)
|