Extiende Cloud Run con activadores de eventos usando Cloud Run Functions
Con Cloud Run Functions, puedes implementar código para controlar eventos que se activan con los cambios en tu base de datos de Cloud Run. Esto te permite agregar funciones del servidor sin ejecutar tus propios servidores.
En esta guía, se describe cómo crear activadores para funciones de Cloud Run a partir de eventos de Firestore.
Puedes activar tus funciones de Cloud Run a partir de eventos en una base de datos de Firestore. Cuando se activa, tu función lee y actualiza una base de datos de Firestore en respuesta a estos eventos a través de las APIs de Firestore y las bibliotecas cliente.
El proceso de eventos de Firestore que activan una función de Cloud Run consta de los siguientes pasos:
El servicio espera cambios en un documento específico.
Cuando se produce un cambio, se activa el servicio y realiza sus tareas.
El servicio recibe un objeto de datos con una instantánea del documento afectado. En el caso de los eventos
write
oupdate
, el objeto de datos contiene instantáneas que representan el estado del documento antes y después del evento de activación.
Antes de comenzar
- Asegúrate de haber configurado un proyecto nuevo para Cloud Run, como se describe en la página de configuración.
Habilita las APIs de Artifact Registry, Cloud Build, Cloud Run Admin, Eventarc, Firestore Cloud Logging y Pub/Sub:
Roles obligatorios
Tú o tu administrador deben otorgar la cuenta del implementador y la identidad del activador. De forma opcional, otorga a la agente de servicio de Pub/Sub los siguientes roles de IAM.
Roles necesarios para la cuenta del implementador
Para obtener los permisos que necesitas para activar desde eventos de Firestore, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:
-
Editor de Cloud Build (
roles/cloudbuild.builds.editor
) -
Administrador de Cloud Run (
roles/run.admin
) -
Propietario de Datastore (
roles/datastore.owner
) -
Administrador de Eventarc (
roles/eventarc.admin
) -
Descriptor de acceso de vista de registros (
roles/logging.viewAccessor
) -
Administrador de IAM de proyecto (
roles/resourcemanager.projectIamAdmin
) -
Administrador de cuenta de servicio (
roles/iam.serviceAccountAdmin
) -
Usuario de cuenta de servicio (
roles/iam.serviceAccountUser
) -
Administrador de Service Usage (
roles/serviceusage.serviceUsageAdmin
)
Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.
También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.
Ten en cuenta que, de forma predeterminada, los permisos de Cloud Build incluyen permisos para subir y descargar artefactos de Artifact Registry.
Roles obligatorios para la identidad del activador
Toma nota del recurso Compute Engine predeterminada, ya que la conectarás a un activador de Eventarc para representar la identidad del activador con fines de prueba. Esta cuenta de servicio se crea automáticamente después de habilitar o usar un servicio de Google Cloud que usa Compute Engine, y con el siguiente formato de correo electrónico:
PROJECT_NUMBER-compute@developer.gserviceaccount.com
Reemplaza
PROJECT_NUMBER
por el número de tu proyecto Google Cloud. Para encontrar el número del proyecto, ve a la página de bienvenida de la consola de Google Cloud o ejecuta el siguiente comando:gcloud projects describe PROJECT_ID --format='value(projectNumber)'
Para entornos de producción, recomendamos crear una cuenta de servicio nueva y otorgarle una o más funciones de IAM que contengan los permisos mínimos requeridos y seguir el principio de privilegio mínimo.
- De forma predeterminada, solo los propietarios y los editores del proyecto, y los administradores y los invocadores de Cloud Run pueden llamar a los servicios de Cloud Run.
Puedes controlar el acceso según el servicio. Sin embargo, para fines de prueba, otorga el rol de invocador de Cloud Run (
run.invoker
) en el proyecto Google Cloud a la cuenta de servicio de Compute Engine. Esto otorga el rol en todos los servicios y trabajos de Cloud Run en un proyecto.gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --role=roles/run.invoker
Ten en cuenta que si creas un activador para un servicio autenticado de Cloud Run sin otorgar la función de invocador de Cloud Run, el activador se crea de forma correcta y está activo. Sin embargo, el activador no funcionará como se espera y aparecerá en el registro un mensaje similar al siguiente:
The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header.
- Otorga el rol de receptor de eventos de Eventarc (
roles/eventarc.eventReceiver
) en el proyecto a la cuenta de servicio predeterminada de Compute Engine para que el activador de Eventarc pueda recibir eventos de proveedores de eventos.gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --role=roles/eventarc.eventReceiver
Rol opcional para el agente de servicio de Pub/Sub
- Si habilitaste el agente de servicio de Cloud Pub/Sub el 8 de abril de 2021 o antes de esa fecha,
para admitir las solicitudes de envío de Pub/Sub autenticadas, otorga
el rol de creador
de tokens de cuenta de servicio (
roles/iam.serviceAccountTokenCreator
) al agente de servicio. De lo contrario, este rol se otorga de forma predeterminada:gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \ --role=roles/iam.serviceAccountTokenCreator
Configura la base de datos de Firestore
Antes de implementar tu servicio, debes crear una base de datos de Firestore:
Ve a la página de Firestore.
Selecciona Crear una base de datos de Firestore.
En el campo Asigna un nombre a tu base de datos, ingresa un ID de base de datos, como
firestore-db
.En la sección Opciones de configuración, Firestore nativo está seleccionado de forma predeterminada junto con las reglas de seguridad aplicables.
En Tipo de ubicación, selecciona Región y elige la región en la que residirá tu base de datos. Esta elección es permanente.
Haz clic en Crear base de datos.
El modelo de datos de Firestore consta de colecciones que contienen documentos. Cada documento contiene un conjunto de pares clave-valor.
Escribe una función activada por Firestore
Para escribir una función que responda a eventos de Firestore, prepárate para especificar lo siguiente durante la implementación:
- un tipo de evento de activación
- un filtro de eventos de activación para seleccionar los documentos asociados con la función
- el código de la función que se ejecutará
Tipos de eventos
Firestore admite los eventos create
, update
, delete
y write
. El evento write
comprende todas las modificaciones que se realizan a un documento.
Tipo de evento | Activador |
---|---|
google.cloud.firestore.document.v1.created (predeterminada) |
Se activa cuando se escribe en un documento por primera vez. |
google.cloud.firestore.document.v1.updated |
Se activa cuando un documento ya existe y se cambia uno de sus valores. |
google.cloud.firestore.document.v1.deleted |
Se activa cuando se borra un documento con datos. |
google.cloud.firestore.document.v1.written |
Se activa cuando se crea, actualiza o borra un documento. |
google.cloud.firestore.document.v1.created.withAuthContext |
Es igual que created , pero agrega información de autenticación. |
google.cloud.firestore.document.v1.updated.withAuthContext |
Es igual que updated , pero agrega información de autenticación. |
google.cloud.firestore.document.v1.deleted.withAuthContext |
Es igual que deleted , pero agrega información de autenticación. |
google.cloud.firestore.document.v1.written.withAuthContext |
Es igual que written , pero agrega información de autenticación. |
Los comodines se escriben en los activadores con llaves, por ejemplo:
projects/YOUR_PROJECT_ID/databases/(default)/documents/collection/{document_wildcard}
Filtros de eventos activadores
Para activar tu servicio, especifica una ruta de acceso al documento que deseas escuchar. La ruta de acceso al documento debe estar en el mismo proyecto Google Cloud que el servicio.
A continuación, se muestran algunos ejemplos de rutas de acceso de documentos válidas:
users/marie
: Supervisa un solo documento,/users/marie
.users/{username}
: Supervisa todos los documentos del usuario. Los comodines se usan para supervisar todos los documentos de la colección.users/{username}/addresses/home
: Supervisa el documento de dirección particular de todos los usuarios.users/{username}/addresses/{addressId}
: Supervisa todos los documentos de dirección.users/{user=**}
: Supervisa todos los documentos del usuario y los documentos de las subcolecciones de cada documento del usuario, como/users/userID/address/home
o/users/userID/phone/work
.users/{username}/addresses
: Es una ruta de acceso de dirección no válida. Se refiere a la subcolecciónaddresses
, no a un documento.
Comodines y parámetros
Si no conoces el documento específico que quieres supervisar, usa un {wildcard}
en lugar del ID del documento:
users/{username}
escucha cambios en todos los documentos del usuario.
En este ejemplo, cuando se cambia cualquier campo en los documentos de users
, coincide con un comodín llamado {username}
.
Si un documento de users
tiene subcolecciones y se modifica un campo de uno de los documentos en ellas, no se activará el comodín {username}
. Si tu objetivo es responder también a los eventos en las subcolecciones, usa el comodín de varios segmentos {username=**}
.
Las coincidencias de comodines se extraen de las rutas de acceso de documentos. Puedes definir tantos comodines como desees para sustituir los IDs explícitos de colección o documento. Puedes usar hasta un comodín de varios segmentos, como {username=**}
.
Código de la función
Consulta los ejemplos para saber cómo usar los eventos de Firestore en modo nativo para activar una función de Cloud Run.
Incluye las dependencias de .proto en tu fuente
Debes incluir el archivo data.proto
de Cloud Run en el directorio del código fuente de tu función. Este archivo importa los siguientes archivos .proto, que también debes incluir en tu directorio del código fuente:
Usa la misma estructura de directorios para las dependencias. Por ejemplo, coloca struct.proto
dentro de google/protobuf
.
Estos archivos son necesarios para decodificar los datos de eventos. Si la fuente de tu función no incluye estos archivos, se mostrará un error cuando se ejecute.
Atributos del evento
Cada evento incluye atributos de datos que contienen información sobre el evento, como la hora en que se activó. Cloud Run agrega datos adicionales sobre la base de datos y el documento involucrados en el evento. Puedes acceder a estos atributos de la siguiente manera:
Java
logger.info("Function triggered by event on: " + event.getSource()); logger.info("Event type: " + event.getType()); logger.info("Event time " + event.getTime()); logger.info("Event project: " + event.getExtension("project")); logger.info("Event location: " + event.getExtension("location")); logger.info("Database name: " + event.getExtension("database")); logger.info("Database document: " + event.getExtension("document")); // For withAuthContext events logger.info("Auth information: " + event.getExtension("authid")); logger.info("Auth information: " + event.getExtension("authtype"));
Node.js
console.log(`Function triggered by event on: ${cloudEvent.source}`); console.log(`Event type: ${cloudEvent.type}`); console.log(`Event time: ${cloudEvent.time}`); console.log(`Event project: ${cloudEvent.project}`); console.log(`Event location: ${cloudEvent.location}`); console.log(`Database name: ${cloudEvent.database}`); console.log(`Document name: ${cloudEvent.document}`); // For withAuthContext events console.log(`Auth information: ${cloudEvent.authid}`); console.log(`Auth information: ${cloudEvent.authtype}`);
Python
print(f"Function triggered by change to: {cloud_event['source']}") print(f"Event type: {cloud_event['type']}") print(f"Event time: {cloud_event['time']}") print(f"Event project: {cloud_event['project']}") print(f"Location: {cloud_event['location']}") print(f"Database name: {cloud_event['database']}") print(f"Document: {cloud_event['document']}") // For withAuthContext events print(f"Auth information: {cloud_event['authid']}") print(f"Auth information: {cloud_event['authtype']}")
Estructuras de eventos
Este activador invoca tu servicio con un evento similar al siguiente:
{ "oldValue": { // Update and Delete operations only A Document object containing a pre-operation document snapshot }, "updateMask": { // Update operations only A DocumentMask object that lists changed fields. }, "value": { // A Document object containing a post-operation document snapshot } }
Cada objeto Document
contiene uno o más objetos Value
. Consulta la documentación de Value
para obtener referencias de tipo.
Crea activadores para funciones
Haz clic en la pestaña para obtener instrucciones de la herramienta que elijas.
Console
Cuando usas la consola de Google Cloud para crear una función, también puedes agregar un activador a tu función. Sigue estos pasos para crear un activador para tu función:
En la consola de Google Cloud , ve a Cloud Run:
Haz clic en Escribir una función y, luego, ingresa los detalles de la función. Para obtener más información sobre la configuración de funciones durante la implementación, consulta Implementa funciones.
En la sección Activador, haz clic en Agregar activador.
Selecciona Firestore trigger.
En el panel Activador de Eventarc, modifica los detalles del activador de la siguiente manera:
Ingresa un nombre para el activador en el campo Nombre del activador o usa el nombre predeterminado.
Selecciona un tipo de activador de la lista:
Fuentes de Google para especificar activadores para Pub/Sub, Cloud Storage, Firestore y otros proveedores de eventos de Google
Terceros para integrarte a proveedores externos a Google que ofrecen una fuente de Eventarc. Para obtener más información, consulta Eventos de terceros en Eventarc.
Selecciona Firestore en la lista Proveedor de eventos para seleccionar un producto que proporcione el tipo de evento para activar tu función. Para obtener la lista de proveedores de eventos, consulta Proveedores y destinos de eventos.
Selecciona type=google.cloud.firestore.document.v1.created en la lista Tipo de evento. La configuración del activador varía según el tipo de evento compatible. Para obtener más información, consulta Tipos de eventos.
En la sección Filtros, selecciona una base de datos, valores de operación y atributos, o usa las selecciones predeterminadas.
Si el campo Región está habilitado, selecciona una ubicación para el activador de Eventarc. En general, la ubicación de un activador de Eventarc debe coincidir con la ubicación del recurso Google Cloud que deseas supervisar para detectar eventos. En la mayoría de los casos, también debes implementar tu función en la misma región. Consulta Información sobre las ubicaciones de Eventarc para obtener más detalles sobre las ubicaciones de activadores de Eventarc.
En el campo Cuenta de servicio, selecciona una cuenta de servicio. Los activadores de Eventarc están vinculados a cuentas de servicio para usarlos como identidad cuando se invoca la función. La cuenta de servicio del activador de Eventarc debe tener permiso para invocar tu función. De forma predeterminada, Cloud Run usa la cuenta de servicio predeterminada de Compute Engine.
De manera opcional, especifica la ruta de URL del servicio a la que se enviará la solicitud entrante. Esta es la ruta de acceso relativa en el servicio de destino al que se deben enviar los eventos del activador. Por ejemplo,
/
,/route
,route
yroute/subroute
.
Una vez que hayas completado los campos obligatorios, haz clic en Guardar activador.
gcloud
Cuando creas una función con gcloud CLI, primero debes implementarla y, luego, crear un activador. Sigue estos pasos para crear un activador para tu función:
Ejecuta el siguiente comando en el directorio que contiene el código de muestra para implementar tu función:
gcloud run deploy FUNCTION \ --source . \ --function FUNCTION_ENTRYPOINT \ --base-image BASE_IMAGE_ID \ --region REGION
Reemplaza lo siguiente:
Reemplaza FUNCTION por el nombre de la función que implementas. Puedes omitir este parámetro por completo, pero se te solicitará el nombre si lo haces.
FUNCTION_ENTRYPOINT por el punto de entrada a tu función en tu código fuente. Este es el código que ejecuta Cloud Run cuando se ejecuta tu función. El valor de esta marca debe ser un nombre de función o un nombre de clase completamente calificado que exista en tu código fuente.
BASE_IMAGE_ID por el entorno de la imagen base de tu función. Para obtener más detalles sobre las imágenes base y los paquetes incluidos en cada imagen, consulta Imágenes base de los tiempos de ejecución.
REGION con la Google Cloud región en la que deseas implementar tu función. Por ejemplo,
europe-west1
.
Ejecuta el siguiente comando para crear un activador que filtre eventos:
gcloud eventarc triggers create TRIGGER_NAME \ --location=EVENTARC_TRIGGER_LOCATION \ --destination-run-service=FUNCTION \ --destination-run-region=REGION \ --event-filters="type=google.cloud.firestore.document.v1.created" \ --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
Reemplaza lo siguiente:
TRIGGER_NAME por el nombre de tu activador.
EVENTARC_TRIGGER_LOCATION con la ubicación del activador de Eventarc. En general, la ubicación de un activador de Eventarc debe coincidir con la ubicación del recurso Google Cloud que deseas supervisar para detectar eventos. En la mayoría de los casos, también debes implementar tu función en la misma región. Para obtener más información, consulta Ubicaciones de Eventarc.
Reemplaza FUNCTION por el nombre de la función que implementas.
REGION por la región de Cloud Run de la función.
PROJECT_NUMBER por el Google Cloud número de tu proyecto. Los activadores de Eventarc están vinculados a cuentas de servicio para usarlos como identidad cuando se invoca la función. La cuenta de servicio del activador de Eventarc debe tener permiso para invocar tu función. De forma predeterminada, Cloud Run usa la cuenta de servicio de procesamiento predeterminada.
Cada marca
event-filters
especifica un tipo de evento, y el activador de la función solo se activa cuando un evento cumple con todos los criterios especificados en sus marcasevent-filters
. Cada activador debe tener una marcaevent-filters
que especifique un tipo de evento compatible, como un documento nuevo escrito en Firestore o un archivo subido a Cloud Storage. No puedes cambiar el tipo de filtro de eventos después de la creación. Para cambiar el tipo de filtro de eventos, debes crear un activador nuevo y borrar el anterior. De manera opcional, puedes repetir la marca--event-filters
con un filtro compatible en el formatoATTRIBUTE=VALUE
para agregar más filtros.
Terraform
Para crear un activador de Eventarc para una función de Cloud Run, consulta Crea un activador con Terraform.
Ejemplos
En los siguientes ejemplos, se describe cómo usar eventos de Firestore en modo nativo para activar una función de Cloud Run.
Ejemplo 1: Función de Hola Firestore
En el siguiente ejemplo, se imprimen los campos de un evento de activación de Firestore:
Node.js
Python
Go
Java
C#
Implementa la función
Para implementar la función Hello Firestore
, ejecuta el siguiente comando:
Si aún no está lista, configura la base de datos de Firestore.
Para implementar la función, consulta Crea activadores para funciones.
Prueba la función
Para probar la función Hello Firestore
, configura una colección llamada users
en tu base de datos de Firestore:
En la consola Google Cloud , ve a la página Bases de datos de Firestore:
Haz clic en Iniciar una colección.
Especifica
users
como el ID de colección.Para empezar a agregar el primer documento de la colección, en Agregar su primer documento, acepta el ID de documento generado de forma automática.
Agrega al menos un campo para el documento y especifica un nombre y un valor. Por ejemplo, en Nombre del campo, ingresa
username
y, en Valor del campo, ingresarowan
.Cuando termines, haz clic en Guardar.
Esta acción crea un documento nuevo, lo que activa tu función.
Para confirmar que tu función se activó, haz clic en el nombre vinculado de la función en la consola de Google Cloud página de descripción general de Cloud Run para abrir la página Detalles del servicio.
Selecciona la pestaña Registros y busca esta cadena:
Function triggered by change to: //firestore.googleapis.com/projects/your-project-id/databases/(default)'
Ejemplo 2: función Convertir en mayúsculas
En el siguiente ejemplo, se recupera el valor que agrega el usuario, se convierte la cadena en esa ubicación a mayúscula y se reemplaza el valor por la cadena en mayúscula:
Node.js
Usa protobufjs para decodificar los datos del evento. Incluye el google.events.cloud.firestore.v1
data.proto
en la fuente.
Python
Go
Java
C#
Implementa la función
Para implementar la función Convert to Uppercase
, ejecuta el siguiente comando:
Si aún no está lista, configura la base de datos de Firestore.
Para implementar la función, consulta Crea activadores para funciones.
Prueba la función
Para probar la función Convert to Uppercase
que acabas de implementar, configura una colección llamada messages
en tu base de datos de Firestore:
En la consola Google Cloud , ve a la página Bases de datos de Firestore:
Haz clic en Iniciar una colección.
Especifica
messages
como el ID de colección.Para empezar a agregar el primer documento de la colección, en Agregar su primer documento, acepta el ID de documento generado de forma automática.
Para activar la función implementada, agrega un documento en el que el Nombre del campo sea
original
y el Valor del campo seaminka
.Cuando guardes el documento, verás la palabra en minúsculas en el campo de valor que convierte a mayúsculas.
Si luego editas el valor del campo para que contenga letras minúsculas, se activará la función de nuevo y se convertirán todas las letras minúsculas en mayúsculas.
Limitaciones de las funciones
- No se garantiza el ordenamiento. Los cambios rápidos pueden activar invocaciones de funciones en un orden inesperado.
- Los eventos se entregan al menos una vez, pero un solo evento puede dar lugar a varias invocaciones de funciones. Evita depender de la mecánica de entrega de eventos exactamente una vez y escribe funciones idempotentes.
- Un activador se asocia con una sola base de datos. No puedes crear un activador que coincida con varias bases de datos.
- Cuando se borra una base de datos, no se borra automáticamente ningún activador de la base de datos. El activador deja de entregar eventos, pero sigue existiendo hasta que lo borras.