示例#1
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.
    """

        client = cloudbuild_util.GetClientInstance()
        messages = cloudbuild_util.GetMessagesModule()
        registry = self.context['registry']

        build_ref = registry.Parse(
            args.build,
            params={
                'projectId': properties.VALUES.core.project.GetOrFail,
            },
            collection='cloudbuild.projects.builds')

        logger = cb_logs.CloudBuildClient(client, messages)
        if args.stream:
            logger.Stream(build_ref)
            return

        # Just print out what's available now.
        logger.PrintLog(build_ref)
示例#2
0
def Build(messages,
          async_,
          build_config,
          hide_logs=False,
          build_region=cloudbuild_util.DEFAULT_REGION):
    """Starts the build."""
    log.debug('submitting build: ' + repr(build_config))
    client = cloudbuild_util.GetClientInstance()

    parent_resource = resources.REGISTRY.Create(
        collection='cloudbuild.projects.locations',
        projectsId=properties.VALUES.core.project.GetOrFail(),
        locationsId=build_region)

    op = client.projects_locations_builds.Create(
        messages.CloudbuildProjectsLocationsBuildsCreateRequest(
            parent=parent_resource.RelativeName(), build=build_config))

    json = encoding.MessageToJson(op.metadata)
    build = encoding.JsonToMessage(messages.BuildOperationMetadata, json).build

    # Need to set the default version to 'v1'
    build_ref = resources.REGISTRY.Parse(
        None,
        collection='cloudbuild.projects.locations.builds',
        api_version='v1',
        params={
            'projectsId': build.projectId,
            'locationsId': build_region,
            'buildsId': build.id,
        })

    if not hide_logs:
        log.CreatedResource(build_ref)
        if build.logUrl:
            log.status.Print('Logs are available at [{log_url}].'.format(
                log_url=build.logUrl))
        else:
            log.status.Print('Logs are available in the Cloud Console.')

    # If the command is run --async, we just print out a reference to the build.
    if async_:
        return build, op

    mash_handler = execution.MashHandler(
        execution.GetCancelBuildHandler(client, messages, build_ref))

    # Otherwise, logs are streamed from GCS.
    with execution_utils.CtrlCSection(mash_handler):
        build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

    if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
        log.status.Print(
            'Your build timed out. Use the [--timeout=DURATION] flag to change '
            'the timeout threshold.')

    if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
        raise FailedBuildException(build)

    return build, op
 def Run(self, args):
     """This is what gets called when the user runs this command."""
     region_ref = args.CONCEPTS.region.Parse()
     region = region_ref.AsDict()['locationsId']
     project = properties.VALUES.core.project.Get(required=True)
     run_id = args.RUN_ID
     if args.type == 'build':
         client = v1_client_util.GetClientInstance()
         messages = v1_client_util.GetMessagesModule()
         build_ref = resources.REGISTRY.Parse(
             run_id,
             params={
                 'projectsId': project,
                 'locationsId': region,
                 'buildsId': run_id,
             },
             collection='cloudbuild.projects.locations.builds')
         logger = v1_logs.CloudBuildClient(client, messages, True)
         if args.stream:
             logger.Stream(build_ref)
             return
         logger.PrintLog(build_ref)
         return
     else:
         logger = v2_logs.CloudBuildLogClient()
         if args.stream:
             logger.Stream(project, region, run_id, args.type)
             return
         logger.PrintLog(project, region, run_id, args.type)
         return
示例#4
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.
    """
        build_region = args.region or cloudbuild_util.DEFAULT_REGION

        client = cloudbuild_util.GetClientInstance()
        messages = cloudbuild_util.GetMessagesModule()

        build_ref = resources.REGISTRY.Parse(
            args.build,
            params={
                'projectsId': properties.VALUES.core.project.GetOrFail,
                'locationsId': build_region,
            },
            collection='cloudbuild.projects.locations.builds')

        logger = cb_logs.CloudBuildClient(client, messages, self._support_gcl)
        if args.stream:
            if not self._support_gcl:
                log.status.Print(
                    '\ngcloud builds log --stream only displays logs from Cloud'
                    ' Storage. To view logs from Cloud Logging, run:\ngcloud beta'
                    ' builds log --stream\n')
            logger.Stream(build_ref)
            return

        # Just print out what's available now.
        logger.PrintLog(build_ref)
示例#5
0
def _RunBuild(name, arch, function_type, source):
    """Builds the Edge function image with Cloud Build.

  Args:
    name: str, name of the Edge Function
    arch: str, target architecture,
      should be one of 'x86-64', 'armhf', 'aarch64'
    function_type: str, type of function,
      should be one of 'on-demand', 'stream-processing'
    source: str, GCS URI to source archive object or
      local path to source directory

  Returns:
    Finished cloudbuild.Build message. build.results.images contains
      built image's name and digest

  Raises:
    FailedBuildException: If the build is completed and not 'SUCCESS'
    FunctionBuilderError: For invalid arguments
  """
    client = cloudbuild_util.GetClientInstance()
    messages = cloudbuild_util.GetMessagesModule()

    build_config = _EdgeFunctionBuildMessage(name, arch, function_type, source)

    log.debug('submitting build: ' + repr(build_config))

    # Start the build.
    op = client.projects_builds.Create(
        messages.CloudbuildProjectsBuildsCreateRequest(
            build=build_config,
            projectId=properties.VALUES.core.project.Get()))
    json = encoding.MessageToJson(op.metadata)
    build = encoding.JsonToMessage(messages.BuildOperationMetadata, json).build

    build_ref = resources.REGISTRY.Create(
        collection='cloudbuild.projects.builds',
        projectId=build.projectId,
        id=build.id)

    log.CreatedResource(build_ref)

    mash_handler = execution.MashHandler(
        execution.GetCancelBuildHandler(client, messages, build_ref))

    # Stream logs from GCS.
    with execution_utils.CtrlCSection(mash_handler):
        build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

    if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
        raise FailedBuildException(build)

    return build
