Crea transferencias

En esta página, se muestra cómo crear y, luego, iniciar trabajos de transferencia.

Para ver si tu fuente y tu destino (también conocidos como receptor) son compatibles con Servicio de transferencia de almacenamiento, consulta Fuentes y receptores admitidos.

Agentes y grupos de agentes

Dependiendo de tu origen y destino, es posible que debas crear y configurar un grupo de agentes y, luego, instalar agentes en una máquina con acceso a tu origen o destino.

  • Las transferencias de Amazon S3, Microsoft Azure, las listas de URL o Cloud Storage a Cloud Storage no requieren agentes y grupos de agentes.

  • Las transferencias cuyo origen o destino es un sistema de archivos, o desde almacenamiento compatible con S3, requieren agentes y grupos de agentes. Consulta Administra grupos de agentes para obtener instrucciones.

Antes de comenzar

Antes de configurar las transferencias, asegúrate de haber configurado el acceso:

Si usas comandos de gcloud, instala la CLI de gcloud.

Crear una transferencia

No incluyas información sensible, como información de identificación personal (PII) ni datos de seguridad en el nombre de la tarea de transferencia. Los nombres de los recursos se pueden propagar a los nombres de otros recursos de Google Cloud y pueden exponerse a sistemas internos de Google fuera de tu proyecto.

Consola de Google Cloud

  1. Ve a la página Servicio de transferencia de almacenamiento en la consola de Google Cloud.

    Ir al Servicio de transferencia de almacenamiento

  2. Haz clic en Crear trabajo de transferencia. Se muestra la página Crea un trabajo de transferencia.

  3. Elige una fuente:

    Cloud Storage

    Tu cuenta de usuario debe tener el permiso storage.buckets.get para seleccionar depósitos de origen y destino. También puedes escribir el nombre del bucket directamente. Para obtener más información, consulta Soluciona problemas de acceso.

    1. En Tipo de fuente, selecciona Cloud Storage.

    2. Selecciona tu Tipo de destino.

    3. Si tu destino es Cloud Storage, selecciona el modo de programación. Las transferencias por lotes se ejecutan de forma única o programada. Las transferencias basadas en eventos supervisan de forma continua la fuente y transfieren datos cuando se agregan o modifican.

      Para configurar una transferencia basada en eventos, sigue las instrucciones que se indican en Transferencias basadas en eventos.

    4. Haz clic en Próximo paso.

    5. Selecciona un bucket y, de manera opcional, una carpeta en él con una de las siguientes opciones:

      • Ingresa un nombre de bucket de Cloud Storage y una ruta de acceso existente en el campo Bucket o carpeta sin el prefijo gs://. Por ejemplo, my-test-bucket/path/to/files. Para especificar un bucket de Cloud Storage de otro proyecto, escriba el nombre exactamente en el campo Nombre del bucket.

      • Selecciona una lista de bucket s existentes en tus proyectos mediante un clic en Explorar y, luego, selecciona un bucket.

        Cuando haces clic en Explorar, puedes seleccionar los buckets en otros proyectos si haces clic en el ID del proyecto y, luego, seleccionas el ID del proyecto y el bucket nuevos.

      • Para crear un bucket nuevo, haz clic en Crear nuevo bucket.

    6. Si se trata de una transferencia basada en eventos, ingresa el nombre de la suscripción de Pub/Sub, que tiene el siguiente formato:

      projects/PROJECT_NAME/subscriptions/SUBSCRIPTION_ID
      
    7. De manera opcional, puedes filtrar objetos por prefijo o por fecha de última modificación. Si especificaste una carpeta como ubicación de origen, los filtros de prefijos se relacionan con esa carpeta. Por ejemplo, si tu fuente es my-test-bucket/path/, un filtro de inclusión de file incluye todos los archivos que comienzan con my-test-bucket/path/file.
    8. Haz clic en Próximo paso.

    Amazon S3

    Consulta Cómo transferir datos de Amazon S3 a Cloud Storage.

    Almacenamiento compatible con S3

    Consulta Cómo transferir desde un almacenamiento compatible con S3 a Cloud Storage.

    Microsoft Azure Blob Storage

    1. En Tipo de fuente, selecciona Azure Blob Storage o Data Lake Storage Gen2.

    2. Haga clic en Siguiente paso.

    3. Especifique lo siguiente:

      1. Nombre de la cuenta de almacenamiento: el nombre de la cuenta de origen de Microsoft Azure Storage.

        El nombre de la cuenta de almacenamiento se muestra en el portal de Microsoft Azure Storage, en Todos los servicios > Almacenamiento > Cuentas de almacenamiento.

      2. Nombre del contenedor: el nombre del contenedor de Microsoft Azure Storage.

        El nombre del contenedor se muestra en el portal de Microsoft Azure Storage en Explorador de almacenamiento > Contenedores de Blob.

      3. Firma de acceso compartido (SAS): el token SAS de Microsoft Azure Storage creado a partir de una política de acceso almacenado. Para obtener más información, consulte Conceder acceso limitado a los recursos de Azure Storage mediante firmas de acceso compartido (SAS).

        El tiempo de vencimiento predeterminado para los tokens SAS es de 8 horas. Cuando crees tu token SAS, asegúrate de establecer un tiempo de vencimiento razonable que te permita completar correctamente tu transferencia.
    4. De manera opcional, puedes filtrar objetos por prefijo o por fecha de última modificación. Si especificaste una carpeta como ubicación de origen, los filtros de prefijos se relacionan con esa carpeta. Por ejemplo, si tu fuente es my-test-bucket/path/, un filtro de inclusión de file incluye todos los archivos que comienzan con my-test-bucket/path/file.
    5. Haz clic en Próximo paso.

    Sistema de archivos

    1. En Tipo de fuente, selecciona Sistema de archivos POSIX.

    2. Selecciona tu Tipo de destino y haz clic en Siguiente paso.

    3. Selecciona un grupo de agentes existente o selecciona Crear grupo de agentes y sigue las instrucciones para crear un grupo nuevo.

    4. Especifica la ruta completamente calificada del directorio del sistema de archivos.

    5. Haz clic en Próximo paso.

    HDFS

    Consulta Cómo transferir datos de HDFS a Cloud Storage.

    Lista de URL

    1. En Tipo de fuente, selecciona Lista de URL y haz clic en Siguiente paso.

    2. En la URL de archivo TSV, proporciona la URL a un archivo de valores separados por tabulaciones (TSV). Consulta Crea una lista de URL si deseas obtener detalles para crear el archivo TSV.

    3. De manera opcional, puedes filtrar objetos por prefijo o por fecha de última modificación. Si especificaste una carpeta como ubicación de origen, los filtros de prefijos se relacionan con esa carpeta. Por ejemplo, si tu fuente es my-test-bucket/path/, un filtro de inclusión de file incluye todos los archivos que comienzan con my-test-bucket/path/file.
    4. Haz clic en Próximo paso.

  4. Elije un destino:

    Cloud Storage

    1. En el campo Bucket o carpeta, ingresa el bucket de destino y el nombre de la carpeta (opcional) o haz clic en Explorar para seleccionar un bucket de una lista de buckets existentes en tu proyecto actual. Para crear un bucket nuevo, haz clic en Crear nuevo bucket.

    2. Haga clic en Siguiente paso.

    3. Elige la configuración del trabajo de transferencia. Algunas opciones solo están disponibles para ciertas combinaciones de fuente y receptor.

      1. En el campo Descripción, ingresa una descripción de la transferencia. Como práctica recomendada, ingresa una descripción que sea significativa y única para que puedas distinguir los trabajos.

      2. En Opciones de metadatos, selecciona las opciones predeterminadas o haz clic en Ver y seleccionar opciones para especificar los valores de todos los metadatos admitidos. Consulta Conservación de metadatos para obtener más información.

      3. En Cuándo reemplazar, selecciona una de las siguientes opciones:

        • Si es diferente: Reemplaza los archivos de destino si el archivo de origen con el mismo nombre tiene diferentes ETags o valores de suma de verificación.

        • Siempre: Siempre escribe archivos de destino cuando el archivo de origen tiene el mismo nombre, incluso si son idénticos.

      4. En Cuándo borrar, selecciona una de las siguientes opciones:

        • Nunca: Nunca borres archivos de origen o de destino.

        • Borrar archivos de la fuente después de la transferencia: Borra los archivos de la fuente después de transferirlos al destino.

        • Borra los archivos del destino si no están también en el origen: Si los archivos en el bucket de Cloud Storage de destino no están también en el origen, borra los archivos del bucket de Cloud Storage.

          Esta opción garantiza que el bucket de destino de Cloud Storage coincida exactamente con tu fuente.

      5. En Opciones de notificación, selecciona tu tema de Pub/Sub y los eventos a los que deseas notificar. Consulta las notificaciones de Pub/Sub para obtener más detalles.

    4. Haga clic en Siguiente paso.

    Sistema de archivos

    1. Selecciona un grupo de agentes existente o selecciona Crear grupo de agentes y sigue las instrucciones para crear un grupo nuevo.

    2. Especifica la ruta de acceso del directorio de destino completamente calificado.

    3. Haga clic en Siguiente paso.

  5. Elige tus opciones de programación:

    1. En la lista desplegable Ejecutar una vez, selecciona una de las siguientes opciones:

      • Ejecutar una vez: Ejecuta una sola transferencia, a la vez a una hora seleccionada.

      • Ejecutar todos los días: Ejecuta una transferencia a diario a partir de la hora que selecciones.

        Puedes ingresar una Fecha de finalización opcional o dejar en blanco Fecha de finalización para ejecutar la transferencia de forma continua.

      • Ejecutar cada semana: Ejecuta una transferencia semanal, a la hora que selecciones.

      • Ejecutar con frecuencia personalizada: Ejecuta una transferencia a la frecuencia que seleccionas. Puedes elegir repetir la transferencia a un intervalo regular de horas, días o semanas.

        Puedes ingresar una Fecha de finalización opcional o dejar en blanco Fecha de finalización para ejecutar la transferencia de forma continua.

    2. En la lista desplegable A partir de ahora, selecciona una de las siguientes opciones:

      • Inicio ahora: Inicia la transferencia después de hacer clic en Crear.

      • A partir del: inicia la transferencia en la fecha y hora que seleccionaste. Haz clic en Calendario para mostrar un calendario a fin de seleccionar la fecha de inicio.

    3. Para crear tu trabajo de transferencia, haz clic en Crear.

