@@ -4347,7 +4347,7 @@ fn read_gcloud_adc() -> Result<(String, String, String)> {
43474347 Ok ( ( client_id, client_secret, refresh_token) )
43484348}
43494349
4350- async fn rollback_provider_create_after_vertex_adc_failure (
4350+ async fn rollback_provider_create_after_gcloud_adc_failure (
43514351 client : & mut crate :: tls:: GrpcClient ,
43524352 provider_name : & str ,
43534353 stage : & str ,
@@ -4360,7 +4360,7 @@ async fn rollback_provider_create_after_vertex_adc_failure(
43604360 . await
43614361 {
43624362 Ok ( _) => Err ( miette ! (
4363- "failed to {stage} Vertex AI credentials from gcloud ADC for provider '{provider_name}': {source}. \
4363+ "failed to {stage} credentials from gcloud ADC for provider '{provider_name}': {source}. \
43644364 The provider was rolled back successfully."
43654365 ) ) ,
43664366 Err ( cleanup_err) => {
@@ -4374,7 +4374,7 @@ async fn rollback_provider_create_after_vertex_adc_failure(
43744374 provider_name
43754375 ) ;
43764376 Err ( miette ! (
4377- "failed to {stage} Vertex AI credentials from gcloud ADC for provider '{provider_name}': {source}. \
4377+ "failed to {stage} credentials from gcloud ADC for provider '{provider_name}': {source}. \
43784378 Cleanup also failed, so the provider may still exist. \
43794379 Run 'openshell provider delete {provider_name}' to remove it manually."
43804380 ) )
@@ -4483,6 +4483,9 @@ async fn discover_existing_provider_data(
44834483/// Canonical provider type string for Google Vertex AI.
44844484const VERTEX_AI_PROVIDER_TYPE : & str = "google-vertex-ai" ;
44854485
4486+ /// Canonical provider type string for Google Cloud (GCP APIs).
4487+ const GOOGLE_CLOUD_PROVIDER_TYPE : & str = "google-cloud" ;
4488+
44864489fn missing_credentials_error ( provider_type : & str ) -> miette:: Report {
44874490 if provider_type == VERTEX_AI_PROVIDER_TYPE {
44884491 return miette:: miette!(
@@ -4493,6 +4496,14 @@ fn missing_credentials_error(provider_type: &str) -> miette::Report {
44934496 ) ;
44944497 }
44954498
4499+ if provider_type == GOOGLE_CLOUD_PROVIDER_TYPE {
4500+ return miette:: miette!(
4501+ "no credentials resolved for provider type '{provider_type}'. \
4502+ Set GCP_ADC_ACCESS_TOKEN or GCP_SA_ACCESS_TOKEN; \
4503+ or use --from-gcloud-adc / --from-existing with those env vars set."
4504+ ) ;
4505+ }
4506+
44964507 miette:: miette!(
44974508 "no credentials resolved for provider type '{provider_type}'. \
44984509 Use --credential KEY[=VALUE], --runtime-credentials for runtime-resolved profile credentials, \
@@ -4583,11 +4594,34 @@ pub async fn provider_create_with_options(
45834594 }
45844595 } ;
45854596
4586- if from_gcloud_adc && provider_type != VERTEX_AI_PROVIDER_TYPE {
4587- return Err ( miette:: miette!(
4588- "--from-gcloud-adc is only valid for google-vertex-ai providers"
4589- ) ) ;
4590- }
4597+ let adc_credential_key = if from_gcloud_adc {
4598+ let profile =
4599+ openshell_providers:: get_default_profile ( & provider_type) . ok_or_else ( || {
4600+ miette:: miette!(
4601+ "--from-gcloud-adc requires a built-in provider profile, \
4602+ but '{provider_type}' has none"
4603+ )
4604+ } ) ?;
4605+ let adc_cred = profile. adc_credential ( ) . ok_or_else ( || {
4606+ miette:: miette!(
4607+ "--from-gcloud-adc is not supported for '{provider_type}' providers \
4608+ (no ADC-compatible credential in the provider profile)"
4609+ )
4610+ } ) ?;
4611+ Some (
4612+ adc_cred
4613+ . env_vars
4614+ . first ( )
4615+ . ok_or_else ( || {
4616+ miette:: miette!(
4617+ "ADC credential in '{provider_type}' profile has no env_vars declared"
4618+ )
4619+ } ) ?
4620+ . clone ( ) ,
4621+ )
4622+ } else {
4623+ None
4624+ } ;
45914625
45924626 let mut credential_map = parse_credential_pairs ( credentials) ?;
45934627 let mut config_map = parse_key_value_pairs ( config, "--config" ) ?;
@@ -4636,10 +4670,12 @@ pub async fn provider_create_with_options(
46364670 }
46374671
46384672 // Validate and read the ADC file BEFORE creating the provider so that
4639- // a bad/missing ADC does not leave an orphan provider behind.
4640- let gcloud_adc_material = if from_gcloud_adc {
4673+ // a bad/missing ADC does not leave an orphan provider behind. Bundle the
4674+ // credential key with the material so they stay coupled.
4675+ let gcloud_adc_bootstrap = if from_gcloud_adc {
46414676 let ( client_id, client_secret, refresh_token) = read_gcloud_adc ( ) ?;
4642- Some ( ( client_id, client_secret, refresh_token) )
4677+ let key = adc_credential_key. expect ( "set when from_gcloud_adc is true" ) ;
4678+ Some ( ( key, client_id, client_secret, refresh_token) )
46434679 } else {
46444680 None
46454681 } ;
@@ -4669,7 +4705,9 @@ pub async fn provider_create_with_options(
46694705 . ok_or_else ( || miette:: miette!( "provider missing from response" ) ) ?;
46704706 let provider_name = provider. object_name ( ) . to_string ( ) ;
46714707
4672- if let Some ( ( client_id, client_secret, refresh_token) ) = gcloud_adc_material {
4708+ if let Some ( ( adc_credential_key, client_id, client_secret, refresh_token) ) =
4709+ gcloud_adc_bootstrap
4710+ {
46734711 let mut material = HashMap :: new ( ) ;
46744712 material. insert ( "client_id" . to_string ( ) , client_id) ;
46754713 material. insert ( "client_secret" . to_string ( ) , client_secret) ;
@@ -4678,7 +4716,7 @@ pub async fn provider_create_with_options(
46784716 if let Err ( configure_err) = client
46794717 . configure_provider_refresh ( ConfigureProviderRefreshRequest {
46804718 provider : provider_name. clone ( ) ,
4681- credential_key : openshell_core :: inference :: VERTEX_AI_ADC_TOKEN_KEY . to_string ( ) ,
4719+ credential_key : adc_credential_key . clone ( ) ,
46824720 strategy : ProviderCredentialRefreshStrategy :: Oauth2RefreshToken as i32 ,
46834721 material,
46844722 secret_material_keys : vec ! [
@@ -4689,7 +4727,7 @@ pub async fn provider_create_with_options(
46894727 } )
46904728 . await
46914729 {
4692- return rollback_provider_create_after_vertex_adc_failure (
4730+ return rollback_provider_create_after_gcloud_adc_failure (
46934731 & mut client,
46944732 & provider_name,
46954733 "configure" ,
@@ -4701,11 +4739,11 @@ pub async fn provider_create_with_options(
47014739 if let Err ( rotate_err) = client
47024740 . rotate_provider_credential ( RotateProviderCredentialRequest {
47034741 provider : provider_name. clone ( ) ,
4704- credential_key : openshell_core :: inference :: VERTEX_AI_ADC_TOKEN_KEY . to_string ( ) ,
4742+ credential_key : adc_credential_key ,
47054743 } )
47064744 . await
47074745 {
4708- return rollback_provider_create_after_vertex_adc_failure (
4746+ return rollback_provider_create_after_gcloud_adc_failure (
47094747 & mut client,
47104748 & provider_name,
47114749 "mint the initial access token for" ,
@@ -4715,9 +4753,7 @@ pub async fn provider_create_with_options(
47154753 }
47164754
47174755 println ! ( "{} Created provider {}" , "✓" . green( ) . bold( ) , provider_name) ;
4718- println ! (
4719- "Configured Vertex AI credentials from gcloud ADC and minted the initial access token"
4720- ) ;
4756+ println ! ( "Configured GCP credentials from gcloud ADC and minted the initial access token" ) ;
47214757 return Ok ( ( ) ) ;
47224758 }
47234759
0 commit comments