Skip to content

Commit f00a428

Browse files
author
ikemilian-lewis
committed
Resolve type issues after rebase
1 parent 30e2a2a commit f00a428

2 files changed

Lines changed: 143 additions & 7 deletions

File tree

src/orb/providers/azure/configuration/template_extension.py

Lines changed: 140 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,27 @@
22

33
from typing import Any, Optional
44

5-
from pydantic import BaseModel, Field
5+
from pydantic import BaseModel, ConfigDict, Field
6+
7+
from orb.providers.azure.domain.template.value_objects import (
8+
AzureAllocationStrategy,
9+
AzureCapacityReservationGroupId,
10+
AzureDataDisk,
11+
AzureDiskEncryptionSetId,
12+
AzureEvictionPolicy,
13+
AzureImageReference,
14+
AzureNetworkConfig,
15+
AzureOSDiskConfig,
16+
AzurePriority,
17+
AzureProximityPlacementGroupId,
18+
AzureProviderApi,
19+
AzureResourceGroupName,
20+
AzureSecurityType,
21+
AzureUpgradePolicyMode,
22+
AzureVmSizePreference,
23+
AzureVMSSOrchestrationMode,
24+
)
25+
626

727
class AzureTemplateExtensionConfig(BaseModel):
828
"""Azure-specific template extension defaults.
@@ -11,6 +31,120 @@ class AzureTemplateExtensionConfig(BaseModel):
1131
can apply Azure defaults when ``provider_type == "azure"``.
1232
"""
1333

