예제 #1
0
def RunDeployCloudTasks(args):
    """Perform a deployment using Cloud Tasks API based on the given args.

  Args:
    args: argparse.Namespace, An object that contains the values for the
        arguments specified in the ArgsDeploy() function.

  Returns:
    A list of config file identifiers, see yaml_parsing.ConfigYamlInfo.
  """
    paths = [os.path.abspath(x) for x in args.deployables]
    configs = []
    for path in paths:
        if not os.path.exists(path):
            raise exceptions.FileNotFoundError(path)
        config = yaml_parsing.ConfigYamlInfo.FromFile(path)
        if config:
            configs.append(config)
    if configs:
        # TODO(b/169069379): Confirm the same metric name can be used twice in the
        # same run.
        metrics.CustomTimedEvent(metric_names.UPDATE_CONFIG_START)
        # TODO(b/169069379): Upgrade to use GA once the relevant code is promoted
        tasks_api = tasks.GetApiAdapter(base.ReleaseTrack.BETA)
        queues_data = app_deploy_migration_util.FetchCurrrentQueuesData(
            tasks_api)
        for config in configs:
            app_deploy_migration_util.ValidateYamlFileConfig(config)
            app_deploy_migration_util.DeployQueuesYamlFile(
                tasks_api, config, queues_data)
        metrics.CustomTimedEvent(metric_names.UPDATE_CONFIG)
    return [c.name for c in configs]
예제 #2
0
def GetDeployables(args, stager, path_matchers):
    """Given a list of args, infer the deployable services and configs.

  Given a deploy command, e.g. `gcloud app deploy ./dir other/service.yaml
  cron.yaml WEB-INF/appengine-web.xml`, the deployables can be on multiple
  forms. This method pre-processes and infers yaml descriptors from the
  various formats accepted. The rules are as following:

  This function is a context manager, and should be used in conjunction with
  the `with` keyword.

  1. If `args` is an empty list, add the current directory to it.
  2. For each arg:
    - If arg refers to a config file, add it to the configs set.
    - Else match the arg against the path matchers. The first match will win.
      The match will be added to the services set. Matchers may run staging.

  Args:
    args: List[str], positional args as given on the command-line.
    stager: staging.Stager, stager that will be invoked on sources that have
        entries in the stager's registry.
    path_matchers: List[Function], list of functions on the form
        fn(path, stager) ordered by descending precedence, where fn returns
        a Service or None if no match.

  Raises:
    FileNotFoundError: One or more argument does not point to an existing file
        or directory.
    UnknownSourceError: Could not infer a config or service from an arg.
    DuplicateConfigError: Two or more config files have the same type.
    DuplicateServiceError: Two or more services have the same service id.

  Returns:
    Tuple[List[Service], List[ConfigYamlInfo]], lists of deployable services
    and configs.
  """
    if not args:
        args = ['.']
    paths = [os.path.abspath(arg) for arg in args]
    configs = Configs()
    services = Services()
    for path in paths:
        if not os.path.exists(path):
            raise exceptions.FileNotFoundError(path)
        config = yaml_parsing.ConfigYamlInfo.FromFile(path)
        if config:
            configs.Add(config)
            continue
        service = Service.FromPath(path, stager, path_matchers)
        if service:
            services.Add(service)
            continue
        raise exceptions.UnknownSourceError(path)
    return services.GetAll(), configs.GetAll()
예제 #3
0
def _GetDeployableConfigsFromArgs(args):
  """Get parsed YAML configs for any deployables specified in args.

  Args:
    args: argparse.Namespace, An object that contains the values for the
        arguments specified in the ArgsDeploy() function.

  Returns:
    A list of yaml_parsing.ConfigYamlInfos object for the parsed YAML file(s)
    we are going to process.

  Raises:
    FileNotFoundError: If the path specified for a deployable does not exist.
  """
  paths = [os.path.abspath(x) for x in args.deployables]
  configs = []
  for path in paths:
    if not os.path.exists(path):
      raise exceptions.FileNotFoundError(path)
    config = yaml_parsing.ConfigYamlInfo.FromFile(path)
    if config:
      configs.append(config)
  return configs