CLI de gcloud

Para crear un nuevo trabajo de transferencia, usa el comando gcloud transfer jobs create. La creación de un trabajo nuevo inicia la transferencia especificada, a menos que se especifique un programa o --do-not-run.

gcloud transfer jobs create \
  SOURCE DESTINATION

Aquí:

  • SOURCE es la fuente de datos de esta transferencia. El formato de cada fuente es el siguiente:

    • Cloud Storage: gs://BUCKET_NAME. Para transferir desde una carpeta en particular, especifica gs://BUCKET_NAME/FOLDER_PATH/, incluida la barra diagonal final.
    • Amazon S3: s3://BUCKET_NAME/FOLDER_PATH
    • Almacenamiento compatible con S3: s3://BUCKET_NAME. El nombre del bucket es relativo al extremo. Por ejemplo, si tus datos residen en https://us-east-1.example.com/folder1/bucket_a, ingresa s3://folder1/bucket_a.
    • Microsoft Azure Storage: https://myaccount.blob.core.windows.net/CONTAINER_NAME
    • Lista de URL: https://PATH_TO_URL_LIST o http://PATH_TO_URL_LIST
    • Sistema de archivos POSIX: posix:///PATH Esta debe ser una ruta de acceso absoluta desde la raíz de la máquina anfitrión del agente.
    • HDFS: hdfs:///PATH
  • DESTINATION es uno de los siguientes:

    • Cloud Storage: gs://BUCKET_NAME. Para transferir a un directorio en particular, especifica gs://BUCKET_NAME/FOLDER_PATH/, incluida la barra diagonal final.
    • Sistema de archivos POSIX: posix:///PATH Esta debe ser una ruta de acceso absoluta desde la raíz de la máquina anfitrión del agente.

