Activadores de Google Cloud Storage

Cloud Functions usa funciones controladas por eventos para controlar los eventos de tu infraestructura de Cloud. Por ejemplo, Cloud Functions puede responder a las notificaciones de cambios que surgen de Google Cloud Storage. Estas notificaciones se pueden configurar para activarse en respuesta a varios eventos dentro de un bucket, como la creación, la eliminación, el archivado y las actualizaciones de metadatos de objetos.

Tipos de eventos

Los eventos de Cloud Storage que se usan en Cloud Functions se basan en Notificaciones de Cloud Pub/Sub para Google Cloud Storage y se proporcionan en el formato de la API de JSON de Cloud Storage.

Las funciones activadas por Storage admiten cuatro tipos de activadores. Estos valores de tipo activador se usan durante la implementación de la función para especificar qué eventos de Cloud Storage la activarán:

Código de función de muestra

La siguiente función de muestra registra datos relevantes cuando ocurre un evento.

Debes especificar el tipo de activador cuando implementas la función. Por ejemplo, en el siguiente ejemplo de implementación, se usa la función para registrar cada vez que se crea un objeto mediante la especificación del tipo de activador google.storage.object.finalize.

Para ver un instructivo completo sobre cómo ejecutar este código, consulta el instructivo de Cloud Storage:

Node.js

 
/**
 * Generic background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} file The Cloud Storage file metadata.
 * @param {object} context The event metadata.
 */
exports.helloGCS = (file, context) => {
  console.log(`  Event: ${context.eventId}`);
  console.log(`  Event Type: ${context.eventType}`);
  console.log(`  Bucket: ${file.bucket}`);
  console.log(`  File: ${file.name}`);
  console.log(`  Metageneration: ${file.metageneration}`);
  console.log(`  Created: ${file.timeCreated}`);
  console.log(`  Updated: ${file.updated}`);
};

Python

 
def hello_gcs(event, context):
    """Background Cloud Function to be triggered by Cloud Storage.
       This generic function logs relevant data when a file is changed.

    Args:
        event (dict):  The dictionary with data specific to this type of event.
                       The `data` field contains a description of the event in
                       the Cloud Storage `object` format described here:
                       https://cloud.google.com/storage/docs/json_api/v1/objects#resource
        context (google.cloud.functions.Context): Metadata of triggering event.
    Returns:
        None; the output is written to Stackdriver Logging
    """

    print('Event ID: {}'.format(context.event_id))
    print('Event type: {}'.format(context.event_type))
    print('Bucket: {}'.format(event['bucket']))
    print('File: {}'.format(event['name']))
    print('Metageneration: {}'.format(event['metageneration']))
    print('Created: {}'.format(event['timeCreated']))
    print('Updated: {}'.format(event['updated']))

Go

 

// Package helloworld provides a set of Cloud Functions samples.
package helloworld

import (
	"context"
	"fmt"
	"log"
	"time"

	"cloud.google.com/go/functions/metadata"
)

// GCSEvent is the payload of a GCS event.
type GCSEvent struct {
	Kind                    string                 `json:"kind"`
	ID                      string                 `json:"id"`
	SelfLink                string                 `json:"selfLink"`
	Name                    string                 `json:"name"`
	Bucket                  string                 `json:"bucket"`
	Generation              string                 `json:"generation"`
	Metageneration          string                 `json:"metageneration"`
	ContentType             string                 `json:"contentType"`
	TimeCreated             time.Time              `json:"timeCreated"`
	Updated                 time.Time              `json:"updated"`
	TemporaryHold           bool                   `json:"temporaryHold"`
	EventBasedHold          bool                   `json:"eventBasedHold"`
	RetentionExpirationTime time.Time              `json:"retentionExpirationTime"`
	StorageClass            string                 `json:"storageClass"`
	TimeStorageClassUpdated time.Time              `json:"timeStorageClassUpdated"`
	Size                    string                 `json:"size"`
	MD5Hash                 string                 `json:"md5Hash"`
	MediaLink               string                 `json:"mediaLink"`
	ContentEncoding         string                 `json:"contentEncoding"`
	ContentDisposition      string                 `json:"contentDisposition"`
	CacheControl            string                 `json:"cacheControl"`
	Metadata                map[string]interface{} `json:"metadata"`
	CRC32C                  string                 `json:"crc32c"`
	ComponentCount          int                    `json:"componentCount"`
	Etag                    string                 `json:"etag"`
	CustomerEncryption      struct {
		EncryptionAlgorithm string `json:"encryptionAlgorithm"`
		KeySha256           string `json:"keySha256"`
	}
	KMSKeyName    string `json:"kmsKeyName"`
	ResourceState string `json:"resourceState"`
}

