Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion dsc/tests/dsc_resource_set.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Describe 'Invoke a resource set directly' {
$result = dsc resource set $alias -r Test/WhatIf --input '{"executionType":"Actual"}' | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$result.afterState.executionType | Should -BeExactly 'WhatIf'
$result.changedProperties | Should -BeExactly 'executionType'
$result.changedProperties | Should -Contain 'executionType'
Comment thread
tgauth marked this conversation as resolved.
Outdated
}

It 'actual execution of WhatIf resource' {
Expand Down
40 changes: 40 additions & 0 deletions dsc/tests/dsc_whatif.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,44 @@ Describe 'whatif tests' {
$out.results[0].result.afterState._exist | Should -BeFalse
$out.metadata.'Microsoft.DSC'.executionType | Should -BeExactly 'whatIf'
}

It 'Test/WhatIfReturnDiff resource returns state and diff in what-if mode' {
$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: WhatIfReturn StateAndDiff
type: Test/WhatIfReturnDiff
properties:
executionType: Actual
"@
$what_if_result = $config_yaml | dsc config set -w -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$what_if_result.hadErrors | Should -BeFalse
$what_if_result.metadata.'Microsoft.DSC'.executionType | Should -BeExactly 'whatIf'
$what_if_result.results[0].result.beforeState.executionType | Should -BeExactly 'Actual'
$what_if_result.results[0].result.afterState.executionType | Should -BeExactly 'WhatIf'
$what_if_result.results[0].result.afterState.fromResource | Should -BeExactly 'ResourceProvidedDiff'
$what_if_result.results[0].result.changedProperties | Should -BeExactly 'fromResource'
$what_if_result.results.Count | Should -Be 1
}

It 'Test/WhatIfReturnDiff resource returns state only in actual mode' {
$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: WhatIfReturn StateAndDiff
type: Test/WhatIfReturnDiff
properties:
executionType: Actual
"@
$actual_result = $config_yaml | dsc config set -f - | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$actual_result.hadErrors | Should -BeFalse
$actual_result.metadata.'Microsoft.DSC'.executionType | Should -BeExactly 'actual'
$actual_result.results[0].result.beforeState.executionType | Should -BeExactly 'Actual'
$actual_result.results[0].result.afterState.executionType | Should -BeExactly 'Actual'
$actual_result.results[0].result.afterState.fromResource | Should -BeNullOrEmpty
$actual_result.results[0].result.changedProperties | Should -Be $null
$actual_result.results.Count | Should -Be 1
}
}
8 changes: 7 additions & 1 deletion lib/dsc-lib/src/dscresources/command_resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,13 @@ pub fn invoke_set(resource: &DscResource, desired: &str, skip_test: bool, execut

let (exit_code, stdout, stderr) = invoke_command(&set.executable, args, input_desired, Some(&resource.directory), env, manifest.exit_codes.as_ref())?;

match set.returns {
let return_kind = if execution_type == &ExecutionKind::WhatIf {
set.what_if_returns.as_ref().or(set.returns.as_ref())
} else {
set.returns.as_ref()
};

match return_kind {
Some(ReturnKind::State) => {

if resource.kind == Kind::Resource {
Expand Down
3 changes: 3 additions & 0 deletions lib/dsc-lib/src/dscresources/resource_manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ pub struct SetMethod {
/// The type of return value expected from the Set method.
#[serde(rename = "return", skip_serializing_if = "Option::is_none")]
pub returns: Option<ReturnKind>,
/// The type of return value expected from the Set method when running in what-if mode. When specified, this overrides the `return` property during what-if execution.
#[serde(rename = "whatIfReturns", skip_serializing_if = "Option::is_none")]
pub what_if_returns: Option<ReturnKind>,
Comment thread
tgauth marked this conversation as resolved.
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, DscRepoSchema)]
Expand Down
22 changes: 8 additions & 14 deletions resources/registry/registry.dsc.resource.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@
{
"jsonInputArg": "--input",
"mandatory": true
},
{
"whatIfArg": "-w"
}
]
],
"whatIfReturns": "state"
},
"delete": {
"executable": "registry",
Expand All @@ -36,21 +40,11 @@
{
"jsonInputArg": "--input",
"mandatory": true
}
]
},
"whatIf": {
"executable": "registry",
"args": [
"config",
"set",
"-w",
},
{
"jsonInputArg": "--input",
"mandatory": true
"whatIfArg": "-w"
}
Comment thread
tgauth marked this conversation as resolved.
],
"return": "state"
]
},
"exitCodes": {
"0": "Success",
Expand Down
34 changes: 34 additions & 0 deletions tools/dsctest/dsctest.dsc.manifests.json
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,40 @@
]
}
}
},
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Test/WhatIfReturnDiff",
"version": "0.1.0",
"description": "Test resource for validating whatIfReturn with stateAndDiff return type",
"get": {
"executable": "dsctest",
"args": [
"whatif"
]
},
"set": {
"executable": "dsctest",
"args": [
"whatif",
{
"whatIfArg": "-w"
},
"--state-and-diff"
],
"return": "state",
"whatIfReturns": "stateAndDiff"
},
"schema": {
"command": {
"executable": "dsctest",
"args": [
"schema",
"-s",
"what-if"
]
}
}
}
]
}
2 changes: 2 additions & 0 deletions tools/dsctest/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ pub enum SubCommand {
WhatIf {
#[clap(name = "whatif", short, long, help = "Run as a whatif executionType instead of actual executionType")]
what_if: bool,
#[clap(name = "state-and-diff", short, long, help = "Output stateAndDiff format (state on first line, diff array on second line)")]
state_and_diff: bool,
},

#[clap(name = "whatif-delete", about = "Check if it is a whatif delete operation")]
Expand Down
37 changes: 33 additions & 4 deletions tools/dsctest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,42 @@ fn main() {
};
serde_json::to_string(&version).unwrap()
},
SubCommand::WhatIf { what_if } => {
SubCommand::WhatIf { what_if, state_and_diff } => {
let result: WhatIf = if what_if {
WhatIf { execution_type: "WhatIf".to_string(), exist: None }
if state_and_diff {
WhatIf {
execution_type: "WhatIf".to_string(),
exist: None,
from_resource: Some("ResourceProvidedDiff".to_string())
}
} else {
WhatIf {
execution_type: "WhatIf".to_string(),
exist: None,
from_resource: None
}
}
} else {
WhatIf { execution_type: "Actual".to_string(), exist: None }
WhatIf {
execution_type: "Actual".to_string(),
exist: None,
from_resource: None
}
};
serde_json::to_string(&result).unwrap()

// Output state as first line
let state_json = serde_json::to_string(&result).unwrap();
println!("{state_json}");

// If state_and_diff is requested and it's a what-if operation, output diff on second line
if state_and_diff && what_if {
let diff = vec!["fromResource"];
let diff_json = serde_json::to_string(&diff).unwrap();
println!("{diff_json}");
}

// Return empty string since we already printed
String::new()
},
SubCommand::WhatIfDelete { what_if } => {
let result = if what_if {
Expand Down
2 changes: 2 additions & 0 deletions tools/dsctest/src/whatif.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ pub struct WhatIf {
pub execution_type: String,
#[serde(rename = "_exist", skip_serializing_if = "Option::is_none")]
pub exist: Option<bool>,
#[serde(rename = "fromResource", skip_serializing_if = "Option::is_none")]
pub from_resource: Option<String>,
}