Skip to content

Fix adapter configuration set which returns result, but needs to be resources #774

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

Merged
merged 4 commits into from
May 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions dsc_lib/src/configure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,12 +405,18 @@ impl Configurator {
let GetResult::Resource(after_result) = after_result else {
return Err(DscError::NotSupported(t!("configure.mod.groupNotSupportedForDelete").to_string()))
};
let before_value = serde_json::to_value(&before_response.actual_state)?;
let after_value = serde_json::to_value(&after_result.actual_state)?;
let diff = get_diff(&before_response.actual_state, &after_result.actual_state);
let mut before: Map<String, Value> = serde_json::from_value(before_response.actual_state)?;
// a `get` will return a `result` property, but an actual `set` will have that as `resources`
if before.contains_key("result") && !before.contains_key("resources") {
before.insert("resources".to_string() ,before["result"].clone());
before.remove("result");
}
let before_value = serde_json::to_value(&before)?;
SetResult::Resource(ResourceSetResponse {
before_state: before_response.actual_state,
before_state: before_value.clone(),
after_state: after_result.actual_state,
changed_properties: Some(get_diff(&before_value, &after_value)),
changed_properties: Some(diff),
})
},
GetResult::Group(_) => {
Expand Down
16 changes: 14 additions & 2 deletions dsc_lib/src/dscresources/command_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use clap::ValueEnum;
use jsonschema::Validator;
use rust_i18n::t;
use serde::Deserialize;
use serde_json::Value;
use serde_json::{Map, Value};
use std::{collections::HashMap, env, process::Stdio};
use crate::configure::{config_doc::ExecutionKind, config_result::{ResourceGetResult, ResourceTestResult}};
use crate::dscerror::DscError;
Expand Down Expand Up @@ -146,12 +146,24 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_te
verify_json(resource, cwd, &stdout)?;
}

let pre_state: Value = if exit_code == 0 {
let pre_state_value: Value = if exit_code == 0 {
serde_json::from_str(&stdout)?
}
else {
return Err(DscError::Command(resource.resource_type.clone(), exit_code, stderr));
};
let pre_state = if pre_state_value.is_object() {
let mut pre_state_map: Map<String, Value> = serde_json::from_value(pre_state_value)?;

// if the resource is an adapter, then the `get` will return a `result`, but a full `set` expects the before state to be `resources`
if resource.kind == Some(Kind::Adapter) && pre_state_map.contains_key("result") && !pre_state_map.contains_key("resources") {
pre_state_map.insert("resources".to_string(), pre_state_map["result"].clone());
pre_state_map.remove("result");
}
serde_json::to_value(pre_state_map)?
} else {
pre_state_value
};

let mut env: Option<HashMap<String, String>> = None;
let mut input_desired: Option<&str> = None;
Expand Down
2 changes: 1 addition & 1 deletion dsc_lib/src/dscresources/dscresource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl Invoke for DscResource {
};
let before_state = resource_result.before_state
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "beforeState", property_type = "object").to_string()))?
.get("result").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "result").to_string()))?
.get("resources").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "resources").to_string()))?
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "array").to_string()))?[0]
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "object").to_string()))?
.get("properties").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "properties").to_string()))?.clone();
Expand Down
7 changes: 4 additions & 3 deletions powershell-adapter/Tests/powershellgroup.config.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,10 @@ Describe 'PowerShell adapter resource tests' {
Name: 'DSCv3'
"@

$out = dsc config $operation -i $yaml | ConvertFrom-Json
$text = dsc config $operation -i $yaml | Out-String
$LASTEXITCODE | Should -Be 0
$out = dsc -l trace config $operation -i $yaml 2> $TestDrive/tracing.txt
$text = $out | Out-String
$out = $out | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0 -Because (Get-Content -Raw -Path $TestDrive/tracing.txt)
switch ($Operation) {
'get' {
$out.results[0].result.actualState.Name | Should -BeExactly 'TestClassResource1' -Because $text
Expand Down
Loading