Esempio n. 1
0
    def Modify(self, args, existing):
        """Returns a modified URL map message."""
        replacement = self._ModifyBase(args, existing)

        # Creates PathRule objects from --path-rules, --backend-service-path-rules,
        # and --backend-bucket-path-rules.
        service_map = collections.defaultdict(set)
        bucket_map = collections.defaultdict(set)
        for path, service in args.path_rules.iteritems():
            service_map[service].add(path)
        for path, service in args.backend_service_path_rules.iteritems():
            service_map[service].add(path)
        for path, bucket in args.backend_bucket_path_rules.iteritems():
            bucket_map[bucket].add(path)
        path_rules = []
        for service, paths in sorted(service_map.iteritems()):
            path_rules.append(
                self.messages.PathRule(
                    paths=sorted(paths),
                    service=self.CreateGlobalReference(service, resource_type="backendServices").SelfLink(),
                )
            )
        for bucket, paths in sorted(bucket_map.iteritems()):
            path_rules.append(
                self.messages.PathRule(
                    paths=sorted(paths),
                    service=self.CreateGlobalReference(bucket, resource_type="backendBuckets").SelfLink(),
                )
            )

        if args.default_service:
            default_backend_uri = self.CreateGlobalReference(
                args.default_service, resource_type="backendServices"
            ).SelfLink()
        else:
            default_backend_uri = self.CreateGlobalReference(
                args.default_backend_bucket, resource_type="backendBuckets"
            ).SelfLink()

        new_path_matcher = self.messages.PathMatcher(
            defaultService=default_backend_uri,
            description=args.description,
            name=args.path_matcher_name,
            pathRules=path_rules,
        )

        replacement.pathMatchers.append(new_path_matcher)
        return replacement
Esempio n. 2
0
    def Modify(self, args, existing):
        """Returns a modified URL map message."""
        replacement = self._ModifyBase(args, existing)

        # Creates PathRule objects from --path-rules.
        service_map = collections.defaultdict(set)
        for path, service in args.path_rules.iteritems():
            service_map[service].add(path)
        path_rules = []
        for service, paths in sorted(service_map.iteritems()):
            path_rules.append(
                self.messages.PathRule(
                    paths=sorted(paths),
                    service=self.CreateGlobalReference(
                        service, resource_type='backendServices').SelfLink()))

        new_path_matcher = self.messages.PathMatcher(
            defaultService=self.CreateGlobalReference(
                args.default_service,
                resource_type='backendServices').SelfLink(),
            description=args.description,
            name=args.path_matcher_name,
            pathRules=path_rules)

        replacement.pathMatchers.append(new_path_matcher)
        return replacement
Esempio n. 3
0
def CreateServiceAccountMessages(messages, scopes):
  """Returns a list of ServiceAccount messages corresponding to scopes."""
  if scopes is None:
    scopes = constants.DEFAULT_SCOPES

  accounts_to_scopes = collections.defaultdict(list)
  for scope in scopes:
    parts = scope.split('=')
    if len(parts) == 1:
      account = 'default'
      scope_uri = scope
    elif len(parts) == 2:
      account, scope_uri = parts
    else:
      raise exceptions.ToolException(
          '[{0}] is an illegal value for [--scopes]. Values must be of the '
          'form [SCOPE] or [ACCOUNT=SCOPE].'.format(scope))

    # Expands the scope if the user provided an alias like
    # "compute-rw".
    scope_uri = constants.SCOPES.get(scope_uri, scope_uri)

    accounts_to_scopes[account].append(scope_uri)

  res = []
  for account, scopes in sorted(accounts_to_scopes.iteritems()):
    res.append(messages.ServiceAccount(email=account,
                                       scopes=sorted(scopes)))
  return res
    def CreateServiceAccountMessages(self, args):
        """Returns a list of ServiceAccount messages corresponding to --scopes."""
        if args.no_scopes:
            scopes = []
        else:
            scopes = args.scopes or constants.DEFAULT_SCOPES

        accounts_to_scopes = collections.defaultdict(list)
        for scope in scopes:
            parts = scope.split('=')
            if len(parts) == 1:
                account = 'default'
                scope_uri = scope
            elif len(parts) == 2:
                account, scope_uri = parts
            else:
                raise exceptions.ToolException(
                    '[{0}] is an illegal value for [--scopes]. Values must be of the '
                    'form [SCOPE] or [ACCOUNT=SCOPE].'.format(scope))

            # Expands the scope if the user provided an alias like
            # "compute-rw".
            scope_uri = constants.SCOPES.get(scope_uri, scope_uri)

            accounts_to_scopes[account].append(scope_uri)

        res = []
        for account, scopes in sorted(accounts_to_scopes.iteritems()):
            res.append(
                self.messages.ServiceAccount(email=account,
                                             scopes=sorted(scopes)))
        return res
