Transferir arquivos ou objetos específicos usando um manifesto

O Serviço de transferência do Cloud Storage é compatível com arquivos ou objetos específicos, que são especificados usando um manifesto. Um manifesto é um arquivo CSV enviado ao Cloud Storage que contém uma lista de arquivos ou objetos para o Serviço de transferência do Cloud Storage.

Um manifesto pode ser usado para as seguintes transferências:

  • Do AWS S3, Azure Blobstore ou Cloud Storage para um bucket do Cloud Storage.

  • De um sistema de arquivos para um bucket do Cloud Storage.

  • Do armazenamento compatível com S3 para um bucket do Cloud Storage.

  • De um bucket do Cloud Storage para um sistema de arquivos.

  • Entre dois sistemas de arquivos.

  • De uma origem HTTP/HTTPS publicamente acessível a um bucket do Cloud Storage. Siga as instruções em Criar uma lista de URLs, já que o formato do manifesto é exclusivo para listas de URLs.

Criar um manifesto

Os manifestos precisam ser formatados como CSV e podem conter qualquer caractere UTF-8. A primeira coluna precisa ser um nome de arquivo ou de objeto especificado como uma string.

Os arquivos de manifesto não são compatíveis com caracteres curinga. O valor precisa ser um nome de arquivo ou de objeto específico. Nomes de pastas sem nome de arquivo ou de objeto não são compatíveis.

O tamanho máximo do arquivo de manifesto é de 1 GiB, o que equivale a aproximadamente 1 milhão de linhas. Se você precisar transferir um arquivo de manifesto maior que 1 GiB, será possível dividi-lo em vários arquivos e executar vários jobs de transferência.

Se o nome de um arquivo ou objeto tiver vírgulas, o nome precisa estar entre aspas duplas, de acordo com os padrões CSV. Por exemplo, "object1,a.txt".

Recomendamos testar a transferência com um pequeno subconjunto de arquivos ou objetos para evitar chamadas de API desnecessárias devido a erros de configuração.

É possível monitorar o status das transferências na página de jobs de transferência. Os arquivos ou objetos que não são transferidos são listados nos registros de transferência.

Transferências do sistema de arquivos

Para criar um manifesto de arquivos em um sistemas, crie um arquivo CSV com uma única coluna contendo os caminhos dos arquivos em relação ao diretório raiz especificado na criação do job de transferência.

Por exemplo, talvez você queira transferir os seguintes arquivos do sistema:

Caminho do arquivo
rootdir/dir1/subdir1/file1.txt
rootdir/file2.txt
rootdir/dir2/subdir1/file3.txt

Seu manifesto vai ser semelhante ao exemplo a seguir:

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

Transferências de armazenamento de objetos

Para criar um manifesto de objetos, crie um arquivo CSV em que a primeira coluna contenha os nomes de objetos em relação ao nome do bucket e caminho especificados na criação do job de transferência. Todos os objetos precisam estar no mesmo bucket.

Também é possível especificar uma segunda coluna opcional com o número de geração do Cloud Storage da versão específica a ser transferida.

Por exemplo, talvez você queira transferir os seguintes objetos:

Caminho do objeto Número de geração do Cloud Storage
SOURCE_PATH/object1.pdf 1664826685911832
SOURCE_PATH/object2.pdf
SOURCE_PATH/object3.pdf 1664826610699837

Seu manifesto vai ser semelhante ao exemplo a seguir:

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

Salve o arquivo de manifesto com qualquer nome de arquivo e uma extensão .csv.

Transferências HTTP/HTTPS

Para transferir arquivos específicos de uma origem HTTP ou HTTPS, consulte as instruções em Criar uma lista de URLs.

Publicar o manifesto

Depois de criar o manifesto, disponibilize-o para o Serviço de transferência do Cloud Storage. O Serviço de transferência do Cloud Storage pode acessar o arquivo em um bucket do Cloud Storage ou no sistema de arquivos.

Fazer upload do manifesto para o Cloud Storage

Você pode armazenar o arquivo de manifesto em qualquer bucket do Cloud Storage.

