Tâche Cloud Functions

La tâche Cloud Functions vous permet de configurer et d'exécuter des fonctions Google Cloud à partir de votre intégration. Google Cloud Functions est une solution de calcul légère permettant aux développeurs de créer des fonctions autonomes à usage spécifique qui répondent aux événements Cloud, sans avoir à gérer de serveur ni d'environnement d'exécution.

Pour en savoir plus, consultez la documentation sur Google Cloud Functions.

Avant de commencer

Assurez-vous d'effectuer les tâches suivantes dans votre projet Google Cloud avant de configurer la tâche Cloud Functions.

  1. Activez l'API Cloud Functions (cloudfunctions.googleapis.com).

    Activer l'API Cloud Functions

  2. Attribuez les rôles IAM suivants à votre compte principal :
    • Administrateur Cloud Functions (roles/cloudfunctions.admin)
    • Éditeur Application Integration (roles/integrations.integrationEditor)
    • Utilisateur du compte de service (roles/iam.serviceAccountUser)

    Pour plus d'informations sur l'attribution de rôles aux comptes principaux, consultez la page Accorder, modifier et révoquer les accès.

  3. Pour vous connecter aux fonctions Cloud Run, assurez-vous d'avoir créé un profil OAuth 2.0 ou d'avoir associé un compte de service géré par l'utilisateur à votre intégration :
    • Si un compte de service est associé à votre intégration, attribuez le rôle IAM Demandeur Cloud Functions à ce compte de service.

      Pour en savoir plus sur l'attribution d'un rôle à un compte de service, consultez la page Gérer l'accès aux comptes de service.

    • La tâche Cloud Functions n'accepte que les profils d'authentification de type Jeton d'ID Google OIDC. Créez un profil d'authentification de type Jeton d'ID Google OIDC à l'aide du compte de service auquel le rôle IAM Demandeur Cloud Functions est attribué. Si votre tâche Cloud Functions ne nécessite pas d'authentification, le champ Profil d'authentification du volet de configuration de la tâche peut être vide.

    Si le profil d'ID OIDC et un compte de service géré par l'utilisateur sont tous deux configurés pour votre intégration, le profil d'ID OIDC est utilisé par défaut pour l'authentification. Lorsqu'aucun des deux n'est configuré, le compte de service par défaut (service-PROJECT_NUMBER@gcp-sa-apigee.iam.gserviceaccount.com) est utilisé pour appeler la tâche Cloud Functions.

  4. Assurez-vous que VPC Service Controls n'est PAS configuré pour Apigee Integration dans votre projet Google Cloud.

Configurer la tâche Cloud Functions

Pour configurer la tâche Cloud Functions dans votre intégration, procédez comme suit :

  1. Dans l'interface utilisateur Apigee, sélectionnez votre organisation Apigee.
  2. Cliquez sur Développer > Intégrations.
  3. Sélectionnez une intégration existante ou créez-en une en cliquant sur Créer une intégration.

    Si vous créez une intégration :

    1. Saisissez un nom et une description dans la boîte de dialogue Créer une intégration.
    2. Dans la liste des régions compatibles, sélectionnez une région pour l'intégration.
    3. Cliquez sur Créer.

    La page de conception d'intégration s'affiche.

  4. Dans la barre de navigation de la page de conception d'intégration, cliquez sur +Ajouter une tâche ou un déclencheur > Tâches pour afficher la liste des tâches disponibles.
  5. Cliquez sur l'élément Fonction Cloud et placez-le dans l'éditeur d'intégrations.
  6. Cliquez sur l'élément Cloud Function dans l'éditeur pour ouvrir le volet de configuration, puis cliquez sur Configuration de la fonction Cloud.
  7. Dans la boîte de dialogue Cloud Function Configuration (Configuration de la fonction Cloud), choisissez l'une des options suivantes :
    • Associer une fonction existante. Sélectionnez cette option pour associer une fonction Cloud existante configurée dans l'intégration. Saisissez l'URL du déclencheur de la fonction Cloud.
    • Créer une fonction. Sélectionnez cette option pour créer une fonction Cloud associée à l'intégration. Saisissez le nom de la fonction Cloud, puis sélectionnez la région de la fonction dans la liste déroulante.
  8. Cliquez sur Enregistrer.

    Une fonction Google Cloud de base est créée dans votre projet Google Cloud et associée à votre intégration. Le volet de configuration de la tâche affiche l'URL du déclencheur et les paramètres de tâche de la fonction Cloud.

Modèle de fonction Cloud

Lorsque vous configurez une fonction Cloud dans une fonction Cloud existante, assurez-vous que les fichiers source main.py, task.py et requirements.txt de la fonction sont au format suivant :

task.py

  # Sample Code:
  # print(event.get('task_string_key'))
  # event.set('task_int_array_key', [456, 789]);
  # event.log('some logging')
  
  def run(event):
    """Actual cloud function custom logic.
    Args:
      event : event object in main.py that contains all parameters.
    """
    return     

