Modules/businessdev.ALbuild.Containers/Private/Get-BcContainerStartFailure.ps1
|
function Get-BcContainerStartFailure { <# .SYNOPSIS Reads a failed container start and says what actually went wrong, and whether recreating the container could ever help. .DESCRIPTION The readiness failure used to carry ONE hypothesis, hard-coded, no matter what the container had said: "if the container log shows a corrupt artifact ... the artifact download is being truncated - typically a proxy/firewall". When the real cause was something else, that sentence did not merely fail to help - it pointed the reader at the network and away from the answer, which was sitting in the very log text appended to the same message. Measured case: a generic image older than 90 days makes Microsoft's start script refuse and exit 0. BC installs perfectly (102 s), the container dies at the nag, and the run then retried the identical refusal twice more before reporting a proxy problem. Five minutes spent to reach a wrong conclusion. Retryable is the second half. Recreating a container is only ever worth it for a TRANSIENT cause; against a deterministic refusal it just multiplies the wait. So a classified, non-transient cause fails fast, and only the unknown case keeps the old benefit of the doubt - an unrecognised failure may well be the flaky download this retry loop was built for. .PARAMETER Message The failure text, including the container log tail that Wait-BcContainerReady appends. .OUTPUTS PSCustomObject with Reason (string, '' when unrecognised) and Retryable (bool). #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [AllowNull()] [AllowEmptyString()] [string] $Message = '' ) $text = if ($null -eq $Message) { '' } else { $Message } # Ordered: the first match wins, so the more specific cause is listed before the general one. $known = @( @{ Match = 'ACCEPT_OUTDATED' Retryable = $false Reason = ("The generic container image is more than 90 days old and its start script refused to run " + "(BC itself installed fine). Pull a newer generic image, or pass " + "-EnvironmentVariables @{ ACCEPT_OUTDATED = 'Y' } to run it anyway.") } @{ Match = 'End of Central Directory record could not be found' Retryable = $true Reason = ('The artifact inside the image is truncated or corrupt - typically a proxy or firewall ' + 'interfering with large downloads on this host.') } @{ Match = 'There is not enough space on the disk|no space left on device' Retryable = $false Reason = ('The drive Docker stores containers on ran out of space while the container was ' + 'installing BC into its writable layer.') } @{ Match = 'The license file .* (is not valid|has expired)|Invalid license' Retryable = $false Reason = 'The BC licence the container was given was rejected.' } ) foreach ($k in $known) { if ($text -match $k.Match) { return [PSCustomObject]@{ Reason = [string]$k.Reason; Retryable = [bool]$k.Retryable } } } # Unrecognised: keep retrying, and say nothing rather than guess. The log tail is already part of # the message the caller reports. return [PSCustomObject]@{ Reason = ''; Retryable = $true } } |