I am trying to create to create a new project and add “script step” or “Run As Script” using Octopus REST API.
New Octopus Project gets created using REST API. However, which script is trying to add “script step” or “Run As Script” , it is throwing Error : Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
Hey there Vivek, thanks for reaching out. Are you using the self-hosted version of Octopus or are you using Octopus Cloud? If you’re using the self-hosted version, you should be able to see what the error is by viewing the Diagnostics tab. This will usually point out what the problem is. I’ll take a gander at the script to see if anything immediately pops out.
I copied your script and did some testing. I was able to get it to fail with a 400 error when the $ScriptBody variable was null or empty. Please check that variable to ensure it has something
I have Powershell script which is “IIS-AppPool-Stop.ps1” in same directory along with the script which I have originally posted. If you wanted to test and try, I would request you to save both script and same directory and try to execute it through PowerShell ISE.
$ScriptBody variable is holding the content of script “IIS-AppPool-Stop.ps1” and the snippet for this is
# Self Elevating Administrator Permission
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
# Convert The Standard Senstive Text Password To Encrypted Password
$SecureStringPassword = ConvertTo-SecureString -String $($UATServiceAccountPassword) -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $($UATServiceAccount), $($SecureStringPassword)
# Stop IIS App Pool On Current Web Server
# Importing WebAdministration Module
Import-Module -Name "WebAdministration" -Force
# Stop IIS Application Pool
$CurrentServer = ([System.Net.Dns]::GetHostByName($env:computerName)).HostName
Write-Output "Stopping $($AppPoolName) Application Pool Is Initiated On Server $($CurrentServer)...`n"
# Get The Number Of Retries
$Retries = "500"
# Get The Number Of Attempts
$Delay = "200"
# Check If Application Pool Exists
if ((Test-Path -Path "IIS:\AppPools\$($AppPoolName)") -eq "True") {
# Stop App Pool If Not Already Stopped
if ((Get-WebAppPoolState -Name $($AppPoolName)).Value -ne "Stopped") {
Stop-WebAppPool -Name $($AppPoolName)
$State = (Get-WebAppPoolState -Name $($AppPoolName)).Value
$Counter = 1
# Wait For The App Pool To Be "Stopped"
do {
$State = (Get-WebAppPoolState -Name $($AppPoolName)).Value
Write-Output "$Counter/$Retries Waiting For IIS App Pool $($AppPoolName) To Stop Completely. Current Status Is: $($State)"
$Counter++
Start-Sleep -Milliseconds $Delay
}
while ($($State) -ne "Stopped" -and ($Counter -le $($Retries)))
# Throw An Error If The App Pool Is Not Stopped
if ($($Counter) -gt $($Retries)) {
throw "Could Not Stop IIS App Pool $($AppPoolName). `nTry To Increase The Number Of Retries $($Retries) Or Delay Between Attempts $($Delay) Milliseconds)."
}
}
else {
Write-Output "Application Pool $($AppPoolName) Is Already Stopped`n"
}
}
else {
Write-Error "IIS App Pool $($AppPoolName) Doesn't Exist`n"
}
Write-Output "Stopping $($AppPoolName) Application Pool Is Initiated On Server $($CurrentServer) Is Completed !!!`n"
# Stop IIS App Pool On Sets Of Web Servers
foreach ($Server in $($Servers)) {
$Session = New-PSSession –ComputerName $($Server) -Credential $($Credential)
Invoke-Command -Session $($Session) -ArgumentList $($AppPoolName), $($Server) {
$AppPoolName = $Args[0]
$Server = $Args[1]
# Self Elevating Administrator Permission
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
# Importing WebAdministration Module
Import-Module -Name "WebAdministration" -Force
# Stop IIS Application Pool
Write-Output "Stopping $($AppPoolName) Application Pool Is Initiated On Server $($Server)...`n"
# Get The Number Of Retries
$Retries = "500"
# Get The Number Of Attempts
$Delay = "200"
# Check If Application Pool Exists
if ((Test-Path -Path "IIS:\AppPools\$($AppPoolName)") -eq "True") {
# Stop App Pool If Not Already Stopped
if ((Get-WebAppPoolState -Name $($AppPoolName)).Value -ne "Stopped") {
Stop-WebAppPool -Name $($AppPoolName)
$State = (Get-WebAppPoolState -Name $($AppPoolName)).Value
$Counter = 1
# Wait For The App Pool To Be "Stopped"
do {
$State = (Get-WebAppPoolState -Name $($AppPoolName)).Value
Write-Output "$Counter/$Retries Waiting For IIS App Pool $($AppPoolName) To Stop Completely. Current Status Is: $($State)"
$Counter++
Start-Sleep -Milliseconds $Delay
}
while ($($State) -ne "Stopped" -and ($Counter -le $($Retries)))
# Throw An Error If The App Pool Is Not Stopped
if ($($Counter) -gt $($Retries)) {
throw "Could Not Stop IIS App Pool $($AppPoolName). `nTry To Increase The Number Of Retries $($Retries) Or Delay Between Attempts $($Delay) Milliseconds)"
}
}
else {
Write-Output "Application Pool $($AppPoolName) Is Already Stopped`n"
}
}
else {
Write-Error "IIS App Pool $($AppPoolName) Doesn't Exist`n"
}
Write-Output "Stopping $($AppPoolName) Application Pool Is Initiated On Server $($Server) Is Completed !!!`n"
}
Remove-PSSession -Session $($Session)
}
Thanks Vivek, I added that content to the script file and successfully tested, so it’s not the script content. There is one difference that I noted, I put the switch statement OctopusProjectABC into double quotes, "OctopusProjectABC". Would you be able to give that a try to see if the switch statement goes through the correct path?
I have tried to do it the way suggested , however no luck with that. In fact, I have I have moved from switch statement to simpler logic. Also, this is to update you that, I am using octopus deploy cloud version. Along with, I do not see any logical issue as well if I want to use Get-Content and pass the variable value to $ScriptBody.
You have mentioned that it is working for you, Can I have the snippet ? . I am wondering if I can see desired output in json payload then why it is not uploading ?. Is it something octopus cloud version doesn’t support the approach I am doing ?
One More Point :
If do paste the content of the file between @’ & '@ with out variable interpolation like below then it works. So, It is staange to see it, becuase the previous method we are using does have valid json but still not able to upload.
I have fix the issue. I have change the foreach loop content in “IIS-AppPool-Stop.ps1” where it was not the issue with original content, it seems that octopus deploy both on-prem and cloud version have some issue with “New-PSSession” command or syntax.
New Content
# Stop IIS App Pool On Sets Of Web Servers
foreach ($Server in $($Servers)) {
$Parameters = @{
ComputerName = "$($Server)"
ArgumentList = "$($AppPoolNameUS)"
ScriptBlock = {
$AppPoolNameUS = $Args[0]
# Self Elevating Administrator Permission
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
# Importing WebAdministration Module
Import-Module -Name "WebAdministration" -Force
# Stop IIS Application Pool
Write-Output "`nStopping $($AppPoolNameUS) Application Pool Is Initiated On Server $($Server)...`n"
# Get The Number Of Retries
$Retries = "500"
# Get The Number Of Attempts
$Delay = "200"
# Check If Application Pool Exists
if ((Test-Path -Path "IIS:\AppPools\$($AppPoolNameUS)") -eq "True") {
# Stop App Pool If Not Already Stopped
if ((Get-WebAppPoolState -Name $($AppPoolNameUS)).Value -ne "Stopped") {
Stop-WebAppPool -Name $($AppPoolNameUS)
$State = (Get-WebAppPoolState -Name $($AppPoolNameUS)).Value
$Counter = 1
# Wait For The App Pool To Be "Stopped"
do {
$State = (Get-WebAppPoolState -Name $($AppPoolNameUS)).Value
Write-Output "$Counter/$Retries Waiting For IIS App Pool $($AppPoolNameUS) To Stop Completely. Current Status Is: $($State)"
$Counter++
Start-Sleep -Milliseconds $Delay
}
while ($($State) -ne "Stopped" -and ($Counter -le $($Retries)))
# Throw An Error If The App Pool Is Not Stopped
if ($($Counter) -gt $($Retries)) {
throw "Could Not Stop IIS App Pool $($AppPoolNameUS). `nTry To Increase The Number Of Retries $($Retries) Or Delay Between Attempts $($Delay) Milliseconds)"
}
}
else {
Write-Output "Application Pool $($AppPoolNameUS) Is Already Stopped`n"
}
}
else {
Write-Error "IIS App Pool $($AppPoolNameUS) Doesn't Exist`n"
}
Write-Output "`nStopping $($AppPoolNameUS) Application Pool Is Initiated On Server $($Server) Is Completed !!!`n"
}
}
Invoke-Command @Parameters
}
OLD CONTENT
# Stop IIS App Pool On Sets Of Web Servers
foreach ($Server in $($Servers)) {
$Session = New-PSSession –ComputerName $($Server) -Credential $($Credential)
Invoke-Command -Session $($Session) -ArgumentList $($AppPoolNameUS), $($Server) {
$AppPoolNameUS = $Args[0]
$Server = $Args[1]
# Self Elevating Administrator Permission
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
# Importing WebAdministration Module
Import-Module -Name "WebAdministration" -Force
# Stop IIS Application Pool
Write-Output "`nStopping $($AppPoolNameUS) Application Pool Is Initiated On Server $($Server)...`n"
# Get The Number Of Retries
$Retries = "500"
# Get The Number Of Attempts
$Delay = "200"
# Check If Application Pool Exists
if ((Test-Path -Path "IIS:\AppPools\$($AppPoolNameUS)") -eq "True") {
# Stop App Pool If Not Already Stopped
if ((Get-WebAppPoolState -Name $($AppPoolNameUS)).Value -ne "Stopped") {
Stop-WebAppPool -Name $($AppPoolNameUS)
$State = (Get-WebAppPoolState -Name $($AppPoolNameUS)).Value
$Counter = 1
# Wait For The App Pool To Be "Stopped"
do {
$State = (Get-WebAppPoolState -Name $($AppPoolNameUS)).Value
Write-Output "$Counter/$Retries Waiting For IIS App Pool $($AppPoolNameUS) To Stop Completely. Current Status Is: $($State)"
$Counter++
Start-Sleep -Milliseconds $Delay
}
while ($($State) -ne "Stopped" -and ($Counter -le $($Retries)))
# Throw An Error If The App Pool Is Not Stopped
if ($($Counter) -gt $($Retries)) {
throw "Could Not Stop IIS App Pool $($AppPoolNameUS). `nTry To Increase The Number Of Retries $($Retries) Or Delay Between Attempts $($Delay) Milliseconds)"
}
}
else {
Write-Output "Application Pool $($AppPoolNameUS) Is Already Stopped`n"
}
}
else {
Write-Error "IIS App Pool $($AppPoolNameUS) Doesn't Exist`n"
}
Write-Output "`nStopping $($AppPoolNameUS) Application Pool Is Initiated On Server $($Server) Is Completed !!!`n"
}
Remove-PSSession -Session $($Session)
}