Skip to content

Commit fa41d0a

Browse files
author
Andrew
authored
Merge branch 'main' into issue_592
2 parents 92ea9fb + e5ff855 commit fa41d0a

File tree

5 files changed

+238
-61
lines changed

5 files changed

+238
-61
lines changed

dsc/examples/osinfo.parameters.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"parameters": {
3+
"osFamily": "macOS"
4+
}
5+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json",
3+
"parameters": {
4+
"osFamily": {
5+
"type": "string",
6+
"defaultValue": "[concat('Win','dows')]",
7+
"allowedValues": [
8+
"Windows",
9+
"Linux",
10+
"macOS"
11+
]
12+
}
13+
},
14+
"resources": [
15+
{
16+
"name": "os",
17+
"type": "Microsoft/OSInfo",
18+
"properties": {
19+
"family": "[parameters('osFamily')]"
20+
}
21+
},
22+
{
23+
"name": "another os instance",
24+
"type": "Microsoft/OSInfo",
25+
"properties": {
26+
"family": "macOS"
27+
}
28+
},
29+
{
30+
"name": "path",
31+
"type": "Microsoft.DSC.Debug/Echo",
32+
"properties": {
33+
"output": "[envvar('PATH')]"
34+
}
35+
}
36+
]
37+
}

dsc/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn ctrlc_handler() {
104104

105105
fn terminate_subprocesses(sys: &System, process: &Process) {
106106
info!("{}: {:?} {}", t!("main.terminatingSubprocess"), process.name(), process.pid());
107-
for subprocess in sys.processes().values().filter(|p| p.parent().map_or(false, |parent| parent == process.pid())) {
107+
for subprocess in sys.processes().values().filter(|p| p.parent().is_some_and(|parent| parent == process.pid())) {
108108
terminate_subprocesses(sys, subprocess);
109109
}
110110

@@ -159,7 +159,7 @@ fn check_store() {
159159
};
160160

161161
// MS Store runs app using `sihost.exe`
162-
if parent_process.name().to_ascii_lowercase() == "sihost.exe" || parent_process.name().to_ascii_lowercase() == "explorer.exe"{
162+
if parent_process.name().eq_ignore_ascii_case("sihost.exe") || parent_process.name().eq_ignore_ascii_case("explorer.exe") {
163163
eprintln!("{}", t!("main.storeMessage"));
164164
// wait for keypress
165165
let _ = io::stdin().read(&mut [0u8]).unwrap();

dsc/src/resolve.rs

Lines changed: 82 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
use dsc_lib::configure::config_doc::Configuration;
54
use dsc_lib::util::parse_input_to_json;
65
use rust_i18n::t;
76
use schemars::JsonSchema;
@@ -14,14 +13,30 @@ use tracing::{debug, info};
1413
use crate::util::DSC_CONFIG_ROOT;
1514

1615
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
17-
pub struct Include {
16+
pub enum IncludeKind {
1817
/// The path to the file to include. Path is relative to the file containing the include
1918
/// and not allowed to reference parent directories. If a configuration document is used
2019
/// instead of a file, then the path is relative to the current working directory.
2120
#[serde(rename = "configurationFile")]
22-
pub configuration_file: String,
21+
ConfigurationFile(String),
22+
#[serde(rename = "configurationContent")]
23+
ConfigurationContent(String),
24+
}
25+
26+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
27+
pub enum IncludeParametersKind {
2328
#[serde(rename = "parametersFile")]
24-
pub parameters_file: Option<String>,
29+
ParametersFile(String),
30+
#[serde(rename = "parametersContent")]
31+
ParametersContent(String),
32+
}
33+
34+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
35+
pub struct Include {
36+
#[serde(flatten)]
37+
pub configuration: IncludeKind,
38+
#[serde(flatten)]
39+
pub parameters: Option<IncludeParametersKind>,
2540
}
2641

2742
/// Read the file specified in the Include input and return the content as a JSON string.
@@ -51,74 +66,83 @@ pub fn get_contents(input: &str) -> Result<(Option<String>, String), String> {
5166
}
5267
};
5368

54-
let include_path = normalize_path(Path::new(&include.configuration_file))?;
69+
let config_json = match include.configuration {
70+
IncludeKind::ConfigurationFile(file_path) => {
71+
let include_path = normalize_path(Path::new(&file_path))?;
5572

56-
// read the file specified in the Include input
57-
let mut buffer: Vec<u8> = Vec::new();
58-
match File::open(&include_path) {
59-
Ok(mut file) => {
60-
match file.read_to_end(&mut buffer) {
61-
Ok(_) => (),
73+
// read the file specified in the Include input
74+
let mut buffer: Vec<u8> = Vec::new();
75+
match File::open(&include_path) {
76+
Ok(mut file) => {
77+
match file.read_to_end(&mut buffer) {
78+
Ok(_) => (),
79+
Err(err) => {
80+
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.failedToReadFile")));
81+
}
82+
}
83+
},
6284
Err(err) => {
63-
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.failedToReadFile")));
85+
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.failedToOpenFile")));
6486
}
6587
}
66-
},
67-
Err(err) => {
68-
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.failedToOpenFile")));
69-
}
70-
}
71-
// convert the buffer to a string
72-
let include_content = match String::from_utf8(buffer) {
73-
Ok(input) => input,
74-
Err(err) => {
75-
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.invalidFileContent")));
76-
}
77-
};
88+
// convert the buffer to a string
89+
let include_content = match String::from_utf8(buffer) {
90+
Ok(input) => input,
91+
Err(err) => {
92+
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.invalidFileContent")));
93+
}
94+
};
7895

79-
// try to deserialize the Include content as YAML first
80-
let configuration: Configuration = match serde_yaml::from_str(&include_content) {
81-
Ok(configuration) => configuration,
82-
Err(_err) => {
83-
// if that fails, try to deserialize it as JSON
84-
match serde_json::from_str(&include_content) {
85-
Ok(configuration) => configuration,
96+
match parse_input_to_json(&include_content) {
97+
Ok(json) => json,
8698
Err(err) => {
8799
return Err(format!("{} '{include_path:?}': {err}", t!("resolve.invalidFile")));
88100
}
89101
}
102+
},
103+
IncludeKind::ConfigurationContent(text) => {
104+
match parse_input_to_json(&text) {
105+
Ok(json) => json,
106+
Err(err) => {
107+
return Err(format!("{}: {err}", t!("resolve.invalidFile")));
108+
}
109+
}
90110
}
91111
};
92112

93-
// serialize the Configuration as JSON
94-
let config_json = match serde_json::to_string(&configuration) {
95-
Ok(json) => json,
96-
Err(err) => {
97-
return Err(format!("JSON: {err}"));
98-
}
99-
};
100-
101-
let parameters = if let Some(parameters_file) = include.parameters_file {
102-
// combine the path with DSC_CONFIG_ROOT
103-
let parameters_file = normalize_path(Path::new(&parameters_file))?;
104-
info!("{} '{parameters_file:?}'", t!("resolve.resolvingParameters"));
105-
match std::fs::read_to_string(&parameters_file) {
106-
Ok(parameters) => {
107-
let parameters_json = match parse_input_to_json(&parameters) {
108-
Ok(json) => json,
109-
Err(err) => {
110-
return Err(format!("{} '{parameters_file:?}': {err}", t!("resolve.failedParseParametersFile")));
111-
}
112-
};
113-
Some(parameters_json)
114-
},
115-
Err(err) => {
116-
return Err(format!("{} '{parameters_file:?}': {err}", t!("resolve.failedResolveParametersFile")));
113+
let parameters = match include.parameters {
114+
Some(IncludeParametersKind::ParametersFile(file_path)) => {
115+
// combine the path with DSC_CONFIG_ROOT
116+
let parameters_file = normalize_path(Path::new(&file_path))?;
117+
info!("{} '{parameters_file:?}'", t!("resolve.resolvingParameters"));
118+
match std::fs::read_to_string(&parameters_file) {
119+
Ok(parameters) => {
120+
let parameters_json = match parse_input_to_json(&parameters) {
121+
Ok(json) => json,
122+
Err(err) => {
123+
return Err(format!("{} '{parameters_file:?}': {err}", t!("resolve.failedParseParametersFile")));
124+
}
125+
};
126+
Some(parameters_json)
127+
},
128+
Err(err) => {
129+
return Err(format!("{} '{parameters_file:?}': {err}", t!("resolve.failedResolveParametersFile")));
130+
}
117131
}
132+
},
133+
Some(IncludeParametersKind::ParametersContent(text)) => {
134+
let parameters_json = match parse_input_to_json(&text) {
135+
Ok(json) => json,
136+
Err(err) => {
137+
return Err(format!("{}: {err}", t!("resolve.invalidParametersContent")));
138+
}
139+
};
140+
Some(parameters_json)
141+
},
142+
None => {
143+
debug!("{}", t!("resolve.noParameters"));
144+
None
118145
}
119-
} else {
120-
debug!("{}", t!("resolve.noParametersFile"));
121-
None
122146
};
123147

124148
Ok((parameters, config_json))

dsc/tests/dsc_include.tests.ps1

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,34 @@ Describe 'Include tests' {
1212
$logPath = Join-Path $TestDrive 'stderr.log'
1313
}
1414

15-
It 'Include config with default parameters' {
15+
It 'Include invalid config file' {
16+
$invalidConfig = @"
17+
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
18+
properties:
19+
- name: osinfo
20+
type: Microsoft.DSC/Include
21+
properties:
22+
configurationFile: include/non-existing.dsc.yaml
23+
"@
24+
25+
$invalidConfigPath = Join-Path $TestDrive 'invalid_config.dsc.yaml'
26+
$invalidConfig | Set-Content -Path $invalidConfigPath
27+
28+
$config = @"
29+
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
30+
resources:
31+
- name: osinfo
32+
type: Microsoft.DSC/Include
33+
properties:
34+
configurationFile: $invalidConfigPath
35+
"@
36+
$configPath = Join-Path $TestDrive 'config.dsc.yaml'
37+
$config | Set-Content -Path $configPath
38+
dsc config get -f $configPath
39+
$LASTEXITCODE | Should -Be 2
40+
}
41+
42+
It 'Include config file with default parameters' {
1643
$config = @"
1744
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
1845
resources:
@@ -35,6 +62,63 @@ Describe 'Include tests' {
3562
$out.results[0].result[0].result.actualState.family | Should -Be $expectedOS
3663
}
3764

65+
It 'Include config YAML content with default parameters' {
66+
# since this is YAML, we need to ensure correct indentation
67+
$includeContent = (Get-Content $osinfoConfigPath -Raw).Replace("`n", "`n" + (' ' * 20))
68+
69+
$config = @"
70+
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
71+
resources:
72+
- name: osinfo
73+
type: Microsoft.DSC/Include
74+
properties:
75+
configurationContent: |
76+
$includeContent
77+
"@
78+
79+
$configPath = Join-Path $TestDrive 'config.dsc.yaml'
80+
$config | Set-Content -Path $configPath
81+
$out = dsc config get -f $configPath | ConvertFrom-Json
82+
$LASTEXITCODE | Should -Be 0
83+
if ($IsWindows) {
84+
$expectedOS = 'Windows'
85+
} elseif ($IsLinux) {
86+
$expectedOS = 'Linux'
87+
} else {
88+
$expectedOS = 'macOS'
89+
}
90+
$out.results[0].result[0].result.actualState.family | Should -Be $expectedOS
91+
}
92+
93+
It 'Include config JSON content with default parameters' {
94+
$osinfoJsonPath = Join-Path $PSScriptRoot '../examples/osinfo_parameters.dsc.json'
95+
96+
# for JSON, we can just have it as a single line
97+
$includeContent = (Get-Content $osinfoJsonPath -Raw).Replace("`n", "").Replace('"', '\"')
98+
99+
$config = @"
100+
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
101+
resources:
102+
- name: osinfo
103+
type: Microsoft.DSC/Include
104+
properties:
105+
configurationContent: "$includeContent"
106+
"@
107+
108+
$configPath = Join-Path $TestDrive 'config.dsc.yaml'
109+
$config | Set-Content -Path $configPath
110+
$out = dsc config get -f $configPath | ConvertFrom-Json
111+
$LASTEXITCODE | Should -Be 0
112+
if ($IsWindows) {
113+
$expectedOS = 'Windows'
114+
} elseif ($IsLinux) {
115+
$expectedOS = 'Linux'
116+
} else {
117+
$expectedOS = 'macOS'
118+
}
119+
$out.results[0].result[0].result.actualState.family | Should -Be $expectedOS
120+
}
121+
38122
It 'Include config with parameters file' {
39123
$config = @"
40124
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
@@ -59,6 +143,33 @@ Describe 'Include tests' {
59143
$out.results[0].result[0].result.actualState.family | Should -Be $expectedOS
60144
}
61145

146+
It 'Include config with parameters content' {
147+
$parametersContentFile = Join-Path $PSScriptRoot '../examples/osinfo.parameters.json'
148+
$parametersContent = (Get-Content $parametersContentFile -Raw).Replace("`n", "").Replace('"', '\"')
149+
150+
$config = @"
151+
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
152+
resources:
153+
- name: osinfo
154+
type: Microsoft.DSC/Include
155+
properties:
156+
configurationFile: include/osinfo_parameters.dsc.yaml
157+
parametersContent: "$parametersContent"
158+
"@
159+
$configPath = Join-Path $TestDrive 'config.dsc.yaml'
160+
$config | Set-Content -Path $configPath
161+
$out = dsc config get -f $configPath | ConvertFrom-Json
162+
$LASTEXITCODE | Should -Be 0
163+
if ($IsWindows) {
164+
$expectedOS = 'Windows'
165+
} elseif ($IsLinux) {
166+
$expectedOS = 'Linux'
167+
} else {
168+
$expectedOS = 'macOS'
169+
}
170+
$out.results[0].result[0].result.actualState.family | Should -Be $expectedOS
171+
}
172+
62173
It 'Invalid file path: <test>' -TestCases @(
63174
@{ test = 'non-existing configuration'; config = 'include/non-existing.dsc.yaml'; parameters = $null }
64175
@{ test = 'non-existing parameters'; config = 'include/osinfo_parameters.dsc.yaml'; parameters = 'include/non-existing.parameters.yaml' }

0 commit comments

Comments
 (0)