Si la transferencia requiere agentes de transferencia, las siguientes opciones están disponibles:

  • --source-agent-pool especifica el grupo de agentes de origen que se usará para esta transferencia. Obligatorio para las transferencias que se originan desde un sistema de archivos.

  • --destination-agent-pool especifica el grupo de agentes de destino que se usará para esta transferencia. Obligatorio para las transferencias a un sistema de archivos.

  • --intermediate-storage-path es la ruta a un bucket de Cloud Storage, en el formato gs://my-intermediary-bucket. Obligatorio para las transferencias entre dos sistemas de archivos. Consulta Crea un bucket de Cloud Storage como intermediario para obtener más información sobre cómo crear el bucket intermedio.

Las opciones adicionales incluyen:

  • --source-creds-file especifica la ruta relativa a un archivo local en tu máquina que incluye credenciales de AWS o Azure para la fuente de transferencia. Para obtener información sobre el formato de archivo de credenciales, consulta la referencia de TransferSpec.

  • --do-not-run evita que el Servicio de transferencia de almacenamiento ejecute el trabajo cuando se envía el comando. Si deseas ejecutar el trabajo, actualízalo para agregar una programación o usa jobs run a fin de iniciarlo de forma manual.

  • --manifest-file especifica la ruta a un archivo CSV en Cloud Storage, que contiene una lista de archivos para transferir de tu fuente. Para formatear archivos de manifiesto, consulta Transfiere archivos o objetos específicos con un manifiesto.

  • Información del trabajo: Puedes especificar --name, --description y --source-creds-file.

  • Programa: Especifica --schedule-starts, --schedule-repeats-every, y --schedule-repeats-until o --do-not-run.

  • Condiciones de objetos: Usa condiciones para determinar qué objetos se transfieren. Estos incluyen --include-prefixes y --exclude-prefixes, y las condiciones basadas en el tiempo en --include-modified-[before | after]-[absolute | relative]. Si especificaste una carpeta con tu fuente, los filtros de prefijo son relativos a esa carpeta. Consulta Filtra objetos de origen por prefijo para obtener más información.

    Las condiciones de los objetos no son compatibles con las transferencias que involucran sistemas de archivos.

  • Opciones de transferencia: Especifica si deseas reemplazar los archivos de destino (--overwrite-when=different o always) y si deseas borrar ciertos archivos durante o después de la transferencia (--delete-from=destination-if-unique o source-after-transfer). Especifica qué valores de metadatos se deben conservar (--preserve-metadata) y, de manera opcional, puedes configurar una clase de almacenamiento en los objetos transferidos (--custom-storage-class).

  • Notificaciones: Configura las notificaciones de Pub/Sub para transferencias con --notification-pubsub-topic, --notification-event-types y --notification-payload-format.

  • Cloud Logging: Habilita Cloud Logging para transferencias sin agentes o transferencias desde fuentes compatibles con S3 con --log-actions y --log-action-states. Consulta Cloud Logging para el servicio de transferencia de almacenamiento para obtener más información.

