@@ -25,6 +25,7 @@ use aws_sdk_s3::RetryConfig;
25
25
use aws_sdk_s3:: { Client , Credentials , Endpoint , Region } ;
26
26
use aws_smithy_async:: rt:: sleep:: default_async_sleep;
27
27
use bytes:: Bytes ;
28
+ use chrono:: Local ;
28
29
use clap:: builder:: ArgPredicate ;
29
30
use datafusion:: arrow:: datatypes:: Schema ;
30
31
use datafusion:: datasource:: file_format:: parquet:: ParquetFormat ;
@@ -58,23 +59,94 @@ const DEFAULT_S3_BUCKET: &str = "parseable";
58
59
const DEFAULT_S3_ACCESS_KEY : & str = "minioadmin" ;
59
60
const DEFAULT_S3_SECRET_KEY : & str = "minioadmin" ;
60
61
62
+ // metadata file names in a Stream prefix
63
+ const METADATA_FILE_NAME : & str = ".metadata.json" ;
64
+ const SCHEMA_FILE_NAME : & str = ".schema" ;
65
+ const ALERT_FILE_NAME : & str = ".alert.json" ;
66
+
61
67
// max concurrent request allowed for datafusion object store
62
68
const MAX_OBJECT_STORE_REQUESTS : usize = 1000 ;
63
69
70
+ // all the supported permissions
71
+ // const PERMISSIONS_READ: &str = "readonly";
72
+ // const PERMISSIONS_WRITE: &str = "writeonly";
73
+ // const PERMISSIONS_DELETE: &str = "delete";
74
+ // const PERMISSIONS_READ_WRITE: &str = "readwrite";
75
+ const PERMISSIONS_ALL : & str = "all" ;
76
+
64
77
#[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
65
78
pub struct ObjectStoreFormat {
66
- #[ serde( rename = "objectstore-format" ) ]
67
79
pub version : String ,
80
+ #[ serde( rename = "objectstore-format" ) ]
81
+ pub objectstore_format : String ,
82
+ #[ serde( rename = "created-at" ) ]
83
+ pub created_at : String ,
84
+ pub owner : Owner ,
85
+ pub access : Access ,
86
+ }
87
+
88
+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
89
+ pub struct Owner {
90
+ pub id : String ,
91
+ pub group : String ,
92
+ }
93
+
94
+ impl Owner {
95
+ pub fn new ( id : String , group : String ) -> Self {
96
+ Self { id, group }
97
+ }
98
+ }
99
+
100
+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
101
+ pub struct Access {
102
+ pub objects : Vec < AccessObject > ,
103
+ }
104
+
105
+ impl Access {
106
+ pub fn new ( objects : Vec < AccessObject > ) -> Self {
107
+ Self { objects }
108
+ }
109
+ }
110
+
111
+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
112
+ pub struct AccessObject {
113
+ pub id : String ,
114
+ pub group : String ,
115
+ pub permissions : Vec < String > ,
116
+ }
117
+
118
+ impl AccessObject {
119
+ pub fn new ( id : String ) -> Self {
120
+ Self {
121
+ id : id. clone ( ) ,
122
+ group : id,
123
+ permissions : vec ! [ PERMISSIONS_ALL . to_string( ) ] ,
124
+ }
125
+ }
68
126
}
69
127
70
128
impl Default for ObjectStoreFormat {
71
129
fn default ( ) -> Self {
72
130
Self {
73
131
version : "v1" . to_string ( ) ,
132
+ objectstore_format : "v1" . to_string ( ) ,
133
+ created_at : Local :: now ( ) . to_rfc3339 ( ) ,
134
+ owner : Owner :: new ( "" . to_string ( ) , "" . to_string ( ) ) ,
135
+ access : Access :: new ( vec ! [ ] ) ,
74
136
}
75
137
}
76
138
}
77
139
140
+ impl ObjectStoreFormat {
141
+ fn set_id ( & mut self , id : String ) {
142
+ self . owner . id . clone_from ( & id) ;
143
+ self . owner . group = id;
144
+ }
145
+ fn set_access ( & mut self , access : Vec < AccessObject > ) {
146
+ self . access . objects = access;
147
+ }
148
+ }
149
+
78
150
lazy_static:: lazy_static! {
79
151
#[ derive( Debug ) ]
80
152
pub static ref S3_CONFIG : Arc <S3Config > = Arc :: new( CONFIG . storage( ) . clone( ) ) ;
@@ -219,7 +291,7 @@ impl S3 {
219
291
. client
220
292
. put_object ( )
221
293
. bucket ( & S3_CONFIG . s3_bucket_name )
222
- . key ( format ! ( "{}/.schema " , stream_name) )
294
+ . key ( format ! ( "{}/{} " , stream_name, SCHEMA_FILE_NAME ) )
223
295
. body ( body. into_bytes ( ) . into ( ) )
224
296
. send ( )
225
297
. await ?;
@@ -235,26 +307,22 @@ impl S3 {
235
307
. client
236
308
. put_object ( )
237
309
. bucket ( & S3_CONFIG . s3_bucket_name )
238
- . key ( format ! ( "{}/.schema " , stream_name) )
310
+ . key ( format ! ( "{}/{} " , stream_name, SCHEMA_FILE_NAME ) )
239
311
. send ( )
240
312
. await ?;
241
- self . _put_parseable_config ( stream_name, format) . await ?;
313
+ self . _put_stream_meta ( stream_name, format) . await ?;
242
314
// Prefix created on S3, now create the directory in
243
315
// the local storage as well
244
316
let _res = fs:: create_dir_all ( CONFIG . parseable . local_stream_data_path ( stream_name) ) ;
245
317
Ok ( ( ) )
246
318
}
247
319
248
- async fn _put_parseable_config (
249
- & self ,
250
- stream_name : & str ,
251
- body : Vec < u8 > ,
252
- ) -> Result < ( ) , AwsSdkError > {
320
+ async fn _put_stream_meta ( & self , stream_name : & str , body : Vec < u8 > ) -> Result < ( ) , AwsSdkError > {
253
321
let _resp = self
254
322
. client
255
323
. put_object ( )
256
324
. bucket ( & S3_CONFIG . s3_bucket_name )
257
- . key ( format ! ( "{}/.parseable.json " , stream_name) )
325
+ . key ( format ! ( "{}/{} " , stream_name, METADATA_FILE_NAME ) )
258
326
. body ( body. into ( ) )
259
327
. send ( )
260
328
. await ?;
@@ -297,7 +365,7 @@ impl S3 {
297
365
. client
298
366
. put_object ( )
299
367
. bucket ( & S3_CONFIG . s3_bucket_name )
300
- . key ( format ! ( "{}/.alert.json " , stream_name) )
368
+ . key ( format ! ( "{}/{} " , stream_name, ALERT_FILE_NAME ) )
301
369
. body ( body. into ( ) )
302
370
. send ( )
303
371
. await ?;
@@ -306,23 +374,23 @@ impl S3 {
306
374
}
307
375
308
376
async fn _get_schema ( & self , stream_name : & str ) -> Result < Bytes , AwsSdkError > {
309
- self . _get ( stream_name, "schema" ) . await
377
+ self . _get ( stream_name, SCHEMA_FILE_NAME ) . await
310
378
}
311
379
312
380
async fn _alert_exists ( & self , stream_name : & str ) -> Result < Bytes , AwsSdkError > {
313
- self . _get ( stream_name, "alert.json" ) . await
381
+ self . _get ( stream_name, ALERT_FILE_NAME ) . await
314
382
}
315
383
316
- async fn _get_parseable_config ( & self , stream_name : & str ) -> Result < Bytes , AwsSdkError > {
317
- self . _get ( stream_name, "parseable.json" ) . await
384
+ async fn _get_stream_meta ( & self , stream_name : & str ) -> Result < Bytes , AwsSdkError > {
385
+ self . _get ( stream_name, METADATA_FILE_NAME ) . await
318
386
}
319
387
320
388
async fn _get ( & self , stream_name : & str , resource : & str ) -> Result < Bytes , AwsSdkError > {
321
389
let resp = self
322
390
. client
323
391
. get_object ( )
324
392
. bucket ( & S3_CONFIG . s3_bucket_name )
325
- . key ( format ! ( "{}/. {}" , stream_name, resource) )
393
+ . key ( format ! ( "{}/{}" , stream_name, resource) )
326
394
. send ( )
327
395
. await ?;
328
396
let body = resp. body . collect ( ) . await ;
@@ -414,7 +482,11 @@ impl ObjectStorage for S3 {
414
482
}
415
483
416
484
async fn create_stream ( & self , stream_name : & str ) -> Result < ( ) , ObjectStorageError > {
417
- let format = ObjectStoreFormat :: default ( ) ;
485
+ let mut format = ObjectStoreFormat :: default ( ) ;
486
+ format. set_id ( CONFIG . parseable . username . clone ( ) ) ;
487
+ let access_object = AccessObject :: new ( CONFIG . parseable . username . clone ( ) ) ;
488
+ format. set_access ( vec ! [ access_object] ) ;
489
+
418
490
let body = serde_json:: to_vec ( & format) ?;
419
491
self . _create_stream ( stream_name, body) . await ?;
420
492
@@ -440,13 +512,13 @@ impl ObjectStorage for S3 {
440
512
441
513
async fn put_stats ( & self , stream_name : & str , stats : & Stats ) -> Result < ( ) , ObjectStorageError > {
442
514
let stats = serde_json:: to_value ( stats) . expect ( "stats are perfectly serializable" ) ;
443
- let parseable_metadata = self . _get_parseable_config ( stream_name) . await ?;
515
+ let parseable_metadata = self . _get_stream_meta ( stream_name) . await ?;
444
516
let mut parseable_metadata: Value =
445
517
serde_json:: from_slice ( & parseable_metadata) . expect ( "parseable config is valid json" ) ;
446
518
447
519
parseable_metadata[ "stats" ] = stats;
448
520
449
- self . _put_parseable_config ( stream_name, parseable_metadata. to_string ( ) . into_bytes ( ) )
521
+ self . _put_stream_meta ( stream_name, parseable_metadata. to_string ( ) . into_bytes ( ) )
450
522
. await ?;
451
523
Ok ( ( ) )
452
524
}
@@ -470,7 +542,7 @@ impl ObjectStorage for S3 {
470
542
}
471
543
472
544
async fn get_stats ( & self , stream_name : & str ) -> Result < Stats , ObjectStorageError > {
473
- let parseable_metadata = self . _get_parseable_config ( stream_name) . await ?;
545
+ let parseable_metadata = self . _get_stream_meta ( stream_name) . await ?;
474
546
let parseable_metadata: Value =
475
547
serde_json:: from_slice ( & parseable_metadata) . expect ( "parseable config is valid json" ) ;
476
548
0 commit comments