8d803563 Andy McCall 1 month ago ↶
1
2
3
4
5
6
7
8
9
10
11
use crate :: StoreUrl;
12
use object_store:: gcp:: { GoogleCloudStorage, GoogleCloudStorageBuilder} ;
13
use oxy_core:: strata:: { Error, Result } ;
14
15
pub const HINT : & str = " run `gcloud auth application-default login`, or set GOOGLE_APPLICATION_CREDENTIALS (or add ?credentials=PATH to the remote URL) to a service account key file" ;
16
17
18
19
fn is_service_account_key ( path : & str ) -> bool {
20
std:: fs:: read_to_string( path)
21
.ok ( )
22
.and_then ( | t | serde_json:: from_str:: < serde_json:: Value> ( & t) .ok ( ) )
23
.and_then ( | v | {
24
v.get ( " type" )
25
.and_then ( | t | t.as_str ( ) )
26
.map ( | t | t = = " service_account" )
27
} )
28
.unwrap_or ( false )
29
}
30
31
pub fn open ( url : & StoreUrl) -> Result< GoogleCloudStorage> {
2cd40ea1 Andy McCall 1 month ago ↶
32
let mut b = GoogleCloudStorageBuilder:: from_env( )
33
.with_bucket_name ( & url.host)
34
.with_http_connector ( crate :: http:: UreqConnector) ;
8d803563 Andy McCall 1 month ago ↶
35
let file = url.param ( " credentials" ) .map ( str :: to_string) .or_else ( | | {
36
std:: env:: var( " GOOGLE_APPLICATION_CREDENTIALS" )
37
.ok ( )
38
.filter ( | v | ! v.is_empty ( ) )
39
} ) ;
40
if let Some ( path) = file {
41
if ! std:: path:: Path:: new( & path) .is_file ( ) {
42
return Err ( Error:: Backend( format! (
43
" {} : the credentials file {path} does not exist: {HINT} " ,
44
url.plain ( )
45
) ) ) ;
46
}
47
b = if is_service_account_key ( & path) {
48
b.with_service_account_path ( path)
49
} else {
50
b.with_application_credentials ( path)
51
} ;
52
}
53
if let Some ( endpoint) = url.param ( " endpoint" ) {
54
b = b.with_base_url ( endpoint) ;
55
}
56
b.build ( )
57
.map_err ( | e | Error:: Backend( format! ( " {} : {e} : {HINT} " , url.plain ( ) ) ) )
58
}