Esempio n. 5
0
    def Modify(self, args, existing):
        """Returns a modified URL map message."""
        replacement = self._ModifyBase(args, existing)

        # Creates PathRule objects from --path-rules, --backend-service-path-rules,
        # and --backend-bucket-path-rules.
        service_map = collections.defaultdict(set)
        bucket_map = collections.defaultdict(set)
        for path, service in args.path_rules.iteritems():
            service_map[service].add(path)
        for path, service in args.backend_service_path_rules.iteritems():
            service_map[service].add(path)
        for path, bucket in args.backend_bucket_path_rules.iteritems():
            bucket_map[bucket].add(path)
        path_rules = []
        for service, paths in sorted(service_map.iteritems()):
            path_rules.append(
                self.messages.PathRule(
                    paths=sorted(paths),
                    service=self.resources.Parse(
                        service,
                        collection='compute.backendServices').SelfLink()))
        for bucket, paths in sorted(bucket_map.iteritems()):
            path_rules.append(
                self.messages.PathRule(
                    paths=sorted(paths),
                    service=self.resources.Parse(
                        bucket,
                        collection='compute.backendBuckets').SelfLink()))

        if args.default_service:
            default_backend_uri = self.BACKEND_SERVICE_ARG.ResolveAsResource(
                args, self.resources).SelfLink()
        else:
            default_backend_uri = self.BACKEND_BUCKET_ARG.ResolveAsResource(
                args, self.resources).SelfLink()

        new_path_matcher = self.messages.PathMatcher(
            defaultService=default_backend_uri,
            description=args.description,
            name=args.path_matcher_name,
            pathRules=path_rules)

        replacement.pathMatchers.append(new_path_matcher)
        return replacement
Esempio n. 6
0
 def __init__(self,
              parsers_by_collection=None,
              parsers_by_url=None,
              default_param_funcs=None,
              registered_apis=None):
     self.parsers_by_collection = parsers_by_collection or {}
     self.parsers_by_url = parsers_by_url or {}
     self.default_param_funcs = default_param_funcs or {}
     self.registered_apis = registered_apis or collections.defaultdict(set)
Esempio n. 7
0
    def MonitorTestMatrixProgress(self):
        """Monitor and report the progress of multiple running tests in a matrix."""
        while True:
            matrix = self.GetTestMatrixStatus()

            state_counts = collections.defaultdict(int)
            for test in matrix.testExecutions:
                state_counts[test.state] += 1

            self._UpdateMatrixStatus(state_counts)

            if matrix.state in self.completed_matrix_states:
                self._LogTestComplete(matrix.state)
                break
            self._SleepForStatusInterval()
Esempio n. 8
0
  def MonitorTestMatrixProgress(self):
    """Monitor and report the progress of multiple running tests in a matrix."""
    while True:
      matrix = self.GetTestMatrixStatus()

      state_counts = collections.defaultdict(int)
      for test in matrix.testExecutions:
        state_counts[test.state] += 1

      self._UpdateMatrixStatus(state_counts)

      if matrix.state in self.completed_matrix_states:
        self._LogTestComplete(matrix.state)
        break
      self._SleepForStatusInterval()
