Skip to content

Commit 5affd98

Browse files
authored
Merge pull request #978 from SteveL-MSFT/resource-condition
Add `condition` support to resources within config
2 parents a711158 + cf73de3 commit 5affd98

File tree

5 files changed

+81
-0
lines changed

5 files changed

+81
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
Describe 'Resource condition tests' {
5+
BeforeAll {
6+
$configYaml = @'
7+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
8+
resources:
9+
- name: test
10+
type: Microsoft.DSC.Debug/Echo
11+
condition: "[equals('skip', 'yes')]"
12+
properties:
13+
output: "This should not be executed"
14+
- name: test2
15+
type: Microsoft.DSC.Debug/Echo
16+
condition: "[equals('no', 'no')]"
17+
properties:
18+
output: "This should be executed"
19+
'@
20+
}
21+
22+
It 'resource should be skipped for <operation>' -TestCases @(
23+
@{ operation = 'get'; property = 'actualState' },
24+
@{ operation = 'set'; property = 'afterState' },
25+
@{ operation = 'test'; property = 'actualState' }
26+
) {
27+
param($operation, $property)
28+
$out = dsc config $operation -i $configYaml 2>$TestDrive/error.log | ConvertFrom-Json
29+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw | Out-String)
30+
$out.results.count | Should -Be 1
31+
$out.results[0].result.$property.Output | Should -BeExactly "This should be executed"
32+
}
33+
34+
It 'resource should be skipped for export' {
35+
$out = dsc config export -i $configYaml 2>$TestDrive/error.log | ConvertFrom-Json
36+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw | Out-String)
37+
$out.resources.count | Should -Be 1
38+
$out.resources[0].type | Should -BeExactly 'Microsoft.DSC.Debug/Echo'
39+
$out.resources[0].properties.output | Should -BeExactly "This should be executed"
40+
}
41+
}

dsc_lib/locales/en-us.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ _version = 1
33
[configure.config_doc]
44
configurationDocumentSchemaTitle = "Configuration document schema URI"
55
configurationDocumentSchemaDescription = "Defines the JSON Schema the configuration document adheres to."
6+
skippingResource = "Skipping resource '%{name}' due to condition '%{condition}' with result '%{result}'"
67

78
[configure.constraints]
89
minLengthIsNull = "Parameter '%{name}' has minimum length constraint but is null"

dsc_lib/src/configure/config_doc.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ pub struct Resource {
160160
pub properties: Option<Map<String, Value>>,
161161
#[serde(skip_serializing_if = "Option::is_none")]
162162
pub metadata: Option<Metadata>,
163+
#[serde(skip_serializing_if = "Option::is_none")]
164+
pub condition: Option<String>,
163165
}
164166

165167
impl Default for Configuration {
@@ -217,6 +219,7 @@ impl Resource {
217219
kind: None,
218220
properties: None,
219221
metadata: None,
222+
condition: None,
220223
}
221224
}
222225
}

dsc_lib/src/configure/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ impl Configurator {
311311
for resource in resources {
312312
progress.set_resource(&resource.name, &resource.resource_type);
313313
progress.write_activity(format!("Get '{}'", resource.name).as_str());
314+
if self.skip_resource(&resource)? {
315+
progress.write_increment(1);
316+
continue;
317+
}
314318
let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else {
315319
return Err(DscError::ResourceNotFound(resource.resource_type));
316320
};
@@ -387,6 +391,10 @@ impl Configurator {
387391
for resource in resources {
388392
progress.set_resource(&resource.name, &resource.resource_type);
389393
progress.write_activity(format!("Set '{}'", resource.name).as_str());
394+
if self.skip_resource(&resource)? {
395+
progress.write_increment(1);
396+
continue;
397+
}
390398
let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else {
391399
return Err(DscError::ResourceNotFound(resource.resource_type));
392400
};
@@ -535,6 +543,10 @@ impl Configurator {
535543
for resource in resources {
536544
progress.set_resource(&resource.name, &resource.resource_type);
537545
progress.write_activity(format!("Test '{}'", resource.name).as_str());
546+
if self.skip_resource(&resource)? {
547+
progress.write_increment(1);
548+
continue;
549+
}
538550
let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else {
539551
return Err(DscError::ResourceNotFound(resource.resource_type));
540552
};
@@ -608,6 +620,10 @@ impl Configurator {
608620
for resource in &resources {
609621
progress.set_resource(&resource.name, &resource.resource_type);
610622
progress.write_activity(format!("Export '{}'", resource.name).as_str());
623+
if self.skip_resource(resource)? {
624+
progress.write_increment(1);
625+
continue;
626+
}
611627
let Some(dsc_resource) = discovery.find_resource(&resource.resource_type) else {
612628
return Err(DscError::ResourceNotFound(resource.resource_type.clone()));
613629
};
@@ -642,6 +658,17 @@ impl Configurator {
642658
Ok(result)
643659
}
644660

661+
fn skip_resource(&mut self, resource: &Resource) -> Result<bool, DscError> {
662+
if let Some(condition) = &resource.condition {
663+
let condition_result = self.statement_parser.parse_and_execute(condition, &self.context)?;
664+
if condition_result != Value::Bool(true) {
665+
info!("{}", t!("configure.config_doc.skippingResource", name = resource.name, condition = condition, result = condition_result));
666+
return Ok(true);
667+
}
668+
}
669+
Ok(false)
670+
}
671+
645672
/// Set the mounted path for the configuration.
646673
///
647674
/// # Arguments

dscecho/echo.dsc.resource.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@
3030
}
3131
]
3232
},
33+
"export": {
34+
"executable": "dscecho",
35+
"args": [
36+
{
37+
"jsonInputArg": "--input",
38+
"mandatory": true
39+
}
40+
]
41+
},
3342
"schema": {
3443
"command": {
3544
"executable": "dscecho"

0 commit comments

Comments
 (0)