From 9eddd7fa8488463f895b4f3f338ea80bbebb4e3c Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 1 Dec 2023 13:21:40 -0800 Subject: [PATCH 1/6] Added resource tracing info --- dsc/tests/dsc_args.tests.ps1 | 7 +++++ dsc_lib/src/discovery/command_discovery.rs | 2 ++ dsc_lib/src/dscresources/command_resource.rs | 29 +++++++++++++++++++- powershellgroup/powershellgroup.resource.ps1 | 18 +++++++++--- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/dsc/tests/dsc_args.tests.ps1 b/dsc/tests/dsc_args.tests.ps1 index 339191d42..d0aa7e770 100644 --- a/dsc/tests/dsc_args.tests.ps1 +++ b/dsc/tests/dsc_args.tests.ps1 @@ -152,4 +152,11 @@ resources: "$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'DEBUG' $LASTEXITCODE | Should -Be 0 } + + It 'resource tracing shows up' { + # Assumption here is that DSC/PowerShellGroup provider is visible + dsc -l trace resource list 2> $TestDrive/tracing.txt + "$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'PSModulePath' + $LASTEXITCODE | Should -Be 0 + } } diff --git a/dsc_lib/src/discovery/command_discovery.rs b/dsc_lib/src/discovery/command_discovery.rs index a7a939c0f..6c9f66ecf 100644 --- a/dsc_lib/src/discovery/command_discovery.rs +++ b/dsc_lib/src/discovery/command_discovery.rs @@ -5,6 +5,7 @@ use crate::discovery::discovery_trait::ResourceDiscovery; use crate::dscresources::dscresource::{DscResource, ImplementedAs}; use crate::dscresources::resource_manifest::{ResourceManifest, import_manifest}; use crate::dscresources::command_resource::invoke_command; +use crate::dscresources::command_resource::print_resource_traces; use crate::dscerror::DscError; use std::collections::BTreeMap; use std::env; @@ -122,6 +123,7 @@ impl CommandDiscovery { continue; }, }; + print_resource_traces(&stderr); if exit_code != 0 { /* In case of "resource list" operation - print failure from provider as warning diff --git a/dsc_lib/src/dscresources/command_resource.rs b/dsc_lib/src/dscresources/command_resource.rs index 2c530dd1a..f0c82c8d4 100644 --- a/dsc_lib/src/dscresources/command_resource.rs +++ b/dsc_lib/src/dscresources/command_resource.rs @@ -6,10 +6,30 @@ use serde_json::Value; use std::{collections::HashMap, process::Command, io::{Write, Read}, process::Stdio}; use crate::dscerror::DscError; use super::{dscresource::get_diff,resource_manifest::{ResourceManifest, InputKind, ReturnKind, SchemaKind}, invoke_result::{GetResult, SetResult, TestResult, ValidateResult, ExportResult}}; -use tracing::{debug, info}; +use tracing::{debug, info, trace}; pub const EXIT_PROCESS_TERMINATED: i32 = 0x102; + +pub fn print_resource_traces(stderr: &String) +{ + if !stderr.is_empty() + { + for trace_line in stderr.lines() { + match serde_json::from_str::(trace_line){ + Result::Ok(json_obj) => { + let trace = json_obj.get("Trace"); + if trace.is_some() + { + trace!("{}", trace.unwrap().as_str().unwrap_or_default()); + } + }, + Result::Err(_) => {} + }; + } + } +} + /// Invoke the get operation on a resource /// /// # Arguments @@ -49,6 +69,7 @@ pub fn invoke_get(resource: &ResourceManifest, cwd: &str, filter: &str) -> Resul info!("Invoking get {} using {}", &resource.resource_type, &resource.get.executable); let (exit_code, stdout, stderr) = invoke_command(&resource.get.executable, get_args, input_filter, Some(cwd), env)?; + print_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -131,6 +152,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_te info!("Getting current state for set by invoking get {} using {}", &resource.resource_type, &resource.get.executable); let (exit_code, stdout, stderr) = invoke_command(&resource.get.executable, get_args, get_input, Some(cwd), get_env)?; + print_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -144,6 +166,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_te info!("Invoking set {} using {}", &resource.resource_type, &set.executable); let (exit_code, stdout, stderr) = invoke_command(&set.executable, set.args.clone(), input_desired, Some(cwd), env)?; + print_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -231,6 +254,7 @@ pub fn invoke_test(resource: &ResourceManifest, cwd: &str, expected: &str) -> Re info!("Invoking test {} using {}", &resource.resource_type, &test.executable); let (exit_code, stdout, stderr) = invoke_command(&test.executable, args, input_expected, Some(cwd), env)?; + print_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -306,6 +330,7 @@ pub fn invoke_validate(resource: &ResourceManifest, cwd: &str, config: &str) -> }; let (exit_code, stdout, stderr) = invoke_command(&validate.executable, validate.args.clone(), Some(config), Some(cwd), None)?; + print_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -331,6 +356,7 @@ pub fn get_schema(resource: &ResourceManifest, cwd: &str) -> Result { let (exit_code, stdout, stderr) = invoke_command(&command.executable, command.args.clone(), None, Some(cwd), None)?; + print_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -375,6 +401,7 @@ pub fn invoke_export(resource: &ResourceManifest, cwd: &str) -> Result Date: Thu, 7 Mar 2024 11:24:41 -0800 Subject: [PATCH 2/6] Renamed to log_resource_traces --- dsc_lib/src/discovery/command_discovery.rs | 4 ++-- dsc_lib/src/dscresources/command_resource.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dsc_lib/src/discovery/command_discovery.rs b/dsc_lib/src/discovery/command_discovery.rs index ef36d9612..2eb72983e 100644 --- a/dsc_lib/src/discovery/command_discovery.rs +++ b/dsc_lib/src/discovery/command_discovery.rs @@ -5,7 +5,7 @@ use crate::discovery::discovery_trait::ResourceDiscovery; use crate::dscresources::dscresource::{DscResource, ImplementedAs}; use crate::dscresources::resource_manifest::{import_manifest, Kind, ResourceManifest}; use crate::dscresources::command_resource::invoke_command; -use crate::dscresources::command_resource::print_resource_traces; +use crate::dscresources::command_resource::log_resource_traces; use crate::dscerror::DscError; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use std::collections::BTreeMap; @@ -174,7 +174,7 @@ impl CommandDiscovery { continue; }, }; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { /* In case of "resource list" operation - print failure from adapter as warning diff --git a/dsc_lib/src/dscresources/command_resource.rs b/dsc_lib/src/dscresources/command_resource.rs index 03a395a53..664277026 100644 --- a/dsc_lib/src/dscresources/command_resource.rs +++ b/dsc_lib/src/dscresources/command_resource.rs @@ -12,7 +12,7 @@ use tracing::{debug, info, trace}; pub const EXIT_PROCESS_TERMINATED: i32 = 0x102; -pub fn print_resource_traces(stderr: &String) +pub fn log_resource_traces(stderr: &String) { if !stderr.is_empty() { @@ -70,7 +70,7 @@ pub fn invoke_get(resource: &ResourceManifest, cwd: &str, filter: &str) -> Resul info!("Invoking get {} using {}", &resource.resource_type, &resource.get.executable); let (exit_code, stdout, stderr) = invoke_command(&resource.get.executable, get_args, input_filter, Some(cwd), env)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -171,7 +171,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_te info!("Getting current state for set by invoking get {} using {}", &resource.resource_type, &resource.get.executable); let (exit_code, stdout, stderr) = invoke_command(&resource.get.executable, get_args, get_input, Some(cwd), get_env)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -185,7 +185,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_te info!("Invoking set {} using {}", &resource.resource_type, &set.executable); let (exit_code, stdout, stderr) = invoke_command(&set.executable, set.args.clone(), input_desired, Some(cwd), env)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -285,7 +285,7 @@ pub fn invoke_test(resource: &ResourceManifest, cwd: &str, expected: &str) -> Re info!("Invoking test {} using {}", &resource.resource_type, &test.executable); let (exit_code, stdout, stderr) = invoke_command(&test.executable, args, input_expected, Some(cwd), env)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -374,7 +374,7 @@ pub fn invoke_validate(resource: &ResourceManifest, cwd: &str, config: &str) -> }; let (exit_code, stdout, stderr) = invoke_command(&validate.executable, validate.args.clone(), Some(config), Some(cwd), None)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -400,7 +400,7 @@ pub fn get_schema(resource: &ResourceManifest, cwd: &str) -> Result { let (exit_code, stdout, stderr) = invoke_command(&command.executable, command.args.clone(), None, Some(cwd), None)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } @@ -439,14 +439,14 @@ pub fn get_schema(resource: &ResourceManifest, cwd: &str) -> Result) -> Result { +pub fn invoke_export(resource: &ResourceManifest, cwd: &str, _input: Option<&str>) -> Result { let Some(export) = resource.export.as_ref() else { return Err(DscError::Operation(format!("Export is not supported by resource {}", &resource.resource_type))) }; let (exit_code, stdout, stderr) = invoke_command(&export.executable, export.args.clone(), None, Some(cwd), None)?; - print_resource_traces(&stderr); + log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr)); } From 00063ecf1849f99c846e4c2e5a79e914bc0c1319 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 7 Mar 2024 11:43:06 -0800 Subject: [PATCH 3/6] Updated log_resource_traces --- dsc_lib/src/dscresources/command_resource.rs | 16 +++++++++++----- powershell-adapter/powershell.resource.ps1 | 10 +++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/dsc_lib/src/dscresources/command_resource.rs b/dsc_lib/src/dscresources/command_resource.rs index 664277026..5d4b9f6f0 100644 --- a/dsc_lib/src/dscresources/command_resource.rs +++ b/dsc_lib/src/dscresources/command_resource.rs @@ -7,7 +7,7 @@ use std::{collections::HashMap, env, process::Command, io::{Write, Read}, proces use crate::{dscerror::DscError, dscresources::invoke_result::{ResourceGetResponse, ResourceSetResponse, ResourceTestResponse}}; use crate::configure::config_result::ResourceGetResult; use super::{dscresource::get_diff,resource_manifest::{ResourceManifest, InputKind, ReturnKind, SchemaKind}, invoke_result::{GetResult, SetResult, TestResult, ValidateResult, ExportResult}}; -use tracing::{debug, info, trace}; +use tracing::{error, warn, info, debug, trace}; pub const EXIT_PROCESS_TERMINATED: i32 = 0x102; @@ -19,10 +19,16 @@ pub fn log_resource_traces(stderr: &String) for trace_line in stderr.lines() { match serde_json::from_str::(trace_line){ Result::Ok(json_obj) => { - let trace = json_obj.get("Trace"); - if trace.is_some() - { - trace!("{}", trace.unwrap().as_str().unwrap_or_default()); + if let Some(msg) = json_obj.get("Error") { + error!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Warning") { + warn!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Info") { + info!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Debug") { + debug!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Trace") { + trace!("{}", msg.as_str().unwrap_or_default()); } }, Result::Err(_) => {} diff --git a/powershell-adapter/powershell.resource.ps1 b/powershell-adapter/powershell.resource.ps1 index 9cab35a1c..3f9817463 100644 --- a/powershell-adapter/powershell.resource.ps1 +++ b/powershell-adapter/powershell.resource.ps1 @@ -75,15 +75,15 @@ Import-Module $DscModule -DisableNameChecking # Adding some debug info to STDERR $m = gmo PSDesiredStateConfiguration -$trace = @{"Trace"="PSVersion="+$PSVersionTable.PSVersion.ToString()} | ConvertTo-Json -Compress +$trace = @{"Debug"="PSVersion="+$PSVersionTable.PSVersion.ToString()} | ConvertTo-Json -Compress $host.ui.WriteErrorLine($trace) -$trace = @{"Trace"="PSPath="+$PSHome} | ConvertTo-Json -Compress +$trace = @{"Debug"="PSPath="+$PSHome} | ConvertTo-Json -Compress $host.ui.WriteErrorLine($trace) -$trace = @{"Trace"="ModuleVersion="+$m.Version.ToString()} | ConvertTo-Json -Compress +$trace = @{"Debug"="ModuleVersion="+$m.Version.ToString()} | ConvertTo-Json -Compress $host.ui.WriteErrorLine($trace) -$trace = @{"Trace"="ModulePath="+$m.Path} | ConvertTo-Json -Compress +$trace = @{"Debug"="ModulePath="+$m.Path} | ConvertTo-Json -Compress $host.ui.WriteErrorLine($trace) -$trace = @{"Trace"="PSModulePath="+$env:PSModulePath} | ConvertTo-Json -Compress +$trace = @{"Debug"="PSModulePath="+$env:PSModulePath} | ConvertTo-Json -Compress $host.ui.WriteErrorLine($trace) if ($Operation -eq 'List') From 04cdf11a0b80e7e92b5f83cdc291f3e8d032251e Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 7 Mar 2024 11:52:08 -0800 Subject: [PATCH 4/6] Updated log_resource_traces 2 --- dsc_lib/src/dscresources/command_resource.rs | 29 +++++++++----------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/dsc_lib/src/dscresources/command_resource.rs b/dsc_lib/src/dscresources/command_resource.rs index 5d4b9f6f0..47147060a 100644 --- a/dsc_lib/src/dscresources/command_resource.rs +++ b/dsc_lib/src/dscresources/command_resource.rs @@ -12,26 +12,23 @@ use tracing::{error, warn, info, debug, trace}; pub const EXIT_PROCESS_TERMINATED: i32 = 0x102; -pub fn log_resource_traces(stderr: &String) +pub fn log_resource_traces(stderr: &str) { if !stderr.is_empty() { for trace_line in stderr.lines() { - match serde_json::from_str::(trace_line){ - Result::Ok(json_obj) => { - if let Some(msg) = json_obj.get("Error") { - error!("{}", msg.as_str().unwrap_or_default()); - } else if let Some(msg) = json_obj.get("Warning") { - warn!("{}", msg.as_str().unwrap_or_default()); - } else if let Some(msg) = json_obj.get("Info") { - info!("{}", msg.as_str().unwrap_or_default()); - } else if let Some(msg) = json_obj.get("Debug") { - debug!("{}", msg.as_str().unwrap_or_default()); - } else if let Some(msg) = json_obj.get("Trace") { - trace!("{}", msg.as_str().unwrap_or_default()); - } - }, - Result::Err(_) => {} + if let Result::Ok(json_obj) = serde_json::from_str::(trace_line) { + if let Some(msg) = json_obj.get("Error") { + error!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Warning") { + warn!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Info") { + info!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Debug") { + debug!("{}", msg.as_str().unwrap_or_default()); + } else if let Some(msg) = json_obj.get("Trace") { + trace!("{}", msg.as_str().unwrap_or_default()); + }; }; } } From 7751a88369f4fa94bec7388cf6d690a877b0f610 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 7 Mar 2024 12:02:04 -0800 Subject: [PATCH 5/6] Fixed error in merge conflict --- dsc/tests/dsc_args.tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/dsc/tests/dsc_args.tests.ps1 b/dsc/tests/dsc_args.tests.ps1 index 4052648f0..b33a6c22d 100644 --- a/dsc/tests/dsc_args.tests.ps1 +++ b/dsc/tests/dsc_args.tests.ps1 @@ -185,6 +185,7 @@ resources: dsc -l trace resource list 2> $TestDrive/tracing.txt "$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'PSModulePath' $LASTEXITCODE | Should -Be 0 + } It 'stdin cannot be empty if neither input or path is provided' { '' | dsc resource set -r Microsoft/OSInfo 2> $TestDrive/error.txt From 6c2a6225eb6d6e167cadfd96ab034334792bde6e Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 12 Mar 2024 18:25:41 -0700 Subject: [PATCH 6/6] Fixed accidental typo --- dsc_lib/src/dscresources/command_resource.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsc_lib/src/dscresources/command_resource.rs b/dsc_lib/src/dscresources/command_resource.rs index 47147060a..001c280af 100644 --- a/dsc_lib/src/dscresources/command_resource.rs +++ b/dsc_lib/src/dscresources/command_resource.rs @@ -442,13 +442,13 @@ pub fn get_schema(resource: &ResourceManifest, cwd: &str) -> Result) -> Result { +pub fn invoke_export(resource: &ResourceManifest, cwd: &str, input: Option<&str>) -> Result { let Some(export) = resource.export.as_ref() else { return Err(DscError::Operation(format!("Export is not supported by resource {}", &resource.resource_type))) }; - let (exit_code, stdout, stderr) = invoke_command(&export.executable, export.args.clone(), None, Some(cwd), None)?; + let (exit_code, stdout, stderr) = invoke_command(&export.executable, export.args.clone(), input, Some(cwd), None)?; log_resource_traces(&stderr); if exit_code != 0 { return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr));