Skip to content

Conversation

SteveL-MSFT
Copy link
Member

@SteveL-MSFT SteveL-MSFT commented Jul 27, 2025

PR Summary

Currently blocked on Azure/bicep#17670 where bicep is crashing when trying to format the resourceId

Add support to use outputs section of configuration to have custom output as part of the result. This is needed to use DSC bicep files as modules.

PR Context

Part of #976
Fix #898

@Gijsreyn
Copy link
Contributor

Gijsreyn commented Aug 15, 2025

Hey @SteveL-MSFT,

In an attempt to fix and test this out locally, I stumbled on a few issues. With the change added to the Bicep CLI at: Azure/bicep#17805, the produced JSON looks like:

{
  "$schema": "https://aka.ms/dsc/schemas/v3/bundled/config/document.json",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.37.52.64608",
      "templateHash": "928342520835393415"
    }
  },
  "resources": [
    {
      "type": "Microsoft.DSC.Debug/Echo",
      "apiVersion": "2025-01-01",
      "name": "exampleEcho",
      "properties": {
        "output": "Hello, world!"
      }
    }
  ],
  "outputs": {
    "exampleOutput": {
      "type": "string",
      "value": "[reference(concat('Microsoft.DSC.Debug/Echo', '/', 'exampleEcho'), '2025-01-01').output]"
    }
  }
}

When I'm running that through your branch, another error pops up: Error: JSON: unknown field value, expected one of condition, type, value_or_copy at line 1 column 392

Looking at the docs, I would say that in the output object, it can be a value or a copy, not what the current implementation has. If I'm running it like this:

"outputs": {
    "exampleOutput": {
      "type": "string",
      "value_or_copy": {
        "value": "[reference(concat('Microsoft.DSC.Debug/Echo', '/', 'exampleEcho'), '2025-01-01').output]"
      }
    }
  }

It at least proceeds further, but comes with the following error message: Parser: Function 'reference' requires exactly 1 arguments. I've seen some changes with that particular apiVersion at the end. However, I cannot say much about it with my current knowledge.

Nevertheless, one more time try with "value": "[reference(concat('Microsoft.DSC.Debug/Echo', '/', 'exampleEcho')).output]" specified, gives me: Parser: Invalid resourceId or resource has not executed yet: Microsoft.DSC.Debug/Echo/exampleEcho. This is probably still a WIP.

I wanted to share this to see if improvements can be made at the Bicep side or DSC. Hope it helps further in the development.

@SteveL-MSFT SteveL-MSFT marked this pull request as ready for review October 16, 2025 02:24
@SteveL-MSFT
Copy link
Member Author

@Gijsreyn the value_or_copy problem just required use of flatten so that it doesn't actually show up in the JSON. Since this works outside of bicep, won't block on this for now and will revisit later when we have bicep integration working.

@SteveL-MSFT SteveL-MSFT requested review from Copilot and tgauth October 16, 2025 04:51
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for an outputs section in DSC configuration files, enabling custom output values to be returned from configuration operations. This functionality is essential for using DSC bicep files as modules.

  • Adds Output and ValueOrCopy types to the configuration schema
  • Implements output processing with type validation and conditional evaluation
  • Integrates outputs into all configuration operation results (get, set, test, export)

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
lib/dsc-lib/src/configure/config_doc.rs Defines the Output and ValueOrCopy data structures and adds outputs field to Configuration
lib/dsc-lib/src/configure/context.rs Adds outputs map to track processed output values during configuration execution
lib/dsc-lib/src/configure/config_result.rs Adds optional outputs field to all configuration result types
lib/dsc-lib/src/configure/mod.rs Implements process_output() method and integrates it into all operation methods
lib/dsc-lib/locales/en-us.toml Adds localized messages for output processing feedback
dsc/tests/dsc_output.tests.ps1 Adds comprehensive test coverage for the outputs feature
dsc/tests/dsc_osinfo.tests.ps1 Adds copyright header to existing test file
dsc/examples/hello_world.dsc.bicep Documents the blocked bicep output feature with a comment

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

value_result.is_boolean() && output.r#type != DataType::Bool ||
value_result.is_array() && output.r#type != DataType::Array ||
value_result.is_object() && output.r#type != DataType::Object {
return Err(DscError::Validation(t!("configure.mod.outputTypeNotMatch", name = name, expected_type = output.r#type).to_string()));
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

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

The error message only includes the expected type but not the actual type received. Include the actual type in the error message to help users understand what went wrong: outputTypeNotMatch should include both expected and actual types.

Copilot uses AI. Check for mistakes.

Comment on lines +781 to +786
if value_result.is_string() && output.r#type != DataType::String ||
value_result.is_i64() && output.r#type != DataType::Int ||
value_result.is_boolean() && output.r#type != DataType::Bool ||
value_result.is_array() && output.r#type != DataType::Array ||
value_result.is_object() && output.r#type != DataType::Object {
return Err(DscError::Validation(t!("configure.mod.outputTypeNotMatch", name = name, expected_type = output.r#type).to_string()));
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

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

The type validation logic is incomplete and doesn't handle all possible value types. Values could be floats, nulls, or other types that would pass through this check without validation. Consider using a match statement or adding an else clause to catch unsupported types.

Suggested change
if value_result.is_string() && output.r#type != DataType::String ||
value_result.is_i64() && output.r#type != DataType::Int ||
value_result.is_boolean() && output.r#type != DataType::Bool ||
value_result.is_array() && output.r#type != DataType::Array ||
value_result.is_object() && output.r#type != DataType::Object {
return Err(DscError::Validation(t!("configure.mod.outputTypeNotMatch", name = name, expected_type = output.r#type).to_string()));
let type_mismatch = match &value_result {
Value::String(_) => output.r#type != DataType::String,
Value::I64(_) => output.r#type != DataType::Int,
Value::Bool(_) => output.r#type != DataType::Bool,
Value::Array(_) => output.r#type != DataType::Array,
Value::Object(_) => output.r#type != DataType::Object,
Value::Float(_) => true, // Float type not supported for output
Value::Null => true, // Null type not supported for output
// Add other variants as needed
_ => true, // Catch-all for any other unsupported types
};
if type_mismatch {
return Err(DscError::Validation(t!("configure.mod.outputTypeNotMatch", name = name, expected_type = output.r#type).to_string()));

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement output in configuration template

2 participants