Modules/businessdev.ALbuild.Containers/Public/Resolve-BcContainerHostShare.ps1
|
function Resolve-BcContainerHostShare { <# .SYNOPSIS Returns the host folder actually bind-mounted to C:\run\my in a container (with a fallback). .DESCRIPTION Files are exchanged with a Business Central container through the host folder bind-mounted to C:\run\my (Copy-BcFileToContainer writes there; Invoke-BcContainerCommand stages large command scripts there). Get-BcContainerHostShare returns the DETERMINISTIC folder that ALbuild's own New-BcContainer mounts - which is correct only for a container this module created in the current job, because the convention is rooted under the job-scoped AGENT_TEMPDIRECTORY. For a container created elsewhere - a BcContainerHelper container, or a long-lived container targeted by a release / on-prem deployment - that path does NOT match the real mount, so staged files are written to a folder the container cannot see (the deploy then fails with "the argument 'C:\run\my\...ps1' to the -File parameter does not exist"). This resolves the REAL host path by inspecting the container's mounts (authoritative regardless of who created it) and returning the Source of the C:\run\my bind mount. If the container cannot be inspected - Docker missing, or the container does not exist yet (e.g. called at creation time) - it falls back to the deterministic Get-BcContainerHostShare convention. .PARAMETER Name Container name. .PARAMETER DockerExecutable The Docker executable to use (default 'docker'). .OUTPUTS System.String - the host folder path bind-mounted to C:\run\my. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory, Position = 0)] [ValidateNotNullOrEmpty()] [string] $Name, [string] $DockerExecutable = 'docker' ) try { # One line per mount: '<destination>|<source>'. PassThru+Quiet so a missing container returns a # non-success result (we fall back) instead of throwing or logging. $inspect = Invoke-BcDocker -DockerExecutable $DockerExecutable -PassThru -Quiet -Arguments @( 'inspect', '--format', '{{range .Mounts}}{{.Destination}}|{{.Source}}{{println}}{{end}}', $Name) if ($inspect.Success -and $inspect.StdOut) { foreach ($line in ($inspect.StdOut -split "`r?`n")) { $sep = $line.IndexOf('|') if ($sep -lt 1) { continue } # Destinations come back as 'c:\run\my' (docker lower-cases the drive); normalise slashes, # trailing separator and case before matching. $dst = $line.Substring(0, $sep).Trim().Replace('/', '\').TrimEnd('\').ToLowerInvariant() if ($dst -eq 'c:\run\my') { $src = $line.Substring($sep + 1).Trim() if ($src) { Write-ALbuildLog -Level Verbose "Resolved '$Name' C:\run\my host mount to '$src' (from docker inspect)." return $src } } } } } catch { Write-ALbuildLog -Level Verbose "Could not inspect '$Name' for its C:\run\my mount ($($_.Exception.Message)); using the conventional host share." } return (Get-BcContainerHostShare -Name $Name) } |