From 0f62e6cdc18aec23f54bce1b5501ed76dfd6fff2 Mon Sep 17 00:00:00 2001 From: ian-flores Date: Wed, 18 Feb 2026 13:28:31 -0800 Subject: [PATCH 1/5] chore: add git worktree docs and roborev configuration --- .envrc | 14 ++++++++++++++ .roborev.toml | 2 ++ CLAUDE.md | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 .envrc create mode 100644 .roborev.toml diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..53f98aa --- /dev/null +++ b/.envrc @@ -0,0 +1,14 @@ +# Inherit workspace-level environment (PTD_CONFIG, PTD_TARGETS_CONFIG_DIR, etc.) +source_up + +# Override PTD to point to THIS directory (works for both main checkout and worktrees) +export PTD="${PWD}" +export PROJECT_ROOT="${PTD}" +export TOP="${PTD}" +export PTD_TOP="${PTD}" + +# Add this checkout's .local/bin to PATH (so worktrees use their own built binary) +PATH_add ".local/bin" + +# Python/uv configuration for Pulumi operations +export UV_PROJECT="${PTD}/python-pulumi" diff --git a/.roborev.toml b/.roborev.toml new file mode 100644 index 0000000..7f625af --- /dev/null +++ b/.roborev.toml @@ -0,0 +1,2 @@ +# roborev per-repo configuration +agent = "claude-code" diff --git a/CLAUDE.md b/CLAUDE.md index 54ef8e7..32a3b6b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -97,6 +97,47 @@ The Go CLI communicates the infrastructure path to Python Pulumi stacks via the - `just aws-unset`: Unset all AWS environment variables +## Git Worktrees + +**Always use git worktrees instead of plain branches.** This enables concurrent Claude sessions in the same repo. + +### Creating a Worktree + +```bash +# From the ptd repo root (or any existing worktree) +git worktree add ../../.worktrees/ptd- -b +``` + +Worktrees live at `ptd-workspace/.worktrees/ptd-` — always prefix with `ptd-` to avoid collisions with other repos. + +### After Creating a Worktree + +1. **Build the binary** — each worktree needs its own ptd binary: + ```bash + cd ../../.worktrees/ptd- + just build-cmd + ``` +2. **direnv** — if direnv is available, `cd` into the worktree and run `direnv allow`. The `.envrc` uses `source_up` to inherit workspace vars and overrides `PTD` to point to the worktree. +3. **For agents without direnv** — set env vars explicitly before running `ptd` commands: + ```bash + export PTD="$(pwd)" + export PATH="${PTD}/.local/bin:${PATH}" + ``` + +### Cleaning Up + +```bash +# From the main checkout +git worktree remove ../../.worktrees/ptd- +``` + +### Rules + +- **NEVER** use `git checkout -b` for new work — always `git worktree add` +- **NEVER** put worktrees inside the repo directory — always use `../../.worktrees/ptd-` +- **ALWAYS** rebuild the binary after creating a worktree (`just build-cmd`) +- Branch names: kebab-case, no slashes, no usernames + ## Contributing When contributing to the project: From c054537af0fa8d39e2db4996d148c39bcb1d5ca0 Mon Sep 17 00:00:00 2001 From: ian-flores Date: Wed, 18 Feb 2026 14:09:27 -0800 Subject: [PATCH 2/5] chore: address review feedback on worktree docs --- CLAUDE.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 32a3b6b..2746a54 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -103,12 +103,17 @@ The Go CLI communicates the infrastructure path to Python Pulumi stacks via the ### Creating a Worktree +This repo is expected to live at `ptd-workspace/ptd/`. The `../../.worktrees/` relative path resolves to `ptd-workspace/.worktrees/` in that layout. + ```bash -# From the ptd repo root (or any existing worktree) +# New branch git worktree add ../../.worktrees/ptd- -b + +# Existing remote branch +git worktree add ../../.worktrees/ptd- ``` -Worktrees live at `ptd-workspace/.worktrees/ptd-` — always prefix with `ptd-` to avoid collisions with other repos. +Always prefix worktree directories with `ptd-` to avoid collisions with other repos. ### After Creating a Worktree @@ -136,7 +141,7 @@ git worktree remove ../../.worktrees/ptd- - **NEVER** use `git checkout -b` for new work — always `git worktree add` - **NEVER** put worktrees inside the repo directory — always use `../../.worktrees/ptd-` - **ALWAYS** rebuild the binary after creating a worktree (`just build-cmd`) -- Branch names: kebab-case, no slashes, no usernames +- Branch names: kebab-case, no slashes, no usernames (slashes break worktree directory paths) ## Contributing From 0cd88f0c8a3d976057202277dd013f99fa5f1c77 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 12 Feb 2026 21:00:51 -0800 Subject: [PATCH 3/5] feat(azure): add configurable bastion instance type Add bastion_instance_type configuration field to AzureWorkloadConfig, matching AWS naming for cross-cloud consistency. Defaults to "Standard_B1s" for backward compatibility. --- lib/types/workload.go | 1 + lib/types/workload_test.go | 54 +++++++ python-pulumi/src/ptd/azure_workload.py | 1 + .../src/ptd/pulumi_resources/azure_bastion.py | 5 +- .../azure_workload_persistent.py | 1 + .../tests/test_azure_bastion_config.py | 143 ++++++++++++++++++ 6 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 python-pulumi/tests/test_azure_bastion_config.py diff --git a/lib/types/workload.go b/lib/types/workload.go index dfd6e9d..7cb2cff 100644 --- a/lib/types/workload.go +++ b/lib/types/workload.go @@ -95,6 +95,7 @@ type AzureWorkloadConfig struct { ClientID string `yaml:"client_id"` SecretsProviderClientID string `yaml:"secrets_provider_client_id"` AdminGroupID string `yaml:"admin_group_id"` + BastionInstanceType string `yaml:"bastion_instance_type"` InstanceType string `yaml:"instance_type"` ControlPlaneNodeCount int `yaml:"control_plane_node_count"` WorkerNodeCount int `yaml:"worker_node_count"` diff --git a/lib/types/workload_test.go b/lib/types/workload_test.go index ebee795..f052a50 100644 --- a/lib/types/workload_test.go +++ b/lib/types/workload_test.go @@ -151,6 +151,60 @@ func TestAzureWorkloadConfigSerialization(t *testing.T) { unmarshaledConfig.Clusters["main"].Components.SecretStoreCsiDriverAzureProviderVersion) } +func TestAzureWorkloadConfigBastionInstanceType(t *testing.T) { + // Test that bastion_instance_type field is properly serialized/deserialized + config := AzureWorkloadConfig{ + SubscriptionID: "123456789-abcd-efgh-ijkl-1234567890ab", + TenantID: "abcdefgh-1234-5678-ijkl-1234567890ab", + Region: "eastus", + ClientID: "12345678-abcd-efgh-ijkl-1234567890ab", + SecretsProviderClientID: "98765432-abcd-efgh-ijkl-1234567890ab", + BastionInstanceType: "Standard_B2s", + InstanceType: "Standard_D4s_v3", + ControlPlaneNodeCount: 1, + WorkerNodeCount: 1, + DBStorageSizeGB: 20, + } + + // Marshal to YAML + yamlData, err := yaml.Marshal(config) + assert.NoError(t, err) + + // Verify the YAML contains the bastion_instance_type field + yamlString := string(yamlData) + assert.Contains(t, yamlString, "bastion_instance_type: Standard_B2s") + + // Unmarshal from YAML + var unmarshaledConfig AzureWorkloadConfig + err = yaml.Unmarshal(yamlData, &unmarshaledConfig) + assert.NoError(t, err) + + // Verify bastion_instance_type matches + assert.Equal(t, config.BastionInstanceType, unmarshaledConfig.BastionInstanceType) + assert.Equal(t, "Standard_B2s", unmarshaledConfig.BastionInstanceType) +} + +func TestAzureWorkloadConfigBastionInstanceTypeFromYAML(t *testing.T) { + // Test parsing bastion_instance_type from YAML + yamlContent := ` +subscription_id: "123456789-abcd-efgh-ijkl-1234567890ab" +tenant_id: "abcdefgh-1234-5678-ijkl-1234567890ab" +region: "eastus" +client_id: "12345678-abcd-efgh-ijkl-1234567890ab" +secrets_provider_client_id: "98765432-abcd-efgh-ijkl-1234567890ab" +bastion_instance_type: "Standard_D2s_v3" +instance_type: "Standard_D4s_v3" +control_plane_node_count: 1 +worker_node_count: 1 +db_storage_size_gb: 20 +` + + var config AzureWorkloadConfig + err := yaml.Unmarshal([]byte(yamlContent), &config) + assert.NoError(t, err) + assert.Equal(t, "Standard_D2s_v3", config.BastionInstanceType) +} + func TestAzureUserNodePoolConfigSerialization(t *testing.T) { initialCount := 5 maxPods := 50 diff --git a/python-pulumi/src/ptd/azure_workload.py b/python-pulumi/src/ptd/azure_workload.py index 940f48c..dae9a08 100644 --- a/python-pulumi/src/ptd/azure_workload.py +++ b/python-pulumi/src/ptd/azure_workload.py @@ -66,6 +66,7 @@ class AzureWorkloadConfig(ptd.WorkloadConfig): resource_tags: dict[str, str] | None = None protect_persistent_resources: bool = True admin_group_id: str | None = None + bastion_instance_type: str = "Standard_B1s" ppm_file_share_size_gib: int = 100 # Minimum size for PPM Azure File Share in GiB diff --git a/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py b/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py index ab0cbc5..6658d46 100644 --- a/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py +++ b/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py @@ -26,6 +26,7 @@ def __init__( resource_group_name: str | pulumi.Output[str], location: str | pulumi.Output[str], tags: dict[str, str], + vm_size: str | pulumi.Output[str], *args, **kwargs, ): @@ -40,6 +41,8 @@ def __init__( **kwargs, ) + self.vm_size = vm_size + # generate a key pair for the jumpbox self.jumpbox_ssh_key = tls.PrivateKey( "ssh-key", @@ -106,7 +109,7 @@ def __init__( resource_group_name=resource_group_name, location=location, hardware_profile=compute.HardwareProfileArgs( - vm_size="Standard_B1s", + vm_size=self.vm_size, ), storage_profile=compute.StorageProfileArgs( image_reference=compute.ImageReferenceArgs( diff --git a/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py b/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py index a3dd5ad..b097580 100644 --- a/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py +++ b/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py @@ -789,6 +789,7 @@ def _define_bastion(self): resource_group_name=self.vnet_rsg_name, location=self.workload.cfg.region, tags=self.required_tags, + vm_size=self.workload.cfg.bastion_instance_type, opts=pulumi.ResourceOptions( protect=self.workload.cfg.protect_persistent_resources, ), diff --git a/python-pulumi/tests/test_azure_bastion_config.py b/python-pulumi/tests/test_azure_bastion_config.py new file mode 100644 index 0000000..cbfd9ad --- /dev/null +++ b/python-pulumi/tests/test_azure_bastion_config.py @@ -0,0 +1,143 @@ +"""Tests for Azure Bastion instance type configuration.""" + +import typing + +import pulumi + +import ptd.azure_workload + + +class AzureBastionMocks(pulumi.runtime.Mocks): + """Mock Pulumi resource calls for testing.""" + + def new_resource(self, args: pulumi.runtime.MockResourceArgs) -> tuple[str | None, dict[typing.Any, typing.Any]]: + """Mock resource creation - return resource ID and properties.""" + # Return the inputs as outputs for testing + return args.name, dict(args.inputs) + + def call( + self, _args: pulumi.runtime.MockCallArgs + ) -> dict[typing.Any, typing.Any] | tuple[dict[typing.Any, typing.Any], list[tuple[str, str]] | None]: + """Mock function calls.""" + return {} + + +pulumi.runtime.set_mocks(AzureBastionMocks(), preview=False) + + +def test_azure_workload_config_default_bastion_instance_type(): + """Test that AzureWorkloadConfig has correct default bastion_instance_type.""" + config = ptd.azure_workload.AzureWorkloadConfig( + clusters={}, + subscription_id="test-sub-id", + tenant_id="test-tenant-id", + client_id="test-client-id", + secrets_provider_client_id="test-sp-client-id", + network=ptd.azure_workload.NetworkConfig( + private_subnet_cidr="10.0.1.0/24", + db_subnet_cidr="10.0.2.0/24", + netapp_subnet_cidr="10.0.3.0/24", + app_gateway_subnet_cidr="10.0.4.0/24", + bastion_subnet_cidr="10.0.5.0/24", + ), + region="eastus", + control_room_account_id="test-account", + control_room_cluster_name="test-cluster", + control_room_domain="test.example.com", + control_room_region="eastus", + control_room_role_name="test-role", + control_room_state_bucket="test-bucket", + environment="test", + network_trust=ptd.NetworkTrust.FULL, + sites={}, + true_name="test-workload", + ) + + # Verify default value + assert config.bastion_instance_type == "Standard_B1s" + + +def test_azure_workload_config_custom_bastion_instance_type(): + """Test that AzureWorkloadConfig accepts custom bastion_instance_type.""" + config = ptd.azure_workload.AzureWorkloadConfig( + clusters={}, + subscription_id="test-sub-id", + tenant_id="test-tenant-id", + client_id="test-client-id", + secrets_provider_client_id="test-sp-client-id", + network=ptd.azure_workload.NetworkConfig( + private_subnet_cidr="10.0.1.0/24", + db_subnet_cidr="10.0.2.0/24", + netapp_subnet_cidr="10.0.3.0/24", + app_gateway_subnet_cidr="10.0.4.0/24", + bastion_subnet_cidr="10.0.5.0/24", + ), + region="eastus", + bastion_instance_type="Standard_B2s", + control_room_account_id="test-account", + control_room_cluster_name="test-cluster", + control_room_domain="test.example.com", + control_room_region="eastus", + control_room_role_name="test-role", + control_room_state_bucket="test-bucket", + environment="test", + network_trust=ptd.NetworkTrust.FULL, + sites={}, + true_name="test-workload", + ) + + # Verify custom value + assert config.bastion_instance_type == "Standard_B2s" + + +def test_azure_workload_config_bastion_instance_type_matches_aws_pattern(): + """Test that Azure uses same field name as AWS for consistency.""" + aws_config = ptd.aws_workload.AWSWorkloadConfig( + clusters={}, + account_id="123456789012", + region="us-east-1", + control_room_account_id="123456789012", + control_room_cluster_name="test-cluster", + control_room_domain="test.example.com", + control_room_region="us-east-1", + control_room_role_name="test-role", + control_room_state_bucket="test-bucket", + environment="test", + network_trust=ptd.NetworkTrust.FULL, + sites={}, + true_name="test-workload", + ) + + azure_config = ptd.azure_workload.AzureWorkloadConfig( + clusters={}, + subscription_id="test-sub-id", + tenant_id="test-tenant-id", + client_id="test-client-id", + secrets_provider_client_id="test-sp-client-id", + network=ptd.azure_workload.NetworkConfig( + private_subnet_cidr="10.0.1.0/24", + db_subnet_cidr="10.0.2.0/24", + netapp_subnet_cidr="10.0.3.0/24", + app_gateway_subnet_cidr="10.0.4.0/24", + bastion_subnet_cidr="10.0.5.0/24", + ), + region="eastus", + control_room_account_id="test-account", + control_room_cluster_name="test-cluster", + control_room_domain="test.example.com", + control_room_region="eastus", + control_room_role_name="test-role", + control_room_state_bucket="test-bucket", + environment="test", + network_trust=ptd.NetworkTrust.FULL, + sites={}, + true_name="test-workload", + ) + + # Both configs should have the same field name for bastion instance type + assert hasattr(aws_config, "bastion_instance_type") + assert hasattr(azure_config, "bastion_instance_type") + + # Verify they have appropriate defaults for their cloud provider + assert aws_config.bastion_instance_type == "t4g.nano" # AWS default + assert azure_config.bastion_instance_type == "Standard_B1s" # Azure default From ef97f7acaf52a99eae94187945aa018de0ed9f7c Mon Sep 17 00:00:00 2001 From: ian-flores Date: Tue, 24 Feb 2026 10:09:10 -0800 Subject: [PATCH 4/5] chore: rename .envrc to envrc.recommended Avoids stomping on developer-local .envrc customizations, per review feedback from Lytol and statik on PR #128. Developers should copy envrc.recommended to .envrc locally. Update CLAUDE.md instructions accordingly. --- CLAUDE.md | 2 +- .envrc => envrc.recommended | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename .envrc => envrc.recommended (100%) diff --git a/CLAUDE.md b/CLAUDE.md index 2746a54..291b326 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -122,7 +122,7 @@ Always prefix worktree directories with `ptd-` to avoid collisions with other re cd ../../.worktrees/ptd- just build-cmd ``` -2. **direnv** — if direnv is available, `cd` into the worktree and run `direnv allow`. The `.envrc` uses `source_up` to inherit workspace vars and overrides `PTD` to point to the worktree. +2. **direnv** — if direnv is available, copy `envrc.recommended` to `.envrc` in the worktree, then run `direnv allow`. The file uses `source_up` to inherit workspace vars and overrides `PTD` to point to the worktree. 3. **For agents without direnv** — set env vars explicitly before running `ptd` commands: ```bash export PTD="$(pwd)" diff --git a/.envrc b/envrc.recommended similarity index 100% rename from .envrc rename to envrc.recommended From d144e451f4586e21e962a0dcf3bde76f1baef849 Mon Sep 17 00:00:00 2001 From: ian-flores Date: Tue, 24 Feb 2026 11:41:21 -0800 Subject: [PATCH 5/5] Revert "feat(azure): add configurable bastion instance type" This reverts commit 0cd88f0c8a3d976057202277dd013f99fa5f1c77. --- lib/types/workload.go | 1 - lib/types/workload_test.go | 54 ------- python-pulumi/src/ptd/azure_workload.py | 1 - .../src/ptd/pulumi_resources/azure_bastion.py | 5 +- .../azure_workload_persistent.py | 1 - .../tests/test_azure_bastion_config.py | 143 ------------------ 6 files changed, 1 insertion(+), 204 deletions(-) delete mode 100644 python-pulumi/tests/test_azure_bastion_config.py diff --git a/lib/types/workload.go b/lib/types/workload.go index 7cb2cff..dfd6e9d 100644 --- a/lib/types/workload.go +++ b/lib/types/workload.go @@ -95,7 +95,6 @@ type AzureWorkloadConfig struct { ClientID string `yaml:"client_id"` SecretsProviderClientID string `yaml:"secrets_provider_client_id"` AdminGroupID string `yaml:"admin_group_id"` - BastionInstanceType string `yaml:"bastion_instance_type"` InstanceType string `yaml:"instance_type"` ControlPlaneNodeCount int `yaml:"control_plane_node_count"` WorkerNodeCount int `yaml:"worker_node_count"` diff --git a/lib/types/workload_test.go b/lib/types/workload_test.go index f052a50..ebee795 100644 --- a/lib/types/workload_test.go +++ b/lib/types/workload_test.go @@ -151,60 +151,6 @@ func TestAzureWorkloadConfigSerialization(t *testing.T) { unmarshaledConfig.Clusters["main"].Components.SecretStoreCsiDriverAzureProviderVersion) } -func TestAzureWorkloadConfigBastionInstanceType(t *testing.T) { - // Test that bastion_instance_type field is properly serialized/deserialized - config := AzureWorkloadConfig{ - SubscriptionID: "123456789-abcd-efgh-ijkl-1234567890ab", - TenantID: "abcdefgh-1234-5678-ijkl-1234567890ab", - Region: "eastus", - ClientID: "12345678-abcd-efgh-ijkl-1234567890ab", - SecretsProviderClientID: "98765432-abcd-efgh-ijkl-1234567890ab", - BastionInstanceType: "Standard_B2s", - InstanceType: "Standard_D4s_v3", - ControlPlaneNodeCount: 1, - WorkerNodeCount: 1, - DBStorageSizeGB: 20, - } - - // Marshal to YAML - yamlData, err := yaml.Marshal(config) - assert.NoError(t, err) - - // Verify the YAML contains the bastion_instance_type field - yamlString := string(yamlData) - assert.Contains(t, yamlString, "bastion_instance_type: Standard_B2s") - - // Unmarshal from YAML - var unmarshaledConfig AzureWorkloadConfig - err = yaml.Unmarshal(yamlData, &unmarshaledConfig) - assert.NoError(t, err) - - // Verify bastion_instance_type matches - assert.Equal(t, config.BastionInstanceType, unmarshaledConfig.BastionInstanceType) - assert.Equal(t, "Standard_B2s", unmarshaledConfig.BastionInstanceType) -} - -func TestAzureWorkloadConfigBastionInstanceTypeFromYAML(t *testing.T) { - // Test parsing bastion_instance_type from YAML - yamlContent := ` -subscription_id: "123456789-abcd-efgh-ijkl-1234567890ab" -tenant_id: "abcdefgh-1234-5678-ijkl-1234567890ab" -region: "eastus" -client_id: "12345678-abcd-efgh-ijkl-1234567890ab" -secrets_provider_client_id: "98765432-abcd-efgh-ijkl-1234567890ab" -bastion_instance_type: "Standard_D2s_v3" -instance_type: "Standard_D4s_v3" -control_plane_node_count: 1 -worker_node_count: 1 -db_storage_size_gb: 20 -` - - var config AzureWorkloadConfig - err := yaml.Unmarshal([]byte(yamlContent), &config) - assert.NoError(t, err) - assert.Equal(t, "Standard_D2s_v3", config.BastionInstanceType) -} - func TestAzureUserNodePoolConfigSerialization(t *testing.T) { initialCount := 5 maxPods := 50 diff --git a/python-pulumi/src/ptd/azure_workload.py b/python-pulumi/src/ptd/azure_workload.py index dae9a08..940f48c 100644 --- a/python-pulumi/src/ptd/azure_workload.py +++ b/python-pulumi/src/ptd/azure_workload.py @@ -66,7 +66,6 @@ class AzureWorkloadConfig(ptd.WorkloadConfig): resource_tags: dict[str, str] | None = None protect_persistent_resources: bool = True admin_group_id: str | None = None - bastion_instance_type: str = "Standard_B1s" ppm_file_share_size_gib: int = 100 # Minimum size for PPM Azure File Share in GiB diff --git a/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py b/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py index 6658d46..ab0cbc5 100644 --- a/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py +++ b/python-pulumi/src/ptd/pulumi_resources/azure_bastion.py @@ -26,7 +26,6 @@ def __init__( resource_group_name: str | pulumi.Output[str], location: str | pulumi.Output[str], tags: dict[str, str], - vm_size: str | pulumi.Output[str], *args, **kwargs, ): @@ -41,8 +40,6 @@ def __init__( **kwargs, ) - self.vm_size = vm_size - # generate a key pair for the jumpbox self.jumpbox_ssh_key = tls.PrivateKey( "ssh-key", @@ -109,7 +106,7 @@ def __init__( resource_group_name=resource_group_name, location=location, hardware_profile=compute.HardwareProfileArgs( - vm_size=self.vm_size, + vm_size="Standard_B1s", ), storage_profile=compute.StorageProfileArgs( image_reference=compute.ImageReferenceArgs( diff --git a/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py b/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py index b097580..a3dd5ad 100644 --- a/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py +++ b/python-pulumi/src/ptd/pulumi_resources/azure_workload_persistent.py @@ -789,7 +789,6 @@ def _define_bastion(self): resource_group_name=self.vnet_rsg_name, location=self.workload.cfg.region, tags=self.required_tags, - vm_size=self.workload.cfg.bastion_instance_type, opts=pulumi.ResourceOptions( protect=self.workload.cfg.protect_persistent_resources, ), diff --git a/python-pulumi/tests/test_azure_bastion_config.py b/python-pulumi/tests/test_azure_bastion_config.py deleted file mode 100644 index cbfd9ad..0000000 --- a/python-pulumi/tests/test_azure_bastion_config.py +++ /dev/null @@ -1,143 +0,0 @@ -"""Tests for Azure Bastion instance type configuration.""" - -import typing - -import pulumi - -import ptd.azure_workload - - -class AzureBastionMocks(pulumi.runtime.Mocks): - """Mock Pulumi resource calls for testing.""" - - def new_resource(self, args: pulumi.runtime.MockResourceArgs) -> tuple[str | None, dict[typing.Any, typing.Any]]: - """Mock resource creation - return resource ID and properties.""" - # Return the inputs as outputs for testing - return args.name, dict(args.inputs) - - def call( - self, _args: pulumi.runtime.MockCallArgs - ) -> dict[typing.Any, typing.Any] | tuple[dict[typing.Any, typing.Any], list[tuple[str, str]] | None]: - """Mock function calls.""" - return {} - - -pulumi.runtime.set_mocks(AzureBastionMocks(), preview=False) - - -def test_azure_workload_config_default_bastion_instance_type(): - """Test that AzureWorkloadConfig has correct default bastion_instance_type.""" - config = ptd.azure_workload.AzureWorkloadConfig( - clusters={}, - subscription_id="test-sub-id", - tenant_id="test-tenant-id", - client_id="test-client-id", - secrets_provider_client_id="test-sp-client-id", - network=ptd.azure_workload.NetworkConfig( - private_subnet_cidr="10.0.1.0/24", - db_subnet_cidr="10.0.2.0/24", - netapp_subnet_cidr="10.0.3.0/24", - app_gateway_subnet_cidr="10.0.4.0/24", - bastion_subnet_cidr="10.0.5.0/24", - ), - region="eastus", - control_room_account_id="test-account", - control_room_cluster_name="test-cluster", - control_room_domain="test.example.com", - control_room_region="eastus", - control_room_role_name="test-role", - control_room_state_bucket="test-bucket", - environment="test", - network_trust=ptd.NetworkTrust.FULL, - sites={}, - true_name="test-workload", - ) - - # Verify default value - assert config.bastion_instance_type == "Standard_B1s" - - -def test_azure_workload_config_custom_bastion_instance_type(): - """Test that AzureWorkloadConfig accepts custom bastion_instance_type.""" - config = ptd.azure_workload.AzureWorkloadConfig( - clusters={}, - subscription_id="test-sub-id", - tenant_id="test-tenant-id", - client_id="test-client-id", - secrets_provider_client_id="test-sp-client-id", - network=ptd.azure_workload.NetworkConfig( - private_subnet_cidr="10.0.1.0/24", - db_subnet_cidr="10.0.2.0/24", - netapp_subnet_cidr="10.0.3.0/24", - app_gateway_subnet_cidr="10.0.4.0/24", - bastion_subnet_cidr="10.0.5.0/24", - ), - region="eastus", - bastion_instance_type="Standard_B2s", - control_room_account_id="test-account", - control_room_cluster_name="test-cluster", - control_room_domain="test.example.com", - control_room_region="eastus", - control_room_role_name="test-role", - control_room_state_bucket="test-bucket", - environment="test", - network_trust=ptd.NetworkTrust.FULL, - sites={}, - true_name="test-workload", - ) - - # Verify custom value - assert config.bastion_instance_type == "Standard_B2s" - - -def test_azure_workload_config_bastion_instance_type_matches_aws_pattern(): - """Test that Azure uses same field name as AWS for consistency.""" - aws_config = ptd.aws_workload.AWSWorkloadConfig( - clusters={}, - account_id="123456789012", - region="us-east-1", - control_room_account_id="123456789012", - control_room_cluster_name="test-cluster", - control_room_domain="test.example.com", - control_room_region="us-east-1", - control_room_role_name="test-role", - control_room_state_bucket="test-bucket", - environment="test", - network_trust=ptd.NetworkTrust.FULL, - sites={}, - true_name="test-workload", - ) - - azure_config = ptd.azure_workload.AzureWorkloadConfig( - clusters={}, - subscription_id="test-sub-id", - tenant_id="test-tenant-id", - client_id="test-client-id", - secrets_provider_client_id="test-sp-client-id", - network=ptd.azure_workload.NetworkConfig( - private_subnet_cidr="10.0.1.0/24", - db_subnet_cidr="10.0.2.0/24", - netapp_subnet_cidr="10.0.3.0/24", - app_gateway_subnet_cidr="10.0.4.0/24", - bastion_subnet_cidr="10.0.5.0/24", - ), - region="eastus", - control_room_account_id="test-account", - control_room_cluster_name="test-cluster", - control_room_domain="test.example.com", - control_room_region="eastus", - control_room_role_name="test-role", - control_room_state_bucket="test-bucket", - environment="test", - network_trust=ptd.NetworkTrust.FULL, - sites={}, - true_name="test-workload", - ) - - # Both configs should have the same field name for bastion instance type - assert hasattr(aws_config, "bastion_instance_type") - assert hasattr(azure_config, "bastion_instance_type") - - # Verify they have appropriate defaults for their cloud provider - assert aws_config.bastion_instance_type == "t4g.nano" # AWS default - assert azure_config.bastion_instance_type == "Standard_B1s" # Azure default