feat: Report execution outcome #151
| @ -34,6 +34,7 @@ pub enum InterpretName { | ||||
|     CephClusterHealth, | ||||
|     Custom(&'static str), | ||||
|     RHOBAlerting, | ||||
|     K8sIngress, | ||||
| } | ||||
| 
 | ||||
| impl std::fmt::Display for InterpretName { | ||||
| @ -64,6 +65,7 @@ impl std::fmt::Display for InterpretName { | ||||
|             InterpretName::CephClusterHealth => f.write_str("CephClusterHealth"), | ||||
|             InterpretName::Custom(name) => f.write_str(name), | ||||
|             InterpretName::RHOBAlerting => f.write_str("RHOBAlerting"), | ||||
|             InterpretName::K8sIngress => f.write_str("K8sIngress"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -82,6 +84,7 @@ pub trait Interpret<T>: std::fmt::Debug + Send { | ||||
| pub struct Outcome { | ||||
|     pub status: InterpretStatus, | ||||
|     pub message: String, | ||||
|     pub details: Vec<String>, | ||||
| } | ||||
| 
 | ||||
| impl Outcome { | ||||
| @ -89,6 +92,7 @@ impl Outcome { | ||||
|         Self { | ||||
|             status: InterpretStatus::NOOP, | ||||
|             message: String::new(), | ||||
|             details: vec![], | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -96,6 +100,23 @@ impl Outcome { | ||||
|         Self { | ||||
|             status: InterpretStatus::SUCCESS, | ||||
|             message, | ||||
|             details: vec![], | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn success_with_details(message: String, details: Vec<String>) -> Self { | ||||
|         Self { | ||||
|             status: InterpretStatus::SUCCESS, | ||||
|             message, | ||||
|             details, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn running(message: String) -> Self { | ||||
|         Self { | ||||
|             status: InterpretStatus::RUNNING, | ||||
|             message, | ||||
|             details: vec![], | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -69,17 +69,14 @@ impl DhcpInterpret { | ||||
| 
 | ||||
|         dhcp_server.set_pxe_options(pxe_options).await?; | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             format!( | ||||
|         Ok(Outcome::success(format!( | ||||
|             "Dhcp Interpret Set next boot to [{:?}], boot_filename to [{:?}], filename to [{:?}], filename64 to [{:?}], filenameipxe to [:{:?}]", | ||||
|             self.score.boot_filename, | ||||
|             self.score.boot_filename, | ||||
|             self.score.filename, | ||||
|             self.score.filename64, | ||||
|             self.score.filenameipxe | ||||
|             ), | ||||
|         )) | ||||
|         ))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -122,8 +119,7 @@ impl<T: Topology + DhcpServer> Interpret<T> for DhcpInterpret { | ||||
| 
 | ||||
|         topology.commit_config().await?; | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|         Ok(Outcome::success( | ||||
|             "Dhcp Interpret execution successful".to_string(), | ||||
|         )) | ||||
|     } | ||||
| @ -197,10 +193,10 @@ impl DhcpHostBindingInterpret { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             format!("Dhcp Interpret registered {} entries", number_new_entries), | ||||
|         )) | ||||
|         Ok(Outcome::success(format!( | ||||
|             "Dhcp Interpret registered {} entries", | ||||
|             number_new_entries | ||||
|         ))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -236,12 +232,9 @@ impl<T: DhcpServer> Interpret<T> for DhcpHostBindingInterpret { | ||||
| 
 | ||||
|         topology.commit_config().await?; | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             format!( | ||||
|         Ok(Outcome::success(format!( | ||||
|             "Dhcp Host Binding Interpret execution successful on {} hosts", | ||||
|             self.score.host_binding.len() | ||||
|             ), | ||||
|         )) | ||||
|         ))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -55,8 +55,7 @@ impl DnsInterpret { | ||||
|             dns.register_dhcp_leases(register).await?; | ||||
|         } | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|         Ok(Outcome::success( | ||||
|             "DNS Interpret execution successfull".to_string(), | ||||
|         )) | ||||
|     } | ||||
| @ -68,13 +67,10 @@ impl DnsInterpret { | ||||
|         let entries = &self.score.dns_entries; | ||||
|         dns_server.ensure_hosts_registered(entries.clone()).await?; | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             format!( | ||||
|         Ok(Outcome::success(format!( | ||||
|             "DnsInterpret registered {} hosts successfully", | ||||
|             entries.len() | ||||
|             ), | ||||
|         )) | ||||
|         ))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -111,8 +107,7 @@ impl<T: Topology + DnsServer> Interpret<T> for DnsInterpret { | ||||
| 
 | ||||
|         topology.commit_config().await?; | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|         Ok(Outcome::success( | ||||
|             "Dns Interpret execution successful".to_string(), | ||||
|         )) | ||||
|     } | ||||
|  | ||||
| @ -197,13 +197,10 @@ impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret { | ||||
|                     self.score.release_name, ns | ||||
|                 ); | ||||
| 
 | ||||
|                 return Ok(Outcome::new( | ||||
|                     InterpretStatus::SUCCESS, | ||||
|                     format!( | ||||
|                 return Ok(Outcome::success(format!( | ||||
|                     "Helm Chart '{}' already installed to namespace {ns} and install_only=true", | ||||
|                     self.score.release_name | ||||
|                     ), | ||||
|                 )); | ||||
|                 ))); | ||||
|             } else { | ||||
|                 info!( | ||||
|                     "Release '{}' not found in namespace '{}'. Proceeding with installation.", | ||||
| @ -228,18 +225,18 @@ impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret { | ||||
|         }; | ||||
| 
 | ||||
|         match status { | ||||
|             helm_wrapper_rs::HelmDeployStatus::Deployed => Ok(Outcome::new( | ||||
|                 InterpretStatus::SUCCESS, | ||||
|                 format!("Helm Chart {} deployed", self.score.release_name), | ||||
|             )), | ||||
|             helm_wrapper_rs::HelmDeployStatus::PendingInstall => Ok(Outcome::new( | ||||
|                 InterpretStatus::RUNNING, | ||||
|                 format!("Helm Chart {} pending install...", self.score.release_name), | ||||
|             )), | ||||
|             helm_wrapper_rs::HelmDeployStatus::PendingUpgrade => Ok(Outcome::new( | ||||
|                 InterpretStatus::RUNNING, | ||||
|                 format!("Helm Chart {} pending upgrade...", self.score.release_name), | ||||
|             )), | ||||
|             helm_wrapper_rs::HelmDeployStatus::Deployed => Ok(Outcome::success(format!( | ||||
|                 "Helm Chart {} deployed", | ||||
|                 self.score.release_name | ||||
|             ))), | ||||
|             helm_wrapper_rs::HelmDeployStatus::PendingInstall => Ok(Outcome::running(format!( | ||||
|                 "Helm Chart {} pending install...", | ||||
|                 self.score.release_name | ||||
|             ))), | ||||
|             helm_wrapper_rs::HelmDeployStatus::PendingUpgrade => Ok(Outcome::running(format!( | ||||
|                 "Helm Chart {} pending upgrade...", | ||||
|                 self.score.release_name | ||||
|             ))), | ||||
|             helm_wrapper_rs::HelmDeployStatus::Failed => Err(InterpretError::new(format!( | ||||
|                 "Helm Chart {} installation failed", | ||||
|                 self.score.release_name | ||||
|  | ||||
| @ -133,10 +133,9 @@ impl<T: Topology> Interpret<T> for DiscoverInventoryAgentInterpret { | ||||
|             }, | ||||
|         ) | ||||
|         .await; | ||||
|         Ok(Outcome { | ||||
|             status: InterpretStatus::SUCCESS, | ||||
|             message: "Discovery process completed successfully".to_string(), | ||||
|         }) | ||||
|         Ok(Outcome::success( | ||||
|             "Discovery process completed successfully".to_string(), | ||||
|         )) | ||||
|     } | ||||
| 
 | ||||
|     fn get_name(&self) -> InterpretName { | ||||
|  | ||||
| @ -1,11 +1,15 @@ | ||||
| use async_trait::async_trait; | ||||
| use harmony_macros::ingress_path; | ||||
| use harmony_types::id::Id; | ||||
| use k8s_openapi::api::networking::v1::Ingress; | ||||
| use log::{debug, trace}; | ||||
| use serde::Serialize; | ||||
| use serde_json::json; | ||||
| 
 | ||||
| use crate::{ | ||||
|     interpret::Interpret, | ||||
|     data::Version, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::Inventory, | ||||
|     score::Score, | ||||
|     topology::{K8sclient, Topology}, | ||||
| }; | ||||
| @ -57,7 +61,7 @@ impl<T: Topology + K8sclient> Score<T> for K8sIngressScore { | ||||
| 
 | ||||
|         let ingress_class = match self.ingress_class_name.clone() { | ||||
|             Some(ingress_class_name) => ingress_class_name, | ||||
|             None => format!("\"default\""), | ||||
|             None => "\"default\"".to_string(), | ||||
|         }; | ||||
| 
 | ||||
|         let ingress = json!( | ||||
| @ -97,11 +101,12 @@ impl<T: Topology + K8sclient> Score<T> for K8sIngressScore { | ||||
|             "Successfully built Ingress for host {:?}", | ||||
|             ingress.metadata.name | ||||
|         ); | ||||
|         Box::new(K8sResourceInterpret { | ||||
|             score: K8sResourceScore::single( | ||||
|                 ingress.clone(), | ||||
|                 self.namespace.clone().map(|f| f.to_string()), | ||||
|             ), | ||||
| 
 | ||||
|         Box::new(K8sIngressInterpret { | ||||
|             ingress, | ||||
|             service: self.name.to_string(), | ||||
|             namespace: self.namespace.clone().map(|f| f.to_string()), | ||||
|             host: self.host.clone(), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
| @ -109,3 +114,59 @@ impl<T: Topology + K8sclient> Score<T> for K8sIngressScore { | ||||
|         format!("{} K8sIngressScore", self.name) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(std::fmt::Debug)] | ||||
| struct K8sIngressInterpret { | ||||
|     ingress: Ingress, | ||||
|     service: String, | ||||
|     namespace: Option<String>, | ||||
|     host: fqdn::FQDN, | ||||
| } | ||||
| 
 | ||||
| #[async_trait] | ||||
| impl<T: Topology + K8sclient> Interpret<T> for K8sIngressInterpret { | ||||
|     async fn execute( | ||||
|         &self, | ||||
|         inventory: &Inventory, | ||||
|         topology: &T, | ||||
|     ) -> Result<Outcome, InterpretError> { | ||||
|         let result = K8sResourceInterpret { | ||||
|             score: K8sResourceScore::single(self.ingress.clone(), self.namespace.clone()), | ||||
|         } | ||||
|         .execute(inventory, topology) | ||||
|         .await; | ||||
| 
 | ||||
|         match result { | ||||
|             Ok(outcome) => match outcome.status { | ||||
|                 InterpretStatus::SUCCESS => { | ||||
|                     let details = match &self.namespace { | ||||
|                         Some(namespace) => { | ||||
|                             vec![format!("{} ({namespace}): {}", self.service, self.host)] | ||||
|                         } | ||||
|                         None => vec![format!("{}: {}", self.service, self.host)], | ||||
|                     }; | ||||
| 
 | ||||
|                     Ok(Outcome::success_with_details(outcome.message, details)) | ||||
|                 } | ||||
|                 _ => Ok(outcome), | ||||
|             }, | ||||
|             Err(e) => Err(e), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_name(&self) -> InterpretName { | ||||
|         InterpretName::K8sIngress | ||||
|     } | ||||
| 
 | ||||
|     fn get_version(&self) -> Version { | ||||
|         Version::from("0.0.1").unwrap() | ||||
|     } | ||||
| 
 | ||||
|     fn get_status(&self) -> InterpretStatus { | ||||
|         todo!() | ||||
|     } | ||||
| 
 | ||||
|     fn get_children(&self) -> Vec<Id> { | ||||
|         vec![] | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,19 +1,19 @@ | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_types::id::Id; | ||||
| use log::{error, info, warn}; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     data::Version, | ||||
|     hardware::PhysicalHost, | ||||
|     infra::inventory::InventoryRepositoryFactory, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::{HostRole, Inventory}, | ||||
|     modules::inventory::{DiscoverHostForRoleScore, LaunchDiscoverInventoryAgentScore}, | ||||
|     modules::inventory::DiscoverHostForRoleScore, | ||||
|     score::Score, | ||||
|     topology::HAClusterTopology, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_types::id::Id; | ||||
| use log::info; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| // -------------------------------------------------------------------------------------------------
 | ||||
| // Step 01: Inventory (default PXE + Kickstart in RAM + Rust agent)
 | ||||
| // - This score exposes/ensures the default inventory assets and waits for discoveries.
 | ||||
| @ -109,12 +109,9 @@ When you can dig them, confirm to continue. | ||||
|             .await?; | ||||
|         } | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             format!( | ||||
|         Ok(Outcome::success(format!( | ||||
|             "Found and assigned bootstrap node: {}", | ||||
|             bootstrap_host.unwrap().summary() | ||||
|             ), | ||||
|         )) | ||||
|         ))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,25 +1,13 @@ | ||||
| use std::{fmt::Write, path::PathBuf}; | ||||
| 
 | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_secret::SecretManager; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, error, info, warn}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use tokio::{fs::File, io::AsyncWriteExt, process::Command}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     config::secret::{RedhatSecret, SshKeyPair}, | ||||
|     data::{FileContent, FilePath, Version}, | ||||
|     hardware::PhysicalHost, | ||||
|     infra::inventory::InventoryRepositoryFactory, | ||||
|     instrumentation::{HarmonyEvent, instrument}, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::{HostRole, Inventory}, | ||||
|     modules::{ | ||||
|         dhcp::DhcpHostBindingScore, | ||||
|         http::{IPxeMacBootFileScore, StaticFilesHttpScore}, | ||||
|         inventory::LaunchDiscoverInventoryAgentScore, | ||||
|         okd::{ | ||||
|             bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, | ||||
|             templates::{BootstrapIpxeTpl, InstallConfigYaml}, | ||||
| @ -28,6 +16,15 @@ use crate::{ | ||||
|     score::Score, | ||||
|     topology::{HAClusterTopology, HostBinding}, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_secret::SecretManager; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, info}; | ||||
| use serde::Serialize; | ||||
| use std::path::PathBuf; | ||||
| use tokio::{fs::File, io::AsyncWriteExt, process::Command}; | ||||
| 
 | ||||
| // -------------------------------------------------------------------------------------------------
 | ||||
| // Step 02: Bootstrap
 | ||||
| // - Select bootstrap node (from discovered set).
 | ||||
| @ -313,7 +310,7 @@ impl OKDSetup02BootstrapInterpret { | ||||
|         info!("[Bootstrap] Rebooting bootstrap node via SSH"); | ||||
|         // TODO reboot programatically, there are some logical checks and refactoring to do such as
 | ||||
|         // accessing the bootstrap node config (ip address) from the inventory
 | ||||
|         let confirmation = inquire::Confirm::new( | ||||
|         let _ = inquire::Confirm::new( | ||||
|                 "Now reboot the bootstrap node so it picks up its pxe boot file. Press enter when ready.", | ||||
|         ) | ||||
|         .prompt() | ||||
| @ -379,9 +376,6 @@ impl Interpret<HAClusterTopology> for OKDSetup02BootstrapInterpret { | ||||
|         self.reboot_target().await?; | ||||
|         self.wait_for_bootstrap_complete().await?; | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             "Bootstrap phase complete".into(), | ||||
|         )) | ||||
|         Ok(Outcome::success("Bootstrap phase complete".into())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,3 @@ | ||||
| use std::{fmt::Write, path::PathBuf}; | ||||
| 
 | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, info}; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     data::Version, | ||||
|     hardware::PhysicalHost, | ||||
| @ -19,6 +11,12 @@ use crate::{ | ||||
|     score::Score, | ||||
|     topology::{HAClusterTopology, HostBinding}, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, info}; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| // -------------------------------------------------------------------------------------------------
 | ||||
| // Step 03: Control Plane
 | ||||
| // - Render per-MAC PXE & ignition for cp0/cp1/cp2.
 | ||||
| @ -269,8 +267,7 @@ impl Interpret<HAClusterTopology> for OKDSetup03ControlPlaneInterpret { | ||||
|         // the `wait-for bootstrap-complete` command.
 | ||||
|         info!("[ControlPlane] Provisioning initiated. Monitor the cluster convergence manually."); | ||||
| 
 | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|         Ok(Outcome::success( | ||||
|             "Control plane provisioning has been successfully initiated.".into(), | ||||
|         )) | ||||
|     } | ||||
|  | ||||
| @ -1,33 +1,17 @@ | ||||
| use std::{fmt::Write, path::PathBuf}; | ||||
| 
 | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_secret::SecretManager; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, error, info, warn}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use tokio::{fs::File, io::AsyncWriteExt, process::Command}; | ||||
| use log::info; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     config::secret::{RedhatSecret, SshKeyPair}, | ||||
|     data::{FileContent, FilePath, Version}, | ||||
|     hardware::PhysicalHost, | ||||
|     infra::inventory::InventoryRepositoryFactory, | ||||
|     instrumentation::{HarmonyEvent, instrument}, | ||||
|     data::Version, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::{HostRole, Inventory}, | ||||
|     modules::{ | ||||
|         dhcp::DhcpHostBindingScore, | ||||
|         http::{IPxeMacBootFileScore, StaticFilesHttpScore}, | ||||
|         inventory::LaunchDiscoverInventoryAgentScore, | ||||
|         okd::{ | ||||
|             bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, | ||||
|             templates::{BootstrapIpxeTpl, InstallConfigYaml}, | ||||
|         }, | ||||
|     }, | ||||
|     inventory::Inventory, | ||||
|     score::Score, | ||||
|     topology::{HAClusterTopology, HostBinding}, | ||||
|     topology::HAClusterTopology, | ||||
| }; | ||||
| 
 | ||||
| // -------------------------------------------------------------------------------------------------
 | ||||
| // Step 04: Workers
 | ||||
| // - Render per-MAC PXE & ignition for workers; join nodes.
 | ||||
| @ -94,9 +78,6 @@ impl Interpret<HAClusterTopology> for OKDSetup04WorkersInterpret { | ||||
|         _topology: &HAClusterTopology, | ||||
|     ) -> Result<Outcome, InterpretError> { | ||||
|         self.render_and_reboot().await?; | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             "Workers provisioned".into(), | ||||
|         )) | ||||
|         Ok(Outcome::success("Workers provisioned".into())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,33 +1,16 @@ | ||||
| use std::{fmt::Write, path::PathBuf}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     data::Version, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::Inventory, | ||||
|     score::Score, | ||||
|     topology::HAClusterTopology, | ||||
| }; | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_secret::SecretManager; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, error, info, warn}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use tokio::{fs::File, io::AsyncWriteExt, process::Command}; | ||||
| use log::info; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     config::secret::{RedhatSecret, SshKeyPair}, | ||||
|     data::{FileContent, FilePath, Version}, | ||||
|     hardware::PhysicalHost, | ||||
|     infra::inventory::InventoryRepositoryFactory, | ||||
|     instrumentation::{HarmonyEvent, instrument}, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::{HostRole, Inventory}, | ||||
|     modules::{ | ||||
|         dhcp::DhcpHostBindingScore, | ||||
|         http::{IPxeMacBootFileScore, StaticFilesHttpScore}, | ||||
|         inventory::LaunchDiscoverInventoryAgentScore, | ||||
|         okd::{ | ||||
|             bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, | ||||
|             templates::{BootstrapIpxeTpl, InstallConfigYaml}, | ||||
|         }, | ||||
|     }, | ||||
|     score::Score, | ||||
|     topology::{HAClusterTopology, HostBinding}, | ||||
| }; | ||||
| // -------------------------------------------------------------------------------------------------
 | ||||
| // Step 05: Sanity Check
 | ||||
| // - Validate API reachability, ClusterOperators, ingress, and SDN status.
 | ||||
| @ -93,9 +76,6 @@ impl Interpret<HAClusterTopology> for OKDSetup05SanityCheckInterpret { | ||||
|         _topology: &HAClusterTopology, | ||||
|     ) -> Result<Outcome, InterpretError> { | ||||
|         self.run_checks().await?; | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             "Sanity checks passed".into(), | ||||
|         )) | ||||
|         Ok(Outcome::success("Sanity checks passed".into())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,32 +1,15 @@ | ||||
| // -------------------------------------------------------------------------------------------------
 | ||||
| use async_trait::async_trait; | ||||
| use derive_new::new; | ||||
| use harmony_secret::SecretManager; | ||||
| use harmony_types::id::Id; | ||||
| use log::{debug, error, info, warn}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use std::{fmt::Write, path::PathBuf}; | ||||
| use tokio::{fs::File, io::AsyncWriteExt, process::Command}; | ||||
| use log::info; | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use crate::{ | ||||
|     config::secret::{RedhatSecret, SshKeyPair}, | ||||
|     data::{FileContent, FilePath, Version}, | ||||
|     hardware::PhysicalHost, | ||||
|     infra::inventory::InventoryRepositoryFactory, | ||||
|     instrumentation::{HarmonyEvent, instrument}, | ||||
|     data::Version, | ||||
|     interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, | ||||
|     inventory::{HostRole, Inventory}, | ||||
|     modules::{ | ||||
|         dhcp::DhcpHostBindingScore, | ||||
|         http::{IPxeMacBootFileScore, StaticFilesHttpScore}, | ||||
|         inventory::LaunchDiscoverInventoryAgentScore, | ||||
|         okd::{ | ||||
|             bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, | ||||
|             templates::{BootstrapIpxeTpl, InstallConfigYaml}, | ||||
|         }, | ||||
|     }, | ||||
|     inventory::Inventory, | ||||
|     score::Score, | ||||
|     topology::{HAClusterTopology, HostBinding}, | ||||
|     topology::HAClusterTopology, | ||||
| }; | ||||
| 
 | ||||
| // Step 06: Installation Report
 | ||||
| @ -93,9 +76,6 @@ impl Interpret<HAClusterTopology> for OKDSetup06InstallationReportInterpret { | ||||
|         _topology: &HAClusterTopology, | ||||
|     ) -> Result<Outcome, InterpretError> { | ||||
|         self.generate().await?; | ||||
|         Ok(Outcome::new( | ||||
|             InterpretStatus::SUCCESS, | ||||
|             "Installation report generated".into(), | ||||
|         )) | ||||
|         Ok(Outcome::success("Installation report generated".into())) | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										32
									
								
								harmony_cli/src/cli_reporter.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								harmony_cli/src/cli_reporter.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| use std::sync::Mutex; | ||||
| 
 | ||||
| use harmony::instrumentation::{self, HarmonyEvent}; | ||||
| use log::info; | ||||
| 
 | ||||
| pub fn init() { | ||||
|     let details: Mutex<Vec<String>> = Mutex::new(vec![]); | ||||
| 
 | ||||
|     instrumentation::subscribe("Harmony CLI Reporter", { | ||||
|         move |event| { | ||||
|             let mut details = details.lock().unwrap(); | ||||
| 
 | ||||
|             if let HarmonyEvent::InterpretExecutionFinished { | ||||
|                 execution_id: _, | ||||
|                 topology: _, | ||||
|                 interpret: _, | ||||
|                 score: _, | ||||
|                 outcome: Ok(outcome), | ||||
|             } = event | ||||
|             { | ||||
|                 if outcome.status == harmony::interpret::InterpretStatus::SUCCESS { | ||||
|                     details.extend(outcome.details.clone()); | ||||
|                 } | ||||
|             } else if let HarmonyEvent::HarmonyFinished = event { | ||||
|                 info!("Here's a summary of what happened:"); | ||||
|                 for detail in details.iter() { | ||||
|                     println!("{detail}"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| @ -8,6 +8,7 @@ use inquire::Confirm; | ||||
| use log::debug; | ||||
| 
 | ||||
| pub mod cli_logger; // FIXME: Don't make me pub
 | ||||
| mod cli_reporter; | ||||
| pub mod progress; | ||||
| pub mod theme; | ||||
| 
 | ||||
| @ -116,6 +117,7 @@ pub async fn run_cli<T: Topology + Send + Sync + 'static>( | ||||
|     args: Args, | ||||
| ) -> Result<(), Box<dyn std::error::Error>> { | ||||
|     cli_logger::init(); | ||||
|     cli_reporter::init(); | ||||
| 
 | ||||
|     let mut maestro = Maestro::initialize(inventory, topology).await.unwrap(); | ||||
|     maestro.register_all(scores); | ||||
|  | ||||
| @ -21,7 +21,6 @@ pub fn handle_events() { | ||||
| 
 | ||||
|     instrumentation::subscribe("Harmony Composer Logger", { | ||||
|         move |event| match event { | ||||
|             HarmonyComposerEvent::HarmonyComposerStarted => {} | ||||
|             HarmonyComposerEvent::ProjectInitializationStarted => { | ||||
|                 progress_tracker.add_section( | ||||
|                     SETUP_SECTION, | ||||
|  | ||||
| @ -5,7 +5,6 @@ use crate::{HarmonyProfile, HarmonyTarget}; | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum HarmonyComposerEvent { | ||||
|     HarmonyComposerStarted, | ||||
|     ProjectInitializationStarted, | ||||
|     ProjectInitialized, | ||||
|     ProjectCompilationStarted { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user