vhdbuilder/packer/windows/components_json_helpers.ps1 (258 lines of code) (raw):
function SafeReplaceString {
Param(
[Parameter(Mandatory = $true)][string]
$stringToReplace
)
$stringToReplace = &{
Clear-Variable -Name * -Exclude version,CPU_ARCH,stringToReplace -ErrorAction SilentlyContinue
$executionContext.InvokeCommand.ExpandString($stringToReplace)
}
return $stringToReplace
}
function GetComponentsFromComponentsJson
{
Param(
[Parameter(Mandatory = $true)][Object]
$componentsJsonContent
)
$output = New-Object System.Collections.ArrayList
foreach ($containerImage in $componentsJsonContent.ContainerImages)
{
$versions = $containerImage.windowsVersions
if ($versions -eq $null)
{
$versions = $containerImage.multiArchVersionsV2
}
$downloadUrl = $containerImage.windowsDownloadUrl
if ($downloadUrl -eq $null)
{
$downloadUrl = $containerImage.downloadUrl
}
foreach ($windowsVersion in $versions)
{
$skuMatch = $windowsVersion.windowsSkuMatch
if ($skuMatch -eq $null -or $windowsSku -eq $null -or $windowsSku -Like $skuMatch)
{
$version = $windowsVersion.latestVersion
$url = SafeReplaceString($downloadUrl)
$url = $url.replace("*", $windowsVersion.latestVersion)
$output += $url
if (-not [string]::IsNullOrEmpty($windowsVersion.previousLatestVersion))
{
$version = $windowsVersion.previousLatestVersion
$url = SafeReplaceString($downloadUrl)
$url = $url.replace("*", $windowsVersion.previousLatestVersion)
$output += $url
}
}
}
}
return $output
}
function GetPackagesFromComponentsJson
{
Param(
[Parameter(Mandatory = $true)][Object]
$componentsJsonContent
)
$output = @{ }
foreach ($package in $componentsJsonContent.Packages)
{
$downloadLocation = $package.windowsDownloadLocation
if ($downloadLocation -eq $null -or $downloadLocation -eq "")
{
continue
}
$thisList = $output[$downloadLocation]
if ($thisList -eq $null)
{
$thisList = New-Object System.Collections.ArrayList
}
$downloadUrls = $package.downloadURIs.windows
if ($downloadUrls -eq $null)
{
$part = $package.downloadURIs.default.current
}
else
{
$part = $downloadUrls.default
switch -Regex ($windowsSku)
{
"2019-containerd" {
$part = $downloadUrls.ws2019
break
}
"2022-containerd*" {
$part = $downloadUrls.ws2022
break
}
"23H2*" {
$part = $downloadUrls.ws32h2
break
}
"2025*" {
$part = $downloadUrls.ws2025
break
}
}
if ($part -eq $null)
{
$part = $downloadUrls.default
}
}
$downloadUrl = $part.windowsDownloadUrl
$items = $part.versionsV2
# no specific windows download url means fall back to regular windows spots.
if ($downloadUrl -eq $null -or $downloadUrl -eq "")
{
$downloadUrl = $part.downloadUrl
}
foreach ($windowsVersion in $items)
{
$version = $windowsVersion.latestVersion
$url = SafeReplaceString($downloadUrl)
$thisList += $url
if (-not [string]::IsNullOrEmpty($windowsVersion.previousLatestVersion))
{
$version = $windowsVersion.previousLatestVersion
$url = SafeReplaceString($downloadUrl)
$thisList += $url
}
}
if ($thisList.Length -gt 0)
{
$output[$downloadLocation] = $thisList
}
}
return $output
}
function GetDefaultContainerDFromComponentsJson
{
Param(
[Parameter(Mandatory = $true)][Object]
$componentsJsonContent
)
$packages = GetPackagesFromComponentsJson($componentsJsonContent)
$containerDPackages = $packages["c:\akse-cache\containerd\"]
return $containerDPackages[0]
}
function GetRegKeysToApply
{
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
$output = New-Object System.Collections.ArrayList
foreach ($key in $windowsSettingsContent.WindowsRegistryKeys)
{
if ($windowsSku -Like $key.WindowsSkuMatch)
{
$output += $key
}
}
return $output;
}
function GetKeyMapForReleaseNotes
{
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
$output = @{ }
foreach ($key in $windowsSettingsContent.WindowsRegistryKeys)
{
if ($windowsSku -Like $key.WindowsSkuMatch)
{
$path = $key.Path
$name = $key.Name
$arr = $output[$path]
if ($output[$path] -eq $null)
{
$output[$path] = New-Object System.Collections.ArrayList
}
$output[$path] += $name
}
}
return $output;
}
function LogReleaseNotesForWindowsRegistryKeys
{
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
$logLines = New-Object System.Collections.ArrayList
$releaseNotesToSet = GetKeyMapForReleaseNotes $windowsSettingsContent
foreach ($key in $releaseNotesToSet.Keys)
{
$logLines += ("`t{0}" -f $key)
$names = $releaseNotesToSet[$key]
foreach ($name in $names)
{
$value = (Get-ItemProperty -Path $key -Name $name).$name
$logLines += ("`t`t{0} : {1}" -f $name, $value)
}
}
return $logLines
}
function GetPatchInfo
{
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSku,
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
$output = New-Object System.Collections.ArrayList
$baseVersionBlock = $windowsSettingsContent.WindowsBaseVersions."$windowsSku";
if ($baseVersionBlock -eq $null) {
return $output
}
$patchData = $baseVersionBlock.patches_to_apply
# I'd much rather have two functions here - one to return the ids and one to return the urls. But annoyingly
# powershell converts an array of strings of size 1 into a string. Which is super dumb. And means we can't trust
# the return value of the function to be an array. It's OK for some of the functions above as they'll always be
# returning lots of items. But there is usually only one patch to apply.
return $patchData
}
function GetWindowsBaseVersions {
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
return $windowsSettingsContent.WindowsBaseVersions.PSObject.Properties.Name
}
function GetDefenderUpdateUrl {
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
return $windowsSettingsContent.WindowsDefenderInfo.DefenderUpdateUrl
}
function GetDefenderUpdateInfoUrl {
Param(
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
return $windowsSettingsContent.WindowsDefenderInfo.DefenderUpdateInfoUrl
}
function GetAllCachedThings {
Param(
[Parameter(Mandatory = $true)][Object]
$componentsJsonContent,
[Parameter(Mandatory = $true)][Object]
$windowsSettingsContent
)
$items = GetComponentsFromComponentsJson $componentsJsonContent
$packages = GetPackagesFromComponentsJson $componentsJsonContent
$regKeys = GetRegKeysToApply $windowsSettingsContent
foreach ($packageName in $packages.keys) {
foreach ($package in $packages[$packageName]) {
$items += $packageName + ": " + $package
}
}
foreach ($regKey in $regKeys) {
$items += $regKey.Path + "\" + $regKey.Name + "=" + $regKey.Value
}
return ($items | Sort-Object)
}