Skip to content

Commit 8757a0e

Browse files
author
Steve Lee (POWERSHELL HE/HIM) (from Dev Box)
committed
Fix resource manifests which weren't actually returning state, updat testadapter, fix tests, fix export format
1 parent 112bb64 commit 8757a0e

File tree

10 files changed

+80
-69
lines changed

10 files changed

+80
-69
lines changed

dsc/examples/powershell.dsc.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
# Example configuration mixing native app resources with classic PS resources
22
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
3+
metadata:
4+
Microsoft.DSC:
5+
securityContext: elevated
36
resources:
47
- name: Use class PowerShell resources
5-
type: Microsoft.DSC/PowerShell
8+
type: Microsoft.Windows/WindowsPowerShell
69
properties:
710
resources:
811
- name: OpenSSH service
9-
type: PsDesiredStateConfiguration/MSFT_ServiceResource
12+
type: PsDesiredStateConfiguration/Service
1013
properties:
1114
Name: sshd
1215
- name: Administrator
13-
type: PsDesiredStateConfiguration/MSFT_UserResource
16+
type: PsDesiredStateConfiguration/User
1417
properties:
1518
UserName: administrator
1619
- name: current user registry
1720
type: Microsoft.Windows/Registry
1821
properties:
1922
keyPath: HKLM\Software\Microsoft\Windows NT\CurrentVersion
2023
valueName: ProductName
21-
_ensure: Present
24+
_exist: True

dsc_lib/locales/en-us.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ circularDependency = "Circular dependency detected for resource named '%{resourc
3535
invocationOrder = "Resource invocation order"
3636

3737
[configure.mod]
38-
escapePropertyValues = "Escape returned property values"
3938
nestedArraysNotSupported = "Nested arrays not supported"
4039
arrayElementCouldNotTransformAsString = "Array element could not be transformed as string"
4140
valueCouldNotBeTransformedAsString = "Property value '%{value}' could not be transformed as string"
@@ -90,7 +89,7 @@ invokeGet = "Invoking get for '%{resource}'"
9089
invokeGetUsing = "Invoking get '%{resource}' using '%{executable}'"
9190
verifyOutputUsing = "Verifying output of get '%{resource}' using '%{executable}'"
9291
groupGetResponse = "Group get response: %{response}"
93-
failedParseJson = "Failed to parse JSON from get %{executable}|%{stdout}|%{stderr} -> %{err}"
92+
failedParseJson = "Failed to parse JSON from 'get': executable = '%{executable}' stdout = '%{stdout}' stderr = '%{stderr}' -> %{err}"
9493
invokeSet = "Invoking set for '%{resource}'"
9594
noPretest = "No pretest, invoking test on '%{resource}'"
9695
syntheticWhatIf = "cannot process what-if execution type, as resource implements pre-test and does not support what-if"
@@ -148,7 +147,7 @@ invokeExportReturnedNoResult = "Invoking export returned no result for '%{resour
148147
invokeResolve = "Invoking resolve for '%{resource}'"
149148
invokeResolveNotSupported = "Invoking resolve is not supported for adapted resource '%{resource}'"
150149
invokeReturnedWrongResult = "Invoking '%{operation}' on '%{resource}' returned unexpected result"
151-
propertyIncorrectType = "Property '%{property}' is not of type '%{type}'"
150+
propertyIncorrectType = "Property '%{property}' is not of type '%{property_type}'"
152151
propertyNotFound = "Property '%{property}' not found"
153152
subDiff = "diff: sub diff for '%{key}'"
154153
diffArray = "diff: arrays differ for '%{key}'"

