gcp_bigquery_client/
client_builder.rs1use std::path::{Path, PathBuf};
2use std::sync::Arc;
3
4use yup_oauth2::ServiceAccountKey;
5
6use crate::auth::{
7 application_default_credentials_authenticator, authorized_user_authenticator, installed_flow_authenticator,
8 service_account_authenticator, Authenticator, ServiceAccountAuthenticator,
9};
10use crate::error::BQError;
11use crate::{Client, BIG_QUERY_AUTH_URL, BIG_QUERY_V2_URL};
12
13pub struct ClientBuilder {
14 v2_base_url: String,
15 auth_base_url: String,
16}
17
18impl ClientBuilder {
19 pub fn new() -> Self {
20 Self {
21 v2_base_url: BIG_QUERY_V2_URL.to_string(),
22 auth_base_url: BIG_QUERY_AUTH_URL.to_string(),
23 }
24 }
25
26 pub fn with_v2_base_url(&mut self, base_url: String) -> &mut Self {
27 self.v2_base_url = base_url;
28 self
29 }
30
31 pub fn with_auth_base_url(&mut self, base_url: String) -> &mut Self {
32 self.auth_base_url = base_url;
33 self
34 }
35
36 pub async fn build_from_authenticator(&self, auth: Arc<dyn Authenticator>) -> Result<Client, BQError> {
37 let mut client = Client::from_authenticator(auth).await?;
38 client.v2_base_url(self.v2_base_url.clone());
39 Ok(client)
40 }
41
42 pub async fn build_from_service_account_key(
43 &self,
44 sa_key: ServiceAccountKey,
45 readonly: bool,
46 ) -> Result<Client, BQError> {
47 let scope = if readonly {
48 format!("{}.readonly", self.auth_base_url)
49 } else {
50 self.auth_base_url.clone()
51 };
52 let sa_auth = ServiceAccountAuthenticator::from_service_account_key(sa_key, &[&scope]).await?;
53
54 self.build_from_authenticator(sa_auth).await
55 }
56
57 pub async fn build_from_service_account_key_file(&self, sa_key_file: &str) -> Result<Client, BQError> {
58 let scopes = vec![self.auth_base_url.as_str()];
59 let sa_auth = service_account_authenticator(scopes, sa_key_file).await?;
60
61 self.build_from_authenticator(sa_auth).await
62 }
63
64 pub async fn build_with_workload_identity(&self, readonly: bool) -> Result<Client, BQError> {
65 let scope = if readonly {
66 format!("{BIG_QUERY_AUTH_URL}.readonly")
67 } else {
68 BIG_QUERY_AUTH_URL.to_string()
69 };
70
71 let sa_auth = ServiceAccountAuthenticator::with_workload_identity(&[&scope]).await?;
72
73 self.build_from_authenticator(sa_auth).await
74 }
75
76 pub async fn build_from_installed_flow_authenticator<S: AsRef<[u8]>, P: Into<PathBuf>>(
77 &self,
78 secret: S,
79 persistant_file_path: P,
80 ) -> Result<Client, BQError> {
81 let scopes = vec![self.auth_base_url.as_str()];
82 let auth = installed_flow_authenticator(secret, &scopes, persistant_file_path).await?;
83
84 let mut client = Client::from_authenticator(auth).await?;
85 client.v2_base_url(self.v2_base_url.clone());
86 Ok(client)
87 }
88
89 pub async fn build_from_installed_flow_authenticator_from_secret_file<P: Into<PathBuf>>(
90 &self,
91 secret_file: &str,
92 persistant_file_path: P,
93 ) -> Result<Client, BQError> {
94 self.build_from_installed_flow_authenticator(
95 tokio::fs::read(secret_file)
96 .await
97 .expect("expecting a valid secret file."),
98 persistant_file_path,
99 )
100 .await
101 }
102
103 pub async fn build_from_application_default_credentials(&self) -> Result<Client, BQError> {
104 let scopes = vec![self.auth_base_url.as_str()];
105 let auth = application_default_credentials_authenticator(&scopes).await?;
106
107 let mut client = Client::from_authenticator(auth).await?;
108 client.v2_base_url(self.v2_base_url.clone());
109 Ok(client)
110 }
111
112 pub async fn build_from_authorized_user_authenticator<P: AsRef<Path>>(
113 &self,
114 authorized_user_secret_path: P,
115 ) -> Result<Client, BQError> {
116 let scopes = vec![self.auth_base_url.as_str()];
117 let auth = authorized_user_authenticator(authorized_user_secret_path, &scopes).await?;
118
119 let mut client = Client::from_authenticator(auth).await?;
120 client.v2_base_url(self.v2_base_url.clone());
121 Ok(client)
122 }
123}
124
125impl Default for ClientBuilder {
126 fn default() -> Self {
127 Self::new()
128 }
129}