Las transferencias desde fuentes compatibles con S3 también usan las siguientes opciones:

  • --source-endpoint (obligatorio) especifica el extremo de tu sistema de almacenamiento. Por ejemplo, s3.example.com Consulta con tu proveedor el formato correcto. No especifiques el protocolo (http:// o https://).
  • --source-signing-region especifica una región para firmar solicitudes. Omite esta marca si tu proveedor de almacenamiento no requiere una región de firma.
  • --source-auth-method especifica el método de autenticación que se usará. Los valores válidos son AWS_SIGNATURE_V2 o AWS_SIGNATURE_V4. Consulta la documentación de SigV4 y SigV2 de Amazon para obtener más información.
  • --source-request-model especifica el estilo de asignación que se usará. Los valores válidos son PATH_STYLE o VIRTUAL_HOSTED_STYLE. El estilo de ruta usa el formato https://s3.example.com/BUCKET_NAME/KEY_NAME. El estilo de alojamiento virtual usa el formato "https://BUCKET_NAME.s3.example.com/KEY_NAME".
  • --source-network-protocol especifica el protocolo de red que los agentes deben usar para este trabajo. Los valores válidos son HTTP o HTTPS.
  • --source-list-api especifica la versión de la API de S3 para mostrar objetos del bucket. Los valores válidos son LIST_OBJECTS o LIST_OBJECTS_V2. Consulta la documentación de ListObjectsV2 y ListObjects de Amazon para obtener más información.

Para ver todas las opciones, ejecuta gcloud transfer jobs create --help o consulta la documentación de referencia de gcloud.

Ejemplos

De Amazon S3 a Cloud Storage

Consulta Cómo transferir datos de Amazon S3 a Cloud Storage.

De almacenamiento compatible con S3 a Cloud Storage

Consulta Cómo transferir datos de un almacenamiento compatible con S3 a Cloud Storage.

Del sistema de archivos a Cloud Storage

Consulta Cómo transferir desde un sistema de archivos a Cloud Storage.

De Cloud Storage al sistema de archivos

Para transferir desde un bucket de Cloud Storage a un sistema de archivos, especifica lo siguiente.

gcloud transfer jobs create \
  gs://my-storage-bucket posix:///tmp/destination \
  --destination-agent-pool=my-destination-agent-pool

De un sistema de archivos a otro

Para transferir entre dos sistemas de archivos, debes especificar un grupo de agentes de origen, un grupo de agentes de destino y un bucket intermedio de Cloud Storage a través del cual pasan los datos.

Consulta Crea un bucket de Cloud Storage como intermediario para obtener más información sobre el bucket intermedio.

Luego, especifica estos 3 recursos cuando llames a transfer jobs create:

gcloud transfer jobs create \
  posix:///tmp/source/on/systemA posix:///tmp/destination/on/systemB \
  --source-agent-pool=source_agent_pool \
  --destination-agent-pool=destination_agent_pool \
  --intermediate-storage-path=gs://my-intermediary-bucket

REST

En los siguientes ejemplos, se muestra cómo usar el Servicio de transferencia de almacenamiento a través de la API de REST.

Cuando configures o edites trabajos de transferencia con la API del Servicio de transferencia de almacenamiento, la hora debe estar en UTC. Para obtener más información sobre cómo especificar el programa de un trabajo de transferencia, consulta Programa.

Transfiere entre depósitos de Cloud Storage

En este ejemplo, aprenderás cómo mover archivos desde un bucket de Cloud Storage a otro. Por ejemplo, puedes replicar datos en un bucket en otra ubicación.

Realiza la solicitud con transferJobs create:

POST https://storagetransfer.googleapis.com/v1/transferJobs
{
  "description": "YOUR DESCRIPTION",
  "status": "ENABLED",
  "projectId": "PROJECT_ID",
  "schedule": {
      "scheduleStartDate": {
          "day": 1,
          "month": 1,
          "year": 2015
      },
      "startTimeOfDay": {
          "hours": 1,
          "minutes": 1
      }
  },
  "transferSpec": {
      "gcsDataSource": {
          "bucketName": "GCS_SOURCE_NAME"
      },
      "gcsDataSink": {
          "bucketName": "GCS_SINK_NAME"
      },
      "transferOptions": {
          "deleteObjectsFromSourceAfterTransfer": true
      }
  }
}
Respuesta:
200 OK
{
  "transferJob": [
      {
          "creationTime": "2015-01-01T01:01:00.000000000Z",
          "description": "YOUR DESCRIPTION",
          "name": "transferJobs/JOB_ID",
          "status": "ENABLED",
          "lastModificationTime": "2015-01-01T01:01:00.000000000Z",
          "projectId": "PROJECT_ID",
          "schedule": {
              "scheduleStartDate": {
                  "day": 1,
                  "month": 1,
                  "year": 2015
              },
              "startTimeOfDay": {
                  "hours": 1,
                  "minutes": 1
              }
          },
          "transferSpec": {
              "gcsDataSource": {
                  "bucketName": "GCS_SOURCE_NAME",
              },
              "gcsDataSink": {
                  "bucketName": "GCS_NEARLINE_SINK_NAME"
              },
              "objectConditions": {
                  "minTimeElapsedSinceLastModification": "2592000.000s"
              },
              "transferOptions": {
                  "deleteObjectsFromSourceAfterTransfer": true
              }
          }
      }
  ]
}

Transferencias desde Amazon S3 a Cloud Storage

Consulta Cómo transferir datos de Amazon S3 a Cloud Storage.

Transferencia entre Microsoft Azure Blob Storage y Cloud Storage

En este ejemplo, aprenderá cómo mover archivos de Microsoft Azure Storage a un bucket de Cloud Storage, con un token de acceso compartido (SAS) de Microsoft Azure Storage.

Para obtener más información sobre Microsoft SAS de Azure Storage, consulta Conceder acceso limitado a los recursos de Azure Storage mediante firmas de acceso compartido (SAS).

Antes de comenzar, revisa Configura el acceso a Microsoft Azure Storage y Precios para comprender lo que implica trasladar datos desde Microsoft Azure Storage a Cloud Storage.

Realiza la solicitud con transferJobs create:

POST https://storagetransfer.googleapis.com/v1/transferJobs
{
  "description": "YOUR DESCRIPTION",
  "status": "ENABLED",
  "projectId": "PROJECT_ID",
  "schedule": {
      "scheduleStartDate": {
          "day": 14,
          "month": 2,
          "year": 2020
      },
      "scheduleEndDate": {
          "day": 14
          "month": 2,
          "year": 2020
      },
      "startTimeOfDay": {
          "hours": 1,
          "minutes": 1
      }
  },
  "transferSpec": {
      "azureBlobStorageDataSource": {
          "storageAccount": "AZURE_SOURCE_NAME",
          "azureCredentials": {
              "sasToken": "AZURE_SAS_TOKEN",
          },
          "container": "AZURE_CONTAINER",
      },
      "gcsDataSink": {
          "bucketName": "GCS_SINK_NAME"
      }
  }
}
Respuesta:
200 OK
{
  "transferJob": [
      {
          "creationTime": "2020-02-14T01:01:00.000000000Z",
          "description": "YOUR DESCRIPTION",
          "name": "transferJobs/JOB_ID",
          "status": "ENABLED",
          "lastModificationTime": "2020-02-14T01:01:00.000000000Z",
          "projectId": "PROJECT_ID",
          "schedule": {
              "scheduleStartDate": {
                  "day": 14
                  "month": 2,
                  "year": 2020
              },
              "scheduleEndDate": {
                  "day": 14,
                  "month": 2,
                  "year": 2020
              },
              "startTimeOfDay": {
                  "hours": 1,
                  "minutes": 1
              }
          },
          "transferSpec": {
              "azureBlobStorageDataSource": {
                  "storageAccount": "AZURE_SOURCE_NAME",
                  "azureCredentials": {
                      "sasToken": "AZURE_SAS_TOKEN",
                  },
                  "container": "AZURE_CONTAINER",
              },
              "objectConditions": {},
              "transferOptions": {}
          }
      }
  ]
}

Transferdesde un sistema de archivos

Consulta Cómo transferir desde un sistema de archivos a Cloud Storage.

Especifica las rutas de origen y destino

Las rutas de origen y destino te permiten especificar directorios de origen y destino cuando transfieres datos a tu bucket de Cloud Storage. Por ejemplo, considera que tienes los archivos file1.txt y file2.txt, y un bucket de Cloud Storage llamado B. Si estableces una ruta de destino llamada my-stuff, después de que la transferencia se complete, tus archivos se encontrarán en gs://B/my-stuff/file1.txt y gs://B/my-stuff/file2.txt.

Especifica una ruta de acceso de origen

Para especificar una ruta de acceso de origen cuando creas un trabajo de transferencia, agrega un campo path al campo gcsDataSource en tu especificación TransferSpec:

{
gcsDataSource: {
  bucketName: "SOURCE_BUCKET",
  path: "SOURCE_PATH/",
},
}

En este ejemplo:

  • SOURCE_BUCKET: El bucket de origen de Cloud Storage.
  • SOURCE_PATH: La ruta de origen de Cloud Storage.

Especifica una ruta de destino

Para especificar una carpeta de destino cuando creas un trabajo de transferencia, agrega un campo path al campo gcsDataSink en tu especificación TransferSpec:

{
gcsDataSink: {
  bucketName: "DESTINATION_BUCKET",
  path: "DESTINATION_PATH/",
},
}

En este ejemplo:

  • DESTINATION_BUCKET: El bucket de destino de Cloud Storage
  • DESTINATION_PATH: La ruta de acceso de Cloud Storage de destino.

Solicitud de ejemplo completa

A continuación, se muestra un ejemplo de una solicitud completa:

POST https://storagetransfer.googleapis.com/v1/transferJobs
{
  "description": "YOUR DESCRIPTION",
  "status": "ENABLED",
  "projectId": "PROJECT_ID",
  "schedule": {
      "scheduleStartDate": {
          "day": 1,
          "month": 1,
          "year": 2015
      },
      "startTimeOfDay": {
          "hours": 1,
          "minutes": 1
      }
  },
  "transferSpec": {
      "gcsDataSource": {
          "bucketName": "GCS_SOURCE_NAME",
          "path": "GCS_SOURCE_PATH",
      },
      "gcsDataSink": {
          "bucketName": "GCS_SINK_NAME",
          "path": "GCS_SINK_PATH",
      },
      "objectConditions": {
          "minTimeElapsedSinceLastModification": "2592000s"
      },
      "transferOptions": {
          "deleteObjectsFromSourceAfterTransfer": true
      }
  }

}

Bibliotecas cliente

En los siguientes ejemplos, se muestra cómo usar el Servicio de transferencia de almacenamiento de manera programática con Go, Java, Node.js y Python.

Cuando configures o edites trabajos de transferencia de manera programática, la hora debe estar en UTC. Para obtener más información sobre cómo especificar el programa de un trabajo de transferencia, consulta Programa.

Para obtener más información sobre las bibliotecas cliente del Servicio de transferencia de almacenamiento, consulta Comienza a usar las bibliotecas cliente del Servicio de transferencia de almacenamiento.

Transfiere entre depósitos de Cloud Storage

En este ejemplo, aprenderás cómo mover archivos desde un bucket de Cloud Storage a otro. Por ejemplo, puedes replicar datos en un bucket en otra ubicación.

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	"google.golang.org/genproto/googleapis/type/date"
	"google.golang.org/genproto/googleapis/type/timeofday"
	"google.golang.org/protobuf/types/known/durationpb"

	storagetransfer "cloud.google.com/go/storagetransfer/apiv1"
	"cloud.google.com/go/storagetransfer/apiv1/storagetransferpb"
)

