Skip to content

Commit b1dacaf

Browse files
author
ikemilian-lewis
committed
fix: ci pyright
1 parent cfea023 commit b1dacaf

8 files changed

Lines changed: 98 additions & 68 deletions

File tree

dev-tools/setup/run_tool.sh

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set -e
77

88
TOOL_NAME="$1"
99
shift # Remove tool name from arguments
10+
read -r -a UV_RUN_OPTIONS <<< "${RUN_TOOL_UV_OPTIONS:-}"
1011

1112
# Walk upward from $PWD looking for a UV/Python project root.
1213
# Prints the path on success; prints nothing and returns 1 if not found.
@@ -105,12 +106,12 @@ run_tool() {
105106
adjusted_args=$(adjust_relative_args "$project_root" "$@")
106107
if [ -n "$adjusted_args" ]; then
107108
# shellcheck disable=SC2086
108-
(cd "$project_root" && uv run "${TOOL_NAME}" $adjusted_args)
109+
(cd "$project_root" && uv run "${UV_RUN_OPTIONS[@]}" "${TOOL_NAME}" $adjusted_args)
109110
else
110-
(cd "$project_root" && uv run "${TOOL_NAME}")
111+
(cd "$project_root" && uv run "${UV_RUN_OPTIONS[@]}" "${TOOL_NAME}")
111112
fi
112113
else
113-
uv run "${TOOL_NAME}" "$@"
114+
uv run "${UV_RUN_OPTIONS[@]}" "${TOOL_NAME}" "$@"
114115
fi
115116
elif [ -f ".venv/bin/${TOOL_NAME}" ] && venv_usable ".venv"; then
116117
echo "Executing with venv..."
@@ -125,12 +126,12 @@ run_tool() {
125126
adjusted_args=$(adjust_relative_args "$project_root" "$@")
126127
if [ -n "$adjusted_args" ]; then
127128
# shellcheck disable=SC2086
128-
(cd "$project_root" && uv run python -m "${TOOL_NAME}" $adjusted_args)
129+
(cd "$project_root" && uv run "${UV_RUN_OPTIONS[@]}" python -m "${TOOL_NAME}" $adjusted_args)
129130
else
130-
(cd "$project_root" && uv run python -m "${TOOL_NAME}")
131+
(cd "$project_root" && uv run "${UV_RUN_OPTIONS[@]}" python -m "${TOOL_NAME}")
131132
fi
132133
else
133-
uv run python -m "${TOOL_NAME}" "$@"
134+
uv run "${UV_RUN_OPTIONS[@]}" python -m "${TOOL_NAME}" "$@"
134135
fi
135136
else
136137
python3 -m "${TOOL_NAME}" "$@"

makefiles/ci.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ci-quality-radon: ## Run radon complexity analysis
1616
$(call run-tool,radon,cc $(PACKAGE) --min B --show-complexity)
1717
$(call run-tool,radon,mi $(PACKAGE) --min B)
1818

19+
ci-quality-pyright: RUN_TOOL_UV_OPTIONS := --extra all-providers
1920
ci-quality-pyright: ## Run pyright type checking
2021
@echo "Running pyright type check..."
2122
$(call run-tool,pyright,)

makefiles/common.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ DOCS_BUILD_DIR := $(DOCS_DIR)/site
7171

7272
# Centralized tool execution function
7373
# Usage: $(call run-tool,tool-name,arguments[,working-dir])
74+
# Set RUN_TOOL_UV_OPTIONS for options that belong to `uv run`, not the tool.
7475
define run-tool
75-
$(if $(3),cd $(3) && ../dev-tools/setup/run_tool.sh $(1) $(2),@dev-tools/setup/run_tool.sh $(1) $(2))
76+
$(if $(3),cd $(3) && RUN_TOOL_UV_OPTIONS="$(RUN_TOOL_UV_OPTIONS)" ../dev-tools/setup/run_tool.sh $(1) $(2),@RUN_TOOL_UV_OPTIONS="$(RUN_TOOL_UV_OPTIONS)" dev-tools/setup/run_tool.sh $(1) $(2))
7677
endef
7778

7879
# Virtual environment setup (common dependency for all makefiles)

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import re
44
from typing import Optional
55

6-
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, field_validator, model_validator
6+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
7+
from pydantic_settings import BaseSettings, SettingsConfigDict
78

89
from orb.infrastructure.interfaces.provider import BaseProviderConfig
910

@@ -64,7 +65,7 @@ def reject_inline_basic_auth(cls, data: object) -> object:
6465
# ---------------------------------------------------------------------------
6566

6667

67-
class AzureProviderConfig(BaseProviderConfig):
68+
class AzureProviderConfig(BaseSettings, BaseProviderConfig): # type: ignore[misc] # Pydantic model mixin MRO is valid at runtime.
6869
"""Configuration for the Azure provider (VMSS / Compute Fleet).
6970
7071
The shared provider interface uses ``region`` across providers. Azure's
@@ -73,7 +74,14 @@ class AzureProviderConfig(BaseProviderConfig):
7374
Azure-native ``location`` input at the boundary.
7475
"""
7576

76-
model_config = ConfigDict(populate_by_name=True, extra="forbid")
77+
# Pydantic's inherited model_config annotations disagree despite compatible runtime values.
78+
model_config = SettingsConfigDict( # type: ignore[assignment]
79+
env_prefix="ORB_AZURE_",
80+
case_sensitive=False,
81+
populate_by_name=True,
82+
env_nested_delimiter="__",
83+
extra="forbid",
84+
)
7785

7886
# ------------------------------------------------------------------
7987
# Provider identity
@@ -82,7 +90,6 @@ class AzureProviderConfig(BaseProviderConfig):
8290
region: str = Field(
8391
default="eastus2",
8492
description="Azure location slug",
85-
validation_alias=AliasChoices("location", "region"),
8693
)
8794

8895
# ------------------------------------------------------------------

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

Lines changed: 71 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -36,102 +36,118 @@ class AzureTemplateExtensionConfig(BaseModel):
3636

3737
# Azure DTO-only fields preserved by TemplateDTO.provider_config round-trips.
3838
resource_group: Optional[AzureResourceGroupName] = Field(
39-
None, description="Azure resource group for the template"
39+
default=None, description="Azure resource group for the template"
4040
)
41-
location: Optional[str] = Field(None, description="Azure location for the template")
41+
location: Optional[str] = Field(default=None, description="Azure location for the template")
4242
subscription_id: Optional[str] = Field(
43-
None, description="Azure subscription override for the template"
43+
default=None, description="Azure subscription override for the template"
4444
)
45-
vmss_name: Optional[str] = Field(None, description="Explicit VMSS name")
45+
vmss_name: Optional[str] = Field(default=None, description="Explicit VMSS name")
4646
orchestration_mode: Optional[AzureVMSSOrchestrationMode] = Field(
47-
None, description="VMSS orchestration mode"
47+
default=None, description="VMSS orchestration mode"
4848
)
4949
platform_fault_domain_count: Optional[int] = Field(
50-
None, description="Fault domain count for Flexible orchestration"
50+
default=None, description="Fault domain count for Flexible orchestration"
5151
)
5252
single_placement_group: Optional[bool] = Field(
53-
None, description="Restrict VMSS to a single placement group"
53+
default=None, description="Restrict VMSS to a single placement group"
54+
)
55+
image: Optional[AzureImageReference] = Field(
56+
default=None, description="Azure VM image reference"
57+
)
58+
eviction_policy: Optional[AzureEvictionPolicy] = Field(
59+
default=None, description="Spot eviction policy"
60+
)
61+
billing_profile_max_price: Optional[float] = Field(
62+
default=None, description="Maximum Spot VM price"
63+
)
64+
spot_percentage: Optional[int] = Field(
65+
default=None, description="Desired percentage of Spot VMs"
5466
)
55-
image: Optional[AzureImageReference] = Field(None, description="Azure VM image reference")
56-
eviction_policy: Optional[AzureEvictionPolicy] = Field(None, description="Spot eviction policy")
57-
billing_profile_max_price: Optional[float] = Field(None, description="Maximum Spot VM price")
58-
spot_percentage: Optional[int] = Field(None, description="Desired percentage of Spot VMs")
5967
base_regular_priority_count: Optional[int] = Field(
60-
None, description="Base regular-priority VM count for priority mix"
68+
default=None, description="Base regular-priority VM count for priority mix"
69+
)
70+
spot_restore_enabled: Optional[bool] = Field(
71+
default=None, description="Enable Spot Try-Restore"
6172
)
62-
spot_restore_enabled: Optional[bool] = Field(None, description="Enable Spot Try-Restore")
6373
spot_restore_timeout: Optional[str] = Field(
64-
None, description="ISO 8601 Spot Try-Restore timeout"
74+
default=None, description="ISO 8601 Spot Try-Restore timeout"
6575
)
6676
spot_placement_score_enabled: Optional[bool] = Field(
67-
None, description="Enable Azure Spot Placement Score planning before launch"
77+
default=None, description="Enable Azure Spot Placement Score planning before launch"
6878
)
6979
placement_split_strategy: Optional[PlacementSplitStrategy] = Field(
70-
None, description="How Spot Placement Score launches split capacity"
80+
default=None, description="How Spot Placement Score launches split capacity"
7181
)
7282
placement_primary_share_percent: Optional[int] = Field(
73-
None, description="Capacity percentage assigned to the top placement candidate"
83+
default=None, description="Capacity percentage assigned to the top placement candidate"
7484
)
7585
placement_regions: Optional[list[str]] = Field(
76-
None, description="Azure regions considered for Spot Placement Score planning"
86+
default=None, description="Azure regions considered for Spot Placement Score planning"
7787
)
7888
placement_zones: Optional[list[str]] = Field(
79-
None, description="Azure zones considered for Spot Placement Score planning"
89+
default=None, description="Azure zones considered for Spot Placement Score planning"
8090
)
81-
zones: Optional[list[str]] = Field(None, description="Availability zones")
82-
zone_balance: Optional[bool] = Field(None, description="Enable zone balancing")
91+
zones: Optional[list[str]] = Field(default=None, description="Availability zones")
92+
zone_balance: Optional[bool] = Field(default=None, description="Enable zone balancing")
8393
proximity_placement_group_id: Optional[AzureProximityPlacementGroupId] = Field(
84-
None, description="Proximity placement group ARM resource ID"
94+
default=None, description="Proximity placement group ARM resource ID"
8595
)
8696
capacity_reservation_group_id: Optional[AzureCapacityReservationGroupId] = Field(
87-
None, description="Capacity reservation group ARM resource ID"
97+
default=None, description="Capacity reservation group ARM resource ID"
8898
)
89-
os_disk: Optional[AzureOSDiskConfig] = Field(None, description="OS disk config")
90-
data_disks: Optional[list[AzureDataDisk]] = Field(None, description="Data disks")
99+
os_disk: Optional[AzureOSDiskConfig] = Field(default=None, description="OS disk config")
100+
data_disks: Optional[list[AzureDataDisk]] = Field(default=None, description="Data disks")
91101
network_config: Optional[AzureNetworkConfig] = Field(
92-
None, description="Azure networking config"
102+
default=None, description="Azure networking config"
103+
)
104+
security_type: Optional[AzureSecurityType] = Field(default=None, description="VM security type")
105+
secure_boot_enabled: Optional[bool] = Field(default=None, description="Enable UEFI Secure Boot")
106+
vtpm_enabled: Optional[bool] = Field(default=None, description="Enable vTPM")
107+
encryption_at_host: Optional[bool] = Field(
108+
default=None, description="Enable host-based encryption"
93109
)
94-
security_type: Optional[AzureSecurityType] = Field(None, description="VM security type")
95-
secure_boot_enabled: Optional[bool] = Field(None, description="Enable UEFI Secure Boot")
96-
vtpm_enabled: Optional[bool] = Field(None, description="Enable vTPM")
97-
encryption_at_host: Optional[bool] = Field(None, description="Enable host-based encryption")
98110
disk_encryption_set_id: Optional[AzureDiskEncryptionSetId] = Field(
99-
None, description="Disk encryption set ARM resource ID"
111+
default=None, description="Disk encryption set ARM resource ID"
112+
)
113+
ssh_key_name: Optional[str] = Field(
114+
default=None, description="Azure SSH Public Key resource name"
100115
)
101-
ssh_key_name: Optional[str] = Field(None, description="Azure SSH Public Key resource name")
102-
ssh_public_keys: Optional[list[str]] = Field(None, description="Inline SSH public keys")
116+
ssh_public_keys: Optional[list[str]] = Field(default=None, description="Inline SSH public keys")
103117
user_assigned_identity_ids: Optional[list[str]] = Field(
104-
None, description="User-assigned managed identity ARM resource IDs"
118+
default=None, description="User-assigned managed identity ARM resource IDs"
105119
)
106120
system_assigned_identity: Optional[bool] = Field(
107-
None, description="Enable system-assigned managed identity"
121+
default=None, description="Enable system-assigned managed identity"
108122
)
109-
custom_data: Optional[str] = Field(None, description="Base64 custom-data payload")
123+
custom_data: Optional[str] = Field(default=None, description="Base64 custom-data payload")
110124
extension_profile: Optional[list[dict[str, Any]]] = Field(
111-
None, description="VMSS extension definitions"
125+
default=None, description="VMSS extension definitions"
112126
)
113-
overprovision: Optional[bool] = Field(None, description="Enable VMSS overprovisioning")
127+
overprovision: Optional[bool] = Field(default=None, description="Enable VMSS overprovisioning")
114128
upgrade_policy_mode: Optional[AzureUpgradePolicyMode] = Field(
115-
None, description="VMSS upgrade policy mode"
129+
default=None, description="VMSS upgrade policy mode"
116130
)
117131
provider_api_spec: Optional[dict[str, Any]] = Field(
118-
None, description="Raw Azure provider request payload override"
132+
default=None, description="Raw Azure provider request payload override"
119133
)
120134
provider_api_spec_file: Optional[str] = Field(
121-
None, description="Path to a native Azure provider spec file"
135+
default=None, description="Path to a native Azure provider spec file"
122136
)
123-
cluster_name: Optional[str] = Field(None, description="CycleCloud cluster name")
124-
node_array: Optional[str] = Field(None, description="CycleCloud node array")
125-
cyclecloud_url: Optional[str] = Field(None, description="CycleCloud API URL")
137+
cluster_name: Optional[str] = Field(default=None, description="CycleCloud cluster name")
138+
node_array: Optional[str] = Field(default=None, description="CycleCloud node array")
139+
cyclecloud_url: Optional[str] = Field(default=None, description="CycleCloud API URL")
126140
cyclecloud_credential_path: Optional[str] = Field(
127-
None, description="CycleCloud credential reference path"
141+
default=None, description="CycleCloud credential reference path"
128142
)
129143
cyclecloud_verify_ssl: Optional[bool] = Field(
130-
None, description="CycleCloud SSL verification setting"
144+
default=None, description="CycleCloud SSL verification setting"
131145
)
132-
cyclecloud_auth_mode: Optional[str] = Field(None, description="CycleCloud auth mode override")
133-
cyclecloud_aad_scope: Optional[str] = Field(None, description="CycleCloud AAD scope")
134-
provider_api: Optional[AzureProviderApi] = Field(None, description="Azure provider API")
146+
cyclecloud_auth_mode: Optional[str] = Field(
147+
default=None, description="CycleCloud auth mode override"
148+
)
149+
cyclecloud_aad_scope: Optional[str] = Field(default=None, description="CycleCloud AAD scope")
150+
provider_api: Optional[AzureProviderApi] = Field(default=None, description="Azure provider API")
135151

136152
# VM configuration
137153
vm_size: Optional[str] = Field(
@@ -152,16 +168,18 @@ class AzureTemplateExtensionConfig(BaseModel):
152168
)
153169

154170
# Pricing
155-
priority: AzurePriority = Field(AzurePriority.REGULAR, description="Default VM priority")
171+
priority: AzurePriority = Field(
172+
default=AzurePriority.REGULAR, description="Default VM priority"
173+
)
156174

157175
# OS disk
158-
os_disk_type: Optional[str] = Field(None, description="Default OS disk type")
176+
os_disk_type: Optional[str] = Field(default=None, description="Default OS disk type")
159177
os_disk_size_gb: Optional[int] = Field(
160-
None, description="OS disk size in GiB (None = image default)"
178+
default=None, description="OS disk size in GiB (None = image default)"
161179
)
162180

163181
# Identity
164-
admin_username: str = Field("azureuser", description="Default admin username")
182+
admin_username: str = Field(default="azureuser", description="Default admin username")
165183

166184
# Freeform attributes
167185
node_attributes: dict[str, Any] = Field(

src/orb/providers/azure/registration.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,10 +526,7 @@ def register_azure_template_factory(
526526
def get_azure_extension_defaults() -> dict[str, Any]:
527527
"""Get default Azure extension configuration."""
528528
return AzureTemplateExtensionConfig(
529-
priority="Regular",
530529
os_disk_type="Premium_LRS",
531-
os_disk_size_gb=None,
532-
admin_username="azureuser",
533530
).to_template_defaults()
534531

535532

src/orb/providers/azure/services/resource_metadata_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def attach_provider_fulfilment(
290290
) -> CheckHostsStatusResult:
291291
"""Attach and return the canonical provider status contract."""
292292
status_result = CheckHostsStatusResult(
293-
instances=list(instances),
293+
instances=[dict(instance) for instance in instances],
294294
fulfilment=_build_provider_fulfilment(
295295
metadata=metadata,
296296
instances=instances,

tests/providers/azure/test_azure_config_and_infra.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636

3737

3838
class TestAzureProviderConfig:
39+
def test_loads_provider_settings_from_azure_environment_prefix(self, monkeypatch):
40+
monkeypatch.setenv("ORB_AZURE_REGION", "westeurope")
41+
42+
assert AzureProviderConfig().region == "westeurope"
43+
3944
def test_location_alias_populates_region(self):
4045
config = AzureProviderConfig(
4146
subscription_id="12345678-1234-1234-1234-123456789012",

0 commit comments

Comments
 (0)