alx9r / zerodsc Goto Github PK
View Code? Open in Web Editor NEWlightweight native PowerShell desired state configuration engine
License: Other
lightweight native PowerShell desired state configuration engine
License: Other
This invokation of Import-Module
in New-ClassResourceObject
seems to re-import the module of the class resource on each invokation even if it has already been loaded. It seems to happen once per bound resource, so the bigger the configuration document the slower the creation of the instructions. Some resource modules are large enough that they take seconds to load. The modules should probably remain cached as they are imported, but they don't currently seem to be.
It looks like all current versions of PowerShell don't consistently reload modules (ref, ref). Relying on Import-Module -Force
to change which module members are exported should be avoided. The ZeroDSC module should not act on any arguments and the tests that rely on -Args 'ExportAll'
should be changed to use InModuleScope{}
instead.
This change shouldn't affect ZeroDSC users. But making the change will likely avoid some problems in development.
I'm not sure whether ZeroDSC resource invokers behave correctly when multiple resource invokers of the same resource but with different versions are created. It should be confirmed that each resource invoker indeed imports the correct version. This should be tested for both MOF- and class-based resources. I think there is already an appropriate class-based test stub resource with multiple versions. Likely a new MOF-based test stub resource with multiple versions needs to be created for testing.
PowerShell implements Import-DscResource
as a dynamic keyword. ZeroDSC implements its own Import-DscResource
as a function. It looks like either Import-DscResource
is only available within the respective configuration scriptblocks where it is used. This means that ZeroDSC does not have to export its Import-DscResource
to operate correctly. However, if Import-DscResource
is not exported, neither help nor intellisense works for Import-DscResource
.
Pros:
Get-Command
outputhelp Import-DscResource
displays somethingCons:
One compromise is to put an explicit note about the dynamic keyword in the help output for the ZeroDSC Import-DscResource
output. I'm leaning toward this option.
There are various code snippets in the .md
files in the .\Docs
folder. They should be tagged with ````Powershell so that github syntax-highlights them.
This code
$document = {
Get-DscResource TestStub | Import-DscResource
TestStub a @{
Key = 'a'
ThrowOnSet = 'always'
}
}
Describe 'resource stack trace' {
$h = @{}
It 'create instructions' {
$h.Instructions = ConfigInstructions Name $document
}
foreach ( $step in $h.Instructions )
{
It $step.Message {
$step | Invoke-ConfigStep
}
}
}
outputs
Describing resource stack trace
[+] create instructions 14.46s
[+] Pretest: Test resource [TestStub]a 1.28s
[-] Configure: Set resource [TestStub]a 162ms
RuntimeException: TestStub forced exception because ThrowOnSet=always
at Set-TargetResource<Process>, C:\Users\un1\Documents\WindowsPowerShell\Modu
les\ZeroDSC\DSCResources\TestStub\TestStub.psm1: line 56
at Invoke-MofResourceCommand<Process>, C:\Users\un1\Documents\WindowsPowerShe
ll\Modules\ZeroDSC\Functions\mofResourceInvokerType.ps1: line 105
at _Invoke, C:\Users\un1\Documents\WindowsPowerShell\Modules\ZeroDSC\Function
s\mofResourceInvokerType.ps1: line 21
at Invoke-ResourceCommand<Process>, C:\Users\un1\Documents\WindowsPowerShell\
Modules\ZeroDSC\Functions\resourceInvokerType.ps1: line 88
at Invoke, C:\Users\un1\Documents\WindowsPowerShell\Modules\ZeroDSC\Functions
\resourceInvokerType.ps1: line 33
at Invoke, C:\Users\un1\Documents\WindowsPowerShell\Modules\ZeroDSC\Functions
\boundResourceType.ps1: line 14
at <ScriptBlock>, C:\Users\un1\Documents\WindowsPowerShell\Modules\ZeroDSC\Fu
nctions\configInstructionsType.ps1: line 285
at Invoke-ConfigStep<Process>, C:\Users\un1\Documents\WindowsPowerShell\Modul
es\ZeroDSC\Functions\configInstructionsType.ps1: line 335
at <ScriptBlock>, <No file>: line 19
[+] Configure: Test resource [TestStub]a 320ms
Most of those lines are uninformative because they are just a record of the stack unwinding inside the ZeroDSC module. They should probably be omitted from the stack trace so that Pester shows only the helpful lines.
Invoking Get-DscResource -Module SomeModule
can result in multiple versions of SomeModule
. ZeroDSC's behavior in such a situation should be tested. I think that ZeroDSC should probably favor the module with the highest version number if there is ambiguity.
Updating documentation currently triggers a CI build. For commits that contain only changes to .md
files, CI should be skipped. It looks like commit filtering supports doing this.
Executing
ConfigInstructions Name {
Get-DscResource TestStub | Import-DscResource
Get-DscResource TestStub | Import-DscResource
TestStub a @{ Key = 'a' }
}
raises the exception
Duplicate resource named TestStub
At C:\Users\un1\Documents\WindowsPowerShell\Modules\ZeroDSC\Functions\configDocumentType.ps1:94 char:17
+ throw [System.FormatException]::new(
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], FormatException
+ FullyQualifiedErrorId : Duplicate resource named TestStub
The file name and line number of the second Import-DscResource
should be reported in the exception.
A test for this behavior is already mentioned in configDocumentType.Tests.ps1
Consider the following:
$document = {
Get-DscResource TestStub | Import-DscResource
TestStub a @{
Key = 'a'
DependsOn = '[TestStub]a'
}
}
$instructions = ConfigInstructions Name $document
[TestStub]a
depends on itself. I can't see any meaning to a normal resource depending on itself. A normal resource depending on itself almost certainly indicates a user error. Processing of [TestStub]a
should throw an exception because it points to itself.
It's worth noting that an aggregate resource could depend on itself because it could count itself in whatever aggregation logic it is applying.
A test for this behavior is already mentioned in configDocumentType.Tests.ps1.
AppVeyor builds ZeroDSC but that is not obvious. The AppVeyor badge should be added to the root readme.md.
The "Installing ZeroDSC" section currently recommends switching to the master
branch. Instead it should recommend switching to the latest release tag.
Currently the config instructions enumerable does not catch exceptions that invoking a resource might throw. This can lead to an endless loop.
Running this code causes an endless loop.
$document = {
Get-DscResource TestStub | Import-DscResource
TestStub a @{
Key = 'a'
ThrowOnSet = 'always'
}
}
$instructions = ConfigInstructions Name $document
$instructions |
Invoke-ConfigStep
The above code results in an endless loop.
Exceptions thrown by resources should be caught, the resource marked as "failed" (or maybe "ExceptionThrown"), and then the exception re-thrown. If the resource is marked with a new value like "ExceptionThrown", the state machines should also be altered to raise and handle 'AtExceptionThrown' events.
Currently prerequisites are only mentioned part-way down the front page. They should definitely be mentioned in/near the "Installing ZeroDSC" section and probably removed from the front page.
Consider the following:
$document = {
Get-DscResource TestStub | Import-DscResource
TestStub a @{
Key = 'a'
DependsOn = '[TestStub]b'
}
}
ConfigInstructions Name $document
[TestStub]a
depends on [TestStub]b
which does not exist. This is a user error and should throw an informative exception accordingly.
A test for this behavior is already mentioned in ConfigDocumentType.Tests.ps1.
ConfigInstructions Name {}
in the REPLConfigInstructions Name {}
in the second REPL tabformat-default : The following exception occurred while trying to enumerate the collection: "The term 'New-ProgressNodes' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.".
+ CategoryInfo : NotSpecified: (:) [format-default], ExtendedTypeSystemException
+ FullyQualifiedErrorId : ExceptionInGetEnumerator,Microsoft.PowerShell.Commands.FormatDefaultCommand
The cause of this error seems to be PowerShell itself. When a module that implements an object that implements IEnumerator
is loaded into two runspaces in the same process, then, in the second runspace no functions from the module are available from within .GetEnumerator()
.
There is a repro of this bug that is independent of ZeroDSC in the ToolFoundations repo.
Versions known to exhibit problem:
Versions known not to exhibit problem:
It looks like PowerShell 5.0 has this problem but 5.1 does not. This issue should remain open until it has been confirmed that the GA version of PowerShell 5.1 indeed ships with this issue resolved.
Right now five functions are exported by ZeroDSC. These five functions form the public API and should have comment-based help.
Consider this document:
$document = {
Get-DscResource TestStub | Import-DscResource
TestStub a @{
Key = 'a'
ThrowOnSet = 'always'
}
}
The follow code creates instructions and invokes them using Pester:
Describe 'resource stack trace' {
$h = @{}
It 'create instructions' {
$h.Instructions = ConfigInstructions Name $document
}
foreach ( $step in $h.Instructions )
{
It $step.Message {
$step | Invoke-ConfigStep
}
}
}
Executing that code yields
Describing resource stack trace
[+] create instructions 4.02s
[+] Pretest: Test resource [TestStub]a 851ms
[-] Configure: Set resource [TestStub]a 124ms
RuntimeException: TestStub forced exception because ThrowOnSet=always
RuntimeException: TestStub forced exception because ThrowOnSet=always
MethodInvocationException: Exception calling "InvokeWithContext" with "2" arg
ument(s): "TestStub forced exception because ThrowOnSet=always"
at Invoke-ConfigStep<Process>, C:\Program Files\WindowsPowerShell\Modules\Zer
oDSC\0.2.0\Functions\configInstructionsType.ps1: line 324
at <ScriptBlock>, <No file>: line 20
[+] Configure: Test resource [TestStub]a 294ms
The following code creates instructions and invokes them:
$instructions = ConfigInstructions Name $document
$instructions | Invoke-ConfigStep
Executing that code yields
Phase Verb ResourceName Progress
----- ---- ------------ --------
Pretest Test [TestStub]a Pending
Exception calling "InvokeWithContext" with "2" argument(s): "TestStub forced
exception because ThrowOnSet=always"
At C:\Program Files\WindowsPowerShell\Modules\ZeroDSC\0.2.0\Functions\configIns
tructionsType.ps1:324 char:13
+ $result = $ConfigStep.Action.InvokeWithContext($functions ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : RuntimeException
Configure Set [TestStub]a Exception
Configure Test [TestStub]a Failed
Note that in the above outputs the stacktrace does not mention the resource file from where the exception originated. In this case the originating file is C:\Program Files\WindowsPowerShell\Modules\ZeroDSC\0.2.0\DSCResources\TestStub\TestStub.psm1
).
The use of Resource Invokers directly is a topic that does not need to be explored during an introduction to ZeroDSC. It should probably be moved somewhere else.
While the other "Getting Started" topics mention configuration documents, there is no topic focused on configuration documents.
Currently parameters specified in configuration documents are not checked for compatibility with the corresponding resource if and when the resource is invoked. Basic checking for parameter compatibility should be performed when the parameters are bound to the resource. That way parameter errors in configuration documents are detected as early as possible.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.