Skip to content

Commit 02906fc

Browse files
authored
Merge pull request #720 from SteveL-MSFT/implicit-ps
Enable using adapter resources without the adapter wrapper
2 parents d769405 + 8ad44b8 commit 02906fc

22 files changed

+355
-352
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/locales/en-us.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ noParameters = "No parameters specified"
6767
[resource_command]
6868
implementedAs = "implemented as"
6969
invalidOperationOnAdapter = "Can not perform this operation on the adapter itself"
70-
adapterNotFound = "Adapter not found"
7170
setInputEmpty = "Desired input is empty"
7271
testInputEmpty = "Expected input is required"
7372

dsc/src/resource_command.rs

Lines changed: 17 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
use crate::args::OutputFormat;
5-
use crate::util::{EXIT_DSC_ERROR, EXIT_INVALID_ARGS, EXIT_JSON_ERROR, EXIT_DSC_RESOURCE_NOT_FOUND, add_type_name_to_json, write_object};
5+
use crate::util::{EXIT_DSC_ERROR, EXIT_INVALID_ARGS, EXIT_JSON_ERROR, EXIT_DSC_RESOURCE_NOT_FOUND, write_object};
66
use dsc_lib::configure::config_doc::{Configuration, ExecutionKind};
77
use dsc_lib::configure::add_resource_export_results_to_configuration;
88
use dsc_lib::dscresources::{resource_manifest::Kind, invoke_result::{GetResult, ResourceGetResponse}};
@@ -16,8 +16,8 @@ use dsc_lib::{
1616
};
1717
use std::process::exit;
1818