示例#6
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.
    """

        client = core_apis.GetClientInstance('cloudbuild', 'v1')
        messages = core_apis.GetMessagesModule('cloudbuild', 'v1')
        registry = self.context['registry']

        build_ref = registry.Parse(args.build,
                                   collection='cloudbuild.projects.builds')

        cb_logs.CloudBuildClient(client, messages).Stream(build_ref)
示例#7
0
def Build(messages, async_, build_config):
    """Starts the build."""
    log.debug('submitting build: ' + repr(build_config))
    client = cloudbuild_util.GetClientInstance()
    op = client.projects_builds.Create(
        messages.CloudbuildProjectsBuildsCreateRequest(
            build=build_config,
            projectId=properties.VALUES.core.project.Get()))
    json = encoding.MessageToJson(op.metadata)
    build = encoding.JsonToMessage(messages.BuildOperationMetadata, json).build

    build_ref = resources.REGISTRY.Create(
        collection='cloudbuild.projects.builds',
        projectId=build.projectId,
        id=build.id)

    log.CreatedResource(build_ref)
    if build.logUrl:
        log.status.Print(
            'Logs are available at [{log_url}].'.format(log_url=build.logUrl))
    else:
        log.status.Print('Logs are available in the Cloud Console.')

    # If the command is run --async, we just print out a reference to the build.
    if async_:
        return build

    mash_handler = execution.MashHandler(
        execution.GetCancelBuildHandler(client, messages, build_ref))

    # Otherwise, logs are streamed from GCS.
    with execution_utils.CtrlCSection(mash_handler):
        build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

    if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
        log.status.Print(
            'Your build timed out. Use the [--timeout=DURATION] flag to change '
            'the timeout threshold.')

    if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
        raise FailedBuildException(build)

    return build
示例#8
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.
    """

        client = cloudbuild_util.GetClientInstance()
        messages = cloudbuild_util.GetMessagesModule()

        build_ref = resources.REGISTRY.Parse(
            args.build,
            params={'projectId': properties.VALUES.core.project.GetOrFail},
            collection='cloudbuild.projects.builds')

        cb_logs.CloudBuildClient(client, messages).Stream(build_ref)
