Skip to content

Commit 9b81ebd

Browse files
committed
feat: Add RI/SP cost display as list price in PAYG
1 parent e73ed0c commit 9b81ebd

File tree

4 files changed

+42
-24
lines changed

4 files changed

+42
-24
lines changed

src/cloudforet/cost_analysis/connector/azure_cost_mgmt_connector.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@
22
import os
33
import tempfile
44
import time
5-
import requests
6-
import pandas as pd
7-
import numpy as np
85
from datetime import datetime
96
from functools import wraps
107
from io import BytesIO
118
from typing import get_type_hints, Union, Any
129

10+
import numpy as np
11+
import pandas as pd
12+
import requests
13+
from azure.core.exceptions import ResourceNotFoundError, HttpResponseError
1314
from azure.identity import DefaultAzureCredential
1415
from azure.mgmt.billing import BillingManagementClient
15-
from azure.mgmt.costmanagement import CostManagementClient
1616
from azure.mgmt.consumption import ConsumptionManagementClient
17-
from azure.core.exceptions import ResourceNotFoundError, HttpResponseError
17+
from azure.mgmt.costmanagement import CostManagementClient
1818
from spaceone.core.connector import BaseConnector
1919

20-
from cloudforet.cost_analysis.error.cost import *
2120
from cloudforet.cost_analysis.conf.cost_conf import *
21+
from cloudforet.cost_analysis.error.cost import *
2222

2323
__all__ = ["AzureCostMgmtConnector"]
2424

@@ -225,7 +225,8 @@ def list_by_billing_account(self):
225225

226226
@staticmethod
227227
def get_retail_price(meter_id: str, currency: str = "USD"):
228-
url = f"https://prices.azure.com/api/retail/prices?currencyCode={currency}&$filter=priceType eq 'Consumption' and meterId eq '{meter_id}'"
228+
# url = f"https://prices.azure.com/api/retail/prices?currencyCode={currency}&$filter=priceType eq 'Consumption' and meterId eq '{meter_id}'"
229+
url = f"https://prices.azure.com/api/retail/prices?currencyCode={currency}&$filter=meterId eq '{meter_id}'"
229230
try:
230231
response = requests.get(url=url)
231232
return response.json()

src/cloudforet/cost_analysis/manager/cost_manager.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import calendar
2-
import logging
32
import json
3+
import logging
44
import time
5-
import pandas as pd
6-
from typing import Union, Tuple, Any, Generator
75
from datetime import datetime, timezone
6+
from typing import Union
87

8+
import pandas as pd
99
from spaceone.core.error import *
1010
from spaceone.core.manager import BaseManager
1111

12+
from cloudforet.cost_analysis.conf.cost_conf import *
1213
from cloudforet.cost_analysis.connector.azure_cost_mgmt_connector import (
1314
AzureCostMgmtConnector,
1415
)
15-
from cloudforet.cost_analysis.conf.cost_conf import *
1616

1717
_LOGGER = logging.getLogger("spaceone")
1818

@@ -454,6 +454,7 @@ def _make_benefit_cost_info(self, result: dict, billed_at: str) -> dict:
454454
result.get("UsageQuantity", 0.0)
455455
)
456456
actual_cost = self._convert_str_to_float_format(result.get("Cost", 0.0))
457+
457458
data = {
458459
"cost": 0,
459460
"usage_quantity": usage_quantity,
@@ -466,6 +467,7 @@ def _make_benefit_cost_info(self, result: dict, billed_at: str) -> dict:
466467
},
467468
"additional_info": additional_info,
468469
}
470+
469471
return data
470472

471473
@staticmethod
@@ -509,14 +511,22 @@ def _get_cost_from_result_with_options(self, result: dict, options: dict) -> flo
509511
cost_pay_as_you_go = 0.0
510512

511513
if options.get("include_reservation_cost_at_payg", False):
512-
pricing_model = result.get("pricingmodel")
513-
charge_type = result.get("chargetype")
514-
515-
if (
516-
pricing_model in ["Reservation", "SavingsPlan"]
517-
and charge_type == "Purchase"
518-
):
519-
cost_pay_as_you_go = result.get("costinbillingcurrency", 0.0)
514+
if options.get("cost_metric") == "AmortizedCost":
515+
pricing_model = result.get("pricingmodel")
516+
charge_type = result.get("chargetype")
517+
if (
518+
pricing_model in ["Reservation", "SavingsPlan"]
519+
and charge_type == "Usage"
520+
):
521+
cost_pay_as_you_go = self._get_retail_cost(result)
522+
elif options.get("cost_metric") == "ActualCost":
523+
pricing_model = result.get("pricingmodel")
524+
charge_type = result.get("chargetype")
525+
if (
526+
pricing_model in ["Reservation", "SavingsPlan"]
527+
and charge_type == "Purchase"
528+
):
529+
cost_pay_as_you_go = self._get_retail_cost(result)
520530

521531
return cost_pay_as_you_go
522532

@@ -554,12 +564,11 @@ def _get_aggregate_data(self, result: dict, options: dict) -> dict:
554564

555565
return aggregate_data
556566

557-
def _get_saved_cost(self, result: dict, cost: float) -> float:
567+
def _get_retail_cost(self, result: dict) -> float:
558568
exchange_rate = 1.0
559-
saved_cost = 0
560-
currency = result.get("billingcurrency", "USD")
561569
meter_id = result.get("meterid")
562570
product_id = result.get("productid")
571+
currency = result.get("billingcurrency", "USD")
563572
quantity = self._convert_str_to_float_format(result.get("quantity", 0.0))
564573

565574
if not self.retail_price_map.get(f"{meter_id}:{product_id}"):
@@ -570,6 +579,13 @@ def _get_saved_cost(self, result: dict, cost: float) -> float:
570579

571580
unit_price = self.retail_price_map[f"{meter_id}:{product_id}"]
572581

582+
retail_cost = exchange_rate * quantity * unit_price
583+
584+
return retail_cost
585+
586+
def _get_saved_cost(self, result: dict, cost: float) -> float:
587+
saved_cost = 0
588+
573589
# if currency != "USD" and quantity > 0:
574590
# cost_in_billing_currency = self._convert_str_to_float_format(
575591
# result.get("costinbillingcurrency", 0.0)
@@ -583,7 +599,7 @@ def _get_saved_cost(self, result: dict, cost: float) -> float:
583599
# else:
584600
# exchange_rate = cost_in_billing_currency / cost_in_pricing_currency
585601

586-
retail_cost = exchange_rate * quantity * unit_price
602+
retail_cost = self._get_retail_cost(result)
587603
if retail_cost:
588604
saved_cost = retail_cost - cost
589605

src/cloudforet/cost_analysis/manager/data_source_manager.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from spaceone.core.error import ERROR_INVALID_ARGUMENT
55
from spaceone.core.manager import BaseManager
6+
67
from cloudforet.cost_analysis.connector.azure_cost_mgmt_connector import (
78
AzureCostMgmtConnector,
89
)

src/cloudforet/cost_analysis/manager/job_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
from typing import Tuple, Union
55

66
from dateutil.relativedelta import relativedelta
7-
87
from spaceone.core.manager import BaseManager
8+
99
from cloudforet.cost_analysis.conf.cost_conf import SECRET_TYPE_DEFAULT
1010
from cloudforet.cost_analysis.connector import AzureCostMgmtConnector
1111
from cloudforet.cost_analysis.error.cost import *

0 commit comments

Comments
 (0)