Tugas Cloud Function

Tugas Cloud Function memungkinkan Anda mengonfigurasi dan menjalankan Google Cloud Functions dari integrasi Anda. Google Cloud Functions adalah komputasi ringan bagi developer untuk membuat tujuan tunggal, fungsi mandiri yang merespons peristiwa Cloud tanpa perlu pengelolaan server atau lingkungan runtime.

Untuk mengetahui informasi selengkapnya, baca dokumentasi Google Cloud Functions.

Sebelum memulai

Pastikan Anda melakukan tugas berikut di project Google Cloud sebelum mengonfigurasi tugas Cloud Function.

  1. Aktifkan Cloud Functions API (cloudfunctions.googleapis.com).

    Mengaktifkan Cloud Functions API

  2. Tetapkan peran IAM berikut ke akun utama Anda:
    • Admin Cloud Functions (roles/cloudfunctions.admin)
    • Editor Integrasi Aplikasi (roles/integrations.integrationEditor)
    • (roles/iam.serviceAccountUser) Pengguna Akun Layanan

    Untuk mengetahui informasi tentang cara memberikan peran kepada akun utama, lihat Memberikan, mengubah, dan mencabut akses.

  3. Agar terhubung ke fungsi Cloud Run, pastikan Anda telah membuat profil OAuth 2.0 atau melampirkan akun layanan yang dikelola pengguna ke integrasi Anda:
    • Jika integrasi Anda memiliki akun layanan yang terlampir, tetapkan peran IAM Cloud Function Invoker ke akun layanan tersebut.

      Untuk mengetahui informasi tentang cara memberikan peran ke akun layanan, lihat Mengelola akses ke akun layanan.

    • Tugas Cloud Function hanya mendukung profil autentikasi jenis Google OIDC ID Token. Buat profil autentikasi jenis Google OIDC ID Token menggunakan akun layanan dengan peran IAM Cloud Function Invoker yang ditetapkan. Jika tugas Cloud Function Anda tidak memerlukan autentikasi, kolom Authentication profile di panel konfigurasi tugas dapat dibiarkan kosong.

    Jika integrasi Anda memiliki profil OIDC ID dan akun layanan yang dikelola pengguna yang sudah dikonfigurasi, profil OIDC ID akan digunakan secara default untuk autentikasi. Jika profil OIDC ID atau akun layanan yang dikelola pengguna tidak dikonfigurasi, akun layanan default (service-PROJECT_NUMBER@gcp-sa-apigee.) digunakan untuk memanggil tugas Cloud Function.

  4. Pastikan Kontrol Layanan VPC BUKAN disiapkan untuk Integrasi Apigee di project Google Cloud.

Mengonfigurasi tugas Cloud Function

Untuk mengonfigurasi tugas Cloud Function dalam integrasi Anda: lakukan langkah-langkah berikut:

  1. Di UI Apigee, pilih Organisasi Apigee Anda.
  2. Klik Develop > Integrasi.
  3. Pilih integrasi yang ada atau buat integrasi baru dengan mengklik Buat Integrasi.

    Jika Anda membuat integrasi baru:

    1. Masukkan nama dan deskripsi dalam dialog Create Integration.
    2. Pilih Region untuk integrasi dari daftar wilayah yang didukung.
    3. Klik Create.

    Tindakan ini akan membuka integrasi di desainer integrasi.

  4. Di menu navigasi desainer integrasi, klik +Tambahkan tugas/pemicu > Tasks untuk melihat daftar tugas yang tersedia.
  5. Klik dan tempatkan elemen Cloud Function ke editor integrasi.
  6. Klik elemen Cloud Function pada desainer untuk buka panel konfigurasi, lalu klik Konfigurasikan Cloud Function.
  7. Pada dialog Cloud Function Configuration, pilih salah satu hal berikut:
    • Tautkan fungsi yang ada. Pilih opsi ini untuk menautkan Cloud Function yang ada yang dikonfigurasi dalam integrasi. Masukkan URL Pemicu Cloud Function.
    • Buat fungsi baru. Pilih opsi ini untuk membuat Cloud Function baru yang terkait dengan integrasi. Masukkan Cloud Function Name dan pilih function region dari daftar {i>drop-down<i}.
  8. Klik Simpan.

    Fungsi Google Cloud dasar dibuat di project Google Cloud Anda dan dikaitkan dengan integrasi Anda. Panel konfigurasi tugas menampilkan URL Pemicu dan Parameter Tugas dari dan Cloud Function.

Template Cloud function

Saat mengonfigurasi Cloud Function menggunakan Cloud function yang ada, pastikan file sumber main.py, task.py, dan requirements.txt fungsi menggunakan format berikut:

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

Mengedit tugas Cloud Function

Mengonfigurasi tugas Cloud Function di Integrasi Apigee akan membuat permintaan HTTP dasar memicu Cloud Function di project Google Cloud Anda.

Untuk mengedit tugas Cloud Function, lakukan langkah-langkah berikut:

  1. Di panel konfigurasi tugas, klik Open Cloud Function.

    Anda akan dialihkan ke halaman Function details di Google Cloud Console.

  2. Klik Edit.
  3. Halaman Configuration memungkinkan Anda mengedit setelan konfigurasi default Cloud Function. Lihat Mengonfigurasi Cloud Functions untuk mengetahui informasi selengkapnya.
  4. Klik Next untuk mengedit file kode sumber Cloud Function.

    Secara default, Cloud Function berisi file sumber berikut:

    • main.py : File ini berisi kode inisialisasi untuk menjalankan Cloud Function dari integrasi Anda.
    • task.py : File ini berisi kode Cloud Function yang dapat dieksekusi. Tulis skrip Anda di dalam fungsi run(event). Fungsi ini dipanggil saat tugas Cloud Function dieksekusi. Objek event dari file main.py berisi semua parameter tugas.

      Lihat Mengakses variabel integrasi untuk mendapatkan informasi tentang cara menggunakan variabel yang ditentukan pada tingkat integrasi dalam skrip Anda.

  5. Klik Deploy.

Mengakses variabel integrasi

Untuk mengakses variabel integrasi di Cloud Function, Anda harus meneruskan variabel dalam bentuk parameter tugas Anda ke tugas Cloud Function. Parameter tugas adalah pasangan nilai kunci dengan Kunci adalah nama variabel referensi yang digunakan dalam file sumber Cloud Function Anda dan Nilai adalah nama variabel integrasi terkait yang ditunjuk oleh variabel referensi. Anda dapat menambahkan satu atau beberapa parameter tugas di bagian Parameter Tugas pada panel konfigurasi tugas.

Metode berikut digunakan untuk mengakses variabel integrasi dari Cloud Function Anda:

  • set: Menulis nilai ke variabel.
  • get: Membaca nilai variabel.

Misalnya, jika Anda memiliki variabel integrasi bernama EmployeeName yang ingin digunakan di file sumber Cloud Function, tentukan parameter tugas berikut:

  • Kunci: EmployeeKey
  • Nilai: EmployeeName

Contoh skrip berikut menunjukkan penggunaan fungsi set dan get untuk mengakses variabel integrasi yang ditentukan.

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

Strategi penanganan error

Strategi penanganan error untuk tugas menentukan tindakan yang akan diambil jika tugas gagal karena error sementara. Untuk informasi tentang cara menggunakan strategi penanganan error, dan mengetahui berbagai jenis strategi penanganan error, lihat Strategi penanganan error.