示例#9
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      FailedBuildException: If the build is completed and not 'SUCCESS'.
    """

        if args.gcs_source_staging_dir is None:
            args.gcs_source_staging_dir = 'gs://{project}_cloudbuild/source'.format(
                project=properties.VALUES.core.project.Get(), )
        if args.gcs_log_dir is None:
            args.gcs_log_dir = 'gs://{project}_cloudbuild/logs'.format(
                project=properties.VALUES.core.project.Get(), )

        client = core_apis.GetClientInstance('cloudbuild', 'v1')
        messages = core_apis.GetMessagesModule('cloudbuild', 'v1')
        registry = self.context['registry']

        gcs_client = storage_api.StorageClient()

        # First, create the build request.
        build_timeout = properties.VALUES.container.build_timeout.Get()
        if build_timeout is not None:
            timeout_str = build_timeout + 's'
        else:
            timeout_str = None

        if args.tag:
            if 'gcr.io/' not in args.tag:
                raise c_exceptions.InvalidArgumentException(
                    '--tag',
                    'Tag value must be in the gcr.io/* or *.gcr.io/* namespace.'
                )
            build_config = messages.Build(
                images=[args.tag],
                steps=[
                    messages.BuildStep(
                        name='gcr.io/cloud-builders/docker',
                        args=['build', '--no-cache', '-t', args.tag, '.'],
                    ),
                ],
                timeout=timeout_str,
            )
        elif args.config:
            build_config = config.LoadCloudbuildConfig(args.config, messages)

        if build_config.timeout is None:
            build_config.timeout = timeout_str

        suffix = '.tgz'
        if args.source.startswith('gs://') or os.path.isfile(args.source):
            _, suffix = os.path.splitext(args.source)

        # Next, stage the source to Cloud Storage.
        staged_object = '{stamp}_{tag_ish}{suffix}'.format(
            stamp=times.GetTimeStampFromDateTime(times.Now()),
            tag_ish='_'.join(build_config.images or 'null').replace('/', '_'),
            suffix=suffix,
        )
        gcs_source_staging_dir = registry.Parse(args.gcs_source_staging_dir,
                                                collection='storage.objects')
        gcs_client.CreateBucketIfNotExists(gcs_source_staging_dir.bucket)
        if gcs_source_staging_dir.object:
            staged_object = gcs_source_staging_dir.object + '/' + staged_object

        gcs_source_staging = registry.Create(
            collection='storage.objects',
            bucket=gcs_source_staging_dir.bucket,
            object=staged_object)

        if args.source.startswith('gs://'):
            gcs_source = registry.Parse(args.source,
                                        collection='storage.objects')
            staged_source_obj = gcs_client.Copy(gcs_source, gcs_source_staging)
            build_config.source = messages.Source(
                storageSource=messages.StorageSource(
                    bucket=staged_source_obj.bucket,
                    object=staged_source_obj.name,
                    generation=staged_source_obj.generation,
                ))
        else:
            if not os.path.exists(args.source):
                raise c_exceptions.BadFileException(
                    'could not find source [{src}]'.format(src=args.source))
            if os.path.isdir(args.source):
                source_snapshot = snapshot.Snapshot(args.source)
                size_str = resource_transform.TransformSize(
                    source_snapshot.uncompressed_size)
                log.status.write(
                    'Creating temporary tarball archive of {num_files} file(s)'
                    ' totalling {size} before compression.\n'.format(
                        num_files=len(source_snapshot.files), size=size_str))
                staged_source_obj = source_snapshot.CopyTarballToGCS(
                    gcs_client, gcs_source_staging)
                build_config.source = messages.Source(
                    storageSource=messages.StorageSource(
                        bucket=staged_source_obj.bucket,
                        object=staged_source_obj.name,
                        generation=staged_source_obj.generation,
                    ))
            elif os.path.isfile(args.source):
                unused_root, ext = os.path.splitext(args.source)
                if ext not in _ALLOWED_SOURCE_EXT:
                    raise c_exceptions.BadFileException(
                        'Local file [{src}] is none of ' +
                        ', '.join(_ALLOWED_SOURCE_EXT))
                log.status.write('Uploading local file [{src}] to '
                                 '[gs://{bucket}/{object}]\n'.format(
                                     src=args.source,
                                     bucket=gcs_source_staging.bucket,
                                     object=gcs_source_staging.object,
                                 ))
                staged_source_obj = gcs_client.CopyFileToGCS(
                    storage_util.BucketReference.FromBucketUrl(
                        gcs_source_staging.bucket), args.source,
                    gcs_source_staging.object)
                build_config.source = messages.Source(
                    storageSource=messages.StorageSource(
                        bucket=staged_source_obj.bucket,
                        object=staged_source_obj.name,
                        generation=staged_source_obj.generation,
                    ))

        gcs_log_dir = registry.Parse(args.gcs_log_dir,
                                     collection='storage.objects')

        if gcs_log_dir.bucket != gcs_source_staging.bucket:
            # Create the logs bucket if it does not yet exist.
            gcs_client.CreateBucketIfNotExists(gcs_log_dir.bucket)
        build_config.logsBucket = 'gs://' + gcs_log_dir.bucket + '/' + gcs_log_dir.object

        log.debug('submitting build: ' + repr(build_config))

        # Start the build.
        op = client.projects_builds.Create(
            messages.CloudbuildProjectsBuildsCreateRequest(
                build=build_config,
                projectId=properties.VALUES.core.project.Get()))
        json = encoding.MessageToJson(op.metadata)
        build = encoding.JsonToMessage(messages.BuildOperationMetadata,
                                       json).build

        build_ref = registry.Create(collection='cloudbuild.projects.builds',
                                    projectId=build.projectId,
                                    id=build.id)

        log.CreatedResource(build_ref)
        if build.logUrl:
            log.status.write(
                'Logs are permanently available at [{log_url}]\n'.format(
                    log_url=build.logUrl))
        else:
            log.status.write('Logs are available in the Cloud Console.\n')

        # If the command is run --async, we just print out a reference to the build.
        if args. async:
            return build

        # Otherwise, logs are streamed from GCS.
        build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

        if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
            raise FailedBuildException(build.status)

        return build
示例#10
0
  def Run(self, args):
    """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      FailedBuildException: If the build is completed and not 'SUCCESS'.
    """

    project = properties.VALUES.core.project.Get(required=True)
    safe_project = project.replace(':', '_')
    safe_project = safe_project.replace('.', '_')
    # The string 'google' is not allowed in bucket names.
    safe_project = safe_project.replace('google', 'elgoog')

    default_bucket_name = '{}_cloudbuild'.format(safe_project)

    default_gcs_source = False
    if args.gcs_source_staging_dir is None:
      default_gcs_source = True
      args.gcs_source_staging_dir = 'gs://{}/source'.format(default_bucket_name)

    client = cloudbuild_util.GetClientInstance()
    messages = cloudbuild_util.GetMessagesModule()

    gcs_client = storage_api.StorageClient()

    # First, create the build request.
    build_timeout = properties.VALUES.builds.timeout.Get()

    if build_timeout is not None:
      try:
        # A bare number is interpreted as seconds.
        build_timeout_secs = int(build_timeout)
      except ValueError:
        build_timeout_duration = times.ParseDuration(build_timeout)
        build_timeout_secs = int(build_timeout_duration.total_seconds)
      timeout_str = six.text_type(build_timeout_secs) + 's'
    else:
      timeout_str = None

    if args.tag is not None:
      if (properties.VALUES.builds.check_tag.GetBool() and
          'gcr.io/' not in args.tag):
        raise c_exceptions.InvalidArgumentException(
            '--tag',
            'Tag value must be in the gcr.io/* or *.gcr.io/* namespace.')
      if properties.VALUES.builds.use_kaniko.GetBool():
        if args.no_cache:
          ttl = '0h'
        else:
          ttl = '{}h'.format(properties.VALUES.builds.kaniko_cache_ttl.Get())
        build_config = messages.Build(
            steps=[
                messages.BuildStep(
                    name=properties.VALUES.builds.kaniko_image.Get(),
                    args=[
                        '--destination', args.tag, '--cache', 'true',
                        '--cache-ttl', ttl
                    ],
                ),
            ],
            timeout=timeout_str,
            substitutions=cloudbuild_util.EncodeSubstitutions(
                args.substitutions, messages))
      else:
        if args.no_cache:
          raise c_exceptions.InvalidArgumentException(
              'no-cache',
              'Cannot specify --no-cache if builds/use_kaniko property is '
              'False')
        build_config = messages.Build(
            images=[args.tag],
            steps=[
                messages.BuildStep(
                    name='gcr.io/cloud-builders/docker',
                    args=[
                        'build', '--network', 'cloudbuild', '--no-cache', '-t',
                        args.tag, '.'
                    ],
                ),
            ],
            timeout=timeout_str,
            substitutions=cloudbuild_util.EncodeSubstitutions(
                args.substitutions, messages))
    elif args.config is not None:
      if args.no_cache:
        raise c_exceptions.ConflictingArgumentsException(
            '--config', '--no-cache')
      if not args.config:
        raise c_exceptions.InvalidArgumentException(
            '--config', 'Config file path must not be empty.')
      build_config = config.LoadCloudbuildConfigFromPath(
          args.config, messages, params=args.substitutions)
    else:
      raise c_exceptions.OneOfArgumentsRequiredException(
          ['--tag', '--config'],
          'Requires either a docker tag or a config file.')

    # If timeout was set by flag, overwrite the config file.
    if timeout_str:
      build_config.timeout = timeout_str

    # --no-source overrides the default --source.
    if not args.IsSpecified('source') and args.no_source:
      args.source = None

    gcs_source_staging = None
    if args.source:
      suffix = '.tgz'
      if args.source.startswith('gs://') or os.path.isfile(args.source):
        _, suffix = os.path.splitext(args.source)

      # Next, stage the source to Cloud Storage.
      staged_object = '{stamp}-{uuid}{suffix}'.format(
          stamp=times.GetTimeStampFromDateTime(times.Now()),
          uuid=uuid.uuid4().hex,
          suffix=suffix,
      )
      gcs_source_staging_dir = resources.REGISTRY.Parse(
          args.gcs_source_staging_dir, collection='storage.objects')

      # We create the bucket (if it does not exist) first. If we do an existence
      # check and then create the bucket ourselves, it would be possible for an
      # attacker to get lucky and beat us to creating the bucket. Block on this
      # creation to avoid this race condition.
      gcs_client.CreateBucketIfNotExists(gcs_source_staging_dir.bucket)

      # If no bucket is specified (for the source `default_gcs_source`), check
      # that the default bucket is also owned by the project (b/33046325).
      if default_gcs_source:
        # This request returns only the buckets owned by the project.
        bucket_list_req = gcs_client.messages.StorageBucketsListRequest(
            project=project, prefix=default_bucket_name)
        bucket_list = gcs_client.client.buckets.List(bucket_list_req)
        found_bucket = False
        for bucket in bucket_list.items:
          if bucket.id == default_bucket_name:
            found_bucket = True
            break
        if not found_bucket:
          if default_gcs_source:
            raise c_exceptions.RequiredArgumentException(
                'gcs_source_staging_dir',
                'A bucket with name {} already exists and is owned by '
                'another project. Specify a bucket using '
                '--gcs_source_staging_dir.'.format(default_bucket_name))

      if gcs_source_staging_dir.object:
        staged_object = gcs_source_staging_dir.object + '/' + staged_object
      gcs_source_staging = resources.REGISTRY.Create(
          collection='storage.objects',
          bucket=gcs_source_staging_dir.bucket,
          object=staged_object)

      if args.source.startswith('gs://'):
        gcs_source = resources.REGISTRY.Parse(
            args.source, collection='storage.objects')
        staged_source_obj = gcs_client.Rewrite(gcs_source, gcs_source_staging)
        build_config.source = messages.Source(
            storageSource=messages.StorageSource(
                bucket=staged_source_obj.bucket,
                object=staged_source_obj.name,
                generation=staged_source_obj.generation,
            ))
      else:
        if not os.path.exists(args.source):
          raise c_exceptions.BadFileException(
              'could not find source [{src}]'.format(src=args.source))
        if os.path.isdir(args.source):
          source_snapshot = snapshot.Snapshot(args.source,
                                              ignore_file=args.ignore_file)
          size_str = resource_transform.TransformSize(
              source_snapshot.uncompressed_size)
          log.status.Print(
              'Creating temporary tarball archive of {num_files} file(s)'
              ' totalling {size} before compression.'.format(
                  num_files=len(source_snapshot.files), size=size_str))
          staged_source_obj = source_snapshot.CopyTarballToGCS(
              gcs_client, gcs_source_staging, ignore_file=args.ignore_file)
          build_config.source = messages.Source(
              storageSource=messages.StorageSource(
                  bucket=staged_source_obj.bucket,
                  object=staged_source_obj.name,
                  generation=staged_source_obj.generation,
              ))
        elif os.path.isfile(args.source):
          unused_root, ext = os.path.splitext(args.source)
          if ext not in _ALLOWED_SOURCE_EXT:
            raise c_exceptions.BadFileException(
                'Local file [{src}] is none of ' +
                ', '.join(_ALLOWED_SOURCE_EXT))
          log.status.Print('Uploading local file [{src}] to '
                           '[gs://{bucket}/{object}].'.format(
                               src=args.source,
                               bucket=gcs_source_staging.bucket,
                               object=gcs_source_staging.object,
                           ))
          staged_source_obj = gcs_client.CopyFileToGCS(args.source,
                                                       gcs_source_staging)
          build_config.source = messages.Source(
              storageSource=messages.StorageSource(
                  bucket=staged_source_obj.bucket,
                  object=staged_source_obj.name,
                  generation=staged_source_obj.generation,
              ))
    else:
      # No source
      if not args.no_source:
        raise c_exceptions.InvalidArgumentException(
            '--no-source', 'To omit source, use the --no-source flag.')

    if args.gcs_log_dir:
      gcs_log_dir = resources.REGISTRY.Parse(
          args.gcs_log_dir, collection='storage.objects')

      build_config.logsBucket = ('gs://' + gcs_log_dir.bucket + '/' +
                                 gcs_log_dir.object)

    # Machine type.
    if args.machine_type is not None:
      machine_type = Submit._machine_type_flag_map.GetEnumForChoice(
          args.machine_type)
      if not build_config.options:
        build_config.options = messages.BuildOptions()
      build_config.options.machineType = machine_type

    # Disk size.
    if args.disk_size is not None:
      disk_size = compute_utils.BytesToGb(args.disk_size)
      if not build_config.options:
        build_config.options = messages.BuildOptions()
      build_config.options.diskSizeGb = int(disk_size)

    log.debug('submitting build: ' + repr(build_config))

    # Start the build.
    op = client.projects_builds.Create(
        messages.CloudbuildProjectsBuildsCreateRequest(
            build=build_config, projectId=properties.VALUES.core.project.Get()))
    json = encoding.MessageToJson(op.metadata)
    build = encoding.JsonToMessage(messages.BuildOperationMetadata, json).build

    build_ref = resources.REGISTRY.Create(
        collection='cloudbuild.projects.builds',
        projectId=build.projectId,
        id=build.id)

    log.CreatedResource(build_ref)
    if build.logUrl:
      log.status.Print(
          'Logs are available at [{log_url}].'.format(log_url=build.logUrl))
    else:
      log.status.Print('Logs are available in the Cloud Console.')

    # If the command is run --async, we just print out a reference to the build.
    if args.async:
      return build

    mash_handler = execution.MashHandler(
        execution.GetCancelBuildHandler(client, messages, build_ref))

    # Otherwise, logs are streamed from GCS.
    with execution_utils.CtrlCSection(mash_handler):
      build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

    if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
      log.status.Print(
          'Your build timed out. Use the [--timeout=DURATION] flag to change '
          'the timeout threshold.')

    if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
      raise FailedBuildException(build)

    return build
示例#11
0
def RunDaisyBuild(args, workflow, variables, daisy_bucket=None, tags=None,
                  user_zone=None):
  """Run a build with Daisy on Google Cloud Builder.

  Args:
    args: an argparse namespace. All the arguments that were provided to this
      command invocation.
    workflow: The path to the Daisy workflow to run.
    variables: A string of key-value pairs to pass to Daisy.
    daisy_bucket: A string containing the name of the GCS bucket that daisy
      should use.
    tags: A list of strings for adding tags to the Argo build.
    user_zone: The GCP zone to tell Daisy to do work in. If unspecified,
      defaults to wherever the Argo runner happens to be.

  Returns:
    A build object that either streams the output or is displayed as a
    link to the build.

  Raises:
    FailedBuildException: If the build is completed and not 'SUCCESS'.
  """
  client = cloudbuild_util.GetClientInstance()
  messages = cloudbuild_util.GetMessagesModule()
  project_id = projects_util.ParseProject(
      properties.VALUES.core.project.GetOrFail())

  CheckIamPermissions(project_id)

  timeout_str = '{0}s'.format(args.timeout)

  daisy_bucket = daisy_bucket or GetAndCreateDaisyBucket()

  daisy_args = ['-gcs_path=gs://{0}/'.format(daisy_bucket),
                '-default_timeout={0}'.format(timeout_str),
                '-variables={0}'.format(variables),
                workflow,
               ]
  if user_zone is not None:
    daisy_args = ['-zone={0}'.format(user_zone)] + daisy_args

  build_tags = ['gce-daisy']
  if tags:
    build_tags.extend(tags)

  # First, create the build request.
  build_config = messages.Build(
      steps=[
          messages.BuildStep(
              name=_BUILDER,
              args=daisy_args,
          ),
      ],
      tags=build_tags,
      timeout=timeout_str,
  )
  if args.log_location:
    gcs_log_dir = resources.REGISTRY.Parse(
        args.log_location, collection='storage.objects')

    build_config.logsBucket = (
        'gs://{0}/{1}'.format(gcs_log_dir.bucket, gcs_log_dir.object))

  # Start the build.
  build, build_ref = _CreateCloudBuild(build_config, client, messages)

  # If the command is run --async, we just print out a reference to the build.
  if args.async:
    return build

  mash_handler = execution.MashHandler(
      execution.GetCancelBuildHandler(client, messages, build_ref))

  # Otherwise, logs are streamed from GCS.
  with execution_utils.CtrlCSection(mash_handler):
    build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

  if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
    log.status.Print(
        'Your build timed out. Use the [--timeout=DURATION] flag to change '
        'the timeout threshold.')

  if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
    raise FailedBuildException(build)

  return build
示例#12
0
  def Run(self, args):
    """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      FailedBuildException: If the build is completed and not 'SUCCESS'.
    """

    project = properties.VALUES.core.project.Get()
    safe_project = project.replace(':', '_')
    safe_project = safe_project.replace('.', '_')
    # The string 'google' is not allowed in bucket names.
    safe_project = safe_project.replace('google', 'elgoog')

    default_bucket_name = '{}_cloudbuild'.format(safe_project)

    default_gcs_source = False
    if args.gcs_source_staging_dir is None:
      default_gcs_source = True
      args.gcs_source_staging_dir = 'gs://{}/source'.format(default_bucket_name)

    default_gcs_log_dir = False
    if args.gcs_log_dir is None:
      default_gcs_log_dir = True
      args.gcs_log_dir = 'gs://{}/logs'.format(default_bucket_name)

    client = cloudbuild_util.GetClientInstance()
    messages = cloudbuild_util.GetMessagesModule()

    gcs_client = storage_api.StorageClient()

    # First, create the build request.
    build_timeout = properties.VALUES.container.build_timeout.Get()

    if build_timeout is not None:
      try:
        # A bare number is interpreted as seconds.
        build_timeout_secs = int(build_timeout)
      except ValueError:
        build_timeout_duration = times.ParseDuration(build_timeout)
        build_timeout_secs = int(build_timeout_duration.total_seconds)
      timeout_str = str(build_timeout_secs) + 's'
    else:
      timeout_str = None

    if args.tag:
      if 'gcr.io/' not in args.tag:
        raise c_exceptions.InvalidArgumentException(
            '--tag',
            'Tag value must be in the gcr.io/* or *.gcr.io/* namespace.')
      build_config = messages.Build(
          images=[args.tag],
          steps=[
              messages.BuildStep(
                  name='gcr.io/cloud-builders/docker',
                  args=['build', '--no-cache', '-t', args.tag, '.'],
              ),
          ],
          timeout=timeout_str,
          substitutions=cloudbuild_util.EncodeSubstitutions(args.substitutions,
                                                            messages)
      )
    elif args.config:
      build_config = config.LoadCloudbuildConfigFromPath(
          args.config, messages, params=args.substitutions)

    # If timeout was set by flag, overwrite the config file.
    if timeout_str:
      build_config.timeout = timeout_str

    suffix = '.tgz'
    if args.source.startswith('gs://') or os.path.isfile(args.source):
      _, suffix = os.path.splitext(args.source)

    # Next, stage the source to Cloud Storage.
    staged_object = '{stamp}{suffix}'.format(
        stamp=times.GetTimeStampFromDateTime(times.Now()),
        suffix=suffix,
    )
    gcs_source_staging_dir = resources.REGISTRY.Parse(
        args.gcs_source_staging_dir, collection='storage.objects')

    # We first try to create the bucket, before doing all the checks, in order
    # to avoid a race condition. If we do the check first, an attacker could
    # be lucky enough to create the bucket after the check and before this
    # bucket creation.
    gcs_client.CreateBucketIfNotExists(gcs_source_staging_dir.bucket)

    # If no bucket is specified (for the source `default_gcs_source` or for the
    # logs `default_gcs_log_dir`), check that the default bucket is also owned
    # by the project (b/33046325).
    if default_gcs_source or default_gcs_log_dir:
      # This request returns only the buckets owned by the project.
      bucket_list_req = gcs_client.messages.StorageBucketsListRequest(
          project=project,
          prefix=default_bucket_name)
      bucket_list = gcs_client.client.buckets.List(bucket_list_req)
      found_bucket = False
      for bucket in bucket_list.items:
        if bucket.id == default_bucket_name:
          found_bucket = True
          break
      if not found_bucket:
        if default_gcs_source:
          raise c_exceptions.RequiredArgumentException(
              'gcs_source_staging_dir',
              'A bucket with name {} already exists and is owned by '
              'another project. Specify a bucket using '
              '--gcs_source_staging_dir.'.format(default_bucket_name))
        elif default_gcs_log_dir:
          raise c_exceptions.RequiredArgumentException(
              'gcs-log-dir',
              'A bucket with name {} already exists and is owned by '
              'another project. Specify a bucket to hold build logs '
              'using --gcs-log-dir.'.format(default_bucket_name))

    if gcs_source_staging_dir.object:
      staged_object = gcs_source_staging_dir.object + '/' + staged_object

    gcs_source_staging = resources.REGISTRY.Create(
        collection='storage.objects',
        bucket=gcs_source_staging_dir.bucket,
        object=staged_object)

    if args.source.startswith('gs://'):
      gcs_source = resources.REGISTRY.Parse(
          args.source, collection='storage.objects')
      staged_source_obj = gcs_client.Rewrite(gcs_source, gcs_source_staging)
      build_config.source = messages.Source(
          storageSource=messages.StorageSource(
              bucket=staged_source_obj.bucket,
              object=staged_source_obj.name,
              generation=staged_source_obj.generation,
          ))
    else:
      if not os.path.exists(args.source):
        raise c_exceptions.BadFileException(
            'could not find source [{src}]'.format(src=args.source))
      if os.path.isdir(args.source):
        source_snapshot = snapshot.Snapshot(args.source)
        size_str = resource_transform.TransformSize(
            source_snapshot.uncompressed_size)
        log.status.Print(
            'Creating temporary tarball archive of {num_files} file(s)'
            ' totalling {size} before compression.'.format(
                num_files=len(source_snapshot.files),
                size=size_str))
        staged_source_obj = source_snapshot.CopyTarballToGCS(
            gcs_client, gcs_source_staging)
        build_config.source = messages.Source(
            storageSource=messages.StorageSource(
                bucket=staged_source_obj.bucket,
                object=staged_source_obj.name,
                generation=staged_source_obj.generation,
            ))
      elif os.path.isfile(args.source):
        unused_root, ext = os.path.splitext(args.source)
        if ext not in _ALLOWED_SOURCE_EXT:
          raise c_exceptions.BadFileException(
              'Local file [{src}] is none of '+', '.join(_ALLOWED_SOURCE_EXT))
        log.status.Print(
            'Uploading local file [{src}] to '
            '[gs://{bucket}/{object}].'.format(
                src=args.source,
                bucket=gcs_source_staging.bucket,
                object=gcs_source_staging.object,
            ))
        staged_source_obj = gcs_client.CopyFileToGCS(
            storage_util.BucketReference.FromBucketUrl(
                gcs_source_staging.bucket),
            args.source, gcs_source_staging.object)
        build_config.source = messages.Source(
            storageSource=messages.StorageSource(
                bucket=staged_source_obj.bucket,
                object=staged_source_obj.name,
                generation=staged_source_obj.generation,
            ))

    gcs_log_dir = resources.REGISTRY.Parse(
        args.gcs_log_dir, collection='storage.objects')

    if gcs_log_dir.bucket != gcs_source_staging.bucket:
      # Create the logs bucket if it does not yet exist.
      gcs_client.CreateBucketIfNotExists(gcs_log_dir.bucket)
    build_config.logsBucket = 'gs://'+gcs_log_dir.bucket+'/'+gcs_log_dir.object

    log.debug('submitting build: '+repr(build_config))

    # Start the build.
    op = client.projects_builds.Create(
        messages.CloudbuildProjectsBuildsCreateRequest(
            build=build_config,
            projectId=properties.VALUES.core.project.Get()))
    json = encoding.MessageToJson(op.metadata)
    build = encoding.JsonToMessage(messages.BuildOperationMetadata, json).build

    build_ref = resources.REGISTRY.Create(
        collection='cloudbuild.projects.builds',
        projectId=build.projectId,
        id=build.id)

    log.CreatedResource(build_ref)
    if build.logUrl:
      log.status.Print('Logs are available at [{log_url}].'.format(
          log_url=build.logUrl))
    else:
      log.status.Print('Logs are available in the Cloud Console.')

    # If the command is run --async, we just print out a reference to the build.
    if args.async:
      return build

    mash_handler = execution.MashHandler(
        execution.GetCancelBuildHandler(client, messages, build_ref))

    # Otherwise, logs are streamed from GCS.
    with execution_utils.CtrlCSection(mash_handler):
      build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

    if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
      log.status.Print(
          'Your build timed out. Use the [--timeout=DURATION] flag to change '
          'the timeout threshold.')

    if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
      raise FailedBuildException(build)

    return build
示例#13
0
    def DeployService(self,
                      service_name,
                      version_id,
                      service_config,
                      manifest,
                      build,
                      extra_config_settings=None):
        """Updates and deploys new app versions.

    Args:
      service_name: str, The service to deploy.
      version_id: str, The version of the service to deploy.
      service_config: AppInfoExternal, Service info parsed from a service yaml
        file.
      manifest: Dictionary mapping source files to Google Cloud Storage
        locations.
      build: BuildArtifact, a wrapper which contains either the build
        ID for an in-progress parallel build, the name of the container image
        for a serial build, or the options for creating a build elsewhere. Not
        present during standard deploys.
      extra_config_settings: dict, client config settings to pass to the server
        as beta settings.
    Returns:
      The Admin API Operation, unfinished.
    """
        operation = self._CreateVersion(service_name, version_id,
                                        service_config, manifest, build,
                                        extra_config_settings)

        message = 'Updating service [{service}]'.format(service=service_name)
        if util.Environment.IsFlexible(service_config.env):
            message += ' (this may take several minutes)'

        operation_metadata_type = self._ResolveMetadataType()
        # This indicates that a server-side build should be created.
        if build and build.IsBuildOptions():
            if not operation_metadata_type:
                log.warning(
                    'Unable to determine build from Operation metadata. '
                    'Skipping log streaming')
            else:
                # Poll the operation until the build is present.
                poller = operations_util.AppEngineOperationBuildPoller(
                    self.client.apps_operations, operation_metadata_type)
                operation = operations_util.WaitForOperation(
                    self.client.apps_operations,
                    operation,
                    message=message,
                    poller=poller)
                build_id = operations_util.GetBuildFromOperation(
                    operation, operation_metadata_type)
                if build_id:
                    build = app_cloud_build.BuildArtifact.MakeBuildIdArtifact(
                        build_id)
        if build and build.IsBuildId():
            build_ref = resources.REGISTRY.Parse(
                build.identifier,
                params={'projectId': properties.VALUES.core.project.GetOrFail},
                collection='cloudbuild.projects.builds')
            cloudbuild_logs.CloudBuildClient().Stream(build_ref)

        done_poller = operations_util.AppEngineOperationPoller(
            self.client.apps_operations, operation_metadata_type)
        return operations_util.WaitForOperation(self.client.apps_operations,
                                                operation,
                                                message=message,
                                                poller=done_poller)
示例#14
0
    def _SubmitBuild(self, client, messages, build_config,
                     gcs_config_staging_path, suggest_configs, async_):
        """Submits the build.

    Args:
      client: Client used to make calls to Cloud Build API.
      messages: Cloud Build messages module. This is the value returned from
        cloudbuild_util.GetMessagesModule().
      build_config: Build to submit.
      gcs_config_staging_path: A path to a GCS subdirectory where deployed
        configs will be saved to. This value will be printed to the user.
      suggest_configs: If True, suggest YAML configs for the user to add to
        their repo.
      async_: If true, exit immediately after submitting Build, rather than
        waiting for it to complete or fail.

    Raises:
      FailedDeployException: If the build is completed and not 'SUCCESS'.
    """
        project = properties.VALUES.core.project.Get(required=True)
        op = client.projects_builds.Create(
            messages.CloudbuildProjectsBuildsCreateRequest(build=build_config,
                                                           projectId=project))
        log.debug('submitting build: ' + six.text_type(build_config))

        json = encoding.MessageToJson(op.metadata)
        build = encoding.JsonToMessage(messages.BuildOperationMetadata,
                                       json).build

        build_ref = resources.REGISTRY.Create(
            collection='cloudbuild.projects.builds',
            projectId=build.projectId,
            id=build.id)

        log.status.Print(
            'Starting Cloud Build to build and deploy to the target '
            'Google Kubernetes Engine cluster...\n')

        log.CreatedResource(build_ref)
        if build.logUrl:
            log.status.Print('Logs are available at [{log_url}].'.format(
                log_url=build.logUrl))
        else:
            log.status.Print('Logs are available in the Cloud Console.')

        suggested_configs_path = build_util.SuggestedConfigsPath(
            gcs_config_staging_path, build.id)
        expanded_configs_path = build_util.ExpandedConfigsPath(
            gcs_config_staging_path, build.id)

        if async_:
            log.status.Print(
                '\nIf successful, you can find the configuration files of the deployed '
                'Kubernetes objects stored at gs://{expanded} or by visiting '
                'https://console.cloud.google.com/storage/browser/{expanded}/.'
                .format(expanded=expanded_configs_path))
            if suggest_configs:
                log.status.Print(
                    '\nYou will also be able to find the suggested base Kubernetes '
                    'configuration files at gs://{suggested} or by visiting '
                    'https://console.cloud.google.com/storage/browser/{suggested}/.'
                    .format(suggested=suggested_configs_path))

            # Return here, otherwise, logs are streamed from GCS.
            return

        mash_handler = execution.MashHandler(
            execution.GetCancelBuildHandler(client, messages, build_ref))

        with execution_utils.CtrlCSection(mash_handler):
            build = cb_logs.CloudBuildClient(client,
                                             messages).Stream(build_ref)

        if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
            log.status.Print(
                'Your build and deploy timed out. Use the [--timeout=DURATION] flag '
                'to change the timeout threshold.')

        if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
            if build_util.SaveConfigsBuildStepIsSuccessful(messages, build):
                log.status.Print(
                    'You can find the configuration files for this attempt at gs://{}.'
                    .format(expanded_configs_path))
            raise FailedDeployException(build)

        log.status.Print(
            'Successfully deployed to your Google Kubernetes Engine cluster.\n\n'
            'You can find the configuration files of the deployed Kubernetes '
            'objects stored at gs://{expanded} or by visiting '
            'https://console.cloud.google.com/storage/browser/{expanded}/.'.
            format(expanded=expanded_configs_path))
        if suggest_configs:
            log.status.Print(
                '\nYou can also find suggested base Kubernetes configuration files at '
                'gs://{suggested} or by visiting '
                'https://console.cloud.google.com/storage/browser/{suggested}/.'
                .format(suggested=suggested_configs_path))
示例#15
0
 def SetUp(self):
     self.build_client = cloudbuild_logs.CloudBuildClient(client=object(),
                                                          messages=object())
示例#16
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      FailedDeployException: If the build is completed and not 'SUCCESS'.
    """

        client = cloudbuild_util.GetClientInstance()
        messages = cloudbuild_util.GetMessagesModule()

        build_config = self._CreateBuildFromArgs(args, messages)

        # Start the build
        project = properties.VALUES.core.project.Get(required=True)
        op = client.projects_builds.Create(
            messages.CloudbuildProjectsBuildsCreateRequest(build=build_config,
                                                           projectId=project))
        log.debug('submitting build: ' + repr(build_config))

        json = encoding.MessageToJson(op.metadata)
        build = encoding.JsonToMessage(messages.BuildOperationMetadata,
                                       json).build

        build_ref = resources.REGISTRY.Create(
            collection='cloudbuild.projects.builds',
            projectId=build.projectId,
            id=build.id)

        log.status.Print(
            'Starting Cloud Build to build and deploy to the target '
            'Google Kubernetes Engine cluster...\n')

        log.CreatedResource(build_ref)
        if build.logUrl:
            log.status.Print('Logs are available at [{log_url}].'.format(
                log_url=build.logUrl))
        else:
            log.status.Print('Logs are available in the Cloud Console.')

        if args.async_:
            return

        mash_handler = execution.MashHandler(
            execution.GetCancelBuildHandler(client, messages, build_ref))

        # Otherwise, logs are streamed from GCS.
        with execution_utils.CtrlCSection(mash_handler):
            build = cb_logs.CloudBuildClient(client,
                                             messages).Stream(build_ref)

        if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
            log.status.Print(
                'Your build and deploy timed out. Use the [--timeout=DURATION] flag '
                'to change the timeout threshold.')

        if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
            raise FailedDeployException(build)

        # Get location of suggested config bucket from gsutil build step
        suggested_configs = build.steps[-1].args[-1]

        log.status.Print(
            'Successfully deployed to your Google Kubernetes Engine cluster.\n\n'
            'You can find the configuration files of the deployed Kubernetes '
            'objects stored at {expanded} These configurations are expanded by the '
            'deployer with additional labels like app name and version.\n\n'
            'You can also find suggested base Kubernetes configuration files '
            'created by the deployer at {suggested}'.format(
                expanded=build.artifacts.objects.location,
                suggested=suggested_configs))
        return
