From a8260f086969d994ab85c60e6fc270efda15eb9b Mon Sep 17 00:00:00 2001 From: Dan Lilienblum Date: Tue, 21 Jul 2026 02:34:16 +0900 Subject: [PATCH] fix: gate imported remote binding params --- crates/alien-infra/src/import_helpers.rs | 22 +++++----- crates/alien-infra/tests/importers.rs | 51 ++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/crates/alien-infra/src/import_helpers.rs b/crates/alien-infra/src/import_helpers.rs index 955ffb344..d59dbf0de 100644 --- a/crates/alien-infra/src/import_helpers.rs +++ b/crates/alien-infra/src/import_helpers.rs @@ -43,14 +43,18 @@ where C: ResourceController + 'static, { let outputs = controller.get_outputs(); - let binding = controller.get_binding_params().map_err(|err| { - AlienError::new(CoreErrorData::GenericError { - message: format!( - "binding params extraction failed for resource '{}': {}", - ctx.resource_id, err - ), - }) - })?; + let remote_binding_params = if ctx.resource.remote_access { + controller.get_binding_params().map_err(|err| { + AlienError::new(CoreErrorData::GenericError { + message: format!( + "binding params extraction failed for resource '{}': {}", + ctx.resource_id, err + ), + }) + })? + } else { + None + }; let internal_state = serialize_controller(&controller).map_err(|err| { AlienError::new(CoreErrorData::JsonSerializationFailed { reason: format!( @@ -68,7 +72,7 @@ where .config(ctx.resource.config.clone()) .internal_state(internal_state) .maybe_outputs(outputs) - .maybe_remote_binding_params(binding) + .maybe_remote_binding_params(remote_binding_params) .lifecycle(ctx.resource.lifecycle) .dependencies(Vec::new()) .build()) diff --git a/crates/alien-infra/tests/importers.rs b/crates/alien-infra/tests/importers.rs index 675e91526..38fb25f5b 100644 --- a/crates/alien-infra/tests/importers.rs +++ b/crates/alien-infra/tests/importers.rs @@ -60,6 +60,15 @@ fn entry(resource: T) -> ResourceEntry { } } +fn remote_entry(resource: T) -> ResourceEntry { + ResourceEntry { + config: Resource::new(resource), + lifecycle: ResourceLifecycle::Live, + dependencies: vec![], + remote_access: true, + } +} + fn frozen_entry(resource: T) -> ResourceEntry { ResourceEntry { config: Resource::new(resource), @@ -311,11 +320,45 @@ fn gcp_storage_round_trip() { internal_state(&state)["bucketName"], "alien-stack-my-bucket" ); + assert_eq!( + state.remote_binding_params, None, + "an imported resource without remote access must not publish its binding params" + ); } #[test] -fn gcp_kv_round_trip() { - let entry = entry(Kv::new("settings".to_string()).build()); +fn gcp_storage_remote_access_round_trip() { + let entry = remote_entry(Storage::new("my-bucket".to_string()).build()); + let data = GcpStorageImportData { + project_id: "my-project".to_string(), + bucket_name: "alien-stack-my-bucket".to_string(), + bucket_self_link: "https://www.googleapis.com/storage/v1/b/alien-stack-my-bucket" + .to_string(), + location: "us-central1".to_string(), + }; + let state = run_through_registry( + &Storage::RESOURCE_TYPE, + Platform::Gcp, + serde_json::to_value(&data).unwrap(), + &entry, + "us-central1", + &gcp_management_config(), + ); + + assert_running_with_internal_state(&state); + assert_eq!( + state.remote_binding_params, + Some(json!({ + "service": "gcs", + "bucketName": "alien-stack-my-bucket", + })), + "an imported resource with remote access must publish its binding params" + ); +} + +#[test] +fn gcp_kv_remote_access_round_trip() { + let entry = remote_entry(Kv::new("settings".to_string()).build()); let data = GcpKvImportData { project_id: "my-project".to_string(), database_id: "alien-stack-settings".to_string(), @@ -343,8 +386,8 @@ fn gcp_kv_round_trip() { } #[test] -fn gcp_build_round_trip() { - let entry = entry( +fn gcp_build_remote_access_round_trip() { + let entry = remote_entry( Build::new("builder".to_string()) .permissions("build-execution".to_string()) .environment(HashMap::from([(