Skip to content

Add billing account scope logic for MPA #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM cloudforet/python-core:2.0
FROM cloudforet/python-core:2.0.90

ENV PYTHONUNBUFFERED 1
ENV SPACEONE_PORT 50051
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def query_usage_http(
yield response_json
except Exception as e:
_LOGGER.error(f"[ERROR] query_usage_http {e}", exc_info=True)
raise ERROR_UNKNOWN(message=f"[ERROR] get_usd_cost_and_tag_http {e}")
raise ERROR_UNKNOWN(message=f"[ERROR] query_usage_http {e}")

def get_billing_account(self) -> dict:
billing_account_name = self.billing_account_id
Expand Down
35 changes: 31 additions & 4 deletions src/cloudforet/cost_analysis/manager/cost_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def get_data(
collect_scope: str = task_options["collect_scope"]
tenant_ids: list = self._get_tenant_ids(task_options, collect_scope)
start: datetime = self._get_first_date_of_month(task_options["start"])
end: datetime = datetime.utcnow()
end = self._get_end_date_from_task_options(task_options)

monthly_time_period = self._make_monthly_time_period(start, end)
for time_period in monthly_time_period:
Expand Down Expand Up @@ -454,6 +454,20 @@ def _get_additional_info(self, result: dict, options: dict, tenant_id: str = Non
if result.get("term") != "" and result.get("term"):
additional_info["Term"] = result["term"]

if options.get("cost_metric") == "AmortizedCost":
if result.get("pricingmodel") in ["Reservation", "SavingsPlan"]:
meter_id = result.get("meterid")
product_id = result.get("productid")
if not self.retail_price_map.get(f"{meter_id}:{product_id}"):
unit_price = self._get_unit_price_from_meter_id(
meter_id, product_id
)
self.retail_price_map[f"{meter_id}:{product_id}"] = unit_price

additional_info["PayG Unit Price"] = self.retail_price_map[
f"{meter_id}:{product_id}"
]

return additional_info

def _get_cost_from_result_with_options(self, result: dict, options: dict) -> float:
Expand Down Expand Up @@ -498,9 +512,12 @@ def _get_aggregate_data(self, result: dict, options: dict) -> dict:
aggregate_data["Actual Cost"] = cost_in_billing_currency

if result.get("pricingmodel") in ["Reservation", "SavingsPlan"]:
aggregate_data["Saved Cost"] = self._get_saved_cost(
result, cost_in_billing_currency
)
if cost_in_billing_currency > 0:
aggregate_data["Saved Cost"] = self._get_saved_cost(
result, cost_in_billing_currency
)
else:
aggregate_data["Saved Cost"] = 0.0

else:
aggregate_data["Actual Cost"] = cost_in_billing_currency
Expand Down Expand Up @@ -578,6 +595,8 @@ def _get_tenant_ids(task_options: dict, collect_scope: str) -> list:
tenant_ids.append(task_options["tenant_id"])
elif collect_scope == "customer_tenant_id":
tenant_ids.extend(task_options["customer_tenants"])
elif "billing_tenant_id" in task_options:
tenant_ids.append(task_options["billing_tenant_id"])
else:
tenant_ids.append("EA Agreement")
return tenant_ids
Expand Down Expand Up @@ -780,3 +799,11 @@ def _set_network_traffic_cost(
def _combine_rows_and_columns_from_results(rows: list, columns: list):
_columns = [column.get("name") for column in columns]
return pd.DataFrame(data=rows, columns=_columns).to_dict(orient="records")

def _get_end_date_from_task_options(self, task_options: dict) -> datetime:
end_date = datetime.utcnow()

if "end" in task_options:
if end_date.strftime("%Y-%m") < task_options["end"]:
end_date = self._get_last_date_of_month(end_date.year, end_date.month)
return end_date
127 changes: 81 additions & 46 deletions src/cloudforet/cost_analysis/manager/job_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,61 +43,96 @@ def get_tasks(
changed = []
synced_accounts = []

# divide customer tenants for each task
customer_tenants, first_sync_tenants = self._get_customer_tenants(
secret_data, linked_accounts
)

if len(customer_tenants) == 0 and len(first_sync_tenants) > 0:
customer_tenants.extend(first_sync_tenants)
first_sync_tenants = []
# Only for MicrosoftPartnerAgreement
if options.get("collect_scope") == "billing_account_id":
start = datetime.strptime(start_month, "%Y-%m")
end = datetime.utcnow()

divided_customer_tenants = self._get_divided_customer_tenants(
customer_tenants
)
month_range = relativedelta(end, start).months
month_range_step = math.ceil((month_range + 1) / _TASK_LIST_SIZE)

for divided_customer_tenant_info in divided_customer_tenants:
tasks.append(
{
"task_options": {
"start": start_month,
"account_agreement_type": billing_account_agreement_type,
"collect_scope": "customer_tenant_id",
"customer_tenants": divided_customer_tenant_info,
"billing_tenant_id": secret_data["tenant_id"],
}
}
)
if linked_accounts:
synced_accounts = self._extend_synced_accounts(
synced_accounts, divided_customer_tenant_info
for month in range(
0,
month_range + 1,
math.ceil((month_range + 1) / _TASK_LIST_SIZE),
):
task_start_month = datetime.strftime(
start + relativedelta(months=month), "%Y-%m"
)
task_end_month = datetime.strftime(
start + relativedelta(months=month + month_range_step - 1),
"%Y-%m",
)
changed.append({"start": start_month})
if first_sync_tenants:
first_sync_start_month = self._get_start_month(start=None)
tasks.append(
{
"task_options": {
"start": first_sync_start_month,
"account_agreement_type": billing_account_agreement_type,
"collect_scope": "customer_tenant_id",
"customer_tenants": first_sync_tenants,
"billing_tenant_id": secret_data["tenant_id"],
"is_sync": False,
tasks.append(
{
"task_options": {
"start": task_start_month,
"end": task_end_month,
"account_agreement_type": billing_account_agreement_type,
"collect_scope": "billing_account_id",
"billing_tenant_id": secret_data["tenant_id"],
}
}
}
)
if linked_accounts:
synced_accounts = linked_accounts
changed.append({"start": start_month})
else:
# divide customer tenants for each task
customer_tenants, first_sync_tenants = self._get_customer_tenants(
secret_data, linked_accounts
)

if len(customer_tenants) == 0 and len(first_sync_tenants) > 0:
customer_tenants.extend(first_sync_tenants)
first_sync_tenants = []

divided_customer_tenants = self._get_divided_customer_tenants(
customer_tenants
)
for tenant_id in first_sync_tenants:
changed.append(

for divided_customer_tenant_info in divided_customer_tenants:
tasks.append(
{
"start": first_sync_start_month,
"filter": {"additional_info.Tenant Id": tenant_id},
"task_options": {
"start": start_month,
"account_agreement_type": billing_account_agreement_type,
"collect_scope": "customer_tenant_id",
"customer_tenants": divided_customer_tenant_info,
"billing_tenant_id": secret_data["tenant_id"],
}
}
)
if linked_accounts:
synced_accounts = self._extend_synced_accounts(
synced_accounts, first_sync_tenants
if linked_accounts:
synced_accounts = self._extend_synced_accounts(
synced_accounts, divided_customer_tenant_info
)
changed.append({"start": start_month})
if first_sync_tenants:
first_sync_start_month = self._get_start_month(start=None)
tasks.append(
{
"task_options": {
"start": first_sync_start_month,
"account_agreement_type": billing_account_agreement_type,
"collect_scope": "customer_tenant_id",
"customer_tenants": first_sync_tenants,
"billing_tenant_id": secret_data["tenant_id"],
"is_sync": False,
}
}
)
for tenant_id in first_sync_tenants:
changed.append(
{
"start": first_sync_start_month,
"filter": {"additional_info.Tenant Id": tenant_id},
}
)
if linked_accounts:
synced_accounts = self._extend_synced_accounts(
synced_accounts, first_sync_tenants
)
else:
tasks = [
{
Expand Down
Loading