Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial skeleton for HealthClient API in mssf_core #114

Merged
merged 12 commits into from
Jan 8, 2025
36 changes: 36 additions & 0 deletions crates/libs/core/src/client/health_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

use mssf_com::FabricClient::IFabricHealthClient4;

use crate::types::HealthReport;

/// Provides functionality to perform health related operations, like report and query health.
/// See C# API [here](https://docs.microsoft.com/en-us/dotnet/api/system.fabric.fabricclient.healthclient?view=azure-dotnet).
///
/// TODO: Implement full functionality of the HealthClient.
#[derive(Debug, Clone)]
pub struct HealthClient {
com: IFabricHealthClient4,
}

// Public implementation block
impl HealthClient {
pub fn from_com(com: IFabricHealthClient4) -> Self {
Self { com: com.clone() }
}

/// Reports health on a Service Fabric entity. See C# API [here](https://docs.microsoft.com/en-us/dotnet/api/system.fabric.fabricclient.healthclient.reporthealth?view=azure-dotnet).
///
/// Remarks:
/// When a cluster is secured, the health client needs administrator permission to be able to send the reports.
/// Read more about [connecting to a cluster using the FabricClient APIs](https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-connect-to-secure-cluster).
/// For more information about health reporting, see [Service Fabric health monitoring](https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-health-introduction).
pub fn report_health(&self, health_report: HealthReport) -> windows_core::Result<()> {
let com = &self.com;
let report = (&health_report).into();
unsafe { com.ReportHealth(&report) }
}
}
30 changes: 21 additions & 9 deletions crates/libs/core/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
// ------------------------------------------------------------

