Skip to content

Commit

Permalink
Added DefaultProduct to existing ProviderCostAllocationType and save …
Browse files Browse the repository at this point in the history
…run time if cost is not used as cost allocation type (#25)

* Added DefaultProduct to existing ProviderCostAllocationType for better traceability purpose

* Save run time if cost is not used as cost allocation type

* Version 1.0.12
  • Loading branch information
marc-perreaut authored May 15, 2024
1 parent 9bf1629 commit 7cf6c94
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 20 deletions.
33 changes: 21 additions & 12 deletions cloud_cost_allocation/cloud_cost_allocator.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ def allocate(self, consumer_cost_items: list[ConsumerCostItem], cloud_cost_items
cost_items = []
cost_items.extend(cloud_cost_items)

# Identify cloud tag selectors and default product consumer cost items
# Identify cloud tag selectors and default product consumer cost items
# Also check if cost is used as cost allocation type
cloud_tag_selector_consumer_cost_items = []
default_product_consumer_cost_items = {}
default_product_allocation_keys = {}
is_cost_used_as_cost_allocation_type = False
for consumer_cost_item in consumer_cost_items:
if consumer_cost_item.provider_cost_allocation_type == "CloudTagSelector":
cloud_tag_selector_consumer_cost_items.append(consumer_cost_item)
Expand All @@ -59,6 +61,8 @@ def allocate(self, consumer_cost_items: list[ConsumerCostItem], cloud_cost_items
default_product_consumer_cost_items[provider_service] = [consumer_cost_item]
default_product_allocation_keys[provider_service] = consumer_cost_item.allocation_keys[0]
else:
if consumer_cost_item.provider_cost_allocation_type == "Cost":
is_cost_used_as_cost_allocation_type = True
cost_items.append(consumer_cost_item)

# Process cloud tag selectors
Expand Down Expand Up @@ -126,22 +130,25 @@ def allocate(self, consumer_cost_items: list[ConsumerCostItem], cloud_cost_items
# Protect against unexpected cycles
try:

# Compute service amortized cost, ignoring the keys that are using cost, and then
# set these keys from the allocated cost
# Build amount allocation key indexes dictionary
amounts = ['AmortizedCost', 'OnDemandCost']
amount_to_allocation_key_indexes = {}
config = self.cost_item_factory.config
if not config.build_amount_to_allocation_key_indexes(amount_to_allocation_key_indexes, amounts):
return False
info("Allocating costs, ignoring keys that are costs, for date " + self.date_str)
self.visit_for_allocation(True, False, amount_to_allocation_key_indexes)
for service_instance in self.service_instances.values():
service_instance_amortized_cost = 0.0
for cost_item in service_instance.cost_items:
if not cost_item.is_self_consumption():
service_instance_amortized_cost += cost_item.amounts[0]
for cost_item in service_instance.cost_items:
cost_item.set_cost_as_key(service_instance_amortized_cost)

# Compute service amortized cost, ignoring the keys that are using cost, and then
# set these keys from the allocated cost
if is_cost_used_as_cost_allocation_type: # Save run time if not needed
info("Allocating costs, ignoring keys that are costs, for date " + self.date_str)
self.visit_for_allocation(True, False, amount_to_allocation_key_indexes)
for service_instance in self.service_instances.values():
service_instance_amortized_cost = 0.0
for cost_item in service_instance.cost_items:
if not cost_item.is_self_consumption():
service_instance_amortized_cost += cost_item.amounts[0]
for cost_item in service_instance.cost_items:
cost_item.set_cost_as_key(service_instance_amortized_cost)

# Allocate amortized costs for services
info("Allocating costs, for date " + self.date_str)
Expand Down Expand Up @@ -484,6 +491,7 @@ def process_default_products(self,
in default_product_consumer_cost_items[cost_item.provider_service]:
new_consumer_cost_item = self.cost_item_factory.create_consumer_cost_item()
new_consumer_cost_item.copy(cost_item)
new_consumer_cost_item.provider_cost_allocation_type += "+DefaultProduct"
new_consumer_cost_item.product = default_product_consumer_cost_item.product
new_consumer_cost_item.product_dimensions =\
default_product_consumer_cost_item.product_dimensions.copy()
Expand All @@ -501,6 +509,7 @@ def process_default_products(self,
if cost_item.is_self_consumption():
if not cost_item.get_product():
cost_item.set_product(default_product)
cost_item.provider_cost_allocation_type += "+DefaultProduct"

# Add consumer cost items with default products for final service instances with no product
for service_instance in self.service_instances.values():
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Setup
setup(
name='cloud-cost-allocation',
version='1.0.11',
version='1.0.12',
description='Python library for shared, hierarchical cost allocation based on user-defined usage metrics.',
long_description=readme,
long_description_content_type='text/markdown',
Expand Down
14 changes: 7 additions & 7 deletions tests/test8/test8_allocated_cost.csv
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ Date,Service,Instance,Tags,AmortizedCost,OnDemandCost,Currency,ProviderService,P
2024-01-25,app2,app2,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,app2,app2,,128.0,128.0,EUR,app2,app2,,DefaultProduct,1.0,,p0,128.0,128.0,,,,,,Y
2024-01-25,app3,a3i1,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,app3,a3i1,,64.0,64.0,EUR,plf1,plf1,,Key,1.0,,p9,64.0,64.0,p9d1,pd9e1,p9d2,p9e2,,N
2024-01-25,app3,a3i1,,64.0,64.0,EUR,plf1,plf1,,Key+DefaultProduct,1.0,,p9,64.0,64.0,p9d1,pd9e1,p9d2,p9e2,,N
2024-01-25,app3,a3i1,,192.0,192.0,EUR,app3,a3i1,,Key,1.0,,p3,128.0,128.0,,,,,,Y
2024-01-25,app3,a3i2,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,app3,a3i2,,64.0,64.0,EUR,plf1,plf1,,Key,1.0,,p9,64.0,64.0,p9d1,pd9e1,p9d2,p9e2,,N
2024-01-25,app3,a3i2,,64.0,64.0,EUR,plf1,plf1,,Key+DefaultProduct,1.0,,p9,64.0,64.0,p9d1,pd9e1,p9d2,p9e2,,N
2024-01-25,app4,app4,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,app4,app4,,192.0,192.0,EUR,app3,a3i2,,Key,1.0,,,,,,,,,,N
2024-01-25,app4,app4,,160.0,160.0,EUR,app4,app4,,DefaultProduct,0.5,,p4,128.0,128.0,p4d1,pd4e1,p4d2,p4e2,,Y
2024-01-25,app4,app4,,160.0,160.0,EUR,app4,app4,,DefaultProduct,0.5,,p5,128.0,128.0,p5d1,pd5e1,p5d2,p5e2,,Y
2024-01-25,app5,app5,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,app5,app5,,64.0,64.0,EUR,plf2,plf2,,Key,1.0,,p2,64.0,64.0,,,,,,N
2024-01-25,app5,app5,,96.0,96.0,EUR,app5,app5,,Key,1.0,,p6,64.0,64.0,p6d1,pd6e1,p6d2,p6e2,,Y
2024-01-25,app5,app5,,96.0,96.0,EUR,app5,app5,,Key+DefaultProduct,1.0,,p6,64.0,64.0,p6d1,pd6e1,p6d2,p6e2,,Y
2024-01-25,app6,app6,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,app6,app6,,64.0,64.0,EUR,plf2,plf2,,Key,1.0,,p2,64.0,64.0,,,,,,N
2024-01-25,app6,app6,,96.0,96.0,EUR,app5,app5,,Key,1.0,,p6,64.0,64.0,p6d1,pd6e1,p6d2,p6e2,,N
2024-01-25,app6,app6,,144.0,144.0,EUR,app6,app6,,Key,0.5,,p7,64.0,64.0,p7d1,pd7e1,p7d2,p7e2,,Y
2024-01-25,app6,app6,,144.0,144.0,EUR,app6,app6,,Key,0.5,,p8,64.0,64.0,p8d1,pd8e1,p8d2,p8e2,,Y
2024-01-25,app6,app6,,96.0,96.0,EUR,app5,app5,,Key+DefaultProduct,1.0,,p6,64.0,64.0,p6d1,pd6e1,p6d2,p6e2,,N
2024-01-25,app6,app6,,144.0,144.0,EUR,app6,app6,,Key+DefaultProduct,0.5,,p7,64.0,64.0,p7d1,pd7e1,p7d2,p7e2,,Y
2024-01-25,app6,app6,,144.0,144.0,EUR,app6,app6,,Key+DefaultProduct,0.5,,p8,64.0,64.0,p8d1,pd8e1,p8d2,p8e2,,Y
2024-01-25,container,container,"service:container,cloud_resource_id:/az/virtualmachines/vm1,",1280.0,1280.0,EUR,,,,,,,,,,,,,,az,N
2024-01-25,container,container,,128.0,128.0,EUR,container,container,,Key,1.0,,p0,128.0,128.0,,,,,,Y
2024-01-25,container,container,,128.0,128.0,EUR,container,container,,Key+DefaultProduct,1.0,,p0,128.0,128.0,,,,,,Y
2024-01-25,plf1,plf1,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N
2024-01-25,plf2,plf2,,128.0,128.0,EUR,container,container,,Key,1.0,,,,,,,,,,N

0 comments on commit 7cf6c94

Please sign in to comment.