func transferToNearline(w io.Writer, projectID string, gcsSourceBucket string, gcsNearlineSinkBucket string) (*storagetransferpb.TransferJob, error) {
	// Your Google Cloud Project ID
	// projectID := "my-project-id"

	// The name of the GCS bucket to transfer objects from
	// gcsSourceBucket := "my-source-bucket"

	// The name of the Nearline GCS bucket to transfer objects to
	// gcsNearlineSinkBucket := "my-sink-bucket"

	ctx := context.Background()
	client, err := storagetransfer.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("storagetransfer.NewClient: %w", err)
	}
	defer client.Close()

	// A description of this job
	jobDescription := "Transfers objects that haven't been modified in 30 days to a Nearline bucket"

	// The time to start the transfer
	startTime := time.Now().UTC()

	req := &storagetransferpb.CreateTransferJobRequest{
		TransferJob: &storagetransferpb.TransferJob{
			ProjectId:   projectID,
			Description: jobDescription,
			TransferSpec: &storagetransferpb.TransferSpec{
				DataSink: &storagetransferpb.TransferSpec_GcsDataSink{
					GcsDataSink: &storagetransferpb.GcsData{BucketName: gcsNearlineSinkBucket}},
				DataSource: &storagetransferpb.TransferSpec_GcsDataSource{
					GcsDataSource: &storagetransferpb.GcsData{BucketName: gcsSourceBucket},
				},
				ObjectConditions: &storagetransferpb.ObjectConditions{
					MinTimeElapsedSinceLastModification: &durationpb.Duration{Seconds: 2592000 /*30 days */},
				},
				TransferOptions: &storagetransferpb.TransferOptions{DeleteObjectsFromSourceAfterTransfer: true},
			},
			Schedule: &storagetransferpb.Schedule{
				ScheduleStartDate: &date.Date{
					Year:  int32(startTime.Year()),
					Month: int32(startTime.Month()),
					Day:   int32(startTime.Day()),
				},
				ScheduleEndDate: &date.Date{
					Year:  int32(startTime.Year()),
					Month: int32(startTime.Month()),
					Day:   int32(startTime.Day()),
				},
				StartTimeOfDay: &timeofday.TimeOfDay{
					Hours:   int32(startTime.Hour()),
					Minutes: int32(startTime.Minute()),
					Seconds: int32(startTime.Second()),
				},
			},
			Status: storagetransferpb.TransferJob_ENABLED,
		},
	}
	resp, err := client.CreateTransferJob(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to create transfer job: %w", err)
	}
	if _, err = client.RunTransferJob(ctx, &storagetransferpb.RunTransferJobRequest{
		ProjectId: projectID,
		JobName:   resp.Name,
	}); err != nil {
		return nil, fmt.Errorf("failed to run transfer job: %w", err)
	}
	fmt.Fprintf(w, "Created and ran transfer job from %v to %v with name %v", gcsSourceBucket, gcsNearlineSinkBucket, resp.Name)
	return resp, nil
}

Java

¿Buscas muestras anteriores? Consulta la Guía de migración del Servicio de transferencia de almacenamiento.

import com.google.protobuf.Duration;
import com.google.storagetransfer.v1.proto.StorageTransferServiceClient;
import com.google.storagetransfer.v1.proto.TransferProto.CreateTransferJobRequest;
import com.google.storagetransfer.v1.proto.TransferTypes.GcsData;
import com.google.storagetransfer.v1.proto.TransferTypes.ObjectConditions;
import com.google.storagetransfer.v1.proto.TransferTypes.Schedule;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob.Status;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferOptions;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferSpec;
import com.google.type.Date;
import com.google.type.TimeOfDay;
import java.io.IOException;
import java.util.Calendar;

