Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions dsc/tests/dsc_discovery.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,31 @@ Describe 'tests for resource discovery' {
$traceLog | Should -Match "Skipping resource discovery due to 'resourceDiscovery' mode set to 'DuringDeployment'"
}
}

It 'Invalid resource manifest will generate info message' {
$invalidManifest = @'
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Test/InvalidManifest",
"version": "0.1.0",
"get": {
"executable": "dsctest",
"unexpectedField": "This field is not expected in the get section and should be ignored by the discovery process"
},
"newProperty": "This property is not expected in the manifest and should be ignored by the discovery process"
}
'@
Set-Content -Path "$testdrive/test.dsc.resource.json" -Value $invalidManifest
try {
$env:DSC_RESOURCE_PATH = $testdrive + [System.IO.Path]::PathSeparator + $env:PATH

$out = dsc -l info resource list 'Test/InvalidManifest' 2> "$testdrive/error.txt" | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out | Should -BeNullOrEmpty -Because (Get-Content -Raw -Path "$testdrive/error.txt")
$errorLog = Get-Content -Raw -Path "$testdrive/error.txt"
$errorLog | Should -BeLike "*INFO Failed to load manifest: Invalid manifest for resource '*test.dsc.resource.json'*" -Because $errorLog
} finally {
$env:DSC_RESOURCE_PATH = $null
}
}
}
57 changes: 57 additions & 0 deletions dsc/tests/dsc_extension_discover.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,61 @@ Describe 'Discover extension tests' {
$env:DSC_RESOURCE_PATH = $null
}
}

It 'Invalid manifest from extension discovery should not fail overall discovery' {
$invalidManifest = @'
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Test/InvalidManifest",
"version": "0.1.0",
"get": {
"executable": "dsctest",
"unexpectedField": "This field is not expected in the get section and should be ignored by the discovery process"
},
"newProperty": "This property is not expected in the manifest and should be ignored by the discovery process"
}
'@
$resourceScript = @'
$resource = @{
manifestPath = "$env:TestDrive" + [System.IO.Path]::DirectorySeparatorChar + 'invalidManifest.dsc.resource.json'
}
$resource | ConvertTo-Json -Compress
'@
$extensionManifest = @'
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Test/DiscoverInvalid",
"version": "0.1.0",
"description": "Test discover resource, this is a really long description to test that the table can be rendered without truncating the description text from this extension.",
"discover": {
"executable": "pwsh",
"args": [
"-NoLogo",
"-NonInteractive",
"-NoProfile",
"-Command",
"./discover.ps1"
]
}
}
'@

Set-Content -Path "$TestDrive/invalidManifest.dsc.resource.json" -Value $invalidManifest
Set-Content -Path "$TestDrive/discover.ps1" -Value $resourceScript
Set-Content -Path "$TestDrive/extension.dsc.extension.json" -Value $extensionManifest
try {
$env:DSC_RESOURCE_PATH = $TestDrive + [System.IO.Path]::PathSeparator + $env:PATH
$env:TestDrive = $TestDrive
$out = dsc -l info resource list 2> $TestDrive/error.log | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0 -Because (Get-Content -Path "$TestDrive/error.log" -Raw | Out-String)
# The invalid manifest should be skipped and not included in the discovered resources
foreach ($resource in $out) {
$resource.type | Should -Not -Be 'Test/InvalidManifest'
}
(Get-Content -Path "$TestDrive/error.log" -Raw) | Should -BeLike "*INFO Extension 'Test/DiscoverInvalid' failed to load manifest: Invalid manifest for resource '*invalidManifest.dsc.resource.json'*" -Because (Get-Content -Path "$TestDrive/error.log" -Raw | Out-String)
} finally {
$env:DSC_RESOURCE_PATH = $null
$env:TestDrive = $null
}
}
}
2 changes: 2 additions & 0 deletions lib/dsc-lib/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ conditionNotBoolean = "Condition '%{condition}' did not evaluate to a boolean"
conditionNotMet = "Condition '%{condition}' not met, skipping manifest at '%{path}' for resource '%{resource}'"
adaptedResourcePathNotFound = "Adapted resource '%{resource}' path not found: %{path}"
invalidManifestFileName = "Invalid manifest file name '%{path}'"
failedLoadManifest = "Failed to load manifest: %{err}"

[dscresources.commandResource]
invokeGet = "Invoking get for '%{resource}'"
Expand Down Expand Up @@ -252,6 +253,7 @@ importNoResults = "Extension '%{extension}' returned no results for import"
secretMultipleLinesReturned = "Extension '%{extension}' returned multiple lines which is not supported for secrets"
importProcessingOutput = "Processing output from extension '%{extension}'"
deprecationMessage = "Extension '%{extension}' is deprecated: %{message}"
failedLoadManifest = "Extension '%{extension}' failed to load manifest: %{err}"

[extensions.extension_manifest]
extensionManifestSchemaTitle = "Extension manifest schema URI"
Expand Down
4 changes: 2 additions & 2 deletions lib/dsc-lib/src/discovery/command_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ impl ResourceDiscovery for CommandDiscovery {
// At this point we can't determine whether or not the bad manifest contains
// resource that is requested by resource/config operation
// if it is, then "ResouceNotFound" error will be issued later
// and here we just write as warning
warn!("{e}");
// and here we just write as info
info!("{}", t!("discovery.commandDiscovery.failedLoadManifest", err = e));
continue;
},
};
Expand Down
9 changes: 8 additions & 1 deletion lib/dsc-lib/src/extensions/discover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,14 @@ impl DscExtension {
return Err(DscError::Extension(t!("extensions.dscextension.discoverNotAbsolutePath", extension = self.type_name.clone(), path = discover_result.manifest_path.display()).to_string()));
}
// Currently we don't support extensions discovering other extensions
for imported_manifest in load_manifest(&discover_result.manifest_path)? {
let manifests = match load_manifest(&discover_result.manifest_path) {
Ok(manifests) => manifests,
Err(err) => {
info!("{}", t!("extensions.dscextension.failedLoadManifest", extension = self.type_name, err = err));
continue;
}
};
for imported_manifest in manifests {
if let ImportedManifest::Resource(resource) = imported_manifest {
resources.push(resource);
}
Expand Down
Loading