@@ -24,7 +24,7 @@ use security_context_lib::{SecurityContext, get_security_context};
2424use serde_json::{Map, Value};
2525use std::path::PathBuf;
2626use std::collections::HashMap;
27- use tracing::{debug, info, trace};
27+ use tracing::{debug, info, trace, warn };
2828pub mod context;
2929pub mod config_doc;
3030pub mod config_result;
@@ -75,27 +75,35 @@ pub fn add_resource_export_results_to_configuration(resource: &DscResource, conf
7575 }
7676 r.kind = kind.as_str().map(std::string::ToString::to_string);
7777 }
78+ r.name = if let Some(name) = props.remove("_name") {
79+ name.as_str()
80+ .map(std::string::ToString::to_string)
81+ .ok_or_else(|| DscError::Parser(t!("configure.mod.propertyNotString", name = "_name", value = name).to_string()))?
82+ } else {
83+ format!("{}-{i}", r.resource_type)
84+ };
85+ let mut metadata = Metadata {
86+ microsoft: None,
87+ other: Map::new(),
88+ };
7889 if let Some(security_context) = props.remove("_securityContext") {
7990 let context: SecurityContextKind = serde_json::from_value(security_context)?;
80- let metadata = Metadata {
81- microsoft: Some(
91+ metadata.microsoft = Some(
8292 MicrosoftDscMetadata {
8393 security_context: Some(context),
8494 ..Default::default()
8595 }
86- ),
87- other: Map::new(),
88- };
89- r.metadata = Some(metadata);
96+ );
9097 }
91- r.name = if let Some(name) = props.remove("_name") {
92- name.as_str()
93- .map(std::string::ToString::to_string)
94- .ok_or_else(|| DscError::Parser(t!("configure.mod.propertyNotString", name = "_name", value = name).to_string()))?
98+ r.properties = escape_property_values(&props)?;
99+ let mut properties = serde_json::to_value(&r.properties)?;
100+ get_metadata_from_result(&mut properties, &mut metadata)?;
101+ r.properties = Some(properties.as_object().cloned().unwrap_or_default());
102+ r.metadata = if metadata.microsoft.is_some() || !metadata.other.is_empty() {
103+ Some(metadata)
95104 } else {
96- format!("{}-{i}", r.resource_type)
105+ None
97106 };
98- r.properties = escape_property_values(&props)?;
99107
100108 conf.resources.push(r);
101109 }
@@ -217,6 +225,26 @@ fn check_security_context(metadata: Option<&Metadata>) -> Result<(), DscError> {
217225 Ok(())
218226}
219227
228+ fn get_metadata_from_result(result: &mut Value, metadata: &mut Metadata) -> Result<(), DscError> {
229+ if let Some(metadata_value) = result.get("_metadata") {
230+ if let Some(metadata_map) = metadata_value.as_object() {
231+ for (key, value) in metadata_map {
232+ if key.starts_with("Microsoft.DSC") {
233+ warn!("{}", t!("configure.mod.metadataMicrosoftDscIgnored", key = key));
234+ continue;
235+ }
236+ metadata.other.insert(key.clone(), value.clone());
237+ }
238+ } else {
239+ return Err(DscError::Parser(t!("configure.mod.metadataNotObject", value = metadata_value).to_string()));
240+ }
241+ if let Some(value_map) = result.as_object_mut() {
242+ value_map.remove("_metadata");
243+ }
244+ }
245+ Ok(())
246+ }
247+
220248impl Configurator {
221249 /// Create a new `Configurator` instance.
222250 ///
@@ -288,7 +316,7 @@ impl Configurator {
288316 let filter = add_metadata(&dsc_resource.kind, properties)?;
289317 trace!("filter: {filter}");
290318 let start_datetime = chrono::Local::now();
291- let get_result = match dsc_resource.get(&filter) {
319+ let mut get_result = match dsc_resource.get(&filter) {
292320 Ok(result) => result,
293321 Err(e) => {
294322 progress.set_failure(get_failure_from_error(&e));
@@ -297,9 +325,17 @@ impl Configurator {
297325 },
298326 };
299327 let end_datetime = chrono::Local::now();
300- match &get_result {
301- GetResult::Resource(resource_result) => {
328+ let mut metadata = Metadata {
329+ microsoft: Some(
330+ MicrosoftDscMetadata::new_with_duration(&start_datetime, &end_datetime)
331+ ),
332+ other: Map::new(),
333+ };
334+
335+ match &mut get_result {
336+ GetResult::Resource(ref mut resource_result) => {
302337 self.context.references.insert(format!("{}:{}", resource.resource_type, resource.name), serde_json::to_value(&resource_result.actual_state)?);
338+ get_metadata_from_result(&mut resource_result.actual_state, &mut metadata)?;
303339 },
304340 GetResult::Group(group) => {
305341 let mut results = Vec::<Value>::new();
@@ -310,17 +346,7 @@ impl Configurator {
310346 },
311347 }
312348 let resource_result = config_result::ResourceGetResult {
313- metadata: Some(
314- Metadata {
315- microsoft: Some(
316- MicrosoftDscMetadata {
317- duration: Some(end_datetime.signed_duration_since(start_datetime).to_string()),
318- ..Default::default()
319- }
320- ),
321- other: Map::new(),
322- }
323- ),
349+ metadata: Some(metadata),
324350 name: resource.name.clone(),
325351 resource_type: resource.resource_type.clone(),
326352 result: get_result.clone(),
@@ -383,7 +409,7 @@ impl Configurator {
383409
384410 let start_datetime;
385411 let end_datetime;
386- let set_result;
412+ let mut set_result;
387413 if exist || dsc_resource.capabilities.contains(&Capability::SetHandlesExist) {
388414 debug!("{}", t!("configure.mod.handlesExist"));
389415 start_datetime = chrono::Local::now();
@@ -453,9 +479,16 @@ impl Configurator {
453479 return Err(DscError::NotImplemented(t!("configure.mod.deleteNotSupported", resource = resource.resource_type).to_string()));
454480 }
455481
456- match &set_result {
482+ let mut metadata = Metadata {
483+ microsoft: Some(
484+ MicrosoftDscMetadata::new_with_duration(&start_datetime, &end_datetime)
485+ ),
486+ other: Map::new(),
487+ };
488+ match &mut set_result {
457489 SetResult::Resource(resource_result) => {
458490 self.context.references.insert(format!("{}:{}", resource.resource_type, resource.name), serde_json::to_value(&resource_result.after_state)?);
491+ get_metadata_from_result(&mut resource_result.after_state, &mut metadata)?;
459492 },
460493 SetResult::Group(group) => {
461494 let mut results = Vec::<Value>::new();
@@ -466,17 +499,7 @@ impl Configurator {
466499 },
467500 }
468501 let resource_result = config_result::ResourceSetResult {
469- metadata: Some(
470- Metadata {
471- microsoft: Some(
472- MicrosoftDscMetadata {
473- duration: Some(end_datetime.signed_duration_since(start_datetime).to_string()),
474- ..Default::default()
475- }
476- ),
477- other: Map::new(),
478- }
479- ),
502+ metadata: Some(metadata),
480503 name: resource.name.clone(),
481504 resource_type: resource.resource_type.clone(),
482505 result: set_result.clone(),
@@ -517,7 +540,7 @@ impl Configurator {
517540 let expected = add_metadata(&dsc_resource.kind, properties)?;
518541 trace!("{}", t!("configure.mod.expectedState", state = expected));
519542 let start_datetime = chrono::Local::now();
520- let test_result = match dsc_resource.test(&expected) {
543+ let mut test_result = match dsc_resource.test(&expected) {
521544 Ok(result) => result,
522545 Err(e) => {
523546 progress.set_failure(get_failure_from_error(&e));
@@ -526,9 +549,16 @@ impl Configurator {
526549 },
527550 };
528551 let end_datetime = chrono::Local::now();
529- match &test_result {
552+ let mut metadata = Metadata {
553+ microsoft: Some(
554+ MicrosoftDscMetadata::new_with_duration(&start_datetime, &end_datetime)
555+ ),
556+ other: Map::new(),
557+ };
558+ match &mut test_result {
530559 TestResult::Resource(resource_test_result) => {
531560 self.context.references.insert(format!("{}:{}", resource.resource_type, resource.name), serde_json::to_value(&resource_test_result.actual_state)?);
561+ get_metadata_from_result(&mut resource_test_result.actual_state, &mut metadata)?;
532562 },
533563 TestResult::Group(group) => {
534564 let mut results = Vec::<Value>::new();
@@ -539,17 +569,7 @@ impl Configurator {
539569 },
540570 }
541571 let resource_result = config_result::ResourceTestResult {
542- metadata: Some(
543- Metadata {
544- microsoft: Some(
545- MicrosoftDscMetadata {
546- duration: Some(end_datetime.signed_duration_since(start_datetime).to_string()),
547- ..Default::default()
548- }
549- ),
550- other: Map::new(),
551- }
552- ),
572+ metadata: Some(metadata),
553573 name: resource.name.clone(),
554574 resource_type: resource.resource_type.clone(),
555575 result: test_result.clone(),
0 commit comments