注意:

设置 Oracle Cloud Infrastructure Functions 以使用电子邮件发送成本使用情况报告

简介

可以根据需求自定义成本使用情况报告,也可以创建计划成本使用情况报告。根据计划,报告将被提取并保存在选定的 Oracle Cloud Infrastructure (OCI) 对象存储桶中。

要使用电子邮件发送此报告,我们需要部署 OCI Functions。将根据在 OCI 中创建的事件规则触发 OCI 函数。每当文件存储在存储桶中时,对象上载事件都会触发函数,OCI Functions 将自动为对象创建预先验证的请求 URL。此 URL 将通过电子邮件发送。

可以通过 OCI Email Delivery 服务或 OCI Notifications 服务接收电子邮件。本教程对这两种配置进行了说明。

目标

先决条件

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

  1. 登录到 OCI 控制台。有关详细信息,请参阅登录到 Oracle Cloud

  2. 转到 OCI IAM 动态组并使用以下规则创建新的动态组。

    创建动态组

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

    allow dynamic-group dynamicgroup_name to manage buckets in compartment CompartmentName where all {target.bucket.name='bucket_name'}
    
    allow dynamic-group dynamicgroup_name to manage objects in compartment CompartmentName where all {target.bucket.name='bucket_name'}
    
    Allow service metering_overlay to manage objects in compartment CompartmentName where all {target.bucket.name='bucket_name', any {request.permission='OBJECT_CREATE', request.permission='OBJECT_DELETE', request.permission='OBJECT_READ'}}
    

    要使用 OCI 通知服务发送电子邮件,需要在 OCI IAM 策略中添加以下语句才能访问 OCI 通知主题

    allow dynamic-group dynamicgroup_name to use ons-topics in compartment CompartmentName
    