Esempio n. 9
0
  def CreateServiceAccountMessages(self, args):
    """Returns a list of ServiceAccount messages corresponding to --scopes.

    Args:
      args: the argparse arguments that this command was invoked with.

    Returns:
      res: a list of ServiceAccount message objects

    Raises:
      ToolException: if the scopes are provided in an invalid format.
    """
    if args.no_scopes:
      scopes = []
    else:
      scopes = args.scopes or constants.DEFAULT_SCOPES

    accounts_to_scopes = collections.defaultdict(list)
    for scope in scopes:
      parts = scope.split('=')
      if len(parts) == 1:
        account = 'default'
        scope_uri = scope
      elif len(parts) == 2:
        account, scope_uri = parts
      else:
        raise exceptions.ToolException(
            '[{0}] is an illegal value for [--scopes]. Values must be of the '
            'form [SCOPE] or [ACCOUNT=SCOPE].'.format(scope))

      # Expands the scope if the user provided an alias like
      # "compute-rw".
      scope_uri = constants.SCOPES.get(scope_uri, scope_uri)

      accounts_to_scopes[account].append(scope_uri)

    res = []
    for account, scopes in sorted(accounts_to_scopes.iteritems()):
      res.append(self.messages.ServiceAccount(
          email=account,
          scopes=sorted(scopes)))
    return res
Esempio n. 10
0
  def Modify(self, args, existing):
    """Returns a modified URL map message."""
    replacement = self._ModifyBase(args, existing)

    # Creates PathRule objects from --path-rules.
    service_map = collections.defaultdict(set)
    for path, service in args.path_rules.iteritems():
      service_map[service].add(path)
    path_rules = []
    for service, paths in sorted(service_map.iteritems()):
      path_rules.append(self.messages.PathRule(
          paths=sorted(paths),
          service=self.CreateGlobalReference(
              service, resource_type='backendServices').SelfLink()))

    new_path_matcher = self.messages.PathMatcher(
        defaultService=self.CreateGlobalReference(
            args.default_service, resource_type='backendServices').SelfLink(),
        description=args.description,
        name=args.path_matcher_name,
        pathRules=path_rules)

    replacement.pathMatchers.append(new_path_matcher)
    return replacement
Esempio n. 11
0
  def _PrintSynopsisSection(self):
    """Prints the command line synopsis section."""
    # MARKDOWN_CODE is the default SYNOPSIS font style.
    code = usage_text.MARKDOWN_CODE
    em = usage_text.MARKDOWN_ITALIC
    self._Section('SYNOPSIS')
    self._out('{code}{command}{code}'.format(code=code,
                                             command=self._command_name))

    # Output the positional args up to the first REMAINDER or '-- *' args. The
    # rest will be picked up after the flag args are output. argparse does not
    # have an explicit '--' arg intercept, so we use the metavar value as a '--'
    # sentinel.
    # Any SUPPRESSed args are ingnored by a pre-pass.
    positional_args = FilterOutSuppressed(self._command.ai.positional_args[:])
    while positional_args:
      arg = positional_args[0]
      if arg.nargs == argparse.REMAINDER or arg.metavar.startswith('-- '):
        break
      positional_args.pop(0)
      self._out(usage_text.PositionalDisplayString(arg, markdown=True))

    if self._subcommands and self._subgroups:
      self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em)
    elif self._subcommands:
      self._out(' ' + em + 'COMMAND' + em)
    elif self._subgroups:
      self._out(' ' + em + 'GROUP' + em)

    # Place all flags into a dict. Flags that are in a mutually
    # exclusive group are mapped group_id -> [flags]. All other flags
    # are mapped dest -> [flag].
    global_flags = False
    groups = collections.defaultdict(list)
    for flag in (self._command.ai.flag_args +
                 self._command.ai.ancestor_flag_args):
      if flag.is_global and not self._is_top_element:
        global_flags = True
      else:
        group_id = self._command.ai.mutex_groups.get(flag.dest, flag.dest)
        groups[group_id].append(flag)

    # Split the groups dict into required, common, and then the rest of the
    # flags.  A group is required if any flag in it is required and common if
    # any flag in it is common.  Required takes precedence over common.
    required_groups = {}
    common_groups = {}
    for group_id, flags in groups.iteritems():
      for f in flags:
        if f.required:
          required_groups[group_id] = flags
          break
        elif f.is_common:
          common_groups[group_id] = flags
          break
    for g in required_groups:
      del groups[g]
    for g in common_groups:
      del groups[g]

    # Generate the flag usage string with required flags first, then common
    # flags, then the rest of the flags.
    for section in [required_groups, common_groups, groups]:
      for group in sorted(section.values(), key=lambda g: g[0].option_strings):
        if len(group) == 1:
          arg = group[0]
          if self._IsSuppressed(arg):
            continue
          msg = usage_text.FlagDisplayString(arg, markdown=True)
          if not msg:
            continue
          if arg.required:
            self._out(' {msg}'.format(msg=msg))
          else:
            self._out(' [{msg}]'.format(msg=msg))
        else:
          group.sort(key=lambda f: f.option_strings)
          group = [flag for flag in group if not self._IsSuppressed(flag)]
          msg = ' | '.join(usage_text.FlagDisplayString(arg, markdown=True)
                           for arg in group)
          if not msg:
            continue
          self._out(' [{msg}]'.format(msg=msg))

    if global_flags:
      self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']')

    # positional_args will only be non-empty if we had -- ... or REMAINDER left.
    for arg in FilterOutSuppressed(positional_args):
      self._out(usage_text.PositionalDisplayString(arg, markdown=True))
