自動化の作成

アプリケーションおよび自動化機能を作成してデプロイします。

Oracle Functionsアプリケーションの作成

アプリケーションは、グループ全体のリソースの割当てと構成、および実行時の関数の分離を可能にする関数の論理グループです。

アプリケーションを作成する前に、ファンクション開発用のテナンシを設定し、ファンクション開発環境を設定する必要があります。

Oracle Functionsでアプリケーションを定義する場合、アプリケーションでファンクションを実行するサブネットを指定します。また、アプリケーションのファンクションのロギングを有効にするかどうかも指定します。

  1. ファンクション開発者としてコンソールにログインします。
  2. コンソールで、ナビゲーション・メニューを開きます。「ソリューションおよびプラットフォーム」で、「開発者サービス」に移動して「関数」をクリックします。
  3. Oracle Functionsで使用するリージョンを選択します。Oracleでは、Fn ProjectのCLIコンテキストで指定されているDockerレジストリと同じリージョンを使用することをお薦めします。
  4. Fn Projectの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 Projectコマンドを入力して、ファンクションとその依存性を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>