03 / RELIABLE ADMINISTRATION TOOLS · LESSON 11

Make a configuration update repeatable

Apply only declared differences and report when a second run has nothing left to change.

15 min · learn at your pace

Ask whether a write is needed

A repeatable administration operation converges on a desired state. Running it again with the same inputs should not append duplicates, erase unrelated values, or keep claiming new work. This property is often called idempotence.

Compare the declared desired keys with the current flat JSON settings. Record missing or different keys before changing them. If that collection is empty, skip the write entirely and return Changed false with an empty ChangedKeys array.

$desired = @{ LogRetentionDays=30; BackupEnabled=$true }
$desired.Keys | Sort-Object

Manage only what you own

Merge the declared keys into the current settings rather than replacing the whole document with the desired subset. A local note or another application's setting is outside this tool's scope. A missing key and a present false value still require separate presence checks.

Return one structured result with a boolean Changed and a sorted ChangedKeys array. Keep that array shape for zero, one, or many changes. Consumers can then summarise how much work occurred without scraping terminal messages.

The task manages flat scalar values with consistent types; it does not attempt a general recursive JSON merge. It also assumes one writer at a time. Real concurrent configuration updates need a strategy for detecting conflicts and preserving an appropriate rollback copy.

The checker invokes your function twice, on a single-key change, and on an empty desired set. The second call must leave the saved bytes alone.

Try an example.ps1
Get-Content '/home/user/settings.json' -Raw | ConvertFrom-Json -AsHashtable
YOUR TURN

Put it into practice.

Define Set-DesiredSettings -Path -Desired <hashtable>. Merge only missing or different declared scalar keys into the JSON file, preserving unrelated settings. Return one object with boolean Changed and a sorted ChangedKeys array. If nothing differs, do not write the file. Handle zero, one, and many changed keys. Define the function without modifying settings.json from your main script.

See an explained solution
One way to solve it.ps1
function Set-DesiredSettings {
    param([string]$Path, [hashtable]$Desired)
    $current = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop | ConvertFrom-Json -AsHashtable -ErrorAction Stop
    $keys = @($Desired.Keys | Where-Object { -not $current.Contains($_) -or $current[$_] -ne $Desired[$_] } | Sort-Object)
    if ($keys.Count) {
        foreach ($key in $keys) { $current[$key] = $Desired[$key] }
        $current | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $Path -ErrorAction Stop
    }
    [pscustomobject]@{ Changed=($keys.Count -gt 0); ChangedKeys=$keys }
}

The change list is both a decision about whether to write and an honest result for the caller. Merging preserves unmanaged settings; an empty difference set produces no write and a stable second result.