34+
model_config = ConfigDict(populate_by_name=True)
35+
36+
# Azure DTO-only fields preserved by TemplateDTO.provider_config round-trips.
37+
resource_group: Optional[AzureResourceGroupName] = Field(
38+
None, description="Azure resource group for the template"
39+
)
40+
location: Optional[str] = Field(None, description="Azure location for the template")
41+
subscription_id: Optional[str] = Field(
42+
None, description="Azure subscription override for the template"
43+
)
44+
vmss_name: Optional[str] = Field(None, description="Explicit VMSS name")
45+
orchestration_mode: Optional[AzureVMSSOrchestrationMode] = Field(
46+
None, description="VMSS orchestration mode"
47+
)
48+
platform_fault_domain_count: Optional[int] = Field(
49+
None, description="Fault domain count for Flexible orchestration"
50+
)
51+
single_placement_group: Optional[bool] = Field(
52+
None, description="Restrict VMSS to a single placement group"
53+
)
54+
image: Optional[AzureImageReference] = Field(
55+
None, description="Azure VM image reference"
56+
)
57+
eviction_policy: Optional[AzureEvictionPolicy] = Field(
58+
None, description="Spot eviction policy"
59+
)
60+
billing_profile_max_price: Optional[float] = Field(
61+
None, description="Maximum Spot VM price"
62+
)
63+
spot_percentage: Optional[int] = Field(
64+
None, description="Desired percentage of Spot VMs"
65+
)
66+
base_regular_priority_count: Optional[int] = Field(
67+
None, description="Base regular-priority VM count for priority mix"
68+
)
69+
spot_restore_enabled: Optional[bool] = Field(
70+
None, description="Enable Spot Try-Restore"
71+
)
72+
spot_restore_timeout: Optional[str] = Field(
73+
None, description="ISO 8601 Spot Try-Restore timeout"
74+
)
75+
zones: Optional[list[str]] = Field(None, description="Availability zones")
76+
zone_balance: Optional[bool] = Field(None, description="Enable zone balancing")
77+
proximity_placement_group_id: Optional[AzureProximityPlacementGroupId] = Field(
78+
None, description="Proximity placement group ARM resource ID"
79+
)
80+
capacity_reservation_group_id: Optional[AzureCapacityReservationGroupId] = Field(
81+
None, description="Capacity reservation group ARM resource ID"
82+
)
83+
os_disk: Optional[AzureOSDiskConfig] = Field(None, description="OS disk config")
84+
data_disks: Optional[list[AzureDataDisk]] = Field(None, description="Data disks")
85+
network_config: Optional[AzureNetworkConfig] = Field(
86+
None, description="Azure networking config"
87+
)
88+
security_type: Optional[AzureSecurityType] = Field(
89+
None, description="VM security type"
90+
)
91+
secure_boot_enabled: Optional[bool] = Field(
92+
None, description="Enable UEFI Secure Boot"
93+
)
94+
vtpm_enabled: Optional[bool] = Field(None, description="Enable vTPM")
95+
encryption_at_host: Optional[bool] = Field(
96+
None, description="Enable host-based encryption"
97+
)
98+
disk_encryption_set_id: Optional[AzureDiskEncryptionSetId] = Field(
99+
None, description="Disk encryption set ARM resource ID"
100+
)
101+
ssh_key_name: Optional[str] = Field(
102+
None, description="Azure SSH Public Key resource name"
103+
)
104+
ssh_public_keys: Optional[list[str]] = Field(
105+
None, description="Inline SSH public keys"
106+
)
107+
user_assigned_identity_ids: Optional[list[str]] = Field(
108+
None, description="User-assigned managed identity ARM resource IDs"
109+
)
110+
system_assigned_identity: Optional[bool] = Field(
111+
None, description="Enable system-assigned managed identity"
112+
)
113+
custom_data: Optional[str] = Field(None, description="Base64 custom-data payload")
114+
extension_profile: Optional[list[dict[str, Any]]] = Field(
115+
None, description="VMSS extension definitions"
116+
)
117+
overprovision: Optional[bool] = Field(
118+
None, description="Enable VMSS overprovisioning"
119+
)
120+
upgrade_policy_mode: Optional[AzureUpgradePolicyMode] = Field(
121+
None, description="VMSS upgrade policy mode"
122+
)
123+
provider_api_spec: Optional[dict[str, Any]] = Field(
124+
None, description="Raw Azure provider request payload override"
125+
)
126+
provider_api_spec_file: Optional[str] = Field(
127+
None, description="Path to a native Azure provider spec file"
128+
)
129+
cluster_name: Optional[str] = Field(None, description="CycleCloud cluster name")
130+
node_array: Optional[str] = Field(None, description="CycleCloud node array")
131+
cyclecloud_url: Optional[str] = Field(None, description="CycleCloud API URL")
132+
cyclecloud_credential_path: Optional[str] = Field(
133+
None, description="CycleCloud credential reference path"
134+
)
135+
cyclecloud_verify_ssl: Optional[bool] = Field(
136+
None, description="CycleCloud SSL verification setting"
137+
)
138+
cyclecloud_auth_mode: Optional[str] = Field(
139+
None, description="CycleCloud auth mode override"
140+
)
141+
cyclecloud_aad_scope: Optional[str] = Field(
142+
None, description="CycleCloud AAD scope"
143+
)
144+
provider_api: Optional[AzureProviderApi] = Field(
145+
None, description="Azure provider API"
146+
)
147+
14148
# VM configuration
15149
vm_size: str = Field(
16150
"Standard_D4s_v5",
@@ -20,20 +154,20 @@ class AzureTemplateExtensionConfig(BaseModel):
20154
default=None,
21155
description="Additional Azure VM size candidates for generic instance mix",
22156
)
23-
vm_size_preferences: Optional[list[dict[str, Any]]] = Field(
157+
vm_size_preferences: Optional[list[AzureVmSizePreference]] = Field(
24158
default=None,
25159
description="Ranked Azure VM size candidates for Prioritized VMSS instance mix",
26160
)
27-
vmss_allocation_strategy: Optional[str] = Field(
161+
vmss_allocation_strategy: Optional[AzureAllocationStrategy] = Field(
28162
default=None,
29163
description="Azure VMSS instance-mix allocation strategy",
30164
)
31165

32166
# Pricing
33-
priority: str = Field("Regular", description="Default VM priority")
167+
priority: AzurePriority = Field(AzurePriority.REGULAR, description="Default VM priority")
34168

35169
# OS disk
36-
os_disk_type: str = Field("Premium_LRS", description="Default OS disk type")
170+
os_disk_type: Optional[str] = Field(None, description="Default OS disk type")
37171
os_disk_size_gb: Optional[int] = Field(
38172
None, description="OS disk size in GiB (None = image default)"
39173
)
@@ -63,7 +197,7 @@ def to_template_defaults(self) -> dict[str, Any]:
63197
defaults["vmss_allocation_strategy"] = self.vmss_allocation_strategy
64198
if self.os_disk_size_gb is not None:
65199
defaults["os_disk"] = {
66-
"storage_account_type": self.os_disk_type,
200+
"storage_account_type": self.os_disk_type or "Premium_LRS",
67201
"disk_size_gb": self.os_disk_size_gb,
68202
}
69203
return defaults

tests/unit/test_template_roundtrip.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from orb.infrastructure.template.dtos import TemplateDTO
2020
from orb.providers.aws.domain.template.aws_template_aggregate import AWSTemplate
2121
from orb.providers.aws.infrastructure.handlers.ec2_fleet.handler import EC2FleetHandler
22+
from orb.providers.azure.configuration.template_extension import AzureTemplateExtensionConfig
2223
from orb.providers.azure.domain.template.azure_template_aggregate import AzureTemplate
2324

2425

@@ -253,6 +254,7 @@ def test_azure_custom_metadata_does_not_leak_into_provider_config_roundtrip(self
253254
result = dto.to_template_config()
254255

255256
assert dto.metadata == {"custom_key": "custom-value"}
256-
assert "custom_key" not in dto.provider_config
257+
assert isinstance(dto.provider_config, AzureTemplateExtensionConfig)
258+
assert "custom_key" not in dto.provider_config.model_dump(exclude_none=True)
257259
assert result["metadata"]["custom_key"] == "custom-value"
258260
AzureTemplate.model_validate(result)

0 commit comments

Comments
 (0)