Repository navigation
Resource Properties
Every entry under resources: is one resource. This page documents every key the runner
reads from a resource, in the order the runner reads them, with worked examples for each.
| Key | Required | Type | Summary |
|---|---|---|---|
type |
yes | string |
Module/ResourceName — which DSC resource to invoke. |
name |
yes | string | The instance name. Unique within the file. |
properties |
yes | map | The DSC resource's own properties. Expanded before use. |
dependsOn |
no | string or list | Ordering only. Module/ResourceName/Instance. |
notify |
no | string or list | Ordering and a gated data link plus forced refresh. |
preCondition |
no | string | A side-effect-free predicate. False ⇒ SKIP. |
condition |
no | string | Deprecated alias for preCondition. |
postCondition |
no | string | Evaluated after Test/Set. False ⇒ FAIL. |
preExecutionScript |
no | string | PowerShell run before Test/Set. Gated. |
postExecutionScript |
no | string | PowerShell run after Test/Set. Gated. |
target |
no | map | Where this resource executes. |
resourceCredential |
no | map | Resolves a credential into a property. |
A resource carrying every one of them:
resources:
- name: Web Server
type: PSDscResources/WindowsFeature
dependsOn:
- PSDscResources/File/Deploy Directory
notify:
- PSDscResources/Service/W3SVC
preCondition: equals (variables 'Role') 'Web'
postCondition: result().InDesiredState
preExecutionScript: Write-Verbose "About to evaluate the web feature." -Verbose
postExecutionScript: Write-Verbose "Web feature evaluated." -Verbose
target:
action: WinRM
computerName: web01.contoso.com
credential:
action: SecretManagement
name: DeployAccount
resourceCredential:
action: Environment
propertyName: Credential
UserNameVariable: DEPLOY_USER
PasswordVariable: DEPLOY_PASSWORD
properties:
Name: Web-Server
Ensure: PresentModule/ResourceName. The runner splits on the first /: the left half is the module, the
right half is the resource name handed to the engine.
- name: Log Directory
type: PSDscResources/FileTogether with name, this forms the resource's identity — Module/ResourceName/Instance
— which is what dependsOn, notify and using() address, and what the report keys on.
The identity of the resource above is PSDscResources/File/Log Directory.
type is also validated at pre-parse time: Test-ResourcesForIncorrectProperties calls
Get-DscResource -Name <ResourceName> -Module <Module> and fails the run if the resource is
not installed.
The instance name. It must be unique within the compiled file, because the report is keyed on
(ConfigurationFile, ResourceType, InstanceName) and because reference() looks up by bare
name.
Names may contain spaces, and every reference to them must match exactly:
- name: Default Repository
type: AzureDevOpsDscNative/AzDoGitRepository
dependsOn:
- AzureDevOpsDscNative/AzDoProject/ProjectRemember that the Datum resources merge is keyed on name: two layers declaring the same
name produce one merged resource, not two. That is how a node layer overrides one property
of a policy-declared resource — see
Configuration Repository Layout.
The DSC resource's own properties. This is the only part of the resource the engine sees.
Every value is run through parameter expansion and then ExpandString, so $(...)
sub-expressions and the function language work anywhere in the map,
including nested maps and lists:
- name: App Config
type: PSDscResources/File
properties:
DestinationPath: $(variables('AppRoot'))\appsettings.json
Contents: $(parameters('ConfigJson'))
Ensure: PresentConditional values are ordinary PowerShell inside $( ):
properties:
Ensure: $( if ([string]::IsNullOrEmpty((variables 'Project_Ensure'))) { 'Present' } else { variables 'Project_Ensure' } )Nested structures expand too:
properties:
ProjectName: $(variables('ProjectName'))
Permissions:
- Identity: $(variables('AdminGroup'))
Access: Allow
- Identity: $(variables('ReaderGroup'))
Access: DenyIf expansion throws — an undefined parameters() name, a using() that is not permitted, a
syntax error in a $( ) block — the resource is recorded FAIL with the exception message and
the run moves to the next resource.
Test-ResourcesForIncorrectProperties checks each key against the installed resource's real
property list: an unknown property, a mandatory property left null, or a value outside a
ValidateSet all fail the run before anything is evaluated. Values containing $ are skipped
by that check, since they are not known until execution.
Ordering, and nothing else. A string or a list of strings, each a full
Module/ResourceName/Instance identity:
- name: Project
type: AzureDevOpsDscNative/AzDoProject
properties:
projectName: Magenta
- name: Project Services
type: AzureDevOpsDscNative/AzDoProjectServices
dependsOn:
- AzureDevOpsDscNative/AzDoProject/Project
properties:
projectName: MagentaMultiple dependencies:
dependsOn:
- PSDscResources/File/Deploy Directory
- PSDscResources/WindowsFeature/Web ServerSort-DependsOn topologically sorts the file on these edges. A cycle, a self-reference, or a
dependency on a resource that is not in the same compiled file fails the run before any
resource runs. dependsOn does not cross files.
dependsOn says nothing about whether the dependency succeeded — it only fixes the order. A
resource whose dependency failed still runs. Use preCondition if you need to gate on state.
Ordering plus two things dependsOn does not do: a forced refresh, and a data link.
- name: App Config
type: PSDscResources/File
notify:
- PSDscResources/Service/AppService
properties:
DestinationPath: C:\app\appsettings.json
Contents: $(parameters('ConfigJson'))
Ensure: Present
- name: AppService
type: PSDscResources/Service
properties:
Name: AppService
State: Running-
Ordering.
Expand-NotifyDependsOnfolds eachnotifyentry into an implicitdependsOnon the target, so the same sort and the same cycle detection govern it. -
Forced re-run —
Setmode only. IfApp Config's ownTest()reported drift and itsSet()then succeeded,AppServicerunsSet()this pass even if its ownTest()says it is already in the desired state. A forced re-run that was itself a no-op does not propagate further; only a resource whose ownTest()reported drift propagates onward. InTestmode there is noSet()to force, sonotifycontributes ordering only. -
Data link.
notifyis the gate forusing()— see below and Function Language.
Notifying several resources:
notify:
- PSDscResources/Service/AppService
- PSDscResources/Service/NotificationWorkerReading across the link:
- name: Project
type: AzureDevOpsDscNative/AzDoProject
notify:
- AzureDevOpsDscNative/AzDoGitRepository/Default Repository
properties:
projectName: Magenta
- name: Default Repository
type: AzureDevOpsDscNative/AzDoGitRepository
properties:
ProjectId: $((using 'AzureDevOpsDscNative/AzDoProject/Project').Id)notify and using() are intra-file, like dependsOn. A notify target that is not in the
same compiled file fails the run at expansion time.
A side-effect-free predicate evaluated before the resource. $false records the resource
SKIP and moves on; the resource is never evaluated.
- name: Web Server
type: PSDscResources/WindowsFeature
preCondition: equals (variables 'Role') 'Web'
properties:
Name: Web-Server
Ensure: PresentComparing a parameter:
preCondition: (parameters 'Environment') -eq 'Production'Negating:
preCondition: not (equals (variables 'Project_Ensure') 'Absent')Combining with ordinary operators:
preCondition: (equals (variables 'Role') 'Web') -and ((parameters 'Environment') -ne 'Sandbox')Assert-SafeConditionExpression parses the expression first and rejects it if it contains a
command invocation outside the allow-list (parameters, variables, reference, using,
nodeName, configurationFile, equals, not, concat, empty, coalesce, toLower,
toUpper, startsWith, contains, add, sub, mul, div, mod, min, max, int,
float), a variable assignment, or a method call. The check walks the whole tree, so a
disallowed call nested inside an allowed one is rejected too. A rejected condition never runs —
the resource is recorded FAIL.
Argument style. These are PowerShell commands, so arguments are space-separated:
equals (variables 'X') 'Y'. Writingequals(X, 'Y')binds the whole parenthesised list to the first parameter and fails.
The original spelling of preCondition, kept for back-compatibility. It behaves identically
and goes through the same validation. preCondition wins when both are present.
- name: Legacy Gate
type: PSDscResources/File
condition: equals (variables 'Role') 'Web'
properties:
DestinationPath: C:\web\marker.txt
Ensure: PresentPrefer preCondition in new configurations — the pairing with postCondition is what makes
the name meaningful.
Evaluated after Test/Set, with two extra accessors available: result() and
stopProcessing(). A $false result marks the resource FAIL regardless of what the engine
itself reported.
Asserting convergence:
- name: Project Services
type: AzureDevOpsDscNative/AzDoProjectServices
postCondition: result().InDesiredState
properties:
projectName: MagentaAccepting non-convergence under a condition:
postCondition: result().InDesiredState -or (not (equals (variables 'Project_Ensure') 'Present'))Halting the rest of the file when this resource did not converge:
- name: Prerequisite Check
type: PSDscResources/Script
postCondition: result().InDesiredState -or stopProcessing()
properties:
GetScript: '@{ Result = "" }'
TestScript: Test-Path C:\prereq.marker
SetScript: 'throw "Prerequisite missing."'stopProcessing() returns $true, so the resource above is not marked FAIL — it stops
the file cleanly. Every remaining resource is recorded SKIP and the run status for the file
becomes StoppedByRequest. Reverse the clauses if you want both a FAIL and a stop.
Reading the engine's message:
postCondition: result().Message -notmatch 'deprecated'postCondition is the only place result() and stopProcessing() are permitted. Using either
in a preCondition is rejected as a disallowed command invocation.
Free-form PowerShell run immediately before Test/Set, after properties have been expanded
and the target session resolved. Requires PipelineRunnerSettings.AllowExecutionScripts: true
— see PipelineRunnerSettings.
- name: Deployment Package
type: PSDscResources/Archive
preExecutionScript: New-Item -ItemType Directory -Path C:\staging -Force | Out-Null
properties:
Path: C:\packages\app.zip
Destination: C:\stagingMulti-line, using YAML's block scalar:
preExecutionScript: |
$stagingPath = 'C:\staging'
if (-not (Test-Path $stagingPath)) {
New-Item -ItemType Directory -Path $stagingPath -Force | Out-Null
}
Write-Verbose "Staging prepared at $stagingPath" -VerboseUnlike properties and the conditions, an execution script is not parsed through
ExpandString or the safety allow-list — it is [scriptblock]::Create plus &. It therefore
reads script-scope variables directly ($ProjectName, not variables('ProjectName')), and
because it is invoked rather than dot-sourced it cannot rewrite the runner's own locals.
A script that throws records the resource FAIL and moves to the next resource.
The same, run after Test/Set and after postCondition. Same gate, same execution model.
- name: Project
type: AzureDevOpsDscNative/AzDoProject
postExecutionScript: if ($Project_Ensure -eq 'Absent') { Stop-TaskProcessing }
properties:
projectName: $(variables('ProjectName'))
Ensure: $(variables('Project_Ensure'))This is the canonical teardown pattern: when the project is being removed, everything beneath
it is moot, so the rest of the file is skipped. The if guard matters — the resource is also
evaluated in Test mode, where a project that does not yet exist is ordinary drift rather than
a reason to stop.
Logging:
postExecutionScript: |
Add-Content -Path C:\Logs\deploy.log -Value "$(Get-Date -Format o) evaluated web feature."Stop-TaskProcessing is only callable from here — it is not on the condition allow-list.
stopProcessing() in a postCondition is the equivalent that needs no opt-in.
Where this resource executes. Overrides PipelineRunnerSettings.Target for this resource only.
- name: Web Feature
type: PSDscResources/WindowsFeature
target:
action: WinRM
computerName: web01.contoso.com
properties:
Name: Web-Server
Ensure: Present| Key | Meaning |
|---|---|
action |
Local, WinRM, SSH, or the name of any file under Actions/Target/. Defaults to the file-level setting, itself defaulting to Local. |
computerName |
The target host. Required by WinRM and SSH. |
credential |
A credential block, resolved through the Credential hook. |
configurationName |
WinRM only: the remote WinRM endpoint the PSSession lands on, e.g. PowerShell.7. Omitted, the target's default endpoint (Windows PowerShell) is used — which has no Invoke-DscResource on a current Windows build, so a DscV2 target running PowerShell 7 should name it. |
No other key in the target block is read.
Who connects. With no
credentialhere, the session is opened as the account the runner process runs as — the agent service account on a self-hosted agent. That account must be permitted on the target (Remote Management Usersto connect, localAdministratorsto apply DSC); the defaultNT AUTHORITY\NETWORK SERVICEis not. See The identity the runner runs as.
With a credential:
target:
action: WinRM
computerName: web01.contoso.com
credential:
action: SecretManagement
name: DeployAccount
vault: DeploymentVaultOver SSH (requires the DscV3 engine — the SSH target action rejects DscV2 outright, because
there is no CIM-over-SSH transport for Invoke-DscResource):
target:
action: SSH
computerName: app01.contoso.comThe runner passes only
ComputerName, the resolved engine, and the resolved credential to a Target action. The SSH action can use aUserNameand aKeyFilePath, but there is notargetkey that reaches them today — SSH authentication falls back to the runner account's own~/.sshconfiguration. Put the user and identity file in an SSHHostblock for the target instead — in the service account's profile on an agent, with that account's key authorised on the target.
Explicitly pinning one resource back to the runner itself, under a remote file-level default:
target:
action: LocalSessions are cached per (action, computerName, configurationName, credential), so several resources aimed at one
host share a connection, and every session is closed when the file finishes — however it
finishes. Local never invokes the Target hook at all.
See Remote Targets and Credentials for the full picture, including reboot behaviour on a remote target.
Resolves a credential through the Credential hook and injects it into the resource's own properties, so the credential never appears in the configuration.
- name: Database
type: SqlServerDsc/SqlDatabase
resourceCredential:
action: Environment
propertyName: Credential
UserNameVariable: SQL_USER
PasswordVariable: SQL_PASSWORD
properties:
ServerName: sql01
InstanceName: MSSQLSERVER
Name: AppDatabase
Ensure: Present| Key | Default | Meaning |
|---|---|---|
action |
Environment |
Which file under Actions/Credential/ resolves it. |
propertyName |
Credential |
The property on the resource the resolved credential is written to. |
All remaining keys are passed to the action as its context. Each built-in action reads different ones:
From environment variables:
resourceCredential:
action: Environment
UserNameVariable: SQL_USER
PasswordVariable: SQL_PASSWORDFrom a SecretManagement vault:
resourceCredential:
action: SecretManagement
name: SqlDeployAccount
vault: DeploymentVaultInto a non-default property name:
resourceCredential:
action: SecretManagement
name: SqlDeployAccount
propertyName: PsDscRunAsCredentialresourceCredential is declarative, not a script, so it is not gated by
AllowExecutionScripts. It resolves during property expansion, which means a failure to
resolve — a missing environment variable, a secret that is not in the vault — records the
resource FAIL with that message and moves on.
Keys the runner does not recognise are carried through the compiled file and never read. They
are not an error, which makes them usable for comments and for tooling of your own — but note
that a typo (propeties:) is therefore silently ignored rather than rejected. The pre-parse
property check catches wrong keys inside properties, not wrong keys on the resource itself.
Dsc.PipelineRunner 1.1.0 — generated from
the repository on 2026-09-17.
Conceptual pages are authored in WikiSource/; command pages are generated from
comment-based help. Edit those, not the wiki: the wiki is overwritten on every release.