예제 #4
0
def GetSourceFiles(upload_dir,
                   skip_files_regex,
                   has_explicit_skip_files,
                   runtime,
                   environment,
                   source_dir,
                   ignore_file=None):
    """Returns an iterator for accessing all source files to be uploaded.

  This method uses several implementations based on the provided runtime and
  env. The rules are as follows, in decreasing priority:
  1) For some runtimes/envs (i.e. those defined in _GCLOUDIGNORE_REGISTRY), we
     completely ignore skip_files and generate a runtime-specific .gcloudignore
     if one is not present, or use the existing .gcloudignore.
  2) For all other runtimes/envs, we:
    2a) If ignore_file is not none, use custom ignore_file to skip files. If the
        specified file does not exist, raise error. We also raise an error if
        the user has both ignore file and explicit skip_files defined.
    2b) If user does not specify ignore_file, check for an existing
        .gcloudignore and use that if one exists. We also raise an error if
        the user has both a .gcloudignore file and explicit skip_files defined.
    2c) If there is no .gcloudignore, we use the provided skip_files.

  Args:
    upload_dir: str, path to upload directory, the files to be uploaded.
    skip_files_regex: str, skip_files to use if necessary - see above rules for
      when this could happen. This can be either the user's explicit skip_files
      as defined in their app.yaml or the default skip_files we implicitly
      provide if they didn't define any.
    has_explicit_skip_files: bool, indicating whether skip_files_regex was
      explicitly defined by the user
    runtime: str, runtime as defined in app.yaml
    environment: env.Environment enum
    source_dir: str, path to original source directory, for writing generated
      files. May be the same as upload_dir.
    ignore_file: custom ignore_file name.
              Override .gcloudignore file to customize files to be skipped.

  Raises:
    SkipFilesError: if you are using a runtime that no longer supports
      skip_files (such as those defined in _GCLOUDIGNORE_REGISTRY), or if using
      a runtime that still supports skip_files, but both skip_files and
      a. gcloudignore file are present.
    FileNotFoundError: if the custom ignore-file does not exist.

  Returns:
    A list of path names of source files to be uploaded.
  """
    gcloudignore_registry = _GetGcloudignoreRegistry()
    registry_entry = gcloudignore_registry.Get(runtime, environment)

    if registry_entry:
        if has_explicit_skip_files:
            raise SkipFilesError(
                'skip_files cannot be used with the [{}] runtime. '
                'Ignore patterns are instead expressed in '
                'a .gcloudignore file. For information on the format and '
                'syntax of .gcloudignore files, see '
                'https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore.'
                .format(runtime))
        file_chooser = gcloudignore.GetFileChooserForDir(
            source_dir,
            default_ignore_file=registry_entry,
            write_on_disk=True,
            gcloud_ignore_creation_predicate=lambda unused_dir: True,
            include_gitignore=False)
        it = file_chooser.GetIncludedFiles(upload_dir, include_dirs=False)
    elif ignore_file:
        if os.path.exists(os.path.join(source_dir, ignore_file)):
            if has_explicit_skip_files:
                raise SkipFilesError(
                    'Cannot have both an ignore file {0} and skip_files defined in '
                    'the same application. We recommend you translate your skip_files '
                    'ignore patterns to your {0} file. '.format(ignore_file))
            it = gcloudignore.GetFileChooserForDir(source_dir, ignore_file=ignore_file)\
                .GetIncludedFiles(upload_dir, include_dirs=False)
        else:
            raise exceptions.FileNotFoundError(
                'File {0} referenced by --ignore-file '
                'does not exist.'.format(ignore_file))
    elif os.path.exists(os.path.join(source_dir,
                                     gcloudignore.IGNORE_FILE_NAME)):
        if has_explicit_skip_files:
            raise SkipFilesError(
                'Cannot have both a .gcloudignore file and skip_files defined in '
                'the same application. We recommend you translate your skip_files '
                'ignore patterns to your .gcloudignore file. See '
                'https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore '
                'for more information about gcloudignore.')
        it = gcloudignore.GetFileChooserForDir(source_dir).GetIncludedFiles(
            upload_dir, include_dirs=False)
    else:
        it = util.FileIterator(upload_dir, skip_files_regex)
    return list(it)