Skip to content

Commit 198e1a1

Browse files
committed
spin up time account validation
Signed-off-by: Zhiwei Liang <zhiwei.liang@zliang.me>
1 parent 989f160 commit 198e1a1

2 files changed

Lines changed: 32 additions & 37 deletions

File tree

crates/key-value-azure/src/auth.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ pub enum AzureCredentialKind {
5454
/// Service principal authenticated with a client secret. Reads
5555
/// `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` from the
5656
/// environment — the same variables the legacy SDK's `EnvironmentCredential`
57-
/// used, so existing deployments keep working without config changes.
57+
/// used, so the environment carries over once `auth_type = "service_principal"`
58+
/// is set.
5859
ServicePrincipal,
5960
}
6061

@@ -93,7 +94,7 @@ impl AzureCredentialKind {
9394
///
9495
/// This runs the credential's own setup (which may fail — e.g. if the
9596
/// environment for workload identity or service principal is absent), so it
96-
/// is called lazily when the Cosmos client is first built.
97+
/// is called at store construction, failing `spin up` on misconfiguration.
9798
pub(crate) fn credential(&self) -> azure_core::Result<Arc<dyn TokenCredential>> {
9899
match self {
99100
Self::DeveloperTools => Ok(azure_identity::DeveloperToolsCredential::new(None)?),
@@ -116,7 +117,7 @@ impl AzureCredentialKind {
116117
// azure_identity 1.0 removed the env-driven `EnvironmentCredential`,
117118
// so read the same variables it used and pass them to
118119
// `ClientSecretCredential` explicitly. A missing variable surfaces
119-
// here (lazily, when the client is first built) as a clear error.
120+
// here (at store construction, during `spin up`) as a clear error.
120121
let tenant_id = service_principal_env("AZURE_TENANT_ID")?;
121122
let client_id = service_principal_env("AZURE_CLIENT_ID")?;
122123
let secret = service_principal_env("AZURE_CLIENT_SECRET")?;

crates/key-value-azure/src/store.rs

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use crate::auth::KeyValueAzureCosmosAuthOptions;
1818

1919
pub struct KeyValueAzureCosmos {
2020
/// Parameters for initializing the Cosmos DB client
21-
account: String,
21+
account_ref: AccountReference,
22+
2223
database: String,
2324
container: String,
24-
auth_options: KeyValueAzureCosmosAuthOptions,
2525
region: Region,
2626

2727
/// The Cosmos DB client
@@ -43,54 +43,48 @@ impl KeyValueAzureCosmos {
4343
region: Region,
4444
app_id: Option<String>,
4545
) -> Result<Self> {
46+
let endpoint: azure_data_cosmos::AccountEndpoint =
47+
format!("https://{account}.documents.azure.com/")
48+
.parse()
49+
.map_err(log_error)?;
50+
51+
let account_ref = match auth_options {
52+
KeyValueAzureCosmosAuthOptions::RuntimeConfigValues(config) => {
53+
AccountReference::with_authentication_key(
54+
endpoint,
55+
Secret::from(config.key.clone()),
56+
)
57+
}
58+
KeyValueAzureCosmosAuthOptions::AadCredential(kind) => {
59+
let credential = kind.credential().map_err(log_error)?;
60+
AccountReference::with_credential(endpoint, credential)
61+
}
62+
};
63+
4664
Ok(Self {
47-
account,
65+
account_ref,
4866
database,
4967
container,
50-
auth_options,
5168
region,
5269
client: tokio::sync::OnceCell::new(),
5370
app_id,
5471
})
5572
}
5673
}
5774

58-
async fn build_cosmos_client(
59-
account: &str,
60-
auth_options: &KeyValueAzureCosmosAuthOptions,
61-
region: &Region,
62-
) -> Result<CosmosClient, Error> {
63-
let endpoint: azure_data_cosmos::AccountEndpoint =
64-
format!("https://{account}.documents.azure.com/")
65-
.parse()
66-
.map_err(log_error)?;
67-
68-
let account_ref = match auth_options {
69-
KeyValueAzureCosmosAuthOptions::RuntimeConfigValues(config) => {
70-
AccountReference::with_authentication_key(endpoint, Secret::from(config.key.clone()))
71-
}
72-
KeyValueAzureCosmosAuthOptions::AadCredential(kind) => {
73-
let credential = kind.credential().map_err(log_error)?;
74-
AccountReference::with_credential(endpoint, credential)
75-
}
76-
};
77-
78-
let routing_strategy = RoutingStrategy::ProximityTo(region.clone());
79-
80-
CosmosClient::builder()
81-
.build(account_ref, routing_strategy)
82-
.await
83-
.map_err(log_error)
84-
}
85-
8675
#[async_trait]
8776
impl StoreManager for KeyValueAzureCosmos {
8877
async fn get(&self, name: &str) -> Result<Arc<dyn Store>, Error> {
8978
let client = self
9079
.client
9180
.get_or_try_init(|| async {
92-
return build_cosmos_client(&self.account, &self.auth_options, &self.region)
93-
.await?
81+
return CosmosClient::builder()
82+
.build(
83+
self.account_ref.clone(),
84+
RoutingStrategy::ProximityTo(self.region.clone()),
85+
)
86+
.await
87+
.map_err(log_error)?
9488
.database_client(&self.database)
9589
.container_client(&self.container)
9690
.await

0 commit comments

Comments
 (0)