Transfiere objetos o archivos específicos con un manifiesto

El Servicio de transferencia de almacenamiento admite la transferencia de objetos o archivos específicos, que se especifican mediante un manifiesto. Un manifiesto es un archivo CSV, subido a Cloud Storage, que contiene una lista de objetos o archivos sobre los que el Servicio de transferencia de almacenamiento debe actuar.

Se puede usar un manifiesto para las siguientes transferencias:

  • Desde AWS S3, Azure Blobstore o Cloud Storage a un bucket de Cloud Storage.

  • De un sistema de archivos a un bucket de Cloud Storage

  • Del almacenamiento compatible con S3 a un bucket de Cloud Storage.

  • De un bucket de Cloud Storage a un sistema de archivos

  • Entre dos sistemas de archivos

  • De una fuente HTTP/HTTPS de acceso público a un bucket de Cloud Storage Sigue las instrucciones que se indican en Cómo crear una lista de URLs, ya que el formato de manifiesto es único para las listas de URLs.

Cómo crear un manifiesto

Los manifiestos deben tener el formato CSV y pueden contener caracteres UTF-8. La primera columna debe ser un nombre de archivo o de objeto especificado como una cadena.

Los archivos de manifiesto no admiten comodines. El valor debe ser un archivo específico o un nombre de objeto. No se admiten nombres de carpetas sin un nombre de objeto o archivo.

El tamaño máximo del archivo de manifiesto es de 1 GiB, lo que se traduce en alrededor de 1 millón de filas. Si necesitas transferir un archivo de manifiesto con un tamaño superior a 1 GiB, puedes dividirlo en varios archivos y ejecutar varios trabajos de transferencia.

Si el nombre de un archivo o un objeto contiene comas, el nombre debe estar entre comillas dobles, según los estándares de CSV. Por ejemplo, "object1,a.txt"

Recomendamos probar tu transferencia con un pequeño subconjunto de objetos o archivos para evitar llamadas innecesarias a la API debido a errores de configuración.

Puedes supervisar el estado de las transferencias de archivos desde la página Trabajos de transferencia. Los archivos o los objetos que no se pueden transferir se muestran en los registros de transferencia.

Transferencias del sistema de archivos

Para crear un manifiesto de archivos en un sistema de archivos, crea un archivo CSV con una sola columna que contenga las rutas de acceso a los archivos en relación con el directorio raíz especificado en la creación del trabajo de transferencia.

Por ejemplo, tal vez quieras transferir los siguientes archivos del sistema de archivos:

Ruta de acceso al archivo
rootdir/dir1/subdir1/file1.txt
rootdir/file2.txt
rootdir/dir2/subdir1/file3.txt

El manifiesto debería verse como el siguiente ejemplo:

dir1/subdir1/file1.txt
file2.txt
dir2/subdir1/file3.txt

Transferencias de almacenamiento de objetos

Para crear un manifiesto de objetos, crea un archivo CSV cuya primera columna contenga los nombres de objetos relacionados con el nombre del bucket y la ruta de acceso especificadas en la creación del trabajo de transferencia. Todos los objetos deben estar en el mismo bucket.

También puedes especificar una segunda columna opcional con el número de generación de Cloud Storage de la versión específica que deseas transferir.

Por ejemplo, puede que quieras transferir los siguientes objetos:

Ruta de acceso del objeto Número de generación de Cloud Storage
SOURCE_PATH/object1.pdf 1664826685911832
SOURCE_PATH/object2.pdf
SOURCE_PATH/object3.pdf 1664826610699837

El manifiesto debería verse como el siguiente ejemplo:

object1.pdf,1664826685911832
object2.pdf
object3.pdf,1664826610699837

Guarda el archivo de manifiesto con cualquier nombre de archivo y una extensión .csv.

Transferencias HTTP/HTTPS

Para transferir archivos específicos desde una fuente HTTP o HTTPS, consulta las instrucciones en Crea una lista de URLs.

Publica el manifiesto