任务 2:创建计划成本使用报表

  1. 转至开单和成本管理,然后选择成本管理。在成本分析下创建您自己的自定义成本使用情况报表,然后单击应用以保存报表。

    创建成本报表

  2. 单击计划报表并使用存储桶信息创建新的计划报表。您可以根据您的要求安排此项工作。

    创建已调度报告

    根据计划,报告将自动保存在给定 OCI 对象存储桶中。

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

  1. 要创建应用程序,请转到开发人员服务,单击应用程序并在可用网络中创建应用程序。

  2. 转到 functions/applications 并创建函数。此函数将使用 OCI IAM 动态组和策略来访问事件。按照屏幕上的步骤创建函数。我们使用 Python 编写所需的逻辑代码,但您可以使用自己的语言,并根据需要更改逻辑。要编写代码,请在 OCI Cloud Shell 中打开函数 requirement.txt 文件和 func.py 文件并编写代码。

    在 Cloud Shell 和代码编辑器中创建函数

  3. 复制 func.py 中的以下 Python 代码和 requirement.txt 文件中的文本文件。

    • func.py:

      • 使用 OCI 电子邮件传送:

        注:添加相应的电子邮件 ID 和简单邮件传输协议 (Simple Mail Transfer Protocol,SMTP) 详细信息。

        import oci
        import json
        import io
        import logging
        import smtplib
        from os.path import basename
        from email.mime.application import MIMEApplication
        from email.mime.multipart import MIMEMultipart
        from email.mime.text import MIMEText
        from email.utils import COMMASPACE, formatdate
        from datetime import datetime
        import ssl
        import email.utils
        from email.message import EmailMessage
        
        def handler(ctx, data: io.BytesIO = None):
           funDataStr = data.read().decode('utf-8')
        
        #Convert the log data to json
           funData =  json.loads(funDataStr)
        
        #Set up OCI configuration using resource principal
           signer = oci.auth.signers.get_resource_principals_signer()
        #Create Object Storage client
           object_storage_client = oci.object_storage.ObjectStorageClient({},signer=signer)
        
        # Extract object details from the event
           object_name = funData['data']['resourceName']
           namespace = funData['data']['additionalDetails']['namespace']
           bucket_name = funData['data']['additionalDetails']['bucketName']
        # Download the object
        #get_object_response = object_storage_client.get_object(namespace, bucket_name, object_name)
        #object_content = str(get_object_response.data.text)
           create_preauthenticated_request_response = object_storage_client.create_preauthenticated_request(
              namespace_name = namespace,
              bucket_name = bucket_name,
              create_preauthenticated_request_details=oci.object_storage.models.CreatePreauthenticatedRequestDetails(
                 name = "prestorage",
                 access_type = "ObjectRead",
                 time_expires = datetime.strptime(
                    "2024-06-05T04:25:22.344Z",
                    "%Y-%m-%dT%H:%M:%S.%fZ"),
                 object_name = object_name))
           #logging.getLogger().info(create_preauthenticated_request_response.data)
           logging.getLogger().info("created pre authenticated url")
           string = str(create_preauthenticated_request_response.data)
           #response = create_preauthenticated_request_response.data().decode('utf-8')
           url = json.loads(string)
           logging.getLogger().info(url)
           temporary_url = f"{url['full_path']}"
           logging.getLogger().info(temporary_url)
        
        #Set your email credentials
           sender_email = "test@domain"
           sender_name = "Tester"
        
        #Set the recipient email address
           recipient_email = "xyz@oracle.com"
           USERNAME_SMTP = "SMTPOCID"
           password_smtp = "************"
           HOST = "smtp_email"
           PORT = 587
        
        #Create the email content
           subject = "Cost Usage Report"
           body = temporary_url
           message = EmailMessage()
           message['From'] = email.utils.formataddr((sender_name, sender_email))
           message['To'] = recipient_email
           message['Subject'] = subject
           message.set_content(body)
           try:
              server = smtplib.SMTP(HOST, PORT)
              server.ehlo()
              server.starttls(context=ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=None, capath=None))
              server.ehlo()
              server.login(USERNAME_SMTP, password_smtp)
              logging.getLogger().info("SMTP server logged in")
              server.sendmail(sender_email, recipient_email, message.as_string())
              #server.send_message(message)
              server.close()
           except Exception as e:
              logging.getLogger().info(f"Error: {e}")
           else:
              logging.getLogger().info('Email sent successfully!')
        
      • 使用 OCI 通知:

        注:更新主题 OCID(任务 5 中说明了创建通知的步骤)。

        import oci
        import json
        import io
        import logging
        import smtplib
        from os.path import basename
        from email.mime.application import MIMEApplication
        from email.mime.multipart import MIMEMultipart
        from email.mime.text import MIMEText
        from email.utils import COMMASPACE, formatdate
        from datetime import datetime
        import ssl
        import email.utils
        from email.message import EmailMessage
        
        def handler(ctx, data: io.BytesIO = None):
           funDataStr = data.read().decode('utf-8')
        
        # Convert the log data to json
           funData =  json.loads(funDataStr)
        
        # Set up OCI configuration using resource principal
           signer = oci.auth.signers.get_resource_principals_signer()
        # Create Object Storage client
           object_storage_client = oci.object_storage.ObjectStorageClient({},signer=signer)
           ons_client = oci.ons.NotificationDataPlaneClient({},signer=signer)
        # Extract object details from the event
        
        
           object_name = funData['data']['resourceName']
           namespace = funData['data']['additionalDetails']['namespace']
           bucket_name = funData['data']['additionalDetails']['bucketName']
        
        # Download the object
           create_preauthenticated_request_response = object_storage_client.create_preauthenticated_request(
              namespace_name = namespace,
              bucket_name = bucket_name,
              create_preauthenticated_request_details=oci.object_storage.models.CreatePreauthenticatedRequestDetails(
                 name = "prestorage",
                 access_type = "ObjectRead",
                 time_expires = datetime.strptime(
                    "2024-06-05T04:25:22.344Z",
                    "%Y-%m-%dT%H:%M:%S.%fZ"),
                 object_name = object_name))
        #logging.getLogger().info(create_preauthenticated_request_response.data)
           logging.getLogger().info("created pre authenticated url")
           string = str(create_preauthenticated_request_response.data)
        #response = create_preauthenticated_request_response.data().decode('utf-8')
           url = json.loads(string)
        
           logging.getLogger().info(url)
           temporary_url = f"{url['full_path']}"
           logging.getLogger().info(temporary_url)
        #to send mail using notification
           publish_message_response = ons_client.publish_message(
              topic_id="ocid1.onstopic.oc1.iad.************",
              message_details=oci.ons.models.MessageDetails(
                 body=temporary_url,
                 title="Cost-usage report"),
           message_type="RAW_TEXT")
           logging.getLogger().info(publish_message_response)
           logging.getLogger().info('Email sent successfully!')
        
    • requirement.txt:

      fdk>=0.1.68
      oci
      
  4. 在 OCI Cloud Shell 上使用以下命令更新注册表中的函数并部署最新代码。

    fn -v deploy — app App_name
    

部署后,即可调用函数。要触发函数,需要创建事件规则。

任务 4:设置事件规则

  1. 在 OCI 中创建事件规则。在可观察性和管理下,单击事件服务规则创建规则。输入匹配规则,如下图所示,并将属性作为存储桶 ID。

    注:创建的 OCI 对象存储存储桶应启用 emit 对象事件

    创建事件规则

  2. 使用在任务 2 中创建的函数添加操作,如下图中所示。

    操作

    现在,为函数创建触发器。

任务 5:使用 OCI 电子邮件传送或 OCI 通知设置电子邮件配置

测试

将对象或任何文件上载到存储桶,并使用事件规则自动触发功能。

确认

更多学习资源

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

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