使用逻辑编排解决阿里云费用账单API集成数据结构差异的问题

简介: 利用流程编排在集成过程中定制阿里云账单API的结构

集成阿里云的费用账单,是公司运维小伙伴经常要承担的工作。阿里云也开放了按照多个维维度查询费用账单的API供企业客户使用,集成到云管平台,财务系统等等。不过在实际工作中,常常会发现需要集成的云供应商不止一家,每一家提供的API格式都不一样。如果想要接入已经开发好的系统,数据结构不一致就需要做额外的数据Mapping工作,费时费力。小编在阿里云上发现了一款神器,可对阿里云提供的API做快速的定制,输出想要的格式,这就是阿里云的逻辑编排。

什么是逻辑编排?

举个实际的例子,阿里云账单的API QueryInstanceBill可返回按照实例维度或者计费项维度的账单,返回的格式是这样的:
"Data": {

"Items": {
  "Item": [
    {
                "SubscriptionType": "PayAsYouGo",
                "ProductCode": "cdn",
                "RecordID": "2019080352963162",
                "BillingItem": "InlandNetworkOut",
                "ProductDetail": "cdn",
                "DeductedByPrepaidCard": 0,
                "PretaxAmount": 0,
                "DeductedByCoupons": 0,
                "RoundDownDiscount": 0,
                "UsageStartTime": "2019-08-08 12:00:00",
                "UsageEndTime": "2019-08-08 13:00:00",
                "Status": "NoSettle",
                "PaymentTime": "",
                "PaymentAmount": 0,
                "Item": "PayAsYouGoBill",
                "OutstandingAmount": 0,
                "ProductType": "",
                "DeductedByCashCoupons": 0,
                "OwnerID": "",
                "ProductName": "cdn",
                "Currency": "CNY",
                "PretaxGrossAmount": 0,
                "InvoiceDiscount": 0
            }
            ]

},

如果在集成的过程中,仅希望InlandNetworkOut这一个计费项的用量和金额汇总,输出一个特定Json格式的结果,可以按照下面的步骤操作。

第一步 权限设置

逻辑编排过程中需要调用QueryInstanceBill接口,因此需要相关的权限。可以使用AliyunBSSFullAccess权限,但为了保证最小可用原则,创建一个新的权限策略AliyunBSSBillReadOnly,使用以下的Statement
{
"Version": "1",
"Statement": [

   {
       "Action": ["bss:Query*", "bss:Describe*"],
       "Resource": "*",
       "Effect": "Allow"
   }

]
}
1579513892267_a3ab1069_ff7f_44e0_b839_8b0389f87636
同时创建一个拥有此权限Ram角色,并添加以下的信任策略:

  1. 创建RAM Role,选择Alibaba Cloud Service类型
  2. 添加刚刚创建的策略AliyunBSSBillReadOnly
  3. 修改信任策略,让逻辑编排可以访问
    {

    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "composer.aliyuncs.com"
                ]
            }
        }
    ],
    "Version": "1"

    }

1579514503818_9c76a9d5_1f66_448a_b251_07f0ea338919

