建立自動化

建立和部署應用程式和自動化函數。

建立 Oracle Functions 應用程式

應用程式是函數的邏輯群組,可讓您配置和設定整個群組的資源,以及在程式實際執行時隔離函數。

在建立應用程式之前,您必須先針對函數開發設定租用戶,並且必須設定函數開發環境。

當您在 Oracle Functions 中定義應用程式時,您可以指定要在其中執行應用程式中函數的子網路。您也可以指定是否啟用應用程式中函數的記錄日誌。

  1. 以函數開發人員身分登入主控台。
  2. 在「主控台」中,開啟導覽功能表。前往解決方案和平台底下的開發人員服務,然後按一下功能
  3. 選取您搭配 Oracle Functions 使用的區域。Oracle 建議您使用與 Fn 專案 CLI 相關資訊環境中指定之 Docker 登錄檔相同的區域。
  4. 選取 Fn 專案 CLI 相關資訊環境中指定的區間。「應用程式」頁面會顯示區間中已經定義的應用程式。
  5. 按一下建立應用程式,然後指定:
    • 名稱:新應用程式的名稱。請避免輸入機密資訊。
    • VCN 和子網路:要在其中執行功能的 VCN 和子網路。
  6. 按一下建立

    新的應用程式會出現在應用程式清單中。

建立及部署自動化函數

在應用程式 ocijsonpub 中建立、部署及設定函數 loadziptojson

  1. 起始函數:
     fn init --runtime python loadziptojson

    系統會使用您指定的函數名稱建立一個目錄,其中包含 func.pyfunc.yaml 以及 requirements.txt 檔案。func.yaml 檔案包含建立和執行函數所需的最小資訊量。

  2. 開啟 func.py 並以下列程式碼區塊取代內容:
    1. 匯入必要的 Python 模組:
      import io
      import json
      import oci
      import csv
      import requests
      import traceback
      from io import StringIO
      from io import BytesIO
       
      from zipfile import ZipFile, is_zipfile
      from fdk import responsecode
    2. 定義函數處理程式以解壓縮檔案,並在上傳檔案至物件儲存時插入 JSON 資料庫:
      def handler(ctx, data: io.BytesIO=None):
          signer = oci.auth.signers.get_resource_principals_signer()
       
          object_name = bucket_name = namespace = ordsbaseurl = schema = dbuser = dbpwd = ""
          try:
              cfg = ctx.Config()
              input_bucket = cfg["inputbucket"]
              processed_bucket = cfg["processedbucket"]
              ordsbaseurl = cfg["ordsbaseurl"]
              schema = cfg["dbschema"]
              dbuser = cfg["dbuser"]
              dbpwd = cfg["dbpwd"]
          except Exception as e:
              print('Missing function parameters: bucket_name, ordsbaseurl, schema, dbuser, dbpwd', flush=True)
              raise
          try:
              body = json.loads(data.getvalue())
              object_name = body["data"]["resourceName"]
              if body["data"]["additionalDetails"]["bucketName"] != input_bucket:
                  raise ValueError("Event Bucket name error")
              namespace = body["data"]["additionalDetails"]["namespace"]
          except Exception as e:
              print('ERROR: bad Event!', flush=True)
              raise
          try:   
              insert_status = load_data(signer, namespace, input_bucket, object_name, ordsbaseurl, schema, dbuser, dbpwd)
              #move_object(signer, namespace, input_bucket, processed_bucket, object_name)
       
              return response.Response(
                 ctx,
                 response_data=json.dumps(insert_status),
                 headers={"Content-Type": "application/json"}
              )
          except Exception as e:
              return response.Response(
                  ctx, response_data=json.dumps([{'Error': traceback.format_exc()}
                                                , ]),
                  headers={"Content-Type": "application/json"}
              )
    3. 定義處理程式函數呼叫以解壓縮檔案的資料載入函數、讀取 zip 檔案中的 csv 檔案,以及逐行迴圈以呼叫 soda_insert 函數。
      def load_data(signer, namespace, bucket_name, object_name, ordsbaseurl, schema, dbuser, dbpwd):
          client = oci.object_storage.ObjectStorageClient(config={}, signer=signer)
          zipfile = client.get_object(namespace, bucket_name, object_name)
          insert_status = {}
       
          if zipfile.status == 200:
             print("INFO - Object {0} is read".format(object_name), flush=True)
             #object_storage_client.get_object
       
             with ZipFile(BytesIO(zipfile.data.content)) as zippy:
                for item in zippy.infolist():
                   print(item.filename, flush=True)
                   try:
                       if not 'MACOS' in item.filename and 'csv' in item.filename:
                          csvdata = csv.DictReader(zippy.read(item.filename).decode('utf-8').split('\n'),delimiter=',')
                          for row in csvdata:
                             insert_status = soda_insert(ordsbaseurl, schema, dbuser, dbpwd, dict(row))
                   except Exception:
                       print('trouble decoding the file ', flush=True)
                       continue
        
              
          else:
               raise SystemExit("cannot retrieve the object" + str(object_name))
          return insert_status
    4. 定義建立集合並將資料插入集合的插入函數。
      def soda_insert(ordsbaseurl, schema, dbuser, dbpwd, document):
         
          auth=(dbuser, dbpwd)
          sodaurl = ordsbaseurl + schema + '/soda/latest/'
          collectionurl = sodaurl + "censusdata"
       
          headers = {'Content-Type': 'application/json'}
          print("INFO - calling SODA with requests:", flush=True)
          print("INFO - before calling SODA :dbuser : "+dbuser, flush=True)
          print("INFO - before calling SODA :dbpwd : "+dbpwd, flush=True)
          reqjson={}
          r = requests.put(collectionurl, auth=auth, headers=headers, data=reqjson)
          print("INFO - before calling SODA :document : "+json.dumps(document), flush=True)
          i = requests.post(collectionurl, auth=auth, headers=headers, data=json.dumps(document))
       
          r_json = {}
          r_json = json.dumps(r.text)
          return r_json
  3. 開啟 func.yaml 並以下列項目取代內容:
    schema_version: 20180708
    name: loadziptojson
    version: 0.0.31
    runtime: python
    entrypoint: /python/bin/fdk /function/func.py handler
    memory: 256
  4. 開啟 requirements.txt 並以下列項目取代內容:
    fdk
    oci
    requests
  5. 輸入下列單一 Fn 專案命令,將函數及其相依性建置為 Docker 映像檔、將映像檔植入指定的 Docker 登錄檔,然後在指定的應用程式中將函數建置到 Oracle Functions
    fn -v deploy --app ocijsonpub
  6. 使用下列格式設定函數參數:
    $ fn config function <application_name> <function_name> --<property> <value>

    例如,使用下列敘述句設定函數 ocijsonpub,並以下列指示替代必要的值:

    #Autonomous Database schema
    fn config function ocijsonpub loadziptojson dbschema <db_schema>
    #Autonomous Database Username
    fn config function ocijsonpub loadziptojson dbuser <db_user_name>
    #Autonomous Database password
    fn config function ocijsonpub loadziptojson dbpwd <db_password>
    # Object storage bucket for input file
    fn config function ocijsonpub loadziptojson inputbucket <input_files_bucket>
    # Object storage bucket to archive the zip file after processing
    fn config function ocijsonpub loadziptojson processedbucket <processed_files_bucket>