File: //snap/google-cloud-cli/396/lib/googlecloudsdk/command_lib/asset/flags.py
# -*- coding: utf-8 -*- #
# Copyright 2018 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Flags for commands in cloudasset."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.util.apis import yaml_data
from googlecloudsdk.command_lib.util.args import common_args
from googlecloudsdk.command_lib.util.args import resource_args
from googlecloudsdk.command_lib.util.concepts import concept_parsers
def _GetOrAddArgGroup(parser, help_text):
"""Create a new arg group or return existing group with given help text."""
for arg in parser.arguments:
if arg.is_group and arg.help == help_text:
return arg
return parser.add_argument_group(help_text)
def GetOrAddOptionGroup(parser):
return _GetOrAddArgGroup(parser, 'The analysis options.')
def AddOrganizationArgs(parser, help_text):
parser.add_argument(
'--organization', metavar='ORGANIZATION_ID', help=help_text)
def AddFolderArgs(parser, help_text):
parser.add_argument('--folder', metavar='FOLDER_ID', help=help_text)
def AddProjectArgs(parser, help_text):
parser.add_argument('--project', metavar='PROJECT_ID', help=help_text)
def AddParentArgs(parser, project_help_text, org_help_text, folder_help_text):
parent_group = parser.add_mutually_exclusive_group(required=True)
common_args.ProjectArgument(
help_text_to_prepend=project_help_text).AddToParser(parent_group)
AddOrganizationArgs(parent_group, org_help_text)
AddFolderArgs(parent_group, folder_help_text)
def AddAnalyzerParentArgs(parser):
"""Adds analysis parent(aka scope) argument."""
parent_group = parser.add_mutually_exclusive_group(required=True)
AddOrganizationArgs(
parent_group, 'Organization ID on which to perform the analysis.'
' Only policies defined at or below this organization '
' will be targeted in the analysis.')
AddFolderArgs(
parent_group, 'Folder ID on which to perform the analysis.'
' Only policies defined at or below this folder will be '
' targeted in the analysis.')
AddProjectArgs(
parent_group, 'Project ID or number on which to perform the analysis.'
' Only policies defined at or below this project will be '
' targeted in the analysis.')
def AddSnapshotTimeArgs(parser):
parser.add_argument(
'--snapshot-time',
type=arg_parsers.Datetime.Parse,
help=('Timestamp to take a snapshot on assets. This can only be a '
'current or past time. If not specified, the current time will be '
'used. Due to delays in resource data collection and indexing, '
'there is a volatile window during which running the same query at '
'different times may return different results. '
'See $ gcloud topic datetimes for information on time formats.'))
def AddAssetTypesArgs(parser):
parser.add_argument(
'--asset-types',
metavar='ASSET_TYPES',
type=arg_parsers.ArgList(),
default=[],
help=(
'A list of asset types (i.e., "compute.googleapis.com/Disk") to take '
'a snapshot. If specified and non-empty, only assets matching the '
'specified types will be returned. '
'See http://cloud.google.com/asset-inventory/docs/supported-asset-types'
' for supported asset types.'))
def AddRelationshipTypesArgs(parser):
parser.add_argument(
'--relationship-types',
metavar='RELATIONSHIP_TYPES',
type=arg_parsers.ArgList(),
default=[],
help=(
'A list of relationship types (i.e., "INSTANCE_TO_INSTANCEGROUP") to '
'take a snapshot. This argument will only be honoured if '
'content_type=RELATIONSHIP. If specified and non-empty, only '
'relationships matching the specified types will be returned. '
'See http://cloud.google.com/asset-inventory/docs/supported-asset-types'
' for supported relationship types.'))
def AddContentTypeArgs(parser, required):
"""--content-type argument for asset export and get-history."""
if required:
help_text = ('Asset content type.')
else:
help_text = (
'Asset content type. If specified, only content matching the '
'specified type will be returned. Otherwise, no content but the '
'asset name will be returned.')
help_text += (
' Specifying `resource` will export resource metadata, specifying '
'`iam-policy` will export the IAM policy for each child asset, '
'specifying `org-policy` will export the Org Policy set on child assets,'
' specifying `access-policy` will export the Access Policy set on child '
'assets, specifying `os-inventory` will export the OS inventory of VM '
'instances, and specifying `relationship` will export relationships of '
'the assets.')
parser.add_argument(
'--content-type',
required=required,
choices=[
'resource', 'iam-policy', 'org-policy', 'access-policy',
'os-inventory', 'relationship'
],
help=help_text)
def AddOutputPathArgs(parser, required):
parser.add_argument(
'--output-path',
metavar='OUTPUT_PATH',
required=required,
type=arg_parsers.RegexpValidator(
r'^gs://.*',
'--output-path must be a Google Cloud Storage URI starting with '
'"gs://". For example, "gs://bucket_name/object_name"'),
help='Google Cloud Storage URI where the results will go. '
'URI must start with "gs://". For example, "gs://bucket_name/object_name"'
)
def AddOutputPathPrefixArgs(parser):
parser.add_argument(
'--output-path-prefix',
type=arg_parsers.RegexpValidator(
r'^gs://.*/.*',
'--output-path-prefix must be a Google Cloud Storage URI starting '
'with "gs://". For example, "gs://bucket_name/object_name_prefix"'),
help=(
'Google Cloud Storage URI where the results will go. '
'URI must start with "gs://". For example, '
'"gs://bucket_name/object_name_prefix", in which case each exported '
'object uri is in format: '
'"gs://bucket_name/object_name_prefix/<asset type>/<shard number>" '
'and it only contains assets for that type.'))
def AddOutputPathBigQueryArgs(parser):
"""Add BigQuery destination args to argument list."""
bigquery_group = parser.add_group(
mutex=False,
required=False,
help='The BigQuery destination for exporting assets.')
resource = yaml_data.ResourceYAMLData.FromPath('bq.table')
table_dic = resource.GetData()
# Update the name 'dataset' in table_ref to 'bigquery-dataset'
attributes = table_dic['attributes']
for attr in attributes:
if attr['attribute_name'] == 'dataset':
attr['attribute_name'] = 'bigquery-dataset'
arg_specs = [
resource_args.GetResourcePresentationSpec(
verb='export to',
name='bigquery-table',
required=True,
prefixes=False,
positional=False,
resource_data=table_dic)
]
concept_parsers.ConceptParser(arg_specs).AddToParser(bigquery_group)
base.Argument(
'--output-bigquery-force',
action='store_true',
dest='force_',
default=False,
required=False,
help=(
'If the destination table already exists and this flag is specified, '
'the table will be overwritten by the contents of assets snapshot. '
'If the flag is not specified and the destination table already exists, '
'the export call returns an error.')).AddToParser(bigquery_group)
base.Argument(
'--per-asset-type',
action='store_true',
dest='per_type_',
default=False,
required=False,
help=('If the flag is specified, the snapshot results will be written to '
'one or more tables, each of which contains results of one '
'asset type.')).AddToParser(bigquery_group)
base.ChoiceArgument(
'--partition-key',
required=False,
choices=['read-time', 'request-time'],
help_str=(
'If specified. the snapshot results will be written to partitioned '
'table(s) with two additional timestamp columns, readTime and '
'requestTime, one of which will be the partition key.'
)).AddToParser(bigquery_group)
def AddDestinationArgs(parser):
destination_group = parser.add_group(
mutex=True,
required=True,
help='The destination path for exporting assets.')
AddOutputPathArgs(destination_group, required=False)
AddOutputPathPrefixArgs(destination_group)
AddOutputPathBigQueryArgs(destination_group)
def AddAssetNamesArgs(parser):
parser.add_argument(
'--asset-names',
metavar='ASSET_NAMES',
required=True,
type=arg_parsers.ArgList(),
help=(
'A list of full names of the assets to get the history for. For more '
'information, see: '
'https://cloud.google.com/apis/design/resource_names#full_resource_name '
))
def AddStartTimeArgs(parser):
parser.add_argument(
'--start-time',
required=True,
type=arg_parsers.Datetime.Parse,
help=('Start time of the time window (inclusive) for the asset history. '
'Must be after the current time minus 35 days. See $ gcloud topic '
'datetimes for information on time formats.'))
def AddEndTimeArgs(parser):
parser.add_argument(
'--end-time',
required=False,
type=arg_parsers.Datetime.Parse,
help=('End time of the time window (exclusive) for the asset history. '
'Defaults to current time if not specified. '
'See $ gcloud topic datetimes for information on time formats.'))
def AddOperationArgs(parser):
parser.add_argument(
'id', metavar='OPERATION_NAME', help='Name of the operation to describe.')
def AddListContentTypeArgs(parser):
help_text = (
'Asset content type. If not specified, no content but the asset name and'
' type will be returned in the feed. For more information, see '
'https://cloud.google.com/asset-inventory/docs/reference/rest/v1/feeds#ContentType'
)
parser.add_argument(
'--content-type',
choices=[
'resource', 'iam-policy', 'org-policy', 'access-policy',
'os-inventory', 'relationship'
],
help=help_text)
def AddSavedQueriesQueryId(parser, query_id_help_text):
parser.add_argument(
'query_id', metavar='QUERY_ID', help=query_id_help_text)
def AddSavedQueriesQueryFilePath(parser, is_required):
query_file_path_help_text = (
'Path to JSON or YAML file that contains the query.')
parser.add_argument(
'--query-file-path', required=is_required, help=query_file_path_help_text)
def AddSavedQueriesQueryDescription(parser):
description_help_text = (
'A string describing the query.'
)
parser.add_argument('--description', help=description_help_text)
def AddFeedIdArgs(parser, help_text):
parser.add_argument('feed', metavar='FEED_ID', help=help_text)
def AddFeedNameArgs(parser, help_text):
parser.add_argument('name', help=help_text)
def AddFeedAssetTypesArgs(parser):
parser.add_argument(
'--asset-types',
metavar='ASSET_TYPES',
type=arg_parsers.ArgList(),
default=[],
help=(
'A comma-separated list of types of the assets types to receive '
'updates. For example: '
'`compute.googleapis.com/Disk,compute.googleapis.com/Network`. Regular '
'expressions (https://github.com/google/re2/wiki/Syntax) are also supported. For '
'more information, see: '
'https://cloud.google.com/resource-manager/docs/cloud-asset-inventory/overview'
))
def AddFeedRelationshipTypesArgs(parser):
parser.add_argument(
'--relationship-types',
metavar='RELATIONSHIP_TYPES',
type=arg_parsers.ArgList(),
default=[],
help=(
'A comma-separated list of the relationship types (i.e., '
'"INSTANCE_TO_INSTANCEGROUP") to receive updates. This argument will '
'only be honoured if content_type=RELATIONSHIP.'
'See http://cloud.google.com/asset-inventory/docs/supported-asset-types'
' for supported relationship types.'))
def AddFeedAssetNamesArgs(parser):
parser.add_argument(
'--asset-names',
metavar='ASSET_NAMES',
type=arg_parsers.ArgList(),
default=[],
help=(
'A comma-separated list of the full names of the assets to '
'receive updates. For example: '
'`//compute.googleapis.com/projects/my_project_123/zones/zone1/instances/instance1`.'
' For more information, see: https://cloud.google.com/apis/design/resource_names#full_resource_name'
))
def AddFeedCriteriaArgs(parser):
parent_group = parser.add_group(mutex=False, required=True)
AddFeedAssetTypesArgs(parent_group)
AddFeedAssetNamesArgs(parent_group)
AddFeedRelationshipTypesArgs(parent_group)
def FeedContentTypeArgs(parser, help_text):
parser.add_argument(
'--content-type',
choices=[
'resource', 'iam-policy', 'org-policy', 'access-policy',
'os-inventory', 'relationship'
],
help=help_text)
def AddFeedContentTypeArgs(parser):
help_text = (
'Asset content type. If not specified, no content but the asset name and'
' type will be returned in the feed. For more information, see '
'https://cloud.google.com/resource-manager/docs/cloud-asset-inventory/overview#asset_content_type'
)
FeedContentTypeArgs(parser, help_text)
def AddFeedPubSubTopicArgs(parser, required):
parser.add_argument(
'--pubsub-topic',
metavar='PUBSUB_TOPIC',
required=required,
help=('Name of the Cloud Pub/Sub topic to publish to, of the form '
'`projects/PROJECT_ID/topics/TOPIC_ID`. '
'You can list existing topics with '
'`gcloud pubsub topics list --format="text(name)"`'))
def AddChangeFeedContentTypeArgs(parser):
help_text = (
'Asset content type to overwrite the existing one. For more information,'
' see: '
'https://cloud.google.com/resource-manager/docs/cloud-asset-inventory/overview#asset_content_type'
)
FeedContentTypeArgs(parser, help_text)
def AddClearFeedContentTypeArgs(parser):
parser.add_argument(
'--clear-content-type',
action='store_true',
help=('Clear any existing content type setting on the feed. '
'Content type will be unspecified, no content but'
' the asset name and type will be returned in the feed.'))
def AddUpdateFeedContentTypeArgs(parser):
parent_group = parser.add_group(mutex=True)
AddChangeFeedContentTypeArgs(parent_group)
AddClearFeedContentTypeArgs(parent_group)
def FeedConditionExpressionArgs(parser, help_text):
parser.add_argument('--condition-expression', help=help_text)
def AddFeedConditionExpressionArgs(parser):
help_text = (
'Feed condition expression. If not specified, no condition will be '
'applied to feed. For more information, see: '
'https://cloud.google.com/asset-inventory/docs/monitoring-asset-changes#feed_with_condition'
)
FeedConditionExpressionArgs(parser, help_text)
def AddChangeFeedConditionExpressionArgs(parser):
help_text = (
'Condition expression to overwrite the existing one. For more '
'information, see: '
'https://cloud.google.com/asset-inventory/docs/monitoring-asset-changes#feed_with_condition'
)
FeedConditionExpressionArgs(parser, help_text)
def AddClearFeedConditionExpressionArgs(parser):
parser.add_argument(
'--clear-condition-expression',
action='store_true',
help=('Clear any existing condition expression setting on the feed. '
'No condition will be applied to feed.'))
def AddUpdateFeedConditionExpressionArgs(parser):
parent_group = parser.add_group(mutex=True)
AddChangeFeedConditionExpressionArgs(parent_group)
AddClearFeedConditionExpressionArgs(parent_group)
def FeedConditionTitleArgs(parser, help_text):
parser.add_argument('--condition-title', help=help_text)
def AddFeedConditionTitleArgs(parser):
help_text = ('Title of the feed condition. For reference only.')
FeedConditionTitleArgs(parser, help_text)
def AddChangeFeedConditionTitleArgs(parser):
help_text = ('Condition title to overwrite the existing one.')
FeedConditionTitleArgs(parser, help_text)
def AddClearFeedConditionTitleArgs(parser):
parser.add_argument(
'--clear-condition-title',
action='store_true',
help=('Clear any existing condition title setting on the feed. '
'Condition title will be empty.'))
def AddUpdateFeedConditionTitleArgs(parser):
parent_group = parser.add_group(mutex=True)
AddChangeFeedConditionTitleArgs(parent_group)
AddClearFeedConditionTitleArgs(parent_group)
def FeedConditionDescriptionArgs(parser, help_text):
parser.add_argument('--condition-description', help=help_text)
def AddFeedConditionDescriptionArgs(parser):
help_text = ('Description of the feed condition. For reference only.')
FeedConditionDescriptionArgs(parser, help_text)
def AddChangeFeedConditionDescriptionArgs(parser):
help_text = ('Condition description to overwrite the existing one.')
FeedConditionDescriptionArgs(parser, help_text)
def AddClearFeedConditionDescriptionArgs(parser):
parser.add_argument(
'--clear-condition-description',
action='store_true',
help=('Clear any existing condition description setting on the feed. '
'Condition description will be empty.'))
def AddUpdateFeedConditionDescriptionArgs(parser):
parent_group = parser.add_group(mutex=True)
AddChangeFeedConditionDescriptionArgs(parent_group)
AddClearFeedConditionDescriptionArgs(parent_group)
def AddAnalyzerFullResourceNameArgs(parser):
parser.add_argument('--full-resource-name', help='The full resource name.')
def AddAnalyzerResourceSelectorGroup(parser):
resource_selector_group = parser.add_group(
mutex=False,
required=False,
help='Specifies a resource for analysis. Leaving it empty means ANY.')
AddAnalyzerFullResourceNameArgs(resource_selector_group)
def AddAnalyzerIdentityArgs(parser):
parser.add_argument(
'--identity',
help=(
'The identity appearing in the form of principals in the IAM policy '
'binding.'))
def AddAnalyzerIdentitySelectorGroup(parser):
identity_selector_group = parser.add_group(
mutex=False,
required=False,
help='Specifies an identity for analysis. Leaving it empty means ANY.')
AddAnalyzerIdentityArgs(identity_selector_group)
def AddAnalyzerRolesArgs(parser):
parser.add_argument(
'--roles',
metavar='ROLES',
type=arg_parsers.ArgList(),
help='The roles to appear in the result.')
def AddAnalyzerPermissionsArgs(parser):
parser.add_argument(
'--permissions',
metavar='PERMISSIONS',
type=arg_parsers.ArgList(),
help='The permissions to appear in the result.')
def AddAnalyzerAccessSelectorGroup(parser):
access_selector_group = parser.add_group(
mutex=False,
required=False,
help=('Specifies roles or permissions for analysis. Leaving it empty '
'means ANY.'))
AddAnalyzerRolesArgs(access_selector_group)
AddAnalyzerPermissionsArgs(access_selector_group)
def AddAnalyzerSelectorsGroup(parser):
AddAnalyzerResourceSelectorGroup(parser)
AddAnalyzerIdentitySelectorGroup(parser)
AddAnalyzerAccessSelectorGroup(parser)
def AddAnalyzerExpandGroupsArgs(parser):
parser.add_argument(
'--expand-groups',
action='store_true',
help=(
'If true, the identities section of the result will expand any '
'Google groups appearing in an IAM policy binding. Default is false.'
))
parser.set_defaults(expand_groups=False)
def AddAnalyzerExpandRolesArgs(parser):
parser.add_argument(
'--expand-roles',
action='store_true',
help=('If true, the access section of result will expand any roles '
'appearing in IAM policy bindings to include their permissions. '
'Default is false.'))
parser.set_defaults(expand_roles=False)
def AddAnalyzerExpandResourcesArgs(parser):
parser.add_argument(
'--expand-resources',
action='store_true',
help=('If true, the resource section of the result will expand any '
'resource attached to an IAM policy to include resources lower in '
'the resource hierarchy. Default is false.'))
parser.set_defaults(expand_resources=False)
def AddAnalyzerOutputResourceEdgesArgs(parser):
parser.add_argument(
'--output-resource-edges',
action='store_true',
help=('If true, the result will output the relevant parent/child '
'relationships between resources. '
'Default is false.'))
parser.set_defaults(output_resource_edges=False)
def AddAnalyzerOutputGroupEdgesArgs(parser):
parser.add_argument(
'--output-group-edges',
action='store_true',
help=('If true, the result will output the relevant membership '
'relationships between groups. '
'Default is false.'))
parser.set_defaults(output_group_edges=False)
def AddAnalyzerExecutionTimeout(parser):
parser.add_argument(
'--execution-timeout',
type=arg_parsers.Duration(),
help=(
'The amount of time the executable has to complete. See JSON '
'representation of '
'[Duration](https://developers.google.com/protocol-buffers/docs/proto3#json). '
'Deafult is empty. '))
def AddAnalyzerShowAccessControlEntries(parser):
parser.add_argument(
'--show-response',
action='store_true',
help=(
'If true, the response will be showed as-is in the command output.'))
parser.set_defaults(show_response=False)
def AddAnalyzerAnalyzeServiceAccountImpersonationArgs(parser):
"""Adds analyze service account impersonation arg into options.
Args:
parser: the option group.
"""
parser.add_argument(
'--analyze-service-account-impersonation',
action='store_true',
help=(
'If true, the response will include access analysis from identities '
'to resources via service account impersonation. This is a very '
'expensive operation, because many derived queries will be executed. '
'We highly recommend you use AnalyzeIamPolicyLongrunning rpc instead.'
' Default is false.'))
parser.set_defaults(analyze_service_account_impersonation=False)
def AddAnalyzerIncludeDenyPolicyAnalysisArgs(parser):
"""Adds include deny policy analysis arg into options.
Args:
parser: the option group.
"""
parser.add_argument(
'--include-deny-policy-analysis',
action='store_true',
help=(
'If true, the response will include analysis for deny policies.'
'This is a very expensive operation, because many derived queries '
'will be executed.'
),
)
parser.set_defaults(include_deny_policy_analysis=False)
def AddAnalyzerOptionsGroup(parser, is_sync):
"""Adds a group of options."""
options_group = GetOrAddOptionGroup(parser)
AddAnalyzerExpandGroupsArgs(options_group)
AddAnalyzerExpandRolesArgs(options_group)
AddAnalyzerExpandResourcesArgs(options_group)
AddAnalyzerOutputResourceEdgesArgs(options_group)
AddAnalyzerOutputGroupEdgesArgs(options_group)
AddAnalyzerAnalyzeServiceAccountImpersonationArgs(options_group)
if is_sync:
AddAnalyzerExecutionTimeout(options_group)
AddAnalyzerShowAccessControlEntries(options_group)
def AddAnalyzerAccessTimeArgs(parser):
parser.add_argument(
'--access-time',
type=arg_parsers.Datetime.Parse,
help=('The hypothetical access timestamp to evaluate IAM conditions.'))
def AddAnalyzerSavedAnalysisQueryArgs(parser):
"""Adds a saved analysis query."""
identity_selector_group = parser.add_group(
mutex=False,
required=False,
help='Specifies the name of a saved analysis query.')
text = (
'The name of a saved query. \n'
'When a `saved_analysis_query` is provided, '
'its query content will be used as the base query. Other flags\' values '
'will override the base query to compose the final query to run. '
'IDs might be in one of the following formats:\n'
'* projects/project_number/savedQueries/saved_query_id'
'* folders/folder_number/savedQueries/saved_query_id'
'* organizations/organization_number/savedQueries/saved_query_id')
identity_selector_group.add_argument('--saved-analysis-query', help=text)
def AddAnalyzerConditionContextGroup(parser):
"""Adds a group of options."""
condition_context_group = parser.add_group(
mutex=False,
required=False,
help='The hypothetical context to evaluate IAM conditions.')
AddAnalyzerAccessTimeArgs(condition_context_group)
def AddStatementArgs(parser):
"""Adds the sql statement."""
parser.add_argument(
'--statement',
help=(
'A BigQuery Standard SQL compatible statement. If the query execution '
'finishes within timeout and there is no pagination, the full query '
'results will be returned. Otherwise, pass job_reference from '
'previous call as `--job-reference` to obtain the full results.'))
def AddJobReferenceArgs(parser):
"""Adds the previous job reference."""
parser.add_argument(
'--job-reference',
help=('Reference to the query job, which is from the previous call.'))
def AddQueryArgs(parser):
"""Adds query args."""
query_group = parser.add_group(
mutex=True,
required=True,
help='The query or job reference of the query request.')
AddStatementArgs(query_group)
AddJobReferenceArgs(query_group)
def AddPageSize(parser):
"""Adds page size."""
parser.add_argument(
'--page-size',
type=int,
help=(
'The maximum number of rows to return in the results. One page is also limited to 10 MB.'
))
def AddPageToken(parser):
"""Adds page token."""
parser.add_argument(
'--page-token', help=('A page token received from previous call.'))
def AddTimeout(parser):
"""Adds timeout."""
parser.add_argument(
'--timeout',
type=arg_parsers.Duration(),
help=(
'Maximum amount of time that the client will wait for the query to complete.'
))
def AddReadTimeWindowArgs(parser):
"""Adds read time window."""
time_window_group = parser.add_group(
mutex=False,
required=False,
help='Specifies what time period or point in time to query asset metadata at.'
)
AddStartTimeArgs(time_window_group)
AddEndTimeArgs(time_window_group)
def AddTimeArgs(parser):
"""Adds read time."""
time_group = parser.add_group(
mutex=True,
required=False,
help='Specifies what time period or point in time to query asset metadata at.'
)
AddSnapshotTimeArgs(time_group)
AddReadTimeWindowArgs(time_group)
def AddQuerySystemBigQueryArgs(parser):
"""Add BigQuery destination args to argument list for query system."""
bigquery_group = parser.add_group(
mutex=False,
required=False,
help='The BigQuery destination for query system.')
resource = yaml_data.ResourceYAMLData.FromPath('bq.table')
table_dic = resource.GetData()
# Update the name 'dataset' in table_ref to 'bigquery-dataset'
attributes = table_dic['attributes']
for attr in attributes:
if attr['attribute_name'] == 'dataset':
attr['attribute_name'] = 'bigquery-dataset'
arg_specs = [
resource_args.GetResourcePresentationSpec(
verb='for the export',
name='bigquery-table',
required=False,
prefixes=False,
positional=False,
resource_data=table_dic)
]
if arg_specs:
concept_parsers.ConceptParser(arg_specs).AddToParser(bigquery_group)
base.ChoiceArgument(
'--write-disposition',
help_str='Specifies the action that occurs if the destination table or partition already exists.',
choices={
'write-truncate':
"""If the table or partition already exists, BigQuery overwrites
the entire table or all the partition\'s data.""",
'write-append':
"""If the table or partition already exists, BigQuery appends the
data to the table or the latest partition.""",
'write-empty':
"""If the table already exists and contains data, an error is
returned.""",
},
).AddToParser(bigquery_group)
def AddDestinationGroup(parser):
destination_group = parser.add_group(
mutex=True,
required=True,
help='The destination path for writing IAM policy analysis results.',
)
AddGcsOutputPathArgs(destination_group)
AddBigQueryDestinationGroup(destination_group)
def AddGcsOutputPathArgs(parser):
parser.add_argument(
'--gcs-output-path',
metavar='GCS_OUTPUT_PATH',
required=False,
type=arg_parsers.RegexpValidator(
r'^gs://.*',
'--gcs-output-path must be a Google Cloud Storage URI starting with '
'"gs://". For example, "gs://bucket_name/object_name".',
),
help=(
'Google Cloud Storage URI where the results will be written. URI must'
' start with "gs://". For example, "gs://bucket_name/object_name".'
),
)
def AddBigQueryDestinationGroup(parser):
bigquery_destination_group = parser.add_group(
mutex=False,
required=False,
help='BigQuery destination where the results will go.',
)
AddBigQueryDatasetArgs(bigquery_destination_group)
AddBigQueryTablePrefixArgs(bigquery_destination_group)
AddBigQueryPartitionKeyArgs(bigquery_destination_group)
AddBigQueryWriteDispositionArgs(bigquery_destination_group)
def AddBigQueryDatasetArgs(parser):
parser.add_argument(
'--bigquery-dataset',
metavar='BIGQUERY_DATASET',
required=True,
type=arg_parsers.RegexpValidator(
r'^projects/[A-Za-z0-9\-]+/datasets/[\w]+',
'--bigquery-dataset must be a dataset relative name starting with '
'"projects/". For example, '
'"projects/project_id/datasets/dataset_id".',
),
help=(
'BigQuery dataset where the results will be written. Must be a '
'dataset relative name starting with "projects/". For example, '
'"projects/project_id/datasets/dataset_id".'
),
)
def AddBigQueryTablePrefixArgs(parser):
parser.add_argument(
'--bigquery-table-prefix',
metavar='BIGQUERY_TABLE_PREFIX',
required=True,
type=arg_parsers.RegexpValidator(
r'[\w]+',
'--bigquery-table-prefix must be a BigQuery table name consists of '
'letters, numbers and underscores".',
),
help=(
'The prefix of the BigQuery tables to which the analysis results '
'will be written. A table name consists of letters, numbers and '
'underscores".'
),
)
def AddBigQueryPartitionKeyArgs(parser):
parser.add_argument(
'--bigquery-partition-key',
choices=['PARTITION_KEY_UNSPECIFIED', 'REQUEST_TIME'],
help=(
'This enum determines the partition key column for the bigquery'
' tables. Partitioning can improve query performance and reduce query'
' cost by filtering partitions. Refer to'
' https://cloud.google.com/bigquery/docs/partitioned-tables for'
' details.'
),
)
def AddBigQueryWriteDispositionArgs(parser):
parser.add_argument(
'--bigquery-write-disposition',
metavar='BIGQUERY_WRITE_DISPOSITION',
help=(
'Specifies the action that occurs if the destination table or '
'partition already exists. The following values are supported: '
'WRITE_TRUNCATE, WRITE_APPEND and WRITE_EMPTY. The default value is '
'WRITE_APPEND.'
),
)