第二步 编排流程
登录国际站并访问逻辑编排控制台https://lc.console.aliyun.com/,在左侧的菜单选择“我的工作流”,然后创建一个新的流程,输入名称和描述。创建完成后,转到“代码设计”,然后复制本文给出的一个段脚本。
{

"actions": {
    "查询_InstanceBill_第一页数据": {
        "type": "ACS::BSS::QueryInstanceBill",
        "inputs": {
            "method": "POST",
            "host": {
                "product": "BSS",
                "api": "QueryInstanceBill",
                "apiVersion": "2017-12-14"
            },
            "connection": {},
            "queries": {
                "RegionId": "ap-southeast-1",
                "BillingCycle": "@get(triggerOutputs(), 'queries.BillingCycle')",
                "ProductCode": "cdn",
                "PageNum": 1,
                "PageSize": 300,
                "IsBillingItem": true
            }
        },
        "runAfter": {
            "初始化变量存放所有记录": [
                "Succeeded"
            ]
        }
    },
    "初始化变量存放所有记录": {
        "type": "InitializeVariable",
        "inputs": {
            "name": "records",
            "type": "Array",
            "value": []
        },
        "runAfter": {}
    },
    "存入第一页数据": {
        "type": "AppendToArrayVariable",
        "inputs": {
            "name": "records",
            "value": "@body('查询_InstanceBill_第一页数据')['Data']['Items']['Item']"
        },
        "runAfter": {
            "查询_InstanceBill_第一页数据": [
                "Succeeded"
            ]
        }
    },
    "遍历剩余页数": {
        "type": "Until",
        "inputs": {},
        "runAfter": {
            "初始化变量存放当前页数": [
                "Succeeded"
            ]
        },
        "actions": {
            "查询某一页_InstanceBill_数据": {
                "type": "ACS::BSS::QueryInstanceBill",
                "inputs": {
                    "method": "POST",
                    "host": {
                        "product": "BSS",
                        "api": "QueryInstanceBill",
                        "apiVersion": "2017-12-14"
                    },
                    "connection": {},
                    "queries": {
                        "BillingCycle": "@get(triggerOutputs(), 'queries.BillingCycle')",
                        "RegionId": "ap-southeast-1",
                        "ProductCode": "cdn",
                        "PageNum": "@variables('pageNumber')",
                        "PageSize": 300,
                        "IsBillingItem": true
                    }
                },
                "runAfter": {
                    "设置页数": [
                        "Succeeded"
                    ]
                }
            },
            "追加值至数组变量": {
                "type": "AppendToArrayVariable",
                "inputs": {
                    "name": "records",
                    "value": "@body('查询某一页_InstanceBill_数据')['Data']['Items']['Item']"
                },
                "runAfter": {
                    "查询某一页_InstanceBill_数据": [
                        "Succeeded"
                    ]
                }
            },
            "设置页数": {
                "runAfter": {},
                "type": "SetVariable",
                "inputs": {
                    "name": "pageNumber",
                    "value": "@add(variables('pageNumber'), 1)"
                }
            }
        },
        "expression": "@lte(sub(ceil(div(body('查询_InstanceBill_第一页数据').Data.TotalCount, 300)), variables('pageNumber')), 0)"
    },
    "初始化变量存放当前页数": {
        "type": "InitializeVariable",
        "inputs": {
            "name": "pageNumber",
            "type": "Integer",
            "value": 1
        },
        "runAfter": {
            "存入第一页数据": [
                "Succeeded"
            ]
        }
    },
    "计算总数": {
        "type": "JavascriptCode",
        "inputs": {
            "code": "const records = $context.variables('records');\n\nconst allUsage = records.reduce((sum, group) => {\n    if (Array.isArray(group)) {\n        group.forEach((record) => {\n            if (record.BillingItem === 'InlandNetworkOut') {\n                if (record.Usage) {\n                    sum.Usage += parseFloat(record.Usage) || 0;\n                }\n                if (record.PretaxAmount) {\n                    sum.PretaxAmount += parseFloat(record.PretaxAmount) || 0;\n                }\n            }\n            \n        });\n    } else if (group.Usage || group.PretaxAmount) {\n        if (group.BillingItem === 'InlandNetworkOut') {\n            sum.Usage += parseFloat(group.Usage) || 0;\n            sum.PretaxAmount += parseFloat(group.PretaxAmount) || 0;\n        }\n    }\n    \n    return sum;\n}, { Usage: 0, PretaxAmount: 0 });\n\nreturn allUsage;"
        },
        "runAfter": {
            "遍历剩余页数": [
                "Succeeded"
            ]
        }
    },
    "响应": {
        "type": "Response",
        "outputs": {
            "statusCode": 500,
            "body": {                  
                "cost_data": [
                    {                        
                        "usage": "@body('计算总数').Usage",
                        "cost": "@body('计算总数').PretaxAmount"
                    }
                ]
            },
            "headers": {
                "Content-Type": "application/json"
            }
        },
        "runAfter": {
            "计算总数": [
                "Succeeded"
            ]
        }
    }
}

}

返回图形化设置,这时需要对其中调用API的过程进行授权。点击并展开“查询InstanceBill第一页数据”,在下方点击Change Permissions,添加刚刚创建新的RAM Role,注意Authorized Policies是否包括了应该有的权限。再点开“遍历剩余页数”这一步,再展开“查询某一页InstanceBill数据”,进行如上的权限添加步骤。点击右上角的保存按键保存流程。

第三步 调用流程
在流程的第一步中,可以找到服务发起的URL,Copy到浏览器中可进行测试。在上面的例子中,调用时需要添加一个查询账期的参数BillingCycle=YYYY-MM。根据所需,可更改调用方式为POST或者GET。

