Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions docs/reference/steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ This page documents built-in IdLE steps discovered from `Invoke-IdleStep*` funct

## EmitEvent

- **Step Name**: $stepType
- **Implementation**: $commandName
- **Idempotent**: $idempotent
- **Contracts**: $contracts
- **Step Name**: `EmitEvent`
- **Implementation**: `Invoke-IdleStepEmitEvent`
Comment thread
blindzero marked this conversation as resolved.
- **Idempotent**: `Unknown`
- **Contracts**: `Unknown`
- **Events**: Unknown

**Synopsis**
Expand All @@ -33,10 +33,10 @@ _Unknown (not detected automatically). Document required With.* keys in the step

## EnsureAttribute

- **Step Name**: $stepType
- **Implementation**: $commandName
- **Idempotent**: $idempotent
- **Contracts**: $contracts
- **Step Name**: `EnsureAttribute`
- **Implementation**: `Invoke-IdleStepEnsureAttribute`
- **Idempotent**: `Yes`
- **Contracts**: `Provider must implement method: EnsureAttribute`
- **Events**: Unknown

**Synopsis**
Expand Down Expand Up @@ -64,10 +64,10 @@ The step is idempotent by design: it converges state to the desired value.

## EnsureEntitlement

- **Step Name**: $stepType
- **Implementation**: $commandName
- **Idempotent**: $idempotent
- **Contracts**: $contracts
- **Step Name**: `EnsureEntitlement`
- **Implementation**: `Invoke-IdleStepEnsureEntitlement`
Comment thread
blindzero marked this conversation as resolved.
- **Idempotent**: `Yes`
- **Contracts**: `Unknown`
- **Events**: Unknown

**Synopsis**
Expand All @@ -79,6 +79,7 @@ Ensures that an entitlement assignment is present or absent for an identity.
This provider-agnostic step uses entitlement provider contracts to converge
an assignment to the desired state. The host must supply a provider instance
via `Context.Providers[<ProviderAlias>]` that implements:

- ListEntitlements(identityKey)
- GrantEntitlement(identityKey, entitlement)
- RevokeEntitlement(identityKey, entitlement)
Expand Down
1 change: 1 addition & 0 deletions src/IdLE.Core/Private/Copy-IdleRedactedObject.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
function Copy-IdleRedactedObject {
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'RedactionMarker', Justification = 'Used within nested helper functions for redaction output.')]
param(
[Parameter()]
[AllowNull()]
Expand Down
3 changes: 2 additions & 1 deletion src/IdLE.Core/Private/Invoke-IdleWithRetry.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ function Invoke-IdleWithRetry {
)
}
catch {
# Intentionally ignored.
# Intentionally ignored, but surfaced for diagnostics.
Write-Verbose "EventSink.WriteEvent failed: $($_.Exception.Message)"
}
}