public class TransferToNearline {
  /**
   * Creates a one-off transfer job that transfers objects in a standard GCS bucket that are more
   * than 30 days old to a Nearline GCS bucket.
   */
  public static void transferToNearline(
      String projectId,
      String jobDescription,
      String gcsSourceBucket,
      String gcsNearlineSinkBucket,
      long startDateTime)
      throws IOException {

    // Your Google Cloud Project ID
    // String projectId = "your-project-id";

    // A short description of this job
    // String jobDescription = "Sample transfer job of old objects to a Nearline GCS bucket.";

    // The name of the source GCS bucket to transfer data from
    // String gcsSourceBucket = "your-gcs-source-bucket";

    // The name of the Nearline GCS bucket to transfer old objects to
    // String gcsSinkBucket = "your-nearline-gcs-bucket";

    // What day and time in UTC to start the transfer, expressed as an epoch date timestamp.
    // If this is in the past relative to when the job is created, it will run the next day.
    // long startDateTime =
    //     new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2000-01-01 00:00:00").getTime();

    // Parse epoch timestamp into the model classes
    Calendar startCalendar = Calendar.getInstance();
    startCalendar.setTimeInMillis(startDateTime);
    // Note that this is a Date from the model class package, not a java.util.Date
    Date date =
        Date.newBuilder()
            .setYear(startCalendar.get(Calendar.YEAR))
            .setMonth(startCalendar.get(Calendar.MONTH) + 1)
            .setDay(startCalendar.get(Calendar.DAY_OF_MONTH))
            .build();
    TimeOfDay time =
        TimeOfDay.newBuilder()
            .setHours(startCalendar.get(Calendar.HOUR_OF_DAY))
            .setMinutes(startCalendar.get(Calendar.MINUTE))
            .setSeconds(startCalendar.get(Calendar.SECOND))
            .build();

    TransferJob transferJob =
        TransferJob.newBuilder()
            .setDescription(jobDescription)
            .setProjectId(projectId)
            .setTransferSpec(
                TransferSpec.newBuilder()
                    .setGcsDataSource(GcsData.newBuilder().setBucketName(gcsSourceBucket))
                    .setGcsDataSink(GcsData.newBuilder().setBucketName(gcsNearlineSinkBucket))
                    .setObjectConditions(
                        ObjectConditions.newBuilder()
                            .setMinTimeElapsedSinceLastModification(
                                Duration.newBuilder().setSeconds(2592000 /* 30 days */)))
                    .setTransferOptions(
                        TransferOptions.newBuilder().setDeleteObjectsFromSourceAfterTransfer(true)))
            .setSchedule(Schedule.newBuilder().setScheduleStartDate(date).setStartTimeOfDay(time))
            .setStatus(Status.ENABLED)
            .build();

    // Create a Transfer Service client
    StorageTransferServiceClient storageTransfer = StorageTransferServiceClient.create();

    // Create the transfer job
    TransferJob response =
        storageTransfer.createTransferJob(
            CreateTransferJobRequest.newBuilder().setTransferJob(transferJob).build());

    System.out.println("Created transfer job from standard bucket to Nearline bucket:");
    System.out.println(response.toString());
  }
}

Node.js


// Imports the Google Cloud client library
const {
  StorageTransferServiceClient,
} = require('@google-cloud/storage-transfer');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of the Google Cloud Platform Project that owns the job
// projectId = 'my-project-id'

// A useful description for your transfer job
// description = 'My transfer job'

// Google Cloud Storage source bucket name
// gcsSourceBucket = 'my-gcs-source-bucket'

// Google Cloud Storage destination bucket name
// gcsSinkBucket = 'my-gcs-destination-bucket'

// Date to start daily migration
// startDate = new Date()

// Creates a client
const client = new StorageTransferServiceClient();

/**
 * Create a daily migration from a GCS bucket to another GCS bucket for
 * objects untouched for 30+ days.
 */
async function createDailyNearline30DayMigration() {
  // Runs the request and creates the job
  const [transferJob] = await client.createTransferJob({
    transferJob: {
      projectId,
      description,
      status: 'ENABLED',
      schedule: {
        scheduleStartDate: {
          day: startDate.getDate(),
          month: startDate.getMonth() + 1,
          year: startDate.getFullYear(),
        },
      },
      transferSpec: {
        gcsDataSource: {
          bucketName: gcsSourceBucket,
        },
        gcsDataSink: {
          bucketName: gcsSinkBucket,
        },
        objectConditions: {
          minTimeElapsedSinceLastModification: {
            seconds: 2592000, // 30 days
          },
        },
        transferOptions: {
          deleteObjectsFromSourceAfterTransfer: true,
        },
      },
    },
  });

  console.log(`Created transferJob: ${transferJob.name}`);
}

createDailyNearline30DayMigration();

Python

¿Buscas muestras anteriores? Consulta la Guía de migración del Servicio de transferencia de almacenamiento.

from datetime import datetime

from google.cloud import storage_transfer
from google.protobuf.duration_pb2 import Duration


def create_daily_nearline_30_day_migration(
    project_id: str,
    description: str,
    source_bucket: str,
    sink_bucket: str,
    start_date: datetime,
):
    """Create a daily migration from a GCS bucket to a Nearline GCS bucket
    for objects untouched for 30 days."""

    client = storage_transfer.StorageTransferServiceClient()

    # The ID of the Google Cloud Platform Project that owns the job
    # project_id = 'my-project-id'

    # A useful description for your transfer job
    # description = 'My transfer job'

    # Google Cloud Storage source bucket name
    # source_bucket = 'my-gcs-source-bucket'

    # Google Cloud Storage destination bucket name
    # sink_bucket = 'my-gcs-destination-bucket'

    transfer_job_request = storage_transfer.CreateTransferJobRequest(
        {
            "transfer_job": {
                "project_id": project_id,
                "description": description,
                "status": storage_transfer.TransferJob.Status.ENABLED,
                "schedule": {
                    "schedule_start_date": {
                        "day": start_date.day,
                        "month": start_date.month,
                        "year": start_date.year,
                    }
                },
                "transfer_spec": {
                    "gcs_data_source": {
                        "bucket_name": source_bucket,
                    },
                    "gcs_data_sink": {
                        "bucket_name": sink_bucket,
                    },
                    "object_conditions": {
                        "min_time_elapsed_since_last_modification": Duration(
                            seconds=2592000  # 30 days
                        )
                    },
                    "transfer_options": {
                        "delete_objects_from_source_after_transfer": True
                    },
                },
            }
        }
    )

    result = client.create_transfer_job(transfer_job_request)
    print(f"Created transferJob: {result.name}")

