'Powershell Script working fine in Visual Code but fails running from Terminal
I'm working on writing a script which will run from AzDo Pipeline to disable F5 WebServers. Below script works fine in Visual Code and does disable the server as expected . But when running from the terminal or PS window fails with the below error . Can someone please help.
$ServerInput = 'server1.abc.com'
$BIGIPBaseURL = "https://ser-f5-1.prod.abc.com"
$usr = "nilesh"
$SecurePassword='P@assword'
Write-Host "Starting the Script..."
# Initialize variables
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$BIGIPToken = $null
Write-Host -ForegroundColor Green " done!"
$DisableWebServers = $true
# Initialize functions
Write-Host "Initializing functions..." -NoNewline
$PSVersionTable
function Disable-BIGIPNode([string]$NodeName) {
# servers should use the Disable-BIGIPTelcoNode() function
Write-Host "In the Disable function"
if ($NodeName -match "(?i).*telco.*") {
Write-Host -ForegroundColor Yellow "WARNING: `"$($NodeName.ToUpper().Split('.')[0])`" is in the wrong list. telcoo hosts should be added to the TelcoServers list in your input file."
BREAK
}
else {
if ($BIGIPToken -eq $null) {
Write-Host "Now will enter the Open-Session"
Open-BIGIPSession
}
Write-Host "Disabling node `"$($NodeName.ToUpper().Split('.')[0])`" in BIG-IP..." -NoNewline
$WebRequestInput = @{
body = @{
"session" = "user-disabled"
} | ConvertTo-Json
uri = $($BIGIPBaseURL) + "/mgmt/tm/ltm/node/~Common~" + $NodeName.ToLower()
headers = @{
"Content-Type" = "application/json"
"X-F5-Auth-Token" = "$BIGIPToken"
}
method = "PATCH"
}
Write-Host $WebRequestInput
Write-Host $WebRequestInput.body
try {
Write-Host "In the final try block"
$Request = Invoke-WebRequest @WebRequestInput -UseBasicParsing -SkipCertificateCheck
}
catch {
Write-Host -ForegroundColor Red " failed!"
Write-Host -ForegroundColor Red ($_.ErrorDetails | ConvertFrom-Json).Message
}
Write-Host -ForegroundColor Green " done!"
$global:ZabbixRequestID++
}
}
function Open-BIGIPSession() {
Write-Host "Authenticating with BIG-IP API..." -NoNewline
$WebRequestInput = @{
body = @{
username = "$usr"
password = "$SecurePassword"
loginProviderName = "tmos"
} | ConvertTo-Json
uri = $ScriptInput.BIGIPBaseURL + "/mgmt/shared/authn/login"
headers = @{
"Content-Type" = "application/json"
}
method = "POST"
}
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$Request = Invoke-WebRequest @WebRequestInput -UseBasicParsing -SkipCertificateCheck
}
catch {
Write-Host -ForegroundColor Red " failed!"
Write-Host -ForegroundColor Red ($_.ErrorDetails | ConvertFrom-Json).Message
EXIT 1
}
Write-Host -ForegroundColor Green " done!"
$global:BIGIPToken = ($Request.Content | ConvertFrom-Json).token.token
}
if ($DisableWebServers) {
Write-Host "Starting the main Methord "
foreach ($Server in $($ServerInput)) {
Disable-BIGIPNode -NodeName $Server
}
}
The PowerShell version is PSVersion 7.2.2
Disabling node "SAC-DEV-WEB2" in BIG-IP...System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.DictionaryEntry
{
"session": "user-disabled"
}
In the final try block
failed!
ConvertFrom-Json: C:\Temp\Testing.ps1:49:64
Line |
49 | … Host -ForegroundColor Red ($_.ErrorDetails | ConvertFrom-Json).Messag …
| ~~~~~~~~~~~~~~~~
| Conversion from JSON failed with error: Additional text encountered after finished reading JSON content: U. Path '', line
| 3, position 4.
Its working fine when running from VsCode but fails if called with the file name from the same terminal
like .\Testing.ps1
Please help
Solution 1:[1]
Your incidental problem is that the true error message is being obscured by a follow-up error that results from attempting to parse the error record's
.ErrorDetailsproperty as JSON, which it isn't. (You report that examining the true error reveals a 401 authentication error).I have no specific explanation for the difference in behavior you're seeing between running in Visual Studio Code vs. in a regular PowerShell console, but I have a guess:
Your Visual Studio Code session in the so-called PowerShell Integrated Console may have lingering state from earlier debugging runs, which may mask a bug in your script.
Restarting Visual Studio Code should clarify whether that is the case, but there's also a way to configure the PowerShell extension so that the problem doesn't arise to begin with - see below.
By default, code you run (debug) via the Visual Code PowerShell extension executes in the same PowerShell session, directly in the global scope.
That is, running a script being edited, say,
foo.ps1, in the debugger is effectively the same as invoking it with. .\foo.ps1, i.e. it is in effect dot-sourced.Therefore, a given debugging run can be affected by earlier runs, because the state of earlier runs lingers.
This can result in bugs going undetected, such as in the following example:
Say your script defines variable
$fooand uses it throughout the script. If you debug your script at least one,$foois now defined in the PowerShell session in the PowerShell Integrated Console.Say you then change the name to
$bar, but you forget to also replace (all) references to$foowith$bar.Your script is now effectively broken, but you won't notice in the same session, because
$foois still around from earlier debugging runs.- However, running the script from a regular PowerShell console would surface the problem.
The obsolescent Windows PowerShell ISE exhibits the same unfortunate behavior, invariably so, but fortunately there is a solution for the PowerShell extension - see next point.
You can avoid this problem by activating the
Create Temporary Integrated Consolesetting (viaFile > Preferences > Settingsor Ctrl+,), which ensure that every debugging run creates a new, temporary session to run in, which starts with a clean slate:Whenever a new temporary session is started, any previous one is automatically discarded.
A temporary session has prefix
[TEMP]in the list of running shells in the integrated terminal.You pay a performance penalty, because a new PowerShell session must be created for every run, and you lose the previous session's display output - but I suspect avoiding the pitfalls of lingering state is worth the price.
Note that, in a given temporary session, the dot-sourced invocation described above still applies, but with the lingering-state problem out of the picture, it can now be considered an advantage: After the script finishes, and before the temporary session is replaced with a new one, the variables and functions defined in the script's top-level scope are then available for inspection.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
