Skip to content

Commit

Permalink
[COST-4915] Add unattributed distribution to cost model form.
Browse files Browse the repository at this point in the history
  • Loading branch information
myersCody committed Apr 26, 2024
1 parent 506059a commit cb32a63
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 33 deletions.
40 changes: 28 additions & 12 deletions koku/cost_models/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@

MARKUP_CHOICES = (("percent", "%"),)
LOG = logging.getLogger(__name__)
NETWORK_UNATTRIBUTED = "network_unattributed"
STORAGE_UNATTRIBUTED = "storage_unattributed"
DEFAULT_DISTRIBUTION_INFO = {
"distribution_type": metric_constants.CPU_DISTRIBUTION,
"platform_cost": True,
"worker_cost": True,
NETWORK_UNATTRIBUTED: False,
STORAGE_UNATTRIBUTED: False,
}


class UUIDKeyRelatedField(serializers.PrimaryKeyRelatedField):
Expand Down Expand Up @@ -58,22 +67,31 @@ class MarkupSerializer(serializers.Serializer):
class DistributionSerializer(BaseSerializer):
"""Serializer for distribution options"""

DISTRIBUTION_OPTIONS = {"distribution_type", "worker_cost", "platform_cost"}
DISTRIBUTION_OPTIONS = {
"distribution_type",
"worker_cost",
"platform_cost",
NETWORK_UNATTRIBUTED,
STORAGE_UNATTRIBUTED,
}

distribution_type = serializers.ChoiceField(choices=metric_constants.DISTRIBUTION_CHOICES, required=False)
platform_cost = serializers.BooleanField(required=False)
worker_cost = serializers.BooleanField(required=False)
network_unattributed = serializers.BooleanField(required=False)
storage_unattributed = serializers.BooleanField(required=False)

def validate(self, data):
"""Run validation for distribution options."""

default_to_true = ["platform_cost", "worker_cost"]
diff = self.DISTRIBUTION_OPTIONS.difference(data)
if diff == self.DISTRIBUTION_OPTIONS:
return {"distribution_type": metric_constants.CPU_DISTRIBUTION, "platform_cost": True, "worker_cost": True}
if diff:
distribution_info_str = ", ".join(diff)
error_msg = f"Missing distribution information: one of {distribution_info_str}"
raise serializers.ValidationError(error_msg)
return DEFAULT_DISTRIBUTION_INFO
for element in diff:
if element not in self.DISTRIBUTION_OPTIONS:
error_msg = f"Incorrect distribution key provided: {element}"
raise serializers.ValidationError(error_msg)

Check warning on line 93 in koku/cost_models/serializers.py

View check run for this annotation

Codecov / codecov/patch

koku/cost_models/serializers.py#L92-L93

Added lines #L92 - L93 were not covered by tests
data[element] = element in default_to_true
return data


Expand Down Expand Up @@ -477,11 +495,9 @@ def validate(self, data):
data["currency"] = get_currency(self.context.get("request"))

if not data.get("distribution_info"):
data["distribution_info"] = {
"distribution_type": data.get("distribution", metric_constants.CPU_DISTRIBUTION),
"platform_cost": True,
"worker_cost": True,
}
distribution_info = copy.deepcopy(DEFAULT_DISTRIBUTION_INFO)
distribution_info["distribution_type"] = data.get("distribution", metric_constants.CPU_DISTRIBUTION)
data["distribution_info"] = distribution_info

if (
data.get("markup")
Expand Down
35 changes: 14 additions & 21 deletions koku/cost_models/test/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from cost_models.models import CostModel
from cost_models.models import CostModelMap
from cost_models.serializers import CostModelSerializer
from cost_models.serializers import DEFAULT_DISTRIBUTION_INFO
from cost_models.serializers import DistributionSerializer
from cost_models.serializers import RateSerializer
from cost_models.serializers import UUIDKeyRelatedField

Expand Down Expand Up @@ -844,47 +846,38 @@ def test_valid_distribution_info_keys(self):
if serializer.is_valid(raise_exception=True):
instance = serializer.save()
self.assertIsNotNone(instance)
# Add in default options
valid_distrib_obj["network_unattributed"] = False
valid_distrib_obj["storage_unattributed"] = False
self.assertEqual(instance.distribution_info, valid_distrib_obj)

def test_invalid_distribution_info_keys(self):
"""Test that source distribution_info object has invalid keys."""

invalid_distrib_info_keys = {"bad_key": "", "badder_key": True, "worker_cost": False}
self.ocp_data["distribution_info"] = invalid_distrib_info_keys
self.assertEqual(self.ocp_data["distribution_info"], invalid_distrib_info_keys)
bad_key1 = "bad_key"
bad_key2 = "worst_key"
invalid_distrib_info_keys = {bad_key1: "", bad_key2: True, "worker_cost": False}
with tenant_context(self.tenant):
serializer = CostModelSerializer(data=self.ocp_data, context=self.request_context)
with self.assertRaises(serializers.ValidationError):
serializer.is_valid(raise_exception=True)
serializer = DistributionSerializer(data=invalid_distrib_info_keys)
self.assertTrue(serializer.is_valid(raise_exception=True))
self.assertNotIn(bad_key1, serializer.data)
self.assertNotIn(bad_key2, serializer.data)

def test_none_distribution_info_returns_defaults(self):
"""Test that a none distribution_info object uses default options."""

default_distrib_info_obj = {
"distribution_type": metric_constants.CPU_DISTRIBUTION,
"platform_cost": True,
"worker_cost": True,
}
with tenant_context(self.tenant):
instance = None
serializer = CostModelSerializer(data=self.ocp_data, context=self.request_context)
if serializer.is_valid(raise_exception=True):
instance = serializer.save()
self.assertIsNotNone(instance)
self.assertEqual(instance.distribution_info, default_distrib_info_obj)
self.assertEqual(instance.distribution_info, DEFAULT_DISTRIBUTION_INFO)

def test_empty_distribution_info_returns_defaults(self):
"""Test that an empty distribution_info object returns default options."""

default_distrib_info_obj = {
"distribution_type": metric_constants.CPU_DISTRIBUTION,
"platform_cost": True,
"worker_cost": True,
}
self.ocp_data["distribution_info"] = {}
with tenant_context(self.tenant):
instance = None
serializer = CostModelSerializer(data=self.ocp_data, context=self.request_context)
if serializer.is_valid(raise_exception=True):
instance = serializer.save()
self.assertEqual(instance.distribution_info, default_distrib_info_obj)
self.assertEqual(instance.distribution_info, DEFAULT_DISTRIBUTION_INFO)

0 comments on commit cb32a63

Please sign in to comment.