main.py

  """Un-editable platform wrapper which invokes user code."""
import traceback

from flask import json
from flask import jsonify
from task import run

VALUE_NAME = [
    'stringValue', 'intValue', 'doubleValue', 'booleanValue', 'protoValue'
]
ARRAY_VALUE_NAME = {
    'stringArray': 'stringValues',
    'intArray': 'intValues',
    'doubleArray': 'doubleValues',
    'booleanArray': 'booleanValues',
    'protoArray': 'protoValues'
}
VALUE_TYPE_URL = 'type.googleapis.com/google.protobuf.Value'
CLOUD_FUNCTION_EXCEPTION_KEY = 'CloudFunctionException'
CLOUD_FUNCTION_LOGGING_KEY = 'CloudFunctionLogging'


class _Event(object):
  """Event object."""

  def __init__(self, json_payload):
    self._event_params = json_payload.get('eventParameters', dict())
    self._task_params = json_payload.get('taskParameters', dict())
    self._log = []
    print('Event param is ' + str(self._event_params))
    print('Task param is ' + str(self._task_params))

  def set(self, key, value):
    """Set the event parameters key-value.

    Args:
      key: parameter key.
      value: parameter value.
    """
    new_param = self._create_param(key, value)
    param = self._get_param_by_key(key)
    if param is None:
      if 'parameters' not in self._event_params:
        self._event_params['parameters'] = []
      self._event_params['parameters'].append(new_param)
    else:
      param['value'] = new_param['value']

  def _create_param(self, key, value):
    """Create a new parameter with given key value pair.

    Args:
      key: parameter key.
      value: parameter value.

    Returns:
      parameter.
    """
    new_param = {}
    new_param['key'] = key
    if isinstance(value, str):
      new_param['value'] = {'stringValue': value}
    elif isinstance(value, int):
      new_param['value'] = {'intValue': value}
    elif isinstance(value, float):
      new_param['value'] = {'doubleValue': value}
    elif isinstance(value, bool):
      new_param['value'] = {'booleanValue': value}
    elif isinstance(value, dict):
      if 'type@' in value:
        new_param['value'] = {'protoValue': value}
      else:
        new_param['value'] = {
            'protoValue': {
                '@type': 'type.googleapis.com/google.protobuf.Value',
                'value': value
            }
        }
    elif isinstance(value, list):
      if not value:
        raise RuntimeError('Cannot create a param with empty list')
      if any(not isinstance(val, type(value[0])) for val in value):
        print('Not all elements in the list have the same type')
        new_param['value'] = {
            'protoValue': {
                '@type': 'type.googleapis.com/google.protobuf.Value',
                'value': value
            }
        }
      elif isinstance(value[0], str):
        new_param['value'] = {'stringArray': {'stringValues': value}}
      elif isinstance(value[0], int):
        new_param['value'] = {'intArray': {'intValues': value}}
      elif isinstance(value[0], float):
        new_param['value'] = {'doubleArray': {'doubleValues': value}}
      elif isinstance(value[0], bool):
        new_param['value'] = {'booleanArray': {'booleanValues': value}}
      elif isinstance(value[0], dict):
        if all('@type' in val and val['@type'] == value[0]['@type']
               for val in value):
          new_param['value'] = {'protoArray': {'protoValues': value}}
        else:
          new_param['value'] = {
              'protoValue': {
                  '@type': 'type.googleapis.com/google.protobuf.Value',
                  'value': value
              }
          }
      else:
        raise RuntimeError('The type ' + type(value[0]) +
                           ' in the list is not supported')
    else:
      raise RuntimeError('Value ' + str(value) + ' has the type ' +
                         type(value) + ' that is not supported')
    return new_param

  def get(self, key):
    """Get the event parameter value for specified key.

    Args:
      key: parameter key.

    Returns:
      Parameter value.
    """
    param = self._get_param_by_key(key)
    if param is None:
      raise RuntimeError('Can not find param with key ' + key)
    return self._get_param_value(param)

  def _get_param_by_key(self, key):
    """Get the parameter for specified key.

    Args:
      key: parameter key.

    Returns:
      Parameter.
    """
    param = self._get_param_by_key_from_params(key, self._task_params)
    if param is None:
      return self._get_param_by_key_from_params(key, self._event_params)
    value = self._get_param_value(param)
    if isinstance(value, str) and len(value) > 2 and value.startswith(
        '$') and value.endswith('$'):
      return self._get_param_by_key_from_params(value[1:-1], self._event_params)
    return param

  def _get_param_by_key_from_params(self, key, params):
    """Get the parameter for specified key from event parameters.

    Args:
      key: parameter key.
      params: event parameters.

    Returns:
      Parameter.
    """
    if not isinstance(params, dict) or 'parameters' not in params:
      return None
    for param in params['parameters']:
      if param['key'] == key:
        return param
    return None

  def _get_param_value(self, param):
    """Get the parameter value for specified parameter.

    Args:
      param: parameter.

    Returns:
      Parameter value.
    """
    value = param['value']
    if len(value) != 1:
      raise RuntimeError('param does not have size of 1')
    for value_name in VALUE_NAME:
      if value_name in value:
        if value_name == 'protoValue' and value[value_name][
            '@type'] == VALUE_TYPE_URL:
          return value[value_name]['value']
        return value[value_name]
    for array_value_name in ARRAY_VALUE_NAME:
      if array_value_name in value:
        return value[array_value_name][ARRAY_VALUE_NAME[array_value_name]]
    raise RuntimeError('Cannot get value from param ' + str(param))

  def set_error(self):
    """Set the cloud function error to event parameters in order for user to see on IP."""

    self.set(CLOUD_FUNCTION_EXCEPTION_KEY, traceback.format_exc())

  def log(self, message):
    self._log.append(str(message))

  def get_response(self):
    """Get the response that can be returned to IP.

    Returns:
      The response text or any set of values that can be turned into a
      Response object using
      `make_response
      <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
    """
    if self._log:
      self.set(CLOUD_FUNCTION_LOGGING_KEY, self._log)
    res = {
        'eventParameters': self._event_params,
    }
    return jsonify(**json.loads(json.htmlsafe_dumps(res)))


