Tarefa da função do Cloud

A tarefa função do Cloud permite configurar e executar o Google Cloud Functions a partir de sua integração. O Google Cloud Functions é uma solução de computação leve para desenvolvedores. Ele cria funções autônomas e de finalidade única que respondem a eventos do Cloud sem a necessidade de gerenciar um servidor ou um ambiente de execução.

Para mais informações, consulte a documentação do Google Cloud Functions.

Antes de começar

Realize as seguintes tarefas no seu projeto do Google Cloud antes de configurar a tarefa da função do Cloud.

  1. Ative a API Cloud Functions (cloudfunctions.googleapis.com).

    Ativação da API Cloud Functions

  2. Atribua os seguintes papéis do IAM ao principal:
    • Administrador do Cloud Functions (roles/cloudfunctions.admin)
    • Editor do Application Integration (roles/integrations.integrationEditor)
    • Usuário da conta de serviço (roles/iam.serviceAccountUser)

    Para informações sobre como conceder papéis a principais, consulte Como conceder, alterar e revogar acesso.

  3. Para se conectar ao Cloud Functions, verifique se você criou um perfil OAuth 2.0 ou anexou uma conta de serviço gerenciada pelo usuário à sua integração:
    • Se a integração tiver uma conta de serviço anexada, atribua o papel do IAM Invocador de funções do Cloud a essa conta.

      Para informações sobre como conceder papéis a uma conta de serviço, consulte Gerenciar o acesso a contas de serviço.

    • A tarefa Cloud Function só aceita perfis de autenticação do tipo Google OIDC ID Token. Criar um perfil de autenticação do tipo Token de ID do Google OIDC usando a conta de serviço com o papel Invocador de função do Cloud do IAM atribuído. Se a tarefa Cloud Function não exigir autenticação, o campo de perfil de autenticação no painel de configuração da tarefa poderá ser deixado em branco.

    Se a integração tiver um perfil de ID do OIDC e uma conta de serviço gerenciada pelo usuário configurados, o perfil de ID do OIDC será usado para autenticação por padrão. Se nem o perfil de ID do OIDC nem a conta de serviço gerenciada pelo usuário estiverem configurados, a conta de serviço padrão (service-PROJECT_NUMBER@gcp-sa-apigee.iam.gserviceaccount.com) será usada para chamar a tarefa Cloud Function.

  4. Verifique se o VPC Service Controls NÃO está configurado para a integração da Apigee no projeto do Google Cloud.

Configurar a tarefa da função do Cloud

Para configurar a tarefa da função do Cloud na integração, execute as seguintes etapas:

  1. Na IU da Apigee, selecione sua organização da Apigee.
  2. Clique em Desenvolver > Integrações.
  3. Selecione uma integração existente ou clique em Criar integração.

    Caso você esteja criando uma nova integração, siga estas etapas:

    1. Digite um nome e uma descrição na caixa de diálogo Criar integração.
    2. Selecione uma Região para a integração na lista de regiões compatíveis.
    3. Clique em Criar.

    Isso abre a integração na página do designer de integração.

  4. Na barra de navegação do designer de integração, clique em +Adicionar uma tarefa/gatilho> Tarefas para conferir a lista de tarefas disponíveis.
  5. Clique e posicione o elemento Função do Cloud no editor de integração.
  6. Clique no elemento Cloud Function no designer para abrir o painel de configuração e clique em Configurar Cloud Function.
  7. Na caixa de diálogo Configuração da função do Cloud, escolha uma das seguintes opções:
    • Vincule a função existente. Selecione esta opção para vincular uma função do Cloud que esteja configurada na integração. Digite o URL do gatilho da função do Cloud.
    • Crie uma nova função. Selecione esta opção para criar uma nova função do Cloud associada à integração. Insira o Nome da função do Cloud e selecione a região da função na lista suspensa.
  8. Clique em Save.

    Uma função básica do Google Cloud é criada no projeto do Google Cloud e associada à sua integração. O painel de configuração da tarefa exibe o URL do gatilho e os Parâmetros da tarefa da Função do Cloud.

Modelo de função do Cloud

Ao configurar a função do Cloud usando uma função que já existe, verifique se os arquivos de origem main.py, task.py e requirements.txt da função estão no seguinte formato:

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

Editar uma tarefa da função do Cloud

A configuração de uma tarefa da função do Cloud na integração da Apigee cria uma função do Cloud básica acionada por HTTP no seu projeto do Google Cloud.

Para editar uma tarefa do Cloud Functions, siga estas etapas:

  1. No painel de configuração da tarefa, clique em Abrir a Função do Cloud.

    Você será redirecionado para a página Detalhes da função no Console do Google Cloud.

  2. Clique em Editar.
  3. Na página Configuração, é possível editar as configurações padrão da função do Cloud. Consulte Como configurar o Cloud Functions para mais informações.
  4. Clique em Avançar para editar os arquivos de código-fonte da função do Cloud.

    Por padrão, a função do Cloud contém os seguintes arquivos de origem:

    • main.py : esse arquivo contém o código de inicialização para executar a função do Cloud a partir da integração.
    • Task.py : esse arquivo contém o código executável da função do Cloud. Escreva o script dentro da função run(event). Essa função é chamada quando a tarefa da função do Cloud é executada. O objeto event do arquivo main.py contém todos os parâmetros da tarefa.

      Consulte Acessar variáveis de integração para saber como usar as variáveis definidas no nível da integração no script.

  5. Clique em Deploy.

Acessar variáveis de integração

Para acessar uma variável de integração na função do Cloud, passe a variável na forma de parâmetros de tarefa para a tarefa da função do Cloud. Os parâmetros da tarefa são pares de chave-valor, em que Chave é o nome da variável de referência usada no arquivo de origem da função do Cloud, e Valor é o nome da variável de integração correspondente que a referência aponta para. É possível adicionar um ou mais parâmetros de tarefa na seção Parâmetros de tarefa do painel de configuração da tarefa.

Os métodos a seguir são usados para acessar variáveis de integração da função do Cloud:

  • set - Grava o valor como uma variável.
  • get - Lê o valor de uma variável.

Por exemplo, se você tiver uma variável de integração chamada EmployeeName que queira usar no arquivo de origem da função do Cloud, defina os seguintes parâmetros de tarefa:

  • Chave: EmployeeKey
  • Valor: EmployeeName

O exemplo de script a seguir mostra o uso de funções "set" e "get" para acessar as variáveis de integração definidas.

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

Estratégia de solução de erros

A estratégia de solução de erros para uma tarefa especifica a ação a ser realizada se a tarefa falhar devido a um erro temporário. Para mais informações sobre como usar uma estratégia de tratamento de erros e conhecer os diferentes tipos de estratégias de tratamento de erros, consulte Estratégias de tratamento de erros.