注意:

使用 Oracle Cloud Native Framework 为成本分析报表设置基于事件的自动电子邮件通知

简介

在云上运行工作负载的每个组织都非常热衷于了解他们在云上的成本支出,并希望以有意义的方式报告工作负载。为此,Oracle Cloud Infrastructure (OCI) 提供了一个功能,您可以基于成本创建自动报告,然后在 OCI 对象存储中获取这些报告。

对于这些成本报告,团队还希望设置自动化,以便相应的团队在生成报告后立即收到通知。为此,他们还希望将报告链接作为通知的一部分。您可以使用 Oracle Cloud Native Framework 设置所有这些自动化。

目标

先决条件

任务 1:设置必需的 OCI IAM 策略和动态组

  1. 登录到 OCI 控制台,转到动态组并创建新的动态组。

    创建动态组

  2. 在规则 1 中输入区间 OCID。您的 OCI 函数应存在于同一区间中。

    设置动态组

  3. 转到 OCI IAM 策略并使用以下语句创建策略。

    allow dynamic-group dynamic_group_name to manage ons-family in compartment compartment_name
    
    allow dynamic-group dynamic_group_name to manage object-family in compartment compartment_name
    

    注:

    • 请根据您的用例使用更具体的 IAM 策略。请参阅以下示例:

      • allow dynamic-group dynamic_group_name to use ons-topics in compartment compartment_name where request.operation = 'PublishMessage'
      • allow dynamic-group dynamic_group_name to manage buckets in compartment compartment_name where all {request.operation = 'CreatePreauthenticatedRequest', target.bucket.name = 'bucket_name'}

任务 2:设置 OCI 对象存储桶并创建调度的报告

  1. 使用 OCI 控制台创建存储桶。我们将使用此存储桶推送报告。请确保您创建的存储桶是专用的,因为这样可以确保您的内容免受公共访问的安全,并且在此存储桶上启用了发出对象事件,因为这样可以在推送新对象时发出事件。

    创建存储桶

  2. 转至成本管理、计划报表,然后创建计划报表。输入名称、说明、开始日期和循环。

    创建已调度报告

    选择要将报表发布到的存储桶。要从下拉菜单中选择存储桶,必须添加策略,如下图中所示,以便计量服务可以访问创建的存储桶。

    创建已调度报告

  3. 创建存储桶和调度的报表后,您可以查看已执行报表的历史记录,还可以看到报表发布到所选 OCI 对象存储桶。

    历史记录计划报告

任务 3:创建 OCI 通知主题并添加订阅

  1. 创建发送电子邮件通知所需的 OCI 通知主题。转到通知、主题并创建主题。

    创建话题

  2. 在同一主题中创建订阅并添加通知将发送到的电子邮件。

    创建订阅

    现在,OCI 通知主题已配置。

任务 4:创建和部署函数代码

转到函数/应用程序并创建函数。当事件触发该函数时,此函数将使用 OCI IAM 动态组和策略来访问 OCI 对象存储存储桶并执行所需的操作(为调度的报告文件创建 PAR URL 并随之发送通知)。