Esempio n. 12
0
  def _PrintSynopsisSection(self):
    """Prints the command line synopsis section."""
    # MARKDOWN_CODE is the default SYNOPSIS font style.
    code = base.MARKDOWN_CODE
    em = base.MARKDOWN_ITALIC
    self._Section('SYNOPSIS')
    self._out('{code}{command}{code}'.format(code=code,
                                             command=self._command_name))

    # Output the positional args up to the first REMAINDER or '-- *' args. The
    # rest will be picked up after the flag args are output. argparse does not
    # have an explicit '--' arg intercept, so we use the metavar value as a '--'
    # sentinel. Any suppressed args are ingnored by a pre-pass.
    positional_args = usage_text.FilterOutSuppressed(
        self._command.ai.positional_args)
    while positional_args:
      arg = positional_args[0]
      if arg.nargs == argparse.REMAINDER or arg.metavar.startswith('-- '):
        break
      positional_args.pop(0)
      self._out(usage_text.PositionalDisplayString(arg, markdown=True))

    if self._subcommands and self._subgroups:
      self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em)
    elif self._subcommands:
      self._out(' ' + em + 'COMMAND' + em)
    elif self._subgroups:
      self._out(' ' + em + 'GROUP' + em)

    # Place all flags into a dict. Flags that are in a mutually
    # exclusive group are mapped group_id -> [flags]. All other flags
    # are mapped dest -> [flag].
    global_flags = False
    groups = collections.defaultdict(list)
    for flag in (self._command.ai.flag_args +
                 self._command.ai.ancestor_flag_args):
      if flag.is_global and not self._is_top_element:
        global_flags = True
      else:
        group_id = self._command.ai.mutex_groups.get(flag.dest, flag.dest)
        groups[group_id].append(flag)

    # Partition the non-GLOBAL flag groups dict into categorized sections. A
    # group is REQUIRED if any flag in it is required, categorized if any flag
    # in it is categorized, otherwise its OTHER.  REQUIRED takes precedence
    # over categorized.
    categorized_groups = {}
    for group_id, flags in groups.iteritems():
      for f in flags:
        if f.required:
          category = 'REQUIRED'
        elif f.category:
          category = f.category
        else:
          continue
        if category not in categorized_groups:
          categorized_groups[category] = {}
        categorized_groups[category][group_id] = flags
        break
    # Delete the categorized groups to get OTHER.
    for v in categorized_groups.values():
      for g in v:
        del groups[g]
    category = 'OTHER'
    if category not in categorized_groups:
      categorized_groups[category] = {}
    for group_id, flags in groups.iteritems():
      categorized_groups[category][group_id] = flags

    # Collect the sections in order: REQUIRED, COMMON, OTHER, and categorized.
    sections = []
    for category in ('REQUIRED', base.COMMONLY_USED_FLAGS, 'OTHER'):
      if category in categorized_groups:
        sections.append(categorized_groups[category])
        del categorized_groups[category]
    for _, v in sorted(categorized_groups.iteritems()):
      sections.append(v)

    # Generate the flag usage string with flags in section order.
    for section in sections:
      for group in sorted(section.values(), key=lambda g: g[0].option_strings):
        if len(group) == 1:
          arg = group[0]
          if usage_text.IsSuppressed(arg):
            continue
          msg = usage_text.FlagDisplayString(arg, markdown=True)
          if not msg:
            continue
          if arg.required:
            self._out(' {msg}'.format(msg=msg))
          else:
            self._out(' [{msg}]'.format(msg=msg))
        else:
          # Check if the inverted boolean name should be displayed.
          inverted = None
          if len(group) == 2:
            for arg in group:
              if getattr(arg, 'show_inverted', False):
                inverted = arg
                break
          if inverted:
            # The inverted arg replaces the boolean group which only contains
            # the arg and inverted arg.
            msg = usage_text.FlagDisplayString(inverted, markdown=True)
          else:
            group = usage_text.FilterOutSuppressed(group)
            group.sort(key=lambda f: f.option_strings)
            msg = ' | '.join(usage_text.FlagDisplayString(arg, markdown=True)
                             for arg in group)
          if not msg:
            continue
          self._out(' [{msg}]'.format(msg=msg))

    if global_flags:
      self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']')

    # positional_args will only be non-empty if we had -- ... or REMAINDER left.
    for arg in usage_text.FilterOutSuppressed(positional_args):
      self._out(usage_text.PositionalDisplayString(arg, markdown=True))
