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
50 changes: 50 additions & 0 deletions dsc/tests/dsc_metadata.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,56 @@
# Licensed under the MIT License.

Describe 'metadata tests' {
It 'resource can provide high-level metadata for <operation>' -TestCases @(
@{ operation = 'get' }
@{ operation = 'set' }
@{ operation = 'test' }
) {
param($operation)

$configYaml = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: test
type: Test/Metadata
metadata:
hello: world
myNumber: 42
properties:
'@

$out = dsc config $operation -i $configYaml 2>$TestDrive/error.log | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.results.count | Should -Be 1
$out.results[0].metadata.hello | Should -BeExactly 'world'
$out.results[0].metadata.myNumber | Should -Be 42
}

It 'resource can provide high-level metadata for export' {
$configYaml = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: test
type: Test/Metadata
metadata:
hello: There
myNumber: 16
properties:
'@
$out = dsc config export -i $configYaml 2>$TestDrive/error.log | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.resources.count | Should -Be 3
$out.resources[0].metadata.hello | Should -BeExactly 'There'
$out.resources[0].metadata.myNumber | Should -Be 16
$out.resources[0].name | Should -BeExactly 'Metadata example 1'
$out.resources[1].metadata.hello | Should -BeExactly 'There'
$out.resources[1].metadata.myNumber | Should -Be 16
$out.resources[1].name | Should -BeExactly 'Metadata example 2'
$out.resources[2].metadata.hello | Should -BeExactly 'There'
$out.resources[2].metadata.myNumber | Should -Be 16
$out.resources[2].name | Should -BeExactly 'Metadata example 3'
}

It 'resource can provide metadata for <operation>' -TestCases @(
@{ operation = 'get' }
@{ operation = 'set' }
Expand Down
29 changes: 23 additions & 6 deletions dsc_lib/src/configure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,15 @@ fn escape_property_values(properties: &Map<String, Value>) -> Result<Option<Map<
Ok(Some(result))
}

fn add_metadata(kind: &Kind, mut properties: Option<Map<String, Value>> ) -> Result<String, DscError> {
fn add_metadata(kind: &Kind, mut properties: Option<Map<String, Value>>, resource_metadata: Option<Metadata> ) -> Result<String, DscError> {
if *kind == Kind::Adapter {
// add metadata to the properties so the adapter knows this is a config
let mut metadata = Map::new();
let mut metadata: Map<String, Value> = Map::new();
if let Some(resource_metadata) = resource_metadata {
if !resource_metadata.other.is_empty() {
metadata.extend(resource_metadata.other);
}
}
let mut dsc_value = Map::new();
dsc_value.insert("context".to_string(), Value::String("configuration".to_string()));
metadata.insert("Microsoft.DSC".to_string(), Value::Object(dsc_value));
Expand All @@ -185,6 +190,18 @@ fn add_metadata(kind: &Kind, mut properties: Option<Map<String, Value>> ) -> Res
return Ok(serde_json::to_string(&properties)?);
}

if let Some(resource_metadata) = resource_metadata {
let other_metadata = resource_metadata.other;
if let Some(mut properties) = properties {
properties.insert("_metadata".to_string(), Value::Object(other_metadata));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to check if the resource has a _metadata property before we add it otherwise it will invalidate their schema. There should be a test added for this as well. In the case the resource doesn't handle _metadata, then we don't send it.

return Ok(serde_json::to_string(&properties)?);
}
let mut props = Map::new();
props.insert("_metadata".to_string(), Value::Object(other_metadata));
properties = Some(props);
return Ok(serde_json::to_string(&properties)?);
}

match properties {
Some(properties) => {
Ok(serde_json::to_string(&properties)?)
Expand Down Expand Up @@ -330,7 +347,7 @@ impl Configurator {
};
let properties = self.get_properties(&resource, &dsc_resource.kind)?;
debug!("resource_type {}", &resource.resource_type);
let filter = add_metadata(&dsc_resource.kind, properties)?;
let filter = add_metadata(&dsc_resource.kind, properties, resource.metadata.clone())?;
trace!("filter: {filter}");
let start_datetime = chrono::Local::now();
let mut get_result = match dsc_resource.get(&filter) {
Expand Down Expand Up @@ -425,7 +442,7 @@ impl Configurator {
}
};

let desired = add_metadata(&dsc_resource.kind, properties)?;
let desired = add_metadata(&dsc_resource.kind, properties, resource.metadata.clone())?;
trace!("{}", t!("configure.mod.desired", state = desired));

let start_datetime;
Expand Down Expand Up @@ -562,7 +579,7 @@ impl Configurator {
};
let properties = self.get_properties(&resource, &dsc_resource.kind)?;
debug!("resource_type {}", &resource.resource_type);
let expected = add_metadata(&dsc_resource.kind, properties)?;
let expected = add_metadata(&dsc_resource.kind, properties, resource.metadata.clone())?;
trace!("{}", t!("configure.mod.expectedState", state = expected));
let start_datetime = chrono::Local::now();
let mut test_result = match dsc_resource.test(&expected) {
Expand Down Expand Up @@ -638,7 +655,7 @@ impl Configurator {
return Err(DscError::ResourceNotFound(resource.resource_type.clone()));
};
let properties = self.get_properties(resource, &dsc_resource.kind)?;
let input = add_metadata(&dsc_resource.kind, properties)?;
let input = add_metadata(&dsc_resource.kind, properties, resource.metadata.clone())?;
trace!("{}", t!("configure.mod.exportInput", input = input));
let export_result = match add_resource_export_results_to_configuration(dsc_resource, &mut conf, input.as_str()) {
Ok(result) => result,
Expand Down
Loading