创建自动化

创建和部署应用程序和自动化功能。

创建 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.yamlrequirements.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>