Skip to content

Commit 06ff0a3

Browse files
authored
[azure][feat] Connect CosmosDB resources to the location instead of subscription (#2214)
1 parent 70e1eec commit 06ff0a3

File tree

4 files changed

+37
-15
lines changed

4 files changed

+37
-15
lines changed

plugins/azure/fix_plugin_azure/collector.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import abstractmethod
33
from concurrent.futures import ThreadPoolExecutor, Future
44
from datetime import datetime, timezone
5-
from typing import Any, Optional, Type, List, Dict
5+
from typing import Any, Optional, Type, List, Dict, Set
66

77
from azure.core.utils import CaseInsensitiveDict
88

@@ -215,7 +215,11 @@ def after_collect(self) -> None:
215215
class AzureSubscriptionCollector(MicrosoftBaseCollector):
216216
def locations(self, builder: GraphBuilder) -> Dict[str, BaseRegion]:
217217
locations = AzureLocation.collect_resources(builder)
218-
return CaseInsensitiveDict({loc.safe_name: loc for loc in locations}) # type: ignore
218+
# сreate a location lookup map with lowercase name and display name of the locations
219+
locations_map = CaseInsensitiveDict()
220+
locations_map.update({loc.safe_name: loc for loc in locations})
221+
locations_map.update({loc.display_name or loc.safe_name: loc for loc in locations})
222+
return locations_map # type: ignore
219223

220224
def collect_with(self, builder: GraphBuilder, locations: Dict[str, BaseRegion]) -> None:
221225
# add deferred edge to organization
@@ -224,8 +228,11 @@ def collect_with(self, builder: GraphBuilder, locations: Dict[str, BaseRegion])
224228
regional_resources = [r for r in subscription_resources if resource_with_params(r, "location")]
225229
global_resources = list(set(subscription_resources) - set(regional_resources))
226230
self.collect_resource_list("subscription", builder, global_resources)
231+
processed_locations: Set[str] = set()
227232
for location in locations.values():
228-
self.collect_resource_list(location.safe_name, builder.with_location(location), regional_resources)
233+
if location.safe_name not in processed_locations:
234+
self.collect_resource_list(location.safe_name, builder.with_location(location), regional_resources)
235+
processed_locations.add(location.safe_name)
229236

230237
def remove_unused(self) -> None:
231238
remove_nodes = []
@@ -264,7 +271,7 @@ def remove_usage_zero_value() -> None:
264271
rm_nodes(AzureStorageSku, AzureLocation)
265272
rm_nodes(AzureMysqlServerType, AzureSubscription)
266273
rm_nodes(AzurePostgresqlServerType, AzureSubscription)
267-
rm_nodes(AzureCosmosDBLocation, AzureSubscription, check_pred=False)
274+
rm_nodes(AzureCosmosDBLocation, AzureLocation, check_pred=False)
268275
rm_nodes(AzureLocation, check_pred=False)
269276
remove_usage_zero_value()
270277

plugins/azure/fix_plugin_azure/resource/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,11 @@ def add_node(self, node: MicrosoftResourceType, source: Optional[Json] = None) -
857857
if location := self.location_lookup.get(source_location):
858858
node._region = location
859859
last_edge_key = self.add_edge(location, node=node)
860+
elif (node_location := getattr(node, "location", None)) is not None:
861+
# reference the location node if available in resource property
862+
if location := self.location_lookup.get(node_location):
863+
node._region = location
864+
last_edge_key = self.add_edge(location, node=node)
860865
if source and "locations" in source:
861866
for loc in source["locations"]:
862867
# reference the location node if available

plugins/azure/fix_plugin_azure/resource/cosmosdb.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@
3232
log = logging.getLogger("fix.plugins.azure")
3333

3434

35+
class CosmosDBLocationSetter:
36+
def __init__(self) -> None:
37+
self.location: Optional[str] = None
38+
39+
def pre_process(self, graph_builder: GraphBuilder, source: Json) -> None:
40+
if isinstance(self, MicrosoftResource):
41+
if location := self.extract_part("locations"):
42+
self.location = location
43+
44+
3545
@define(eq=False, slots=False)
3646
class AzureManagedCassandraReaperStatus:
3747
kind: ClassVar[str] = "azure_managed_cassandra_reaper_status"
@@ -1550,7 +1560,7 @@ class AzureRestorableLocationResource:
15501560

15511561

15521562
@define(eq=False, slots=False)
1553-
class AzureCosmosDBRestorableAccount(MicrosoftResource):
1563+
class AzureCosmosDBRestorableAccount(CosmosDBLocationSetter, MicrosoftResource):
15541564
kind: ClassVar[str] = "azure_cosmos_db_restorable_account"
15551565
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable Account"
15561566
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2032,7 +2042,7 @@ def collect_usages(cls, account_id: str, raw: List[Json], builder: GraphBuilder)
20322042

20332043

20342044
@define(eq=False, slots=False)
2035-
class AzureCosmosDBLocation(MicrosoftResource):
2045+
class AzureCosmosDBLocation(CosmosDBLocationSetter, MicrosoftResource):
20362046
kind: ClassVar[str] = "azure_cosmos_db_location"
20372047
_kind_display: ClassVar[str] = "Azure Cosmos DB Location"
20382048
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2163,7 +2173,7 @@ class AzureRestorableDatabase:
21632173

21642174

21652175
@define(eq=False, slots=False)
2166-
class AzureCosmosDBRestorableGremlinDatabase(MicrosoftResource):
2176+
class AzureCosmosDBRestorableGremlinDatabase(CosmosDBLocationSetter, MicrosoftResource):
21672177
kind: ClassVar[str] = "azure_cosmos_db_restorable_gremlin_database"
21682178
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable Gremlin Database"
21692179
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2211,7 +2221,7 @@ def collect_restorable_graphs() -> None:
22112221

22122222

22132223
@define(eq=False, slots=False)
2214-
class AzureCosmosDBRestorableGremlinGraph(MicrosoftResource):
2224+
class AzureCosmosDBRestorableGremlinGraph(CosmosDBLocationSetter, MicrosoftResource):
22152225
kind: ClassVar[str] = "azure_cosmos_db_restorable_gremlin_graph"
22162226
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable Gremlin Graph"
22172227
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2229,7 +2239,7 @@ class AzureCosmosDBRestorableGremlinGraph(MicrosoftResource):
22292239

22302240

22312241
@define(eq=False, slots=False)
2232-
class AzureCosmosDBRestorableMongoDBCollection(MicrosoftResource):
2242+
class AzureCosmosDBRestorableMongoDBCollection(CosmosDBLocationSetter, MicrosoftResource):
22332243
kind: ClassVar[str] = "azure_cosmos_db_restorable_mongo_db_collection"
22342244
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable Mongo DB Collection"
22352245
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2247,7 +2257,7 @@ class AzureCosmosDBRestorableMongoDBCollection(MicrosoftResource):
22472257

22482258

22492259
@define(eq=False, slots=False)
2250-
class AzureCosmosDBRestorableMongoDBDatabase(MicrosoftResource):
2260+
class AzureCosmosDBRestorableMongoDBDatabase(CosmosDBLocationSetter, MicrosoftResource):
22512261
kind: ClassVar[str] = "azure_cosmos_db_restorable_mongo_db_database"
22522262
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable Mongo DB Database"
22532263
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2295,7 +2305,7 @@ def collect_restorable_collections() -> None:
22952305

22962306

22972307
@define(eq=False, slots=False)
2298-
class AzureCosmosDBRestorableSqlContainer(MicrosoftResource):
2308+
class AzureCosmosDBRestorableSqlContainer(CosmosDBLocationSetter, MicrosoftResource):
22992309
kind: ClassVar[str] = "azure_cosmos_db_restorable_sql_container"
23002310
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable SQL Container"
23012311
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2344,7 +2354,7 @@ class AzureExtendedPropertiesSqlDatabase(AzureSqlDatabaseResource):
23442354

23452355

23462356
@define(eq=False, slots=False)
2347-
class AzureCosmosDBRestorableSqlDatabase(MicrosoftResource):
2357+
class AzureCosmosDBRestorableSqlDatabase(CosmosDBLocationSetter, MicrosoftResource):
23482358
kind: ClassVar[str] = "azure_cosmos_db_restorable_sql_database"
23492359
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable SQL Database"
23502360
_kind_service: ClassVar[Optional[str]] = service_name
@@ -2406,7 +2416,7 @@ def collect_restorable_containers() -> None:
24062416

24072417

24082418
@define(eq=False, slots=False)
2409-
class AzureCosmosDBRestorableTable(MicrosoftResource):
2419+
class AzureCosmosDBRestorableTable(CosmosDBLocationSetter, MicrosoftResource):
24102420
kind: ClassVar[str] = "azure_cosmos_db_restorable_table"
24112421
_kind_display: ClassVar[str] = "Azure Cosmos DB Restorable Table"
24122422
_kind_service: ClassVar[Optional[str]] = service_name

plugins/azure/test/collector_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ def test_collect(
4848
config, Cloud(id="azure"), azure_subscription, credentials, core_feedback
4949
)
5050
subscription_collector.collect()
51-
assert len(subscription_collector.graph.nodes) == 645
52-
assert len(subscription_collector.graph.edges) == 1034
51+
assert len(subscription_collector.graph.nodes) == 654
52+
assert len(subscription_collector.graph.edges) == 1043
5353

5454
graph_collector = MicrosoftGraphOrganizationCollector(
5555
config, Cloud(id="azure"), MicrosoftGraphOrganization(id="test", name="test"), credentials, core_feedback

0 commit comments

Comments
 (0)