master
ps1 239 lines 8.01 KB
Raw
1 [CmdletBinding(PositionalBinding = $false)]
2 param (
3 [Parameter(Mandatory)]
4 [string]$Version,
5 [string]$Distribution
6 )
7
8 $ErrorActionPreference = "Stop"
9 Set-StrictMode -Version Latest
10
11 $WorkingDirectory = Join-Path $PSScriptRoot "test-data"
12 $OutputDirectory = $PWD.Path
13
14 $wslArguments = @()
15 if (-not [string]::IsNullOrEmpty($Distribution)) {
16 $wslArguments += @("--distribution", $Distribution)
17 }
18 $wslArguments += "--exec"
19
20 function Invoke-WslCommand {
21 param (
22 [Parameter(Mandatory = $true)][string[]]$Command,
23 [switch]$CaptureOutput
24 )
25
26 if ($CaptureOutput) {
27 $output = & wsl.exe @wslArguments @Command
28 if ($LASTEXITCODE -ne 0) {
29 throw "WSL command failed with exit code $LASTEXITCODE`: $($Command -join ' ')"
30 }
31
32 return $output
33 }
34
35 & wsl.exe @wslArguments @Command
36 if ($LASTEXITCODE -ne 0) {
37 throw "WSL command failed with exit code $LASTEXITCODE`: $($Command -join ' ')"
38 }
39 }
40
41 function ConvertTo-WslPath {
42 param (
43 [Parameter(Mandatory = $true)][string]$Path
44 )
45
46 $result = Invoke-WslCommand -Command @("wslpath", "-a", $Path) -CaptureOutput
47 return ($result | Select-Object -Last 1).Trim()
48 }
49
50 function Enable-ForeignArchitectureBuilds {
51 $nativeArchitecture = (
52 Invoke-WslCommand -Command @("docker", "version", "--format", "{{.Server.Arch}}") -CaptureOutput |
53 Select-Object -Last 1
54 ).Trim()
55
56 foreach ($architecture in @("amd64", "arm64")) {
57 if ($architecture -eq $nativeArchitecture) {
58 continue
59 }
60
61 Write-Host "Installing Docker binfmt support for $architecture"
62 Invoke-WslCommand -Command @(
63 "docker", "container", "run",
64 "--privileged",
65 "--rm",
66 "tonistiigi/binfmt",
67 "--install", $architecture
68 )
69 }
70 }
71
72 function Download-TestDataRpms {
73 param (
74 [Parameter(Mandatory = $true)][string]$NugetArchitecture,
75 [Parameter(Mandatory = $true)][string]$DockerArchitecture
76 )
77
78 $packagesDirectory = Join-Path $WorkingDirectory "$NugetArchitecture\packages"
79 New-Item -ItemType Directory -Path $packagesDirectory -Force | Out-Null
80 $packagesPath = ConvertTo-WslPath $packagesDirectory
81
82 Write-Host "[$NugetArchitecture] Downloading Azure Linux RPMs"
83 $downloadCommand = @(
84 "tdnf reinstall -y --downloadonly --downloaddir=/packages readline ncurses-libs",
85 "tdnf install -y --downloadonly --downloaddir=/packages socat"
86 ) -join " && "
87
88 Invoke-WslCommand -Command @(
89 "docker", "container", "run",
90 "--rm",
91 "--platform", "linux/$DockerArchitecture",
92 "--volume", "${packagesPath}:/packages",
93 "mcr.microsoft.com/azurelinux/base/core:3.0",
94 "sh", "-c", $downloadCommand
95 )
96
97 $downloadedPackages = @(Get-ChildItem -LiteralPath $packagesDirectory -Filter "*.rpm" -File)
98 if ($downloadedPackages.Count -ne 3) {
99 throw "Expected 3 RPMs for $NugetArchitecture, found $($downloadedPackages.Count)."
100 }
101 }
102
103 function Export-DockerImage {
104 param (
105 [Parameter(Mandatory = $true)][string]$Image,
106 [Parameter(Mandatory = $true)][string]$DockerArchitecture,
107 [Parameter(Mandatory = $true)][string]$OutputPath,
108 [string]$Source
109 )
110
111 if ([string]::IsNullOrEmpty($Source)) {
112 $Source = "docker-daemon:$Image"
113 }
114
115 $outputDirectory = Split-Path -Parent $OutputPath
116 $outputFileName = Split-Path -Leaf $OutputPath
117 $wslOutputDirectory = ConvertTo-WslPath $outputDirectory
118
119 Invoke-WslCommand -Command @(
120 "docker", "container", "run",
121 "--rm",
122 "--volume", "/var/run/docker.sock:/var/run/docker.sock",
123 "--volume", "${wslOutputDirectory}:/output",
124 "quay.io/skopeo/stable",
125 "copy",
126 "--override-arch", $DockerArchitecture,
127 $Source,
128 "docker-archive:/output/${outputFileName}:$Image"
129 )
130
131 # Adjust the tar padding to match docker's behavior so the "wslc image save" tests match the size of the tars in the testdata package.
132 $archive = Get-Item -LiteralPath $OutputPath
133 [long]$tarRecordSize = 10KB
134 $paddedLength = [Math]::Ceiling($archive.Length / $tarRecordSize) * $tarRecordSize
135 if ($paddedLength -ne $archive.Length) {
136 $stream = [System.IO.File]::OpenWrite($archive.FullName)
137 try {
138 $stream.SetLength($paddedLength)
139 }
140 finally {
141 $stream.Dispose()
142 }
143 }
144 }
145
146 function Export-TestImages {
147 param (
148 [Parameter(Mandatory = $true)][string]$NugetArchitecture,
149 [Parameter(Mandatory = $true)][string]$DockerArchitecture
150 )
151
152 $architectureDirectory = Join-Path $WorkingDirectory $NugetArchitecture
153 New-Item -ItemType Directory -Path $architectureDirectory -Force | Out-Null
154
155 $images = [ordered]@{
156 "alpine:latest" = "alpine-latest.tar"
157 "debian:latest" = "debian-latest.tar"
158 "hello-world:latest" = "HelloWorldSaved.tar"
159 "python:3.12-alpine" = "python-3_12-alpine.tar"
160 }
161
162 foreach ($entry in $images.GetEnumerator()) {
163 Write-Host "[$NugetArchitecture] Downloading $($entry.Key)"
164 Export-DockerImage `
165 -Image $entry.Key `
166 -DockerArchitecture $DockerArchitecture `
167 -OutputPath (Join-Path $architectureDirectory $entry.Value) `
168 -Source "docker://docker.io/library/$($entry.Key)"
169 }
170
171 Invoke-WslCommand -Command @("docker", "image", "pull", "--platform", "linux/$DockerArchitecture", "hello-world:latest")
172
173 $containerId = $null
174 try {
175 $containerId = (
176 Invoke-WslCommand -Command @(
177 "docker", "container", "create", "--platform", "linux/$DockerArchitecture", "hello-world:latest"
178 ) -CaptureOutput |
179 Select-Object -Last 1
180 ).Trim()
181
182 $exportPath = ConvertTo-WslPath (Join-Path $architectureDirectory "HelloWorldExported.tar")
183 Invoke-WslCommand -Command @("docker", "container", "export", "--output", $exportPath, $containerId)
184 }
185 finally {
186 if (-not [string]::IsNullOrEmpty($containerId)) {
187 Invoke-WslCommand -Command @("docker", "container", "rm", "--force", $containerId)
188 }
189 }
190
191 Write-Host "[$NugetArchitecture] Building wslc-registry:latest"
192 $buildContext = ConvertTo-WslPath (Join-Path $PSScriptRoot "images\wslc-registry")
193 Invoke-WslCommand -Command @(
194 "docker", "image", "build",
195 "--platform", "linux/$DockerArchitecture",
196 "--pull",
197 "--tag", "wslc-registry:latest",
198 $buildContext
199 )
200
201 Export-DockerImage `
202 -Image "wslc-registry:latest" `
203 -DockerArchitecture $DockerArchitecture `
204 -OutputPath (Join-Path $architectureDirectory "wslc-registry.tar")
205 }
206
207 try {
208 if (Test-Path -LiteralPath $WorkingDirectory) {
209 Remove-Item -LiteralPath $WorkingDirectory -Recurse -Force
210 }
211
212 New-Item -ItemType Directory -Path $WorkingDirectory -Force | Out-Null
213
214 Write-Host "Checking Docker in WSL"
215 Invoke-WslCommand -Command @("docker", "version")
216 Enable-ForeignArchitectureBuilds
217
218 Export-TestImages -NugetArchitecture "x64" -DockerArchitecture "amd64"
219 Export-TestImages -NugetArchitecture "arm64" -DockerArchitecture "arm64"
220
221 Download-TestDataRpms -NugetArchitecture "x64" -DockerArchitecture "amd64"
222 Download-TestDataRpms -NugetArchitecture "arm64" -DockerArchitecture "arm64"
223
224 $nuspecPath = Join-Path $WorkingDirectory "Microsoft.WSL.TestData.nuspec"
225 Copy-Item -LiteralPath (Join-Path $PSScriptRoot "Microsoft.WSL.TestData.nuspec") -Destination $nuspecPath -Force
226
227 Write-Host "Building test data NuGet. Input: $WorkingDirectory. Version: $Version"
228 & (Join-Path $PSScriptRoot "..\..\_deps\nuget.exe") pack $nuspecPath `
229 -Properties "version=$Version" `
230 -OutputDirectory $OutputDirectory
231 if ($LASTEXITCODE -ne 0) {
232 throw "NuGet pack failed with exit code $LASTEXITCODE."
233 }
234 }
235 finally {
236 if (Test-Path -LiteralPath $WorkingDirectory) {
237 Remove-Item -LiteralPath $WorkingDirectory -Recurse -Force
238 }
239 }