Skip to main content

regent_sdk/state/attribute/utilities/
debug.rs

1//! Debug message attribute
2//!
3//! This module provides the `DebugExpectedState` type for outputting debug messages
4//! during compliance assessment. Useful for troubleshooting and logging.
5//!
6//! **Compatible OS:** All (cross-platform)
7//!
8//! # Examples
9//!
10//! ## Rust API
11//!
12//! ```no_run
13//! use regent_sdk::state::attribute::utilities::debug::DebugExpectedState;
14//! use regent_sdk::{Attribute, ExpectedState, Privilege};
15//!
16//! // Output a debug message
17//! let debug_msg = DebugExpectedState::builder("Checking system configuration")
18//!     .build()
19//!     .unwrap();
20//!
21//! let expected_state = ExpectedState::new()
22//!     .with_attribute(Attribute::debug(debug_msg, Privilege::None, None))
23//!     .build();
24//! ```
25//!
26//! ## YAML API
27//!
28//! ```yaml
29//! Attributes:
30//!   - Name: Debug message to print
31//!     Privilege: !None
32//!     Detail: !Debug
33//!       Msg: "Checking system configuration"
34//! ```
35
36use crate::error::RegentError;
37use crate::hosts::managed_host::InternalApiCallOutcome;
38use crate::hosts::managed_host::{AssessCompliance, ReachCompliance, Timeout};
39use crate::hosts::properties::HostProperties;
40use crate::secrets::SecretProvidersPool;
41use crate::state::Check;
42use crate::state::attribute::HostHandler;
43use crate::state::attribute::Privilege;
44
45use crate::state::compliance::AttributeComplianceAssessment;
46use serde::{Deserialize, Serialize};
47use std::time::Duration;
48
49/// Configuration for a debug message
50#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
51#[serde(deny_unknown_fields)]
52#[serde(rename_all = "PascalCase")]
53pub struct DebugExpectedState {
54    /// Debug message to output during compliance assessment
55    msg: String,
56}
57
58impl Timeout for DebugExpectedState {
59    fn default_timeout(&self) -> Duration {
60        Duration::from_secs(1)
61    }
62}
63
64impl Check for DebugExpectedState {
65    fn check(&self) -> Result<(), RegentError> {
66        Ok(())
67    }
68
69    fn check_host_compatibility(
70        &self,
71        _host_properties: &HostProperties,
72    ) -> Result<(), RegentError> {
73        // Debug messages are cross-platform compatible
74        Ok(())
75    }
76}
77
78impl<Handler: HostHandler> AssessCompliance<Handler> for DebugExpectedState {
79    async fn assess_compliance(
80        &self,
81        _host_handler: &mut Handler,
82        host_properties: &Option<HostProperties>,
83        _privilege: &Privilege,
84        _optional_secret_provider: &Option<SecretProvidersPool>,
85    ) -> Result<AttributeComplianceAssessment, RegentError> {
86        if let Some(props) = host_properties {
87            self.check_host_compatibility(props)?;
88        }
89        // Debug is a no-op that doesn't affect compliance state
90        return Ok(AttributeComplianceAssessment::Compliant);
91    }
92}
93
94#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub struct DebugApiCall {}
96
97impl DebugApiCall {
98    pub fn display(&self) -> String {
99        "Debug module".into()
100    }
101}
102
103impl Timeout for DebugApiCall {
104    fn default_timeout(&self) -> Duration {
105        Duration::from_secs(1)
106    }
107}
108
109impl Check for DebugApiCall {
110    fn check(&self) -> Result<(), RegentError> {
111        Ok(())
112    }
113
114    fn check_host_compatibility(
115        &self,
116        _host_properties: &HostProperties,
117    ) -> Result<(), RegentError> {
118        // Debug messages are cross-platform compatible
119        Ok(())
120    }
121}
122
123impl<Handler: HostHandler> ReachCompliance<Handler> for DebugApiCall {
124    async fn call(
125        &self,
126        _host_handler: &mut Handler,
127        host_properties: &Option<HostProperties>,
128        _optional_secret_provider: &Option<SecretProvidersPool>,
129    ) -> Result<InternalApiCallOutcome, RegentError> {
130        if let Some(props) = host_properties {
131            self.check_host_compatibility(props)?;
132        }
133
134        Ok(InternalApiCallOutcome::Success(None))
135    }
136}
137
138#[cfg(test)]
139mod tests {
140
141    use super::*;
142
143    #[test]
144    fn parsing_debug_module_block_from_yaml_str() {
145        let attribute = "---
146Msg: some content
147    ";
148
149        let attribute: DebugExpectedState = yaml_serde::from_str(attribute).unwrap();
150
151        assert_eq!(attribute.msg, "some content".to_string());
152    }
153}