1+ use std:: collections:: BTreeMap ;
2+ use std:: ptr:: read;
3+ //TODO: Check if is possible to use the get_config_path function. Check for reusable components
14use std:: { fs, io:: stdin, path:: PathBuf , process:: exit} ;
25
36use directories:: ProjectDirs ;
7+ use k8s_openapi:: api:: core:: v1:: ConfigMap ;
8+ use k8s_openapi:: serde_json:: json;
9+ use kube:: Config ;
10+ use prost_types:: MethodDescriptorProto ;
411use serde:: Serialize ;
5- use std:: fs:: OpenOptions ;
12+ use std:: fs:: { Metadata , OpenOptions } ;
13+ use std:: result:: Result :: Ok ;
614
715use colored:: Colorize ;
816use std:: thread;
917use std:: time:: Duration ;
1018
1119use std:: process:: Command ;
1220
21+ use kube:: api:: { Api , ObjectMeta , Patch , PatchParams , PostParams } ;
22+ use kube:: client:: Client ;
23+
1324pub struct GeneralData {
1425 env : String ,
1526}
1627#[ derive( Serialize ) ]
1728pub struct MetadataConfigFile {
18- env : String ,
29+ blocklist : Vec < String > ,
1930}
2031#[ derive( Debug ) ]
2132pub enum Environments {
@@ -27,10 +38,10 @@ impl TryFrom<&str> for Environments {
2738 fn try_from ( environment : & str ) -> Result < Self , Self :: Error > {
2839 match environment {
2940 "kubernetes" | "k8s" => Ok ( Environments :: Kubernetes ) ,
30- _ => Err ( format ! (
31- "Environment '{}' not supported. Please insert a supported value: Kubernetes, K8s" ,
32- environment
33- ) ) ,
41+ _ =>
42+ Err (
43+ format ! ( "Environment '{}' not supported. Please insert a supported value: Kubernetes, K8s" , environment)
44+ ) ,
3445 }
3546 }
3647}
@@ -75,141 +86,155 @@ impl GeneralData {
7586
7687pub fn update_cli ( ) {
7788 println ! ( "{} {}" , "=====>" . blue( ) . bold( ) , "Updating CortexFlow CLI" ) ;
78- println ! (
79- "{} {}" ,
80- "=====>" . blue( ) . bold( ) ,
81- "Looking for a newer version"
82- ) ;
89+ println ! ( "{} {}" , "=====>" . blue( ) . bold( ) , "Looking for a newer version" ) ;
8390
84- let output = Command :: new ( "cargo" )
85- . args ( [ "update" , "cortexflow-cli" ] )
86- . output ( )
87- . expect ( "error" ) ;
91+ let output = Command :: new ( "cargo" ) . args ( [ "update" , "cortexflow-cli" ] ) . output ( ) . expect ( "error" ) ;
8892
8993 if !output. status . success ( ) {
90- eprintln ! (
91- "Error updating CLI : {}" ,
92- String :: from_utf8_lossy( & output. stderr)
93- ) ;
94+ eprintln ! ( "Error updating CLI : {}" , String :: from_utf8_lossy( & output. stderr) ) ;
9495 } else {
9596 println ! ( "✅ Updated CLI" ) ;
9697 }
9798}
9899pub fn info ( general_data : GeneralData ) {
99- println ! (
100- "{} {} {}" ,
101- "=====>" . blue( ) . bold( ) ,
102- "Version:" ,
103- GeneralData :: VERSION
104- ) ;
105- println ! (
106- "{} {} {}" ,
107- "=====>" . blue( ) . bold( ) ,
108- "Author:" ,
109- GeneralData :: AUTHOR
110- ) ;
111- println ! (
112- "{} {} {}" ,
113- "=====>" . blue( ) . bold( ) ,
114- "Description:" ,
115- GeneralData :: DESCRIPTION
116- ) ;
117- println ! (
118- "{} {} {}" ,
119- "=====>" . blue( ) . bold( ) ,
120- "Environment:" ,
121- general_data. get_env( )
122- ) ;
100+ println ! ( "{} {} {}" , "=====>" . blue( ) . bold( ) , "Version:" , GeneralData :: VERSION ) ;
101+ println ! ( "{} {} {}" , "=====>" . blue( ) . bold( ) , "Author:" , GeneralData :: AUTHOR ) ;
102+ println ! ( "{} {} {}" , "=====>" . blue( ) . bold( ) , "Description:" , GeneralData :: DESCRIPTION ) ;
103+ println ! ( "{} {} {}" , "=====>" . blue( ) . bold( ) , "Environment:" , general_data. get_env( ) ) ;
123104}
124105
125106fn is_supported_env ( env : & str ) -> bool {
126107 matches ! ( env. to_lowercase( ) . trim( ) , "kubernetes" | "k8s" )
127108}
128109
129110pub fn create_configs ( ) -> MetadataConfigFile {
130- let mut user_input: String = String :: new ( ) ;
131- println ! (
132- "{} {}" ,
133- "=====>" . blue( ) . bold( ) ,
134- "Insert your cluster environment (e.g. Kubernetes)" . white( )
135- ) ;
136- stdin ( ) . read_line ( & mut user_input) . unwrap ( ) ;
137- let cluster_environment = user_input. trim ( ) . to_string ( ) ;
138-
139- if !is_supported_env ( & cluster_environment) {
140- eprintln ! (
141- "Cannot save cluster environment data. Installation aborted. Please insert supported environment"
142- ) ;
143- exit ( 1 ) ;
144- }
111+ let mut blocklist: Vec < String > = Vec :: new ( ) ;
112+ blocklist. push ( "" . to_string ( ) ) ;
145113
146- let configs = MetadataConfigFile {
147- env : cluster_environment,
148- } ;
114+ let configs = MetadataConfigFile { blocklist } ;
149115 configs
150116}
151- //TODO: add here and explaination of what read_configs returns
152- pub fn read_configs ( config_path : PathBuf ) -> String {
153- let config = fs:: File :: open ( config_path) . unwrap ( ) ;
154- let parsed_config: Result < serde_yaml:: Value , serde_yaml:: Error > =
155- serde_yaml:: from_reader ( config) ;
156-
157- match parsed_config {
158- Ok ( cfg) => {
159- let env = & cfg[ "env" ] . as_str ( ) . unwrap ( ) . to_string ( ) ;
160- thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
161- println ! (
162- "{} {} {:?}" ,
163- "[SYSTEM]" . blue( ) . bold( ) ,
164- "Readed configs for env variable:" . white( ) ,
165- env
166- ) ;
167- return env. to_string ( ) ;
117+ pub async fn read_configs ( ) -> Result < Vec < String > , anyhow:: Error > {
118+ let client = Client :: try_default ( ) . await ?;
119+ let namespace = "cortexflow" ;
120+ let configmap = "cortexbrain-client-config" ;
121+ let api: Api < ConfigMap > = Api :: namespaced ( client, namespace) ;
122+
123+ let cm = api. get ( configmap) . await ?;
124+
125+ if let Some ( data) = cm. data {
126+ if let Some ( blocklist_raw) = data. get ( "blocklist" ) {
127+ let lines: Vec < String > = blocklist_raw
128+ . lines ( )
129+ . map ( |s| s. trim ( ) . to_string ( ) )
130+ . filter ( |s| !s. is_empty ( ) ) // ignora righe vuote
131+ . collect ( ) ;
132+
133+ return Ok ( lines) ;
134+ }
135+ }
136+
137+ Ok ( Vec :: new ( ) ) //in case the key fails
138+ }
139+ pub async fn create_config_file ( config_struct : MetadataConfigFile ) -> Result < ( ) , anyhow:: Error > {
140+ let client = Client :: try_default ( ) . await ?;
141+ let namespace = "cortexflow" ;
142+ let configmap = "cortexbrain-client-config" ;
143+
144+ let api: Api < ConfigMap > = Api :: namespaced ( client, namespace) ;
145+
146+ // create configmap
147+ let mut data = BTreeMap :: new ( ) ;
148+ for x in config_struct. blocklist {
149+ data. insert ( "blocklist" . to_string ( ) , x) ;
150+ }
151+ let cm = ConfigMap {
152+ metadata : ObjectMeta {
153+ name : Some ( "cortexbrain-client-config" . to_string ( ) ) ,
154+ ..Default :: default ( )
155+ } , // type ObjectMeta
156+ data : Some ( data) , //type Option<BTreeMap<String, String, Global>>
157+ ..Default :: default ( )
158+ } ;
159+ match api. create ( & PostParams :: default ( ) , & cm) . await {
160+ Ok ( _) => {
161+ println ! ( "Configmap created successfully" ) ;
168162 }
169163 Err ( e) => {
170- eprintln ! ( "An error occured while reading the config file: {:?}" , e) ;
171- exit ( 1 )
164+ eprintln ! ( "An error occured: {}" , e) ;
172165 }
173- }
166+ } ;
167+ Ok ( ( ) )
174168}
175169
176- pub fn create_config_file ( config_struct : MetadataConfigFile ) {
177- let dirs = ProjectDirs :: from ( "org" , "cortexflow" , "cfcli" )
178- . expect ( "Cannot determine the config directory" ) ;
179- let config_dir = dirs. config_dir ( ) . to_path_buf ( ) ;
180- let config_save_path = config_dir. join ( "config.yaml" ) ;
170+ pub async fn update_config_metadata ( input : & str , action : & str ) {
171+ if action == "add" {
172+ //retrieve current blocked ips list
173+ let mut ips = read_configs ( ) . await . unwrap ( ) ;
174+ println ! ( "Readed current blocked ips: {:?}" , ips) ;
175+
176+ //create a temporary vector of ips
177+ ips. push ( input. to_string ( ) ) ;
178+
179+ // override blocklist parameters
180+ let new_configs = MetadataConfigFile { blocklist : ips } ;
181+ //create a new config
182+ update_configmap ( new_configs) . await ;
183+ } else if action == "delete" {
184+ let mut ips = read_configs ( ) . await . unwrap ( ) ;
185+ if let Some ( index) = ips. iter ( ) . position ( |target| target == & input. to_string ( ) ) {
186+ ips. remove ( index) ;
187+ } else {
188+ eprintln ! ( "Index of element not found" ) ;
189+ }
181190
182- //create directory
183- fs:: create_dir_all ( & config_dir) . expect ( "Cannot create directories" ) ;
191+ // override blocklist parameters
192+ let new_configs = MetadataConfigFile { blocklist : ips } ;
193+ //create a new config
194+ update_configmap ( new_configs) . await ;
195+ }
196+ }
184197
185- let configs = OpenOptions :: new ( )
186- . write ( true )
187- . create ( true )
188- . open ( & config_save_path)
189- . expect ( "Cannot open config file" ) ;
198+ pub async fn update_configmap ( config_struct : MetadataConfigFile ) -> Result < ( ) , anyhow:: Error > {
199+ let client = Client :: try_default ( ) . await ?;
200+ let namespace = "cortexflow" ;
201+ let name = "cortexbrain-client-config" ;
202+ let api: Api < ConfigMap > = Api :: namespaced ( client, namespace) ;
203+
204+ let blocklist_yaml = config_struct
205+ . blocklist
206+ . iter ( )
207+ . map ( |x| format ! ( "{}" , x) )
208+ . collect :: < Vec < String > > ( )
209+ . join ( "\n " ) ;
210+
211+ let patch = Patch :: Apply ( json ! ( {
212+ "apiVersion" : "v1" ,
213+ "kind" : "ConfigMap" ,
214+ "data" : {
215+ "blocklist" : blocklist_yaml
216+ }
217+ } ) ) ;
190218
191- match serde_yaml:: to_writer ( configs, & config_struct) {
219+ let patch_params = PatchParams :: apply ( "cortexbrain" ) . force ( ) ;
220+ match api. patch ( name, & patch_params, & patch) . await {
192221 Ok ( _) => {
193- println ! ( "\n " ) ;
194- thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
195- println ! (
196- "{} {}{:?}" ,
197- "[SYSTEM]" . blue( ) . bold( ) ,
198- "Configuration files saved in path :" . white( ) ,
199- & config_save_path. display( )
200- ) ;
201- println ! ( "\n " ) ;
222+ println ! ( "Map updated successfully" ) ;
223+ }
224+ Err ( e) => {
225+ eprintln ! ( "An error occured during the patching process: {}" , e) ;
226+ return Err ( e. into ( ) ) ;
202227 }
203- Err ( e) => eprintln ! (
204- "An error occured during the creation of the config files. {:?}" ,
205- e
206- ) ,
207228 }
229+
230+ Ok ( ( ) )
208231}
232+
209233//TODO: add here an explanation of what are config_dir and file_path
210234pub fn get_config_directory ( ) -> Result < ( PathBuf , PathBuf ) , ( ) > {
211- let dirs = ProjectDirs :: from ( "org" , "cortexflow" , "cfcli" )
212- . expect ( "Cannot determine the config directory" ) ;
235+ let dirs = ProjectDirs :: from ( "org" , "cortexflow" , "cfcli" ) . expect (
236+ "Cannot determine the config directory"
237+ ) ;
213238 let config_dir = dirs. config_dir ( ) . to_path_buf ( ) ;
214239 let file_path = config_dir. join ( "config.yaml" ) ;
215240
@@ -224,4 +249,3 @@ pub fn get_startup_config_dir() -> bool {
224249 } )
225250 . unwrap_or ( false )
226251}
227- // TODO: add save to config function
0 commit comments