Transferencias desde Amazon S3 a Cloud Storage

Consulta Cómo transferir datos de Amazon S3 a Cloud Storage.

Transferencia entre Microsoft Azure Blob Storage y Cloud Storage

En este ejemplo, aprenderá cómo mover archivos de Microsoft Azure Storage a un bucket de Cloud Storage, con un token de acceso compartido (SAS) de Microsoft Azure Storage.

Para obtener más información sobre Microsoft SAS de Azure Storage, consulta Conceder acceso limitado a los recursos de Azure Storage mediante firmas de acceso compartido (SAS).

Antes de comenzar, revisa Configura el acceso a Microsoft Azure Storage y Precios para comprender lo que implica trasladar datos desde Microsoft Azure Storage a Cloud Storage.

Go

Para obtener información sobre cómo instalar y usar la biblioteca cliente del Servicio de transferencia de almacenamiento, consulta las Bibliotecas cliente del Servicio de transferencia de almacenamiento. Si deseas obtener más información, consulta la documentación de referencia de la API de Go del Servicio de transferencia de almacenamiento.

Para autenticarte en el Servicio de transferencia de almacenamiento, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

import (
	"context"
	"fmt"
	"io"
	"os"

	storagetransfer "cloud.google.com/go/storagetransfer/apiv1"
	"cloud.google.com/go/storagetransfer/apiv1/storagetransferpb"
)

func transferFromAzure(w io.Writer, projectID string, azureStorageAccountName string, azureSourceContainer string, gcsSinkBucket string) (*storagetransferpb.TransferJob, error) {
	// Your Google Cloud Project ID.
	// projectID := "my-project-id"

	// The name of your Azure Storage account.
	// azureStorageAccountName := "my-azure-storage-acc"

	// The name of the Azure container to transfer objects from.
	// azureSourceContainer := "my-source-container"

	// The name of the GCS bucket to transfer objects to.
	// gcsSinkBucket := "my-sink-bucket"

	ctx := context.Background()
	client, err := storagetransfer.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("storagetransfer.NewClient: %w", err)
	}
	defer client.Close()

	// The Azure SAS token, should be accessed via environment variable for security
	azureSasToken := os.Getenv("AZURE_SAS_TOKEN")

	req := &storagetransferpb.CreateTransferJobRequest{
		TransferJob: &storagetransferpb.TransferJob{
			ProjectId: projectID,
			TransferSpec: &storagetransferpb.TransferSpec{
				DataSource: &storagetransferpb.TransferSpec_AzureBlobStorageDataSource{
					AzureBlobStorageDataSource: &storagetransferpb.AzureBlobStorageData{
						StorageAccount: azureStorageAccountName,
						AzureCredentials: &storagetransferpb.AzureCredentials{
							SasToken: azureSasToken,
						},
						Container: azureSourceContainer,
					},
				},
				DataSink: &storagetransferpb.TransferSpec_GcsDataSink{
					GcsDataSink: &storagetransferpb.GcsData{BucketName: gcsSinkBucket}},
			},
			Status: storagetransferpb.TransferJob_ENABLED,
		},
	}
	resp, err := client.CreateTransferJob(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to create transfer job: %w", err)
	}
	if _, err = client.RunTransferJob(ctx, &storagetransferpb.RunTransferJobRequest{
		ProjectId: projectID,
		JobName:   resp.Name,
	}); err != nil {
		return nil, fmt.Errorf("failed to run transfer job: %w", err)
	}
	fmt.Fprintf(w, "Created and ran transfer job from %v to %v with name %v", azureSourceContainer, gcsSinkBucket, resp.Name)
	return resp, nil
}

Java

Para obtener información sobre cómo instalar y usar la biblioteca cliente del Servicio de transferencia de almacenamiento, consulta las Bibliotecas cliente del Servicio de transferencia de almacenamiento. Si deseas obtener más información, consulta la documentación de referencia de la API de Java del Servicio de transferencia de almacenamiento.

Para autenticarte en el Servicio de transferencia de almacenamiento, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

import com.google.storagetransfer.v1.proto.StorageTransferServiceClient;
import com.google.storagetransfer.v1.proto.TransferProto;
import com.google.storagetransfer.v1.proto.TransferProto.RunTransferJobRequest;
import com.google.storagetransfer.v1.proto.TransferTypes.AzureBlobStorageData;
import com.google.storagetransfer.v1.proto.TransferTypes.AzureCredentials;
import com.google.storagetransfer.v1.proto.TransferTypes.GcsData;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob.Status;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferSpec;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

public class TransferFromAzure {
  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException {
    // TODO(developer): Replace these variables before running the sample.
    // Your Google Cloud Project ID
    String projectId = "my-project-id";

    // Your Azure Storage Account name
    String azureStorageAccount = "my-azure-account";

    // The Azure source container to transfer data from
    String azureSourceContainer = "my-source-container";

    // The GCS bucket to transfer data to
    String gcsSinkBucket = "my-sink-bucket";

    transferFromAzureBlobStorage(
        projectId, azureStorageAccount, azureSourceContainer, gcsSinkBucket);
  }