示例#17
0
def Build(messages,
          async_,
          build_config,
          hide_logs=False,
          build_region=cloudbuild_util.DEFAULT_REGION,
          support_gcl=False,
          suppress_logs=False):
  """Starts the build."""
  log.debug('submitting build: ' + repr(build_config))
  client = cloudbuild_util.GetClientInstance()

  parent_resource = resources.REGISTRY.Create(
      collection='cloudbuild.projects.locations',
      projectsId=properties.VALUES.core.project.GetOrFail(),
      locationsId=build_region)

  op = client.projects_locations_builds.Create(
      messages.CloudbuildProjectsLocationsBuildsCreateRequest(
          parent=parent_resource.RelativeName(), build=build_config))

  json = encoding.MessageToJson(op.metadata)
  build = encoding.JsonToMessage(messages.BuildOperationMetadata, json).build

  # Need to set the default version to 'v1'
  build_ref = resources.REGISTRY.Parse(
      None,
      collection='cloudbuild.projects.locations.builds',
      api_version='v1',
      params={
          'projectsId': build.projectId,
          'locationsId': build_region,
          'buildsId': build.id,
      })

  if not hide_logs:
    log.CreatedResource(build_ref)
    if build.logUrl:
      log.status.Print(
          'Logs are available at [{log_url}].'.format(log_url=build.logUrl))
    else:
      log.status.Print('Logs are available in the Cloud Console.')

  # If the command is run --async, we just print out a reference to the build.
  if async_:
    return build, op

  if not support_gcl and build.options and build.options.logging in [
      messages.BuildOptions.LoggingValueValuesEnum.STACKDRIVER_ONLY,
      messages.BuildOptions.LoggingValueValuesEnum.CLOUD_LOGGING_ONLY,
  ]:
    log.status.Print('\ngcloud builds submit only displays logs from Cloud'
                     ' Storage. To view logs from Cloud Logging, run:\ngcloud'
                     ' beta builds submit\n')

  mash_handler = execution.MashHandler(
      execution.GetCancelBuildHandler(client, messages, build_ref))

  out = log.out if not suppress_logs else None
  # Otherwise, logs are streamed from the chosen logging service
  # (defaulted to GCS).
  with execution_utils.CtrlCSection(mash_handler):
    build = cb_logs.CloudBuildClient(client, messages,
                                     support_gcl).Stream(build_ref, out)

  if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
    log.status.Print(
        'Your build timed out. Use the [--timeout=DURATION] flag to change '
        'the timeout threshold.')

  if build.warnings:
    for warn in build.warnings:
      log.status.Print('\n{priority}: {text}'.format(
          text=warn.text, priority=warn.priority))

    log.status.Print(
        '\n{count} message(s) issued.'.format(count=len(build.warnings)))

  if build.failureInfo:
    log.status.Print(
        '\nBUILD FAILURE: {detail}'.format(detail=build.failureInfo.detail))

  if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
    raise FailedBuildException(build)

  return build, op
