Create a script to generate the Microsoft.WSL.TestData nuget package (#41405)
Blue committed
Aug 21, 2026 at 20:47 UTC
4bc9ed298c08845f1365c6af9b87b889809d9588
4 files changed
+240
-109
tools/test/download-test-data-rpms.ps1
deleted
-73
@@ -1,73 +0,0 @@
1
-
2
-[CmdletBinding(PositionalBinding = $False)]
3
-param (
4
- [Parameter(Mandatory = $true)][string]$Target,
5
- [string]$BaseUrl = "https://packages.microsoft.com/azurelinux/3.0/prod/base"
6
-)
7
-
8
-$ErrorActionPreference = "Stop"
9
-Set-StrictMode -Version Latest
10
-$ProgressPreference = "SilentlyContinue"
11
-
12
-$archMap = @{
13
- "x64" = "x86_64"
14
- "arm64" = "aarch64"
15
-}
16
-
17
-$packages = @("socat", "readline", "ncurses-libs")
18
-
19
-function Get-LatestRpmUrl {
20
- param (
21
- [string]$RepoUrl,
22
- [string]$Arch,
23
- [string]$Package
24
- )
25
-
26
- $letter = $Package.Substring(0, 1).ToLowerInvariant()
27
- $listingUrl = "$RepoUrl/$Arch/Packages/$letter/"
28
-
29
- $listing = curl.exe --fail -sSL $listingUrl
30
- if ($LASTEXITCODE -ne 0) {
31
- throw "Failed to list packages at $listingUrl"
32
- }
33
-
34
- $pattern = 'href="(?<file>' + [regex]::Escape($Package) + '-(?<ver>[0-9][0-9.]*)-(?<rel>[0-9]+)\.azl[0-9]+\.' + $Arch + '\.rpm)"'
35
- $matches = [regex]::Matches($listing, $pattern)
36
- if ($matches.Count -eq 0) {
37
- throw "No '$Package' rpm found for '$Arch' at $listingUrl"
38
- }
39
-
40
- $latest = $matches |
41
- Sort-Object -Property `
42
- @{ Expression = { [version]$_.Groups["ver"].Value } }, `
43
- @{ Expression = { [int]$_.Groups["rel"].Value } } |
44
- Select-Object -Last 1
45
-
46
- return "$listingUrl$($latest.Groups['file'].Value)"
47
-}
48
-
49
-foreach ($archEntry in $archMap.GetEnumerator()) {
50
- $nugetArch = $archEntry.Key
51
- $repoArch = $archEntry.Value
52
-
53
- $archInput = Join-Path $Target $nugetArch
54
- if (-not (Test-Path -Path $archInput -PathType Container)) {
55
- Write-Warning "Skipping '$nugetArch': '$archInput' does not exist."
56
- continue
57
- }
58
-
59
- $packagesDir = Join-Path $archInput "packages"
60
- New-Item -ItemType Directory -Path $packagesDir -Force | Out-Null
61
-
62
- foreach ($package in $packages) {
63
- $url = Get-LatestRpmUrl -RepoUrl $BaseUrl -Arch $repoArch -Package $package
64
- $fileName = Split-Path -Path $url -Leaf
65
- $destination = Join-Path $packagesDir $fileName
66
-
67
- Write-Output "[$nugetArch] Downloading $url"
68
- curl.exe --fail -sSL -o $destination $url
69
- if ($LASTEXITCODE -ne 0) {
70
- throw "Failed to download $url"
71
- }
72
- }
73
-}
\ No newline at end of file
tools/test/generate-test-data.ps1
new
+239
@@ -0,0 +1,239 @@
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
+}
tools/test/images/wslc-registry/Dockerfile
+1
-1
@@ -3,6 +3,6 @@ FROM registry:3
3
RUN apk add --no-cache apache2-utils
4
5
COPY entrypoint.sh /entrypoint.sh
6
-RUN chmod +x /entrypoint.sh
6
+RUN sed -i 's/\r$//' /entrypoint.sh && chmod +x /entrypoint.sh
7
8
ENTRYPOINT ["/entrypoint.sh"]
tools/test/pack-test-data.ps1
deleted
-35
@@ -1,35 +0,0 @@
1
-<#
2
-.SYNOPSIS
3
- Helper to pack WSL test data nuget.
4
-.PARAMETER InputDirectory
5
- Directory containing arch-specific subdirectories (x64, arm64) with test data.
6
-.PARAMETER Version
7
- Nuget package version.
8
-.PARAMETER OutputDirectory
9
- Directory to place the packaged nuget file. Default to current working directory.
10
-#>
11
-
12
-[CmdletBinding(PositionalBinding=$False, DefaultParameterSetName='vm')]
13
-param (
14
- [Parameter(Mandatory = $true)][string]$InputDirectory,
15
- [Parameter(Mandatory = $true)][string]$Version,
16
- [string]$OutputDirectory = $PWD.Path
17
-)
18
-
19
-$ErrorActionPreference = "Stop"
20
-Set-StrictMode -Version Latest
21
-
22
-if (-not (Test-Path -Path $InputDirectory -PathType Container)) {
23
- throw("The path '$InputDirectory' is not an existing directory.")
24
-}
25
-
26
-$hasArch = (Test-Path "$InputDirectory\x64") -or (Test-Path "$InputDirectory\arm64")
27
-if (-not $hasArch) {
28
- throw("The input directory must contain at least one architecture subdirectory (x64, arm64).")
29
-}
30
-
31
-echo "Building test data nuget. Input: $InputDirectory. Version: $Version"
32
-
33
-Copy-Item -Path "$PSScriptRoot\Microsoft.WSL.TestData.nuspec" -Destination "$InputDirectory" -Force
34
-
35
-& "$PSScriptRoot\..\..\_deps\nuget.exe" pack "$InputDirectory\Microsoft.WSL.TestData.nuspec" -Properties "version=$Version" -OutputDirectory "$OutputDirectory"
\ No newline at end of file