// HelloGCS consumes a GCS event.
func HelloGCS(ctx context.Context, e GCSEvent) error {
	meta, err := metadata.FromContext(ctx)
	if err != nil {
		return fmt.Errorf("metadata.FromContext: %v", err)
	}
	log.Printf("Event ID: %v\n", meta.EventID)
	log.Printf("Event type: %v\n", meta.EventType)
	log.Printf("Bucket: %v\n", e.Bucket)
	log.Printf("File: %v\n", e.Name)
	log.Printf("Metageneration: %v\n", e.Metageneration)
	log.Printf("Created: %v\n", e.TimeCreated)
	log.Printf("Updated: %v\n", e.Updated)
	return nil
}

Java

import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import functions.eventpojos.GcsEvent;
import java.util.logging.Logger;

public class HelloGcs implements BackgroundFunction<GcsEvent> {
  private static final Logger logger = Logger.getLogger(HelloGcs.class.getName());

  @Override
  public void accept(GcsEvent event, Context context) {
    logger.info("Event: " + context.eventId());
    logger.info("Event Type: " + context.eventType());
    logger.info("Bucket: " + event.getBucket());
    logger.info("File: " + event.getName());
    logger.info("Metageneration: " + event.getMetageneration());
    logger.info("Created: " + event.getTimeCreated());
    logger.info("Updated: " + event.getUpdated());
  }
}

C#

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.Storage.V1;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;

namespace HelloGcs
{
    public class Function : ICloudEventFunction<StorageObjectData>
    {
        private readonly ILogger _logger;

        public Function(ILogger<Function> logger) =>
            _logger = logger;

        public Task HandleAsync(CloudEvent cloudEvent, StorageObjectData data, CancellationToken cancellationToken)
        {
            _logger.LogInformation("Event: {event}", cloudEvent.Id);
            _logger.LogInformation("Event Type: {type}", cloudEvent.Type);
            _logger.LogInformation("Bucket: {bucket}", data.Bucket);
            _logger.LogInformation("File: {file}", data.Name);
            _logger.LogInformation("Metageneration: {metageneration}", data.Metageneration);
            _logger.LogInformation("Created: {created:s}", data.TimeCreated?.ToDateTimeOffset());
            _logger.LogInformation("Updated: {updated:s}", data.Updated?.ToDateTimeOffset());
            return Task.CompletedTask;
        }
    }
}

Ruby

require "functions_framework"

FunctionsFramework.cloud_event "hello_gcs" do |event|
  # The event parameter is a CloudEvents::Event::V1 object.
  # See https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event/V1.html
  payload = event.data

  logger.info "Event: #{event.id}"
  logger.info "Event Type: #{event.type}"
  logger.info "Bucket: #{payload['bucket']}"
  logger.info "File: #{payload['name']}"
  logger.info "Metageneration: #{payload['metageneration']}"
  logger.info "Created: #{payload['timeCreated']}"
  logger.info "Updated: #{payload['updated']}"
end

PHP


use CloudEvents\V1\CloudEventInterface;
use Google\CloudFunctions\FunctionsFramework;

// Register the function with Functions Framework.
// This enables omitting the `FUNCTIONS_SIGNATURE_TYPE=cloudevent` environment
// variable when deploying. The `FUNCTION_TARGET` environment variable should
// match the first parameter.
FunctionsFramework::cloudEvent('helloGCS', 'helloGCS');

function helloGCS(CloudEventInterface $cloudevent)
{
    $log = fopen(getenv('LOGGER_OUTPUT') ?: 'php://stderr', 'wb');
    $data = $cloudevent->getData();
    fwrite($log, 'Event: ' . $cloudevent->getId() . PHP_EOL);
    fwrite($log, 'Event Type: ' . $cloudevent->getType() . PHP_EOL);
    fwrite($log, 'Bucket: ' . $data['bucket'] . PHP_EOL);
    fwrite($log, 'File: ' . $data['name'] . PHP_EOL);
    fwrite($log, 'Metageneration: ' . $data['metageneration'] . PHP_EOL);
    fwrite($log, 'Created: ' . $data['timeCreated'] . PHP_EOL);
    fwrite($log, 'Updated: ' . $data['updated'] . PHP_EOL);
}

Especifica el tipo de activador en la implementación

El siguiente comando de gcloud implementa la función con un activador object.finalize.

Node.js

gcloud functions deploy helloGCS \
--runtime nodejs16 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
Puedes usar los siguientes valores para que la marca --runtime especifique tu versión preferida de Node.js:
  • nodejs16 (recomendada)
  • nodejs14
  • nodejs12
  • nodejs10

Python

gcloud functions deploy hello_gcs \
--runtime python39 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
Puedes usar los siguientes valores para que la marca --runtime especifique tu versión preferida de Python:
  • python39 (recomendada)
  • python38
  • python37