示例#18
0
    def DeployService(self,
                      service_name,
                      version_id,
                      service_config,
                      manifest,
                      build,
                      extra_config_settings=None,
                      service_account_email=None):
        """Updates and deploys new app versions.

    Args:
      service_name: str, The service to deploy.
      version_id: str, The version of the service to deploy.
      service_config: AppInfoExternal, Service info parsed from a service yaml
        file.
      manifest: Dictionary mapping source files to Google Cloud Storage
        locations.
      build: BuildArtifact, a wrapper which contains either the build
        ID for an in-progress parallel build, the name of the container image
        for a serial build, or the options for creating a build elsewhere. Not
        present during standard deploys.
      extra_config_settings: dict, client config settings to pass to the server
        as beta settings.
      service_account_email: Identity of this deployed version. If not set, the
        Admin API will fall back to use the App Engine default appspot service
        account.

    Returns:
      The Admin API Operation, unfinished.

    Raises:
      apitools_exceptions.HttpNotFoundError if build ID doesn't exist
    """
        operation = self._CreateVersion(service_name, version_id,
                                        service_config, manifest, build,
                                        extra_config_settings,
                                        service_account_email)

        message = 'Updating service [{service}]'.format(service=service_name)
        if service_config.env in [env.FLEX, env.MANAGED_VMS]:
            message += ' (this may take several minutes)'

        operation_metadata_type = self._ResolveMetadataType()
        # This indicates that a server-side build should be created.
        if build and build.IsBuildOptions():
            if not operation_metadata_type:
                log.warning(
                    'Unable to determine build from Operation metadata. '
                    'Skipping log streaming')
            else:
                # Poll the operation until the build is present.
                poller = operations_util.AppEngineOperationBuildPoller(
                    self.client.apps_operations, operation_metadata_type)
                operation = operations_util.WaitForOperation(
                    self.client.apps_operations,
                    operation,
                    message=message,
                    poller=poller)
                build_id = operations_util.GetBuildFromOperation(
                    operation, operation_metadata_type)
                if build_id:
                    build = app_cloud_build.BuildArtifact.MakeBuildIdArtifact(
                        build_id)

        if build and build.IsBuildId():
            try:
                build_ref = resources.REGISTRY.Parse(
                    build.identifier,
                    params={
                        'projectId': properties.VALUES.core.project.GetOrFail
                    },
                    collection='cloudbuild.projects.builds')
                cloudbuild_logs.CloudBuildClient().Stream(build_ref,
                                                          out=log.status)
            except apitools_exceptions.HttpNotFoundError:
                region = util.ConvertToCloudRegion(
                    self.GetApplication().locationId)
                build_ref = resources.REGISTRY.Create(
                    collection='cloudbuild.projects.locations.builds',
                    projectsId=properties.VALUES.core.project.GetOrFail,
                    locationsId=region,
                    buildsId=build.identifier)
                cloudbuild_logs.CloudBuildClient().Stream(build_ref,
                                                          out=log.status)

        done_poller = operations_util.AppEngineOperationPoller(
            self.client.apps_operations, operation_metadata_type)
        return operations_util.WaitForOperation(self.client.apps_operations,
                                                operation,
                                                message=message,
                                                poller=done_poller)
