Skip to content

Commit a4e959b

Browse files
committed
Setup e2e pipeline
1 parent 216fb37 commit a4e959b

File tree

7 files changed

+475
-0
lines changed

7 files changed

+475
-0
lines changed

build/e2e/e2e.ps1

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<#
2+
.SYNOPSIS
3+
Runs Containers Toolkit end-to-end tests on Windows.
4+
5+
6+
.PARAMETER ManifestPath
7+
Path to the Containers Toolkit manifest file (PSD1) to import the module.
8+
9+
#>
10+
11+
[CmdletBinding()]
12+
param (
13+
[Parameter(Mandatory = $false)]
14+
[ValidateScript({ Test-Path $_ -PathType Leaf })]
15+
[String]$ManifestPath = (Get-ChildItem -Recurse -Filter "containers-toolkit.psd1").FullName
16+
)
17+
18+
$ErrorActionPreference = 'Stop'
19+
20+
# Get PS Version
21+
Write-Host "PowerShell version:" -ForegroundColor Cyan
22+
Write-Output $PSVersionTable
23+
24+
# Get OS Info
25+
Write-Host "Operating System Information:" -ForegroundColor Cyan
26+
$regInfo = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' |
27+
Select-Object ProductName, ReleaseId, CurrentBuild, DisplayVersion
28+
$osVersion = [PSCustomObject]@{
29+
OSVersion = [System.Environment]::OSVersion.Version
30+
}
31+
$compInfo = Get-ComputerInfo | Select-Object `
32+
@{l='WindowsProductName'; e={$_.WindowsProductName}}, `
33+
@{l='OsArchitecture'; e={$_.OsArchitecture}}, `
34+
@{l='WindowsBuildLabEx'; e={$_.WindowsBuildLabEx}}
35+
$osInfo = [PSCustomObject]@{
36+
ProductName = $regInfo.ProductName
37+
ReleaseId = $regInfo.ReleaseId
38+
DisplayVersion = $regInfo.DisplayVersion
39+
OSVersion = $osVersion.OSVersion
40+
WindowsProductName = $compInfo.WindowsProductName
41+
OsArchitecture = $compInfo.OsArchitecture
42+
WindowsBuildLabEx = $compInfo.WindowsBuildLabEx
43+
}
44+
Write-Output $osInfo
45+
46+
# Unblock all files in the module directory
47+
Write-Debug "Unblocking files in the module directory..."
48+
$modulePath = Split-Path -Path $ManifestPath -Parent
49+
Get-ChildItem -Path $modulePath -Recurse | Unblock-File
50+
51+
# Install HNS module
52+
Write-Debug "Installing HNS module..."
53+
$hnsDir = "$env:USERPROFILE\HNS"
54+
New-Item -Path $hnsDir -ItemType Directory -Force | Out-Null
55+
$Uri = 'https://raw.githubusercontent.com/microsoft/SDN/refs/heads/master/Kubernetes/windows/hns.v2.psm1'
56+
Invoke-WebRequest -Uri $Uri -OutFile "$hnsDir/hns.psm1"
57+
58+
# Add the HNS module to the PSModulePath environment variable
59+
$env:PSModulePath += ";$hnsDir"
60+
61+
$failed = $false
62+
63+
# Test the import of the HNS module
64+
Write-Debug "Testing import of HNS module..."
65+
if (-not (Get-Module -ListAvailable -Name "HNS")) {
66+
Write-Error "HNS module not found. Please ensure the HNS module is installed correctly." -ErrorAction Continue
67+
$failed = $true
68+
}
69+
Write-Host "HNS module imported successfully." -ForegroundColor Green
70+
71+
# Import the Contaners Toolkit module
72+
Write-Debug "Importing the Containers Toolkit module from: $ManifestPath"
73+
Import-Module -Name "$ManifestPath" -Force -ErrorAction Stop
74+
75+
# Test the import of the Containers Toolkit module
76+
Write-Debug "Testing import of Containers Toolkit module..."
77+
if (-not (Get-Module -Name "Containers-Toolkit")) {
78+
Write-Error "Containers Toolkit module not found. Please ensure the module is installed correctly." -ErrorAction Continue
79+
$failed = $true
80+
}
81+
else {
82+
Write-Host "Containers Toolkit module imported successfully." -ForegroundColor Green
83+
}
84+
85+
if ($failed) {
86+
Write-Error "Module import failed. Please check the output for details." -ErrorAction Continue
87+
exit 1
88+
}
89+
90+
# Install the container tools
91+
# - install all the tools
92+
# - register containerd and buildkitd services
93+
# - initialize a new NAT network
94+
Write-Host "Installing the latest version of the container tools..."
95+
Install-Containerd -Setup -Force -Confirm:$false
96+
Install-Buildkit -Setup -Force -Confirm:$false
97+
Install-Nerdctl -Force -Confirm:$false
98+
Initialize-NatNetwork -Gateway 192.168.0.1 -Force -Confirm:$false
99+
100+
# Verify the container tools installation
101+
Write-Host "Verifying container tools installation..."
102+
$toolInfo = Show-ContainerTools -Latest
103+
Write-Output $toolInfo
104+
if ($toolInfo -eq $null) {
105+
Write-Error "Container tools installation verification failed." -ErrorAction Continue
106+
$failed = $true
107+
}
108+
109+
# Test the installation of the container tools
110+
Write-Host "Test containerd service has been registered..."
111+
Get-Service -Name containerd -ErrorAction Stop | Format-List -Property *
112+
113+
# Test the installation of the buildkitd service
114+
Write-Host "Test buildkitd service has been registered..."
115+
Get-Service -Name buildkitd -ErrorAction Stop | Format-List -Property *
116+
117+
# Test the initialization of a NAT network
118+
Write-Host "Test NAT network has been created..."
119+
$hnsNetwork = Get-HnsNetwork | Where-Object { $_.Name -eq "Nat" }
120+
if (-not $hnsNetwork) {
121+
Write-Error "No network named 'Nat' found. NAT network initialization failed." -ErrorAction Continue
122+
$failed = $true
123+
}
124+
Write-Output $hnsNetwork
125+
126+
if ($failed) {
127+
Write-Error "One or more tests failed. Please check the output for details." -ErrorAction Continue
128+
exit 1
129+
}
130+
131+
# Uninstall the container tools
132+
Write-Host "Uninstalling the container tools..."
133+
Uninstall-Containerd -Force -Confirm:$false -ErrorAction Continue
134+
Uninstall-Buildkit -Force -Confirm:$false -ErrorAction Continue
135+
Uninstall-Nerdctl -Force -Confirm:$false -ErrorAction Continue
136+
137+
138+
# Verify the uninstallation of the container tools
139+
$tools = @(
140+
"containerd",
141+
"buildkit",
142+
"nerdctl"
143+
)
144+
foreach ($tool in $tools) {
145+
Write-Host "Verifying $tool has been uninstalled..."
146+
$retryCount = 3
147+
while ($retryCount -gt 0) {
148+
Write-Debug "Retrying to verify uninstallation of $tool... ($retryCount retries left)"
149+
$command = Get-Command -Name $tool -ErrorAction SilentlyContinue | Where-Object { $_.Source -like "$env:programfiles\*" }
150+
if ($command) {
151+
Start-Sleep -Seconds 5
152+
$retryCount--
153+
154+
if ($retryCount -eq 0) {
155+
Write-Error "Failed to uninstall $tool after multiple attempts." -ErrorAction Continue
156+
$failed = $true
157+
}
158+
}
159+
else {
160+
break
161+
}
162+
}
163+
}
164+
165+
$services = @(
166+
"containerd",
167+
"buildkitd"
168+
)
169+
foreach ($service in $services) {
170+
Write-Host "Verifying $service service has been unregistered..."
171+
$retryCount = 3
172+
while ($retryCount -gt 0) {
173+
Write-Debug "Retrying to verify unregistration of $service service... ($retryCount retries left)"
174+
$serviceObj = Get-Service -Name $service -ErrorAction SilentlyContinue
175+
if ($serviceObj) {
176+
Start-Sleep -Seconds 5
177+
$retryCount--
178+
179+
if ($retryCount -eq 0) {
180+
Write-Error "Failed to unregister $service service after multiple attempts." -ErrorAction Continue
181+
$failed = $true
182+
}
183+
}
184+
else {
185+
break
186+
}
187+
}
188+
}
189+
190+
if ($failed) {
191+
Write-Error "Uninstallation of one or more container tools failed. Please check the output for details." -ErrorAction Continue
192+
exit 1
193+
}
194+
195+
# Summary
196+
Write-Host "E2E script completed successfully."

build/e2e/e2e.yaml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#########################################################
2+
# This pipeline is used to run end-to-end tests
3+
# for the Containers Toolkit PowerShell module.
4+
# The pipeline should run on ADO when changes are pushed
5+
# to the main branch or when a pull request is created
6+
# against the main branch.
7+
# We run the E2E tests on:
8+
# - Windows Server 2025
9+
# - Windows Server 2022
10+
# - Windows Server 2019
11+
# The tests are run using both PowerShell Core and Windows PowerShell.
12+
#########################################################
13+
14+
name: e2e
15+
trigger:
16+
branches:
17+
include:
18+
- main
19+
- release/*
20+
paths:
21+
include:
22+
- build/e2e.yaml
23+
- containers-toolkit/*
24+
25+
# The difference in the two jobs is that the first one runs the E2E tests using PowerShell Core (pwsh: true),
26+
# while the second one runs them using Windows PowerShell (pwsh: false).
27+
# By default, PowerShell v2 uses PowerShell Core for Linux agents and Windows PowerShell for Windows agents.
28+
# To use the latest version of PowerShell on Windows agents, set the pwsh parameter to true.
29+
# PowerShell Core will then be used instead.
30+
# https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/powershell-v2?view=azure-pipelines
31+
# We run a separate job for each to ensure that the tests are run a clean environment for each PowerShell version.
32+
jobs:
33+
34+
# pwsh: true (PowerShell Core)
35+
- job: PowerShellCoreE2ETests
36+
displayName: 'Run E2E Tests on PowerShell Core'
37+
strategy:
38+
matrix:
39+
windows-latest:
40+
imageName: 'windows-latest'
41+
windows-2022:
42+
imageName: 'windows-2022'
43+
windows-2019:
44+
imageName: 'windows-2019'
45+
pool:
46+
vmImage: $(imageName)
47+
steps:
48+
- task: PowerShell@2
49+
displayName: Run E2E Tests on PowerShell Core
50+
inputs:
51+
pwsh: true
52+
continueOnError: true
53+
targetType: 'filePath'
54+
filePath: "$(Build.SourcesDirectory)/build/e2e/e2e.ps1"
55+
errorActionPreference: 'stop'
56+
failOnStderr: true
57+
ignoreLASTEXITCODE: false
58+
showWarnings: true
59+
60+
61+
# pwsh: false (Windows PowerShell)
62+
- job: WindowsPowerShellE2ETests
63+
displayName: 'Run E2E Tests on Windows PowerShell'
64+
strategy:
65+
matrix:
66+
windows-latest:
67+
imageName: 'windows-latest'
68+
windows-2022:
69+
imageName: 'windows-2022'
70+
windows-2019:
71+
imageName: 'windows-2019'
72+
pool:
73+
vmImage: $(imageName)
74+
steps:
75+
- task: PowerShell@2
76+
displayName: Run E2E Tests on Windows PowerShell
77+
inputs:
78+
pwsh: false
79+
continueOnError: true
80+
targetType: 'filePath'
81+
filePath: "$(Build.SourcesDirectory)/build/e2e/e2e.ps1"
82+
errorActionPreference: 'stop'
83+
failOnStderr: true
84+
ignoreLASTEXITCODE: false
85+
showWarnings: true

build/hacks/Load-NewtonsoftDlls.ps1

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
function Get-DllFile {
2+
[CmdletBinding()]
3+
param(
4+
[Parameter(Mandatory = $true)]
5+
[string]$Path,
6+
7+
[Parameter(Mandatory = $true)]
8+
[string]$PackageName
9+
)
10+
11+
$dllPath = Get-ChildItem -Path "$Path" -Filter "$PackageName.dll" -File -Recurse -ErrorAction SilentlyContinue | `
12+
Select-Object -First 1 -ExpandProperty FullName
13+
14+
return $dllPath
15+
}
16+
17+
function Import-NewtonsoftDll {
18+
[CmdletBinding()]
19+
param(
20+
[Parameter(Mandatory = $true)]
21+
[ValidateSet("Newtonsoft.Json", "Newtonsoft.Json.Schema")]
22+
[string]$PackageName,
23+
24+
[Parameter(Mandatory = $false)]
25+
[string]$Path
26+
)
27+
28+
if (-not $Path) {
29+
$profileDir = Split-Path -Parent "$($PROFILE.CurrentUserCurrentHost)"
30+
$Path = Join-Path "$profileDir" "Modules\newtonsoft.json"
31+
}
32+
Write-Host "Using path: $Path"
33+
if (-not (Test-Path -Path $Path)) {
34+
New-Item -Path $Path -ItemType Directory -Force | Out-Null
35+
}
36+
37+
$framework = "net45"
38+
$packageDir = Join-Path -Path $Path -ChildPath "$PackageName\lib\$framework"
39+
Write-Host "Using package directory: $packageDir" -ForegroundColor Magenta
40+
41+
# Install the package if it doesn't exist from nuget
42+
$dllPath = Get-DllFile -Path $packageDir -PackageName $PackageName
43+
if (-not $dllPath) {
44+
Write-Host "Installing $PackageName from NuGet." -ForegroundColor Magenta
45+
nuget.exe install $PackageName -NoHttpCache -ExcludeVersion -NonInteractive -Force `
46+
-OutputDirectory $Path `
47+
-Framework "net45"
48+
}
49+
50+
$dllPath = Get-DllFile -Path $packageDir -PackageName $PackageName
51+
if (-not $dllPath) {
52+
Write-Error "The $PackageName.dll file could not be found in the provided directory."
53+
return
54+
}
55+
56+
# Load the assembly from the path
57+
Write-Host "Loading assembly from '$dllPath'." -ForegroundColor Magenta
58+
try {
59+
$asm = [Reflection.Assembly]::LoadFile($dllPath) | Out-Null
60+
}
61+
catch {
62+
Write-Error "Failed to load assembly from ${dllPath}. $_"
63+
return
64+
}
65+
}
66+
67+
68+
# Ensure the Newtonsoft.Json and Newtonsoft.Json.Schema modules are imported
69+
Import-NewtonsoftDll -PackageName "Newtonsoft.Json.Schema"
70+
Import-NewtonsoftDll -PackageName "Newtonsoft.Json"

containers-toolkit/Private/CommonToolUtilities.psm1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,13 @@ function ValidateJSONChecksumFile {
650650

651651
# Test JSON checksum file is valid
652652
try {
653+
# Check if Test-Json cmdlet is available
654+
if (-not (Get-Command -Name Test-Json -ErrorAction SilentlyContinue)) {
655+
Write-Debug "Using custom JSON validation module."
656+
Import-Module "$ModuleParentPath\Private\Json-Validator.psm1" -Force
657+
} else {
658+
Write-Debug "Using built-in Test-Json cmdlet."
659+
}
653660
$isValidJSON = Test-Json -Json "$(Get-Content -Path $ChecksumFilePath -Raw)" -Schema "$schemaFileContent"
654661
return $isValidJSON
655662
}

0 commit comments

Comments
 (0)