注意:
- 此教程需要访问 Oracle Cloud。要注册免费账户,请参阅开始使用 Oracle Cloud Infrastructure Free Tier 。
- 它使用 Oracle Cloud Infrastructure 身份证明、租户和区间示例值。完成实验室时,请将这些值替换为特定于云环境的值。
使用 Oracle Cloud Native Framework 为成本分析报表设置基于事件的自动电子邮件通知
简介
在云上运行工作负载的每个组织都非常热衷于了解他们在云上的成本支出,并希望以有意义的方式报告工作负载。为此,Oracle Cloud Infrastructure (OCI) 提供了一个功能,您可以基于成本创建自动报告,然后在 OCI 对象存储中获取这些报告。
对于这些成本报告,团队还希望设置自动化,以便相应的团队在生成报告后立即收到通知。为此,他们还希望将报告链接作为通知的一部分。您可以使用 Oracle Cloud Native Framework 设置所有这些自动化。
目标
-
设置 OCI 成本的报告生成,并基于报告生成生成生成事件。
-
使用 OCI 上的云原生托管服务配置所有自动化。
先决条件
-
在 Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) 中创建动态组、策略、存储桶、函数、设置事件和通知服务所需的权限。
-
访问所有必需的组件以查看其 Oracle Cloud 标识符 (OCID) 和其他信息。
-
访问 OCI Cloud Shell 以创建、部署和调用函数。
任务 1:设置必需的 OCI IAM 策略和动态组
-
登录到 OCI 控制台,转到动态组并创建新的动态组。
-
在规则 1 中输入区间 OCID。您的 OCI 函数应存在于同一区间中。
-
转到 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 对象存储桶并创建调度的报告
-
使用 OCI 控制台创建存储桶。我们将使用此存储桶推送报告。请确保您创建的存储桶是专用的,因为这样可以确保您的内容免受公共访问的安全,并且在此存储桶上启用了发出对象事件,因为这样可以在推送新对象时发出事件。
-
转至成本管理、计划报表,然后创建计划报表。输入名称、说明、开始日期和循环。
选择要将报表发布到的存储桶。要从下拉菜单中选择存储桶,必须添加策略,如下图中所示,以便计量服务可以访问创建的存储桶。
-
创建存储桶和调度的报表后,您可以查看已执行报表的历史记录,还可以看到报表发布到所选 OCI 对象存储桶。
任务 3:创建 OCI 通知主题并添加订阅
-
创建发送电子邮件通知所需的 OCI 通知主题。转到通知、主题并创建主题。
-
在同一主题中创建订阅并添加通知将发送到的电子邮件。
现在,OCI 通知主题已配置。
任务 4:创建和部署函数代码
转到函数/应用程序并创建函数。当事件触发该函数时,此函数将使用 OCI IAM 动态组和策略来访问 OCI 对象存储存储桶并执行所需的操作(为调度的报告文件创建 PAR URL 并随之发送通知)。
有多种方法可用于开发 OCI 函数,并提供快速入门指南,引导您使用 OCI Cloud Shell、OCI 虚拟机或本地运行来设置开发环境。本指南其余部分中的图像将显示 OCI Cloud Shell,但其中任何方法都有效。我们使用 Python 编写所需的逻辑代码,但是你可以使用另一种语言,并根据需要更改逻辑。
-
要编写代码,请在 OCI Cloud Shell 中打开
requirement.txt
和func.py
文件。 -
以下是函数代码,它使用 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...")
-
-
在 OCI Cloud Shell 上使用以下命令更新注册表中的函数并部署最新代码。
fn -v deploy — app reportsauto
-
部署后,即可调用函数。您可以尝试使用函数调用命令进行测试,并确保该函数根据需要工作。
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 事件规则
-
转到 OCI 控制台,单击应用集成、事件服务、规则和创建事件规则。输入规则条件并添加在任务 4 中创建的函数作为触发器操作。
-
输入显示名称和说明。
-
在规则条件部分中,选择第一个条件作为事件类型、对象存储、对象 - 创建,选择另一个条件作为属性、bucketName 、demoBucket 。
-
通过操作部分将事件与函数连接。选择函数区间、函数应用程序和任务 4 中部署的函数。
-
单击保存更改以保存事件规则。当条件与 OCI 对象存储桶中发出的事件匹配时,这将调用函数。
相关链接
确认
- Authors - Lovelesh Saxena(首席软件工程架构师)、Mike Fung(首席云架构师)、Tim Lee(员工云工程师)
更多学习资源
浏览 docs.oracle.com/learn 上的其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Set Up Events Based Automated Email Notifications for Cost Analysis Reports Using Oracle Cloud Native Framework
F99121-01
May 2024