マニフェストを使用して特定のファイルまたはオブジェクトを転送する

Storage Transfer Service では、特定のファイルまたはオブジェクトの転送がサポートされています。これらのファイルは、マニフェストを使用して指定します。マニフェストは、Cloud Storage にアップロードされる CSV ファイルです。このファイルには、Storage Transfer Service が処理するファイルまたはオブジェクトのリストが含まれています。

マニフェストは次の転送に使用できます。

  • AWS S3、Azure Blobstore、または Cloud Storage から Cloud Storage バケット。

  • ファイル システムから Cloud Storage バケット。

  • S3 互換ストレージから Cloud Storage バケット。

  • Cloud Storage バケットからファイル システム。

  • 2 つのファイル システム間。

  • 一般公開されている HTTP / HTTPS ソースから Cloud Storage バケット。マニフェストの形式は URL リストに固有なため、URL リストを作成するの手順に沿って操作します。

マニフェストを作成する

マニフェストは CSV 形式にする必要があります。また、UTF-8 文字を含めることができます。最初の列は、文字列として指定されたファイル名またはオブジェクト名にする必要があります。

マニフェスト ファイルはワイルドカードをサポートしていません。値は特定のファイル名またはオブジェクト名にする必要があります。ファイル名またはオブジェクト名のないフォルダ名はサポートされていません。

マニフェスト ファイルの最大サイズは 1 GiB で、約 100 万行に相当します。1 GiB を超えるマニフェスト ファイルを転送する必要がある場合は、ファイルを複数のファイルに分割し、複数の転送ジョブを実行します。

ファイル名やオブジェクト名にカンマが含まれている場合は、CSV の標準に従って、名前を二重引用符で囲む必要があります。例: "object1,a.txt"

構成エラーによる不要な API 呼び出しを避けるため、少数のファイルまたはオブジェクトで転送をテストすることをおすすめします。

ファイル転送のステータスは、転送ジョブのページでモニタリングできます。転送に失敗したファイルまたはオブジェクトは転送ログに記録されます。

ファイル システム転送

ファイル システム上のファイルのマニフェストを作成するには、1 列の CSV ファイルを作成し、その列に転送ジョブの作成で指定したルート ディレクトリからの相対ファイルパスを記述します。

たとえば、次のファイル システム ファイルを転送するとします。

ファイルパス
rootdir/dir1/subdir1/file1.txt
rootdir/file2.txt
rootdir/dir2/subdir1/file3.txt

マニフェストは次のようになります。

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

オブジェクト ストレージ転送

オブジェクトのマニフェストを作成するには、最初の列にオブジェクト名を含む CSV ファイルを作成します。オブジェクト名は、転送ジョブの作成時に指定したバケット名とパスに対する相対名で記述します。すべてのオブジェクトは同じバケット内に存在する必要があります。

オプションの 2 列目に、転送する特定のバージョンの Cloud Storage 世代番号を指定することもできます。

たとえば、次のオブジェクトを転送するとします。

オブジェクト パス Cloud Storage の世代番号
SOURCE_PATH/object1.pdf 1664826685911832
SOURCE_PATH/object2.pdf
SOURCE_PATH/object3.pdf 1664826610699837

マニフェストは次のようになります。

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

マニフェスト ファイルを任意のファイル名と .csv 拡張子で保存します。

HTTP / HTTPS 転送

特定のファイルを HTTP または HTTPS ソースから転送するには、URL リストを作成するの手順をご覧ください。

マニフェストを公開する

マニフェストを作成したら、Storage Transfer Service で使用できるようにする必要があります。Storage Transfer Service は、Cloud Storage バケットまたはファイル システムのファイルにアクセスできます。

マニフェストを Cloud Storage にアップロードする

マニフェスト ファイルは任意の Cloud Storage バケットに格納できます。

