Skip to content

Commit 93bfd68

Browse files
authored
[azure] [feat] Add new edges between resources (#1954)
1 parent 293b3e7 commit 93bfd68

File tree

10 files changed

+166
-109
lines changed

10 files changed

+166
-109
lines changed

plugins/azure/fix_plugin_azure/resource/base.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,12 @@ class AzureResource(BaseResource):
4848
def resource_subscription_id(self) -> Optional[str]:
4949
return self.extract_part("subscriptionId")
5050

51-
def resource_group_name(self) -> Optional[str]:
52-
return self.extract_part("resourceGroupName")
53-
5451
def extract_part(self, part: str) -> Optional[str]:
5552
"""
5653
Extracts a specific part from a resource ID.
5754
58-
The function takes a resource ID and a specified part to extract, such as 'subscriptionId'
59-
or 'resourceGroupName'. The resource ID is expected to follow the Azure Resource Manager
60-
path format.
55+
The function takes a resource ID and a specified part to extract, such as 'subscriptionId'.
56+
The resource ID is expected to follow the Azure Resource Manager path format.
6157
6258
Example:
6359
For the resource ID "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/...",
@@ -78,14 +74,6 @@ def extract_part(self, part: str) -> Optional[str]:
7874
if index := id_parts.index("subscriptions"):
7975
return id_parts[index + 1]
8076
return None
81-
82-
elif part == "resourceGroupName":
83-
if "resourceGroups" not in id_parts:
84-
return None
85-
if index := id_parts.index("resourceGroups"):
86-
return id_parts[index + 1]
87-
return None
88-
8977
else:
9078
return None
9179

plugins/azure/fix_plugin_azure/resource/compute.py

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class AzureAvailabilitySet(AzureResource):
6868
expect_array=True,
6969
)
7070
reference_kinds: ClassVar[ModelReference] = {
71-
"successors": {"default": ["azure_proximity_placement_group", "azure_virtual_machine"]},
71+
"successors": {"default": ["azure_proximity_placement_group", "azure_virtual_machine_base"]},
7272
}
7373
mapping: ClassVar[Dict[str, Bender]] = {
7474
"id": S("id"),
@@ -95,7 +95,7 @@ def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
9595
)
9696
if virtual_machines := self.virtual_machines_availability:
9797
for vm_id in virtual_machines:
98-
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureVirtualMachine, id=vm_id)
98+
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureVirtualMachineBase, id=vm_id)
9999

100100

101101
@define(eq=False, slots=False)
@@ -120,7 +120,7 @@ class AzureCapacityReservationGroup(AzureResource):
120120
expect_array=True,
121121
)
122122
reference_kinds: ClassVar[ModelReference] = {
123-
"successors": {"default": ["azure_virtual_machine"]},
123+
"successors": {"default": ["azure_virtual_machine_base"]},
124124
}
125125
mapping: ClassVar[Dict[str, Bender]] = {
126126
"id": S("id"),
@@ -140,7 +140,7 @@ class AzureCapacityReservationGroup(AzureResource):
140140
def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
141141
if virtual_machines := self.virtual_machines_associated:
142142
for vm_id in virtual_machines:
143-
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureVirtualMachine, id=vm_id)
143+
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureVirtualMachineBase, id=vm_id)
144144

145145

146146
@define(eq=False, slots=False)
@@ -1755,7 +1755,7 @@ class AzureRestorePointCollection(AzureResource):
17551755
expect_array=True,
17561756
)
17571757
reference_kinds: ClassVar[ModelReference] = {
1758-
"successors": {"default": ["azure_virtual_machine"]},
1758+
"successors": {"default": ["azure_virtual_machine_base"]},
17591759
}
17601760
mapping: ClassVar[Dict[str, Bender]] = {
17611761
"id": S("id"),
@@ -1773,7 +1773,7 @@ class AzureRestorePointCollection(AzureResource):
17731773

17741774
def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
17751775
if (source_id := self.source) and (vm_id := source_id.id):
1776-
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureVirtualMachine, id=vm_id)
1776+
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureVirtualMachineBase, id=vm_id)
17771777

17781778

17791779
@define(eq=False, slots=False)
@@ -2515,17 +2515,8 @@ class AzureVirtualMachineIdentity:
25152515

25162516

25172517
@define(eq=False, slots=False)
2518-
class AzureVirtualMachine(AzureResource, BaseInstance):
2519-
kind: ClassVar[str] = "azure_virtual_machine"
2520-
api_spec: ClassVar[AzureApiSpec] = AzureApiSpec(
2521-
service="compute",
2522-
version="2023-03-01",
2523-
path="/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachines",
2524-
path_parameters=["subscriptionId"],
2525-
query_parameters=["api-version"],
2526-
access_path="value",
2527-
expect_array=True,
2528-
)
2518+
class AzureVirtualMachineBase(AzureResource, BaseInstance):
2519+
kind: ClassVar[str] = "azure_virtual_machine_base"
25292520
reference_kinds: ClassVar[ModelReference] = {
25302521
"predecessors": {
25312522
"default": [
@@ -2780,6 +2771,20 @@ def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
27802771
)
27812772

27822773

2774+
@define(eq=False, slots=False)
2775+
class AzureVirtualMachine(AzureVirtualMachineBase):
2776+
kind: ClassVar[str] = "azure_virtual_machine"
2777+
api_spec: ClassVar[AzureApiSpec] = AzureApiSpec(
2778+
service="compute",
2779+
version="2023-03-01",
2780+
path="/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachines",
2781+
path_parameters=["subscriptionId"],
2782+
query_parameters=["api-version"],
2783+
access_path="value",
2784+
expect_array=True,
2785+
)
2786+
2787+
27832788
@define(eq=False, slots=False)
27842789
class AzureRollingUpgradePolicy:
27852790
kind: ClassVar[str] = "azure_rolling_upgrade_policy"
@@ -3229,7 +3234,8 @@ class AzureVirtualMachineScaleSet(AzureResource, BaseAutoScalingGroup):
32293234
expect_array=True,
32303235
)
32313236
reference_kinds: ClassVar[ModelReference] = {
3232-
"predecessors": {"default": ["azure_load_balancer"]},
3237+
"predecessors": {"default": ["azure_load_balancer", "azure_subnet"]},
3238+
"successors": {"default": ["azure_virtual_machine_scale_set_instance"]},
32333239
}
32343240
mapping: ClassVar[Dict[str, Bender]] = {
32353241
"id": S("id"),
@@ -3287,6 +3293,30 @@ class AzureVirtualMachineScaleSet(AzureResource, BaseAutoScalingGroup):
32873293
virtual_machine_profile: Optional[AzureVirtualMachineScaleSetVMProfile] = field(default=None, metadata={'description': 'Describes a virtual machine scale set virtual machine profile.'}) # fmt: skip
32883294
zone_balance: Optional[bool] = field(default=None, metadata={'description': 'Whether to force strictly even virtual machine distribution cross x-zones in case there is zone outage. Zonebalance property can only be set if the zones property of the scale set contains more than one zone. If there are no zones or only one zone specified, then zonebalance property should not be set.'}) # fmt: skip
32893295

3296+
def post_process(self, graph_builder: GraphBuilder, source: Json) -> None:
3297+
def collect_vmss_instances() -> None:
3298+
api_spec = AzureApiSpec(
3299+
service="compute",
3300+
version="2023-09-01",
3301+
path=f"{self.id}/virtualMachines",
3302+
path_parameters=[],
3303+
query_parameters=["api-version"],
3304+
access_path="value",
3305+
expect_array=True,
3306+
)
3307+
3308+
items = graph_builder.client.list(api_spec)
3309+
vmss_instance_ids = [str(item.get("id")) for item in items if item.get("id") is not None]
3310+
3311+
AzureVirtualMachineScaleSetInstance.collect(items, graph_builder)
3312+
3313+
for vmss_instance_id in vmss_instance_ids:
3314+
graph_builder.add_edge(
3315+
self, edge_type=EdgeType.default, clazz=AzureVirtualMachineScaleSetInstance, id=vmss_instance_id
3316+
)
3317+
3318+
graph_builder.submit_work("azure_all", collect_vmss_instances)
3319+
32903320
def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
32913321
if (
32923322
(vm_profile := self.virtual_machine_profile)
@@ -3298,14 +3328,22 @@ def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
32983328
for ip_config in ip_configs:
32993329
if baps := ip_config.load_balancer_backend_address_pools:
33003330
for bap in baps:
3301-
if bap_id := bap:
3302-
builder.add_edge(
3303-
self,
3304-
edge_type=EdgeType.default,
3305-
reverse=True,
3306-
clazz=AzureLoadBalancer,
3307-
id=bap_id,
3308-
)
3331+
bap_id = "/".join(bap.split("/")[:-2])
3332+
builder.add_edge(
3333+
self,
3334+
edge_type=EdgeType.default,
3335+
reverse=True,
3336+
clazz=AzureLoadBalancer,
3337+
id=bap_id,
3338+
)
3339+
if subnet_id := ip_config.subnet:
3340+
builder.add_edge(
3341+
self,
3342+
edge_type=EdgeType.default,
3343+
reverse=True,
3344+
clazz=AzureSubnet,
3345+
id=subnet_id,
3346+
)
33093347

33103348

33113349
@define(eq=False, slots=False)
@@ -3344,6 +3382,13 @@ def pre_process(self, graph_builder: GraphBuilder, source: Json) -> None:
33443382
self.location = graph_builder.location.name if graph_builder.location else ""
33453383

33463384

3385+
@define(eq=False, slots=False)
3386+
class AzureVirtualMachineScaleSetInstance(AzureVirtualMachineBase):
3387+
# note: instances are collected as part of collecting AzureVirtualMachineScaleSets
3388+
3389+
kind: ClassVar[str] = "azure_virtual_machine_scale_set_instance"
3390+
3391+
33473392
resources: List[Type[AzureResource]] = [
33483393
AzureAvailabilitySet,
33493394
AzureCapacityReservationGroup,

plugins/azure/fix_plugin_azure/resource/containerservice.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime
2-
from typing import ClassVar, Dict, Optional, List, Type
2+
from typing import ClassVar, Dict, Optional, List, Tuple, Type
33

44
from attr import define, field
55

@@ -814,7 +814,7 @@ class AzureManagedCluster(AzureResource):
814814
expect_array=True,
815815
)
816816
reference_kinds: ClassVar[ModelReference] = {
817-
"successors": {"default": ["azure_disk_encryption_set"]},
817+
"successors": {"default": ["azure_disk_encryption_set", "azure_virtual_machine_scale_set"]},
818818
}
819819
mapping: ClassVar[Dict[str, Bender]] = AzureTrackedResource.mapping | {
820820
"id": S("id"),
@@ -875,9 +875,7 @@ class AzureManagedCluster(AzureResource):
875875
}
876876
aad_profile: Optional[AzureManagedClusterAADProfile] = field(default=None, metadata={'description': 'For more details see [managed AAD on AKS](https://docs.microsoft.com/azure/aks/managed-aad).'}) # fmt: skip
877877
addon_profiles: Optional[Dict[str, AzureManagedClusterAddonProfile]] = field(default=None, metadata={'description': 'The profile of managed cluster add-on.'}) # fmt: skip
878-
agent_pool_profiles: Optional[List[str]] = field(
879-
default=None, metadata={"description": "The agent pool properties."}
880-
)
878+
agent_pool_profiles: Optional[List[str]] = field(default=None, metadata={"description": "The agent pool properties."}) # fmt: skip
881879
api_server_access_profile: Optional[AzureManagedClusterAPIServerAccessProfile] = field(default=None, metadata={'description': 'Access profile for managed cluster API server.'}) # fmt: skip
882880
auto_scaler_profile: Optional[AutoScalerProfile] = field(default=None, metadata={'description': 'Parameters to be applied to the cluster-autoscaler when enabled'}) # fmt: skip
883881
auto_upgrade_profile: Optional[AzureManagedClusterAutoUpgradeProfile] = field(default=None, metadata={'description': 'Auto upgrade profile for a managed cluster.'}) # fmt: skip
@@ -919,11 +917,30 @@ class AzureManagedCluster(AzureResource):
919917
workload_auto_scaler_profile: Optional[AzureManagedClusterWorkloadAutoScalerProfile] = field(default=None, metadata={'description': 'Workload Auto-scaler profile for the managed cluster.'}) # fmt: skip
920918

921919
def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
922-
from fix_plugin_azure.resource.compute import AzureDiskEncryptionSet
920+
from fix_plugin_azure.resource.compute import AzureDiskEncryptionSet, AzureVirtualMachineScaleSet
923921

924922
if disk_id := self.disk_encryption_set_id:
925923
builder.add_edge(self, edge_type=EdgeType.default, clazz=AzureDiskEncryptionSet, id=disk_id)
926924

925+
if agent_pool_profiles := self.agent_pool_profiles:
926+
vmss_agent_pool_names_and_ids = self._get_poolnames_and_vmss_ids(builder)
927+
for agent_pool_profile_name in agent_pool_profiles:
928+
for info in vmss_agent_pool_names_and_ids:
929+
pool_name, vmss_id = info
930+
if agent_pool_profile_name == pool_name:
931+
builder.add_edge(
932+
self, edge_type=EdgeType.default, clazz=AzureVirtualMachineScaleSet, id=vmss_id
933+
)
934+
935+
def _get_poolnames_and_vmss_ids(self, builder: GraphBuilder) -> List[Tuple[str, str]]:
936+
from fix_plugin_azure.resource.compute import AzureVirtualMachineScaleSet
937+
938+
return [
939+
(poolname, vmss_id)
940+
for vmss in builder.nodes(clazz=AzureVirtualMachineScaleSet)
941+
if (poolname := vmss.tags.get("aks-managed-poolName")) and (vmss_id := vmss.id)
942+
]
943+
927944

928945
@define(eq=False, slots=False)
929946
class AzureProxyResource:

plugins/azure/fix_plugin_azure/resource/metrics.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ def query_for(
219219
"aggregation",
220220
"interval",
221221
"AutoAdjustTimegrain",
222+
"ValidateDimensions",
222223
],
223224
access_path=None,
224225
expect_array=False,
@@ -272,6 +273,7 @@ def _query_for_single(
272273
aggregation=aggregation,
273274
interval=interval,
274275
AutoAdjustTimegrain=True,
276+
ValidateDimensions=False,
275277
)
276278
# Iterate over the retrieved data and map it to AzureMetricData objects
277279
for single in part:

0 commit comments

Comments
 (0)