Esempio n. 13
0
 def Clear(self):
     self.parsers_by_collection = {}
     self.parsers_by_url = {}
     self.default_param_funcs = {}
     self.registered_apis = collections.defaultdict(list)
    def Modify(self, args, existing):
        """Returns a modified URL map message."""
        replacement = copy.deepcopy(existing)

        if not args.new_hosts and not args.existing_host:
            new_hosts = ['*']
        else:
            new_hosts = args.new_hosts

        # If --new-hosts is given, we check to make sure none of those
        # hosts already exist and once the check succeeds, we create the
        # new host rule.
        if new_hosts:
            new_hosts = set(new_hosts)
            for host_rule in existing.hostRules:
                for host in host_rule.hosts:
                    if host in new_hosts:
                        raise exceptions.ToolException(
                            'Cannot create a new host rule with host [{0}] because the '
                            'host is already part of a host rule that references the path '
                            'matcher [{1}].'.format(host,
                                                    host_rule.pathMatcher))

            replacement.hostRules.append(
                self.messages.HostRule(hosts=sorted(new_hosts),
                                       pathMatcher=args.path_matcher_name))

        # If --existing-host is given, we check to make sure that the
        # corresponding host rule will not render a patch matcher
        # orphan. If the check succeeds, we change the path matcher of the
        # host rule. If the check fails, we remove the path matcher if
        # --delete-orphaned-path-matcher is given otherwise we fail.
        else:
            target_host_rule = None
            for host_rule in existing.hostRules:
                for host in host_rule.hosts:
                    if host == args.existing_host:
                        target_host_rule = host_rule
                        break
                if target_host_rule:
                    break

            if not target_host_rule:
                raise exceptions.ToolException(
                    'No host rule with host [{0}] exists. Check your spelling or '
                    'use [--new-hosts] to create a new host rule.'.format(
                        args.existing_host))

            path_matcher_orphaned = True
            for host_rule in replacement.hostRules:
                if host_rule == target_host_rule:
                    host_rule.pathMatcher = args.path_matcher_name
                    continue

                if host_rule.pathMatcher == target_host_rule.pathMatcher:
                    path_matcher_orphaned = False
                    break

            if path_matcher_orphaned:
                # A path matcher will be orphaned, so now we determine whether
                # we should delete the path matcher or report an error.
                if args.delete_orphaned_path_matcher:
                    replacement.pathMatchers = [
                        path_matcher for path_matcher in existing.pathMatchers
                        if path_matcher.name != target_host_rule.pathMatcher
                    ]
                else:
                    raise exceptions.ToolException(
                        'This operation will orphan the path matcher [{0}]. To '
                        'delete the orphan path matcher, rerun this command with '
                        '[--delete-orphaned-path-matcher] or use [gcloud compute '
                        'url-maps edit] to modify the URL map by hand.'.format(
                            host_rule.pathMatcher))

        # Creates PathRule objects from --path-rules.
        service_map = collections.defaultdict(set)
        for path, service in args.path_rules.iteritems():
            service_map[service].add(path)
        path_rules = []
        for service, paths in sorted(service_map.iteritems()):
            path_rules.append(
                self.messages.PathRule(
                    paths=sorted(paths),
                    service=self.CreateGlobalReference(
                        service, resource_type='backendServices').SelfLink()))

        new_path_matcher = self.messages.PathMatcher(
            defaultService=self.CreateGlobalReference(
                args.default_service,
                resource_type='backendServices').SelfLink(),
            description=args.description,
            name=args.path_matcher_name,
            pathRules=path_rules)

        replacement.pathMatchers.append(new_path_matcher)
        return replacement
