內建阿裡雲的費用賬單,是公司運維小夥伴經常要承擔的工作。阿裡雲也開放了按照多個維次元查詢費用賬單的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"
}
]
}

同時建立一個擁有此權限Ram角色,并添加以下的信任政策:
- 建立RAM Role,選擇Alibaba Cloud Service類型
- 添加剛剛建立的政策AliyunBSSBillReadOnly
- 修改信任政策,讓邏輯編排可以通路
"Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": [ "composer.aliyuncs.com" ] } } ], "Version": "1"
第二步 編排流程
登入國際站并通路邏輯編排控制台
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結構的方式,希望能夠幫助到您。