dsc_lib/src/configure/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ pub fn add_resource_export_results_to_configuration(resource: &DscResource, conf
8282
// for values returned by resources, they may look like expressions, so we make sure to escape them in case
8383
// they are re-used to apply configuration
8484
fn escape_property_values(properties: &Map<String, Value>) -> Result<Option<Map<String, Value>>, DscError> {
85-
debug!("{}", t!("configure.mod.escapePropertyValues"));
8685
let mut result: Map<String, Value> = Map::new();
8786
for (name, value) in properties {
8887
match value {

dsc_lib/src/dscresources/dscresource.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,11 @@ impl DscResource {
100100
let mut property_map = Map::new();
101101
property_map.insert("name".to_string(), Value::String(self.type_name.clone()));
102102
property_map.insert("type".to_string(), Value::String(self.type_name.clone()));
103-
let resource_properties: Value = serde_json::from_str(input)?;
103+
if !input.is_empty() {
104+
let resource_properties: Value = serde_json::from_str(input)?;
105+
property_map.insert("properties".to_string(), resource_properties);
106+
}
104107
let mut resources_map = Map::new();
105-
property_map.insert("properties".to_string(), resource_properties);
106108
resources_map.insert("resources".to_string(), Value::Array(vec![Value::Object(property_map)]));
107109
let adapter_resource = Resource {
108110
name: self.type_name.clone(),
@@ -222,10 +224,10 @@ impl Invoke for DscResource {
222224
return Err(DscError::Operation(t!("dscresources.dscresource.invokeReturnedWrongResult", operation = "get", resource = self.type_name).to_string()));
223225
};
224226
let properties = resource_result.actual_state
225-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "actualState", r#type = "object").to_string()))?
227+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "actualState", property_type = "object").to_string()))?
226228
.get("result").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "result").to_string()))?
227-
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "array").to_string()))?[0]
228-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "object").to_string()))?
229+
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "array").to_string()))?[0]
230+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "object").to_string()))?
229231
.get("properties").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "properties").to_string()))?.clone();
230232
let get_result = GetResult::Resource(ResourceGetResponse {
231233
actual_state: properties.clone(),
@@ -256,16 +258,16 @@ impl Invoke for DscResource {
256258
return Err(DscError::Operation(t!("dscresources.dscresource.invokeReturnedWrongResult", operation = "set", resource = self.type_name).to_string()));
257259
};
258260
let before_state = resource_result.before_state
259-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "beforeState", r#type = "object").to_string()))?
261+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "beforeState", property_type = "object").to_string()))?
260262
.get("result").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "result").to_string()))?
261-
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "array").to_string()))?[0]
262-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "object").to_string()))?
263+
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "array").to_string()))?[0]
264+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "object").to_string()))?
263265
.get("properties").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "properties").to_string()))?.clone();
264266
let after_state = resource_result.after_state
265-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "afterState", r#type = "object").to_string()))?
267+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "afterState", property_type = "object").to_string()))?
266268
.get("result").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "result").to_string()))?
267-
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "array").to_string()))?[0]
268-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "object").to_string()))?
269+
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "array").to_string()))?[0]
270+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "object").to_string()))?
269271
.get("properties").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "properties").to_string()))?.clone();
270272
let diff = get_diff(&before_state, &after_state);
271273
let set_result = SetResult::Resource(ResourceSetResponse {
@@ -299,16 +301,16 @@ impl Invoke for DscResource {
299301
return Err(DscError::Operation(t!("dscresources.dscresource.invokeReturnedWrongResult", operation = "test", resource = self.type_name).to_string()));
300302
};
301303
let desired_state = resource_result.desired_state
302-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "desiredState", r#type = "object").to_string()))?
304+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "desiredState", property_type = "object").to_string()))?
303305
.get("resources").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "resources").to_string()))?
304-
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "resources", r#type = "array").to_string()))?[0]
305-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "resources", r#type = "object").to_string()))?
306+
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "resources", property_type = "array").to_string()))?[0]
307+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "resources", property_type = "object").to_string()))?
306308
.get("properties").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "properties").to_string()))?.clone();
307309
let actual_state = resource_result.actual_state
308-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "actualState", r#type = "object").to_string()))?
310+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "actualState", property_type = "object").to_string()))?
309311
.get("result").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "result").to_string()))?
310-
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "array").to_string()))?[0]
311-
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", r#type = "object").to_string()))?
312+
.as_array().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "array").to_string()))?[0]
313+
.as_object().ok_or(DscError::Operation(t!("dscresources.dscresource.propertyIncorrectType", property = "result", property_type = "object").to_string()))?
312314
.get("properties").ok_or(DscError::Operation(t!("dscresources.dscresource.propertyNotFound", property = "properties").to_string()))?.clone();
313315
let diff_properties = get_diff(&desired_state, &actual_state);
314316
let test_result = TestResult::Resource(ResourceTestResponse {
@@ -436,8 +438,10 @@ impl Invoke for DscResource {
436438
actual_state: Vec::new(),
437439
};
438440
for resource in configuration.resources {
439-
let value = serde_json::to_value(resource)?;
440-
export_result.actual_state.push(value);
441+
let Some(properties) = resource.properties else {
442+
return Err(DscError::Operation(t!("dscresources.dscresource.invokeExportReturnedNoResult", resource = self.type_name).to_string()));
443+
};
444+
export_result.actual_state.push(serde_json::to_value(properties["properties"].clone())?);
441445
}
442446
return Ok(export_result);
443447
}

powershell-adapter/Tests/TestAdapter/testadapter.dsc.resource.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@
4141
"$Input | ./testadapter.resource.ps1 Set"
4242
],
4343
"input": "stdin",
44-
"implementsPretest": true,
45-
"return": "state"
44+
"implementsPretest": true
4645
},
4746
"test": {
4847
"executable": "pwsh",
@@ -53,8 +52,7 @@
5352
"-Command",
5453
"$Input | ./testadapter.resource.ps1 Test"
5554
],
56-
"input": "stdin",
57-
"return": "state"
55+
"input": "stdin"
5856
},
5957
"export": {
6058
"executable": "pwsh",
@@ -65,8 +63,7 @@
6563
"-Command",
6664
"$Input | ./testadapter.resource.ps1 Export"
6765
],
68-
"input": "stdin",
69-
"return": "state"
66+
"input": "stdin"
7067
},
7168
"validate": {
7269
"executable": "pwsh",

powershell-adapter/Tests/TestAdapter/testadapter.resource.ps1

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ if ($jsonInput -ne '@{}') {
3030
$inputobj = $jsonInput | ConvertFrom-Json
3131
}
3232

33-
$jsonInput | Write-DscTrace
33+
"Input: $jsonInput" | Write-DscTrace
3434

3535
switch ($Operation) {
3636
'List' {
@@ -48,14 +48,19 @@ switch ($Operation) {
4848
description = 'TestCase resource'
4949
} | ConvertTo-Json -Compress
5050
}
51-
{ @('Get','Set','Test','Export') -contains $_ } {
51+
{ @('Get','Set','Test') -contains $_ } {
52+
"Operation: $Operation" | Write-DscTrace
5253

53-
if (($inputobj.TestCaseId -eq 1 ) -or ($_ -eq 'Export')){
54-
$result = @{'TestCaseId'=1; 'Input'=''; result = $result } | ConvertTo-Json -Depth 10 -Compress
55-
return $result
54+
if (($inputobj.resources.properties.TestCaseId -eq 1 ) -or ($_ -eq 'Export')){
55+
"Is TestCaseId 1" | Write-DscTrace
56+
@{result = @(@{name = $inputobj.resources.name; type = $inputobj.resources.type; properties = @{'TestCaseId' = 1; 'Input' = ''}})} | ConvertTo-Json -Depth 10 -Compress
5657
}
5758

5859
}
60+
'Export' {
61+
@(@{name = $inputobj.resources.name; type = $inputobj.resources.type; properties = @{'TestCaseId' = 1; 'Input' = ''}}) | ConvertTo-Json -Depth 10 -Compress
62+
@(@{name = $inputobj.resources.name; type = $inputobj.resources.type; properties = @{'TestCaseId' =2 ; 'Input' = ''}}) | ConvertTo-Json -Depth 10 -Compress
63+
}
5964
'Validate' {
6065
@{ valid = $true } | ConvertTo-Json
6166
}

0 commit comments

Comments
 (0)