Expand Down
1 change: 1 addition & 0 deletions src/IdLE.Core/Private/New-IdleEventSink.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
function New-IdleEventSink {
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'EventBuffer', Justification = 'Passed to Write-IdleEvent via closure.')]
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
Expand Down
1 change: 1 addition & 0 deletions src/IdLE.Core/Private/Test-IdleCondition.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
function Test-IdleCondition {
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Context', Justification = 'Used for path resolution within nested helper functions.')]
param(
[Parameter(Mandatory)]
[ValidateNotNull()]
Expand Down
2 changes: 1 addition & 1 deletion src/IdLE.Core/Private/Write-IdleEvent.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function Write-IdleEvent {
#
# We never mutate the original event object. We emit a redacted copy.
$shouldEmitToSink = ($null -ne $EventSink)
$shouldBuffer = ($null -ne $EventBuffer)
$shouldBuffer = ($null -ne $EventBuffer)

$eventToEmit = $Event
if ($shouldEmitToSink -or $shouldBuffer) {
Expand Down
190 changes: 130 additions & 60 deletions src/IdLE.Core/Public/Invoke-IdlePlanObject.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,16 @@ function Invoke-IdlePlanObject {
}
}

$context.EventSink.WriteEvent('RunStarted', 'Plan execution started.', $null, @{
CorrelationId = $corr
Actor = $actor
StepCount = @($Plan.Steps).Count
})
$context.EventSink.WriteEvent(
'RunStarted',
'Plan execution started.',
$null,
@{
CorrelationId = $corr
Actor = $actor
StepCount = @($Plan.Steps).Count
}
)

$failed = $false
$stepResults = @()
Expand Down Expand Up @@ -351,19 +356,29 @@ function Invoke-IdlePlanObject {
Attempts = 1
}

$context.EventSink.WriteEvent('StepNotApplicable', "Step '$stepName' not applicable (condition not met).", $stepName, @{
StepType = $stepType
Index = $i
})
$context.EventSink.WriteEvent(
'StepNotApplicable',
"Step '$stepName' not applicable (condition not met).",
$stepName,
@{
StepType = $stepType
Index = $i
}
)

$i++
continue
}

$context.EventSink.WriteEvent('StepStarted', "Step '$stepName' started.", $stepName, @{
StepType = $stepType
Index = $i
})
$context.EventSink.WriteEvent(
'StepStarted',
"Step '$stepName' started.",
$stepName,
@{
StepType = $stepType
Index = $i
}
)

try {
$impl = Resolve-IdleStepHandler -StepType ([string]$stepType) -StepRegistry $stepRegistry
Expand Down Expand Up @@ -415,19 +430,29 @@ function Invoke-IdlePlanObject {
if ($result.Status -eq 'Failed') {
$failed = $true

$context.EventSink.WriteEvent('StepFailed', "Step '$stepName' failed.", $stepName, @{
StepType = $stepType
Index = $i
Error = $result.Error
})
$context.EventSink.WriteEvent(
'StepFailed',
"Step '$stepName' failed.",
$stepName,
@{
StepType = $stepType
Index = $i
Error = $result.Error
}
)

break
}

$context.EventSink.WriteEvent('StepCompleted', "Step '$stepName' completed.", $stepName, @{
StepType = $stepType
Index = $i
})
$context.EventSink.WriteEvent(
'StepCompleted',
"Step '$stepName' completed.",
$stepName,
@{
StepType = $stepType
Index = $i
}
)
}
catch {
$failed = $true
Expand All @@ -442,11 +467,16 @@ function Invoke-IdlePlanObject {
Attempts = 1
}

$context.EventSink.WriteEvent('StepFailed', "Step '$stepName' failed.", $stepName, @{
StepType = $stepType
Index = $i
Error = $err.Exception.Message
})
$context.EventSink.WriteEvent(
'StepFailed',
"Step '$stepName' failed.",
$stepName,
@{
StepType = $stepType
Index = $i
Error = $err.Exception.Message
}
)

break
}
Expand All @@ -470,9 +500,14 @@ function Invoke-IdlePlanObject {
}

if ($failed -and @($planOnFailureSteps).Count -gt 0) {
$context.EventSink.WriteEvent('OnFailureStarted', 'Executing OnFailureSteps (best effort).', $null, @{
OnFailureStepCount = @($planOnFailureSteps).Count
})
$context.EventSink.WriteEvent(
'OnFailureStarted',
'Executing OnFailureSteps (best effort).',
$null,
@{
OnFailureStepCount = @($planOnFailureSteps).Count
}
)

$onFailureHadFailures = $false
$onFailureStepResults = @()
Expand Down Expand Up @@ -502,19 +537,29 @@ function Invoke-IdlePlanObject {
Attempts = 1
}

$context.EventSink.WriteEvent('OnFailureStepNotApplicable', "OnFailure step '$ofName' not applicable (condition not met).", $ofName, @{
StepType = $ofType
Index = $j
})
$context.EventSink.WriteEvent(
'OnFailureStepNotApplicable',
"OnFailure step '$ofName' not applicable (condition not met).",
$ofName,
@{
StepType = $ofType
Index = $j
}
)

$j++
continue
}

$context.EventSink.WriteEvent('OnFailureStepStarted', "OnFailure step '$ofName' started.", $ofName, @{
StepType = $ofType
Index = $j
})
$context.EventSink.WriteEvent(
'OnFailureStepStarted',
"OnFailure step '$ofName' started.",
$ofName,
@{
StepType = $ofType
Index = $j
}
)

try {
$impl = Resolve-IdleStepHandler -StepType ([string]$ofType) -StepRegistry $stepRegistry
Expand Down Expand Up @@ -564,17 +609,27 @@ function Invoke-IdlePlanObject {
if ($result.Status -eq 'Failed') {
$onFailureHadFailures = $true

$context.EventSink.WriteEvent('OnFailureStepFailed', "OnFailure step '$ofName' failed.", $ofName, @{
StepType = $ofType
Index = $j
Error = $result.Error
})
$context.EventSink.WriteEvent(
'OnFailureStepFailed',
"OnFailure step '$ofName' failed.",
$ofName,
@{
StepType = $ofType
Index = $j
Error = $result.Error
}
)
}
else {
$context.EventSink.WriteEvent('OnFailureStepCompleted', "OnFailure step '$ofName' completed.", $ofName, @{
StepType = $ofType
Index = $j
})
$context.EventSink.WriteEvent(
'OnFailureStepCompleted',
"OnFailure step '$ofName' completed.",
$ofName,
@{
StepType = $ofType
Index = $j
}
)
}
}
catch {
Expand All @@ -590,11 +645,16 @@ function Invoke-IdlePlanObject {
Attempts = 1
}

$context.EventSink.WriteEvent('OnFailureStepFailed', "OnFailure step '$ofName' failed.", $ofName, @{
StepType = $ofType
Index = $j
Error = $err.Exception.Message
})
$context.EventSink.WriteEvent(
'OnFailureStepFailed',
"OnFailure step '$ofName' failed.",
$ofName,
@{
StepType = $ofType
Index = $j
Error = $err.Exception.Message
}
)
}

$j++
Expand All @@ -608,17 +668,27 @@ function Invoke-IdlePlanObject {
Steps = @($onFailureStepResults)
}

$context.EventSink.WriteEvent('OnFailureCompleted', "OnFailureSteps finished (status: $onFailureStatus).", $null, @{
Status = $onFailureStatus
StepCount = @($planOnFailureSteps).Count
})
$context.EventSink.WriteEvent(
'OnFailureCompleted',
"OnFailureSteps finished (status: $onFailureStatus).",
$null,
@{
Status = $onFailureStatus
StepCount = @($planOnFailureSteps).Count
}
)
}

# RunCompleted should always be the last event for deterministic event order.
$context.EventSink.WriteEvent('RunCompleted', "Plan execution finished (status: $runStatus).", $null, @{
Status = $runStatus
StepCount = @($Plan.Steps).Count
})
$context.EventSink.WriteEvent(
'RunCompleted',
"Plan execution finished (status: $runStatus).",
$null,
@{
Status = $runStatus
StepCount = @($Plan.Steps).Count
}
)

# Issue #48:
# Redact provider configuration/state at the output boundary (execution result).
Expand Down
4 changes: 2 additions & 2 deletions src/IdLE.Core/Public/New-IdlePlanObject.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function New-IdlePlanObject {
return $null
}

$m = $Object | Get-Member -Name $Name -MemberType NoteProperty,Property -ErrorAction SilentlyContinue
$m = $Object | Get-Member -Name $Name -MemberType NoteProperty, Property -ErrorAction SilentlyContinue
if ($null -eq $m) {
return $null
}
Expand Down Expand Up @@ -378,7 +378,7 @@ function New-IdlePlanObject {
return $Step.ContainsKey($Key)
}

$m = $Step | Get-Member -Name $Key -MemberType NoteProperty,Property -ErrorAction SilentlyContinue
$m = $Step | Get-Member -Name $Key -MemberType NoteProperty, Property -ErrorAction SilentlyContinue
return ($null -ne $m)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function Invoke-IdleStepEnsureEntitlement {
This provider-agnostic step uses entitlement provider contracts to converge
an assignment to the desired state. The host must supply a provider instance
via `Context.Providers[<ProviderAlias>]` that implements:

- ListEntitlements(identityKey)
- GrantEntitlement(identityKey, entitlement)
- RevokeEntitlement(identityKey, entitlement)
Expand Down
Loading