Go

gcloud functions deploy HelloGCS \
--runtime go116 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
Puedes usar los siguientes valores en la marca --runtime para especificar tu versión preferida de Go:
  • go116 (recomendada)
  • go113
  • go111

Java

gcloud functions deploy java-gcs-function \
--entry-point functions.HelloGcs \
--runtime java11 \
--memory 512MB \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize

C#

gcloud functions deploy csharp-gcs-function \
--entry-point HelloGcs.Function \
--runtime dotnet3 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize

Ruby

gcloud functions deploy hello_gcs --runtime ruby27 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize
Puedes usar los siguientes valores para que con la marca --runtime se especifique tu versión preferida de Ruby:
  • ruby27 (recomendada)
  • ruby26

PHP

gcloud functions deploy helloGCS --runtime php74 \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event google.storage.object.finalize

En el comando anterior, YOUR_TRIGGER_BUCKET_NAME es el nombre del bucket de Cloud Storage que la función supervisará.

Finalización del objeto

Valor del tipo de activador: google.storage.object.finalize

Este evento se envía cuando se crea un objeto nuevo (o se sobrescribe un objeto existente y se crea una generación nueva de ese objeto) en el bucket.

Eliminación del objeto

Valor del tipo de activador: google.storage.object.delete

Este evento se envía cuando se borra un objeto de manera permanente. Según la configuración del control de versiones del objeto de un bucket , esto significa lo siguiente:

  • En el caso de los depósitos con control de versiones, este solo se envía cuando se borra una versión de manera permanente (pero no cuando se archiva un objeto).

  • En el caso de los depósitos sin control de versiones, este se envía cuando se borra o se sobrescribe un objeto.

Archivado del objeto

Valor del tipo de activador: google.storage.object.archive

Este evento se envía cuando una versión publicada de un objeto se archiva o se borra.

Este evento solo se envía para depósitos con control de versiones.

Actualización de metadatos del objeto

Valor del tipo de activador: google.storage.object.metadataUpdate

Este evento se envía cuando los metadatos de un objeto existente cambian.

Estructura de eventos

Los datos de eventos de Storage se entregan en el formato object de Cloud Storage.

Mecanismo de entrega de eventos

Los eventos se entregan mediante las notificaciones de Pub/Sub desde Cloud Storage.

Límite de notificaciones

Un bucket puede tener hasta 10 configuraciones de notificación definidas para activar un evento específico. La configuración de demasiadas notificaciones para el mismo bucket puede superar el límite de notificaciones de este y puede imposibilitar la creación de la función, como se indica en el siguiente error:

Cloud Storage bucket ...: Pub/Sub notification limit reached

Si alcanzas el límite, no puedes crear una función hasta que realices una acción correctiva, como quitar las notificaciones.

Obtén más información sobre las cuotas y límites de solicitud de Cloud Storage.

Permisos

Debes tener los permisos necesarios en el proyecto que recibirá las notificaciones. Esto incluye asegurarte de hacer lo siguiente:

  1. Obtén la dirección de correo electrónico del agente de servicio asociada con el proyecto que contiene tu bucket de Cloud Storage.

  2. Usa la dirección de correo electrónico que obtuviste en el paso anterior a fin de asignar a la cuenta de servicio la función pubsub.publisher de IAM para el tema de Pub/Sub que desees.

Obtén más información sobre la configuración de notificaciones de Pub/Sub para Cloud Storage.

Activadores de Cloud Storage heredados

El comando de gcloud que aparece a continuación implementa una función que se activa con notificaciones de cambio de objeto heredadas en un bucket específico. En general, las notificaciones de Cloud Pub/Sub son más fáciles de usar, más flexibles y más potentes que las de cambio de objeto. Sin embargo, estas notificaciones heredadas son compatibles con las funciones heredadas que ya consumen estos eventos.

gcloud functions deploy YOUR_FUNCTION_NAME \
--trigger-resource YOUR_TRIGGER_BUCKET_NAME \
--trigger-event providers/cloud.storage/eventTypes/object.change \
FLAGS...
Argumento Descripción
--trigger-resource NAME El nombre del bucket de Cloud Storage que la función vigila en busca de cambios.
--trigger-event NAME El nombre del tipo de evento que la función desea recibir. En este caso, es el evento object.change heredado.
FLAGS... Son marcas adicionales que debes especificar durante la implementación, como --runtime. Para obtener una referencia completa, consulta la documentación de gcloud functions deploy.

Próximos pasos

Consulta el instructivo de Cloud Storage para ver un ejemplo de cómo implementar una función controlada por eventos que se activa con Cloud Storage.