Skip to content

Commit 84ccfc5

Browse files
(GH-538) Update target_resource to use FQTN
This change updates the `target_resource` field of `DscResource` to use `FullyQualifiedTypeName` instead of `String`. It also updates related functions to expect that type instead of `&str`.
1 parent 709e61f commit 84ccfc5

File tree

5 files changed

+37
-37
lines changed

5 files changed

+37
-37
lines changed

dsc/src/mcp/list_dsc_resources.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl McpServer {
7070
r#type: resource.type_name.to_string(),
7171
kind: resource.kind.clone(),
7272
description: resource.description.clone(),
73-
require_adapter: resource.require_adapter.clone(),
73+
require_adapter: resource.require_adapter.map(|fqtn| fqtn.to_string()),
7474
};
7575
resources.insert(resource.type_name.to_lowercase(), summary);
7676
}

dsc/src/subcommand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ pub fn list_resources(dsc: &mut DscManager, resource_name: Option<&String>, adap
824824
format!("{:?}", resource.kind),
825825
resource.version,
826826
capabilities,
827-
resource.require_adapter.unwrap_or_default(),
827+
resource.require_adapter.unwrap_or_default().to_string(),
828828
resource.description.unwrap_or_default()
829829
]);
830830
}

lib/dsc-lib/src/dscresources/command_resource.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rust_i18n::t;
77
use serde::Deserialize;
88
use serde_json::{Map, Value};
99
use std::{collections::HashMap, env, path::Path, process::Stdio};
10-
use crate::{configure::{config_doc::ExecutionKind, config_result::{ResourceGetResult, ResourceTestResult}}, util::canonicalize_which};
10+
use crate::{configure::{config_doc::ExecutionKind, config_result::{ResourceGetResult, ResourceTestResult}}, types::FullyQualifiedTypeName, util::canonicalize_which};
1111
use crate::dscerror::DscError;
1212
use super::{dscresource::{get_diff, redact}, invoke_result::{ExportResult, GetResult, ResolveResult, SetResult, TestResult, ValidateResult, ResourceGetResponse, ResourceSetResponse, ResourceTestResponse, get_in_desired_state}, resource_manifest::{ArgKind, InputKind, Kind, ResourceManifest, ReturnKind, SchemaKind}};
1313
use tracing::{error, warn, info, debug, trace};
@@ -25,17 +25,17 @@ pub const EXIT_PROCESS_TERMINATED: i32 = 0x102;
2525
/// # Errors
2626
///
2727
/// Error returned if the resource does not successfully get the current state
28-
pub fn invoke_get(resource: &ResourceManifest, cwd: &Path, filter: &str, target_resource: Option<&str>) -> Result<GetResult, DscError> {
28+
pub fn invoke_get(resource: &ResourceManifest, cwd: &Path, filter: &str, target_resource: Option<FullyQualifiedTypeName>) -> Result<GetResult, DscError> {
2929
debug!("{}", t!("dscresources.commandResource.invokeGet", resource = &resource.resource_type));
3030
let mut command_input = CommandInput { env: None, stdin: None };
3131
let Some(get) = &resource.get else {
3232
return Err(DscError::NotImplemented("get".to_string()));
3333
};
3434
let resource_type = match target_resource {
3535
Some(r) => r,
36-
None => &resource.resource_type,
36+
None => resource.resource_type.clone(),
3737
};
38-
let args = process_args(get.args.as_ref(), filter, resource_type);
38+
let args = process_args(get.args.as_ref(), filter, &resource_type);
3939
if !filter.is_empty() {
4040
verify_json(resource, cwd, filter)?;
4141
command_input = get_command_input(get.input.as_ref(), filter)?;
@@ -78,7 +78,7 @@ pub fn invoke_get(resource: &ResourceManifest, cwd: &Path, filter: &str, target_
7878
///
7979
/// Error returned if the resource does not successfully set the desired state
8080
#[allow(clippy::too_many_lines)]
81-
pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_test: bool, execution_type: &ExecutionKind, target_resource: Option<&str>) -> Result<SetResult, DscError> {
81+
pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_test: bool, execution_type: &ExecutionKind, target_resource: Option<FullyQualifiedTypeName>) -> Result<SetResult, DscError> {
8282
debug!("{}", t!("dscresources.commandResource.invokeSet", resource = &resource.resource_type));
8383
let operation_type: String;
8484
let mut is_synthetic_what_if = false;
@@ -105,7 +105,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_t
105105
// if resource doesn't implement a pre-test, we execute test first to see if a set is needed
106106
if !skip_test && set.pre_test != Some(true) {
107107
info!("{}", t!("dscresources.commandResource.noPretest", resource = &resource.resource_type));
108-
let test_result = invoke_test(resource, cwd, desired, target_resource)?;
108+
let test_result = invoke_test(resource, cwd, desired, target_resource.clone())?;
109109
if is_synthetic_what_if {
110110
return Ok(test_result.into());
111111
}
@@ -140,11 +140,11 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_t
140140
let Some(get) = &resource.get else {
141141
return Err(DscError::NotImplemented("get".to_string()));
142142
};
143-
let resource_type = match target_resource {
143+
let resource_type = match target_resource.clone() {
144144
Some(r) => r,
145-
None => &resource.resource_type,
145+
None => resource.resource_type.clone(),
146146
};
147-
let args = process_args(get.args.as_ref(), desired, resource_type);
147+
let args = process_args(get.args.as_ref(), desired, &resource_type);
148148
let command_input = get_command_input(get.input.as_ref(), desired)?;
149149

150150
info!("{}", t!("dscresources.commandResource.setGetCurrent", resource = &resource.resource_type, executable = &get.executable));
@@ -176,7 +176,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_t
176176

177177
let mut env: Option<HashMap<String, String>> = None;
178178
let mut input_desired: Option<&str> = None;
179-
let args = process_args(set.args.as_ref(), desired, resource_type);
179+
let args = process_args(set.args.as_ref(), desired, &resource_type);
180180
match &set.input {
181181
Some(InputKind::Env) => {
182182
env = Some(json_to_hashmap(desired)?);
@@ -271,7 +271,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_t
271271
/// # Errors
272272
///
273273
/// Error is returned if the underlying command returns a non-zero exit code.
274-
pub fn invoke_test(resource: &ResourceManifest, cwd: &Path, expected: &str, target_resource: Option<&str>) -> Result<TestResult, DscError> {
274+
pub fn invoke_test(resource: &ResourceManifest, cwd: &Path, expected: &str, target_resource: Option<FullyQualifiedTypeName>) -> Result<TestResult, DscError> {
275275
debug!("{}", t!("dscresources.commandResource.invokeTest", resource = &resource.resource_type));
276276
let Some(test) = &resource.test else {
277277
info!("{}", t!("dscresources.commandResource.testSyntheticTest", resource = &resource.resource_type));
@@ -280,11 +280,11 @@ pub fn invoke_test(resource: &ResourceManifest, cwd: &Path, expected: &str, targ
280280

281281
verify_json(resource, cwd, expected)?;
282282

283-
let resource_type = match target_resource {
283+
let resource_type = match target_resource.clone() {
284284
Some(r) => r,
285-
None => &resource.resource_type,
285+
None => resource.resource_type.clone(),
286286
};
287-
let args = process_args(test.args.as_ref(), expected, resource_type);
287+
let args = process_args(test.args.as_ref(), expected, &resource_type);
288288
let command_input = get_command_input(test.input.as_ref(), expected)?;
289289

290290
info!("{}", t!("dscresources.commandResource.invokeTestUsing", resource = &resource.resource_type, executable = &test.executable));
@@ -380,7 +380,7 @@ fn get_desired_state(actual: &Value) -> Result<Option<bool>, DscError> {
380380
Ok(in_desired_state)
381381
}
382382

383-
fn invoke_synthetic_test(resource: &ResourceManifest, cwd: &Path, expected: &str, target_resource: Option<&str>) -> Result<TestResult, DscError> {
383+
fn invoke_synthetic_test(resource: &ResourceManifest, cwd: &Path, expected: &str, target_resource: Option<FullyQualifiedTypeName>) -> Result<TestResult, DscError> {
384384
let get_result = invoke_get(resource, cwd, expected, target_resource)?;
385385
let actual_state = match get_result {
386386
GetResult::Group(results) => {
@@ -511,7 +511,7 @@ pub fn get_schema(resource: &ResourceManifest, cwd: &Path) -> Result<String, Dsc
511511
/// # Errors
512512
///
513513
/// Error returned if the resource does not successfully export the current state
514-
pub fn invoke_export(resource: &ResourceManifest, cwd: &Path, input: Option<&str>, target_resource: Option<&str>) -> Result<ExportResult, DscError> {
514+
pub fn invoke_export(resource: &ResourceManifest, cwd: &Path, input: Option<&str>, target_resource: Option<FullyQualifiedTypeName>) -> Result<ExportResult, DscError> {
515515
let Some(export) = resource.export.as_ref() else {
516516
// see if get is supported and use that instead
517517
if resource.get.is_some() {
@@ -540,7 +540,7 @@ pub fn invoke_export(resource: &ResourceManifest, cwd: &Path, input: Option<&str
540540
let args: Option<Vec<String>>;
541541
let resource_type = match target_resource {
542542
Some(r) => r,
543-
None => &resource.resource_type,
543+
None => resource.resource_type.clone(),
544544
};
545545
if let Some(input) = input {
546546
if !input.is_empty() {
@@ -549,9 +549,9 @@ pub fn invoke_export(resource: &ResourceManifest, cwd: &Path, input: Option<&str
549549
command_input = get_command_input(export.input.as_ref(), input)?;
550550
}
551551

552-
args = process_args(export.args.as_ref(), input, resource_type);
552+
args = process_args(export.args.as_ref(), input, &resource_type);
553553
} else {
554-
args = process_args(export.args.as_ref(), "", resource_type);
554+
args = process_args(export.args.as_ref(), "", &resource_type);
555555
}
556556

557557
let (_exit_code, stdout, stderr) = invoke_command(&export.executable, args, command_input.stdin.as_deref(), Some(cwd), command_input.env, resource.exit_codes.as_ref())?;

lib/dsc-lib/src/dscresources/dscresource.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub struct DscResource {
5757
#[serde(rename="requireAdapter")]
5858
pub require_adapter: Option<FullyQualifiedTypeName>,
5959
/// The target resource for the resource adapter.
60-
pub target_resource: Option<String>,
60+
pub target_resource: Option<FullyQualifiedTypeName>,
6161
/// The manifest of the resource.
6262
pub manifest: Option<Value>,
6363
}
@@ -140,11 +140,11 @@ impl DscResource {
140140
Ok(configurator)
141141
}
142142

143-
fn invoke_get_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &str, filter: &str) -> Result<GetResult, DscError> {
143+
fn invoke_get_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &FullyQualifiedTypeName, filter: &str) -> Result<GetResult, DscError> {
144144
let mut configurator = self.clone().create_config_for_adapter(adapter, filter)?;
145145
let mut adapter = Self::get_adapter_resource(&mut configurator, adapter)?;
146146
if get_adapter_input_kind(&adapter)? == AdapterInputKind::Single {
147-
adapter.target_resource = Some(resource_name.to_string());
147+
adapter.target_resource = Some(resource_name.clone());
148148
return adapter.get(filter);
149149
}
150150

@@ -164,11 +164,11 @@ impl DscResource {
164164
Ok(get_result)
165165
}
166166

167-
fn invoke_set_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &str, desired: &str, skip_test: bool, execution_type: &ExecutionKind) -> Result<SetResult, DscError> {
167+
fn invoke_set_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &FullyQualifiedTypeName, desired: &str, skip_test: bool, execution_type: &ExecutionKind) -> Result<SetResult, DscError> {
168168
let mut configurator = self.clone().create_config_for_adapter(adapter, desired)?;
169169
let mut adapter = Self::get_adapter_resource(&mut configurator, adapter)?;
170170
if get_adapter_input_kind(&adapter)? == AdapterInputKind::Single {
171-
adapter.target_resource = Some(resource_name.to_string());
171+
adapter.target_resource = Some(resource_name.clone());
172172
return adapter.set(desired, skip_test, execution_type);
173173
}
174174

@@ -197,11 +197,11 @@ impl DscResource {
197197
Ok(set_result)
198198
}
199199

200-
fn invoke_test_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &str, expected: &str) -> Result<TestResult, DscError> {
200+
fn invoke_test_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &FullyQualifiedTypeName, expected: &str) -> Result<TestResult, DscError> {
201201
let mut configurator = self.clone().create_config_for_adapter(adapter, expected)?;
202202
let mut adapter = Self::get_adapter_resource(&mut configurator, adapter)?;
203203
if get_adapter_input_kind(&adapter)? == AdapterInputKind::Single {
204-
adapter.target_resource = Some(resource_name.to_string());
204+
adapter.target_resource = Some(resource_name.clone());
205205
return adapter.test(expected);
206206
}
207207

@@ -231,12 +231,12 @@ impl DscResource {
231231
Ok(test_result)
232232
}
233233

234-
fn invoke_delete_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &str, filter: &str) -> Result<(), DscError> {
234+
fn invoke_delete_with_adapter(&self, adapter: &FullyQualifiedTypeName, resource_name: &FullyQualifiedTypeName, filter: &str) -> Result<(), DscError> {
235235
let mut configurator = self.clone().create_config_for_adapter(adapter, filter)?;
236236
let mut adapter = Self::get_adapter_resource(&mut configurator, adapter)?;
237237
if get_adapter_input_kind(&adapter)? == AdapterInputKind::Single {
238238
if adapter.capabilities.contains(&Capability::Delete) {
239-
adapter.target_resource = Some(resource_name.to_string());
239+
adapter.target_resource = Some(resource_name.clone());
240240
return adapter.delete(filter);
241241
}
242242
return Err(DscError::NotSupported(t!("dscresources.dscresource.adapterDoesNotSupportDelete", adapter = adapter.type_name).to_string()));
@@ -250,7 +250,7 @@ impl DscResource {
250250
let mut configurator = self.clone().create_config_for_adapter(adapter, input)?;
251251
let mut adapter = Self::get_adapter_resource(&mut configurator, adapter)?;
252252
if get_adapter_input_kind(&adapter)? == AdapterInputKind::Single {
253-
adapter.target_resource = Some(self.type_name.to_string());
253+
adapter.target_resource = Some(self.type_name.clone());
254254
return adapter.export(input);
255255
}
256256

@@ -394,7 +394,7 @@ impl Invoke for DscResource {
394394
return Err(DscError::MissingManifest(self.type_name.to_string()));
395395
};
396396
let resource_manifest = import_manifest(manifest.clone())?;
397-
command_resource::invoke_get(&resource_manifest, &self.directory, filter, self.target_resource.as_deref())
397+
command_resource::invoke_get(&resource_manifest, &self.directory, filter, self.target_resource.clone())
398398
},
399399
}
400400
}
@@ -414,7 +414,7 @@ impl Invoke for DscResource {
414414
return Err(DscError::MissingManifest(self.type_name.to_string()));
415415
};
416416
let resource_manifest = import_manifest(manifest.clone())?;
417-
command_resource::invoke_set(&resource_manifest, &self.directory, desired, skip_test, execution_type, self.target_resource.as_deref())
417+
command_resource::invoke_set(&resource_manifest, &self.directory, desired, skip_test, execution_type, self.target_resource.clone())
418418
},
419419
}
420420
}
@@ -462,7 +462,7 @@ impl Invoke for DscResource {
462462
Ok(test_result)
463463
}
464464
else {
465-
command_resource::invoke_test(&resource_manifest, &self.directory, expected, self.target_resource.as_deref())
465+
command_resource::invoke_test(&resource_manifest, &self.directory, expected, self.target_resource.clone())
466466
}
467467
},
468468
}
@@ -538,7 +538,7 @@ impl Invoke for DscResource {
538538
return Err(DscError::MissingManifest(self.type_name.to_string()));
539539
};
540540
let resource_manifest = import_manifest(manifest.clone())?;
541-
command_resource::invoke_export(&resource_manifest, &self.directory, Some(input), self.target_resource.as_deref())
541+
command_resource::invoke_export(&resource_manifest, &self.directory, Some(input), self.target_resource.clone())
542542
}
543543

544544
fn resolve(&self, input: &str) -> Result<ResolveResult, DscError> {

tools/test_group_resource/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn main() {
2525
directory: PathBuf::from("test_directory"),
2626
author: Some("Microsoft".to_string()),
2727
properties: vec!["Property1".to_string(), "Property2".to_string()],
28-
require_adapter: Some("Test/TestGroup".to_string()),
28+
require_adapter: Some("Test/TestGroup".parse().unwrap()),
2929
target_resource: None,
3030
manifest: Some(serde_json::to_value(ResourceManifest {
3131
description: Some("This is a test resource.".to_string()),
@@ -51,7 +51,7 @@ fn main() {
5151
directory: PathBuf::from("test_directory"),
5252
author: Some("Microsoft".to_string()),
5353
properties: vec!["Property1".to_string(), "Property2".to_string()],
54-
require_adapter: Some("Test/TestGroup".to_string()),
54+
require_adapter: Some("Test/TestGroup".parse().unwrap()),
5555
target_resource: None,
5656
manifest: Some(serde_json::to_value(ResourceManifest {
5757
description: Some("This is a test resource.".to_string()),

0 commit comments

Comments
 (0)