Repository navigation
Initial draft of configuration PS authoring experience - #1658
Steve Lee (SteveL-MSFT) wants to merge 3 commits into
Conversation
| $config.Parameters += New-DscParameter -Name 'ComputerName' -Type 'string' | ||
|
|
||
| # users can also use the types directly to create a parameter | ||
| $config.Parameters += [DSC.Parameter]@{ |
There was a problem hiding this comment.
Shouldn't the namespace be something like Microsoft.Dsc.Parameter?
There was a problem hiding this comment.
It should be, but I'm also trying to optimize for less typing
There was a problem hiding this comment.
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.
| 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`. |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
| 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')]" | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ``` |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.

PR Summary
Initial draft proposing PS script authoring experience for configurations