Una vez que hayas creado el manifiesto, debes hacer que esté disponible para el Servicio de transferencia de almacenamiento. El Servicio de transferencia de almacenamiento puede acceder al archivo en un bucket de Cloud Storage o en tu sistema de archivos.

Sube el manifiesto a Cloud Storage

Puedes almacenar el archivo de manifiesto en cualquier bucket de Cloud Storage.

El agente de servicio que ejecuta la transferencia debe tener el permiso storage.objects.get para el bucket que contiene el manifiesto. Consulta Otorga los permisos necesarios para obtener instrucciones sobre cómo encontrar el ID del agente de servicio y otorgar permisos a ese agente de servicio en un bucket.

Si quieres obtener instrucciones para subir el manifiesto a un bucket, consulta Sube objetos en la documentación de Cloud Storage.

Por ejemplo, si quieres usar la CLI de gcloud para subir un archivo a Cloud Storage, usa el comando gcloud storage cp:

gcloud storage cp MANIFEST.CSV gs://DESTINATION_BUCKET_NAME/

Aquí:

  • MANIFEST.CSV es la ruta de acceso local a tu archivo de manifiesto. Por ejemplo, Desktop/manifest01.csv

  • DESTINATION_BUCKET_NAME es el nombre del bucket al que subes el objeto. Por ejemplo, my-bucket

Si se ejecuta de forma correcta, la respuesta se parece al siguiente ejemplo:

Completed files 1/1 | 164.3kiB/164.3kiB

Puedes encriptar un manifiesto con claves de encriptación de Cloud KMS administradas por el cliente. En este caso, asegúrate de que cualquier cuenta de servicio que acceda al manifiesto tenga asignadas las claves de encriptación aplicables. No se admiten las claves que proporciona el cliente.

Almacena el manifiesto en un sistema de archivos

Puedes almacenar el archivo de manifiesto en tu sistema de archivos de origen o de destino.

Los agentes de transferencia deben poder acceder a la ubicación del archivo. Si restringes el acceso a directorios para tus agentes, asegúrate de que el archivo de manifiesto esté ubicado dentro de un directorio activado.

Cómo iniciar una transferencia

No modifiques el archivo de manifiesto hasta que se complete una operación de transferencia. Te recomendamos que bloquees el archivo de manifiesto cuando se realice una transferencia.

consola de Cloud

Para iniciar una transferencia con un manifiesto desde la consola de Cloud, sigue estos pasos:

  1. Sigue las instrucciones en Crea transferencias para seleccionar el origen, el destino y las opciones.

  2. En el paso final, Choose settings, selecciona la casilla de verificación llamada Provide list of files to transfer via manifest file.

  3. Ingresa la ubicación del archivo de manifiesto.

gcloud

Para transferir los archivos o los objetos que se enumeran en el manifiesto, incluye la marca --manifest-file=MANIFEST_FILE con el comando gcloud transfer jobs create.

gcloud transfer jobs create SOURCE DESTINATION \
  --manifest-file=MANIFEST_FILE

MANIFEST_FILE puede ser cualquiera de los siguientes valores:

  • La ruta al archivo CSV en un bucket de Cloud Storage:

    --manifest-file=gs://my_bucket/sample_manifest.csv
    

    Consulta Sube el manifiesto a Cloud Storage para obtener detalles sobre los permisos necesarios si el bucket o el archivo no es público.

  • La ruta de acceso relativa del sistema de archivos SOURCE, incluida cualquier ruta que se especificó:

    --manifest-file=source://relative_path/sample_manifest.csv
    
  • La ruta de acceso relativa del sistema de archivos DESTINATION, incluida cualquier ruta que se especificó:

    --manifest-file=destination://relative_path/sample_manifest.csv
    

Bibliotecas cliente y de REST

REST

Para transferir los objetos o archivos que se enumeran en el manifiesto, realiza una llamada a la API de createTransferJob que especifique una transferSpec con el campo transferManifest agregado. Por ejemplo:

POST https://storagetransfer.googleapis.com/v1/transferJobs