O agente de serviço que executa a transferência precisa ter a permissão storage.objects.get para o bucket que contém o manifesto. Consulte Conceder as permissões necessárias para ver instruções sobre como encontrar o ID do agente de serviço e conceder permissões a esse agente de serviço em um bucket.

Para ver instruções sobre como fazer upload do manifesto para um bucket, consulte Fazer upload de objetos na documentação do Cloud Storage.

Por exemplo, para usar a CLI gcloud para fazer upload de um arquivo para o Cloud Storage, use o comando gcloud storage cp:

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

Em que:

  • MANIFEST.CSV é o caminho local para o arquivo de manifesto. Por exemplo, Desktop/manifest01.csv.

  • DESTINATION_BUCKET_NAME é o nome do bucket de upload do objeto. Por exemplo, my-bucket.

Se funcionar, a resposta será parecida com esta:

Completed files 1/1 | 164.3kiB/164.3kiB

Criptografe um manifesto usando as chaves de criptografia do Cloud KMS gerenciadas pelo cliente. Nesse caso, verifique se todas as contas de serviço que acessam o manifesto receberam chaves de criptografia correspondentes. Não há suporte para chaves fornecidas pelo cliente.

Armazenar o manifesto em um sistema de arquivos

Você pode armazenar o arquivo de manifesto no sistema de arquivos de origem ou de destino.

O local do arquivo precisa ser acessível aos agentes de transferência. Se você restringir o acesso ao diretório para seus agentes, verifique se o arquivo de manifesto está localizado em um diretório montado.

Iniciar uma transferência

Não modifique o arquivo de manifesto até que uma operação de transferência seja concluída. Recomendamos bloquear o arquivo de manifesto quando uma transferência estiver em andamento.

Console do Cloud

Para iniciar uma transferência com um manifesto do Console do Cloud:

  1. Siga as instruções em Criar transferências para selecionar a origem, o destino e as opções.

  2. Na etapa final, Escolher configurações, marque a caixa de seleção Fornecer lista de arquivos a serem transferidos por arquivo de manifesto.

  3. Digite o local do arquivo de manifesto.

gcloud

Para transferir os arquivos ou objetos listados no manifesto, inclua a sinalização --manifest-file=MANIFEST_FILE com o comando gcloud transfer jobs create.

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

MANIFEST_FILE pode ser qualquer um dos seguintes valores:

  • O caminho para o arquivo CSV em um bucket do Cloud Storage:

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

    Consulte Fazer upload do manifesto para o Cloud Storage para ver detalhes sobre as permissões necessárias, se o bucket ou arquivo não for público.

  • O caminho relativo do sistema de arquivos SOURCE, incluindo qualquer caminho especificado:

    --manifest-file=source://relative_path/sample_manifest.csv
    
  • O caminho relativo do sistema de arquivos DESTINATION, incluindo qualquer caminho especificado:

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

REST + bibliotecas de cliente

REST

Para transferir os arquivos ou objetos listados no manifesto, faça uma chamada de API createTransferJob que especifique um transferSpec com o campo transferManifest adicionado. Exemplo:

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"
      }
  }

O arquivo de manifesto pode ser armazenado em um bucket do Cloud Storage ou no sistema de arquivos de origem ou de destino. Os buckets do Cloud Storage precisam usar o prefixo gs:// e incluir o caminho completo, incluindo o nome do bucket. Os locais do sistema de arquivos precisam usar um prefixo source:// ou destination:// e são relativos à origem ou ao destino do sistema de arquivos e ao diretório raiz 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}")

Os objetos ou arquivos do manifesto não são necessariamente transferidos na ordem listada.

Se o manifesto incluir arquivos que já existem no destino, eles serão ignorados, a menos que a opção substituir objetos que já existem no coletor seja especificada.

Se o manifesto incluir objetos que existem em uma versão diferente no destino, o objeto do destino vai ser substituído pela versão de origem do objeto. Se o destino for um bucket com controle de versão, vai ser criada uma nova versão do objeto.

A seguir