Esempio n. 15
0
    def _PrintSynopsisSection(self):
        """Prints the command line synopsis section."""
        # MARKDOWN_CODE is the default SYNOPSIS font style.
        code = base.MARKDOWN_CODE
        em = base.MARKDOWN_ITALIC
        self._Section('SYNOPSIS')
        self._out('{code}{command}{code}'.format(code=code,
                                                 command=self._command_name))

        # Output the positional args up to the first REMAINDER or '-- *' args. The
        # rest will be picked up after the flag args are output. argparse does not
        # have an explicit '--' arg intercept, so we use the metavar value as a '--'
        # sentinel. Any suppressed args are ingnored by a pre-pass.
        positional_args = usage_text.FilterOutSuppressed(
            self._command.ai.positional_args)
        while positional_args:
            arg = positional_args[0]
            if arg.nargs == argparse.REMAINDER or arg.metavar.startswith(
                    '-- '):
                break
            positional_args.pop(0)
            self._out(usage_text.PositionalDisplayString(arg, markdown=True))

        if self._subcommands and self._subgroups:
            self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em)
        elif self._subcommands:
            self._out(' ' + em + 'COMMAND' + em)
        elif self._subgroups:
            self._out(' ' + em + 'GROUP' + em)

        # Place all flags into a dict. Flags that are in a mutually
        # exclusive group are mapped group_id -> [flags]. All other flags
        # are mapped dest -> [flag].
        global_flags = False
        groups = collections.defaultdict(list)
        for flag in (self._command.ai.flag_args +
                     self._command.ai.ancestor_flag_args):
            if flag.is_global and not self._is_top_element:
                global_flags = True
            else:
                group_id = self._command.ai.mutex_groups.get(
                    flag.dest, flag.dest)
                groups[group_id].append(flag)

        # Partition the non-GLOBAL flag groups dict into categorized sections. A
        # group is REQUIRED if any flag in it is required, categorized if any flag
        # in it is categorized, otherwise its OTHER.  REQUIRED takes precedence
        # over categorized.
        categorized_groups = {}
        for group_id, flags in groups.iteritems():
            for f in flags:
                if f.required:
                    category = 'REQUIRED'
                elif f.category:
                    category = f.category
                else:
                    continue
                if category not in categorized_groups:
                    categorized_groups[category] = {}
                categorized_groups[category][group_id] = flags
                break
        # Delete the categorized groups to get OTHER.
        for v in categorized_groups.values():
            for g in v:
                del groups[g]
        category = 'OTHER'
        if category not in categorized_groups:
            categorized_groups[category] = {}
        for group_id, flags in groups.iteritems():
            categorized_groups[category][group_id] = flags

        # Collect the sections in order: REQUIRED, COMMON, OTHER, and categorized.
        sections = []
        for category in ('REQUIRED', base.COMMONLY_USED_FLAGS, 'OTHER'):
            if category in categorized_groups:
                sections.append(categorized_groups[category])
                del categorized_groups[category]
        for _, v in sorted(categorized_groups.iteritems()):
            sections.append(v)

        # Generate the flag usage string with flags in section order.
        for section in sections:
            for group in sorted(section.values(),
                                key=lambda g: g[0].option_strings):
                if len(group) == 1:
                    arg = group[0]
                    if usage_text.IsSuppressed(arg):
                        continue
                    msg = usage_text.FlagDisplayString(arg, markdown=True)
                    if not msg:
                        continue
                    if arg.required:
                        self._out(' {msg}'.format(msg=msg))
                    else:
                        self._out(' [{msg}]'.format(msg=msg))
                else:
                    # Check if the inverted boolean name should be displayed.
                    inverted = None
                    if len(group) == 2:
                        for arg in group:
                            if getattr(arg, 'show_inverted', False):
                                inverted = arg
                                break
                    if inverted:
                        # The inverted arg replaces the boolean group which only contains
                        # the arg and inverted arg.
                        msg = usage_text.FlagDisplayString(inverted,
                                                           markdown=True)
                    else:
                        group = usage_text.FilterOutSuppressed(group)
                        group.sort(key=lambda f: f.option_strings)
                        msg = ' | '.join(
                            usage_text.FlagDisplayString(arg, markdown=True)
                            for arg in group)
                    if not msg:
                        continue
                    self._out(' [{msg}]'.format(msg=msg))

        if global_flags:
            self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']')

        # positional_args will only be non-empty if we had -- ... or REMAINDER left.
        for arg in usage_text.FilterOutSuppressed(positional_args):
            self._out(usage_text.PositionalDisplayString(arg, markdown=True))

        self._out('\n')