...
  "transferSpec": {
      "posixDataSource": {
          "rootDirectory": "/home/",
      },
      "gcsDataSink": {
          "bucketName": "GCS_NEARLINE_SINK_NAME",
          "path": "GCS_SINK_PATH",
      },
      "transferManifest": {
          "location": "gs://my_bucket/sample_manifest.csv"
      }
  }

El archivo de manifiesto se puede almacenar en un bucket de Cloud Storage o en el sistema de archivos de origen o de destino. Los buckets de Cloud Storage deben usar el prefijo gs:// y, además, incluir la ruta de acceso completa, incluido el nombre del bucket. Las ubicaciones del sistema de archivos deben usar un prefijo source:// o destination:// y están relacionadas con la fuente o el destino del sistema de archivos y el directorio raíz opcional.

Go


import (
	"context"
	"fmt"
	"io"

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

func transferUsingManifest(w io.Writer, projectID string, sourceAgentPoolName string, rootDirectory string, gcsSinkBucket string, manifestBucket string, manifestObjectName string) (*storagetransferpb.TransferJob, error) {
	// Your project id
	// projectId := "myproject-id"

	// The agent pool associated with the POSIX data source. If not provided, defaults to the default agent
	// sourceAgentPoolName := "projects/my-project/agentPools/transfer_service_default"

	// The root directory path on the source filesystem
	// rootDirectory := "/directory/to/transfer/source"

	// The ID of the GCS bucket to transfer data to
	// gcsSinkBucket := "my-sink-bucket"

	// The ID of the GCS bucket that contains the manifest file
	// manifestBucket := "my-manifest-bucket"

	// The name of the manifest file in manifestBucket that specifies which objects to transfer
	// manifestObjectName := "path/to/manifest.csv"

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

	manifestLocation := "gs://" + manifestBucket + "/" + manifestObjectName
	req := &storagetransferpb.CreateTransferJobRequest{
		TransferJob: &storagetransferpb.TransferJob{
			ProjectId: projectID,
			TransferSpec: &storagetransferpb.TransferSpec{
				SourceAgentPoolName: sourceAgentPoolName,
				DataSource: &storagetransferpb.TransferSpec_PosixDataSource{
					PosixDataSource: &storagetransferpb.PosixFilesystem{RootDirectory: rootDirectory},
				},
				DataSink: &storagetransferpb.TransferSpec_GcsDataSink{
					GcsDataSink: &storagetransferpb.GcsData{BucketName: gcsSinkBucket},
				},
				TransferManifest: &storagetransferpb.TransferManifest{Location: manifestLocation},
			},
			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 using manifest file %v with name %v", rootDirectory, gcsSinkBucket, manifestLocation, resp.Name)
	return resp, nil
}

Java


import com.google.storagetransfer.v1.proto.StorageTransferServiceClient;
import com.google.storagetransfer.v1.proto.TransferProto;
import com.google.storagetransfer.v1.proto.TransferTypes.GcsData;
import com.google.storagetransfer.v1.proto.TransferTypes.PosixFilesystem;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferManifest;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferSpec;
import java.io.IOException;

public class TransferUsingManifest {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.

    // Your project id
    String projectId = "my-project-id";

    // The agent pool associated with the POSIX data source. If not provided, defaults to the
    // default agent
    String sourceAgentPoolName = "projects/my-project-id/agentPools/transfer_service_default";

    // The root directory path on the source filesystem
    String rootDirectory = "/directory/to/transfer/source";

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

    // The ID of the GCS bucket which has your manifest file
    String manifestBucket = "my-bucket";

    // The ID of the object in manifestBucket that specifies which files to transfer
    String manifestObjectName = "path/to/manifest.csv";

    transferUsingManifest(
        projectId,
        sourceAgentPoolName,
        rootDirectory,
        gcsSinkBucket,
        manifestBucket,
        manifestObjectName);
  }

  public static void transferUsingManifest(
      String projectId,
      String sourceAgentPoolName,
      String rootDirectory,
      String gcsSinkBucket,
      String manifestBucket,
      String manifestObjectName)
      throws IOException {
    String manifestLocation = "gs://" + manifestBucket + "/" + manifestObjectName;
    TransferJob transferJob =
        TransferJob.newBuilder()
            .setProjectId(projectId)
            .setTransferSpec(
                TransferSpec.newBuilder()
                    .setSourceAgentPoolName(sourceAgentPoolName)
                    .setPosixDataSource(
                        PosixFilesystem.newBuilder().setRootDirectory(rootDirectory).build())
                    .setGcsDataSink((GcsData.newBuilder().setBucketName(gcsSinkBucket)).build())
                    .setTransferManifest(
                        TransferManifest.newBuilder().setLocation(manifestLocation).build()))
            .setStatus(TransferJob.Status.ENABLED)
            .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());

      System.out.println(
          "Created and ran a transfer job from "
              + rootDirectory
              + " to "
              + gcsSinkBucket
              + " using "
              + "manifest file "
              + manifestLocation
              + " with name "
              + response.getName());
    }
  }
}

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.
 */
