Skip to content

Commit ab4ab4e

Browse files
committed
fix: Short-circuit adapter discovery when a native resource type has no matching version
1 parent 4cb6706 commit ab4ab4e

3 files changed

Lines changed: 57 additions & 2 deletions

File tree

dsc/tests/dsc_config_version.tests.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,26 @@ Describe 'Tests for resource versioning' {
9191
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
9292
$out.results[0].result.actualState.version | Should -BeExactly '1.1.2'
9393
}
94+
95+
It 'Skips adapter discovery when a native resource type version requirement cannot be satisfied' {
96+
$config_yaml = @"
97+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
98+
resources:
99+
- name: Test Version
100+
type: Test/Version
101+
requireVersion: '=99.0.0'
102+
properties:
103+
version: '99.0.0'
104+
"@
105+
$out = dsc -l trace config get -i $config_yaml 2> $TestDrive/error.log
106+
$LASTEXITCODE | Should -Not -Be 0
107+
108+
$traces = Get-Content $TestDrive/error.log -Raw
109+
110+
$traces | Should -Match "Skipping adapter search for resource 'Test/Version'"
111+
$traces | Should -Not -Match 'Searching for adapted resources'
112+
$traces | Should -Not -Match 'Enumerating resources for adapter'
113+
$traces | Should -Match "Test/Version"
114+
$traces | Should -Match "=99.0.0"
115+
}
94116
}

lib/dsc-lib/locales/en-us.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ importExtensionsEmpty = "Import extension '%{extension}' has no import extension
132132
searchingForResources = "Searching for resources: %{resources}"
133133
foundResourceWithVersion = "Found matching resource '%{resource}' version %{version}"
134134
foundNonAdapterResources = "Found %{count} non-adapter resources"
135+
skipAdapterSearchForNativeType = "Skipping adapter search for resource '%{resource}': type is registered as a native command-based resource; version requirement does not match any installed version"
135136
resourceMissingRequireAdapter = "Resource '%{resource}' is missing 'require_adapter' field."
136137
extensionDiscoverFailed = "Extension '%{extension}' failed to discover resources: %{error}"
137138
conditionNotBoolean = "Condition '%{condition}' did not evaluate to a boolean"

lib/dsc-lib/src/discovery/command_discovery.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,11 +504,43 @@ impl ResourceDiscovery for CommandDiscovery {
504504
return Ok(found_resources);
505505
}
506506

507+
// Determine which still-unsatisfied filters actually require adapter discovery.
508+
//
509+
// If a filter's resource type is already known to native discovery (present in
510+
// RESOURCES or ADAPTERS) and the user did not pin an adapter via `requireAdapter`,
511+
// then any unsatisfied state is necessarily a version-requirement mismatch
512+
let adapter_filter_candidates: Vec<&DiscoveryFilter> = required_resource_types
513+
.iter()
514+
.filter(|filter| {
515+
if required_resources.get(*filter).copied().unwrap_or(false) {
516+
return false;
517+
}
518+
if filter.require_adapter().is_some() {
519+
return true;
520+
}
521+
let type_known_natively = locked_get!(RESOURCES, filter.resource_type()).is_some()
522+
|| locked_get!(ADAPTERS, filter.resource_type()).is_some();
523+
if type_known_natively {
524+
debug!(
525+
"{}",
526+
t!("discovery.commandDiscovery.skipAdapterSearchForNativeType",
527+
resource = filter.resource_type())
528+
);
529+
return false;
530+
}
531+
true
532+
})
533+
.collect();
534+
535+
if adapter_filter_candidates.is_empty() {
536+
return Ok(found_resources);
537+
}
538+
507539
// store the keys of the ADAPTERS into a vec
508540
let mut adapters: Vec<FullyQualifiedTypeName> = locked_clone!(ADAPTERS).keys().cloned().collect();
509541
// sort the adapters by ones specified in the required resources first
510542

511-
for filter in required_resource_types {
543+
for filter in &adapter_filter_candidates {
512544
if let Some(required_adapter) = filter.require_adapter() {
513545
if !adapters.contains(required_adapter) {
514546
return Err(DscError::AdapterNotFound(required_adapter.to_string()));
@@ -522,7 +554,7 @@ impl ResourceDiscovery for CommandDiscovery {
522554
for adapter_name in &adapters {
523555
self.discover_adapted_resources(&TypeNameFilter::default(), &adapter_name.clone().into())?;
524556
add_resources_to_lookup_table(&locked_clone!(ADAPTED_RESOURCES));
525-
for filter in required_resource_types {
557+
for filter in &adapter_filter_candidates {
526558
if let Some(adapted_resources) = locked_get!(ADAPTED_RESOURCES, filter.resource_type()) {
527559
filter_resources(&mut found_resources, &mut required_resources, &adapted_resources, filter);
528560
}

0 commit comments

Comments
 (0)