Skip to content

Commit 21dc656

Browse files
committed
Add Bicep extension to enable passing bicep file directly to dsc
1 parent 7ef1714 commit 21dc656

File tree

18 files changed

+259
-40
lines changed

18 files changed

+259
-40
lines changed

build.ps1

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ if ($GetPackageVersion) {
4040
$filesForWindowsPackage = @(
4141
'appx.dsc.extension.json',
4242
'appx-discover.ps1',
43+
'bicep.dsc.extension.json',
4344
'dsc.exe',
4445
'dsc_default.settings.json',
4546
'dsc.settings.json',
@@ -75,6 +76,7 @@ $filesForWindowsPackage = @(
7576
)
7677

7778
$filesForLinuxPackage = @(
79+
'bicep.dsc.extension.json',
7880
'dsc',
7981
'dsc_default.settings.json',
8082
'dsc.settings.json'
@@ -99,6 +101,7 @@ $filesForLinuxPackage = @(
99101
)
100102

101103
$filesForMacPackage = @(
104+
'bicep.dsc.extension.json',
102105
'dsc',
103106
'dsc_default.settings.json',
104107
'dsc.settings.json'
@@ -305,6 +308,7 @@ if (!$SkipBuild) {
305308
"dsc_lib",
306309
"dsc",
307310
"dscecho",
311+
"extensions/bicep",
308312
"osinfo",
309313
"powershell-adapter",
310314
'resources/PSScript',
@@ -313,8 +317,7 @@ if (!$SkipBuild) {
313317
"sshdconfig",
314318
"tools/dsctest",
315319
"tools/test_group_resource",
316-
"y2j",
317-
"."
320+
"y2j"
318321
)
319322
$pedantic_unclean_projects = @()
320323
$clippy_unclean_projects = @("tree-sitter-dscexpression", "tree-sitter-ssh-server-config")

dsc/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dsc/examples/hello_world.dsc.bicep

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// This is a very simple example Bicep file for testing
2+
3+
targetScope = 'desiredStateConfiguration'
4+
5+
// use workaround where Bicep currently requires version in date format
6+
resource echo 'Microsoft.DSC.Debug/Echo@2025-01-01' = {
7+
name: 'exampleEcho'
8+
properties: {
9+
output: 'Hello, world!'
10+
}
11+
}

dsc/src/subcommand.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ pub fn validate_config(config: &Configuration, progress_format: ProgressFormat)
480480
let schema = serde_json::to_value(get_schema(SchemaType::Configuration))?;
481481
let config_value = serde_json::to_value(config)?;
482482
validate_json("Configuration", &schema, &config_value)?;
483-
let mut dsc = DscManager::new()?;
483+
let mut dsc = DscManager::new();
484484

485485
// then validate each resource
486486
let Some(resources) = config_value["resources"].as_array() else {
@@ -551,13 +551,7 @@ pub fn validate_config(config: &Configuration, progress_format: ProgressFormat)
551551
}
552552

553553
pub fn extension(subcommand: &ExtensionSubCommand, progress_format: ProgressFormat) {
554-
let mut dsc = match DscManager::new() {
555-
Ok(dsc) => dsc,
556-
Err(err) => {
557-
error!("Error: {err}");
558-
exit(EXIT_DSC_ERROR);
559-
}
560-
};
554+
let mut dsc = DscManager::new();
561555

562556
match subcommand {
563557
ExtensionSubCommand::List{extension_name, output_format} => {
@@ -577,13 +571,7 @@ pub fn function(subcommand: &FunctionSubCommand) {
577571

578572
#[allow(clippy::too_many_lines)]
579573
pub fn resource(subcommand: &ResourceSubCommand, progress_format: ProgressFormat) {
580-
let mut dsc = match DscManager::new() {
581-
Ok(dsc) => dsc,
582-
Err(err) => {
583-
error!("Error: {err}");
584-
exit(EXIT_DSC_ERROR);
585-
}
586-
};
574+
let mut dsc = DscManager::new();
587575

588576
match subcommand {
589577
ResourceSubCommand::List { resource_name, adapter_name, description, tags, output_format } => {

dsc/src/util.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33

44
use crate::args::{SchemaType, OutputFormat, TraceFormat};
55
use crate::resolve::Include;
6-
use dsc_lib::configure::config_result::ResourceTestResult;
7-
use dsc_lib::extensions::discover::DiscoverResult;
8-
use dsc_lib::extensions::extension_manifest::ExtensionManifest;
96
use dsc_lib::{
107
configure::{
118
config_doc::{
@@ -16,22 +13,33 @@ use dsc_lib::{
1613
config_result::{
1714
ConfigurationGetResult,
1815
ConfigurationSetResult,
19-
ConfigurationTestResult
20-
}
16+
ConfigurationTestResult,
17+
ResourceTestResult,
18+
},
2119
},
20+
discovery::Discovery,
2221
dscerror::DscError,
2322
dscresources::{
2423
command_resource::TraceLevel,
25-
dscresource::DscResource, invoke_result::{
24+
dscresource::DscResource,
25+
invoke_result::{
2626
GetResult,
2727
SetResult,
2828
TestResult,
2929
ResolveResult,
30-
}, resource_manifest::ResourceManifest
30+
},
31+
resource_manifest::ResourceManifest
32+
},
33+
extensions::{
34+
discover::DiscoverResult,
35+
dscextension::Capability,
36+
extension_manifest::ExtensionManifest,
3137
},
3238
functions::FunctionDefinition,
33-
util::parse_input_to_json,
34-
util::get_setting,
39+
util::{
40+
get_setting,
41+
parse_input_to_json,
42+
},
3543
};
3644
use jsonschema::Validator;
3745
use path_absolutize::Absolutize;
@@ -487,6 +495,14 @@ pub fn get_input(input: Option<&String>, file: Option<&String>, parameters_from_
487495
}
488496
}
489497
} else {
498+
// see if an extension should handle this file
499+
let mut discovery = Discovery::new();
500+
for extension in discovery.get_extensions(&Capability::Import) {
501+
let Ok(content) = extension.import(path) else {
502+
continue;
503+
};
504+
return content;
505+
}
490506
match std::fs::read_to_string(path) {
491507
Ok(input) => {
492508
// check if it contains UTF-8 BOM and remove it

dsc_lib/Cargo.lock

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dsc_lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ indicatif = "0.18"
2121
jsonschema = { version = "0.30", default-features = false }
2222
linked-hash-map = "0.5"
2323
num-traits = "0.2"
24+
path-absolutize = { version = "3.1" }
2425
regex = "1.11"
2526
rt-format = "0.3"
2627
rust-i18n = { version = "3.1" }

dsc_lib/locales/en-us.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ extensionResourceFound = "Extension found resource '%{resource}'"
9696
callingExtension = "Calling extension '%{extension}' to discover resources"
9797
extensionFoundResources = "Extension '%{extension}' found %{count} resources"
9898
invalidManifestVersion = "Manifest '%{path}' has invalid version: %{err}"
99+
importExtensionsEmpty = "Import extension '%{extension}' has no import extensions defined"
100+
importNotSupported = "Import is not supported by extension '%{extension}' for file '%{file}'"
99101

100102
[dscresources.commandResource]
101103
invokeGet = "Invoking get for '%{resource}'"
@@ -183,6 +185,7 @@ secretExtensionReturnedInvalidJson = "Extension '%{extension}' returned invalid
183185
extensionReturnedSecret = "Extension '%{extension}' returned secret"
184186
extensionReturnedNoSecret = "Extension '%{extension}' did not return a secret"
185187
secretNoResults = "Extension '%{extension}' returned no output"
188+
importingFile = "Importing file '%{file}' with extension '%{extension}'"
186189

187190
[extensions.extension_manifest]
188191
extensionManifestSchemaTitle = "Extension manifest schema URI"

dsc_lib/src/configure/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ impl Configurator {
266266
///
267267
/// This function will return an error if the configuration is invalid or the underlying discovery fails.
268268
pub fn new(json: &str, progress_format: ProgressFormat) -> Result<Configurator, DscError> {
269-
let discovery = Discovery::new()?;
269+
let discovery = Discovery::new();
270270
let mut config = Configurator {
271271
json: json.to_owned(),
272272
config: Configuration::new(),

dsc_lib/src/discovery/command_discovery.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,12 +726,25 @@ fn load_extension_manifest(path: &Path, manifest: &ExtensionManifest) -> Result<
726726
verify_executable(&manifest.r#type, "secret", &secret.executable);
727727
capabilities.push(dscextension::Capability::Secret);
728728
}
729+
let import_extensions = if let Some(import) = &manifest.import {
730+
verify_executable(&manifest.r#type, "import", &import.executable);
731+
capabilities.push(dscextension::Capability::Import);
732+
if import.extensions.is_empty() {
733+
warn!("{}", t!("discovery.commandDiscovery.importExtensionsEmpty", extension = manifest.r#type));
734+
None
735+
} else {
736+
Some(import.extensions.clone())
737+
}
738+
} else {
739+
None
740+
};
729741

730742
let extension = DscExtension {
731743
type_name: manifest.r#type.clone(),
732744
description: manifest.description.clone(),
733745
version: manifest.version.clone(),
734746
capabilities,
747+
import_extensions,
735748
path: path.to_str().unwrap().to_string(),
736749
directory: path.parent().unwrap().to_str().unwrap().to_string(),
737750
manifest: serde_json::to_value(manifest)?,

0 commit comments

Comments
 (0)