// Your project id
// const projectId = 'my-project'

// The agent pool associated with the POSIX data source. Defaults to the default agent
// const sourceAgentPoolName = 'projects/my-project/agentPools/transfer_service_default'

// The root directory path on the source filesystem
// const rootDirectory = '/directory/to/transfer/source'

// The ID of the GCS bucket to transfer data to
// const gcsSinkBucket = 'my-sink-bucket'

// Transfer manifest location. Must be a `gs:` URL
// const manifestLocation = 'gs://my-bucket/sample_manifest.csv'

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

/**
 * Creates a request to transfer from the local file system to the sink bucket
 */
async function transferViaManifest() {
  const createRequest = {
    transferJob: {
      projectId,
      transferSpec: {
        sourceAgentPoolName,
        posixDataSource: {
          rootDirectory,
        },
        gcsDataSink: {bucketName: gcsSinkBucket},
        transferManifest: {
          location: manifestLocation,
        },
      },
      status: 'ENABLED',
    },
  };

  // Runs the request and creates the job
  const [transferJob] = await client.createTransferJob(createRequest);

  const runRequest = {
    jobName: transferJob.name,
    projectId: projectId,
  };

  await client.runTransferJob(runRequest);

  console.log(
    `Created and ran a transfer job from '${rootDirectory}' to '${gcsSinkBucket}' using manifest \`${manifestLocation}\` with name ${transferJob.name}`
  );
}

transferViaManifest();

Python

from google.cloud import storage_transfer

def create_transfer_with_manifest(
    project_id: str,
    description: str,
    source_agent_pool_name: str,
    root_directory: str,
    sink_bucket: str,
    manifest_location: str,
):
    """Create a transfer from a POSIX file system to a GCS bucket using
    a manifest file."""

    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'

    # The agent pool associated with the POSIX data source.
    # Defaults to 'projects/{project_id}/agentPools/transfer_service_default'
    # source_agent_pool_name = 'projects/my-project/agentPools/my-agent'

    # The root directory path on the source filesystem
    # root_directory = '/directory/to/transfer/source'

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

    # Transfer manifest location. Must be a `gs:` URL
    # manifest_location = 'gs://my-bucket/sample_manifest.csv'

    transfer_job_request = storage_transfer.CreateTransferJobRequest(
        {
            "transfer_job": {
                "project_id": project_id,
                "description": description,
                "status": storage_transfer.TransferJob.Status.ENABLED,
                "transfer_spec": {
                    "source_agent_pool_name": source_agent_pool_name,
                    "posix_data_source": {
                        "root_directory": root_directory,
                    },
                    "gcs_data_sink": {
                        "bucket_name": sink_bucket,
                    },
                    "transfer_manifest": {"location": manifest_location},
                },
            }
        }
    )

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

Los objetos o archivos del manifiesto no necesariamente se transfieren en el orden indicado.

Si el manifiesto incluye archivos que ya existen en el destino, esos archivos se omiten, a menos que se especifique la opción reemplazar los objetos que ya existen en el receptor.

Si el manifiesto incluye objetos que existen en una versión diferente en el destino, el objeto se reemplaza por la versión de origen. Si el destino es un bucket con control de versiones, se crea una versión nueva del objeto.

¿Qué sigue?