def execute_function(request):
  """Entry point of the cloud function.

  Args:
    request (flask.Request): HTTP request object.

  Returns:
    The response text or any set of values that can be turned into a
    Response object using
    `make_response
    <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
  """
  try:
    request_json = request.get_json(silent=True)
    event = _Event(request_json)
    run(event)
  except:
    event.set_error()
  return event.get_response()

requirements.txt

# Function dependencies, for example:
# package>=version

Modifier une tâche Cloud Functions

La configuration d'une tâche Cloud Functions dans Apigee Integration permet de créer une fonction Cloud de base déclenchée par HTTP dans votre projet Google Cloud.

Pour modifier une tâche Cloud Functions, procédez comme suit :

  1. Dans le volet de configuration de la tâche, cliquez sur Open Cloud Function (Ouvrir une fonction Cloud).

    Vous êtes redirigé vers la page Informations sur la fonction de Google Cloud Console.

  2. Cliquez sur Modifier.
  3. La page Configuration vous permet de modifier les paramètres de configuration par défaut de la fonction Cloud. Pour en savoir plus, consultez la page Configurer Cloud Functions.
  4. Cliquez sur Suivant pour modifier les fichiers de code source de la fonction Cloud.

    Par défaut, la fonction Cloud contient les fichiers sources suivants :

    • main.py : ce fichier contient le code d'initialisation permettant d'exécuter la fonction Cloud à partir de votre intégration.
    • task.py : ce fichier contient le code exécutable de la fonction Cloud. Écrivez votre script dans la fonction run(event). Cette fonction est appelée lors de l'exécution de la tâche Cloud Functions. L'objet event du fichier main.py contient tous les paramètres de la tâche.

      Consultez la section Accéder aux variables d'intégration pour en savoir plus sur l'utilisation des variables définies au niveau de l'intégration dans votre script.

  5. Cliquez sur Déployer.

Accéder aux variables d'intégration

Pour accéder à une variable d'intégration dans votre fonction Cloud, vous devez la transmettre sous la forme de paramètres de tâche à la tâche Cloud Function. Les paramètres de tâche sont des paires clé/valeur où Key est le nom de la variable de référence utilisée dans le fichier source de votre fonction Cloud et Value est le nom de la variable d'intégration correspondante vers laquelle pointe la variable de référence. Vous pouvez ajouter un ou plusieurs paramètres de tâche dans la section Paramètres de tâche du volet de configuration de la tâche.

Les méthodes suivantes permettent d'accéder aux variables d'intégration à partir de votre fonction Cloud :

  • set : écrit la valeur dans une variable.
  • get : lit la valeur d'une variable.

Par exemple, si vous souhaitez utiliser une variable d'intégration nommée EmployeeName dans le fichier source de votre fonction Cloud, définissez les paramètres de tâche suivants :

  • Key (Clé) : EmployeeKey
  • Valeur : EmployeeName

L'exemple de script suivant montre comment utiliser des fonctions "set" et "get" pour accéder aux variables d'intégration définies.

def run(event):
  # Read the integration variable EmployeeName using the reference variable EmployeeKey
  value = event.get('EmployeeKey');
  # Change the integration variable EmployeeName value using the reference variable EmployeeKey
  newValue = event.set('EmployeeKey' , 'XYZ');
  # The new value of the integration variable is retained throughout the Cloud Function task.
  return

Stratégie de traitement des erreurs

Une stratégie de traitement des erreurs d'une tâche spécifie l'action à effectuer si celle-ci échoue en raison d'une erreur temporaire. Pour en savoir plus sur l'utilisation et les différents types de stratégies de traitement des erreurs, consultez la page Stratégies de traitement des erreurs.