Esempio n. 16
0
 def __init__(self, parsers_by_collection=None, parsers_by_url=None,
              default_param_funcs=None, registered_apis=None):
   self.parsers_by_collection = parsers_by_collection or {}
   self.parsers_by_url = parsers_by_url or {}
   self.default_param_funcs = default_param_funcs or {}
   self.registered_apis = registered_apis or collections.defaultdict(set)
Esempio n. 17
0
  def Modify(self, args, existing):
    """Returns a modified URL map message."""
    replacement = copy.deepcopy(existing)

    if not args.new_hosts and not args.existing_host:
      new_hosts = ['*']
    else:
      new_hosts = args.new_hosts

    # If --new-hosts is given, we check to make sure none of those
    # hosts already exist and once the check succeeds, we create the
    # new host rule.
    if new_hosts:
      new_hosts = set(new_hosts)
      for host_rule in existing.hostRules:
        for host in host_rule.hosts:
          if host in new_hosts:
            raise exceptions.ToolException(
                'Cannot create a new host rule with host [{0}] because the '
                'host is already part of a host rule that references the path '
                'matcher [{1}].'.format(host, host_rule.pathMatcher))

      replacement.hostRules.append(self.messages.HostRule(
          hosts=sorted(new_hosts),
          pathMatcher=args.path_matcher_name))

    # If --existing-host is given, we check to make sure that the
    # corresponding host rule will not render a patch matcher
    # orphan. If the check succeeds, we change the path matcher of the
    # host rule. If the check fails, we remove the path matcher if
    # --delete-orphaned-path-matcher is given otherwise we fail.
    else:
      target_host_rule = None
      for host_rule in existing.hostRules:
        for host in host_rule.hosts:
          if host == args.existing_host:
            target_host_rule = host_rule
            break
        if target_host_rule:
          break

      if not target_host_rule:
        raise exceptions.ToolException(
            'No host rule with host [{0}] exists. Check your spelling or '
            'use [--new-hosts] to create a new host rule.'
            .format(args.existing_host))

      path_matcher_orphaned = True
      for host_rule in replacement.hostRules:
        if host_rule == target_host_rule:
          host_rule.pathMatcher = args.path_matcher_name
          continue

        if host_rule.pathMatcher == target_host_rule.pathMatcher:
          path_matcher_orphaned = False
          break

      if path_matcher_orphaned:
        # A path matcher will be orphaned, so now we determine whether
        # we should delete the path matcher or report an error.
        if args.delete_orphaned_path_matcher:
          replacement.pathMatchers = [
              path_matcher for path_matcher in existing.pathMatchers
              if path_matcher.name != target_host_rule.pathMatcher]
        else:
          raise exceptions.ToolException(
              'This operation will orphan the path matcher [{0}]. To '
              'delete the orphan path matcher, rerun this command with '
              '[--delete-orphaned-path-matcher] or use [gcloud compute '
              'url-maps edit] to modify the URL map by hand.'.format(
                  host_rule.pathMatcher))

    # Creates PathRule objects from --path-rules.
    service_map = collections.defaultdict(set)
    for path, service in args.path_rules.iteritems():
      service_map[service].add(path)
    path_rules = []
    for service, paths in sorted(service_map.iteritems()):
      path_rules.append(self.messages.PathRule(
          paths=sorted(paths),
          service=self.CreateGlobalReference(
              service, resource_type='backendServices').SelfLink()))

    new_path_matcher = self.messages.PathMatcher(
        defaultService=self.CreateGlobalReference(
            args.default_service, resource_type='backendServices').SelfLink(),
        description=args.description,
        name=args.path_matcher_name,
        pathRules=path_rules)

    replacement.pathMatchers.append(new_path_matcher)
    return replacement
