Skip to content

Commit

Permalink
[azure][feat] Azure adjust names and connections (#2183)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthias Veit <[email protected]>
  • Loading branch information
1101-1 and aquamatthias authored Sep 11, 2024
1 parent 2b99e41 commit 85fbe2d
Show file tree
Hide file tree
Showing 28 changed files with 938 additions and 799 deletions.
14 changes: 11 additions & 3 deletions plugins/azure/fix_plugin_azure/azure_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ class AzureResourceSpec:
query_parameters: List[str] = []
access_path: Optional[str] = None
expect_array: bool = False
expected_error_codes: List[str] = field(factory=list)
expected_error_codes: Dict[str, Optional[str]] = field(factory=dict)
"""
A dictionary that maps specific error codes (str) to corresponding hints (Optional[str]) to provide additional context or troubleshooting information when an error occurs.
"""

def request(self, client: "MicrosoftResourceManagementClient", **kwargs: Any) -> HttpRequest:
ser = Serializer()
Expand Down Expand Up @@ -118,7 +121,10 @@ class RestApiSpec:
parameters: Optional[Dict[str, str]] = None
access_path: Optional[str] = None
expect_array: bool = False
expected_error_codes: List[str] = field(factory=list)
expected_error_codes: Dict[str, Optional[str]] = field(factory=dict)
"""
A dictionary that maps specific error codes (str) to corresponding hints (Optional[str]) to provide additional context or troubleshooting information when an error occurs.
"""

def __attrs_post_init__(self) -> None:
if self.scope == "":
Expand Down Expand Up @@ -317,13 +323,15 @@ def _list_with_retry(self, spec: MicrosoftRestSpec, **kwargs: Any) -> Optional[L
return None
except HttpResponseError as e:
if error := e.error:
code = error.code or "Unknown"
if error.code == "NoRegisteredProviderFound":
return None # API not available in this region
elif error.code in spec.expected_error_codes:
if hint := spec.expected_error_codes.get(code):
self.accumulator.add_error(False, code, spec.service, spec.action, str(hint))
return None
elif error.code == "BadRequest" and spec.service == "metric":
raise MetricRequestError from e
code = error.code or "Unknown"
self.accumulator.add_error(False, code, spec.service, spec.action, str(e), self.location)
log.warning(f"[Azure] Client Error: status={e.status_code}, error={e.error}, message={e}, spec={spec}")
return None
Expand Down
18 changes: 9 additions & 9 deletions plugins/azure/fix_plugin_azure/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
MicrosoftResource,
)
from fix_plugin_azure.resource.compute import (
AzureVirtualMachineSize,
AzureDiskType,
AzureDiskTypePricing,
AzureComputeVirtualMachineSize,
AzureComputeDiskType,
AzureComputeDiskTypePricing,
resources as compute_resources,
)
from fix_plugin_azure.resource.containerservice import resources as aks_resources
Expand All @@ -32,7 +32,7 @@
from fix_plugin_azure.resource.monitor import resources as monitor_resources
from fix_plugin_azure.resource.mysql import AzureMysqlServerType, resources as mysql_resources
from fix_plugin_azure.resource.network import (
AzureExpressRoutePortsLocation,
AzureNetworkExpressRoutePortsLocation,
AzureNetworkVirtualApplianceSku,
AzureNetworkUsage,
resources as network_resources,
Expand Down Expand Up @@ -256,10 +256,10 @@ def remove_usage_zero_value() -> None:
remove_nodes.append(node)
self._delete_nodes(remove_nodes)

rm_nodes(AzureVirtualMachineSize, AzureLocation)
rm_nodes(AzureExpressRoutePortsLocation, AzureSubscription)
rm_nodes(AzureComputeVirtualMachineSize, AzureLocation)
rm_nodes(AzureNetworkExpressRoutePortsLocation, AzureSubscription)
rm_nodes(AzureNetworkVirtualApplianceSku, AzureSubscription)
rm_nodes(AzureDiskType, AzureSubscription)
rm_nodes(AzureComputeDiskType, AzureSubscription)
rm_nodes(AzureMachineLearningVirtualMachineSize, AzureLocation)
rm_nodes(AzureStorageSku, AzureLocation)
rm_nodes(AzureMysqlServerType, AzureSubscription)
Expand All @@ -269,9 +269,9 @@ def remove_usage_zero_value() -> None:
remove_usage_zero_value()

def after_collect(self) -> None:
# Filter unnecessary nodes such as AzureDiskTypePricing
# Filter unnecessary nodes such as AzureComputeDiskTypePricing
nodes_to_remove = []
node_types = (AzureDiskTypePricing,)
node_types = (AzureComputeDiskTypePricing,)

for node in self.graph.nodes:
if not isinstance(node, node_types):
Expand Down
37 changes: 22 additions & 15 deletions plugins/azure/fix_plugin_azure/resource/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class AzurePrincipal:


@define(eq=False, slots=False)
class AzureDenyAssignment(MicrosoftResource):
kind: ClassVar[str] = "azure_deny_assignment"
class AzureAuthorizationDenyAssignment(MicrosoftResource):
kind: ClassVar[str] = "azure_authorization_deny_assignment"
api_spec: ClassVar[AzureResourceSpec] = AzureResourceSpec(
service="authorization",
version="2022-04-01",
Expand Down Expand Up @@ -109,8 +109,8 @@ class AzureDenyAssignment(MicrosoftResource):


@define(eq=False, slots=False)
class AzureRoleAssignment(MicrosoftResource):
kind: ClassVar[str] = "azure_role_assignment"
class AzureAuthorizationRoleAssignment(MicrosoftResource):
kind: ClassVar[str] = "azure_authorization_role_assignment"
api_spec: ClassVar[AzureResourceSpec] = AzureResourceSpec(
service="authorization",
version="2022-04-01",
Expand All @@ -130,9 +130,16 @@ class AzureRoleAssignment(MicrosoftResource):
"Resource": "azure_resource",
}
reference_kinds: ClassVar[ModelReference] = {
"successors": {"default": ["azure_role_definition", *(p.kind for p in MicrosoftGraphPrincipalTypes)]},
"successors": {
"default": ["azure_authorization_role_definition", *(p.kind for p in MicrosoftGraphPrincipalTypes)]
},
"predecessors": {
"default": ["azure_role_definition", "azure_subscription", "azure_resource_group", "azure_resource"]
"default": [
"azure_authorization_role_definition",
"azure_subscription",
"azure_resource_group",
"azure_resource",
]
},
}
mapping: ClassVar[Dict[str, Bender]] = {
Expand Down Expand Up @@ -171,7 +178,7 @@ class AzureRoleAssignment(MicrosoftResource):
def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:
# role definition
if rid := self.role_definition_id:
builder.add_edge(self, clazz=AzureRoleDefinition, id=rid)
builder.add_edge(self, clazz=AzureAuthorizationRoleDefinition, id=rid)

# scope
if scope := self.scope:
Expand Down Expand Up @@ -206,8 +213,8 @@ class AzurePermission:


@define(eq=False, slots=False)
class AzureRoleDefinition(MicrosoftResource, BaseRole):
kind: ClassVar[str] = "azure_role_definition"
class AzureAuthorizationRoleDefinition(MicrosoftResource, BaseRole):
kind: ClassVar[str] = "azure_authorization_role_definition"
api_spec: ClassVar[AzureResourceSpec] = AzureResourceSpec(
service="authorization",
version="2022-04-01",
Expand Down Expand Up @@ -242,8 +249,8 @@ class AzureRoleDefinition(MicrosoftResource, BaseRole):


@define(eq=False, slots=False)
class AzureManagementLock(MicrosoftResource):
kind: ClassVar[str] = "azure_management_lock"
class AzureAuthorizationManagementLock(MicrosoftResource):
kind: ClassVar[str] = "azure_authorization_management_lock"
api_spec: ClassVar[AzureResourceSpec] = AzureResourceSpec(
service="resources",
version="2020-05-01",
Expand Down Expand Up @@ -275,8 +282,8 @@ def connect_in_graph(self, builder: GraphBuilder, source: Json) -> None:


resources: List[Type[MicrosoftResource]] = [
AzureDenyAssignment,
AzureManagementLock,
AzureRoleAssignment,
AzureRoleDefinition,
AzureAuthorizationDenyAssignment,
AzureAuthorizationManagementLock,
AzureAuthorizationRoleAssignment,
AzureAuthorizationRoleDefinition,
]
14 changes: 7 additions & 7 deletions plugins/azure/fix_plugin_azure/resource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ def collect_resources_in_group() -> None:
self._resource_ids_in_group = [r["id"] for r in graph_builder.client.list(resources_api_spec)]

def collect_network_gateways() -> None:
from fix_plugin_azure.resource.network import AzureVirtualNetworkGateway
from fix_plugin_azure.resource.network import AzureNetworkVirtualNetworkGateway

api_spec = AzureResourceSpec(
service="network",
Expand All @@ -388,10 +388,10 @@ def collect_network_gateways() -> None:
expect_array=True,
)
items = graph_builder.client.list(api_spec)
AzureVirtualNetworkGateway.collect(items, graph_builder)
AzureNetworkVirtualNetworkGateway.collect(items, graph_builder)

def collect_local_network_gateway() -> None:
from fix_plugin_azure.resource.network import AzureLocalNetworkGateway
from fix_plugin_azure.resource.network import AzureNetworkLocalNetworkGateway

api_spec = AzureResourceSpec(
service="network",
Expand All @@ -403,10 +403,10 @@ def collect_local_network_gateway() -> None:
expect_array=True,
)
items = graph_builder.client.list(api_spec)
AzureLocalNetworkGateway.collect(items, graph_builder)
AzureNetworkLocalNetworkGateway.collect(items, graph_builder)

def collect_network_gateway_connections() -> None:
from fix_plugin_azure.resource.network import AzureVirtualNetworkGatewayConnection
from fix_plugin_azure.resource.network import AzureNetworkVirtualNetworkGatewayConnection

api_spec = AzureResourceSpec(
service="network",
Expand All @@ -418,7 +418,7 @@ def collect_network_gateway_connections() -> None:
expect_array=True,
)
items = graph_builder.client.list(api_spec)
AzureVirtualNetworkGatewayConnection.collect(items, graph_builder)
AzureNetworkVirtualNetworkGatewayConnection.collect(items, graph_builder)

graph_builder.submit_work(service_name, collect_resources_in_group)
graph_builder.submit_work(service_name, collect_network_gateways)
Expand Down Expand Up @@ -453,7 +453,7 @@ class AzureBaseUsage:
current_value: Optional[int] = field(default=None, metadata={"description": "The current value of the usage."})
limit: Optional[int] = field(default=None, metadata={"description": "The limit of usage."})
unit: Optional[str] = field(default=None, metadata={"description": "An enum describing the unit of measurement."})
_expected_error_codes: ClassVar[List[str]] = ["SubscriptionHasNoUsages"]
_expected_error_codes: ClassVar[Dict[str, Optional[str]]] = {"SubscriptionHasNoUsages": None}


@define(eq=False, slots=False)
Expand Down
Loading

0 comments on commit 85fbe2d

Please sign in to comment.