这就是一个利用流程编改变API结构的方式,希望能够帮助到您。

相关文章
|
9天前
|
人工智能 JSON 安全
DeepSeek Engineer:集成 DeepSeek API 的开源 AI 编程助手,支持文件读取、编辑并生成结构化响应
DeepSeek Engineer 是一款开源AI编程助手,通过命令行界面处理用户对话并生成结构化JSON,支持文件操作和代码生成。
149 5
DeepSeek Engineer:集成 DeepSeek API 的开源 AI 编程助手,支持文件读取、编辑并生成结构化响应
|
2月前
|
安全 Java API
【三方服务集成】最新版 | 阿里云短信服务SMS使用教程(包含支持单双参数模板的工具类,拿来即用!)
阿里云短信服务提供API/SDK和控制台调用方式,支持验证码、通知、推广等短信类型。需先注册阿里云账号并实名认证,然后在短信服务控制台申请资质、签名和模板,并创建AccessKey。最后通过Maven引入依赖,使用工具类发送短信验证码。
【三方服务集成】最新版 | 阿里云短信服务SMS使用教程(包含支持单双参数模板的工具类,拿来即用!)
|
2月前
|
存储 Prometheus 运维
在云原生环境中,阿里云ARMS与Prometheus的集成提供了强大的应用实时监控解决方案
在云原生环境中,阿里云ARMS与Prometheus的集成提供了强大的应用实时监控解决方案。该集成结合了ARMS的基础设施监控能力和Prometheus的灵活配置及社区支持,实现了全面、精准的系统状态、性能和错误监控,提升了应用的稳定性和管理效率。通过统一的数据视图和高级查询功能,帮助企业有效应对云原生挑战,促进业务的持续发展。
52 3
|
2月前
|
API Docker 微服务
Ocelot集成Consul实现api网关与服务发现
本文介绍了如何在.NET微服务架构中集成API网关Ocelot和Consul服务发现。首先通过Docker安装并配置Consul,接着在GoodApi项目中实现服务的自动注册与注销,并配置健康检查。然后,通过修改Ocelot的配置文件`ocelot.json`和`Program.cs`,实现基于Consul的服务发现,确保API请求能够正确路由到后端服务。最后,解决了服务解析时可能出现的问题,确保服务的IP地址而非节点名称被正确解析。
52 0
Ocelot集成Consul实现api网关与服务发现
|
3月前
|
IDE API 开发工具
沉浸式集成阿里云 OpenAPI|Alibaba Cloud API Toolkit for VS Code
Alibaba Cloud API Toolkit for VSCode 是集成了 OpenAPI 开发者门户多项功能的 VSCode 插件,开发者可以通过这个插件方便地查找API文档、进行API调试、插入SDK代码,并配置基础环境设置。我们的目标是缩短开发者在门户和IDE之间的频繁切换,实现API信息和开发流程的无缝结合,让开发者的工作变得更加高效和紧密。
沉浸式集成阿里云 OpenAPI|Alibaba Cloud API Toolkit for VS Code
|
3月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
113 9
|
3月前
|
存储 数据可视化 JavaScript
可视化集成API接口请求+变量绑定+源码输出
可视化集成API接口请求+变量绑定+源码输出
85 4
|
3月前
|
人工智能 自然语言处理 关系型数据库
阿里云云原生数据仓库 AnalyticDB PostgreSQL 版已完成和开源LLMOps平台Dify官方集成
近日,阿里云云原生数据仓库 AnalyticDB PostgreSQL 版已完成和开源LLMOps平台Dify官方集成。
|
4月前
|
机器学习/深度学习 DataWorks 数据挖掘
基于阿里云Hologres和DataWorks数据集成的方案
基于阿里云Hologres和DataWorks数据集成的方案
96 7
|
4月前
|
存储 SQL 分布式计算
Hologres 与阿里云生态的集成:构建高效的数据处理解决方案
【9月更文第1天】随着大数据时代的到来,数据处理和分析的需求日益增长。阿里云作为国内领先的云计算平台之一,提供了多种数据存储和处理的服务,其中Hologres作为一款实时数仓产品,以其高性能、高可用性以及对标准SQL的支持而受到广泛关注。本文将探讨Hologres如何与阿里云上的其他服务如MaxCompute、DataHub等进行集成,以构建一个完整的数据处理解决方案。
109 2