Skip to content

Commit

Permalink
Impl FabricErrorCode (#82)
Browse files Browse the repository at this point in the history
When SF returns an error code from COM api, it is hard to debug what the
error is because it is only an int code.
This PR adds all FabricErrorCode in mssf-core and can convert from int
and support debug and fmt prints.
For example:
```rs
        let fe = FabricError::from(FABRIC_E_CODE_PACKAGE_NOT_FOUND);
        // check debug string
        assert_eq!(
            format!("{:?}", fe),
            "FabricError { code: -2147017733, message: FABRIC_E_CODE_PACKAGE_NOT_FOUND }"
        );
```
  • Loading branch information
youyuanwu authored Oct 19, 2024
1 parent 4a4dd11 commit cef09b3
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 54 deletions.
2 changes: 1 addition & 1 deletion crates/libs/core/src/client/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async fn test_fabric_client() {
let list = qc.get_node_list(&desc, timeout, Some(token.clone()));
token.cancel();
let err = list.await.expect_err("request should be cancelled");
assert_eq!(err, FabricErrorCode::OperationCanceled.into());
assert_eq!(err, FabricErrorCode::E_ABORT.into());
}

let smgr = c.get_service_manager();
Expand Down
335 changes: 335 additions & 0 deletions crates/libs/core/src/error/errorcode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
// ------------------------------------------------------------
// 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_ERROR_CODE;
use windows_core::HRESULT;

use super::FabricError;

// Common HRESULT codes that SF reuses from windows.
const S_OK: FABRIC_ERROR_CODE = FABRIC_ERROR_CODE(windows::Win32::Foundation::S_OK.0);
const E_ABORT: FABRIC_ERROR_CODE = FABRIC_ERROR_CODE(windows::Win32::Foundation::E_ABORT.0);
const E_ACCESSDENIED: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(windows::Win32::Foundation::E_ACCESSDENIED.0);
const E_FAIL: FABRIC_ERROR_CODE = FABRIC_ERROR_CODE(windows::Win32::Foundation::E_FAIL.0);
const E_HANDLE: FABRIC_ERROR_CODE = FABRIC_ERROR_CODE(windows::Win32::Foundation::E_HANDLE.0);
const E_INVALIDARG: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(windows::Win32::Foundation::E_INVALIDARG.0);
const E_NOINTERFACE: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(windows::Win32::Foundation::E_NOINTERFACE.0);
const E_NOTIMPL: FABRIC_ERROR_CODE = FABRIC_ERROR_CODE(windows::Win32::Foundation::E_NOTIMPL.0);
const E_OUTOFMEMORY: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(windows::Win32::Foundation::E_OUTOFMEMORY.0);
const E_POINTER: FABRIC_ERROR_CODE = FABRIC_ERROR_CODE(windows::Win32::Foundation::E_POINTER.0);
const E_UNEXPECTED: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(windows::Win32::Foundation::E_UNEXPECTED.0);

// HRESULT codes from win32 errors that SF resuses.
const E_FILE_EXISTS: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(HRESULT::from_win32(windows::Win32::Foundation::ERROR_FILE_EXISTS.0).0);
const E_DIR_NOT_EMPTY: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(HRESULT::from_win32(windows::Win32::Foundation::ERROR_DIR_NOT_EMPTY.0).0);
const E_NOT_FOUND: FABRIC_ERROR_CODE =
FABRIC_ERROR_CODE(HRESULT::from_win32(windows::Win32::Foundation::ERROR_NOT_FOUND.0).0);

/// Hepler macro to define fabric error code.
/// SF uses win32 hresult code together with the custom fabric error code.
/// This enum helps passing errors between Rust and SF API, and is easy to debug.
/// code1 list are windows errors, lit is a dummy string literal, code list are fabric errors.
/// The macro defines windows errors first, then followed by fabric errors.
// Need to match cs impl:
// https://github.com/microsoft/service-fabric/blob/19791eb97c8d876517daa030e5a403f4bcad25b1/src/prod/src/managed/Api/src/System/Fabric/Interop/NativeTypes.cs#L57
macro_rules! define_fabric_error_code{
($( $code1:ident ),* ,($lit:literal), $( $code:ident ),*) =>{
#[allow(non_camel_case_types)]
#[derive(Debug, Clone)]
#[repr(i32)]
pub enum FabricErrorCode {
// Define windows error codes for SF
$(
$code1 = $code1 .0,
)*

// defines SF error codes.
$(
$code = mssf_com::ServiceFabric::FabricTypes::$code .0,
)*
}

impl TryFrom<FABRIC_ERROR_CODE> for FabricErrorCode {
type Error = &'static str;

fn try_from(value: FABRIC_ERROR_CODE) -> Result<Self, Self::Error> {
match value {
$(
$code1 => Ok(Self::$code1),
)*
// SF code converts.
$(
mssf_com::ServiceFabric::FabricTypes::$code => Ok(Self::$code),
)*
_ => Err("Unknown FABRIC_ERROR_CODE")
}
}
}
}
}

impl From<FabricErrorCode> for FabricError {
fn from(value: FabricErrorCode) -> Self {
FabricError(HRESULT(value as i32))
}
}

// other conversions goes through FabricError
impl From<FabricErrorCode> for HRESULT {
fn from(value: FabricErrorCode) -> Self {
FabricError::from(value).into()
}
}

impl From<FabricErrorCode> for crate::Error {
fn from(value: FabricErrorCode) -> Self {
FabricError::from(value).into()
}
}

impl core::fmt::Display for FabricErrorCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
core::write!(f, "{:?}", self) // use the debug string
}
}

