Initial draft of configuration PS authoring experience by SteveL-MSFT · Pull Request #1658 · PowerShell/DSC · GitHub
Skip to content

Initial draft of configuration PS authoring experience - #1658

Draft
Steve Lee (SteveL-MSFT) wants to merge 3 commits into
PowerShell:mainfrom
SteveL-MSFT:rfc-ps
Draft

Steve Lee (SteveL-MSFT) wants to merge 3 commits into
PowerShell:mainfrom
SteveL-MSFT:rfc-ps

Conversation

@SteveL-MSFT

Copy link
Copy Markdown
Member

PR Summary

Initial draft proposing PS script authoring experience for configurations

@SteveL-MSFT Steve Lee (SteveL-MSFT) changed the title Initial draft of PS authoring experience Initial draft of configuration PS authoring experience Aug 6, 2026
@Gijsreyn

Copy link
Copy Markdown
Collaborator

$config.Parameters += New-DscParameter -Name 'ComputerName' -Type 'string'

# users can also use the types directly to create a parameter
$config.Parameters += [DSC.Parameter]@{

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Shouldn't the namespace be something like Microsoft.Dsc.Parameter?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It should be, but I'm also trying to optimize for less typing

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We could put a using statement at the top to reduce typing then the user wouldn't need to put in the name space at all.

@kilasuit Ryan Yates (kilasuit) left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Overall generally agree with this proposal & can't wait to see what comes of this in future.

Comment on lines +29 to +34
Within PowerShell, this was previously accomplished by using the `configuration` keyword in a PowerShell script which would generate a
legacy DSC mof file.
However, this approach is no longer viable:

- The `mof` file format is not widely adopted and therefore not used by the new DSC engine.
- The new configuration document format supports expressions which is not supported by `mof`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could we look at extending the how the Configuration Keyword works in a future version of PowerShell so that

  • It outputs a configuration document in the new format by default not the older mof based documents

(This q is likely answered in the DscConfiguration Alternate proposal below)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unfortunately, the Configuration keyword has some painful baggage in the parser/engine. We're unlikely to be able to readily override it without a great deal of work that has to land both in PowerShell (and won't be available in older versions) and any tooling modules.

There's also enough differences between the two models to recommend starting with an entirely new DSL instead of trying to get the previous model inputs to "just work" with emitting a v3 configuration document.

Comment on lines +47 to +137
Creating a DSC configuration document:

```powershell
Import-Module Microsoft.DesiredStateConfiguration

$config = New-DscConfiguration
$config.Metadata = @{
Name = 'MyConfiguration'
Version = '1.0.0'
Author = 'SteveL-MSFT'
}

# cmdlets provided to create consistent discovery experience
# the `parameters` member is a collection of `[Dsc.Parameter]` objects
$config.Parameters += New-DscParameter -Name 'ComputerName' -Type 'string'

# users can also use the types directly to create a parameter
$config.Parameters += [DSC.Parameter]@{
Name = 'Environment'
Type = [Dsc.DataType]::String
DefaultValue = 'Production'
}

# The `-Type` would allow for intellisense performing the equivalent to `dsc resource list` on statically cached
# resources found during module import.
$echoResource = New-DscResource -Name 'My echo' -Type 'Microsoft.DSC.Debug/Echo'

# The resulting `[DSC.Resource]` object would have a `Properties` property that would allow for intellisense to provide the available properties for the resource.
$echoResource.Properties.Output = 'Hello World'

$echoResource2 = New-DscResource -Name 'My echo 2' -Type 'Microsoft.DSC.Debug/Echo'

# Here we use a scriptblock to generate a DSC expression
$echoResource2.Properties.Output = {
$config.Parameters['Environment'] + ' ' + $config.Parameters['ComputerName']
}

# Handle dependencies between resources by using the `DependsOn` property of the `[Dsc.Resource]` object.
$echoResource2.DependsOn += $echoResource

# The `Resources` property is a collection of `[Dsc.Resource]` objects
$config.Resources += $echoResource
$config.Resources += $echoResource2

$config.Export('./MyConfiguration.dsc.json')

# alternatively using cmdlet
$config | Export-DscConfiguration -Path './MyConfiguration.dsc.json'
```