示例#19
0
def RunDaisyBuild(args, workflow, variables):
    """Run a build with Daisy on Google Cloud Builder.

  Args:
    args: an argparse namespace. All the arguments that were provided to this
      command invocation.
    workflow: The path to the Daisy workflow to run.
    variables: A string of key-value pairs to pass to Daisy.

  Returns:
    A build object that either streams the output or is displayed as a
    link to the build.

  Raises:
    FailedBuildException: If the build is completed and not 'SUCCESS'.
  """
    client = cloudbuild_util.GetClientInstance()
    messages = cloudbuild_util.GetMessagesModule()
    project_id = projects_util.ParseProject(
        properties.VALUES.core.project.GetOrFail())

    CheckIamPermissions(project_id)

    timeout_str = '{0}s'.format(args.timeout)

    # First, create the build request.
    build_config = messages.Build(
        steps=[
            messages.BuildStep(
                name=_BUILDER,
                args=[
                    '-variables={0}'.format(variables),
                    workflow,
                ],
            ),
        ],
        timeout=timeout_str,
    )
    if args.log_location:
        gcs_log_dir = resources.REGISTRY.Parse(args.log_location,
                                               collection='storage.objects')

        build_config.logsBucket = ('gs://{0}/{1}'.format(
            gcs_log_dir.bucket, gcs_log_dir.object))

    # Start the build.
    build, build_ref = _CreateCloudBuild(build_config, client, messages)

    # If the command is run --async, we just print out a reference to the build.
    if args. async:
        return build

    mash_handler = execution.MashHandler(
        execution.GetCancelBuildHandler(client, messages, build_ref))

    # Otherwise, logs are streamed from GCS.
    with execution_utils.CtrlCSection(mash_handler):
        build = cb_logs.CloudBuildClient(client, messages).Stream(build_ref)

    if build.status == messages.Build.StatusValueValuesEnum.TIMEOUT:
        log.status.Print(
            'Your build timed out. Use the [--timeout=DURATION] flag to change '
            'the timeout threshold.')

    if build.status != messages.Build.StatusValueValuesEnum.SUCCESS:
        raise FailedBuildException(build)

    return build