有多种方法可用于开发 OCI 函数,并提供快速入门指南,引导您使用 OCI Cloud Shell、OCI 虚拟机或本地运行来设置开发环境。本指南其余部分中的图像将显示 OCI Cloud Shell,但其中任何方法都有效。我们使用 Python 编写所需的逻辑代码,但是你可以使用另一种语言,并根据需要更改逻辑。

  1. 要编写代码,请在 OCI Cloud Shell 中打开 requirement.txt 和 func.py 文件。

    部署函数

  2. 以下是函数代码,它使用 OCI 资源主体,因此您不必保留 OCI 身份证明。请记住替换您创作的变量,例如存储桶名称、主题 OCID 等。

    • requirements.txt.

      fdk>=0.1.71
      oci>=2.112.0
      
    • func.yaml.

      schema_version: 20180708
      name: reportsauto
      version: 0.0.6
      runtime: python
      build_image: fnproject/python:3.11-dev
      run_image: fnproject/python:3.11
      entrypoint: /python/bin/fdk /function/func.py handler
      memory: 256
      
    • func.py.

      import io
      import json
      import logging
      import oci
      from datetime import datetime
      
      from fdk import response
      
      
      def handler(ctx, data: io.BytesIO = None):
          try:
              body = json.loads(data.getvalue())
              logging.getLogger().info(body.get("eventType"))
              logging.getLogger().info(body.get("data").get("resourceName"))
          except (Exception, ValueError) as ex:
              logging.getLogger().info('error parsing json payload: ' + str(ex))
      
          logging.getLogger().info("Inside Python Hello World function")
          initiateFn(body.get("data").get("resourceName"))
          return response.Response(
              ctx, response_data=json.dumps(
                  {"message": "Function Executed!"}),
              headers={"Content-Type": "application/json"}
          )
      
      def initiateFn(uploaded_file):
          logging.getLogger().info("Reached initiate function...")
      
          signer = oci.auth.signers.get_resource_principals_signer()
          object_storage_client = oci.object_storage.ObjectStorageClient(config={}, signer=signer)
          namespace_name="orasenatdplt01"
          bucket_name="demobucket"
      
          now = datetime.now()
          par_name = "PAR_Request_" + str(now).split('.')[0].replace(" ", "_").replace(":", "_").replace("-", "_")
          create_preauthenticated_request_response = object_storage_client.create_preauthenticated_request(
              namespace_name=namespace_name,
              bucket_name=bucket_name,
              create_preauthenticated_request_details=oci.object_storage.models.CreatePreauthenticatedRequestDetails(
                  name=par_name,
                  access_type="ObjectRead",
                  time_expires=datetime.strptime(
                      "2037-06-05T04:25:22.344Z",
                      "%Y-%m-%dT%H:%M:%S.%fZ"),
                  object_name=uploaded_file))
      
          callNotificationAPI(create_preauthenticated_request_response.data)
      
      # Function to call Notification API as soon as an object push is detected
      def callNotificationAPI(parData):
          logging.getLogger().info("Trigger notification as object push is detected...")
          topicOcid = "ocid1.onstopic.oc1.iad.amaaaaxxxxxxxxxamn4"
          signer = oci.auth.signers.get_resource_principals_signer()
          ons_client = oci.ons.NotificationDataPlaneClient(config={}, signer=signer)
          publish_message_response = ons_client.publish_message(
              topic_id=topicOcid,
              message_details=oci.ons.models.MessageDetails(
                  body="OCI Notification Service - Cost Report File is created: " + str(parData.full_path),
                  title="OCI Notification Service - Cost Report File is created"),
              message_type="RAW_TEXT")
          logging.getLogger().info("Triggered notification as object push is detected...")
      
  3. 在 OCI Cloud Shell 上使用以下命令更新注册表中的函数并部署最新代码。

    fn -v deploy — app reportsauto
    
  4. 部署后,即可调用函数。您可以尝试使用函数调用命令进行测试,并确保该函数根据需要工作。

    DEBUG=1 fn invoke reportsauto your_app_name
    

    注:

    • OCI 支持资源/实例主体,以避免在执行函数时提供任何用户相关信息。因此,需要执行此任务以确保函数具有调用 API 的正确权限集,否则函数将无法正常工作。

    • (可选)您还可以检查调试模式以进行故障排除。例如:从 OCI Cloud Shell 运行以下命令,以便在函数按预期工作时调用和测试函数。

      DEBUG=1 fn invoke e2e-function-demo e2e-fn-streaming
      

任务 5:设置 OCI 事件规则

  1. 转到 OCI 控制台,单击应用集成、事件服务、规则和创建事件规则。输入规则条件并添加在任务 4 中创建的函数作为触发器操作。

  2. 输入显示名称和说明。

    创建事件规则

  3. 在规则条件部分中,选择第一个条件作为事件类型、对象存储、对象 - 创建,选择另一个条件作为属性、bucketName 、demoBucket 。

    定义事件规则

  4. 通过操作部分将事件与函数连接。选择函数区间、函数应用程序和任务 4 中部署的函数。

    事件规则目标

  5. 单击保存更改以保存事件规则。当条件与 OCI 对象存储桶中发出的事件匹配时,这将调用函数。

确认

更多学习资源

浏览 docs.oracle.com/learn 上的其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心。