HEX
Server: Apache/2.4.65 (Ubuntu)
System: Linux ielts-store-v2 6.8.0-1036-gcp #38~22.04.1-Ubuntu SMP Thu Aug 14 01:19:18 UTC 2025 x86_64
User: root (0)
PHP: 7.2.34-54+ubuntu20.04.1+deb.sury.org+1
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: //snap/google-cloud-cli/394/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.'
      ),
  )