Files
vault/Career/Microlise/ESS ESP/Remote-Session Script.md
Zaine 129ce1442b
Some checks failed
Build Quartz Notes / build (push) Failing after 20s
13
2026-07-13 09:16:09 +01:00

7.0 KiB
Executable File
Raw Blame History

note type, date, done
note type date done
ess
note
2026-06-11

Reference script (TMC Session.ps1)

1. What is the pool key?

The server name string ($serverName).

flowchart LR
    serverName["serverName: APP01"]
    pool["remoteSessionPool hashtable"]
    session["PSSession object"]

    serverName -->|"used as key"| pool
    pool --> session

Same server name → same pool entry. Different server → different entry.

Caveat for your task: if the same server could be reached with different credentials, keying only on server name can return the wrong session. For a first version, matching the reference (key = server name) is fine if credentials are consistent per server.


2. What happens on the second call for the same server?

sequenceDiagram
    participant Caller
    participant GetRemoteSession as Get-RemoteSession
    participant Pool
    participant NewPSSession as New-PSSession

    Caller->>GetRemoteSession: serverName = APP01
    GetRemoteSession->>Pool: lookup APP01
    Pool-->>GetRemoteSession: session found
    GetRemoteSession-->>Caller: existing session
    Note over NewPSSession: not called
  • Pool lookup hits.
  • Logs something like “Using existing remote session”.
  • Returns the cached session.
  • New-PSSession is not called — thats the whole point of the pool.

3. When is New-PSSession called vs skipped?

Condition Action
Pool has an entry for $serverName Skip New-PSSession, return cached session
Pool has no entry for $serverName Call New-PSSession, store result in pool, return it
flowchart TD
    start[Get-RemoteSession called]
    lookup{Pool contains serverName?}
    reuse[Log: using existing session]
    create[Log: creating session]
    newPs[New-PSSession]
    store[Store in pool]
    return[Return session]

    start --> lookup
    lookup -->|yes| reuse --> return
    lookup -->|no| create --> newPs --> store --> return

Important: Get-RemoteSession creates/reuses the session. Invoke-Command -Session $session is a separate step the caller does afterward (e.g. Test-Path on the remote box).


4. What happens when session creation fails? Does that fit ESS?

In the reference: if $session is falsy after New-PSSession, it logs an error and runs exit (ends the whole PowerShell process).

In ESS capabilities: that does not fit. Look at Remove-Folder.psm1 — failures use throw, not exit.

TMC reference ESS pattern
Failure exit throw "message"
Why Script runner stops everything Pester, pipelines, and orchestrators can catch/handle it

For your module: log with Write-Log -Level ERROR, then throw so deployment fails cleanly and tests can use Should -Throw.


Design decisions (for your implementation)

Parameters

Match the reference, adapted to ESS style:

  • ServerName (mandatory) — pool key and New-PSSession target.
  • Credential (optional) — pass through when present; omit when using default/current-user auth.

Do not put remote script logic (e.g. Test-Path) inside Get-RemoteSession. Callers get a session, then run Invoke-Command themselves.


Pool scope — where does the hashtable live?

At module scope in the .psm1, above the function — not inside the function body.

flowchart TB
    subgraph psm1 [Get-RemoteSession.psm1]
        poolVar["script-scoped pool hashtable"]
        func[Get-RemoteSession function]
        poolVar --> func
    end

    call1[First call] --> func
    call2[Second call] --> func
    func --> poolVar

If the pool is inside the function, it is recreated every call and caching never works.

Use $script: scope so the pool belongs to the module instance, not the global session (unless you deliberately want global — you dont for this task).


Naming: Get-RemoteSession vs New-RemoteSession

Verb Meaning here
New-* Always creates something new
Get-* Retrieves existing or obtains one if needed

Your function is “get from pool, or create and cache” → Get-RemoteSession is the right approved verb.


Logging

Use Write-Log (from Core.Logging.psm1), not TMCs Logging.

Worth logging:

  • INFO — “Using existing…” vs “Creating…”
  • INFO — elapsed time for creation only (optional but matches the reference and helps debug slow WinRM)
  • ERROR — before you throw on failure

Failure behavior

flowchart LR
    fail[New-PSSession fails or returns nothing]
    log[Write-Log ERROR]
    throwNode[throw with clear message]

    fail --> log --> throwNode

No exit. Callers and Pester expect exceptions, not process termination.


Pool key edge case (same server, different credentials)

Reference keys only on server name. Implication:

flowchart TD
    callA["Call: APP01 + CredA"] --> pool1[Pool stores APP01 → sessionA]
    callB["Call: APP01 + CredB"] --> pool2[Pool returns sessionA]
    pool2 --> wrong[Wrong cred — sessionA reused]

For learning / v1: same as reference is OK if each server always uses one credential set. If thats not true later, the key would need to include something credential-related — out of scope unless your manifests require it.


How this connects to Invoke-Command

sequenceDiagram
    participant Step as Deployment step
    participant Get as Get-RemoteSession
    participant IC as Invoke-Command

    Step->>Get: ServerName, Credential
    Get-->>Step: $session
    Step->>IC: -Session $session -ScriptBlock { Test-Path ... }
    IC-->>Step: $fileExists

Get-RemoteSession = connection management.
Invoke-Command = run code on the remote machine.


Testing note (relevant to your attached snippet)

For “fails when session cannot be created”, assert like other capabilities:

  • { Get-RemoteSession ... } | Should -Throw — proves the function throws.
  • Optionally assert Write-Log was called with -Level ERROR.

Should -Invoke Throw is not valid Pester — throw is a language statement, not a mockable cmdlet. Same idea as Remove-Folder.Tests.ps1: use Should -Throw on the script block, and Should -Invoke Write-Log for the error log line.

For pool behavior tests: mock New-PSSession, call the function twice with the same server, expect New-PSSession invoked once.


One-line summary

Question Answer
Pool key Server name
Second call Return cached session; no New-PSSession
When to create Only when key missing from pool
On failure Reference: exityou: Write-Log + throw
Pool location Module-level $script: hashtable, not inside the function