Como criar um cliente do Storage Transfer Service para uma biblioteca de APIs do Google

Antes de fazer solicitações ao Serviço de transferência do Cloud Storage, verifique se a API Storage Transfer Service está ativada no seu projeto e se seu aplicativo está configurado para autorização, usando o protocolo OAuth 2.0 (em inglês). Recomendamos que você também implemente a espera exponencial truncada para lidar com tentativas de repetição em caso de falhas de solicitação.

Como ativar o serviço

Para acessar o Serviço de transferência do Cloud Storage usando uma biblioteca de APIs Google ou diretamente usando a API Storage Transfer Service, é necessário ativar a API Google Storage Transfer.

Ative a Google Storage Transfer API.

Ative a API

Fluxo de autenticação

Como todas as operações do Storage Transfer Service ocorrem sem a necessidade de intervenção humana ou consentimento do usuário, o melhor fluxo de autenticação para um aplicativo do Storage Transfer Service é de servidor para servidor, usando uma conta de serviço. O App Engine e o Compute Engine têm contas de serviço integradas que podem ser usadas. Também é possível criar uma credencial de serviço no Console do Google Cloud.

Quando você usa uma conta de serviço, as bibliotecas de cliente de APIs do Google lidam com o processo de autenticação e autorização nos seguintes cenários:

Aplicativo do App Engine

Se o aplicativo for executado no App Engine, ele será autenticado com a conta de serviço padrão do aplicativo do App Engine.

O código também funciona com o emulador local do App Engine, desde que você use o SDK do Cloud (mvn gcloud:run). Para isso, use uma conta de serviço e configure a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS.

Para mais informações, consulte a seção Host local ou de terceiros.

Aplicativo do Compute Engine

Se o aplicativo for executado em uma instância do Compute Engine, ele será autenticado usando a conta de serviço padrão do Compute Engine associada ao projeto.

Configure a instância para usar contas de serviço e inclua o escopo listado na seção Escopo de autorização.

Para mais informações, consulte Como configurar o escopo do acesso à conta de serviço para instâncias na documentação do Compute Engine.

Host local ou de terceiros

Se você estiver executando um cliente local ou o programa em um ambiente que não seja do Google Cloud, crie uma nova conta de serviço, faça o download do arquivo de chave JSON e defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS para indicar o arquivo de chave JSON.

Para mais informações, consulte Autenticação como uma conta de serviço.

Escopo de autorização

Os aplicativos que acessam o Serviço de transferência do Cloud Storage usando o OAuth 2.0 precisam especificar o escopo de autorização cloud-platform.

Escopo Significado
https://www.googleapis.com/auth/cloud-platform Acesso total.

Criar um cliente

É possível usar o código de amostra abaixo para criar um cliente do Serviço de transferência do Cloud Storage em qualquer um dos ambientes discutidos no Fluxo de autenticação. Como o código usa Google Application Default Credentials, ele seleciona a conta de serviço apropriada para uso.

É preciso atribuir um dos seguintes papéis à conta de serviço:

Para verificar, acesse a página de permissões do seu projeto.

Java

Neste exemplo, usamos a biblioteca de cliente de APIs do Google para Java. A classe RetryHttpInitializerWrapper personalizada está descrita na seção Manipulação de repetição.


package com.google.cloud.storage.storagetransfer.samples;

import com.google.api.client.googleapis.util.Utils;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.services.storagetransfer.v1.Storagetransfer;
import com.google.api.services.storagetransfer.v1.StoragetransferScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.base.Preconditions;
import java.io.IOException;

/** Create a client to make calls to Storage Transfer API. */
public final class TransferClientCreator {

  /**
   * Create a Storage Transfer client using application default credentials and other default
   * settings.
   *
   * @return a Storage Transfer client
   * @throws IOException there was an error obtaining application default credentials
   */
  public static Storagetransfer createStorageTransferClient() throws IOException {
    HttpTransport httpTransport = Utils.getDefaultTransport();
    JsonFactory jsonFactory = Utils.getDefaultJsonFactory();
    GoogleCredentials credential = GoogleCredentials.getApplicationDefault();
    return createStorageTransferClient(httpTransport, jsonFactory, credential);
  }