This would generate the following configuration document:

```json
{
"Metadata": {
"Name": "MyConfiguration",
"Version": "1.0.0",
"Author": "SteveL-MSFT"
},
"Parameters": [
{
"Name": "ComputerName",
"Type": "string"
},
{
"Name": "Environment",
"Type": "string",
"DefaultValue": "Production"
}
],
"Resources": [
{
"Name": "My echo",
"Type": "Microsoft.DSC.Debug/Echo",
"Properties": {
"Output": "Hello World"
}
},
{
"Name": "My echo 2",
"Type": "Microsoft.DSC.Debug/Echo",
"Properties": {
"Output": "[concat(parameters('Environment'), ' ', parameters('ComputerName'))]"
},
"DependsOn": [
"[resourceId('Microsoft.DSC.Debug/Echo', 'My echo')]"
]
}
]
}
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This all seems sensible enough to me


## Alternate Proposals and Considerations

There is an alternate proposal for a Pester-like experience although this would require significantly more work:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'd prefer to work this way as it aligns better with how DSC 1.1 works today however this feels like a We may get to this in future approach than a We plan to commit to this at this time

As mentioned above this likely ends up being a PowerShell Language change question to the Configuration Keyword though I do understand why that can of worms may want to be avoided.

@michaeltlombardi Mikey Lombardi (He/Him) (michaeltlombardi) Aug 28, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Any DSL will necessarily depend on the type definitions and cmdlets (or be forced to reimplement them internally).

I think the PowerShell/DSC team is best situated to define the types and basic cmdlets for operating on those types.

On the other hand, I think the DSC community is better suited to defining a DSL that builds on those types/cmdlets. I think there's likely more than one coherent approach to a DSL, too.

Consider the following pseudocode examples of DSLs emitting the same end document:

Script-like
DscConfig {
    param(
        [bool]
        $UpdateAutomatically = $false,

        [ValidateRange(0,90)]
        [int]
        $UpdateFrequency = 0
    )
    
    resources {
        TailSpinToys.Cli/Package "Ensure 'tstoy' is installed" {
            VersionRequirement = '>=2.0.0, <3.0.0'
        }
        TailSpinToys.Cli/Settings "Enforce 'tstoy' machine settings" {
            Scope               = 'Machine'
            UpdateAutomatically = $UpdateAutomatically
            UpdateFrequency     = $UpdateFrequency
        } -DependsOn TailSpinToys.Cli/Package("Ensure 'tstoy' is installed")
    }
}
Builder-like
DscBuilder {
    WithParameter(bool) {
        Name    = UpdateAutomatically
        Default = $false
    }
    WithParameter(integer) {
        Name    = UpdateFrequency
        Default = 0
        Minimum = 0
        Maximum = 90
    }
    WithResource(TailspinToys.Cli/Package) {
        Name = "Ensure 'tstoy' is installed"
        Properties = @{
            VersionRequirement = '>=2.0.0, <3.0.0'
        }
    }
    WithResource(TailspinToys.Cli/Settings) {
        Name = "Enforce 'tstoy' machine settings"
        Properties = @{
            Scope = 'Machine'
            UpdateAutomatically = [Parameters]::UpdateAutomatically
            UpdateFrequency     = [Parameters]::UpdateFrequency
        }
        DependsOn = @(
            TailspinToys.Cli/Package = "Ensure 'tstoy' is installed"
        )
    }
}

Given the limited resources available to the project, I think it would be better to provide the primitives that a DSL will need to build on. Any DSL implementation will likely need to rapidly iterate separately from the DSC engine as user feedback rolls in.

@Gijsreyn

Copy link
Copy Markdown
Collaborator

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

Labels

None yet

Projects

Status: RFC

Development

Successfully merging this pull request may close these issues.

6 participants