use connection::{ClientConnectionEventHandlerBridge, LambdaClientConnectionNotificationHandler};
use health_client::HealthClient;
use mssf_com::FabricClient::{
IFabricClientConnectionEventHandler, IFabricPropertyManagementClient2, IFabricQueryClient10,
IFabricServiceManagementClient6, IFabricServiceNotificationEventHandler,
IFabricClientConnectionEventHandler, IFabricHealthClient4, IFabricPropertyManagementClient2,
IFabricQueryClient10, IFabricServiceManagementClient6, IFabricServiceNotificationEventHandler,
};
use notification::{
LambdaServiceNotificationHandler, ServiceNotificationEventHandler,
Expand All @@ -20,6 +21,9 @@ use self::{query_client::QueryClient, svc_mgmt_client::ServiceManagementClient};

mod connection;
mod notification;

// Export public client modules
pub mod health_client;
pub mod query_client;
pub mod svc_mgmt_client;

Expand Down Expand Up @@ -201,6 +205,7 @@ pub struct FabricClient {
com_property_client: IFabricPropertyManagementClient2,
com_service_client: IFabricServiceManagementClient6,
com_query_client: IFabricQueryClient10,
com_health_client: IFabricHealthClient4,
}

impl FabricClient {
Expand All @@ -209,44 +214,51 @@ impl FabricClient {
FabricClientBuilder::new()
}

// Get a copy of COM object
/// Get a copy of COM object
pub fn get_com(&self) -> IFabricPropertyManagementClient2 {
self.com_property_client.clone()
}

// Creates from com directly. This gives the user freedom to create com from
// custom code and pass it in.
// For the final state of FabricClient, this function should be private.
/// Creates from com directly. This gives the user freedom to create com from
/// custom code and pass it in.
/// For the final state of FabricClient, this function should be private.
pub fn from_com(com: IFabricPropertyManagementClient2) -> Self {
let com_property_client = com.clone();
let com_service_client = com
.clone()
.cast::<IFabricServiceManagementClient6>()
.unwrap();
let com_query_client = com.clone().cast::<IFabricQueryClient10>().unwrap();
let com_health_client = com.clone().cast::<IFabricHealthClient4>().unwrap();
Self {
com_property_client,
com_service_client,
com_query_client,
com_health_client,
}
}

// Get the client for managing Fabric Properties in Naming Service
/// Get the client for managing Fabric Properties in Naming Service
pub fn get_property_manager(&self) -> PropertyManagementClient {
PropertyManagementClient {
_com: self.com_property_client.clone(),
}
}

// Get the client for quering SF info.
/// Get the client for quering Service Fabric information.
pub fn get_query_manager(&self) -> QueryClient {
QueryClient::from_com(self.com_query_client.clone())
}

// Get the client for managing service info and lifecycles.
/// Get the client for managing service information and lifecycles.
pub fn get_service_manager(&self) -> ServiceManagementClient {
ServiceManagementClient::from_com(self.com_service_client.clone())
}

/// Get the client for get/set Service Fabric health properties.
pub fn get_health_manager(&self) -> HealthClient {
HealthClient::from_com(self.com_health_client.clone())
}
}

pub struct PropertyManagementClient {
Expand Down
138 changes: 138 additions & 0 deletions crates/libs/core/src/types/client/health.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

use mssf_com::FabricTypes::{
FABRIC_HEALTH_REPORT, FABRIC_HEALTH_REPORT_KIND_APPLICATION, FABRIC_HEALTH_REPORT_KIND_CLUSTER,
FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION,
FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE, FABRIC_HEALTH_REPORT_KIND_INVALID,
FABRIC_HEALTH_REPORT_KIND_NODE, FABRIC_HEALTH_REPORT_KIND_PARTITION,
FABRIC_HEALTH_REPORT_KIND_SERVICE, FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA,
FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE,
};

/// Wrapper of FABRIC_HEALTH_REPORT
pub enum HealthReport {
Invalid,
StatefulServiceReplica(StatefulServiceReplicaHealthReport),
StatelessServiceInstance(StatelessServiceInstanceHealthReport),
Partition(PartitionHealthReport),
Node(NodeHealthReport),
Service(ServiceHealthReport),
Application(ApplicationHealthReport),
DeployedApplication(DeployedApplicationHealthReport),
DeployedServicePackage(DeployedServicePackageHealthReport),
Cluster(ClusterHealthReport),
}

// TODO: Implement the conversion functions for the HealthReport enum properly.
OscarTHZhang marked this conversation as resolved.
Show resolved Hide resolved
impl From<&FABRIC_HEALTH_REPORT> for HealthReport {
fn from(value: &FABRIC_HEALTH_REPORT) -> Self {
match value.Kind {
FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA => {
HealthReport::StatefulServiceReplica(StatefulServiceReplicaHealthReport)
}
FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE => {
HealthReport::StatelessServiceInstance(StatelessServiceInstanceHealthReport)
}
FABRIC_HEALTH_REPORT_KIND_PARTITION => HealthReport::Partition(PartitionHealthReport),
FABRIC_HEALTH_REPORT_KIND_NODE => HealthReport::Node(NodeHealthReport),
FABRIC_HEALTH_REPORT_KIND_SERVICE => HealthReport::Service(ServiceHealthReport),
FABRIC_HEALTH_REPORT_KIND_APPLICATION => {
HealthReport::Application(ApplicationHealthReport)
}
FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION => {
HealthReport::DeployedApplication(DeployedApplicationHealthReport)
}
FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE => {
HealthReport::DeployedServicePackage(DeployedServicePackageHealthReport)
}
FABRIC_HEALTH_REPORT_KIND_CLUSTER => HealthReport::Cluster(ClusterHealthReport),
_ => HealthReport::Invalid,
}
}
}

impl From<&HealthReport> for FABRIC_HEALTH_REPORT {
fn from(value: &HealthReport) -> Self {
match value {
OscarTHZhang marked this conversation as resolved.
Show resolved Hide resolved
HealthReport::StatefulServiceReplica(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_STATEFUL_SERVICE_REPLICA,
Value: v as *const StatefulServiceReplicaHealthReport as *mut std::ffi::c_void,
},
HealthReport::StatelessServiceInstance(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_STATELESS_SERVICE_INSTANCE,
Value: v as *const StatelessServiceInstanceHealthReport as *mut std::ffi::c_void,
},
HealthReport::Partition(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_PARTITION,
Value: v as *const PartitionHealthReport as *mut std::ffi::c_void,
},
HealthReport::Node(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_NODE,
Value: v as *const NodeHealthReport as *mut std::ffi::c_void,
},
HealthReport::Service(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_SERVICE,
Value: v as *const ServiceHealthReport as *mut std::ffi::c_void,
},
HealthReport::Application(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_APPLICATION,
Value: v as *const ApplicationHealthReport as *mut std::ffi::c_void,
},
HealthReport::DeployedApplication(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_DEPLOYED_APPLICATION,
Value: v as *const DeployedApplicationHealthReport as *mut std::ffi::c_void,
},
HealthReport::DeployedServicePackage(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_DEPLOYED_SERVICE_PACKAGE,
Value: v as *const DeployedServicePackageHealthReport as *mut std::ffi::c_void,
},
HealthReport::Cluster(v) => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_CLUSTER,
Value: v as *const ClusterHealthReport as *mut std::ffi::c_void,
},
HealthReport::Invalid => Self {
Kind: FABRIC_HEALTH_REPORT_KIND_INVALID,
Value: std::ptr::null_mut(),
},
}
}
}

/// Wrapper of FABRIC_STATEFUL_SERVICE_REPLICA_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct StatefulServiceReplicaHealthReport;

/// Wrapper of FABRIC_STATELESS_SERVICE_INSTANCE_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct StatelessServiceInstanceHealthReport;

/// Wrapper of FABRIC_PARTITION_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct PartitionHealthReport;

/// Wrapper of FABRIC_NODE_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct NodeHealthReport;

/// Wrapper of FABRIC_SERVICE_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct ServiceHealthReport;

/// Wrapper of FABRIC_APPLICATION_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct ApplicationHealthReport;

/// Wrapper of FABRIC_DEPLOYED_APPLICATION_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct DeployedApplicationHealthReport;

/// Wrapper of FABRIC_DEPLOYED_SERVICE_PACKAGE_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct DeployedServicePackageHealthReport;

/// Wrapper of FABRIC_CLUSTER_HEALTH_REPORT
/// TODO: Implement this struct.
pub struct ClusterHealthReport;
2 changes: 2 additions & 0 deletions crates/libs/core/src/types/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use crate::WString;
pub use replica::*;
mod metrics;
pub use metrics::*;
mod health;
pub use health::*;

// FABRIC_SERVICE_NOTIFICATION_FILTER_FLAGS
bitflags::bitflags! {
Expand Down
Loading