転送を実行するサービス エージェントには、マニフェストを含むバケットに対する storage.objects.get 権限が必要です。サービス エージェント ID を見つけて、そのサービス エージェントにバケットに対する権限を付与する方法については、必要な権限の付与をご覧ください。

マニフェストをバケットにアップロードする手順については、Cloud Storage ドキュメントのオブジェクトをアップロードするをご覧ください。

たとえば、gcloud CLI を使用して Cloud Storage にファイルをアップロードするには、gcloud storage cp コマンドを使用します。

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

ここで

  • MANIFEST.CSV は、マニフェスト ファイルのローカルパスです。例: Desktop/manifest01.csv

  • DESTINATION_BUCKET_NAME は、オブジェクトをアップロードするバケットの名前です。例: my-bucket

成功した場合は、次の例のようなレスポンスになります。

Completed files 1/1 | 164.3kiB/164.3kiB

マニフェストは、顧客管理の Cloud KMS 暗号鍵を使用して暗号化できます。暗号化を行う場合は、マニフェストにアクセスするサービス アカウントに該当する暗号鍵が割り当てられていることを確認してください。顧客指定の暗号鍵はサポートされていません。

マニフェストをファイル システムに保存する

マニフェスト ファイルは、転送元または転送先のファイル システムに保存できます。

転送エージェントがアクセス可能な場所にする必要があります。エージェントのディレクトリ アクセスを制限する場合は、マウントされたディレクトリ内にマニフェスト ファイルがあることを確認してください。

転送を開始する

転送オペレーションが完了するまで、マニフェスト ファイルを変更しないでください。転送が行われている間は、マニフェスト ファイルをロックすることをおすすめします。

Cloud コンソール

Cloud コンソールからマニフェストを使用して転送を開始するには:

  1. 転送を作成するの手順に沿って、転送元、転送先、オプションを選択します。

  2. 最後のステップ [設定の選択] で、[マニフェスト ファイルを介して転送するファイルのリストを指定する] チェックボックスをオンにします。

  3. マニフェスト ファイルの場所を入力します。

gcloud

マニフェストに記述されているファイルまたはオブジェクトを転送するには、gcloud transfer jobs create コマンドで --manifest-file=MANIFEST_FILE フラグを指定します。

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

MANIFEST_FILE には次のいずれかの値を指定できます。

  • Cloud Storage バケット内の CSV ファイルのパス。

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

    必要な権限がバケットやファイルが公開されていない場合は、マニフェストを Cloud Storage にアップロードするをご覧ください。

  • ファイル システム SOURCE からの相対パス(指定されたパスを含む):

    --manifest-file=source://relative_path/sample_manifest.csv
    
  • ファイル システム DESTINATION からの相対パス(指定されたパスを含む):

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

REST + クライアント ライブラリ

REST

マニフェストに記述されているファイルまたはオブジェクトを転送するには、transferManifest フィールドを追加して transferSpec を指定し、createTransferJob API 呼び出しを行います。例:

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

マニフェスト ファイルは、Cloud Storage バケットに格納することも、転送元または転送先の宛先ファイル システムに格納することもできます。Cloud Storage バケットの場合は、gs:// 接頭辞を使用し、バケット名を含むフルパスを含める必要があります。ファイル システムの場所の場合は、source:// または destination:// 接頭辞を使用します。これらの場所は、ファイル システムの転送元または転送先、およびオプションのルート ディレクトリからの相対位置になります。

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

マニフェスト内のオブジェクトとファイルは、記述された順序で転送されるとは限りません。

転送先にすでに存在しているファイルがマニフェストに含まれている場合、[overwrite objects already existing in sink] オプションを指定しない限り、そのファイルはスキップされます。

マニフェストに記述されたオブジェクトの別のバージョンが宛先に存在する場合、宛先にあるオブジェクトが転送元のオブジェクトのバージョンで上書きされます。宛先がバージョニングされたバケットの場合は、オブジェクトの新しいバージョンが作成されます。

次のステップ