diff --git a/dsc/tests/dsc_expressions.tests.ps1 b/dsc/tests/dsc_expressions.tests.ps1 index 11907a49..7b33366d 100644 --- a/dsc/tests/dsc_expressions.tests.ps1 +++ b/dsc/tests/dsc_expressions.tests.ps1 @@ -79,4 +79,32 @@ string. "@.Replace("`r", "") $out.results[1].result.actualState.output | Should -BeExactly "This is a single-quote: '" } + + It 'Nested Group resource does not invoke expressions' { + $yaml = @' +$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json +resources: +- name: Nested Group + type: Microsoft.DSC/Group + properties: + $schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json + resources: + - name: Deeply nested OSInfo + type: Microsoft/OSInfo + properties: {} + - name: Deeply nested echo + type: Microsoft.DSC.Debug/Echo + properties: + output: >- + [reference( + resourceId('Microsoft/OSInfo', 'Deeply nested OSInfo') + )] + dependsOn: + - "[resourceId('Microsoft/OSInfo', 'Deeply nested OSInfo')]" +'@ + + $out = dsc config get -i $yaml | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 + $out.results[0].result[1].result.actualState.output.family | Should -BeExactly $out.results[0].result[0].result.actualState.family + } } diff --git a/dsc_lib/src/configure/mod.rs b/dsc_lib/src/configure/mod.rs index 91fd5bc4..d2004873 100644 --- a/dsc_lib/src/configure/mod.rs +++ b/dsc_lib/src/configure/mod.rs @@ -232,6 +232,18 @@ impl Configurator { &self.config } + fn get_properties(&mut self, resource: &Resource, resource_kind: &Kind) -> Result>, DscError> { + match resource_kind { + Kind::Group => { + // if Group resource, we leave it to the resource to handle expressions + Ok(resource.properties.clone()) + }, + _ => { + Ok(self.invoke_property_expressions(resource.properties.as_ref())?) + }, + } + } + /// Invoke the get operation on a resource. /// /// # Returns @@ -245,13 +257,14 @@ impl Configurator { let mut result = ConfigurationGetResult::new(); let resources = get_resource_invocation_order(&self.config, &mut self.statement_parser, &self.context)?; let mut progress = ProgressBar::new(resources.len() as u64, self.progress_format)?; + let discovery = &self.discovery.clone(); for resource in resources { progress.set_resource(&resource.name, &resource.resource_type); progress.write_activity(format!("Get '{}'", resource.name).as_str()); - let properties = self.invoke_property_expressions(resource.properties.as_ref())?; - let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type) else { + let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else { return Err(DscError::ResourceNotFound(resource.resource_type)); }; + let properties = self.get_properties(&resource, &dsc_resource.kind)?; debug!("resource_type {}", &resource.resource_type); let filter = add_metadata(&dsc_resource.kind, properties)?; trace!("filter: {filter}"); @@ -322,13 +335,14 @@ impl Configurator { let mut result = ConfigurationSetResult::new(); let resources = get_resource_invocation_order(&self.config, &mut self.statement_parser, &self.context)?; let mut progress = ProgressBar::new(resources.len() as u64, self.progress_format)?; + let discovery = &self.discovery.clone(); for resource in resources { progress.set_resource(&resource.name, &resource.resource_type); progress.write_activity(format!("Set '{}'", resource.name).as_str()); - let properties = self.invoke_property_expressions(resource.properties.as_ref())?; - let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type) else { + let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else { return Err(DscError::ResourceNotFound(resource.resource_type)); }; + let properties = self.get_properties(&resource, &dsc_resource.kind)?; debug!("resource_type {}", &resource.resource_type); // see if the properties contains `_exist` and is false @@ -466,13 +480,14 @@ impl Configurator { let mut result = ConfigurationTestResult::new(); let resources = get_resource_invocation_order(&self.config, &mut self.statement_parser, &self.context)?; let mut progress = ProgressBar::new(resources.len() as u64, self.progress_format)?; + let discovery = &self.discovery.clone(); for resource in resources { progress.set_resource(&resource.name, &resource.resource_type); progress.write_activity(format!("Test '{}'", resource.name).as_str()); - let properties = self.invoke_property_expressions(resource.properties.as_ref())?; - let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type) else { + let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else { return Err(DscError::ResourceNotFound(resource.resource_type)); }; + let properties = self.get_properties(&resource, &dsc_resource.kind)?; debug!("resource_type {}", &resource.resource_type); let expected = add_metadata(&dsc_resource.kind, properties)?; trace!("{}", t!("configure.mod.expectedState", state = expected)); @@ -541,13 +556,14 @@ impl Configurator { let mut progress = ProgressBar::new(self.config.resources.len() as u64, self.progress_format)?; let resources = self.config.resources.clone(); + let discovery = &self.discovery.clone(); for resource in &resources { progress.set_resource(&resource.name, &resource.resource_type); progress.write_activity(format!("Export '{}'", resource.name).as_str()); - let properties = self.invoke_property_expressions(resource.properties.as_ref())?; - let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type) else { + let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else { return Err(DscError::ResourceNotFound(resource.resource_type.clone())); }; + let properties = self.get_properties(resource, &dsc_resource.kind)?; let input = add_metadata(&dsc_resource.kind, properties)?; trace!("{}", t!("configure.mod.exportInput", input = input)); let export_result = match add_resource_export_results_to_configuration(dsc_resource, Some(dsc_resource), &mut conf, input.as_str()) { diff --git a/dsc_lib/src/discovery/mod.rs b/dsc_lib/src/discovery/mod.rs index 17796999..edcc29ba 100644 --- a/dsc_lib/src/discovery/mod.rs +++ b/dsc_lib/src/discovery/mod.rs @@ -9,6 +9,7 @@ use crate::{dscresources::dscresource::DscResource, dscerror::DscError, progress use std::collections::BTreeMap; use tracing::error; +#[derive(Clone)] pub struct Discovery { pub resources: BTreeMap, }