TechDebt: MyPy CostExplorer (#5593)
This commit is contained in:
parent
6f3b250fc7
commit
c0b581aa08
@ -3,7 +3,7 @@ from moto.core.exceptions import JsonRESTError
|
|||||||
|
|
||||||
|
|
||||||
class CostCategoryNotFound(JsonRESTError):
|
class CostCategoryNotFound(JsonRESTError):
|
||||||
def __init__(self, ccd_id):
|
def __init__(self, ccd_id: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"ResourceNotFoundException", f"No Cost Categories found with ID {ccd_id}"
|
"ResourceNotFoundException", f"No Cost Categories found with ID {ccd_id}"
|
||||||
)
|
)
|
||||||
|
@ -5,11 +5,18 @@ from moto.core import BaseBackend, BaseModel
|
|||||||
from moto.core.utils import BackendDict
|
from moto.core.utils import BackendDict
|
||||||
from moto.utilities.tagging_service import TaggingService
|
from moto.utilities.tagging_service import TaggingService
|
||||||
from moto.moto_api._internal import mock_random
|
from moto.moto_api._internal import mock_random
|
||||||
|
from typing import Any, Dict, List, Tuple
|
||||||
|
|
||||||
|
|
||||||
class CostCategoryDefinition(BaseModel):
|
class CostCategoryDefinition(BaseModel):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, account_id, name, rule_version, rules, default_value, split_charge_rules
|
self,
|
||||||
|
account_id: str,
|
||||||
|
name: str,
|
||||||
|
rule_version: str,
|
||||||
|
rules: List[Dict[str, Any]],
|
||||||
|
default_value: str,
|
||||||
|
split_charge_rules: List[Dict[str, Any]],
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.rule_version = rule_version
|
self.rule_version = rule_version
|
||||||
@ -18,13 +25,19 @@ class CostCategoryDefinition(BaseModel):
|
|||||||
self.split_charge_rules = split_charge_rules
|
self.split_charge_rules = split_charge_rules
|
||||||
self.arn = f"arn:aws:ce::{account_id}:costcategory/{str(mock_random.uuid4())}"
|
self.arn = f"arn:aws:ce::{account_id}:costcategory/{str(mock_random.uuid4())}"
|
||||||
|
|
||||||
def update(self, rule_version, rules, default_value, split_charge_rules):
|
def update(
|
||||||
|
self,
|
||||||
|
rule_version: str,
|
||||||
|
rules: List[Dict[str, Any]],
|
||||||
|
default_value: str,
|
||||||
|
split_charge_rules: List[Dict[str, Any]],
|
||||||
|
) -> None:
|
||||||
self.rule_version = rule_version
|
self.rule_version = rule_version
|
||||||
self.rules = rules
|
self.rules = rules
|
||||||
self.default_value = default_value
|
self.default_value = default_value
|
||||||
self.split_charge_rules = split_charge_rules
|
self.split_charge_rules = split_charge_rules
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
"CostCategoryArn": self.arn,
|
"CostCategoryArn": self.arn,
|
||||||
"Name": self.name,
|
"Name": self.name,
|
||||||
@ -38,20 +51,20 @@ class CostCategoryDefinition(BaseModel):
|
|||||||
class CostExplorerBackend(BaseBackend):
|
class CostExplorerBackend(BaseBackend):
|
||||||
"""Implementation of CostExplorer APIs."""
|
"""Implementation of CostExplorer APIs."""
|
||||||
|
|
||||||
def __init__(self, region_name, account_id):
|
def __init__(self, region_name: str, account_id: str):
|
||||||
super().__init__(region_name, account_id)
|
super().__init__(region_name, account_id)
|
||||||
self.cost_categories = dict()
|
self.cost_categories: Dict[str, CostCategoryDefinition] = dict()
|
||||||
self.tagger = TaggingService()
|
self.tagger = TaggingService()
|
||||||
|
|
||||||
def create_cost_category_definition(
|
def create_cost_category_definition(
|
||||||
self,
|
self,
|
||||||
name,
|
name: str,
|
||||||
rule_version,
|
rule_version: str,
|
||||||
rules,
|
rules: List[Dict[str, Any]],
|
||||||
default_value,
|
default_value: str,
|
||||||
split_charge_rules,
|
split_charge_rules: List[Dict[str, Any]],
|
||||||
tags,
|
tags: List[Dict[str, str]],
|
||||||
):
|
) -> Tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
The EffectiveOn and ResourceTags-parameters are not yet implemented
|
The EffectiveOn and ResourceTags-parameters are not yet implemented
|
||||||
"""
|
"""
|
||||||
@ -67,7 +80,9 @@ class CostExplorerBackend(BaseBackend):
|
|||||||
self.tag_resource(ccd.arn, tags)
|
self.tag_resource(ccd.arn, tags)
|
||||||
return ccd.arn, ""
|
return ccd.arn, ""
|
||||||
|
|
||||||
def describe_cost_category_definition(self, cost_category_arn):
|
def describe_cost_category_definition(
|
||||||
|
self, cost_category_arn: str
|
||||||
|
) -> CostCategoryDefinition:
|
||||||
"""
|
"""
|
||||||
The EffectiveOn-parameter is not yet implemented
|
The EffectiveOn-parameter is not yet implemented
|
||||||
"""
|
"""
|
||||||
@ -76,7 +91,9 @@ class CostExplorerBackend(BaseBackend):
|
|||||||
raise CostCategoryNotFound(ccd_id)
|
raise CostCategoryNotFound(ccd_id)
|
||||||
return self.cost_categories[cost_category_arn]
|
return self.cost_categories[cost_category_arn]
|
||||||
|
|
||||||
def delete_cost_category_definition(self, cost_category_arn):
|
def delete_cost_category_definition(
|
||||||
|
self, cost_category_arn: str
|
||||||
|
) -> Tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
The EffectiveOn-parameter is not yet implemented
|
The EffectiveOn-parameter is not yet implemented
|
||||||
"""
|
"""
|
||||||
@ -84,8 +101,13 @@ class CostExplorerBackend(BaseBackend):
|
|||||||
return cost_category_arn, ""
|
return cost_category_arn, ""
|
||||||
|
|
||||||
def update_cost_category_definition(
|
def update_cost_category_definition(
|
||||||
self, cost_category_arn, rule_version, rules, default_value, split_charge_rules
|
self,
|
||||||
):
|
cost_category_arn: str,
|
||||||
|
rule_version: str,
|
||||||
|
rules: List[Dict[str, Any]],
|
||||||
|
default_value: str,
|
||||||
|
split_charge_rules: List[Dict[str, Any]],
|
||||||
|
) -> Tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
The EffectiveOn-parameter is not yet implemented
|
The EffectiveOn-parameter is not yet implemented
|
||||||
"""
|
"""
|
||||||
@ -94,13 +116,13 @@ class CostExplorerBackend(BaseBackend):
|
|||||||
|
|
||||||
return cost_category_arn, ""
|
return cost_category_arn, ""
|
||||||
|
|
||||||
def list_tags_for_resource(self, resource_arn):
|
def list_tags_for_resource(self, resource_arn: str) -> List[Dict[str, str]]:
|
||||||
return self.tagger.list_tags_for_resource(arn=resource_arn)["Tags"]
|
return self.tagger.list_tags_for_resource(arn=resource_arn)["Tags"]
|
||||||
|
|
||||||
def tag_resource(self, resource_arn, tags):
|
def tag_resource(self, resource_arn: str, tags: List[Dict[str, str]]) -> None:
|
||||||
self.tagger.tag_resource(resource_arn, tags)
|
self.tagger.tag_resource(resource_arn, tags)
|
||||||
|
|
||||||
def untag_resource(self, resource_arn, tag_keys):
|
def untag_resource(self, resource_arn: str, tag_keys: List[str]) -> None:
|
||||||
self.tagger.untag_resource_using_names(resource_arn, tag_keys)
|
self.tagger.untag_resource_using_names(resource_arn, tag_keys)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from .models import ce_backends
|
from .models import ce_backends, CostExplorerBackend
|
||||||
|
|
||||||
|
|
||||||
class CostExplorerResponse(BaseResponse):
|
class CostExplorerResponse(BaseResponse):
|
||||||
"""Handler for CostExplorer requests and responses."""
|
"""Handler for CostExplorer requests and responses."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ce_backend(self):
|
def ce_backend(self) -> CostExplorerBackend:
|
||||||
"""Return backend instance specific for this region."""
|
"""Return backend instance specific for this region."""
|
||||||
return ce_backends[self.current_account]["global"]
|
return ce_backends[self.current_account]["global"]
|
||||||
|
|
||||||
def create_cost_category_definition(self):
|
def create_cost_category_definition(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
name = params.get("Name")
|
name = params.get("Name")
|
||||||
rule_version = params.get("RuleVersion")
|
rule_version = params.get("RuleVersion")
|
||||||
@ -36,7 +36,7 @@ class CostExplorerResponse(BaseResponse):
|
|||||||
dict(CostCategoryArn=cost_category_arn, EffectiveStart=effective_start)
|
dict(CostCategoryArn=cost_category_arn, EffectiveStart=effective_start)
|
||||||
)
|
)
|
||||||
|
|
||||||
def describe_cost_category_definition(self):
|
def describe_cost_category_definition(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
cost_category_arn = params.get("CostCategoryArn")
|
cost_category_arn = params.get("CostCategoryArn")
|
||||||
cost_category = self.ce_backend.describe_cost_category_definition(
|
cost_category = self.ce_backend.describe_cost_category_definition(
|
||||||
@ -44,7 +44,7 @@ class CostExplorerResponse(BaseResponse):
|
|||||||
)
|
)
|
||||||
return json.dumps(dict(CostCategory=cost_category.to_json()))
|
return json.dumps(dict(CostCategory=cost_category.to_json()))
|
||||||
|
|
||||||
def delete_cost_category_definition(self):
|
def delete_cost_category_definition(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
cost_category_arn = params.get("CostCategoryArn")
|
cost_category_arn = params.get("CostCategoryArn")
|
||||||
(
|
(
|
||||||
@ -57,7 +57,7 @@ class CostExplorerResponse(BaseResponse):
|
|||||||
dict(CostCategoryArn=cost_category_arn, EffectiveEnd=effective_end)
|
dict(CostCategoryArn=cost_category_arn, EffectiveEnd=effective_end)
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_cost_category_definition(self):
|
def update_cost_category_definition(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
cost_category_arn = params.get("CostCategoryArn")
|
cost_category_arn = params.get("CostCategoryArn")
|
||||||
rule_version = params.get("RuleVersion")
|
rule_version = params.get("RuleVersion")
|
||||||
@ -78,20 +78,20 @@ class CostExplorerResponse(BaseResponse):
|
|||||||
dict(CostCategoryArn=cost_category_arn, EffectiveStart=effective_start)
|
dict(CostCategoryArn=cost_category_arn, EffectiveStart=effective_start)
|
||||||
)
|
)
|
||||||
|
|
||||||
def list_tags_for_resource(self):
|
def list_tags_for_resource(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
resource_arn = params.get("ResourceArn")
|
resource_arn = params.get("ResourceArn")
|
||||||
tags = self.ce_backend.list_tags_for_resource(resource_arn)
|
tags = self.ce_backend.list_tags_for_resource(resource_arn)
|
||||||
return json.dumps({"ResourceTags": tags})
|
return json.dumps({"ResourceTags": tags})
|
||||||
|
|
||||||
def tag_resource(self):
|
def tag_resource(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
resource_arn = params.get("ResourceArn")
|
resource_arn = params.get("ResourceArn")
|
||||||
tags = params.get("ResourceTags")
|
tags = params.get("ResourceTags")
|
||||||
self.ce_backend.tag_resource(resource_arn, tags)
|
self.ce_backend.tag_resource(resource_arn, tags)
|
||||||
return json.dumps({})
|
return json.dumps({})
|
||||||
|
|
||||||
def untag_resource(self):
|
def untag_resource(self) -> str:
|
||||||
params = json.loads(self.body)
|
params = json.loads(self.body)
|
||||||
resource_arn = params.get("ResourceArn")
|
resource_arn = params.get("ResourceArn")
|
||||||
tag_names = params.get("ResourceTagKeys")
|
tag_names = params.get("ResourceTagKeys")
|
||||||
|
@ -22,7 +22,7 @@ class TaggingService:
|
|||||||
result[key] = val
|
result[key] = val
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def list_tags_for_resource(self, arn: str) -> List[Dict[str, str]]:
|
def list_tags_for_resource(self, arn: str) -> Dict[str, List[Dict[str, str]]]:
|
||||||
"""Return list of tags inside dict with key of "tag_name".
|
"""Return list of tags inside dict with key of "tag_name".
|
||||||
|
|
||||||
Useful for describe functions; this return value can be added to
|
Useful for describe functions; this return value can be added to
|
||||||
|
@ -18,7 +18,7 @@ disable = W,C,R,E
|
|||||||
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
|
enable = anomalous-backslash-in-string, arguments-renamed, dangerous-default-value, deprecated-module, function-redefined, import-self, redefined-builtin, redefined-outer-name, reimported, pointless-statement, super-with-arguments, unused-argument, unused-import, unused-variable, useless-else-on-loop, wildcard-import
|
||||||
|
|
||||||
[mypy]
|
[mypy]
|
||||||
files= moto/a*,moto/b*
|
files= moto/a*,moto/b*,moto/ce
|
||||||
show_column_numbers=True
|
show_column_numbers=True
|
||||||
show_error_codes = True
|
show_error_codes = True
|
||||||
disable_error_code=abstract
|
disable_error_code=abstract
|
||||||
|
Loading…
Reference in New Issue
Block a user