  /**
   * Create a Storage Transfer client using user-supplied credentials and other settings.
   *
   * @param httpTransport a user-supplied HttpTransport
   * @param jsonFactory a user-supplied JsonFactory
   * @param credential a user-supplied Google credential
   * @return a Storage Transfer client
   */
  public static Storagetransfer createStorageTransferClient(
      HttpTransport httpTransport, JsonFactory jsonFactory, GoogleCredentials credential) {
    Preconditions.checkNotNull(httpTransport);
    Preconditions.checkNotNull(jsonFactory);
    Preconditions.checkNotNull(credential);

    // In some cases, you need to add the scope explicitly.
    if (credential.createScopedRequired()) {
      credential = credential.createScoped(StoragetransferScopes.all());
    }
    // Please use custom HttpRequestInitializer for automatic
    // retry upon failures. We provide a simple reference
    // implementation in the "Retry Handling" section.
    HttpRequestInitializer initializer = new HttpCredentialsAdapter(credential);
    return new Storagetransfer.Builder(httpTransport, jsonFactory, initializer)
        .setApplicationName("storagetransfer-sample")
        .build();
  }
}

Python

Neste exemplo, usamos a biblioteca de cliente de APIs do Google para Python.

import googleapiclient.discovery

def create_transfer_client():
    return googleapiclient.discovery.build('storagetransfer', 'v1')

Manipulação de repetição

Nesse caso de falhas de RPC, implemente o código para lidar com tentativas de repetição com uma estratégia de espera exponencial truncada.

Java

Neste exemplo, usamos a biblioteca de cliente de APIs do Google para Java. A classe RetryHttpInitializerWrapper manipula as tentativas de repetição para você.


package com.google.cloud.storage.storagetransfer.samples;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.http.HttpBackOffIOExceptionHandler;
import com.google.api.client.http.HttpBackOffUnsuccessfulResponseHandler;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpUnsuccessfulResponseHandler;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.client.util.Sleeper;
import com.google.common.base.Preconditions;
import java.io.IOException;
import java.util.logging.Logger;

/**
 * RetryHttpInitializerWrapper will automatically retry upon RPC failures, preserving the
 * auto-refresh behavior of the Google Credentials.
 */
public class RetryHttpInitializerWrapper implements HttpRequestInitializer {

  private static final Logger LOG = Logger.getLogger(RetryHttpInitializerWrapper.class.getName());
  private final Credential wrappedCredential;
  private final Sleeper sleeper;
  private static final int MILLIS_PER_MINUTE = 60 * 1000;

  /**
   * A constructor using the default Sleeper.
   *
   * @param wrappedCredential the credential used to authenticate with a Google Cloud Platform
   *     project
   */
  public RetryHttpInitializerWrapper(Credential wrappedCredential) {
    this(wrappedCredential, Sleeper.DEFAULT);
  }

  /**
   * A constructor used only for testing.
   *
   * @param wrappedCredential the credential used to authenticate with a Google Cloud Platform
   *     project
   * @param sleeper a user-supplied Sleeper
   */
  RetryHttpInitializerWrapper(Credential wrappedCredential, Sleeper sleeper) {
    this.wrappedCredential = Preconditions.checkNotNull(wrappedCredential);
    this.sleeper = sleeper;
  }

  /**
   * Initialize an HttpRequest.
   *
   * @param request an HttpRequest that should be initialized
   */
  public void initialize(HttpRequest request) {
    request.setReadTimeout(2 * MILLIS_PER_MINUTE); // 2 minutes read timeout
    final HttpUnsuccessfulResponseHandler backoffHandler =
        new HttpBackOffUnsuccessfulResponseHandler(new ExponentialBackOff()).setSleeper(sleeper);
    request.setInterceptor(wrappedCredential);
    request.setUnsuccessfulResponseHandler(
        new HttpUnsuccessfulResponseHandler() {
          public boolean handleResponse(
              final HttpRequest request, final HttpResponse response, final boolean supportsRetry)
              throws IOException {
            if (wrappedCredential.handleResponse(request, response, supportsRetry)) {
              // If credential decides it can handle it, the return code or message indicated
              // something specific to authentication, and no backoff is desired.
              return true;
            } else if (backoffHandler.handleResponse(request, response, supportsRetry)) {
              // Otherwise, we defer to the judgement of our internal backoff handler.
              LOG.info("Retrying " + request.getUrl().toString());
              return true;
            } else {
              return false;
            }
          }
        });
    request.setIOExceptionHandler(
        new HttpBackOffIOExceptionHandler(new ExponentialBackOff()).setSleeper(sleeper));
  }
}

Python

É possível passar o argumento num_retries=n para o método execute da biblioteca para repetição com retirada exponencial em caso de falhas que podem ser repetidas.


        resp = client.projects().subscriptions().pull(
        subscription=subscription, body=body).execute(num_retries=3)