Créer un client de service de transfert de stockage pour une bibliothèque d'API Google

Pour pouvoir adresser des requêtes au service de transfert de stockage, vous devez vérifier, à l'aide du protocole OAuth 2.0, que l'API du service de transfert de stockage est bien activée pour votre projet et que votre application est configurée pour les autorisations. Nous vous recommandons également de mettre en œuvre un intervalle exponentiel entre les tentatives tronqué en cas d'échec de la requête.

Activer le service

Pour accéder au service de transfert de stockage via une bibliothèque d'API Google ou directement à l'aide de l'API du service de transfert de stockage, vous devez activer cette API.

Activez Google Storage Transfer API.

Activer l'API

Flux d'authentification

Étant donné que toutes les opérations du service de transfert de stockage ne nécessitent ni intervention humaine ni consentement de l'utilisateur, le flux d'authentification le plus adapté à une application du service de transfert de stockage s'effectue de serveur à serveur, à l'aide d'un compte de service. App Engine et Compute Engine disposent de comptes de service intégrés que vous pouvez utiliser. Vous pouvez également créer un identifiant de service dans Google Cloud Console.

Lorsque vous utilisez un compte de service, les bibliothèques clientes des API Google se chargent d'exécuter le processus d'authentification et d'autorisation dans les scénarios suivants :

Application App Engine

Si votre application s'exécute sur App Engine, elle s'authentifie avec le compte de service par défaut de votre application App Engine.

Ce code fonctionne également avec votre émulateur local App Engine tant que vous utilisez le SDK Cloud (mvn gcloud:run), à l'aide d'un compte de service et en définissant la variable d'environnement GOOGLE_APPLICATION_CREDENTIALS.

Pour plus d'informations, consultez la section Hôte local ou tiers.

Application Compute Engine

Si votre application s'exécute sur une instance Compute Engine, elle s'authentifie à l'aide du compte de service Compute Engine par défaut associé au projet.

Configurez votre instance pour qu'elle utilise des comptes de service et ajoutez le champ d'application répertorié dans la section Champ d'application des autorisations.

Pour plus d'informations, consultez la section Définir le champ d'application de l'accès au compte de service pour les instances dans la documentation de Compute Engine.

Hôte local ou tiers

Si vous exécutez un client local ou un programme dans un environnement autre que Google Cloud, créez un compte de service, téléchargez son fichier de clé JSON, puis définissez la variable d'environnement GOOGLE_APPLICATION_CREDENTIALS de sorte qu'elle pointe vers le fichier de clé JSON.

Pour en savoir plus, consultez la section Authentification en tant que compte de service.

Champ d'application des autorisations

Les applications qui accèdent au service de transfert de stockage via le protocole OAuth 2.0 doivent spécifier le champ d'application des autorisations cloud-platform.

Portée Signification
https://www.googleapis.com/auth/cloud-platform Accès complet

Créer un client

Vous pouvez utiliser l'exemple de code ci-dessous pour créer un client de service de transfert de stockage dans l'un des environnements décrits dans la section Flux d'authentification. Étant donné que le code utilise les Identifiants par défaut de l'application Google, il sélectionne le compte de service approprié à utiliser.

Le compte de service doit disposer de l'un des rôles suivants :

Pour vérifier vos autorisations, accédez à la page Autorisations de votre projet.

Java

Cet exemple utilise la bibliothèque cliente des API Google pour Java. La classe personnalisée RetryHttpInitializerWrapper est décrite dans la section Gérer les tentatives.


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

Cet exemple utilise la bibliothèque cliente des API Google pour Python.

import googleapiclient.discovery

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

Gérer les tentatives

Dans le cas d'échecs RPC, vous devez mettre en œuvre le code permettant de gérer les tentatives en définissant un intervalle exponentiel entre les tentatives tronqué.

Java

Cet exemple utilise la bibliothèque cliente des API Google pour Java. La classe RetryHttpInitializerWrapper gère les nouvelles tentatives pour vous.


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

Vous pouvez transmettre l'argument num_retries=n à la méthode execute de la bibliothèque pour qu'elle réessaie d'exécuter le code en fonction d'un intervalle exponentiel entre les tentatives, en cas d'échecs récupérables.


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