Thanks for getting in touch! I’m sorry to see you’re hitting this unexpected difference in behavior. I haven’t been able to reproduce this, however. Tables seem to be formatted in the same way in my testing. Would you be willing to enable debugging variables, create and deploy a new release and send the resulting verbose task log? Hopefully that’ll point us in the right direction in figuring this out, or help in reproducing this more accurately.
I am happy to run it with the debugging variables, but I should have mentioned in my original post that this tentacle is a Linux Tentacle. If this does not repro on a windows tentacle, then I would imagine this is a Linux specific problem. (I have had other formatting issues in regards to a Linux Tentacles and PowerShell in the past.)
In case it is relevant, my Tentacle is running version 6.1.1409 of the container image and PowerShell 7.2.2.
Sorry for not mentioning this right away. If this does not repro on a Linux Tentacle, I will setup a run with the debug variables.
Thanks for following up and for your additional information. I have been able to reproduce a portion of this issue when run on Linux, however only the formatting issue. It looks like the e[32;1m correlates to ANSI color code, and instead of just being hidden they’re inserted into the start of the line, pushing the column headers and --- separators over 7 spaces but not the data beneath.
I haven’t sorted out a definitive solution in my local repro, but just wanted to let you know I’m still working on this one and hoping to get something working today.
Regarding the outright missing columns, e.g. Environment, TenantName, etc. I’m wondering if this might be related to permissions. When you run the same script via the console, compared to when running it against your Linux target in Octopus, are these run as different users? Perhaps there’s a discrepancy between the two users and their privileges to see these specific objects. E.g. something like the API key used in your Octopus script is owned by a user who does not have permission to view the Dev and DevUnstable environments, and similarly they cannot view your Blue & Green tenants?
The color code thing makes sense, though I have to wonder why PowerShell put that into the Linux version if it is not there in the Windows version.
As for the permissions, the user I am making the calls as (via the API Key) is a Space Manager for all the Octopus Deploy space’s my scripts run in or access. Additionally, I access the underlying data in some conditionals and other logic and it all works correctly.
I’m still attempting to sort this one out, but I agree it does seem odd that it’s putting that in when running on Linux but not Windows.
I think it’d be worth attempting to repro this exactly as you have it to also get a look at the other issue not showing the other columns and their data at the same time. How is the $unfinishedRedeployments variable built up? Would you be willing to share your full script for me to test (retracting any sensitive details)? Feel free to upload it here if preferred.
Here is the script I run to build up that variable. Its purpose is to redeploy all of the projects in a given space. (I do this when I swap out my Kuberentes cluster and need to re-setup a new one.)
I seriously doubt that all of this is needed to recreate the issue. I imagine just making the $redeployments list will be enough. But it is all here incase you need it:
$octopusBaseUrl = $OctopusParameters["OctopusBaseUrl"]
$targetSpaceId = $OctopusParameters["KuberentesApplicationsSpaceId"]
$octopusApiKey = $OctopusParameters["OctopusApiKey"]
$headers = @{ "X-Octopus-ApiKey" = $octopusApiKey }
$archEnvironmentName = $OctopusParameters["ArchEnvironmentName"]
$projectIdsToIgnore = $OctopusParameters["ProjectsToIgnore"]
$isTestRun = ([System.Convert]::ToBoolean($OctopusParameters["IsTestRun"]))
if ($isTestRun -eq $true)
{
Write-Highlight "Testing Only Run"
}
# Get our list of projects
$projects = (Invoke-WebRequest "$octopusBaseUrl/api/$targetSpaceId/projects/all" -Headers $headers).content | ConvertFrom-Json
$projectListToIgnore = $projectIdsToIgnore.Split(",")
$projectsToIgnore = $projects | Where-Object {$_.Id -in $projectListToIgnore}
Write-Output "Going to ignore the following projects: $($projectsToIgnore.Name -join ", ")"
Write-Output "Found $($projects.Count - $projectsToIgnore.Count) unignored projects in $($space.Name) space"
# Get our list of Tenants
$tenants = (Invoke-WebRequest "$octopusBaseUrl/api/$targetSpaceId/tenants/all" -Headers $headers).content | ConvertFrom-Json
# Get our list of Environments
$environments = (Invoke-WebRequest "$octopusBaseUrl/api/$targetSpaceId/environments/all" -Headers $headers).content | ConvertFrom-Json
class Redeployment
{
Redeployment()
{
$this.IsFinished = $false
}
[string]$TaskId
[string]$ProjectName
[string]$ProjectId
[string]$Version
[string]$Environment
[string]$EnvironmentId
[string]$TenantName
[string]$TenantId
[bool]$IsFinished
[bool]$WasSuccessful
}
$redeployments = New-Object Collections.Generic.List[Redeployment]
Write-Output "Starting up redeploy of all projects"
foreach ($tenant in $tenants)
{
Write-Debug "Starting $($tenant.Name) Pipeline"
foreach ($projectEnvironment in $tenant.ProjectEnvironments.PsObject.Properties)
{
$project = $projects | Where-Object {$_.Id -eq $projectEnvironment.Name}
if ($projectListToIgnore -contains $project.Id)
{
Write-Debug " * Project $($project.Name) is on the ignore list, skipping redeploy"
}
else
{
Write-Debug " Starting project $($project.Name) - $($project.Id)"
$progressionInformation = (Invoke-WebRequest "$octopusBaseUrl/api/$targetSpaceId/progression/$($project.Id)" -Headers $headers).content | ConvertFrom-Json
# Though not really required, lets sort the environments so we deploy them in order
$environmentsForProject = $environments | Where-Object {$_.Id -in $projectEnvironment.Value} | Sort-Object SortOrder
foreach ($environment in $environmentsForProject)
{
# Check to see if we should be running this environment
# If this run is NOT targeting the Prod ArchEnv and the env is Prod, then we need to skip it.
if (($archEnvironmentName -ne "Prod" -and $environment.Name -eq "Prod") -or
# If this run IS targeting the Prod ArchEnv and the env is NOT Prod, then we need to skip it.
($archEnvironmentName -eq "Prod" -and $environment.Name -ne "Prod"))
{
continue;
}
Write-Debug " Starting env $($environment.Name)"
$foundRelease = ""
$isReleaseFoundForEnvAndTenant = $false
# These are ordered newest to oldest. So the first successful one we find in our environment, is the one we want.
# If there is not one then the env, does not have any successful releases.
foreach($release in $progressionInformation.Releases)
{
foreach($deploymentEnvironments in $release.Deployments)
{
if (Get-Member -InputObject $deploymentEnvironments -Name $($environment.Id) -MemberType Properties )
{
$deployments = $deploymentEnvironments | Select-Object -ExpandProperty $environment.Id
$deployments = $deployments | Where-Object {$_.TenantId -eq $tenant.Id -and $_.State -eq "Success"}
if ($deployments)
{
$foundRelease = $release.Release
$isReleaseFoundForEnvAndTenant = $true
Write-Debug " - $($release.Release.Version)"
break
}
}
}
if ($isReleaseFoundForEnvAndTenant)
{
break
}
}
if ($isReleaseFoundForEnvAndTenant)
{
Write-Output "Redeploying: $($project.Name) - release: $($foundRelease.Version) to the $($tenant.Name) pipeline in the $($environment.Name) environment"
$bodyRaw = @{
EnvironmentId = "$($environment.Id)"
ExcludedMachineIds = @()
ForcePackageDownload = $False
ForcePackageRedeployment = $false
FormValues = @{}
QueueTime = $null
QueueTimeExpiry = $null
ReleaseId = "$($foundRelease.Id)"
SkipActions = @()
SpecificMachineIds = @()
TenantId = "$($tenant.Id)"
UseGuidedFailure = $false
Comments = "Redeployed to alternate Kubernetes cluster by IT Software Operations."
}
$bodyAsJson = $bodyRaw | ConvertTo-Json
$taskId = $null
if ($isTestRun -eq $false)
{
$redeploymentResponse = Invoke-RestMethod "$octopusBaseUrl/api/$targetSpaceId/deployments" -Headers $headers -Method Post -Body $bodyAsJson -ContentType "application/json"
$taskId = $redeploymentResponse.TaskId
}
$redeployment = [Redeployment]::new()
$redeployment.TaskId = $taskId
$redeployment.ProjectName = $project.Name
$redeployment.ProjectId = $project.Id
$redeployment.Version = $foundRelease.Version
$redeployment.Environment = $environment.Name
$redeployment.EnvironmentId = $environment.Id
$redeployment.TenantName = $tenant.Name
$redeployment.TenantId = $tenant.Id
$redeployments.Add($redeployment)
}
}
}
}
}
# Check on the deployments to see when they finish:
do {
if ($isTestRun -eq $true)
{
break
}
Write-Output "---------------------------"
$areDeploymentsActive = $false
foreach ($redeployment in ($redeployments | Where-Object {$_.IsFinished -eq $false}))
{
$deploymentStatus = Invoke-RestMethod "$octopusBaseUrl/api/tasks/$($redeployment.TaskId)/details?verbose=false" -Headers $headers
$deploymentStatusState = $deploymentStatus.Task.State
if ($deploymentStatusState -eq "Success")
{
$redeployment.IsFinished = $true
$redeployment.WasSuccessful = $true
}
elseif ($deploymentStatusState -eq "Running" -or $deploymentStatusState -eq "Pending" -or $deploymentStatusState -eq "Executing")
{
$areDeploymentsActive = $true
}
else
{
$redeployment.IsFinished = $true
$redeployment.WasSuccessful = $false
}
}
$unfinishedRedeployments = $redeployments | Where-Object {$_.IsFinished -eq $false} | Format-Table
if ($unfinishedRedeployments.Count -gt 0){
Write-Output "Pending Redeploys:"
$unfinishedRedeployments | Format-Table
Write-Output "Checking again in 60 seconds"
}
Start-Sleep -Seconds 60
} While ($areDeploymentsActive)
Write-Output "==========================="
Write-Output "Redeployments Have Finished:"
$redeployments | Format-Table
# Save off the unsuccessful redeployment to show to the user later
$failedRedeployments = $redeployments | Where-Object {$_.WasSuccessful -eq $false} | ForEach-Object{" **$($_.ProjectName)** Failed for Environment **$($_.Environment)** on Tenant **$($_.TenantName)** `r`n"} | Out-String
Set-OctopusVariable -name "FailedRedeployments" -value $failedRedeployments
Thank you for following up and sharing that. I’m going to go through some tests shortly, but you’re probably right that a simplified version should be enough to reproduce. I’m immediately curious after re-reading this thread, since the ANSI color code issue previously discussed was narrowed down to only when run on Linux targets - if you run this exact script in Octopus, but on a Windows target, is this missing columns issue also not present? E.g. running on Windows, is this whole table populated and formatted correctly?
So, both the Windows and Linux workers truncated the number or columns. Linux also added in the extra chars at the start and end of the title rows.
While the extra chars are annoying, the real issue is the the truncation of the data. It even truncates in the Raw view. (Here is the Linux raw view, but the Windows one also truncates it.)
Thank you very much for providing that sample script to repro this behavior. That made it very straight forward and I’ve been able to reproduce this exactly as you’ve shown. I brought your question up internally, and I’ll let you know as soon as I hear back with any information.
I appreciate your patience as I had a further look into this one. We were able to scrounge up a solution that I’m hoping will be acceptable. Since the width of the table itself is being restricted, I increased this by appending the following to your sample repro script:
Unfortunately given the smaller screen width on the task log overview in the UI the lines wrap, causing the formatting to not be too pretty. To address this I decreased each column size from 20 → 15 (via the below line) which seems to get the overall width down enough to format nicely in the task overview.