  /**
   * Creates and runs a transfer job to transfer all data from an Azure container to a GCS bucket.
   */
  public static void transferFromAzureBlobStorage(
      String projectId,
      String azureStorageAccount,
      String azureSourceContainer,
      String gcsSinkBucket)
      throws IOException, ExecutionException, InterruptedException {

    // Your Azure SAS token, should be accessed via environment variable
    String azureSasToken = System.getenv("AZURE_SAS_TOKEN");

    TransferSpec transferSpec =
        TransferSpec.newBuilder()
            .setAzureBlobStorageDataSource(
                AzureBlobStorageData.newBuilder()
                    .setAzureCredentials(
                        AzureCredentials.newBuilder().setSasToken(azureSasToken).build())
                    .setContainer(azureSourceContainer)
                    .setStorageAccount(azureStorageAccount))
            .setGcsDataSink(GcsData.newBuilder().setBucketName(gcsSinkBucket).build())
            .build();

    TransferJob transferJob =
        TransferJob.newBuilder()
            .setProjectId(projectId)
            .setStatus(Status.ENABLED)
            .setTransferSpec(transferSpec)
            .build();

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources,
    // or use "try-with-close" statement to do this automatically.
    try (StorageTransferServiceClient storageTransfer = StorageTransferServiceClient.create()) {
      // Create the transfer job
      TransferJob response =
          storageTransfer.createTransferJob(
              TransferProto.CreateTransferJobRequest.newBuilder()
                  .setTransferJob(transferJob)
                  .build());

      // Run the created job
      storageTransfer
          .runTransferJobAsync(
              RunTransferJobRequest.newBuilder()
                  .setProjectId(projectId)
                  .setJobName(response.getName())
                  .build())
          .get();

      System.out.println(
          "Created and ran a transfer job from "
              + azureSourceContainer
              + " to "
              + gcsSinkBucket
              + " with "
              + "name "
              + response.getName());
    }
  }
}

Node.js

Para obtener información sobre cómo instalar y usar la biblioteca cliente del Servicio de transferencia de almacenamiento, consulta las Bibliotecas cliente del Servicio de transferencia de almacenamiento. Si deseas obtener más información, consulta la documentación de referencia de la API de Node.js del Servicio de transferencia de almacenamiento.

Para autenticarte en el Servicio de transferencia de almacenamiento, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.


// Imports the Google Cloud client library
const {
  StorageTransferServiceClient,
} = require('@google-cloud/storage-transfer');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of the Google Cloud Platform Project that owns the job
// projectId = 'my-project-id'

// A useful description for your transfer job
// description = 'My transfer job'

// Azure Storage Account name
// azureStorageAccount = 'accountname'

// Azure Storage Account name
// azureSourceContainer = 'my-azure-source-bucket'

// Azure Shared Access Signature token
// azureSASToken = '?sv=...'

// Google Cloud Storage destination bucket name
// gcsSinkBucket = 'my-gcs-destination-bucket'

// Creates a client
const client = new StorageTransferServiceClient();

/**
 * Creates a one-time transfer job from Azure Blob Storage to Google Cloud Storage.
 */
async function transferFromBlobStorage() {
  // Setting the start date and the end date as the same time creates a
  // one-time transfer
  const now = new Date();
  const oneTimeSchedule = {
    day: now.getDate(),
    month: now.getMonth() + 1,
    year: now.getFullYear(),
  };

  // Runs the request and creates the job
  const [transferJob] = await client.createTransferJob({
    transferJob: {
      projectId,
      description,
      status: 'ENABLED',
      schedule: {
        scheduleStartDate: oneTimeSchedule,
        scheduleEndDate: oneTimeSchedule,
      },
      transferSpec: {
        azureBlobStorageDataSource: {
          azureCredentials: {
            sasToken: azureSASToken,
          },
          container: azureSourceContainer,
          storageAccount: azureStorageAccount,
        },
        gcsDataSink: {
          bucketName: gcsSinkBucket,
        },
      },
    },
  });

  console.log(
    `Created and ran a transfer job from '${azureSourceContainer}' to '${gcsSinkBucket}' with name ${transferJob.name}`
  );
}

transferFromBlobStorage();

Python

Para obtener información sobre cómo instalar y usar la biblioteca cliente del Servicio de transferencia de almacenamiento, consulta las Bibliotecas cliente del Servicio de transferencia de almacenamiento. Si deseas obtener más información, consulta la documentación de referencia de la API de Python del Servicio de transferencia de almacenamiento.

Para autenticarte en el Servicio de transferencia de almacenamiento, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

from datetime import datetime

from google.cloud import storage_transfer


def create_one_time_azure_transfer(
    project_id: str,
    description: str,
    azure_storage_account: str,
    azure_sas_token: str,
    source_container: str,
    sink_bucket: str,
):
    """Creates a one-time transfer job from Azure Blob Storage to Google Cloud
    Storage."""

    # Initialize client that will be used to create storage transfer requests.
    # This client only needs to be created once, and can be reused for
    # multiple requests.
    client = storage_transfer.StorageTransferServiceClient()

    # The ID of the Google Cloud Platform Project that owns the job
    # project_id = 'my-project-id'

    # A useful description for your transfer job
    # description = 'My transfer job'

    # Azure Storage Account name
    # azure_storage_account = 'accountname'

    # Azure Shared Access Signature token
    # azure_sas_token = '?sv=...'

    # Azure Blob source container name
    # source_container = 'my-azure-source-bucket'

    # Google Cloud Storage destination bucket name
    # sink_bucket = 'my-gcs-destination-bucket'

    now = datetime.utcnow()
    # Setting the start date and the end date as
    # the same time creates a one-time transfer
    one_time_schedule = {"day": now.day, "month": now.month, "year": now.year}

    transfer_job_request = storage_transfer.CreateTransferJobRequest(
        {
            "transfer_job": {
                "project_id": project_id,
                "description": description,
                "status": storage_transfer.TransferJob.Status.ENABLED,
                "schedule": {
                    "schedule_start_date": one_time_schedule,
                    "schedule_end_date": one_time_schedule,
                },
                "transfer_spec": {
                    "azure_blob_storage_data_source": {
                        "storage_account": azure_storage_account,
                        "azure_credentials": {"sas_token": azure_sas_token},
                        "container": source_container,
                    },
                    "gcs_data_sink": {
                        "bucket_name": sink_bucket,
                    },
                },
            }
        }
    )

    result = client.create_transfer_job(transfer_job_request)
    print(f"Created transferJob: {result.name}")

Transferdesde un sistema de archivos

Consulta Cómo transferir desde un sistema de archivos a Cloud Storage.