19-
pub fn get(dsc: &DscManager, resource_type: &str, mut input: String, format: Option<&OutputFormat>) {
20-
let Some(mut resource) = get_resource(dsc, resource_type) else {
19+
pub fn get(dsc: &DscManager, resource_type: &str, input: &str, format: Option<&OutputFormat>) {
20+
let Some(resource) = get_resource(dsc, resource_type) else {
2121
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
2222
exit(EXIT_DSC_RESOURCE_NOT_FOUND);
2323
};
@@ -28,17 +28,7 @@ pub fn get(dsc: &DscManager, resource_type: &str, mut input: String, format: Opt
2828
exit(EXIT_DSC_ERROR);
2929
}
3030

31-
if let Some(requires) = &resource.require_adapter {
32-
input = add_type_name_to_json(input, resource.type_name.clone());
33-
if let Some(pr) = get_resource(dsc, requires) {
34-
resource = pr;
35-
} else {
36-
error!("{}: {requires}", t!("resource_command.adapterNotFound"));
37-
return;
38-
};
39-
}
40-
41-
match resource.get(input.as_str()) {
31+
match resource.get(input) {
4232
Ok(result) => {
4333
// convert to json
4434
let json = match serde_json::to_string(&result) {
@@ -58,8 +48,8 @@ pub fn get(dsc: &DscManager, resource_type: &str, mut input: String, format: Opt
5848
}
5949

6050
pub fn get_all(dsc: &DscManager, resource_type: &str, format: Option<&OutputFormat>) {
61-
let mut input = String::new();
62-
let Some(mut resource) = get_resource(dsc, resource_type) else {
51+
let input = String::new();
52+
let Some(resource) = get_resource(dsc, resource_type) else {
6353
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
6454
exit(EXIT_DSC_RESOURCE_NOT_FOUND);
6555
};
@@ -70,16 +60,6 @@ pub fn get_all(dsc: &DscManager, resource_type: &str, format: Option<&OutputForm
7060
exit(EXIT_DSC_ERROR);
7161
}
7262

73-
if let Some(requires) = &resource.require_adapter {
74-
input = add_type_name_to_json(input, resource.type_name.clone());
75-
if let Some(pr) = get_resource(dsc, requires) {
76-
resource = pr;
77-
} else {
78-
error!("{}: {requires}", t!("resource_command.adapterNotFound"));
79-
return;
80-
};
81-
}
82-
8363
let export_result = match resource.export(&input) {
8464
Ok(export) => { export }
8565
Err(err) => {
@@ -107,13 +87,13 @@ pub fn get_all(dsc: &DscManager, resource_type: &str, format: Option<&OutputForm
10787
}
10888
}
10989

110-
pub fn set(dsc: &DscManager, resource_type: &str, mut input: String, format: Option<&OutputFormat>) {
90+
pub fn set(dsc: &DscManager, resource_type: &str, input: &str, format: Option<&OutputFormat>) {
11191
if input.is_empty() {
11292
error!("{}", t!("resource_command.setInputEmpty"));
11393
exit(EXIT_INVALID_ARGS);
11494
}
11595

116-
let Some(mut resource) = get_resource(dsc, resource_type) else {
96+
let Some(resource) = get_resource(dsc, resource_type) else {
11797
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
11898
exit(EXIT_DSC_RESOURCE_NOT_FOUND);
11999
};
@@ -124,17 +104,7 @@ pub fn set(dsc: &DscManager, resource_type: &str, mut input: String, format: Opt
124104
exit(EXIT_DSC_ERROR);
125105
}
126106

127-
if let Some(requires) = &resource.require_adapter {
128-
input = add_type_name_to_json(input, resource.type_name.clone());
129-
if let Some(pr) = get_resource(dsc, requires) {
130-
resource = pr;
131-
} else {
132-
error!("{}: {requires}", t!("resource_command.adapterNotFound"));
133-
return;
134-
};
135-
}
136-
137-
match resource.set(input.as_str(), true, &ExecutionKind::Actual) {
107+
match resource.set(input, true, &ExecutionKind::Actual) {
138108
Ok(result) => {
139109
// convert to json
140110
let json = match serde_json::to_string(&result) {
@@ -153,13 +123,13 @@ pub fn set(dsc: &DscManager, resource_type: &str, mut input: String, format: Opt
153123
}
154124
}
155125

156-
pub fn test(dsc: &DscManager, resource_type: &str, mut input: String, format: Option<&OutputFormat>) {
126+
pub fn test(dsc: &DscManager, resource_type: &str, input: &str, format: Option<&OutputFormat>) {
157127
if input.is_empty() {
158128
error!("{}", t!("resource_command.testInputEmpty"));
159129
exit(EXIT_INVALID_ARGS);
160130
}
161131

162-
let Some(mut resource) = get_resource(dsc, resource_type) else {
132+
let Some(resource) = get_resource(dsc, resource_type) else {
163133
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
164134
exit(EXIT_DSC_RESOURCE_NOT_FOUND);
165135
};
@@ -170,17 +140,7 @@ pub fn test(dsc: &DscManager, resource_type: &str, mut input: String, format: Op
170140
exit(EXIT_DSC_ERROR);
171141
}
172142

173-
if let Some(requires) = &resource.require_adapter {
174-
input = add_type_name_to_json(input, resource.type_name.clone());
175-
if let Some(pr) = get_resource(dsc, requires) {
176-
resource = pr;
177-
} else {
178-
error!("{}: {requires}", t!("resource_command.adapterNotFound"));
179-
return;
180-
};
181-
}
182-
183-
match resource.test(input.as_str()) {
143+
match resource.test(input) {
184144
Ok(result) => {
185145
// convert to json
186146
let json = match serde_json::to_string(&result) {
@@ -199,8 +159,8 @@ pub fn test(dsc: &DscManager, resource_type: &str, mut input: String, format: Op
199159
}
200160
}
201161

202-
pub fn delete(dsc: &DscManager, resource_type: &str, mut input: String) {
203-
let Some(mut resource) = get_resource(dsc, resource_type) else {
162+
pub fn delete(dsc: &DscManager, resource_type: &str, input: &str) {
163+
let Some(resource) = get_resource(dsc, resource_type) else {
204164
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
205165
exit(EXIT_DSC_RESOURCE_NOT_FOUND);
206166
};
@@ -211,17 +171,7 @@ pub fn delete(dsc: &DscManager, resource_type: &str, mut input: String) {
211171
exit(EXIT_DSC_ERROR);
212172
}
213173

214-
if let Some(requires) = &resource.require_adapter {
215-
input = add_type_name_to_json(input, resource.type_name.clone());
216-
if let Some(pr) = get_resource(dsc, requires) {
217-
resource = pr;
218-
} else {
219-
error!("{}: {requires}", t!("resource_command.adapterNotFound"));
220-
return;
221-
};
222-
}
223-
224-
match resource.delete(input.as_str()) {
174+
match resource.delete(input) {
225175
Ok(()) => {}
226176
Err(err) => {
227177
error!("Error: {err}");
@@ -259,7 +209,7 @@ pub fn schema(dsc: &DscManager, resource_type: &str, format: Option<&OutputForma
259209
}
260210
}
261211

262-
pub fn export(dsc: &mut DscManager, resource_type: &str, mut input: String, format: Option<&OutputFormat>) {
212+
pub fn export(dsc: &mut DscManager, resource_type: &str, input: &str, format: Option<&OutputFormat>) {
263213
let Some(dsc_resource) = get_resource(dsc, resource_type) else {
264214
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
265215
exit(EXIT_DSC_RESOURCE_NOT_FOUND);
@@ -270,20 +220,8 @@ pub fn export(dsc: &mut DscManager, resource_type: &str, mut input: String, form
270220
exit(EXIT_DSC_ERROR);
271221
}
272222

273-
let mut adapter_resource: Option<&DscResource> = None;
274-
if let Some(requires) = &dsc_resource.require_adapter {
275-
input = add_type_name_to_json(input, dsc_resource.type_name.clone());
276-
if let Some(pr) = get_resource(dsc, requires) {
277-
adapter_resource = Some(pr);
278-
} else {
279-
error!("{}: {requires}", t!("resource_command.adapterNotFound"));
280-
return;
281-
};
282-
}
283-
284223
let mut conf = Configuration::new();
285-
286-
if let Err(err) = add_resource_export_results_to_configuration(dsc_resource, adapter_resource, &mut conf, &input) {
224+
if let Err(err) = add_resource_export_results_to_configuration(dsc_resource, &mut conf, input) {
287225
error!("{err}");
288226
exit(EXIT_DSC_ERROR);
289227
}

dsc/src/subcommand.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -548,30 +548,30 @@ pub fn resource(subcommand: &ResourceSubCommand, progress_format: ProgressFormat
548548
ResourceSubCommand::Export { resource, input, file, output_format } => {
549549
dsc.find_resources(&[resource.to_string()], progress_format);
550550
let parsed_input = get_input(input.as_ref(), file.as_ref());
551-
resource_command::export(&mut dsc, resource, parsed_input, output_format.as_ref());
551+
resource_command::export(&mut dsc, resource, &parsed_input, output_format.as_ref());
552552
},
553553
ResourceSubCommand::Get { resource, input, file: path, all, output_format } => {
554554
dsc.find_resources(&[resource.to_string()], progress_format);
555555
if *all { resource_command::get_all(&dsc, resource, output_format.as_ref()); }
556556
else {
557557
let parsed_input = get_input(input.as_ref(), path.as_ref());
558-
resource_command::get(&dsc, resource, parsed_input, output_format.as_ref());
558+
resource_command::get(&dsc, resource, &parsed_input, output_format.as_ref());
559559
}
560560
},
561561
ResourceSubCommand::Set { resource, input, file: path, output_format } => {
562562
dsc.find_resources(&[resource.to_string()], progress_format);
563563
let parsed_input = get_input(input.as_ref(), path.as_ref());
564-
resource_command::set(&dsc, resource, parsed_input, output_format.as_ref());
564+
resource_command::set(&dsc, resource, &parsed_input, output_format.as_ref());
565565
},
566566
ResourceSubCommand::Test { resource, input, file: path, output_format } => {
567567
dsc.find_resources(&[resource.to_string()], progress_format);
568568
let parsed_input = get_input(input.as_ref(), path.as_ref());
569-
resource_command::test(&dsc, resource, parsed_input, output_format.as_ref());
569+
resource_command::test(&dsc, resource, &parsed_input, output_format.as_ref());
570570
},
571571
ResourceSubCommand::Delete { resource, input, file: path } => {
572572
dsc.find_resources(&[resource.to_string()], progress_format);
573573
let parsed_input = get_input(input.as_ref(), path.as_ref());
574-
resource_command::delete(&dsc, resource, parsed_input);
574+
resource_command::delete(&dsc, resource, &parsed_input);
575575
},
576576
}
577577
}

dsc/src/util.rs

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -129,37 +129,6 @@ pub fn add_fields_to_json(json: &str, fields_to_add: &HashMap<String, String>) -
129129
Ok(result)
130130
}
131131

132-
/// Add the type property value to the JSON.
133-
///
134-
/// # Arguments
135-
///
136-
/// * `json` - The JSON to add the type property to
137-
/// * `type_name` - The type name to add
138-
///
139-
/// # Returns
140-
///
141-
/// * `String` - The JSON with the type property added
142-
#[must_use]
143-
pub fn add_type_name_to_json(json: String, type_name: String) -> String
144-
{
145-
let mut map:HashMap<String,String> = HashMap::new();
146-
map.insert(String::from("adapted_dsc_type"), type_name);
147-
148-
let mut j = json;
149-
if j.is_empty()
150-
{
151-
j = String::from("{}");
152-
}
153-
154-
match add_fields_to_json(&j, &map) {
155-
Ok(json) => json,
156-
Err(err) => {
157-
error!("JSON: {err}");
158-
exit(EXIT_JSON_ERROR);
159-
}
160-
}
161-
}
162-
163132
/// Get the JSON schema for requested type.
164133
///
165134
/// # Arguments

dsc_lib/locales/en-us.toml

Lines changed: 8 additions & 2 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"
@@ -89,7 +88,7 @@ invokeGet = "Invoking get for '%{resource}'"
8988
invokeGetUsing = "Invoking get '%{resource}' using '%{executable}'"
9089
verifyOutputUsing = "Verifying output of get '%{resource}' using '%{executable}'"
9190
groupGetResponse = "Group get response: %{response}"
92-
failedParseJson = "Failed to parse JSON from get %{executable}|%{stdout}|%{stderr} -> %{err}"
91+
failedParseJson = "Failed to parse JSON from 'get': executable = '%{executable}' stdout = '%{stdout}' stderr = '%{stderr}' -> %{err}"
9392
invokeSet = "Invoking set for '%{resource}'"
9493
noPretest = "No pretest, invoking test on '%{resource}'"
9594
syntheticWhatIf = "cannot process what-if execution type, as resource implements pre-test and does not support what-if"
@@ -139,9 +138,16 @@ invokeSet = "Invoking set for '%{resource}'"
139138
invokeTest = "Invoking test for '%{resource}'"
140139
invokeDelete = "Invoking delete for '%{resource}'"
141140
invokeValidate = "Invoking validate for '%{resource}'"
141+
invokeValidateNotSupported = "Invoking validate is not supported for adapted resource '%{resource}'"
142142
invokeSchema = "Invoking schema for '%{resource}'"
143+
invokeSchemaNotSupported = "Invoking schema is not supported for adapted resource '%{resource}'"
143144
invokeExport = "Invoking export for '%{resource}'"
145+
invokeExportReturnedNoResult = "Invoking export returned no result for '%{resource}'"
144146
invokeResolve = "Invoking resolve for '%{resource}'"
147+
invokeResolveNotSupported = "Invoking resolve is not supported for adapted resource '%{resource}'"
148+
invokeReturnedWrongResult = "Invoking '%{operation}' on '%{resource}' returned unexpected result"
149+
propertyIncorrectType = "Property '%{property}' is not of type '%{property_type}'"
150+
propertyNotFound = "Property '%{property}' not found"
145151
subDiff = "diff: sub diff for '%{key}'"
146152
diffArray = "diff: arrays differ for '%{key}'"
147153
diffNotArray = "diff: '%{key}' is not an array"

dsc_lib/src/configure/config_doc.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ use std::collections::HashMap;
99

1010
use crate::{dscerror::DscError, schemas::DscRepoSchema};
1111

12-
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
13-
#[serde(rename_all = "camelCase")]
14-
pub enum ContextKind {
15-
Configuration,
16-
Resource,
17-
}
18-
1912
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
2013
#[serde(rename_all = "camelCase")]
2114
pub enum SecurityContextKind {
@@ -63,9 +56,6 @@ pub struct MicrosoftDscMetadata {
6356
/// The security context of the configuration operation, can be specified to be required
6457
#[serde(rename = "securityContext", skip_serializing_if = "Option::is_none")]
6558
pub security_context: Option<SecurityContextKind>,
66-
/// Identifies if the operation is part of a configuration
67-
#[serde(skip_serializing_if = "Option::is_none")]
68-
pub context: Option<ContextKind>,
6959
}
7060

7161
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]

0 commit comments

Comments
 (0)