// This defines all the fabric error codes.
// list copied from https://github.com/microsoft/service-fabric/blob/19791eb97c8d876517daa030e5a403f4bcad25b1/src/prod/src/idl/public/FabricTypes.idl#L60C18-L60C35
define_fabric_error_code!(
S_OK,
E_ABORT,
E_ACCESSDENIED,
E_FAIL,
E_HANDLE,
E_INVALIDARG,
E_NOINTERFACE,
E_NOTIMPL,
E_OUTOFMEMORY,
E_POINTER,
E_UNEXPECTED,
E_FILE_EXISTS,
E_DIR_NOT_EMPTY,
E_NOT_FOUND,
("Literal for breaking up first error chunk and the fabric errors"),
FABRIC_E_COMMUNICATION_ERROR,
FABRIC_E_INVALID_ADDRESS,
FABRIC_E_INVALID_NAME_URI,
FABRIC_E_INVALID_PARTITION_KEY,
FABRIC_E_NAME_ALREADY_EXISTS,
FABRIC_E_NAME_DOES_NOT_EXIST,
FABRIC_E_NAME_NOT_EMPTY,
FABRIC_E_NODE_NOT_FOUND,
FABRIC_E_NODE_IS_UP,
FABRIC_E_NO_WRITE_QUORUM,
FABRIC_E_NOT_PRIMARY,
FABRIC_E_NOT_READY,
FABRIC_E_OPERATION_NOT_COMPLETE,
FABRIC_E_PROPERTY_DOES_NOT_EXIST,
FABRIC_E_RECONFIGURATION_PENDING,
FABRIC_E_REPLICATION_QUEUE_FULL,
FABRIC_E_SERVICE_ALREADY_EXISTS,
FABRIC_E_SERVICE_DOES_NOT_EXIST,
FABRIC_E_SERVICE_OFFLINE,
FABRIC_E_SERVICE_METADATA_MISMATCH,
FABRIC_E_SERVICE_AFFINITY_CHAIN_NOT_SUPPORTED,
FABRIC_E_SERVICE_TYPE_ALREADY_REGISTERED,
FABRIC_E_SERVICE_TYPE_NOT_REGISTERED,
FABRIC_E_VALUE_TOO_LARGE,
FABRIC_E_VALUE_EMPTY,
FABRIC_E_PROPERTY_CHECK_FAILED,
FABRIC_E_WRITE_CONFLICT,
FABRIC_E_ENUMERATION_COMPLETED,
FABRIC_E_APPLICATION_TYPE_PROVISION_IN_PROGRESS,
FABRIC_E_APPLICATION_TYPE_ALREADY_EXISTS,
FABRIC_E_APPLICATION_TYPE_NOT_FOUND,
FABRIC_E_APPLICATION_TYPE_IN_USE,
FABRIC_E_APPLICATION_ALREADY_EXISTS,
FABRIC_E_APPLICATION_NOT_FOUND,
FABRIC_E_APPLICATION_UPGRADE_IN_PROGRESS,
FABRIC_E_APPLICATION_UPGRADE_VALIDATION_ERROR,
FABRIC_E_SERVICE_TYPE_NOT_FOUND,
FABRIC_E_SERVICE_TYPE_MISMATCH,
FABRIC_E_SERVICE_TYPE_TEMPLATE_NOT_FOUND,
FABRIC_E_CONFIGURATION_SECTION_NOT_FOUND,
FABRIC_E_CONFIGURATION_PARAMETER_NOT_FOUND,
FABRIC_E_INVALID_CONFIGURATION,
FABRIC_E_IMAGEBUILDER_VALIDATION_ERROR,
FABRIC_E_PARTITION_NOT_FOUND,
FABRIC_E_REPLICA_DOES_NOT_EXIST,
FABRIC_E_SERVICE_GROUP_ALREADY_EXISTS,
FABRIC_E_SERVICE_GROUP_DOES_NOT_EXIST,
FABRIC_E_PROCESS_DEACTIVATED,
FABRIC_E_PROCESS_ABORTED,
FABRIC_E_UPGRADE_FAILED,
FABRIC_E_INVALID_CREDENTIAL_TYPE,
FABRIC_E_INVALID_X509_FIND_TYPE,
FABRIC_E_INVALID_X509_STORE_LOCATION,
FABRIC_E_INVALID_X509_STORE_NAME,
FABRIC_E_INVALID_X509_THUMBPRINT,
FABRIC_E_INVALID_PROTECTION_LEVEL,
FABRIC_E_INVALID_X509_STORE,
FABRIC_E_INVALID_SUBJECT_NAME,
FABRIC_E_INVALID_ALLOWED_COMMON_NAME_LIST,
FABRIC_E_INVALID_CREDENTIALS,
FABRIC_E_DECRYPTION_FAILED,
FABRIC_E_CONFIGURATION_PACKAGE_NOT_FOUND,
FABRIC_E_DATA_PACKAGE_NOT_FOUND,
FABRIC_E_CODE_PACKAGE_NOT_FOUND,
FABRIC_E_SERVICE_ENDPOINT_RESOURCE_NOT_FOUND,
FABRIC_E_INVALID_OPERATION,
FABRIC_E_OBJECT_CLOSED,
FABRIC_E_TIMEOUT,
FABRIC_E_FILE_NOT_FOUND,
FABRIC_E_DIRECTORY_NOT_FOUND,
FABRIC_E_INVALID_DIRECTORY,
FABRIC_E_PATH_TOO_LONG,
FABRIC_E_IMAGESTORE_IOERROR,
FABRIC_E_CORRUPTED_IMAGE_STORE_OBJECT_FOUND,
FABRIC_E_APPLICATION_NOT_UPGRADING,
FABRIC_E_APPLICATION_ALREADY_IN_TARGET_VERSION,
FABRIC_E_IMAGEBUILDER_UNEXPECTED_ERROR,
FABRIC_E_FABRIC_VERSION_NOT_FOUND,
FABRIC_E_FABRIC_VERSION_IN_USE,
FABRIC_E_FABRIC_VERSION_ALREADY_EXISTS,
FABRIC_E_FABRIC_ALREADY_IN_TARGET_VERSION,
FABRIC_E_FABRIC_NOT_UPGRADING,
FABRIC_E_FABRIC_UPGRADE_IN_PROGRESS,
FABRIC_E_FABRIC_UPGRADE_VALIDATION_ERROR,
FABRIC_E_HEALTH_MAX_REPORTS_REACHED,
FABRIC_E_HEALTH_STALE_REPORT,
FABRIC_E_KEY_TOO_LARGE,
FABRIC_E_KEY_NOT_FOUND,
FABRIC_E_SEQUENCE_NUMBER_CHECK_FAILED,
FABRIC_E_ENCRYPTION_FAILED,
FABRIC_E_INVALID_ATOMIC_GROUP,
FABRIC_E_HEALTH_ENTITY_NOT_FOUND,
FABRIC_E_SERVICE_MANIFEST_NOT_FOUND,
FABRIC_E_RELIABLE_SESSION_TRANSPORT_STARTUP_FAILURE,
FABRIC_E_RELIABLE_SESSION_ALREADY_EXISTS,
FABRIC_E_RELIABLE_SESSION_CANNOT_CONNECT,
FABRIC_E_RELIABLE_SESSION_MANAGER_EXISTS,
FABRIC_E_RELIABLE_SESSION_REJECTED,
FABRIC_E_RELIABLE_SESSION_MANAGER_ALREADY_LISTENING,
FABRIC_E_RELIABLE_SESSION_MANAGER_NOT_FOUND,
FABRIC_E_RELIABLE_SESSION_MANAGER_NOT_LISTENING,
FABRIC_E_INVALID_SERVICE_TYPE,
FABRIC_E_IMAGEBUILDER_TIMEOUT,
FABRIC_E_IMAGEBUILDER_ACCESS_DENIED,
FABRIC_E_IMAGEBUILDER_INVALID_MSI_FILE,
FABRIC_E_SERVICE_TOO_BUSY,
FABRIC_E_TRANSACTION_NOT_ACTIVE,
FABRIC_E_REPAIR_TASK_ALREADY_EXISTS,
FABRIC_E_REPAIR_TASK_NOT_FOUND,
FABRIC_E_RELIABLE_SESSION_NOT_FOUND,
FABRIC_E_RELIABLE_SESSION_QUEUE_EMPTY,
FABRIC_E_RELIABLE_SESSION_QUOTA_EXCEEDED,
FABRIC_E_RELIABLE_SESSION_SERVICE_FAULTED,
FABRIC_E_RELIABLE_SESSION_INVALID_TARGET_PARTITION,
FABRIC_E_TRANSACTION_TOO_LARGE,
FABRIC_E_REPLICATION_OPERATION_TOO_LARGE,
FABRIC_E_INSTANCE_ID_MISMATCH,
FABRIC_E_UPGRADE_DOMAIN_ALREADY_COMPLETED,
FABRIC_E_NODE_HAS_NOT_STOPPED_YET,
FABRIC_E_INSUFFICIENT_CLUSTER_CAPACITY,
FABRIC_E_INVALID_PACKAGE_SHARING_POLICY,
FABRIC_E_PREDEPLOYMENT_NOT_ALLOWED,
FABRIC_E_INVALID_BACKUP_SETTING,
FABRIC_E_MISSING_FULL_BACKUP,
FABRIC_E_BACKUP_IN_PROGRESS,
FABRIC_E_DUPLICATE_SERVICE_NOTIFICATION_FILTER_NAME,
FABRIC_E_INVALID_REPLICA_OPERATION,
FABRIC_E_INVALID_REPLICA_STATE,
FABRIC_E_LOADBALANCER_NOT_READY,
FABRIC_E_INVALID_PARTITION_OPERATION,
FABRIC_E_PRIMARY_ALREADY_EXISTS,
FABRIC_E_SECONDARY_ALREADY_EXISTS,
FABRIC_E_BACKUP_DIRECTORY_NOT_EMPTY,
FABRIC_E_FORCE_NOT_SUPPORTED_FOR_REPLICA_OPERATION,
FABRIC_E_ACQUIRE_FILE_LOCK_FAILED,
FABRIC_E_CONNECTION_DENIED,
FABRIC_E_SERVER_AUTHENTICATION_FAILED,
FABRIC_E_CONSTRAINT_KEY_UNDEFINED,
FABRIC_E_MULTITHREADED_TRANSACTIONS_NOT_ALLOWED,
FABRIC_E_INVALID_X509_NAME_LIST,
FABRIC_E_VERBOSE_FM_PLACEMENT_HEALTH_REPORTING_REQUIRED,
FABRIC_E_GATEWAY_NOT_REACHABLE,
FABRIC_E_USER_ROLE_CLIENT_CERTIFICATE_NOT_CONFIGURED,
FABRIC_E_TRANSACTION_ABORTED,
FABRIC_E_CANNOT_CONNECT,
FABRIC_E_MESSAGE_TOO_LARGE,
FABRIC_E_CONSTRAINT_NOT_SATISFIED,
FABRIC_E_ENDPOINT_NOT_FOUND,
FABRIC_E_APPLICATION_UPDATE_IN_PROGRESS,
FABRIC_E_DELETE_BACKUP_FILE_FAILED,
FABRIC_E_CONNECTION_CLOSED_BY_REMOTE_END,
FABRIC_E_INVALID_TEST_COMMAND_STATE,
FABRIC_E_TEST_COMMAND_OPERATION_ID_ALREADY_EXISTS,
FABRIC_E_CM_OPERATION_FAILED,
FABRIC_E_IMAGEBUILDER_RESERVED_DIRECTORY_ERROR,
FABRIC_E_CERTIFICATE_NOT_FOUND,
FABRIC_E_CHAOS_ALREADY_RUNNING,
FABRIC_E_FABRIC_DATA_ROOT_NOT_FOUND,
FABRIC_E_INVALID_RESTORE_DATA,
FABRIC_E_DUPLICATE_BACKUPS,
FABRIC_E_INVALID_BACKUP_CHAIN,
FABRIC_E_STOP_IN_PROGRESS,
FABRIC_E_ALREADY_STOPPED,
FABRIC_E_NODE_IS_DOWN,
FABRIC_E_NODE_TRANSITION_IN_PROGRESS,
FABRIC_E_INVALID_BACKUP,
FABRIC_E_INVALID_INSTANCE_ID,
FABRIC_E_INVALID_DURATION,
FABRIC_E_RESTORE_SAFE_CHECK_FAILED,
FABRIC_E_CONFIG_UPGRADE_FAILED,
FABRIC_E_UPLOAD_SESSION_RANGE_NOT_SATISFIABLE,
FABRIC_E_UPLOAD_SESSION_ID_CONFLICT,
FABRIC_E_INVALID_PARTITION_SELECTOR,
FABRIC_E_INVALID_REPLICA_SELECTOR,
FABRIC_E_DNS_SERVICE_NOT_FOUND,
FABRIC_E_INVALID_DNS_NAME,
FABRIC_E_DNS_NAME_IN_USE,
FABRIC_E_COMPOSE_DEPLOYMENT_ALREADY_EXISTS,
FABRIC_E_COMPOSE_DEPLOYMENT_NOT_FOUND,
FABRIC_E_INVALID_FOR_STATEFUL_SERVICES,
FABRIC_E_INVALID_FOR_STATELESS_SERVICES,
FABRIC_E_ONLY_VALID_FOR_STATEFUL_PERSISTENT_SERVICES,
FABRIC_E_INVALID_UPLOAD_SESSION_ID,
FABRIC_E_BACKUP_NOT_ENABLED,
FABRIC_E_BACKUP_IS_ENABLED,
FABRIC_E_BACKUP_POLICY_DOES_NOT_EXIST,
FABRIC_E_BACKUP_POLICY_ALREADY_EXISTS,
FABRIC_E_RESTORE_IN_PROGRESS,
FABRIC_E_RESTORE_SOURCE_TARGET_PARTITION_MISMATCH,
FABRIC_E_FAULT_ANALYSIS_SERVICE_NOT_ENABLED,
FABRIC_E_CONTAINER_NOT_FOUND,
FABRIC_E_OBJECT_DISPOSED,
FABRIC_E_NOT_READABLE,
FABRIC_E_BACKUPCOPIER_UNEXPECTED_ERROR,
FABRIC_E_BACKUPCOPIER_TIMEOUT,
FABRIC_E_BACKUPCOPIER_ACCESS_DENIED,
FABRIC_E_INVALID_SERVICE_SCALING_POLICY,
FABRIC_E_SINGLE_INSTANCE_APPLICATION_ALREADY_EXISTS,
FABRIC_E_SINGLE_INSTANCE_APPLICATION_NOT_FOUND,
FABRIC_E_VOLUME_ALREADY_EXISTS,
FABRIC_E_VOLUME_NOT_FOUND,
FABRIC_E_DATABASE_MIGRATION_IN_PROGRESS,
FABRIC_E_CENTRAL_SECRET_SERVICE_GENERIC,
FABRIC_E_SECRET_INVALID,
FABRIC_E_SECRET_VERSION_ALREADY_EXISTS,
FABRIC_E_SINGLE_INSTANCE_APPLICATION_UPGRADE_IN_PROGRESS,
FABRIC_E_OPERATION_NOT_SUPPORTED,
FABRIC_E_COMPOSE_DEPLOYMENT_NOT_UPGRADING,
FABRIC_E_SECRET_TYPE_CANNOT_BE_CHANGED,
FABRIC_E_NETWORK_NOT_FOUND,
FABRIC_E_NETWORK_IN_USE,
FABRIC_E_ENDPOINT_NOT_REFERENCED
);
Loading

0 comments on commit cef09b3

Please sign in to comment.