Esempio n. 18
0
 def Clear(self):
   self.parsers_by_collection = {}
   self.parsers_by_url = {}
   self.default_param_funcs = {}
   self.registered_apis = collections.defaultdict(list)
    def _PrintSynopsisSection(self):
        """Prints the command line synopsis section."""
        # MARKDOWN_CODE is the default SYNOPSIS font style.
        code = usage_text.MARKDOWN_CODE
        em = usage_text.MARKDOWN_ITALIC
        self._Section('SYNOPSIS')
        self._out('{code}{command}{code}'.format(code=code,
                                                 command=self._command_name))

        # Output the positional args up to the first REMAINDER or '-- *' args. The
        # rest will be picked up after the flag args are output. argparse does not
        # have an explicit '--' arg intercept, so we use the metavar value as a '--'
        # sentinel.
        # Any SUPPRESSed args are ingnored by a pre-pass.
        positional_args = FilterOutSuppressed(
            self._command.ai.positional_args[:])
        while positional_args:
            arg = positional_args[0]
            if arg.nargs == argparse.REMAINDER or arg.metavar.startswith(
                    '-- '):
                break
            positional_args.pop(0)
            self._out(usage_text.PositionalDisplayString(arg, markdown=True))

        if self._subcommands and self._subgroups:
            self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em)
        elif self._subcommands:
            self._out(' ' + em + 'COMMAND' + em)
        elif self._subgroups:
            self._out(' ' + em + 'GROUP' + em)

        # Place all flags into a dict. Flags that are in a mutually
        # exclusive group are mapped group_id -> [flags]. All other flags
        # are mapped dest -> [flag].
        global_flags = False
        groups = collections.defaultdict(list)
        for flag in (self._command.ai.flag_args +
                     self._command.ai.ancestor_flag_args):
            if flag.is_global and not self._is_top_element:
                global_flags = True
            else:
                group_id = self._command.ai.mutex_groups.get(
                    flag.dest, flag.dest)
                groups[group_id].append(flag)

        # Split the groups dict into required, common, and then the rest of the
        # flags.  A group is required if any flag in it is required and common if
        # any flag in it is common.  Required takes precedence over common.
        required_groups = {}
        common_groups = {}
        for group_id, flags in groups.iteritems():
            for f in flags:
                if f.required:
                    required_groups[group_id] = flags
                    break
                elif f.is_common:
                    common_groups[group_id] = flags
                    break
        for g in required_groups:
            del groups[g]
        for g in common_groups:
            del groups[g]

        # Generate the flag usage string with required flags first, then common
        # flags, then the rest of the flags.
        for section in [required_groups, common_groups, groups]:
            for group in sorted(section.values(),
                                key=lambda g: g[0].option_strings):
                if len(group) == 1:
                    arg = group[0]
                    if self._IsSuppressed(arg):
                        continue
                    msg = usage_text.FlagDisplayString(arg, markdown=True)
                    if not msg:
                        continue
                    if arg.required:
                        self._out(' {msg}'.format(msg=msg))
                    else:
                        self._out(' [{msg}]'.format(msg=msg))
                else:
                    group.sort(key=lambda f: f.option_strings)
                    group = [
                        flag for flag in group if not self._IsSuppressed(flag)
                    ]
                    msg = ' | '.join(
                        usage_text.FlagDisplayString(arg, markdown=True)
                        for arg in group)
                    if not msg:
                        continue
                    self._out(' [{msg}]'.format(msg=msg))

        if global_flags:
            self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']')

        # positional_args will only be non-empty if we had -- ... or REMAINDER left.
        for arg in FilterOutSuppressed(positional_args):
            self._out(usage_text.PositionalDisplayString(arg, markdown=True))